coralite 0.38.0 → 0.38.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.
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../lib/compiler.js"],"names":[],"mappings":"AAiBA;;;;;;;;;GASG;AACH,uFANG;IAAkC,IAAI,EAA9B,gBAAgB;IACe,OAAO,EAAtC,qBAAqB;IACL,MAAM;IACJ,uBAAuB;CACjD,GAAU,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,UAAU,EAAE,GAAG,CAAA;CAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAuFzG;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,mLAhBG;IAAgC,MAAM,EAA9B,cAAc;IACqB,KAAK,EAAxC,yBAAyB;IACH,IAAI,EAA1B,YAAY;IACC,IAAI,EAAjB,GAAG;IACa,SAAS,EAAzB,MAAM;IACmB,OAAO,EAAhC,eAAe;IACE,WAAW,EAA5B,OAAO;IACS,GAAG;IACH,MAAM;IACJ,WAAW;IACX,eAAe;IACf,oBAAoB;IACpB,YAAY;CAEtC,GAAU,OAAO,CAAC,yBAAyB,CAAC,CA6H9C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,kLAhBG;IAAgC,MAAM,EAA9B,cAAc;IACqB,KAAK,EAAxC,yBAAyB;IACH,IAAI,EAA1B,YAAY;IACC,IAAI,EAAjB,GAAG;IACa,SAAS,EAAzB,MAAM;IACmB,OAAO,EAAhC,eAAe;IACE,WAAW,EAA5B,OAAO;IACS,GAAG;IACH,MAAM;IACJ,WAAW;IACX,eAAe;IACf,oBAAoB;IACpB,YAAY;CAEtC,GAAU,OAAO,CAAC,yBAAyB,CAAC,CAsH9C;AAED;;;GAGG;AACH,kCAFW,GAAG,sCAOb;sCA7YqI,mBAAmB;2CAAnB,mBAAmB;4BAC9H,SAAS;oCADkG,mBAAmB;+CAAnB,mBAAmB;kCAAnB,mBAAmB;qCAAnB,mBAAmB"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../lib/compiler.js"],"names":[],"mappings":"AAiBA;;;;;;;;;GASG;AACH,uFANG;IAAkC,IAAI,EAA9B,gBAAgB;IACe,OAAO,EAAtC,qBAAqB;IACL,MAAM;IACJ,uBAAuB;CACjD,GAAU,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,UAAU,EAAE,GAAG,CAAA;CAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAwFzG;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,mLAhBG;IAAgC,MAAM,EAA9B,cAAc;IACqB,KAAK,EAAxC,yBAAyB;IACH,IAAI,EAA1B,YAAY;IACC,IAAI,EAAjB,GAAG;IACa,SAAS,EAAzB,MAAM;IACmB,OAAO,EAAhC,eAAe;IACE,WAAW,EAA5B,OAAO;IACS,GAAG;IACH,MAAM;IACJ,WAAW;IACX,eAAe;IACf,oBAAoB;IACpB,YAAY;CAEtC,GAAU,OAAO,CAAC,yBAAyB,CAAC,CAmI9C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,kLAhBG;IAAgC,MAAM,EAA9B,cAAc;IACqB,KAAK,EAAxC,yBAAyB;IACH,IAAI,EAA1B,YAAY;IACC,IAAI,EAAjB,GAAG;IACa,SAAS,EAAzB,MAAM;IACmB,OAAO,EAAhC,eAAe;IACE,WAAW,EAA5B,OAAO;IACS,GAAG;IACH,MAAM;IACJ,WAAW;IACX,eAAe;IACf,oBAAoB;IACpB,YAAY;CAEtC,GAAU,OAAO,CAAC,yBAAyB,CAAC,CA8H9C;AAED;;;GAGG;AACH,kCAFW,GAAG,sCAOb;sCA5ZqI,mBAAmB;2CAAnB,mBAAmB;4BAC9H,SAAS;oCADkG,mBAAmB;+CAAnB,mBAAmB;kCAAnB,mBAAmB;qCAAnB,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"component-setup.d.ts","sourceRoot":"","sources":["../../lib/component-setup.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,mDAHG;IAAuC,GAAG,EAAlC,gBAAgB;CACxB,YA2MF;AAED;;;;;;;;;;;GAWG;AACH,mGAPG;IAAqB,SAAS,EAAtB,GAAG;IACe,QAAQ;IACb,aAAa,EAA1B,GAAG;IACe,aAAa;IACf,IAAI,EAApB,MAAM;CACd,GAAU,OAAO,CAAC,IAAI,CAAC,CA2HzB;sCA1VS,mBAAmB"}
1
+ {"version":3,"file":"component-setup.d.ts","sourceRoot":"","sources":["../../lib/component-setup.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,mDAHG;IAAuC,GAAG,EAAlC,gBAAgB;CACxB,YA4MF;AAED;;;;;;;;;;;GAWG;AACH,mGAPG;IAAqB,SAAS,EAAtB,GAAG;IACe,QAAQ;IACb,aAAa,EAA1B,GAAG;IACe,aAAa;IACf,IAAI,EAApB,MAAM;CACd,GAAU,OAAO,CAAC,IAAI,CAAC,CA2HzB;sCA3VS,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"coralite-element.d.ts","sourceRoot":"","sources":["../../lib/coralite-element.js"],"names":[],"mappings":"AAuCA;;;;;;GAMG;AACH,8BAJW,GAAG,QACH,WAAS,MAAM,GACb,GAAG,CAmBf;AAkmBD;;;;;;;;;;GAUG;AACH,6CARW,wBAAwB,kBACxB,WAAS,IAAI,UAErB;IAAyE,uBAAuB,GAAxF,KAAK,CAAC,iDAAiD,CAAC;IACQ,sBAAsB,GAAtF,KAAK,CAAC,gDAAgD,CAAC;IACC,cAAc,GAAtE,KAAK,CAAC,wCAAwC,CAAC;CACvD,GAAU,OAAO,eAAe,CA8BlC;AAvoBD;;;;;;;;;;GAUG;AAEH;;;;GAIG;AACH;IAOI;;;;OAIG;IACH,4BAHU,eAAe,GAAC,IAAI,CAGF;IAE5B;;;;OAIG;IACH,uBAHU,MAAM,GAAC,IAAI,CAGE;IAEvB;;;;OAIG;IACH,kBAHU,MAAO,IAAI,CAGH;IAElB;;;;OAIG;IACH,qBAHU,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAG1D;IAEnB;;;;OAIG;IACH,4BAHU,OAAO,CAGY;IAE7B;;;;OAIG;IACH,iCAHU,MAAM,GAAC,IAAI,CAGY;IAEjC;;;OAGG;IACH,qBAHU,gBAAgB,GAAC,IAAI,CAGV;IAErB;;;;OAIG;IACH,gCAHU,WAAS,IAAI,CAGS;IAEhC;;;;OAIG;IACH,mCAHU;YAAQ,MAAM,GAAE,eAAe;KAAC,GAAC,IAAI,CAGZ;IAEnC;;;;;;;;OAQG;IACH,kBAPU;QACL,uBAAuB,EAAE,KAAK,CAAC,iDAAiD,CAAC,CAAC;QAClF,sBAAsB,EAAE,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChF,cAAc,EAAE,KAAK,CAAC,wCAAwC,CAAC,CAAA;KAChE,CAOH;IAED;;;OAGG;IACH,kBAFU,wBAAwB,GAAC,IAAI,CAEX;IAG9B;;;;OAIG;IACH,0BAsDC;IAED;;;;;OAKG;IACH,sCAkBC;IAED;;;;;;;OAOG;IACH,+BAJW,MAAM,UACN,MAAM,GAAC,IAAI,UACX,MAAM,GAAC,IAAI,QAWrB;IAED;;;;;;OAMG;IACH,oBAkFC;IAED;;;;;;OAMG;IACH,6BAYC;IAED;;;;;OAKG;IACH,oBAHW,MAAM,EAAE,GACN,IAAI,GAAC,IAAI,CAYrB;IAED;;;;OAIG;IACH,uBAiCC;IAED;;;;OAIG;IACH,wBASC;IAED;;;;;;;OAOG;IACH,mBA2GC;IAED;;;;OAIG;IACH,sBAqCC;IAED;;;;;;OAMG;IACH,cAqCC;CACF;;;;;iBA5lBa,MAAM;;;;mBACN,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uEA/DV,oBAAoB;sEAApB,oBAAoB;8DAApB,oBAAoB"}
1
+ {"version":3,"file":"coralite-element.d.ts","sourceRoot":"","sources":["../../lib/coralite-element.js"],"names":[],"mappings":"AAuCA;;;;;;GAMG;AACH,8BAJW,GAAG,QACH,WAAS,MAAM,GACb,GAAG,CAmBf;AAmmBD;;;;;;;;;;GAUG;AACH,6CARW,wBAAwB,kBACxB,WAAS,IAAI,UAErB;IAAyE,uBAAuB,GAAxF,KAAK,CAAC,iDAAiD,CAAC;IACQ,sBAAsB,GAAtF,KAAK,CAAC,gDAAgD,CAAC;IACC,cAAc,GAAtE,KAAK,CAAC,wCAAwC,CAAC;CACvD,GAAU,OAAO,eAAe,CA8BlC;AAxoBD;;;;;;;;;;GAUG;AAEH;;;;GAIG;AACH;IAOI;;;;OAIG;IACH,4BAHU,eAAe,GAAC,IAAI,CAGF;IAE5B;;;;OAIG;IACH,uBAHU,MAAM,GAAC,IAAI,CAGE;IAEvB;;;;OAIG;IACH,kBAHU,MAAO,IAAI,CAGH;IAElB;;;;OAIG;IACH,qBAHU,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAG1D;IAEnB;;;;OAIG;IACH,4BAHU,OAAO,CAGY;IAE7B;;;;OAIG;IACH,iCAHU,MAAM,GAAC,IAAI,CAGY;IAEjC;;;OAGG;IACH,qBAHU,gBAAgB,GAAC,IAAI,CAGV;IAErB;;;;OAIG;IACH,gCAHU,WAAS,IAAI,CAGS;IAEhC;;;;OAIG;IACH,mCAHU;YAAQ,MAAM,GAAE,eAAe;KAAC,GAAC,IAAI,CAGZ;IAEnC;;;;;;;;OAQG;IACH,kBAPU;QACL,uBAAuB,EAAE,KAAK,CAAC,iDAAiD,CAAC,CAAC;QAClF,sBAAsB,EAAE,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChF,cAAc,EAAE,KAAK,CAAC,wCAAwC,CAAC,CAAA;KAChE,CAOH;IAED;;;OAGG;IACH,kBAFU,wBAAwB,GAAC,IAAI,CAEX;IAG9B;;;;OAIG;IACH,0BAsDC;IAED;;;;;OAKG;IACH,sCAkBC;IAED;;;;;;;OAOG;IACH,+BAJW,MAAM,UACN,MAAM,GAAC,IAAI,UACX,MAAM,GAAC,IAAI,QAWrB;IAED;;;;;;OAMG;IACH,oBAmFC;IAED;;;;;;OAMG;IACH,6BAYC;IAED;;;;;OAKG;IACH,oBAHW,MAAM,EAAE,GACN,IAAI,GAAC,IAAI,CAYrB;IAED;;;;OAIG;IACH,uBAiCC;IAED;;;;OAIG;IACH,wBASC;IAED;;;;;;;OAOG;IACH,mBA2GC;IAED;;;;OAIG;IACH,sBAqCC;IAED;;;;;;OAMG;IACH,cAqCC;CACF;;;;;iBA7lBa,MAAM;;;;mBACN,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uEA/DV,oBAAoB;sEAApB,oBAAoB;8DAApB,oBAAoB"}
@@ -236,15 +236,13 @@ var CoraliteElement = class extends HTMLElement {
236
236
  }
237
237
  }
238
238
  }
239
- for (const hook of this._hooks.onBeforeComponentRender) {
240
- hook({
241
- state: target,
242
- instanceId: this._instanceId,
243
- componentId: this.componentOptions.componentId,
244
- refs,
245
- element: this,
246
- options: this.componentOptions
247
- });
239
+ for (const attr of this.attributes) {
240
+ if (attr.name === "data-cid") {
241
+ continue;
242
+ }
243
+ const camelName = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
244
+ const schema = options.attributes?.[camelName] || options.attributes?.[attr.name];
245
+ target[camelName] = schema ? coerce(attr.value, schema.type) : attr.value;
248
246
  }
249
247
  const hydrationTag = document.getElementById("__CORALITE_HYDRATION__");
250
248
  if (hydrationTag) {
@@ -257,13 +255,15 @@ var CoraliteElement = class extends HTMLElement {
257
255
  console.error("Coralite Element hydration failed:", this._instanceId);
258
256
  }
259
257
  }
260
- for (const attr of this.attributes) {
261
- if (attr.name === "data-cid") {
262
- continue;
263
- }
264
- const camelName = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
265
- const schema = options.attributes?.[camelName] || options.attributes?.[attr.name];
266
- target[camelName] = schema ? coerce(attr.value, schema.type) : attr.value;
258
+ for (const hook of this._hooks.onBeforeComponentRender) {
259
+ hook({
260
+ state: target,
261
+ instanceId: this._instanceId,
262
+ componentId: this.componentOptions.componentId,
263
+ refs,
264
+ element: this,
265
+ options: this.componentOptions
266
+ });
267
267
  }
268
268
  this._getterAbortControllers = {};
269
269
  for (const [key, getter] of Object.entries(options.getters || {})) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../lib/utils/errors.js", "../../lib/utils/core.js", "../../lib/coralite-element.js"],
4
- "sourcesContent": ["\n/**\n * @import { CoraliteErrorData } from '../../types/index.js'\n */\n\n/**\n * Base error class for all Coralite-related errors.\n */\nexport class CoraliteError extends Error {\n /**\n * @param {string} message - The error message.\n * @param {Object} [options] - Additional options for the error.\n * @param {string} [options.componentId] - The ID of the component where the error occurred.\n * @param {string} [options.filePath] - The path to the file where the error occurred.\n * @param {string} [options.instanceId] - The unique ID of the component instance.\n * @param {string} [options.pagePath] - The path to the page being rendered.\n * @param {number} [options.line] - The line number where the error occurred.\n * @param {number} [options.column] - The column number where the error occurred.\n * @param {string} [options.stackFile] - The file name from the stack trace.\n * @param {Error} [options.cause] - The original error that caused this error.\n */\n constructor (message, options = {}) {\n super(message, options)\n this.name = 'CoraliteError'\n this.isCoraliteError = true\n this.componentId = options.componentId\n this.filePath = options.filePath\n this.instanceId = options.instanceId\n this.pagePath = options.pagePath\n this.line = options.line\n this.column = options.column\n this.stackFile = options.stackFile\n\n // Polyfill cause if necessary (node version differences)\n if (options.cause && !this.cause) {\n this.cause = options.cause\n }\n }\n}\n\n/**\n * Default error handler.\n * @param {CoraliteErrorData} data - The data object containing error details.\n */\nexport function defaultOnError ({ level, message, error }) {\n if (level === 'ERR') {\n if (error) {\n throw error\n }\n throw new CoraliteError(message)\n } else if (level === 'WARN') {\n console.warn(message)\n } else {\n console.log(message)\n }\n}\n\n/**\n * Handles errors using an optional callback or the default handler.\n * @param {Object} options - The options for handling the error.\n * @param {Function} [options.onErrorCallback] - The optional custom error callback function.\n * @param {CoraliteErrorData} options.data - The error data to be handled.\n */\nexport function handleError ({ onErrorCallback, data }) {\n const error = data.error\n if (error && 'isCoraliteError' in error && error.isCoraliteError) {\n const coraliteError = error\n // @ts-ignore\n data.componentId = data.componentId || coraliteError.componentId\n // @ts-ignore\n data.filePath = data.filePath || coraliteError.filePath\n // @ts-ignore\n data.instanceId = data.instanceId || coraliteError.instanceId\n // @ts-ignore\n data.pagePath = data.pagePath || coraliteError.pagePath\n // @ts-ignore\n data.line = data.line || coraliteError.line\n // @ts-ignore\n data.column = data.column || coraliteError.column\n // @ts-ignore\n data.stackFile = data.stackFile || coraliteError.stackFile\n }\n\n if (onErrorCallback) {\n onErrorCallback(data)\n } else {\n defaultOnError(data)\n }\n}\n", "import { CoraliteError } from './errors.js'\n\n/**\n * @import {\n * CoraliteModule,\n * CoraliteComponent,\n * CoraliteComponentResult,\n * } from '../../types/index.js'\n */\n\nconst KEBAB_REGEX = /[-|:]([a-z])/g\n\n/**\n * Converts a kebab-case string to camelCase\n * @param {string} str - The kebab-case string to convert\n * @returns {string} - The camelCase version of the string\n */\nexport function kebabToCamel (str) {\n // replace each dash followed by a letter with the uppercase version of the letter\n return str.replace(KEBAB_REGEX, function (match, letter) {\n return letter.toUpperCase()\n })\n}\n\n/**\n * Converts all keys in an object from kebab-case to camelCase\n * @template T\n * @param {Record<string, T>} object - The object with kebab-case keys\n * @returns {Record<string, T>} - A new object with camelCase keys\n */\nexport function cleanKeys (object) {\n /** @type {Record<string, T>} */\n const result = {}\n\n for (const [key, value] of Object.entries(object)) {\n result[key] = value\n\n const camelKey = kebabToCamel(key)\n if (camelKey !== key) {\n result[camelKey] = value\n }\n }\n\n return result\n}\n\n/**\n * Recursively clones an object or array and normalizes any function state\n * it finds into a string representation that preserves standard function syntax,\n * bypassing ES6 shorthand method serialization issues.\n * @param {any} target - The object or array to normalize.\n * @param {Function} [transform] - Optional transform function for each node.\n * @param {WeakMap} [seen=new WeakMap()] - Map of seen objects to handle circular references.\n * @returns {any} A deeply cloned object with normalized functions.\n */\nexport function normalizeObjectFunctions (target, transform = null, seen = new WeakMap()) {\n if (typeof transform === 'function') {\n const transformed = transform(target)\n if (transformed !== target) {\n return transformed\n }\n }\n\n if (typeof target !== 'object' || target === null) {\n return target\n }\n\n if (seen.has(target)) {\n return seen.get(target)\n }\n\n if (Array.isArray(target)) {\n const arr = []\n seen.set(target, arr)\n for (let i = 0; i < target.length; i++) {\n arr.push(normalizeObjectFunctions(target[i], transform, seen))\n }\n return arr\n }\n\n const obj = {}\n seen.set(target, obj)\n for (const key in target) {\n if (Object.hasOwn(target, key)) {\n if (typeof target[key] === 'function') {\n const normalizedString = normalizeFunction(target[key])\n const originalFunction = target[key]\n\n const wrapper = function () {\n return originalFunction.apply(this, arguments)\n }\n wrapper.toString = () => normalizedString\n obj[key] = wrapper\n } else {\n obj[key] = normalizeObjectFunctions(target[key], transform, seen)\n }\n }\n }\n\n return obj\n}\n\n/**\n * Checks whether the given object is an object and has at least one own key.\n * @param {any} obj - The object to check.\n * @returns {boolean} True if the object is truthy and has keys, otherwise false.\n */\nexport function hasObjectKeys (obj) {\n return obj && typeof obj === 'object' && Object.keys(obj).length > 0\n}\n\n/**\n * Merges two arrays, returning a new array with unique items.\n * Uses JSON.stringify for deep comparison of object elements, preserving object uniqueness correctly.\n * @param {Array<any>} [arr1] - The first array.\n * @param {Array<any>} [arr2] - The second array.\n * @returns {Array<any>} A new array with unique values from both input arrays.\n */\nexport function mergeUniqueObjects (arr1, arr2) {\n const all = [...(arr1 || []), ...(arr2 || [])]\n const seen = new Set()\n return all.filter(item => {\n const key = typeof item === 'object' ? JSON.stringify(item) : item\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\n/**\n * Normalizes function declarations to ensure consistent formatting.\n * Converts shorthand method syntax to full function declarations where needed,\n * while preserving arrow functions and existing full declarations.\n *\n * @param {Function} func - The function to normalize\n * @returns {string} The normalized function string representation\n */\nexport function normalizeFunction (func) {\n const original = func.toString().trim()\n\n const firstBrace = original.indexOf('{')\n const firstArrow = original.indexOf('=>')\n\n const isArrow = firstArrow !== -1 && (firstBrace === -1 || firstArrow < firstBrace)\n\n if (isArrow) {\n return original\n }\n\n // For non-arrows, extract header to check for shorthand\n const header = firstBrace !== -1 ? original.slice(0, firstBrace).trim() : original\n\n const isStandard = header.startsWith('function') || header.startsWith('async function')\n\n if (isStandard) {\n return original\n }\n\n // Handle Method Shorthand\n if (header.startsWith('async ')) {\n if (header.startsWith('async get ') || header.startsWith('async set ')) {\n return original\n }\n\n return original.replace(/^async\\s+([$\\w]+)\\s*\\(/, 'async function(')\n } else {\n if (header.startsWith('get ') || header.startsWith('set ')) {\n return original\n }\n\n return original.replace(/^([$\\w]+)\\s*\\(/, 'function(')\n }\n}\n\n\n/**\n * Recursively clones an AST node and its children, ensuring that\n * inner references (like parents and slots) point to the newly cloned nodes.\n *\n * @param {Map<Object, Object>} nodeMap - A map tracking original nodes to their newly cloned counterparts.\n * @param {Object} node - The current AST node being cloned.\n * @param {Object} [parent] - The parent node reference to assign to the clone.\n * @returns {Object} The newly cloned node.\n */\nexport function cloneNode (nodeMap, node, parent) {\n const newNode = Object.create(Object.getPrototypeOf(node))\n\n // Copy all own enumerable properties\n Object.assign(newNode, node)\n\n if (parent) {\n newNode.parent = parent\n }\n\n if (newNode.attribs) {\n newNode.attribs = { ...newNode.attribs }\n }\n\n // Register in map\n nodeMap.set(node, newNode)\n\n // Recursively clone children\n if (node.children) {\n const children = node.children\n const length = children.length\n const clonedChildren = new Array(length)\n newNode.children = clonedChildren\n\n for (let i = 0; i < length; i++) {\n const clonedChild = cloneNode(nodeMap, children[i], newNode)\n clonedChildren[i] = clonedChild\n if (i > 0) {\n clonedChild.prev = clonedChildren[i - 1]\n clonedChildren[i - 1].next = clonedChild\n }\n }\n }\n\n // Update slot references to point to new cloned nodes\n if (node.slots) {\n const slots = node.slots\n const length = slots.length\n const clonedSlots = new Array(length)\n for (let i = 0; i < length; i++) {\n const slot = slots[i]\n const clonedSlot = { ...slot }\n if (slot.node) {\n const clonedNode = nodeMap.get(slot.node)\n if (clonedNode) {\n clonedSlot.node = clonedNode\n }\n }\n clonedSlots[i] = clonedSlot\n }\n newNode.slots = clonedSlots\n }\n\n // Preserve the enhanced flag without re-running enhanceNode\n Object.defineProperty(newNode, '__coralite_enhanced__', {\n value: true,\n enumerable: false,\n configurable: true\n })\n\n return newNode\n}\n\n/**\n * Creates a shallow copy of a CoraliteModule with a deep clone of its DOM tree (template) and re-linked internal references to enable safe independent mutation.\n *\n * Top-level non-DOM state (id, path, script, isTemplate, lineOffset) are shallow copied. Nested objects within these state (e.g., path) remain shared references. Only DOM-related structures undergo deep cloning and reference re-linking to isolate mutations from the original module.\n *\n * @param {CoraliteModule} originalModule - Module to clone.\n * @returns {CoraliteModule}\n */\nexport function cloneModuleInstance (originalModule) {\n const nodeMap = new Map()\n\n // Clone the main template tree\n const newTemplate = cloneNode(nodeMap, originalModule.template, null)\n\n // Reconstruct the 'values' object\n const newValues = {\n attributes: originalModule.values.attributes.map(item => ({\n ...item,\n element: nodeMap.get(item.element)\n })),\n textNodes: originalModule.values.textNodes.map(item => ({\n ...item,\n textNode: nodeMap.get(item.textNode)\n })),\n refs: originalModule.values.refs.map(item => ({\n ...item,\n element: nodeMap.get(item.element)\n }))\n }\n\n // Reconstruct customElements list\n const newCustomElements = originalModule.customElements.map(el => nodeMap.get(el))\n\n // Reconstruct slotElements\n const newSlotElements = {}\n if (originalModule.slotElements) {\n for (const modId in originalModule.slotElements) {\n newSlotElements[modId] = {}\n const slotGroup = originalModule.slotElements[modId]\n\n for (const slotName in slotGroup) {\n const slotItem = slotGroup[slotName]\n newSlotElements[modId][slotName] = {\n ...slotItem,\n element: nodeMap.get(slotItem.element)\n }\n }\n }\n }\n\n // Return the new module structure\n return {\n ...originalModule,\n template: newTemplate,\n values: newValues,\n customElements: newCustomElements,\n // @ts-ignore\n slotElements: newSlotElements\n }\n}\n\n/**\n * Creates a deep copy of a CoraliteComponent with re-linked internal references to enable safe independent mutation.\n *\n * @param {CoraliteComponent & CoraliteComponentResult} originalDocument - Document to clone.\n * @returns {CoraliteComponent & CoraliteComponentResult}\n */\nexport function cloneComponentInstance (originalDocument) {\n const nodeMap = new Map()\n const newRoot = cloneNode(nodeMap, originalDocument.root, null)\n\n const newCustomElements = originalDocument.customElements.map(el => nodeMap.get(el))\n const newTempElements = originalDocument.tempElements ? originalDocument.tempElements.map(el => nodeMap.get(el)) : []\n const newSkipRenderElements = originalDocument.skipRenderElements ? originalDocument.skipRenderElements.map(el => nodeMap.get(el)) : []\n\n return {\n ...originalDocument,\n state: { ...originalDocument.state },\n root: newRoot,\n customElements: newCustomElements,\n tempElements: newTempElements,\n skipRenderElements: newSkipRenderElements\n }\n}\n\n/**\n * Calculates the DOM path from a node to the root.\n * @param {Object} node - The node to calculate the path for.\n * @param {Object} root - The root node.\n * @returns {Array<number>} An array of indices representing the path.\n */\nexport function getNodePath (node, root) {\n const path = []\n let current = node\n while (current && current !== root) {\n const parent = current.parent\n if (!parent) {\n break\n }\n const index = parent.children.indexOf(current)\n if (index === -1) {\n break\n }\n path.unshift(index)\n current = parent\n }\n return path\n}\n\n/**\n * Generates a hydration map for the client.\n * @param {Array<Object>} templateNodes - The component's template nodes.\n * @param {Object} templateValues - The component's template values.\n * @returns {Object} The hydration map.\n */\nexport function generateHydrationMap (templateNodes, templateValues) {\n const map = {\n texts: [],\n attributes: [],\n refs: []\n }\n\n if (!templateNodes || !templateValues) {\n return map\n }\n\n const root = templateNodes.length > 0 ? templateNodes[0].parent : { children: templateNodes }\n\n if (templateValues.textNodes) {\n for (const item of templateValues.textNodes) {\n if (item.textNode) {\n const isHtml = item.type === 'html'\n const targetNode = isHtml ? item.textNode.parent : item.textNode\n\n map.texts.push({\n path: getNodePath(targetNode, root),\n template: item.textNode.data,\n type: isHtml ? 'html' : 'text'\n })\n }\n }\n }\n\n if (templateValues.attributes) {\n for (const item of templateValues.attributes) {\n if (item.element && item.element.attribs) {\n const originalValue = item.element.attribs[item.name]\n map.attributes.push({\n path: getNodePath(item.element, root),\n name: item.name,\n template: originalValue\n })\n }\n }\n }\n\n if (templateValues.refs) {\n for (const item of templateValues.refs) {\n if (item.element) {\n map.refs.push({\n path: getNodePath(item.element, root),\n name: item.name\n })\n }\n }\n }\n\n return map\n}\n\n/**\n * Recursively adds a component and its dependencies to a tracking object.\n *\n * @param {string} componentId - The ID of the component to add.\n * @param {Object.<string, boolean>} processed - The object tracking processed components.\n * @param {Object.<string, any>} sharedFunctions - The map of shared component functions.\n */\nexport function addComponentAndDependencies (componentId, processed, sharedFunctions) {\n if (!processed[componentId] && sharedFunctions[componentId]) {\n processed[componentId] = true\n\n // Add all dependencies of this component\n const dependencies = sharedFunctions[componentId].components || []\n for (const depId of dependencies) {\n addComponentAndDependencies(depId, processed, sharedFunctions)\n }\n }\n}\n\n/**\n * Recursively clones an AST node and its children, stripping circular references\n * and assigning unique IDs for client-side hydration.\n *\n * @param {Array<Object>} nodes - The nodes to clean.\n * @param {WeakMap} nodeMap - Map to track original nodes to their unique IDs.\n * @param {Object} state - Object containing the current node counter.\n * @returns {Array<Object>|null} The cleaned AST nodes.\n */\nexport function cleanAST (nodes, nodeMap, state) {\n if (!nodes) {\n return null\n }\n\n return nodes.map((node) => {\n const cloned = { ...node }\n // Assign unique ID for token mapping\n const id = state.counter++\n nodeMap.set(node, id)\n cloned._id = id\n\n // Remove circular references\n delete cloned.parent\n delete cloned.prev\n delete cloned.next\n delete cloned.slots\n\n if (cloned.children) {\n cloned.children = cleanAST(cloned.children, nodeMap, state)\n }\n return cloned\n })\n}\n\n/**\n * Cleans the template values object, mapping original node references to unique IDs.\n *\n * @param {Object} values - The values object to clean.\n * @param {WeakMap} nodeMap - Map of original nodes to their unique IDs.\n * @returns {Object|null} The cleaned values object.\n */\nexport function cleanValues (values, nodeMap) {\n if (!values) {\n return null\n }\n\n const result = { ...values }\n\n if (result.attributes) {\n result.attributes = result.attributes.map(item => {\n const cloned = { ...item }\n cloned.elementId = nodeMap.get(item.element)\n delete cloned.element\n return cloned\n })\n }\n\n if (result.textNodes) {\n result.textNodes = result.textNodes.map(item => {\n const cloned = { ...item }\n cloned.textNodeId = nodeMap.get(item.textNode)\n delete cloned.textNode\n return cloned\n })\n }\n\n if (result.refs) {\n result.refs = result.refs.map(item => {\n const cloned = { ...item }\n cloned.elementId = nodeMap.get(item.element)\n delete cloned.element\n return cloned\n })\n }\n return result\n}\n\n/**\n * Safely merges partial plugin updates into the main context object.\n * Deeply merges plain objects and overwrites other types (arrays, primitives, etc.).\n *\n * @param {any} current - The current state object.\n * @param {any} patch - The patch object containing updates.\n * @returns {any} The newly merged state object.\n */\nexport function mergePluginState (current, patch) {\n if (!patch || typeof patch !== 'object') {\n return current\n }\n\n const result = { ...current }\n\n for (const key of Object.keys(patch)) {\n const patchValue = patch[key]\n const currentValue = result[key]\n\n // If both are plain objects, merge them deeply\n if (\n patchValue && typeof patchValue === 'object' && !Array.isArray(patchValue) &&\n currentValue && typeof currentValue === 'object' && !Array.isArray(currentValue)\n ) {\n result[key] = mergePluginState(currentValue, patchValue)\n } else {\n // Otherwise, overwrite (Arrays, strings, numbers, etc.)\n result[key] = patchValue\n }\n }\n\n return result\n}\n\n/**\n * Creates a reactive proxy that triggers a callback on changes.\n * Supports deep reactivity via lazy proxying of nested objects.\n *\n * @param {Object} target - The object to proxy.\n * @param {Function} onChange - Callback triggered when a property is set or deleted.\n * @param {WeakMap} [proxies=new WeakMap()] - Cache for existing proxies to handle circular references and identity.\n * @returns {Proxy} The reactive proxy.\n */\nexport function createReactiveProxy (target, onChange, proxies = new WeakMap()) {\n if (proxies.has(target)) {\n return proxies.get(target)\n }\n\n const handler = {\n get (target, property, receiver) {\n const value = Reflect.get(target, property, receiver)\n if (value !== null && typeof value === 'object' && !(typeof Node !== 'undefined' && value instanceof Node)) {\n return createReactiveProxy(value, onChange, proxies)\n }\n return value\n },\n set (target, property, value, receiver) {\n const oldValue = target[property]\n if (oldValue === value && property in target) {\n return true\n }\n\n const result = Reflect.set(target, property, value, receiver)\n if (result) {\n onChange({\n property,\n value,\n oldValue,\n target\n })\n }\n return result\n },\n deleteProperty (target, property) {\n const hadProperty = Object.prototype.hasOwnProperty.call(target, property)\n const oldValue = target[property]\n const result = Reflect.deleteProperty(target, property)\n if (result && hadProperty) {\n onChange({\n property,\n value: undefined,\n oldValue,\n target,\n deleted: true\n })\n }\n return result\n }\n }\n\n const proxy = new Proxy(target, handler)\n proxies.set(target, proxy)\n return proxy\n}\n\n/**\n * Creates a read-only proxy that throws on mutation attempts.\n * @param {Object} target - The object to proxy.\n * @param {WeakMap} [proxies=new WeakMap()] - Cache for existing proxies.\n * @returns {Proxy} The read-only proxy.\n */\nexport function createReadOnlyProxy (target, proxies = new WeakMap()) {\n if (proxies.has(target)) {\n return proxies.get(target)\n }\n\n const handler = {\n get (target, property, receiver) {\n const value = Reflect.get(target, property, receiver)\n if (value !== null && typeof value === 'object' && !(typeof Node !== 'undefined' && value instanceof Node)) {\n return createReadOnlyProxy(value, proxies)\n }\n return value\n },\n set () {\n throw new CoraliteError('Cannot mutate state inside a getter. State is read-only here.')\n },\n deleteProperty () {\n throw new CoraliteError('Cannot delete state inside a getter. State is read-only here.')\n }\n }\n\n const proxy = new Proxy(target, handler)\n\n proxies.set(target, proxy)\n\n return proxy\n}\n\n/**\n * Defines a Coralite component.\n * On the client, this acts as an identity function for type safety and HRM.\n * @param {Object} options - Component options\n * @returns {Object} The component options\n */\nexport function defineComponent (options) {\n return options\n}\n", "/**\n * @import {\n * CoraliteClientPluginDisconnectedCallback,\n * CoraliteClientPluginAfterComponentRenderCallback,\n * CoraliteClientPluginBeforeComponentRenderCallback\n * } from '../types/plugin.js'\n */\n\nimport { createReadOnlyProxy } from './utils/core.js'\n\nconst BOOLEAN_ATTRIBUTES = new Set([\n 'allowfullscreen',\n 'async',\n 'autofocus',\n 'autoplay',\n 'checked',\n 'controls',\n 'default',\n 'defer',\n 'disabled',\n 'formnovalidate',\n 'hidden',\n 'inert',\n 'ismap',\n 'itemscope',\n 'loop',\n 'multiple',\n 'muted',\n 'nomodule',\n 'novalidate',\n 'open',\n 'playsinline',\n 'readonly',\n 'required',\n 'reversed',\n 'selected',\n 'truespeed'\n])\n\n/**\n * Coerces a value to a specified type.\n * Supports Number, Boolean, and String.\n * @param {any} value - The value to coerce.\n * @param {Function|string} type - The target type (Constructor or string name).\n * @returns {any} The coerced value.\n */\nexport function coerce (value, type) {\n if (value === null || value === undefined) {\n return value\n }\n if (type === Number || type === 'Number') {\n return Number(value)\n }\n if (type === Boolean || type === 'Boolean') {\n if (value === '') {\n return true\n }\n return value !== 'false' && value !== null\n }\n if (type === String || type === 'String') {\n return String(value)\n }\n return value\n}\n\n/**\n * @typedef {Object} CoraliteComponentOptions\n * @property {string} componentId - The unique identifier for the component.\n * @property {string} [templateHTML] - The raw HTML string for imperative mounting.\n * @property {Object} [defaultValues] - The initial state values extracted from the server data block.\n * @property {Object} [attributes] - Schema for coercing HTML attributes into typed primitives.\n * @property {Object.<string, Function>} [getters] - Pure functions for derived state, supporting Promises.\n * @property {Object.<string, Function>} [slots] - Transformation functions for projected Light DOM.\n * @property {Function} [client] - The client-side controller logic.\n * @property {Object} [hydrationMap] - AST mapping for reactive text nodes, attributes, and refs.\n */\n\n/**\n * Base class for all Coralite custom elements.\n *\n * @augments HTMLElement\n */\nexport class CoraliteElement extends HTMLElement {\n /**\n * Initializes a new instance of the CoraliteElement.\n * Sets up internal state trackers, binding collections, and hook registries.\n */\n constructor () {\n super()\n /**\n * Controls native teardown of event listeners and async fetches upon disconnection.\n * @type {AbortController|null}\n * @protected\n */\n this._abortController = null\n\n /**\n * A globally unique, deterministic identifier (e.g., `my-comp-0`).\n * @type {string|null}\n * @protected\n */\n this._instanceId = null\n\n /**\n * The unified, deeply reactive proxy holding attributes, data, and getters.\n * @type {Object|null}\n * @protected\n */\n this._state = null\n\n /**\n * The collection of DOM nodes mapped to template tokens and attributes.\n * @type {Array<{type: string, node: Node, template?: string, name?: string}>}\n * @protected\n */\n this._bindings = []\n\n /**\n * Flag to prevent multiple synchronous state mutations from triggering multiple DOM paints.\n * @type {boolean}\n * @protected\n */\n this._isUpdatePending = false\n\n /**\n * A unique Symbol generated per render cycle to prevent async getter race conditions.\n * @type {symbol|null}\n * @protected\n */\n this._currentRenderVersion = null\n\n /**\n * @type {MutationObserver|null}\n * @protected\n */\n this._observer = null\n\n /**\n * Hook to fetch globally registered Phase-2 plugin contexts.\n * @type {Function|null}\n * @protected\n */\n this._clientContextGetter = null\n\n /**\n * Tracks AbortControllers specifically for cancelling stale async getters.\n * @type {Object.<string, AbortController>|null}\n * @protected\n */\n this._getterAbortControllers = null\n\n /**\n * Internal lifecycle hooks injected by registered Coralite plugins.\n * @type {{\n * onBeforeComponentRender: Array<CoraliteClientPluginBeforeComponentRenderCallback>,\n * onAfterComponentRender: Array<CoraliteClientPluginAfterComponentRenderCallback>,\n * onDisconnected: Array<CoraliteClientPluginDisconnectedCallback>\n * }}\n * @protected\n */\n this._hooks = {\n onBeforeComponentRender: [],\n onAfterComponentRender: [],\n onDisconnected: []\n }\n\n /**\n * The definition and schema of the component generated by the compiler.\n * @type {CoraliteComponentOptions|null}\n */\n this.componentOptions = null\n }\n\n /**\n * Invoked natively when the element is added to the document.\n * Handles the architectural split between Declarative (SSR) and Imperative (JS) components.\n * Orchestrates template injection, instance ID generation, and state/binding setup.\n */\n connectedCallback () {\n this._abortController = new AbortController()\n\n if (!this.componentOptions) {\n return\n }\n\n // Declarative components receive a data-cid from the server.\n // Imperative components (created via document.createElement) do not.\n const isImperative = !this.hasAttribute('data-cid')\n\n // Imperative Flow: Manually stamp the template and project the Light DOM.\n if (isImperative && this.componentOptions.templateHTML) {\n const originalLightDOM = Array.from(this.childNodes)\n this.innerHTML = this.componentOptions.templateHTML\n\n if (originalLightDOM.length > 0) {\n const slots = this.querySelectorAll('slot')\n slots.forEach(slot => {\n const slotName = slot.getAttribute('name') || 'default'\n const matchingNodes = originalLightDOM.filter(node => {\n // @ts-ignore\n const nodeSlot = (node.getAttribute && node.getAttribute('slot')) || 'default'\n return nodeSlot === slotName\n })\n matchingNodes.forEach(n => slot.appendChild(n))\n })\n }\n }\n\n // Establish the Deterministic Instance ID\n if (this.hasAttribute('data-cid')) {\n this._instanceId = this.getAttribute('data-cid')\n } else {\n // Fallback counter for imperatively created components\n // @ts-ignore\n window.__coralite_instanceCounters = window.__coralite_instanceCounters || {}\n const prefix = this.componentOptions.componentId\n // @ts-ignore\n if (window.__coralite_instanceCounters[prefix] === undefined) {\n // @ts-ignore\n window.__coralite_instanceCounters[prefix] = 0\n }\n // @ts-ignore\n this._instanceId = `${prefix}-${window.__coralite_instanceCounters[prefix]++}`\n }\n\n if (isImperative) {\n this.setAttribute('data-cid', this._instanceId)\n }\n\n this._setupState()\n this._setupBindings()\n this._init(isImperative)\n }\n\n /**\n * Invoked natively when the element is removed from the document.\n * Aborts pending requests and triggers `onDisconnected` plugin hooks\n * to ensure external libraries (e.g., Observers) do not cause memory leaks.\n * @this {any}\n */\n disconnectedCallback () {\n if (this._abortController) {\n this._abortController.abort()\n }\n\n if (!this.componentOptions) {\n return\n }\n\n for (const hook of this._hooks.onDisconnected) {\n hook({\n state: this._state,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n element: this,\n options: this.componentOptions\n })\n }\n }\n\n /**\n * Invoked natively when an observed HTML attribute changes.\n * Coerces the raw string value based on the component's attribute schema\n * and synchronizes it into the reactive state proxy.\n * @param {string} name - The kebab-case name of the attribute.\n * @param {string|null} oldVal - The previous value.\n * @param {string|null} newVal - The new value.\n */\n attributeChangedCallback (name, oldVal, newVal) {\n if (!this._state || oldVal === newVal || name === 'data-cid') {\n return\n }\n const camelName = name.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n const schema = this.componentOptions.attributes?.[camelName] || this.componentOptions.attributes?.[name]\n const value = schema ? coerce(newVal, schema.type) : newVal\n\n this._state[camelName] = value\n }\n\n /**\n * Constructs the unified state object.\n * Merges `defaultValues`, JSON hydration payloads, and DOM attributes.\n * Defines getters (wrapping state in a Read-Only proxy) and applies the final Read/Write Proxy.\n * @this {any}\n * @private\n */\n _setupState () {\n const options = this.componentOptions\n const target = { ...options.defaultValues }\n\n /** @type {Array<{name: string, element: HTMLElement}>} */\n const refs = []\n if (options.hydrationMap && options.hydrationMap.refs) {\n for (const ref of options.hydrationMap.refs) {\n const uniqueRefValue = `${this._instanceId}__${ref.name}`\n\n if (!target[`ref_${ref.name}`]) {\n target[`ref_${ref.name}`] = uniqueRefValue\n }\n\n const node = this.getNodeByPath(ref.path)\n if (node) {\n if (node.setAttribute) {\n node.setAttribute('ref', uniqueRefValue)\n }\n refs.push({\n name: ref.name,\n element: node\n })\n }\n }\n }\n\n // Trigger Before-Render hooks BEFORE state is proxied, allowing plugins to inject reactive data\n for (const hook of this._hooks.onBeforeComponentRender) {\n hook({\n state: target,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n refs,\n element: this,\n options: this.componentOptions\n })\n }\n\n // Hydrate data() block results from the SSR JSON payload\n const hydrationTag = document.getElementById('__CORALITE_HYDRATION__')\n if (hydrationTag) {\n try {\n const allData = JSON.parse(hydrationTag.textContent)\n if (allData[this._instanceId]) {\n Object.assign(target, allData[this._instanceId])\n }\n } catch {\n console.error('Coralite Element hydration failed:', this._instanceId)\n }\n }\n\n // Process initial attributes mapping\n for (const attr of this.attributes) {\n if (attr.name === 'data-cid') {\n continue\n }\n const camelName = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n const schema = options.attributes?.[camelName] || options.attributes?.[attr.name]\n target[camelName] = schema ? coerce(attr.value, schema.type) : attr.value\n }\n\n // Define derived state getters with isolation controllers\n this._getterAbortControllers = {}\n for (const [key, getter] of Object.entries(options.getters || {})) {\n Object.defineProperty(target, key, {\n get: () => {\n if (this._getterAbortControllers[key]) {\n this._getterAbortControllers[key].abort()\n }\n this._getterAbortControllers[key] = new AbortController()\n\n // Enforce \"Dual-Proxy\" safety: Getters cannot mutate state\n const roState = createReadOnlyProxy(this._state)\n return getter(roState, { signal: this._getterAbortControllers[key].signal })\n },\n enumerable: true,\n configurable: true\n })\n }\n\n this._state = this._createReactiveProxy(target)\n }\n\n /**\n * Wraps the state target in a reactive Proxy.\n * Intercepts property setters to automatically batch and schedule DOM updates.\n * @param {Object} target - The state dictionary.\n * @returns {Proxy} The reactive state proxy.\n * @private\n */\n _createReactiveProxy (target) {\n const self = this\n return new Proxy(target, {\n set (t, p, v) {\n if (t[p] === v) {\n return true\n }\n t[p] = v\n self._scheduleUpdate()\n return true\n }\n })\n }\n\n /**\n * Traverses the DOM tree using an AST-generated path index array.\n * Allows O(1) element lookups without relying on querySelectors or classes.\n * @param {number[]} path - Array of childNode indices (e.g., `[0, 1, 2]`).\n * @returns {Node|null} The physical DOM node, or null if traversal fails.\n */\n getNodeByPath (path) {\n let node = this\n for (const index of path) {\n if (!node) {\n return null\n }\n // @ts-ignore\n node = node.childNodes[index]\n }\n return node\n }\n\n /**\n * Initializes DOM bindings based on the compiler's hydration map.\n * Caches physical DOM references to text nodes and attributes that contain template tokens.\n * @private\n */\n _setupBindings () {\n this._bindings = []\n const map = this.componentOptions.hydrationMap\n if (!map) {\n return\n }\n\n if (map.texts) {\n for (const item of map.texts) {\n const node = this.getNodeByPath(item.path)\n if (node) {\n this._bindings.push({\n type: item.type || 'text',\n node,\n template: item.template\n })\n }\n }\n }\n\n if (map.attributes) {\n for (const item of map.attributes) {\n const node = this.getNodeByPath(item.path)\n if (node) {\n this._bindings.push({\n type: 'attribute',\n node,\n name: item.name,\n template: item.template\n })\n }\n }\n }\n }\n\n /**\n * Schedules a DOM update in the next microtask queue.\n * This guarantees that multiple synchronous state mutations result in only one render pass.\n * @private\n */\n _scheduleUpdate () {\n if (this._isUpdatePending) {\n return\n }\n this._isUpdatePending = true\n queueMicrotask(() => {\n this._updateDOM()\n this._isUpdatePending = false\n })\n }\n\n /**\n * Performs the physical DOM update and resolves template tokens.\n * **Async Safety:** Implements a Symbol-based locking mechanism (`renderVersion`)\n * to guarantee that if state mutates while an async getter is pending, the stale\n * Promise will be discarded, preventing DOM race conditions.\n * @this {any}\n * @private\n */\n _updateDOM () {\n // Create a unique lock for this specific render cycle\n const renderVersion = Symbol()\n this._currentRenderVersion = renderVersion\n\n // Extract unique tokens to prevent double-reading and accidental aborts\n /** @type {Set<string>} */\n const requiredTokens = new Set()\n for (const binding of this._bindings) {\n binding.template.replace(/\\{\\{\\s*(.+?)\\s*\\}\\}/g, (_, key) => {\n requiredTokens.add(key)\n return ''\n })\n }\n\n const evaluatedTokens = {}\n let hasPromise = false\n\n // Evaluate getters exactly once per render cycle\n for (const key of requiredTokens) {\n let val = this._state[key]\n if (typeof val === 'function') {\n val = val(this._state)\n }\n evaluatedTokens[key] = val\n if (val instanceof Promise) {\n hasPromise = true\n }\n }\n\n // The DOM Mutator Function\n const applyBindings = (tokenValues) => {\n // Race Condition Lock: Abort if a newer render cycle has already begun\n if (this._currentRenderVersion !== renderVersion) {\n return\n }\n\n for (const binding of this._bindings) {\n const hydratedValue = binding.template.replace(/\\{\\{\\s*(.+?)\\s*\\}\\}/g, (_, key) => {\n return tokenValues[key] ?? ''\n })\n\n if (binding.type === 'text') {\n if (binding.node.textContent !== hydratedValue) {\n binding.node.textContent = hydratedValue\n }\n } else if (binding.type === 'html') {\n /** @type {HTMLElement} */\n // @ts-ignore\n const element = binding.node\n\n if (element.innerHTML !== hydratedValue) {\n element.innerHTML = hydratedValue\n }\n } else if (binding.type === 'attribute') {\n /** @type {HTMLElement} */\n // @ts-ignore\n const element = binding.node\n\n if (BOOLEAN_ATTRIBUTES.has(binding.name)) {\n const isFalsy = hydratedValue === '' || hydratedValue === 'false' || hydratedValue === 'null' || hydratedValue === '0' || hydratedValue === 'undefined'\n if (isFalsy) {\n element.removeAttribute(binding.name)\n } else {\n element.setAttribute(binding.name, '')\n }\n } else {\n if (element.getAttribute(binding.name) !== hydratedValue) {\n element.setAttribute(binding.name, hydratedValue)\n }\n }\n }\n }\n\n this._processSlots()\n\n // Trigger After-Render hooks ONLY after the physical DOM is stable\n for (const hook of this._hooks.onAfterComponentRender) {\n hook({\n state: this._state,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n element: this,\n options: this.componentOptions\n })\n }\n }\n\n // Await Promises or Apply Synchronously\n if (hasPromise) {\n const keys = Object.keys(evaluatedTokens)\n const promises = keys.map(k => Promise.resolve(evaluatedTokens[k]))\n\n Promise.all(promises).then(resolvedValues => {\n const resolvedMap = {}\n keys.forEach((k, i) => {\n resolvedMap[k] = resolvedValues[i]\n })\n applyBindings(resolvedMap)\n }).catch(e => {\n if (e.name !== 'AbortError') {\n console.error('Coralite Async Getter Error:', e)\n }\n })\n } else {\n applyBindings(evaluatedTokens)\n }\n }\n\n /**\n * Evaluates and projects Light DOM elements into their respective `<slot>` nodes.\n * Invokes component-specific slot transformation functions.\n * @private\n */\n _processSlots () {\n const slots = this.componentOptions.slots\n if (!slots || Object.keys(slots).length === 0) {\n return\n }\n\n const slotElements = this.querySelectorAll('slot')\n slotElements.forEach(slotEl => {\n const slotName = slotEl.getAttribute('name') || 'default'\n const slotFn = slots[slotName]\n\n if (slotFn) {\n // @ts-ignore\n if (!slotEl._originalNodes) {\n // @ts-ignore\n slotEl._originalNodes = Array.from(slotEl.childNodes).map(n => n.cloneNode(true))\n }\n\n // @ts-ignore\n const result = slotFn(slotEl._originalNodes, this._state)\n\n if (result === undefined) {\n return\n }\n\n if (result === null || result === '' || (Array.isArray(result) && result.length === 0)) {\n slotEl.innerHTML = ''\n return\n }\n\n if (typeof result === 'string') {\n slotEl.innerHTML = result\n } else if (Array.isArray(result)) {\n slotEl.replaceChildren(...result)\n }\n }\n })\n }\n\n /**\n * The final initialization pipeline.\n * Injects globally registered client plugins into the local context payload,\n * triggers the initial DOM render, and invokes the user's `script()` logic.\n * @param {boolean} [isImperative=false] - If true, initial render runs synchronously.\n * @private\n */\n async _init (isImperative = false) {\n const self = this\n /**\n * The context payload injected into the user's script block.\n * @type {Object}\n */\n let localContext = {\n instanceId: this._instanceId,\n state: this._state,\n root: this,\n signal: this._abortController.signal,\n refs (id) {\n const refId = self._state[`ref_${id}`]\n if (!refId && typeof refId !== 'string') {\n return null\n }\n return self.querySelector(`[ref=\"${refId}\"]`)\n }\n }\n\n if (typeof this._clientContextGetter === 'function') {\n localContext = await this._clientContextGetter(localContext)\n }\n\n if (isImperative) {\n this._updateDOM()\n } else {\n this._scheduleUpdate()\n }\n\n if (this.componentOptions.client) {\n try {\n this.componentOptions.client(localContext)\n } catch (error) {\n console.error(`Coralite Error: Component \"${this.componentOptions.componentId}\" script failed:`, error)\n }\n }\n }\n}\n\n/**\n * Factory function to create a Coralite element class.\n * It dynamically defines the class, including observed attributes and hook initialization.\n * @param {CoraliteComponentOptions} options - Component options and metadata.\n * @param {Function|null} [contextGetter=null] - Optional function to retrieve client-side plugin context.\n * @param {Object} [hooks={}] - Lifecycle hooks to register.\n * @param {Array<CoraliteClientPluginBeforeComponentRenderCallback>} [hooks.onBeforeComponentRender] - Hooks to run before render.\n * @param {Array<CoraliteClientPluginAfterComponentRenderCallback>} [hooks.onAfterComponentRender] - Hooks to run after render.\n * @param {Array<CoraliteClientPluginDisconnectedCallback>} [hooks.onDisconnected] - Hooks to run after render.\n * @returns {typeof CoraliteElement} A new CoraliteElement subclass.\n */\nexport function createCoraliteClass (options, contextGetter = null, hooks = {}) {\n return class extends CoraliteElement {\n /**\n * The attributes to observe for changes.\n * @returns {string[]} Array of attribute names.\n */\n static get observedAttributes () {\n if (!options.attributes) {\n return []\n }\n return Object.keys(options.attributes).map(key => key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n )\n }\n\n /**\n * Initializes the dynamic Coralite element.\n */\n constructor () {\n super()\n this.componentOptions = options\n this._clientContextGetter = contextGetter\n this._hooks = {\n onBeforeComponentRender: hooks.onBeforeComponentRender || [],\n onAfterComponentRender: hooks.onAfterComponentRender || [],\n onDisconnected: hooks.onDisconnected || []\n }\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\n/**\n * @import { CoraliteErrorData } from '../../types/index.js'\n */\n\n/**\n * Base error class for all Coralite-related errors.\n */\nexport class CoraliteError extends Error {\n /**\n * @param {string} message - The error message.\n * @param {Object} [options] - Additional options for the error.\n * @param {string} [options.componentId] - The ID of the component where the error occurred.\n * @param {string} [options.filePath] - The path to the file where the error occurred.\n * @param {string} [options.instanceId] - The unique ID of the component instance.\n * @param {string} [options.pagePath] - The path to the page being rendered.\n * @param {number} [options.line] - The line number where the error occurred.\n * @param {number} [options.column] - The column number where the error occurred.\n * @param {string} [options.stackFile] - The file name from the stack trace.\n * @param {Error} [options.cause] - The original error that caused this error.\n */\n constructor (message, options = {}) {\n super(message, options)\n this.name = 'CoraliteError'\n this.isCoraliteError = true\n this.componentId = options.componentId\n this.filePath = options.filePath\n this.instanceId = options.instanceId\n this.pagePath = options.pagePath\n this.line = options.line\n this.column = options.column\n this.stackFile = options.stackFile\n\n // Polyfill cause if necessary (node version differences)\n if (options.cause && !this.cause) {\n this.cause = options.cause\n }\n }\n}\n\n/**\n * Default error handler.\n * @param {CoraliteErrorData} data - The data object containing error details.\n */\nexport function defaultOnError ({ level, message, error }) {\n if (level === 'ERR') {\n if (error) {\n throw error\n }\n throw new CoraliteError(message)\n } else if (level === 'WARN') {\n console.warn(message)\n } else {\n console.log(message)\n }\n}\n\n/**\n * Handles errors using an optional callback or the default handler.\n * @param {Object} options - The options for handling the error.\n * @param {Function} [options.onErrorCallback] - The optional custom error callback function.\n * @param {CoraliteErrorData} options.data - The error data to be handled.\n */\nexport function handleError ({ onErrorCallback, data }) {\n const error = data.error\n if (error && 'isCoraliteError' in error && error.isCoraliteError) {\n const coraliteError = error\n // @ts-ignore\n data.componentId = data.componentId || coraliteError.componentId\n // @ts-ignore\n data.filePath = data.filePath || coraliteError.filePath\n // @ts-ignore\n data.instanceId = data.instanceId || coraliteError.instanceId\n // @ts-ignore\n data.pagePath = data.pagePath || coraliteError.pagePath\n // @ts-ignore\n data.line = data.line || coraliteError.line\n // @ts-ignore\n data.column = data.column || coraliteError.column\n // @ts-ignore\n data.stackFile = data.stackFile || coraliteError.stackFile\n }\n\n if (onErrorCallback) {\n onErrorCallback(data)\n } else {\n defaultOnError(data)\n }\n}\n", "import { CoraliteError } from './errors.js'\n\n/**\n * @import {\n * CoraliteModule,\n * CoraliteComponent,\n * CoraliteComponentResult,\n * } from '../../types/index.js'\n */\n\nconst KEBAB_REGEX = /[-|:]([a-z])/g\n\n/**\n * Converts a kebab-case string to camelCase\n * @param {string} str - The kebab-case string to convert\n * @returns {string} - The camelCase version of the string\n */\nexport function kebabToCamel (str) {\n // replace each dash followed by a letter with the uppercase version of the letter\n return str.replace(KEBAB_REGEX, function (match, letter) {\n return letter.toUpperCase()\n })\n}\n\n/**\n * Converts all keys in an object from kebab-case to camelCase\n * @template T\n * @param {Record<string, T>} object - The object with kebab-case keys\n * @returns {Record<string, T>} - A new object with camelCase keys\n */\nexport function cleanKeys (object) {\n /** @type {Record<string, T>} */\n const result = {}\n\n for (const [key, value] of Object.entries(object)) {\n result[key] = value\n\n const camelKey = kebabToCamel(key)\n if (camelKey !== key) {\n result[camelKey] = value\n }\n }\n\n return result\n}\n\n/**\n * Recursively clones an object or array and normalizes any function state\n * it finds into a string representation that preserves standard function syntax,\n * bypassing ES6 shorthand method serialization issues.\n * @param {any} target - The object or array to normalize.\n * @param {Function} [transform] - Optional transform function for each node.\n * @param {WeakMap} [seen=new WeakMap()] - Map of seen objects to handle circular references.\n * @returns {any} A deeply cloned object with normalized functions.\n */\nexport function normalizeObjectFunctions (target, transform = null, seen = new WeakMap()) {\n if (typeof transform === 'function') {\n const transformed = transform(target)\n if (transformed !== target) {\n return transformed\n }\n }\n\n if (typeof target !== 'object' || target === null) {\n return target\n }\n\n if (seen.has(target)) {\n return seen.get(target)\n }\n\n if (Array.isArray(target)) {\n const arr = []\n seen.set(target, arr)\n for (let i = 0; i < target.length; i++) {\n arr.push(normalizeObjectFunctions(target[i], transform, seen))\n }\n return arr\n }\n\n const obj = {}\n seen.set(target, obj)\n for (const key in target) {\n if (Object.hasOwn(target, key)) {\n if (typeof target[key] === 'function') {\n const normalizedString = normalizeFunction(target[key])\n const originalFunction = target[key]\n\n const wrapper = function () {\n return originalFunction.apply(this, arguments)\n }\n wrapper.toString = () => normalizedString\n obj[key] = wrapper\n } else {\n obj[key] = normalizeObjectFunctions(target[key], transform, seen)\n }\n }\n }\n\n return obj\n}\n\n/**\n * Checks whether the given object is an object and has at least one own key.\n * @param {any} obj - The object to check.\n * @returns {boolean} True if the object is truthy and has keys, otherwise false.\n */\nexport function hasObjectKeys (obj) {\n return obj && typeof obj === 'object' && Object.keys(obj).length > 0\n}\n\n/**\n * Merges two arrays, returning a new array with unique items.\n * Uses JSON.stringify for deep comparison of object elements, preserving object uniqueness correctly.\n * @param {Array<any>} [arr1] - The first array.\n * @param {Array<any>} [arr2] - The second array.\n * @returns {Array<any>} A new array with unique values from both input arrays.\n */\nexport function mergeUniqueObjects (arr1, arr2) {\n const all = [...(arr1 || []), ...(arr2 || [])]\n const seen = new Set()\n return all.filter(item => {\n const key = typeof item === 'object' ? JSON.stringify(item) : item\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\n/**\n * Normalizes function declarations to ensure consistent formatting.\n * Converts shorthand method syntax to full function declarations where needed,\n * while preserving arrow functions and existing full declarations.\n *\n * @param {Function} func - The function to normalize\n * @returns {string} The normalized function string representation\n */\nexport function normalizeFunction (func) {\n const original = func.toString().trim()\n\n const firstBrace = original.indexOf('{')\n const firstArrow = original.indexOf('=>')\n\n const isArrow = firstArrow !== -1 && (firstBrace === -1 || firstArrow < firstBrace)\n\n if (isArrow) {\n return original\n }\n\n // For non-arrows, extract header to check for shorthand\n const header = firstBrace !== -1 ? original.slice(0, firstBrace).trim() : original\n\n const isStandard = header.startsWith('function') || header.startsWith('async function')\n\n if (isStandard) {\n return original\n }\n\n // Handle Method Shorthand\n if (header.startsWith('async ')) {\n if (header.startsWith('async get ') || header.startsWith('async set ')) {\n return original\n }\n\n return original.replace(/^async\\s+([$\\w]+)\\s*\\(/, 'async function(')\n } else {\n if (header.startsWith('get ') || header.startsWith('set ')) {\n return original\n }\n\n return original.replace(/^([$\\w]+)\\s*\\(/, 'function(')\n }\n}\n\n\n/**\n * Recursively clones an AST node and its children, ensuring that\n * inner references (like parents and slots) point to the newly cloned nodes.\n *\n * @param {Map<Object, Object>} nodeMap - A map tracking original nodes to their newly cloned counterparts.\n * @param {Object} node - The current AST node being cloned.\n * @param {Object} [parent] - The parent node reference to assign to the clone.\n * @returns {Object} The newly cloned node.\n */\nexport function cloneNode (nodeMap, node, parent) {\n const newNode = Object.create(Object.getPrototypeOf(node))\n\n // Copy all own enumerable properties\n Object.assign(newNode, node)\n\n if (parent) {\n newNode.parent = parent\n }\n\n if (newNode.attribs) {\n newNode.attribs = { ...newNode.attribs }\n }\n\n // Register in map\n nodeMap.set(node, newNode)\n\n // Recursively clone children\n if (node.children) {\n const children = node.children\n const length = children.length\n const clonedChildren = new Array(length)\n newNode.children = clonedChildren\n\n for (let i = 0; i < length; i++) {\n const clonedChild = cloneNode(nodeMap, children[i], newNode)\n clonedChildren[i] = clonedChild\n if (i > 0) {\n clonedChild.prev = clonedChildren[i - 1]\n clonedChildren[i - 1].next = clonedChild\n }\n }\n }\n\n // Update slot references to point to new cloned nodes\n if (node.slots) {\n const slots = node.slots\n const length = slots.length\n const clonedSlots = new Array(length)\n for (let i = 0; i < length; i++) {\n const slot = slots[i]\n const clonedSlot = { ...slot }\n if (slot.node) {\n const clonedNode = nodeMap.get(slot.node)\n if (clonedNode) {\n clonedSlot.node = clonedNode\n }\n }\n clonedSlots[i] = clonedSlot\n }\n newNode.slots = clonedSlots\n }\n\n // Preserve the enhanced flag without re-running enhanceNode\n Object.defineProperty(newNode, '__coralite_enhanced__', {\n value: true,\n enumerable: false,\n configurable: true\n })\n\n return newNode\n}\n\n/**\n * Creates a shallow copy of a CoraliteModule with a deep clone of its DOM tree (template) and re-linked internal references to enable safe independent mutation.\n *\n * Top-level non-DOM state (id, path, script, isTemplate, lineOffset) are shallow copied. Nested objects within these state (e.g., path) remain shared references. Only DOM-related structures undergo deep cloning and reference re-linking to isolate mutations from the original module.\n *\n * @param {CoraliteModule} originalModule - Module to clone.\n * @returns {CoraliteModule}\n */\nexport function cloneModuleInstance (originalModule) {\n const nodeMap = new Map()\n\n // Clone the main template tree\n const newTemplate = cloneNode(nodeMap, originalModule.template, null)\n\n // Reconstruct the 'values' object\n const newValues = {\n attributes: originalModule.values.attributes.map(item => ({\n ...item,\n element: nodeMap.get(item.element)\n })),\n textNodes: originalModule.values.textNodes.map(item => ({\n ...item,\n textNode: nodeMap.get(item.textNode)\n })),\n refs: originalModule.values.refs.map(item => ({\n ...item,\n element: nodeMap.get(item.element)\n }))\n }\n\n // Reconstruct customElements list\n const newCustomElements = originalModule.customElements.map(el => nodeMap.get(el))\n\n // Reconstruct slotElements\n const newSlotElements = {}\n if (originalModule.slotElements) {\n for (const modId in originalModule.slotElements) {\n newSlotElements[modId] = {}\n const slotGroup = originalModule.slotElements[modId]\n\n for (const slotName in slotGroup) {\n const slotItem = slotGroup[slotName]\n newSlotElements[modId][slotName] = {\n ...slotItem,\n element: nodeMap.get(slotItem.element)\n }\n }\n }\n }\n\n // Return the new module structure\n return {\n ...originalModule,\n template: newTemplate,\n values: newValues,\n customElements: newCustomElements,\n // @ts-ignore\n slotElements: newSlotElements\n }\n}\n\n/**\n * Creates a deep copy of a CoraliteComponent with re-linked internal references to enable safe independent mutation.\n *\n * @param {CoraliteComponent & CoraliteComponentResult} originalDocument - Document to clone.\n * @returns {CoraliteComponent & CoraliteComponentResult}\n */\nexport function cloneComponentInstance (originalDocument) {\n const nodeMap = new Map()\n const newRoot = cloneNode(nodeMap, originalDocument.root, null)\n\n const newCustomElements = originalDocument.customElements.map(el => nodeMap.get(el))\n const newTempElements = originalDocument.tempElements ? originalDocument.tempElements.map(el => nodeMap.get(el)) : []\n const newSkipRenderElements = originalDocument.skipRenderElements ? originalDocument.skipRenderElements.map(el => nodeMap.get(el)) : []\n\n return {\n ...originalDocument,\n state: { ...originalDocument.state },\n root: newRoot,\n customElements: newCustomElements,\n tempElements: newTempElements,\n skipRenderElements: newSkipRenderElements\n }\n}\n\n/**\n * Calculates the DOM path from a node to the root.\n * @param {Object} node - The node to calculate the path for.\n * @param {Object} root - The root node.\n * @returns {Array<number>} An array of indices representing the path.\n */\nexport function getNodePath (node, root) {\n const path = []\n let current = node\n while (current && current !== root) {\n const parent = current.parent\n if (!parent) {\n break\n }\n const index = parent.children.indexOf(current)\n if (index === -1) {\n break\n }\n path.unshift(index)\n current = parent\n }\n return path\n}\n\n/**\n * Generates a hydration map for the client.\n * @param {Array<Object>} templateNodes - The component's template nodes.\n * @param {Object} templateValues - The component's template values.\n * @returns {Object} The hydration map.\n */\nexport function generateHydrationMap (templateNodes, templateValues) {\n const map = {\n texts: [],\n attributes: [],\n refs: []\n }\n\n if (!templateNodes || !templateValues) {\n return map\n }\n\n const root = templateNodes.length > 0 ? templateNodes[0].parent : { children: templateNodes }\n\n if (templateValues.textNodes) {\n for (const item of templateValues.textNodes) {\n if (item.textNode) {\n const isHtml = item.type === 'html'\n const targetNode = isHtml ? item.textNode.parent : item.textNode\n\n map.texts.push({\n path: getNodePath(targetNode, root),\n template: item.textNode.data,\n type: isHtml ? 'html' : 'text'\n })\n }\n }\n }\n\n if (templateValues.attributes) {\n for (const item of templateValues.attributes) {\n if (item.element && item.element.attribs) {\n const originalValue = item.element.attribs[item.name]\n map.attributes.push({\n path: getNodePath(item.element, root),\n name: item.name,\n template: originalValue\n })\n }\n }\n }\n\n if (templateValues.refs) {\n for (const item of templateValues.refs) {\n if (item.element) {\n map.refs.push({\n path: getNodePath(item.element, root),\n name: item.name\n })\n }\n }\n }\n\n return map\n}\n\n/**\n * Recursively adds a component and its dependencies to a tracking object.\n *\n * @param {string} componentId - The ID of the component to add.\n * @param {Object.<string, boolean>} processed - The object tracking processed components.\n * @param {Object.<string, any>} sharedFunctions - The map of shared component functions.\n */\nexport function addComponentAndDependencies (componentId, processed, sharedFunctions) {\n if (!processed[componentId] && sharedFunctions[componentId]) {\n processed[componentId] = true\n\n // Add all dependencies of this component\n const dependencies = sharedFunctions[componentId].components || []\n for (const depId of dependencies) {\n addComponentAndDependencies(depId, processed, sharedFunctions)\n }\n }\n}\n\n/**\n * Recursively clones an AST node and its children, stripping circular references\n * and assigning unique IDs for client-side hydration.\n *\n * @param {Array<Object>} nodes - The nodes to clean.\n * @param {WeakMap} nodeMap - Map to track original nodes to their unique IDs.\n * @param {Object} state - Object containing the current node counter.\n * @returns {Array<Object>|null} The cleaned AST nodes.\n */\nexport function cleanAST (nodes, nodeMap, state) {\n if (!nodes) {\n return null\n }\n\n return nodes.map((node) => {\n const cloned = { ...node }\n // Assign unique ID for token mapping\n const id = state.counter++\n nodeMap.set(node, id)\n cloned._id = id\n\n // Remove circular references\n delete cloned.parent\n delete cloned.prev\n delete cloned.next\n delete cloned.slots\n\n if (cloned.children) {\n cloned.children = cleanAST(cloned.children, nodeMap, state)\n }\n return cloned\n })\n}\n\n/**\n * Cleans the template values object, mapping original node references to unique IDs.\n *\n * @param {Object} values - The values object to clean.\n * @param {WeakMap} nodeMap - Map of original nodes to their unique IDs.\n * @returns {Object|null} The cleaned values object.\n */\nexport function cleanValues (values, nodeMap) {\n if (!values) {\n return null\n }\n\n const result = { ...values }\n\n if (result.attributes) {\n result.attributes = result.attributes.map(item => {\n const cloned = { ...item }\n cloned.elementId = nodeMap.get(item.element)\n delete cloned.element\n return cloned\n })\n }\n\n if (result.textNodes) {\n result.textNodes = result.textNodes.map(item => {\n const cloned = { ...item }\n cloned.textNodeId = nodeMap.get(item.textNode)\n delete cloned.textNode\n return cloned\n })\n }\n\n if (result.refs) {\n result.refs = result.refs.map(item => {\n const cloned = { ...item }\n cloned.elementId = nodeMap.get(item.element)\n delete cloned.element\n return cloned\n })\n }\n return result\n}\n\n/**\n * Safely merges partial plugin updates into the main context object.\n * Deeply merges plain objects and overwrites other types (arrays, primitives, etc.).\n *\n * @param {any} current - The current state object.\n * @param {any} patch - The patch object containing updates.\n * @returns {any} The newly merged state object.\n */\nexport function mergePluginState (current, patch) {\n if (!patch || typeof patch !== 'object') {\n return current\n }\n\n const result = { ...current }\n\n for (const key of Object.keys(patch)) {\n const patchValue = patch[key]\n const currentValue = result[key]\n\n // If both are plain objects, merge them deeply\n if (\n patchValue && typeof patchValue === 'object' && !Array.isArray(patchValue) &&\n currentValue && typeof currentValue === 'object' && !Array.isArray(currentValue)\n ) {\n result[key] = mergePluginState(currentValue, patchValue)\n } else {\n // Otherwise, overwrite (Arrays, strings, numbers, etc.)\n result[key] = patchValue\n }\n }\n\n return result\n}\n\n/**\n * Creates a reactive proxy that triggers a callback on changes.\n * Supports deep reactivity via lazy proxying of nested objects.\n *\n * @param {Object} target - The object to proxy.\n * @param {Function} onChange - Callback triggered when a property is set or deleted.\n * @param {WeakMap} [proxies=new WeakMap()] - Cache for existing proxies to handle circular references and identity.\n * @returns {Proxy} The reactive proxy.\n */\nexport function createReactiveProxy (target, onChange, proxies = new WeakMap()) {\n if (proxies.has(target)) {\n return proxies.get(target)\n }\n\n const handler = {\n get (target, property, receiver) {\n const value = Reflect.get(target, property, receiver)\n if (value !== null && typeof value === 'object' && !(typeof Node !== 'undefined' && value instanceof Node)) {\n return createReactiveProxy(value, onChange, proxies)\n }\n return value\n },\n set (target, property, value, receiver) {\n const oldValue = target[property]\n if (oldValue === value && property in target) {\n return true\n }\n\n const result = Reflect.set(target, property, value, receiver)\n if (result) {\n onChange({\n property,\n value,\n oldValue,\n target\n })\n }\n return result\n },\n deleteProperty (target, property) {\n const hadProperty = Object.prototype.hasOwnProperty.call(target, property)\n const oldValue = target[property]\n const result = Reflect.deleteProperty(target, property)\n if (result && hadProperty) {\n onChange({\n property,\n value: undefined,\n oldValue,\n target,\n deleted: true\n })\n }\n return result\n }\n }\n\n const proxy = new Proxy(target, handler)\n proxies.set(target, proxy)\n return proxy\n}\n\n/**\n * Creates a read-only proxy that throws on mutation attempts.\n * @param {Object} target - The object to proxy.\n * @param {WeakMap} [proxies=new WeakMap()] - Cache for existing proxies.\n * @returns {Proxy} The read-only proxy.\n */\nexport function createReadOnlyProxy (target, proxies = new WeakMap()) {\n if (proxies.has(target)) {\n return proxies.get(target)\n }\n\n const handler = {\n get (target, property, receiver) {\n const value = Reflect.get(target, property, receiver)\n if (value !== null && typeof value === 'object' && !(typeof Node !== 'undefined' && value instanceof Node)) {\n return createReadOnlyProxy(value, proxies)\n }\n return value\n },\n set () {\n throw new CoraliteError('Cannot mutate state inside a getter. State is read-only here.')\n },\n deleteProperty () {\n throw new CoraliteError('Cannot delete state inside a getter. State is read-only here.')\n }\n }\n\n const proxy = new Proxy(target, handler)\n\n proxies.set(target, proxy)\n\n return proxy\n}\n\n/**\n * Defines a Coralite component.\n * On the client, this acts as an identity function for type safety and HRM.\n * @param {Object} options - Component options\n * @returns {Object} The component options\n */\nexport function defineComponent (options) {\n return options\n}\n", "/**\n * @import {\n * CoraliteClientPluginDisconnectedCallback,\n * CoraliteClientPluginAfterComponentRenderCallback,\n * CoraliteClientPluginBeforeComponentRenderCallback\n * } from '../types/plugin.js'\n */\n\nimport { createReadOnlyProxy } from './utils/core.js'\n\nconst BOOLEAN_ATTRIBUTES = new Set([\n 'allowfullscreen',\n 'async',\n 'autofocus',\n 'autoplay',\n 'checked',\n 'controls',\n 'default',\n 'defer',\n 'disabled',\n 'formnovalidate',\n 'hidden',\n 'inert',\n 'ismap',\n 'itemscope',\n 'loop',\n 'multiple',\n 'muted',\n 'nomodule',\n 'novalidate',\n 'open',\n 'playsinline',\n 'readonly',\n 'required',\n 'reversed',\n 'selected',\n 'truespeed'\n])\n\n/**\n * Coerces a value to a specified type.\n * Supports Number, Boolean, and String.\n * @param {any} value - The value to coerce.\n * @param {Function|string} type - The target type (Constructor or string name).\n * @returns {any} The coerced value.\n */\nexport function coerce (value, type) {\n if (value === null || value === undefined) {\n return value\n }\n if (type === Number || type === 'Number') {\n return Number(value)\n }\n if (type === Boolean || type === 'Boolean') {\n if (value === '') {\n return true\n }\n return value !== 'false' && value !== null\n }\n if (type === String || type === 'String') {\n return String(value)\n }\n return value\n}\n\n/**\n * @typedef {Object} CoraliteComponentOptions\n * @property {string} componentId - The unique identifier for the component.\n * @property {string} [templateHTML] - The raw HTML string for imperative mounting.\n * @property {Object} [defaultValues] - The initial state values extracted from the server data block.\n * @property {Object} [attributes] - Schema for coercing HTML attributes into typed primitives.\n * @property {Object.<string, Function>} [getters] - Pure functions for derived state, supporting Promises.\n * @property {Object.<string, Function>} [slots] - Transformation functions for projected Light DOM.\n * @property {Function} [client] - The client-side controller logic.\n * @property {Object} [hydrationMap] - AST mapping for reactive text nodes, attributes, and refs.\n */\n\n/**\n * Base class for all Coralite custom elements.\n *\n * @augments HTMLElement\n */\nexport class CoraliteElement extends HTMLElement {\n /**\n * Initializes a new instance of the CoraliteElement.\n * Sets up internal state trackers, binding collections, and hook registries.\n */\n constructor () {\n super()\n /**\n * Controls native teardown of event listeners and async fetches upon disconnection.\n * @type {AbortController|null}\n * @protected\n */\n this._abortController = null\n\n /**\n * A globally unique, deterministic identifier (e.g., `my-comp-0`).\n * @type {string|null}\n * @protected\n */\n this._instanceId = null\n\n /**\n * The unified, deeply reactive proxy holding attributes, data, and getters.\n * @type {Object|null}\n * @protected\n */\n this._state = null\n\n /**\n * The collection of DOM nodes mapped to template tokens and attributes.\n * @type {Array<{type: string, node: Node, template?: string, name?: string}>}\n * @protected\n */\n this._bindings = []\n\n /**\n * Flag to prevent multiple synchronous state mutations from triggering multiple DOM paints.\n * @type {boolean}\n * @protected\n */\n this._isUpdatePending = false\n\n /**\n * A unique Symbol generated per render cycle to prevent async getter race conditions.\n * @type {symbol|null}\n * @protected\n */\n this._currentRenderVersion = null\n\n /**\n * @type {MutationObserver|null}\n * @protected\n */\n this._observer = null\n\n /**\n * Hook to fetch globally registered Phase-2 plugin contexts.\n * @type {Function|null}\n * @protected\n */\n this._clientContextGetter = null\n\n /**\n * Tracks AbortControllers specifically for cancelling stale async getters.\n * @type {Object.<string, AbortController>|null}\n * @protected\n */\n this._getterAbortControllers = null\n\n /**\n * Internal lifecycle hooks injected by registered Coralite plugins.\n * @type {{\n * onBeforeComponentRender: Array<CoraliteClientPluginBeforeComponentRenderCallback>,\n * onAfterComponentRender: Array<CoraliteClientPluginAfterComponentRenderCallback>,\n * onDisconnected: Array<CoraliteClientPluginDisconnectedCallback>\n * }}\n * @protected\n */\n this._hooks = {\n onBeforeComponentRender: [],\n onAfterComponentRender: [],\n onDisconnected: []\n }\n\n /**\n * The definition and schema of the component generated by the compiler.\n * @type {CoraliteComponentOptions|null}\n */\n this.componentOptions = null\n }\n\n /**\n * Invoked natively when the element is added to the document.\n * Handles the architectural split between Declarative (SSR) and Imperative (JS) components.\n * Orchestrates template injection, instance ID generation, and state/binding setup.\n */\n connectedCallback () {\n this._abortController = new AbortController()\n\n if (!this.componentOptions) {\n return\n }\n\n // Declarative components receive a data-cid from the server.\n // Imperative components (created via document.createElement) do not.\n const isImperative = !this.hasAttribute('data-cid')\n\n // Imperative Flow: Manually stamp the template and project the Light DOM.\n if (isImperative && this.componentOptions.templateHTML) {\n const originalLightDOM = Array.from(this.childNodes)\n this.innerHTML = this.componentOptions.templateHTML\n\n if (originalLightDOM.length > 0) {\n const slots = this.querySelectorAll('slot')\n slots.forEach(slot => {\n const slotName = slot.getAttribute('name') || 'default'\n const matchingNodes = originalLightDOM.filter(node => {\n // @ts-ignore\n const nodeSlot = (node.getAttribute && node.getAttribute('slot')) || 'default'\n return nodeSlot === slotName\n })\n matchingNodes.forEach(n => slot.appendChild(n))\n })\n }\n }\n\n // Establish the Deterministic Instance ID\n if (this.hasAttribute('data-cid')) {\n this._instanceId = this.getAttribute('data-cid')\n } else {\n // Fallback counter for imperatively created components\n // @ts-ignore\n window.__coralite_instanceCounters = window.__coralite_instanceCounters || {}\n const prefix = this.componentOptions.componentId\n // @ts-ignore\n if (window.__coralite_instanceCounters[prefix] === undefined) {\n // @ts-ignore\n window.__coralite_instanceCounters[prefix] = 0\n }\n // @ts-ignore\n this._instanceId = `${prefix}-${window.__coralite_instanceCounters[prefix]++}`\n }\n\n if (isImperative) {\n this.setAttribute('data-cid', this._instanceId)\n }\n\n this._setupState()\n this._setupBindings()\n this._init(isImperative)\n }\n\n /**\n * Invoked natively when the element is removed from the document.\n * Aborts pending requests and triggers `onDisconnected` plugin hooks\n * to ensure external libraries (e.g., Observers) do not cause memory leaks.\n * @this {any}\n */\n disconnectedCallback () {\n if (this._abortController) {\n this._abortController.abort()\n }\n\n if (!this.componentOptions) {\n return\n }\n\n for (const hook of this._hooks.onDisconnected) {\n hook({\n state: this._state,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n element: this,\n options: this.componentOptions\n })\n }\n }\n\n /**\n * Invoked natively when an observed HTML attribute changes.\n * Coerces the raw string value based on the component's attribute schema\n * and synchronizes it into the reactive state proxy.\n * @param {string} name - The kebab-case name of the attribute.\n * @param {string|null} oldVal - The previous value.\n * @param {string|null} newVal - The new value.\n */\n attributeChangedCallback (name, oldVal, newVal) {\n if (!this._state || oldVal === newVal || name === 'data-cid') {\n return\n }\n const camelName = name.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n const schema = this.componentOptions.attributes?.[camelName] || this.componentOptions.attributes?.[name]\n const value = schema ? coerce(newVal, schema.type) : newVal\n\n this._state[camelName] = value\n }\n\n /**\n * Constructs the unified state object.\n * Merges `defaultValues`, JSON hydration payloads, and DOM attributes.\n * Defines getters (wrapping state in a Read-Only proxy) and applies the final Read/Write Proxy.\n * @this {any}\n * @private\n */\n _setupState () {\n const options = this.componentOptions\n const target = { ...options.defaultValues }\n\n /** @type {Array<{name: string, element: HTMLElement}>} */\n const refs = []\n if (options.hydrationMap && options.hydrationMap.refs) {\n for (const ref of options.hydrationMap.refs) {\n const uniqueRefValue = `${this._instanceId}__${ref.name}`\n\n if (!target[`ref_${ref.name}`]) {\n target[`ref_${ref.name}`] = uniqueRefValue\n }\n\n const node = this.getNodeByPath(ref.path)\n if (node) {\n if (node.setAttribute) {\n node.setAttribute('ref', uniqueRefValue)\n }\n refs.push({\n name: ref.name,\n element: node\n })\n }\n }\n }\n\n // Process initial attributes mapping\n for (const attr of this.attributes) {\n if (attr.name === 'data-cid') {\n continue\n }\n const camelName = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n const schema = options.attributes?.[camelName] || options.attributes?.[attr.name]\n target[camelName] = schema ? coerce(attr.value, schema.type) : attr.value\n }\n\n // Hydrate data() block results from the SSR JSON payload\n const hydrationTag = document.getElementById('__CORALITE_HYDRATION__')\n if (hydrationTag) {\n try {\n const allData = JSON.parse(hydrationTag.textContent)\n if (allData[this._instanceId]) {\n Object.assign(target, allData[this._instanceId])\n }\n } catch {\n console.error('Coralite Element hydration failed:', this._instanceId)\n }\n }\n\n // Trigger Before-Render hooks BEFORE state is proxied, allowing plugins to inject reactive data\n for (const hook of this._hooks.onBeforeComponentRender) {\n hook({\n state: target,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n refs,\n element: this,\n options: this.componentOptions\n })\n }\n\n\n // Define derived state getters with isolation controllers\n this._getterAbortControllers = {}\n for (const [key, getter] of Object.entries(options.getters || {})) {\n Object.defineProperty(target, key, {\n get: () => {\n if (this._getterAbortControllers[key]) {\n this._getterAbortControllers[key].abort()\n }\n this._getterAbortControllers[key] = new AbortController()\n\n // Enforce \"Dual-Proxy\" safety: Getters cannot mutate state\n const roState = createReadOnlyProxy(this._state)\n return getter(roState, { signal: this._getterAbortControllers[key].signal })\n },\n enumerable: true,\n configurable: true\n })\n }\n\n this._state = this._createReactiveProxy(target)\n }\n\n /**\n * Wraps the state target in a reactive Proxy.\n * Intercepts property setters to automatically batch and schedule DOM updates.\n * @param {Object} target - The state dictionary.\n * @returns {Proxy} The reactive state proxy.\n * @private\n */\n _createReactiveProxy (target) {\n const self = this\n return new Proxy(target, {\n set (t, p, v) {\n if (t[p] === v) {\n return true\n }\n t[p] = v\n self._scheduleUpdate()\n return true\n }\n })\n }\n\n /**\n * Traverses the DOM tree using an AST-generated path index array.\n * Allows O(1) element lookups without relying on querySelectors or classes.\n * @param {number[]} path - Array of childNode indices (e.g., `[0, 1, 2]`).\n * @returns {Node|null} The physical DOM node, or null if traversal fails.\n */\n getNodeByPath (path) {\n let node = this\n for (const index of path) {\n if (!node) {\n return null\n }\n // @ts-ignore\n node = node.childNodes[index]\n }\n return node\n }\n\n /**\n * Initializes DOM bindings based on the compiler's hydration map.\n * Caches physical DOM references to text nodes and attributes that contain template tokens.\n * @private\n */\n _setupBindings () {\n this._bindings = []\n const map = this.componentOptions.hydrationMap\n if (!map) {\n return\n }\n\n if (map.texts) {\n for (const item of map.texts) {\n const node = this.getNodeByPath(item.path)\n if (node) {\n this._bindings.push({\n type: item.type || 'text',\n node,\n template: item.template\n })\n }\n }\n }\n\n if (map.attributes) {\n for (const item of map.attributes) {\n const node = this.getNodeByPath(item.path)\n if (node) {\n this._bindings.push({\n type: 'attribute',\n node,\n name: item.name,\n template: item.template\n })\n }\n }\n }\n }\n\n /**\n * Schedules a DOM update in the next microtask queue.\n * This guarantees that multiple synchronous state mutations result in only one render pass.\n * @private\n */\n _scheduleUpdate () {\n if (this._isUpdatePending) {\n return\n }\n this._isUpdatePending = true\n queueMicrotask(() => {\n this._updateDOM()\n this._isUpdatePending = false\n })\n }\n\n /**\n * Performs the physical DOM update and resolves template tokens.\n * **Async Safety:** Implements a Symbol-based locking mechanism (`renderVersion`)\n * to guarantee that if state mutates while an async getter is pending, the stale\n * Promise will be discarded, preventing DOM race conditions.\n * @this {any}\n * @private\n */\n _updateDOM () {\n // Create a unique lock for this specific render cycle\n const renderVersion = Symbol()\n this._currentRenderVersion = renderVersion\n\n // Extract unique tokens to prevent double-reading and accidental aborts\n /** @type {Set<string>} */\n const requiredTokens = new Set()\n for (const binding of this._bindings) {\n binding.template.replace(/\\{\\{\\s*(.+?)\\s*\\}\\}/g, (_, key) => {\n requiredTokens.add(key)\n return ''\n })\n }\n\n const evaluatedTokens = {}\n let hasPromise = false\n\n // Evaluate getters exactly once per render cycle\n for (const key of requiredTokens) {\n let val = this._state[key]\n if (typeof val === 'function') {\n val = val(this._state)\n }\n evaluatedTokens[key] = val\n if (val instanceof Promise) {\n hasPromise = true\n }\n }\n\n // The DOM Mutator Function\n const applyBindings = (tokenValues) => {\n // Race Condition Lock: Abort if a newer render cycle has already begun\n if (this._currentRenderVersion !== renderVersion) {\n return\n }\n\n for (const binding of this._bindings) {\n const hydratedValue = binding.template.replace(/\\{\\{\\s*(.+?)\\s*\\}\\}/g, (_, key) => {\n return tokenValues[key] ?? ''\n })\n\n if (binding.type === 'text') {\n if (binding.node.textContent !== hydratedValue) {\n binding.node.textContent = hydratedValue\n }\n } else if (binding.type === 'html') {\n /** @type {HTMLElement} */\n // @ts-ignore\n const element = binding.node\n\n if (element.innerHTML !== hydratedValue) {\n element.innerHTML = hydratedValue\n }\n } else if (binding.type === 'attribute') {\n /** @type {HTMLElement} */\n // @ts-ignore\n const element = binding.node\n\n if (BOOLEAN_ATTRIBUTES.has(binding.name)) {\n const isFalsy = hydratedValue === '' || hydratedValue === 'false' || hydratedValue === 'null' || hydratedValue === '0' || hydratedValue === 'undefined'\n if (isFalsy) {\n element.removeAttribute(binding.name)\n } else {\n element.setAttribute(binding.name, '')\n }\n } else {\n if (element.getAttribute(binding.name) !== hydratedValue) {\n element.setAttribute(binding.name, hydratedValue)\n }\n }\n }\n }\n\n this._processSlots()\n\n // Trigger After-Render hooks ONLY after the physical DOM is stable\n for (const hook of this._hooks.onAfterComponentRender) {\n hook({\n state: this._state,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n element: this,\n options: this.componentOptions\n })\n }\n }\n\n // Await Promises or Apply Synchronously\n if (hasPromise) {\n const keys = Object.keys(evaluatedTokens)\n const promises = keys.map(k => Promise.resolve(evaluatedTokens[k]))\n\n Promise.all(promises).then(resolvedValues => {\n const resolvedMap = {}\n keys.forEach((k, i) => {\n resolvedMap[k] = resolvedValues[i]\n })\n applyBindings(resolvedMap)\n }).catch(e => {\n if (e.name !== 'AbortError') {\n console.error('Coralite Async Getter Error:', e)\n }\n })\n } else {\n applyBindings(evaluatedTokens)\n }\n }\n\n /**\n * Evaluates and projects Light DOM elements into their respective `<slot>` nodes.\n * Invokes component-specific slot transformation functions.\n * @private\n */\n _processSlots () {\n const slots = this.componentOptions.slots\n if (!slots || Object.keys(slots).length === 0) {\n return\n }\n\n const slotElements = this.querySelectorAll('slot')\n slotElements.forEach(slotEl => {\n const slotName = slotEl.getAttribute('name') || 'default'\n const slotFn = slots[slotName]\n\n if (slotFn) {\n // @ts-ignore\n if (!slotEl._originalNodes) {\n // @ts-ignore\n slotEl._originalNodes = Array.from(slotEl.childNodes).map(n => n.cloneNode(true))\n }\n\n // @ts-ignore\n const result = slotFn(slotEl._originalNodes, this._state)\n\n if (result === undefined) {\n return\n }\n\n if (result === null || result === '' || (Array.isArray(result) && result.length === 0)) {\n slotEl.innerHTML = ''\n return\n }\n\n if (typeof result === 'string') {\n slotEl.innerHTML = result\n } else if (Array.isArray(result)) {\n slotEl.replaceChildren(...result)\n }\n }\n })\n }\n\n /**\n * The final initialization pipeline.\n * Injects globally registered client plugins into the local context payload,\n * triggers the initial DOM render, and invokes the user's `script()` logic.\n * @param {boolean} [isImperative=false] - If true, initial render runs synchronously.\n * @private\n */\n async _init (isImperative = false) {\n const self = this\n /**\n * The context payload injected into the user's script block.\n * @type {Object}\n */\n let localContext = {\n instanceId: this._instanceId,\n state: this._state,\n root: this,\n signal: this._abortController.signal,\n refs (id) {\n const refId = self._state[`ref_${id}`]\n if (!refId && typeof refId !== 'string') {\n return null\n }\n return self.querySelector(`[ref=\"${refId}\"]`)\n }\n }\n\n if (typeof this._clientContextGetter === 'function') {\n localContext = await this._clientContextGetter(localContext)\n }\n\n if (isImperative) {\n this._updateDOM()\n } else {\n this._scheduleUpdate()\n }\n\n if (this.componentOptions.client) {\n try {\n this.componentOptions.client(localContext)\n } catch (error) {\n console.error(`Coralite Error: Component \"${this.componentOptions.componentId}\" script failed:`, error)\n }\n }\n }\n}\n\n/**\n * Factory function to create a Coralite element class.\n * It dynamically defines the class, including observed attributes and hook initialization.\n * @param {CoraliteComponentOptions} options - Component options and metadata.\n * @param {Function|null} [contextGetter=null] - Optional function to retrieve client-side plugin context.\n * @param {Object} [hooks={}] - Lifecycle hooks to register.\n * @param {Array<CoraliteClientPluginBeforeComponentRenderCallback>} [hooks.onBeforeComponentRender] - Hooks to run before render.\n * @param {Array<CoraliteClientPluginAfterComponentRenderCallback>} [hooks.onAfterComponentRender] - Hooks to run after render.\n * @param {Array<CoraliteClientPluginDisconnectedCallback>} [hooks.onDisconnected] - Hooks to run after render.\n * @returns {typeof CoraliteElement} A new CoraliteElement subclass.\n */\nexport function createCoraliteClass (options, contextGetter = null, hooks = {}) {\n return class extends CoraliteElement {\n /**\n * The attributes to observe for changes.\n * @returns {string[]} Array of attribute names.\n */\n static get observedAttributes () {\n if (!options.attributes) {\n return []\n }\n return Object.keys(options.attributes).map(key => key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n )\n }\n\n /**\n * Initializes the dynamic Coralite element.\n */\n constructor () {\n super()\n this.componentOptions = options\n this._clientContextGetter = contextGetter\n this._hooks = {\n onBeforeComponentRender: hooks.onBeforeComponentRender || [],\n onAfterComponentRender: hooks.onAfterComponentRender || [],\n onDisconnected: hooks.onDisconnected || []\n }\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["target"]
7
7
  }
package/dist/lib/index.js CHANGED
@@ -2154,11 +2154,39 @@ function getAST(code, locations = false) {
2154
2154
  astCache.set(cacheKey, ast);
2155
2155
  return ast;
2156
2156
  }
2157
+ function extractFromHTMLString(html, components) {
2158
+ try {
2159
+ const matches = html.matchAll(/<([a-zA-Z0-9-]+)/g);
2160
+ for (const match of matches) {
2161
+ const tag = match[1].toLowerCase();
2162
+ if (tag.includes("-")) {
2163
+ components.add(tag);
2164
+ }
2165
+ }
2166
+ } catch {
2167
+ }
2168
+ }
2157
2169
  function findAndExtractScript(code) {
2158
2170
  const ast = getAST(code, true);
2159
2171
  let result = null;
2160
2172
  const components = /* @__PURE__ */ new Set();
2173
+ const findHTMLComponents = (node) => {
2174
+ if (node.type === "Literal" && typeof node.value === "string") {
2175
+ extractFromHTMLString(node.value, components);
2176
+ } else if (node.type === "TemplateLiteral") {
2177
+ for (const element of node.quasis) {
2178
+ if (element.value && element.value.cooked) {
2179
+ extractFromHTMLString(element.value.cooked, components);
2180
+ }
2181
+ }
2182
+ }
2183
+ };
2161
2184
  walkJS(ast, {
2185
+ AssignmentExpression(node) {
2186
+ if (node.left.type === "MemberExpression" && node.left.property.type === "Identifier" && (node.left.property.name === "innerHTML" || node.left.property.name === "outerHTML")) {
2187
+ findHTMLComponents(node.right);
2188
+ }
2189
+ },
2162
2190
  CallExpression(node) {
2163
2191
  if (node.callee && node.callee.type === "MemberExpression" && node.callee.object && node.callee.object.type === "Identifier" && node.callee.object.name === "document" && node.callee.property && node.callee.property.type === "Identifier" && node.callee.property.name === "createElement") {
2164
2192
  const arg = node.arguments[0];
@@ -2168,6 +2196,12 @@ function findAndExtractScript(code) {
2168
2196
  }
2169
2197
  }
2170
2198
  }
2199
+ if (node.callee && node.callee.type === "MemberExpression" && node.callee.property && node.callee.property.type === "Identifier" && node.callee.property.name === "insertAdjacentHTML") {
2200
+ const arg = node.arguments[1];
2201
+ if (arg) {
2202
+ findHTMLComponents(arg);
2203
+ }
2204
+ }
2171
2205
  if (node.callee && node.callee.type === "Identifier" && node.callee.name === "defineComponent") {
2172
2206
  const firstArg = node.arguments[0];
2173
2207
  if (firstArg && firstArg.type === "ObjectExpression") {
@@ -2182,6 +2216,21 @@ function findAndExtractScript(code) {
2182
2216
  let source = code.slice(value.start, value.end);
2183
2217
  const replacements = [];
2184
2218
  walkJS(value, {
2219
+ AssignmentExpression(node2) {
2220
+ if (node2.left.type === "MemberExpression" && node2.left.property.type === "Identifier" && (node2.left.property.name === "innerHTML" || node2.left.property.name === "outerHTML")) {
2221
+ findHTMLComponents(node2.right);
2222
+ replacements.push({
2223
+ start: node2.right.start - value.start,
2224
+ end: node2.right.start - value.start,
2225
+ replacement: "processHTML("
2226
+ });
2227
+ replacements.push({
2228
+ start: node2.right.end - value.start,
2229
+ end: node2.right.end - value.start,
2230
+ replacement: ")"
2231
+ });
2232
+ }
2233
+ },
2185
2234
  CallExpression(node2) {
2186
2235
  if (node2.callee && node2.callee.type === "MemberExpression" && node2.callee.object && node2.callee.object.type === "Identifier" && node2.callee.object.name === "document" && node2.callee.property && node2.callee.property.type === "Identifier" && node2.callee.property.name === "createElement") {
2187
2236
  const arg = node2.arguments[0];
@@ -2196,6 +2245,22 @@ function findAndExtractScript(code) {
2196
2245
  });
2197
2246
  }
2198
2247
  }
2248
+ if (node2.callee && node2.callee.type === "MemberExpression" && node2.callee.property && node2.callee.property.type === "Identifier" && node2.callee.property.name === "insertAdjacentHTML") {
2249
+ const arg = node2.arguments[1];
2250
+ if (arg) {
2251
+ findHTMLComponents(arg);
2252
+ replacements.push({
2253
+ start: arg.start - value.start,
2254
+ end: arg.start - value.start,
2255
+ replacement: "processHTML("
2256
+ });
2257
+ replacements.push({
2258
+ start: arg.end - value.start,
2259
+ end: arg.end - value.start,
2260
+ replacement: ")"
2261
+ });
2262
+ }
2263
+ }
2199
2264
  }
2200
2265
  });
2201
2266
  replacements.sort((a, b) => b.start - a.start);
@@ -2230,7 +2295,7 @@ function findAndExtractScript(code) {
2230
2295
  }
2231
2296
  }
2232
2297
  });
2233
- if (result && components.size > 0) {
2298
+ if (result) {
2234
2299
  result.components = Array.from(components);
2235
2300
  }
2236
2301
  return result;
@@ -2284,7 +2349,21 @@ function findAndExtractImperativeComponents(code) {
2284
2349
  try {
2285
2350
  const ast = getAST(code);
2286
2351
  const components = /* @__PURE__ */ new Set();
2352
+ const findHTMLComponents = (node) => {
2353
+ if (node.type === "Literal" && typeof node.value === "string") {
2354
+ extractFromHTMLString(node.value, components);
2355
+ } else if (node.type === "TemplateLiteral") {
2356
+ for (const element of node.quasis) {
2357
+ extractFromHTMLString(element.value.cooked, components);
2358
+ }
2359
+ }
2360
+ };
2287
2361
  walkJS(ast, {
2362
+ AssignmentExpression(node) {
2363
+ if (node.left.type === "MemberExpression" && node.left.property.type === "Identifier" && (node.left.property.name === "innerHTML" || node.left.property.name === "outerHTML")) {
2364
+ findHTMLComponents(node.right);
2365
+ }
2366
+ },
2288
2367
  CallExpression(node) {
2289
2368
  if (node.callee && (node.callee.type === "MemberExpression" && node.callee.object && node.callee.object.type === "Identifier" && node.callee.object.name === "document" && node.callee.property && node.callee.property.type === "Identifier" && node.callee.property.name === "createElement" || node.callee.type === "Identifier" && node.callee.name === "createCoraliteElement")) {
2290
2369
  const arg = node.arguments[0];
@@ -2292,6 +2371,12 @@ function findAndExtractImperativeComponents(code) {
2292
2371
  components.add(arg.value);
2293
2372
  }
2294
2373
  }
2374
+ if (node.callee && node.callee.type === "MemberExpression" && node.callee.property && node.callee.property.type === "Identifier" && node.callee.property.name === "insertAdjacentHTML") {
2375
+ const arg = node.arguments[1];
2376
+ if (arg) {
2377
+ findHTMLComponents(arg);
2378
+ }
2379
+ }
2295
2380
  }
2296
2381
  });
2297
2382
  return [...components];
@@ -2541,7 +2626,7 @@ ScriptManager.prototype.compileAllInstances = async function(instances, mode) {
2541
2626
  ${contextParts}
2542
2627
  };
2543
2628
  `);
2544
- entryCodeParts.push("const globalContext = { values: {} };\n");
2629
+ entryCodeParts.push("const globalContext = {};\n");
2545
2630
  entryCodeParts.push(`const resolvedContextFactoriesPromise = (async () => {
2546
2631
  const factories = {};
2547
2632
  const keys = Object.keys(coraliteComponentClientContextProps);
@@ -2821,19 +2906,24 @@ export default {
2821
2906
  `;
2822
2907
  contents += "export const clientContextProps = {\n";
2823
2908
  if (module.context) {
2824
- const clientName = module.name;
2909
+ const clientName = module.client?.name || module.name;
2825
2910
  if (["id", "state", "page", "root", "signal"].includes(clientName)) {
2826
2911
  throw new CoraliteError(`Reserved context key '${clientName}' cannot be used in plugin context.`);
2827
2912
  }
2828
2913
  const fn = normalizeFunction(module.context);
2914
+ const clientConfig = module.client?.config || module.config || {};
2915
+ const configStr = JSON.stringify(clientConfig);
2829
2916
  contents += ` "${clientName}": async (globalContext) => {
2830
2917
  `;
2831
2918
  contents += ` const fn = ${fn};
2919
+ `;
2920
+ contents += ` const pluginConfig = ${configStr};
2832
2921
  `;
2833
2922
  contents += ` const pluginContext = new Proxy(globalContext, {
2834
2923
  get (target, prop) {
2835
2924
  if (prop === 'config') return pluginConfig;
2836
- return target[prop];
2925
+ if (prop in target) return target[prop];
2926
+ return undefined;
2837
2927
  },
2838
2928
  set (target, prop, value) {
2839
2929
  return Reflect.set(target, prop, value);
@@ -3512,6 +3602,7 @@ function createModuleLinker({ path: path2, context: context2, source, importModu
3512
3602
  }
3513
3603
  coraliteExports += "export const defineComponent = globalThis.__coralite_define_component__;\n";
3514
3604
  coraliteExports += "export const createCoraliteElement = globalThis.__coralite_create_coralite_element__;\n";
3605
+ coraliteExports += "export const processHTML = globalThis.__coralite_process_html__;\n";
3515
3606
  return new SourceTextModule(coraliteExports, {
3516
3607
  context: referencingModule.context,
3517
3608
  importModuleDynamically
@@ -3607,6 +3698,12 @@ async function evaluateDevelopment({
3607
3698
  return globalThis.createCoraliteElement(tag, options);
3608
3699
  }
3609
3700
  return globalThis.document.createElement(tag, options);
3701
+ },
3702
+ __coralite_process_html__: (html) => {
3703
+ if (typeof globalThis.processHTML === "function") {
3704
+ return globalThis.processHTML(html);
3705
+ }
3706
+ return html;
3610
3707
  }
3611
3708
  };
3612
3709
  for (const glob of usedGlobals) {
@@ -3712,14 +3809,22 @@ async function evaluateProduction({
3712
3809
  }
3713
3810
  return globalThis.document.createElement(tag, options);
3714
3811
  };
3812
+ const processHTML = (html) => {
3813
+ if (typeof globalThis.processHTML === "function") {
3814
+ return globalThis.processHTML(html);
3815
+ }
3816
+ return html;
3817
+ };
3715
3818
  return {
3716
3819
  ...symmetricalContext,
3717
3820
  defineComponent: (options) => defineComponent2(options, symmetricalContext),
3718
3821
  createCoraliteElement: createCoraliteElement2,
3822
+ processHTML,
3719
3823
  default: {
3720
3824
  ...symmetricalContext,
3721
3825
  defineComponent: (options) => defineComponent2(options, symmetricalContext),
3722
- createCoraliteElement: createCoraliteElement2
3826
+ createCoraliteElement: createCoraliteElement2,
3827
+ processHTML
3723
3828
  }
3724
3829
  };
3725
3830
  }
@@ -3923,9 +4028,15 @@ function createComponentDefinition({ app }) {
3923
4028
  ...initialState
3924
4029
  });
3925
4030
  if (serverResult) {
4031
+ if (typeof serverResult !== "object" || Array.isArray(serverResult)) {
4032
+ throw new CoraliteError(`Component "${module.id}" server() function must return an object. Received: ${Array.isArray(serverResult) ? "Array" : typeof serverResult}`, {
4033
+ componentId: module.id,
4034
+ filePath: module.path?.pathname
4035
+ });
4036
+ }
3926
4037
  state.__script__.server = serverResult;
3927
4038
  Object.assign(state, serverResult);
3928
- Object.assign(state.__script__.state, serverResult);
4039
+ Object.assign(state.__script__.defaultValues, serverResult);
3929
4040
  }
3930
4041
  }
3931
4042
  if (getters) {
@@ -4017,19 +4128,14 @@ function createComponentDefinition({ app }) {
4017
4128
  const hasAttributes = attributes && Object.keys(attributes).length > 0;
4018
4129
  const hasServer = typeof server === "function";
4019
4130
  if (hasClient || hasSlots || hasGetters || hasAttributes || hasServer) {
4020
- if (hasClient) {
4021
- const clientTextContent = client.toString().trim();
4022
- const args = {};
4023
- for (const key in state) {
4024
- if (!Object.hasOwn(state, key)) {
4025
- continue;
4026
- }
4027
- if (clientTextContent.includes(key) || key.startsWith("ref_")) {
4028
- args[key] = state.__script__.defaultValues[key] !== void 0 ? state.__script__.defaultValues[key] : state[key];
4029
- }
4131
+ const args = {};
4132
+ for (const key in state) {
4133
+ if (!Object.hasOwn(state, key) || key === "__script__") {
4134
+ continue;
4030
4135
  }
4031
- Object.assign(state.__script__.state, args);
4136
+ args[key] = state[key];
4032
4137
  }
4138
+ Object.assign(state.__script__.state, args);
4033
4139
  } else {
4034
4140
  delete state.__script__;
4035
4141
  }
@@ -4724,6 +4830,18 @@ import { getClientContext, createCoraliteClass, globalClientHooks } from '${base
4724
4830
  }
4725
4831
  return document.createElement(tag, options);
4726
4832
  };
4833
+
4834
+ window.processHTML = (html) => {
4835
+ if (typeof html !== 'string') return html;
4836
+ const matches = html.matchAll(/<([a-zA-Z0-9-]+)/g);
4837
+ for (const match of matches) {
4838
+ const tag = match[1].toLowerCase();
4839
+ if (componentManifest[tag]) {
4840
+ loadComponent(tag);
4841
+ }
4842
+ }
4843
+ return html;
4844
+ };
4727
4845
  })();
4728
4846
  `.trim();
4729
4847
  }