@coherent.js/express 1.0.0-beta.5 → 1.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -24,171 +24,11 @@ __export(index_exports, {
24
24
  setupCoherent: () => setupCoherent
25
25
  });
26
26
  module.exports = __toCommonJS(index_exports);
27
-
28
- // ../core/src/index.js
29
- var scopeCounter = { value: 0 };
30
- function generateScopeId() {
31
- return `coh-${scopeCounter.value++}`;
32
- }
33
- function scopeCSS(css, scopeId) {
34
- if (!css || typeof css !== "string") return css;
35
- return css.replace(/([^{}]*)\s*{/g, (match, selector) => {
36
- const selectors = selector.split(",").map((s) => {
37
- const trimmed = s.trim();
38
- if (!trimmed) return s;
39
- if (trimmed.includes(":")) {
40
- return trimmed.replace(/([^:]+)(:.*)?/, `$1[${scopeId}]$2`);
41
- }
42
- return `${trimmed}[${scopeId}]`;
43
- });
44
- return `${selectors.join(", ")} {`;
45
- });
46
- }
47
- function applyScopeToElement(element, scopeId) {
48
- if (typeof element === "string" || typeof element === "number" || !element) {
49
- return element;
50
- }
51
- if (Array.isArray(element)) {
52
- return element.map((item) => applyScopeToElement(item, scopeId));
53
- }
54
- if (typeof element === "object") {
55
- const scoped = {};
56
- for (const [tagName, props] of Object.entries(element)) {
57
- if (typeof props === "object" && props !== null) {
58
- const scopedProps = { ...props };
59
- scopedProps[scopeId] = "";
60
- if (scopedProps.children) {
61
- scopedProps.children = applyScopeToElement(scopedProps.children, scopeId);
62
- }
63
- scoped[tagName] = scopedProps;
64
- } else {
65
- scoped[tagName] = props;
66
- }
67
- }
68
- return scoped;
69
- }
70
- return element;
71
- }
72
- function escapeHtml(text) {
73
- if (typeof text !== "string") return text;
74
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
75
- }
76
- function isTrustedContent(value) {
77
- return value && typeof value === "object" && value.__trusted === true && typeof value.__html === "string";
78
- }
79
- function isVoidElement(tagName) {
80
- const voidElements = /* @__PURE__ */ new Set([
81
- "area",
82
- "base",
83
- "br",
84
- "col",
85
- "embed",
86
- "hr",
87
- "img",
88
- "input",
89
- "link",
90
- "meta",
91
- "param",
92
- "source",
93
- "track",
94
- "wbr"
95
- ]);
96
- return voidElements.has(tagName.toLowerCase());
97
- }
98
- function formatAttributes(attrs) {
99
- if (!attrs || typeof attrs !== "object") return "";
100
- return Object.entries(attrs).filter(([, value]) => value !== null && value !== void 0 && value !== false).map(([key, value]) => {
101
- if (typeof value === "function") {
102
- value = value();
103
- }
104
- const attrName = key === "className" ? "class" : key;
105
- if (value === true) return attrName;
106
- return `${attrName}="${escapeHtml(String(value))}"`;
107
- }).join(" ");
108
- }
109
- function renderRaw(obj) {
110
- if (obj === null || obj === void 0) return "";
111
- if (typeof obj === "string" || typeof obj === "number") return escapeHtml(String(obj));
112
- if (Array.isArray(obj)) return obj.map(renderRaw).join("");
113
- if (typeof obj === "function") {
114
- const result = obj(renderRaw);
115
- return renderRaw(result);
116
- }
117
- if (typeof obj !== "object") return escapeHtml(String(obj));
118
- if (obj.text !== void 0) {
119
- return escapeHtml(String(obj.text));
120
- }
121
- for (const [tagName, props] of Object.entries(obj)) {
122
- if (typeof props === "object" && props !== null) {
123
- const { children, text, ...attributes } = props;
124
- const attrsStr = formatAttributes(attributes);
125
- const openTag = attrsStr ? `<${tagName} ${attrsStr}>` : `<${tagName}>`;
126
- if (isVoidElement(tagName)) {
127
- return openTag.replace(">", " />");
128
- }
129
- let content = "";
130
- if (text !== void 0) {
131
- if (isTrustedContent(text)) {
132
- content = text.__html;
133
- } else {
134
- content = escapeHtml(String(text));
135
- }
136
- } else if (children) {
137
- content = renderRaw(children);
138
- }
139
- return `${openTag}${content}</${tagName}>`;
140
- } else if (typeof props === "string") {
141
- const content = isTrustedContent(props) ? props.__html : escapeHtml(props);
142
- return isVoidElement(tagName) ? `<${tagName} />` : `<${tagName}>${content}</${tagName}>`;
143
- }
144
- }
145
- return "";
146
- }
147
- function render(obj, options = {}) {
148
- const { scoped = false } = options;
149
- if (scoped) {
150
- return renderScopedComponent(obj);
151
- }
152
- return renderRaw(obj);
153
- }
154
- function renderScopedComponent(component) {
155
- const scopeId = generateScopeId();
156
- function processScopedElement(element) {
157
- if (!element || typeof element !== "object") {
158
- return element;
159
- }
160
- if (Array.isArray(element)) {
161
- return element.map(processScopedElement);
162
- }
163
- const result = {};
164
- for (const [tagName, props] of Object.entries(element)) {
165
- if (tagName === "style" && typeof props === "object" && props.text) {
166
- result[tagName] = {
167
- ...props,
168
- text: scopeCSS(props.text, scopeId)
169
- };
170
- } else if (typeof props === "object" && props !== null) {
171
- const scopedProps = { ...props };
172
- if (scopedProps.children) {
173
- scopedProps.children = processScopedElement(scopedProps.children);
174
- }
175
- result[tagName] = scopedProps;
176
- } else {
177
- result[tagName] = props;
178
- }
179
- }
180
- return result;
181
- }
182
- const processedComponent = processScopedElement(component);
183
- const scopedComponent = applyScopeToElement(processedComponent, scopeId);
184
- return renderRaw(scopedComponent);
185
- }
186
-
187
- // src/index.js
27
+ var import_core = require("@coherent.js/core");
188
28
  function expressEngine() {
189
29
  return (filePath, options, callback) => {
190
30
  try {
191
- const html = render(options);
31
+ const html = (0, import_core.render)(options);
192
32
  callback(null, html);
193
33
  } catch (_error) {
194
34
  callback(_error);
@@ -204,12 +44,4 @@ function setupCoherent(app) {
204
44
  expressEngine,
205
45
  setupCoherent
206
46
  });
207
- /**
208
- * Coherent.js - Object-Based Rendering Framework
209
- * A pure JavaScript framework for server-side rendering using natural object syntax
210
- *
211
- * @version 2.0.0
212
- * @author Coherent Framework Team
213
- * @license MIT
214
- */
215
47
  //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.js", "../../core/src/index.js"],
4
- "sourcesContent": ["// src/express/index.js\nimport { render } from '../../core/src/index.js';\n\nexport function expressEngine() {\n return (filePath, options, callback) => {\n try {\n // options contains the Coherent object structure\n const html = render(options);\n callback(null, html);\n } catch (_error) {\n callback(_error);\n }\n };\n}\n\n// Helper for Express apps\nexport function setupCoherent(app) {\n app.engine('coherent', expressEngine());\n app.set('view engine', 'coherent');\n}\n", "/**\n * Coherent.js - Object-Based Rendering Framework\n * A pure JavaScript framework for server-side rendering using natural object syntax\n *\n * @version 2.0.0\n * @author Coherent Framework Team\n * @license MIT\n */\n\n// Performance monitoring\nimport { performanceMonitor } from './performance/monitor.js';\n\n// Component system imports\nimport {\n withState,\n withStateUtils,\n createStateManager,\n createComponent,\n defineComponent,\n registerComponent,\n getComponent,\n getRegisteredComponents,\n lazy,\n isLazy,\n evaluateLazy\n} from './components/component-system.js';\n\n// Component lifecycle imports\nimport {\n ComponentLifecycle,\n LIFECYCLE_PHASES,\n withLifecycle,\n createLifecycleHooks,\n useHooks,\n componentUtils as lifecycleUtils\n} from './components/lifecycle.js';\n\n// Object factory imports\nimport {\n createElement,\n createTextNode,\n h\n} from './core/object-factory.js';\n\n// Component cache imports\nimport {\n ComponentCache,\n createComponentCache,\n memoize\n} from './performance/component-cache.js';\n\n// Error boundary imports\nimport {\n createErrorBoundary,\n createErrorFallback,\n withErrorBoundary,\n createAsyncErrorBoundary,\n GlobalErrorHandler,\n createGlobalErrorHandler\n} from './components/error-boundary.js';\n\n// CSS Scoping System (similar to Angular View Encapsulation)\nconst scopeCounter = { value: 0 };\n\nfunction generateScopeId() {\n return `coh-${scopeCounter.value++}`;\n}\n\nfunction scopeCSS(css, scopeId) {\n if (!css || typeof css !== 'string') return css;\n\n // Add scope attribute to all selectors\n return css\n .replace(/([^{}]*)\\s*{/g, (match, selector) => {\n // Handle multiple selectors separated by commas\n const selectors = selector.split(',').map(s => {\n const trimmed = s.trim();\n if (!trimmed) return s;\n\n // Handle pseudo-selectors and complex selectors\n if (trimmed.includes(':')) {\n return trimmed.replace(/([^:]+)(:.*)?/, `$1[${scopeId}]$2`);\n }\n\n // Simple selector scoping\n return `${trimmed}[${scopeId}]`;\n });\n\n return `${selectors.join(', ')} {`;\n });\n}\n\nfunction applyScopeToElement(element, scopeId) {\n if (typeof element === 'string' || typeof element === 'number' || !element) {\n return element;\n }\n\n if (Array.isArray(element)) {\n return element.map(item => applyScopeToElement(item, scopeId));\n }\n\n if (typeof element === 'object') {\n const scoped = {};\n\n for (const [tagName, props] of Object.entries(element)) {\n if (typeof props === 'object' && props !== null) {\n const scopedProps = { ...props };\n\n // Add scope attribute to the element\n scopedProps[scopeId] = '';\n\n // Recursively scope children\n if (scopedProps.children) {\n scopedProps.children = applyScopeToElement(scopedProps.children, scopeId);\n }\n\n scoped[tagName] = scopedProps;\n } else {\n // For simple text content elements, keep them as is\n // Don't add scope attributes to text-only elements\n scoped[tagName] = props;\n }\n }\n\n return scoped;\n }\n\n return element;\n}\n\n// Core HTML utilities\nfunction escapeHtml(text) {\n if (typeof text !== 'string') return text;\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#x27;');\n}\n\n/**\n * Mark content as safe/trusted to skip HTML escaping\n * USE WITH EXTREME CAUTION - only for developer-controlled content\n * NEVER use with user input!\n *\n * @param {string} content - Trusted content (e.g., inline scripts/styles)\n * @returns {Object} Marked safe content\n */\nexport function dangerouslySetInnerContent(content) {\n return {\n __html: content,\n __trusted: true\n };\n}\n\n/**\n * Check if content is marked as safe\n */\nfunction isTrustedContent(value) {\n return value && typeof value === 'object' && value.__trusted === true && typeof value.__html === 'string';\n}\n\nfunction isVoidElement(tagName) {\n const voidElements = new Set([\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\n ]);\n return voidElements.has(tagName.toLowerCase());\n}\n\nfunction formatAttributes(attrs) {\n if (!attrs || typeof attrs !== 'object') return '';\n\n return Object.entries(attrs)\n .filter(([, value]) => value !== null && value !== undefined && value !== false)\n .map(([key, value]) => {\n // Execute functions to get the actual value\n if (typeof value === 'function') {\n value = value();\n }\n\n // Convert className to class\n const attrName = key === 'className' ? 'class' : key;\n if (value === true) return attrName;\n return `${attrName}=\"${escapeHtml(String(value))}\"`;\n })\n .join(' ');\n}\n\n// Internal raw rendering (no encapsulation) - used by scoped renderer\nfunction renderRaw(obj) {\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string' || typeof obj === 'number') return escapeHtml(String(obj));\n if (Array.isArray(obj)) return obj.map(renderRaw).join('');\n\n // Handle functions (like context providers)\n if (typeof obj === 'function') {\n const result = obj(renderRaw);\n return renderRaw(result);\n }\n\n if (typeof obj !== 'object') return escapeHtml(String(obj));\n\n // Handle text content\n if (obj.text !== undefined) {\n return escapeHtml(String(obj.text));\n }\n\n // Handle HTML elements\n for (const [tagName, props] of Object.entries(obj)) {\n if (typeof props === 'object' && props !== null) {\n const { children, text, ...attributes } = props;\n const attrsStr = formatAttributes(attributes);\n const openTag = attrsStr ? `<${tagName} ${attrsStr}>` : `<${tagName}>`;\n\n if (isVoidElement(tagName)) {\n return openTag.replace('>', ' />');\n }\n\n let content = '';\n if (text !== undefined) {\n // Check if content is explicitly marked as trusted\n if (isTrustedContent(text)) {\n content = text.__html;\n } else {\n content = escapeHtml(String(text));\n }\n } else if (children) {\n content = renderRaw(children);\n }\n\n return `${openTag}${content}</${tagName}>`;\n } else if (typeof props === 'string') {\n // Simple text content - always escape unless explicitly marked as trusted\n const content = isTrustedContent(props) ? props.__html : escapeHtml(props);\n return isVoidElement(tagName) ? `<${tagName} />` : `<${tagName}>${content}</${tagName}>`;\n }\n }\n\n return '';\n}\n\n// Main rendering function\nexport function render(obj, options = {}) {\n const { scoped = false } = options;\n\n // Scoped mode - use CSS encapsulation\n if (scoped) {\n return renderScopedComponent(obj);\n }\n\n // Default: unscoped rendering\n return renderRaw(obj);\n}\n\n// Internal: Scoped rendering with CSS encapsulation\nfunction renderScopedComponent(component) {\n const scopeId = generateScopeId();\n\n // Handle style elements specially\n function processScopedElement(element) {\n if (!element || typeof element !== 'object') {\n return element;\n }\n\n if (Array.isArray(element)) {\n return element.map(processScopedElement);\n }\n\n const result = {};\n\n for (const [tagName, props] of Object.entries(element)) {\n if (tagName === 'style' && typeof props === 'object' && props.text) {\n // Scope CSS within style tags\n result[tagName] = {\n ...props,\n text: scopeCSS(props.text, scopeId)\n };\n } else if (typeof props === 'object' && props !== null) {\n // Recursively process children\n const scopedProps = { ...props };\n if (scopedProps.children) {\n scopedProps.children = processScopedElement(scopedProps.children);\n }\n result[tagName] = scopedProps;\n } else {\n result[tagName] = props;\n }\n }\n\n return result;\n }\n\n // First process styles, then apply scope attributes\n const processedComponent = processScopedElement(component);\n const scopedComponent = applyScopeToElement(processedComponent, scopeId);\n\n return renderRaw(scopedComponent);\n}\n\n// Component system - Re-export from component-system for unified API\nexport {\n withState,\n withStateUtils,\n createStateManager,\n createComponent,\n defineComponent,\n registerComponent,\n getComponent,\n getRegisteredComponents,\n lazy,\n isLazy,\n evaluateLazy\n} from './components/component-system.js';\n\n// Component lifecycle exports\nexport {\n ComponentLifecycle,\n LIFECYCLE_PHASES,\n withLifecycle,\n createLifecycleHooks,\n useHooks,\n componentUtils as lifecycleUtils\n} from './components/lifecycle.js';\n\n// Object factory exports\nexport {\n createElement,\n createTextNode,\n h\n} from './core/object-factory.js';\n\n// Component cache exports\nexport {\n ComponentCache,\n createComponentCache,\n memoize\n} from './performance/component-cache.js';\n\n// Error boundaries\nexport {\n createErrorBoundary,\n createErrorFallback,\n withErrorBoundary,\n createAsyncErrorBoundary,\n GlobalErrorHandler,\n createGlobalErrorHandler\n} from './components/error-boundary.js';\n\n// Simple memoization\nconst memoCache = new Map();\n\nexport function memo(component, keyGenerator) {\n return function MemoizedComponent(props = {}) {\n const key = keyGenerator ? keyGenerator(props) : JSON.stringify(props);\n\n if (memoCache.has(key)) {\n return memoCache.get(key);\n }\n\n const result = component(props);\n memoCache.set(key, result);\n\n // Simple cache cleanup - keep only last 100 items\n if (memoCache.size > 100) {\n const firstKey = memoCache.keys().next().value;\n memoCache.delete(firstKey);\n }\n\n return result;\n };\n}\n\n// Utility functions\nexport function validateComponent(obj) {\n if (!obj || typeof obj !== 'object') {\n throw new Error('Component must be an object');\n }\n return true;\n}\n\nexport function isCoherentObject(obj) {\n return obj && typeof obj === 'object' && !Array.isArray(obj);\n}\n\nexport function deepClone(obj) {\n if (obj === null || typeof obj !== 'object') return obj;\n if (obj instanceof Date) return new Date(obj);\n if (Array.isArray(obj)) return obj.map(deepClone);\n\n const cloned = {};\n for (const [key, value] of Object.entries(obj)) {\n cloned[key] = deepClone(value);\n }\n return cloned;\n}\n\n// Version info\nexport const VERSION = '2.0.0';\n\n// Performance monitoring export\nexport { performanceMonitor };\n\n// Shadow DOM exports\nexport { shadowDOM };\n\n// Import Shadow DOM functionality\nimport * as shadowDOM from './shadow-dom.js';\n\n// Event system imports and exports\nimport eventSystemDefault, {\n EventBus,\n createEventBus,\n globalEventBus,\n emit,\n emitSync,\n on,\n once,\n off,\n registerAction,\n handleAction,\n DOMEventIntegration,\n globalDOMIntegration,\n initializeDOMIntegration,\n withEventBus,\n withEventState,\n createActionHandlers,\n createEventHandlers,\n createEventComponent\n} from './events/index.js';\n\nexport {\n eventSystemDefault as eventSystem,\n EventBus,\n createEventBus,\n globalEventBus,\n emit,\n emitSync,\n on,\n once,\n off,\n registerAction,\n handleAction,\n DOMEventIntegration,\n globalDOMIntegration,\n initializeDOMIntegration,\n withEventBus,\n withEventState,\n createActionHandlers,\n createEventHandlers,\n createEventComponent\n};\n\n// Note: Forms have been moved to @coherent.js/forms package\n\n// Default export\nconst coherent = {\n // Core rendering\n render,\n\n // Shadow DOM (client-side only)\n shadowDOM,\n\n // Component system\n createComponent,\n defineComponent,\n registerComponent,\n getComponent,\n getRegisteredComponents,\n lazy,\n isLazy,\n evaluateLazy,\n\n // Component lifecycle\n ComponentLifecycle,\n LIFECYCLE_PHASES,\n withLifecycle,\n createLifecycleHooks,\n useHooks,\n lifecycleUtils,\n\n // Object factory\n createElement,\n createTextNode,\n h,\n\n // Component cache\n ComponentCache,\n createComponentCache,\n memoize,\n\n // State management\n withState,\n withStateUtils,\n createStateManager,\n memo,\n\n // Error boundaries\n createErrorBoundary,\n createErrorFallback,\n withErrorBoundary,\n createAsyncErrorBoundary,\n GlobalErrorHandler,\n createGlobalErrorHandler,\n\n // Event system\n eventSystem: eventSystemDefault,\n emit,\n emitSync,\n on,\n once,\n off,\n registerAction,\n handleAction,\n withEventBus,\n withEventState,\n\n // Utilities\n validateComponent,\n isCoherentObject,\n deepClone,\n escapeHtml,\n performanceMonitor,\n VERSION\n};\n\nexport default coherent;\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/index.js"],
4
+ "sourcesContent": ["// src/express/index.js\nimport { render } from '@coherent.js/core';\n\nexport function expressEngine() {\n return (filePath, options, callback) => {\n try {\n // options contains the Coherent object structure\n const html = render(options);\n callback(null, html);\n } catch (_error) {\n callback(_error);\n }\n };\n}\n\n// Helper for Express apps\nexport function setupCoherent(app) {\n app.engine('coherent', expressEngine());\n app.set('view engine', 'coherent');\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAuB;AAEhB,SAAS,gBAAgB;AAC5B,SAAO,CAAC,UAAU,SAAS,aAAa;AACpC,QAAI;AAEA,YAAM,WAAO,oBAAO,OAAO;AAC3B,eAAS,MAAM,IAAI;AAAA,IACvB,SAAS,QAAQ;AACb,eAAS,MAAM;AAAA,IACnB;AAAA,EACJ;AACJ;AAGO,SAAS,cAAc,KAAK;AAC/B,MAAI,OAAO,YAAY,cAAc,CAAC;AACtC,MAAI,IAAI,eAAe,UAAU;AACrC;",
6
6
  "names": []
7
7
  }
package/dist/index.js CHANGED
@@ -1,163 +1,5 @@
1
- // ../core/src/index.js
2
- var scopeCounter = { value: 0 };
3
- function generateScopeId() {
4
- return `coh-${scopeCounter.value++}`;
5
- }
6
- function scopeCSS(css, scopeId) {
7
- if (!css || typeof css !== "string") return css;
8
- return css.replace(/([^{}]*)\s*{/g, (match, selector) => {
9
- const selectors = selector.split(",").map((s) => {
10
- const trimmed = s.trim();
11
- if (!trimmed) return s;
12
- if (trimmed.includes(":")) {
13
- return trimmed.replace(/([^:]+)(:.*)?/, `$1[${scopeId}]$2`);
14
- }
15
- return `${trimmed}[${scopeId}]`;
16
- });
17
- return `${selectors.join(", ")} {`;
18
- });
19
- }
20
- function applyScopeToElement(element, scopeId) {
21
- if (typeof element === "string" || typeof element === "number" || !element) {
22
- return element;
23
- }
24
- if (Array.isArray(element)) {
25
- return element.map((item) => applyScopeToElement(item, scopeId));
26
- }
27
- if (typeof element === "object") {
28
- const scoped = {};
29
- for (const [tagName, props] of Object.entries(element)) {
30
- if (typeof props === "object" && props !== null) {
31
- const scopedProps = { ...props };
32
- scopedProps[scopeId] = "";
33
- if (scopedProps.children) {
34
- scopedProps.children = applyScopeToElement(scopedProps.children, scopeId);
35
- }
36
- scoped[tagName] = scopedProps;
37
- } else {
38
- scoped[tagName] = props;
39
- }
40
- }
41
- return scoped;
42
- }
43
- return element;
44
- }
45
- function escapeHtml(text) {
46
- if (typeof text !== "string") return text;
47
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
48
- }
49
- function isTrustedContent(value) {
50
- return value && typeof value === "object" && value.__trusted === true && typeof value.__html === "string";
51
- }
52
- function isVoidElement(tagName) {
53
- const voidElements = /* @__PURE__ */ new Set([
54
- "area",
55
- "base",
56
- "br",
57
- "col",
58
- "embed",
59
- "hr",
60
- "img",
61
- "input",
62
- "link",
63
- "meta",
64
- "param",
65
- "source",
66
- "track",
67
- "wbr"
68
- ]);
69
- return voidElements.has(tagName.toLowerCase());
70
- }
71
- function formatAttributes(attrs) {
72
- if (!attrs || typeof attrs !== "object") return "";
73
- return Object.entries(attrs).filter(([, value]) => value !== null && value !== void 0 && value !== false).map(([key, value]) => {
74
- if (typeof value === "function") {
75
- value = value();
76
- }
77
- const attrName = key === "className" ? "class" : key;
78
- if (value === true) return attrName;
79
- return `${attrName}="${escapeHtml(String(value))}"`;
80
- }).join(" ");
81
- }
82
- function renderRaw(obj) {
83
- if (obj === null || obj === void 0) return "";
84
- if (typeof obj === "string" || typeof obj === "number") return escapeHtml(String(obj));
85
- if (Array.isArray(obj)) return obj.map(renderRaw).join("");
86
- if (typeof obj === "function") {
87
- const result = obj(renderRaw);
88
- return renderRaw(result);
89
- }
90
- if (typeof obj !== "object") return escapeHtml(String(obj));
91
- if (obj.text !== void 0) {
92
- return escapeHtml(String(obj.text));
93
- }
94
- for (const [tagName, props] of Object.entries(obj)) {
95
- if (typeof props === "object" && props !== null) {
96
- const { children, text, ...attributes } = props;
97
- const attrsStr = formatAttributes(attributes);
98
- const openTag = attrsStr ? `<${tagName} ${attrsStr}>` : `<${tagName}>`;
99
- if (isVoidElement(tagName)) {
100
- return openTag.replace(">", " />");
101
- }
102
- let content = "";
103
- if (text !== void 0) {
104
- if (isTrustedContent(text)) {
105
- content = text.__html;
106
- } else {
107
- content = escapeHtml(String(text));
108
- }
109
- } else if (children) {
110
- content = renderRaw(children);
111
- }
112
- return `${openTag}${content}</${tagName}>`;
113
- } else if (typeof props === "string") {
114
- const content = isTrustedContent(props) ? props.__html : escapeHtml(props);
115
- return isVoidElement(tagName) ? `<${tagName} />` : `<${tagName}>${content}</${tagName}>`;
116
- }
117
- }
118
- return "";
119
- }
120
- function render(obj, options = {}) {
121
- const { scoped = false } = options;
122
- if (scoped) {
123
- return renderScopedComponent(obj);
124
- }
125
- return renderRaw(obj);
126
- }
127
- function renderScopedComponent(component) {
128
- const scopeId = generateScopeId();
129
- function processScopedElement(element) {
130
- if (!element || typeof element !== "object") {
131
- return element;
132
- }
133
- if (Array.isArray(element)) {
134
- return element.map(processScopedElement);
135
- }
136
- const result = {};
137
- for (const [tagName, props] of Object.entries(element)) {
138
- if (tagName === "style" && typeof props === "object" && props.text) {
139
- result[tagName] = {
140
- ...props,
141
- text: scopeCSS(props.text, scopeId)
142
- };
143
- } else if (typeof props === "object" && props !== null) {
144
- const scopedProps = { ...props };
145
- if (scopedProps.children) {
146
- scopedProps.children = processScopedElement(scopedProps.children);
147
- }
148
- result[tagName] = scopedProps;
149
- } else {
150
- result[tagName] = props;
151
- }
152
- }
153
- return result;
154
- }
155
- const processedComponent = processScopedElement(component);
156
- const scopedComponent = applyScopeToElement(processedComponent, scopeId);
157
- return renderRaw(scopedComponent);
158
- }
159
-
160
1
  // src/index.js
2
+ import { render } from "@coherent.js/core";
161
3
  function expressEngine() {
162
4
  return (filePath, options, callback) => {
163
5
  try {
@@ -176,12 +18,4 @@ export {
176
18
  expressEngine,
177
19
  setupCoherent
178
20
  };
179
- /**
180
- * Coherent.js - Object-Based Rendering Framework
181
- * A pure JavaScript framework for server-side rendering using natural object syntax
182
- *
183
- * @version 2.0.0
184
- * @author Coherent Framework Team
185
- * @license MIT
186
- */
187
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../core/src/index.js", "../src/index.js"],
4
- "sourcesContent": ["/**\n * Coherent.js - Object-Based Rendering Framework\n * A pure JavaScript framework for server-side rendering using natural object syntax\n *\n * @version 2.0.0\n * @author Coherent Framework Team\n * @license MIT\n */\n\n// Performance monitoring\nimport { performanceMonitor } from './performance/monitor.js';\n\n// Component system imports\nimport {\n withState,\n withStateUtils,\n createStateManager,\n createComponent,\n defineComponent,\n registerComponent,\n getComponent,\n getRegisteredComponents,\n lazy,\n isLazy,\n evaluateLazy\n} from './components/component-system.js';\n\n// Component lifecycle imports\nimport {\n ComponentLifecycle,\n LIFECYCLE_PHASES,\n withLifecycle,\n createLifecycleHooks,\n useHooks,\n componentUtils as lifecycleUtils\n} from './components/lifecycle.js';\n\n// Object factory imports\nimport {\n createElement,\n createTextNode,\n h\n} from './core/object-factory.js';\n\n// Component cache imports\nimport {\n ComponentCache,\n createComponentCache,\n memoize\n} from './performance/component-cache.js';\n\n// Error boundary imports\nimport {\n createErrorBoundary,\n createErrorFallback,\n withErrorBoundary,\n createAsyncErrorBoundary,\n GlobalErrorHandler,\n createGlobalErrorHandler\n} from './components/error-boundary.js';\n\n// CSS Scoping System (similar to Angular View Encapsulation)\nconst scopeCounter = { value: 0 };\n\nfunction generateScopeId() {\n return `coh-${scopeCounter.value++}`;\n}\n\nfunction scopeCSS(css, scopeId) {\n if (!css || typeof css !== 'string') return css;\n\n // Add scope attribute to all selectors\n return css\n .replace(/([^{}]*)\\s*{/g, (match, selector) => {\n // Handle multiple selectors separated by commas\n const selectors = selector.split(',').map(s => {\n const trimmed = s.trim();\n if (!trimmed) return s;\n\n // Handle pseudo-selectors and complex selectors\n if (trimmed.includes(':')) {\n return trimmed.replace(/([^:]+)(:.*)?/, `$1[${scopeId}]$2`);\n }\n\n // Simple selector scoping\n return `${trimmed}[${scopeId}]`;\n });\n\n return `${selectors.join(', ')} {`;\n });\n}\n\nfunction applyScopeToElement(element, scopeId) {\n if (typeof element === 'string' || typeof element === 'number' || !element) {\n return element;\n }\n\n if (Array.isArray(element)) {\n return element.map(item => applyScopeToElement(item, scopeId));\n }\n\n if (typeof element === 'object') {\n const scoped = {};\n\n for (const [tagName, props] of Object.entries(element)) {\n if (typeof props === 'object' && props !== null) {\n const scopedProps = { ...props };\n\n // Add scope attribute to the element\n scopedProps[scopeId] = '';\n\n // Recursively scope children\n if (scopedProps.children) {\n scopedProps.children = applyScopeToElement(scopedProps.children, scopeId);\n }\n\n scoped[tagName] = scopedProps;\n } else {\n // For simple text content elements, keep them as is\n // Don't add scope attributes to text-only elements\n scoped[tagName] = props;\n }\n }\n\n return scoped;\n }\n\n return element;\n}\n\n// Core HTML utilities\nfunction escapeHtml(text) {\n if (typeof text !== 'string') return text;\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#x27;');\n}\n\n/**\n * Mark content as safe/trusted to skip HTML escaping\n * USE WITH EXTREME CAUTION - only for developer-controlled content\n * NEVER use with user input!\n *\n * @param {string} content - Trusted content (e.g., inline scripts/styles)\n * @returns {Object} Marked safe content\n */\nexport function dangerouslySetInnerContent(content) {\n return {\n __html: content,\n __trusted: true\n };\n}\n\n/**\n * Check if content is marked as safe\n */\nfunction isTrustedContent(value) {\n return value && typeof value === 'object' && value.__trusted === true && typeof value.__html === 'string';\n}\n\nfunction isVoidElement(tagName) {\n const voidElements = new Set([\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\n ]);\n return voidElements.has(tagName.toLowerCase());\n}\n\nfunction formatAttributes(attrs) {\n if (!attrs || typeof attrs !== 'object') return '';\n\n return Object.entries(attrs)\n .filter(([, value]) => value !== null && value !== undefined && value !== false)\n .map(([key, value]) => {\n // Execute functions to get the actual value\n if (typeof value === 'function') {\n value = value();\n }\n\n // Convert className to class\n const attrName = key === 'className' ? 'class' : key;\n if (value === true) return attrName;\n return `${attrName}=\"${escapeHtml(String(value))}\"`;\n })\n .join(' ');\n}\n\n// Internal raw rendering (no encapsulation) - used by scoped renderer\nfunction renderRaw(obj) {\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string' || typeof obj === 'number') return escapeHtml(String(obj));\n if (Array.isArray(obj)) return obj.map(renderRaw).join('');\n\n // Handle functions (like context providers)\n if (typeof obj === 'function') {\n const result = obj(renderRaw);\n return renderRaw(result);\n }\n\n if (typeof obj !== 'object') return escapeHtml(String(obj));\n\n // Handle text content\n if (obj.text !== undefined) {\n return escapeHtml(String(obj.text));\n }\n\n // Handle HTML elements\n for (const [tagName, props] of Object.entries(obj)) {\n if (typeof props === 'object' && props !== null) {\n const { children, text, ...attributes } = props;\n const attrsStr = formatAttributes(attributes);\n const openTag = attrsStr ? `<${tagName} ${attrsStr}>` : `<${tagName}>`;\n\n if (isVoidElement(tagName)) {\n return openTag.replace('>', ' />');\n }\n\n let content = '';\n if (text !== undefined) {\n // Check if content is explicitly marked as trusted\n if (isTrustedContent(text)) {\n content = text.__html;\n } else {\n content = escapeHtml(String(text));\n }\n } else if (children) {\n content = renderRaw(children);\n }\n\n return `${openTag}${content}</${tagName}>`;\n } else if (typeof props === 'string') {\n // Simple text content - always escape unless explicitly marked as trusted\n const content = isTrustedContent(props) ? props.__html : escapeHtml(props);\n return isVoidElement(tagName) ? `<${tagName} />` : `<${tagName}>${content}</${tagName}>`;\n }\n }\n\n return '';\n}\n\n// Main rendering function\nexport function render(obj, options = {}) {\n const { scoped = false } = options;\n\n // Scoped mode - use CSS encapsulation\n if (scoped) {\n return renderScopedComponent(obj);\n }\n\n // Default: unscoped rendering\n return renderRaw(obj);\n}\n\n// Internal: Scoped rendering with CSS encapsulation\nfunction renderScopedComponent(component) {\n const scopeId = generateScopeId();\n\n // Handle style elements specially\n function processScopedElement(element) {\n if (!element || typeof element !== 'object') {\n return element;\n }\n\n if (Array.isArray(element)) {\n return element.map(processScopedElement);\n }\n\n const result = {};\n\n for (const [tagName, props] of Object.entries(element)) {\n if (tagName === 'style' && typeof props === 'object' && props.text) {\n // Scope CSS within style tags\n result[tagName] = {\n ...props,\n text: scopeCSS(props.text, scopeId)\n };\n } else if (typeof props === 'object' && props !== null) {\n // Recursively process children\n const scopedProps = { ...props };\n if (scopedProps.children) {\n scopedProps.children = processScopedElement(scopedProps.children);\n }\n result[tagName] = scopedProps;\n } else {\n result[tagName] = props;\n }\n }\n\n return result;\n }\n\n // First process styles, then apply scope attributes\n const processedComponent = processScopedElement(component);\n const scopedComponent = applyScopeToElement(processedComponent, scopeId);\n\n return renderRaw(scopedComponent);\n}\n\n// Component system - Re-export from component-system for unified API\nexport {\n withState,\n withStateUtils,\n createStateManager,\n createComponent,\n defineComponent,\n registerComponent,\n getComponent,\n getRegisteredComponents,\n lazy,\n isLazy,\n evaluateLazy\n} from './components/component-system.js';\n\n// Component lifecycle exports\nexport {\n ComponentLifecycle,\n LIFECYCLE_PHASES,\n withLifecycle,\n createLifecycleHooks,\n useHooks,\n componentUtils as lifecycleUtils\n} from './components/lifecycle.js';\n\n// Object factory exports\nexport {\n createElement,\n createTextNode,\n h\n} from './core/object-factory.js';\n\n// Component cache exports\nexport {\n ComponentCache,\n createComponentCache,\n memoize\n} from './performance/component-cache.js';\n\n// Error boundaries\nexport {\n createErrorBoundary,\n createErrorFallback,\n withErrorBoundary,\n createAsyncErrorBoundary,\n GlobalErrorHandler,\n createGlobalErrorHandler\n} from './components/error-boundary.js';\n\n// Simple memoization\nconst memoCache = new Map();\n\nexport function memo(component, keyGenerator) {\n return function MemoizedComponent(props = {}) {\n const key = keyGenerator ? keyGenerator(props) : JSON.stringify(props);\n\n if (memoCache.has(key)) {\n return memoCache.get(key);\n }\n\n const result = component(props);\n memoCache.set(key, result);\n\n // Simple cache cleanup - keep only last 100 items\n if (memoCache.size > 100) {\n const firstKey = memoCache.keys().next().value;\n memoCache.delete(firstKey);\n }\n\n return result;\n };\n}\n\n// Utility functions\nexport function validateComponent(obj) {\n if (!obj || typeof obj !== 'object') {\n throw new Error('Component must be an object');\n }\n return true;\n}\n\nexport function isCoherentObject(obj) {\n return obj && typeof obj === 'object' && !Array.isArray(obj);\n}\n\nexport function deepClone(obj) {\n if (obj === null || typeof obj !== 'object') return obj;\n if (obj instanceof Date) return new Date(obj);\n if (Array.isArray(obj)) return obj.map(deepClone);\n\n const cloned = {};\n for (const [key, value] of Object.entries(obj)) {\n cloned[key] = deepClone(value);\n }\n return cloned;\n}\n\n// Version info\nexport const VERSION = '2.0.0';\n\n// Performance monitoring export\nexport { performanceMonitor };\n\n// Shadow DOM exports\nexport { shadowDOM };\n\n// Import Shadow DOM functionality\nimport * as shadowDOM from './shadow-dom.js';\n\n// Event system imports and exports\nimport eventSystemDefault, {\n EventBus,\n createEventBus,\n globalEventBus,\n emit,\n emitSync,\n on,\n once,\n off,\n registerAction,\n handleAction,\n DOMEventIntegration,\n globalDOMIntegration,\n initializeDOMIntegration,\n withEventBus,\n withEventState,\n createActionHandlers,\n createEventHandlers,\n createEventComponent\n} from './events/index.js';\n\nexport {\n eventSystemDefault as eventSystem,\n EventBus,\n createEventBus,\n globalEventBus,\n emit,\n emitSync,\n on,\n once,\n off,\n registerAction,\n handleAction,\n DOMEventIntegration,\n globalDOMIntegration,\n initializeDOMIntegration,\n withEventBus,\n withEventState,\n createActionHandlers,\n createEventHandlers,\n createEventComponent\n};\n\n// Note: Forms have been moved to @coherent.js/forms package\n\n// Default export\nconst coherent = {\n // Core rendering\n render,\n\n // Shadow DOM (client-side only)\n shadowDOM,\n\n // Component system\n createComponent,\n defineComponent,\n registerComponent,\n getComponent,\n getRegisteredComponents,\n lazy,\n isLazy,\n evaluateLazy,\n\n // Component lifecycle\n ComponentLifecycle,\n LIFECYCLE_PHASES,\n withLifecycle,\n createLifecycleHooks,\n useHooks,\n lifecycleUtils,\n\n // Object factory\n createElement,\n createTextNode,\n h,\n\n // Component cache\n ComponentCache,\n createComponentCache,\n memoize,\n\n // State management\n withState,\n withStateUtils,\n createStateManager,\n memo,\n\n // Error boundaries\n createErrorBoundary,\n createErrorFallback,\n withErrorBoundary,\n createAsyncErrorBoundary,\n GlobalErrorHandler,\n createGlobalErrorHandler,\n\n // Event system\n eventSystem: eventSystemDefault,\n emit,\n emitSync,\n on,\n once,\n off,\n registerAction,\n handleAction,\n withEventBus,\n withEventState,\n\n // Utilities\n validateComponent,\n isCoherentObject,\n deepClone,\n escapeHtml,\n performanceMonitor,\n VERSION\n};\n\nexport default coherent;\n", "// src/express/index.js\nimport { render } from '../../core/src/index.js';\n\nexport function expressEngine() {\n return (filePath, options, callback) => {\n try {\n // options contains the Coherent object structure\n const html = render(options);\n callback(null, html);\n } catch (_error) {\n callback(_error);\n }\n };\n}\n\n// Helper for Express apps\nexport function setupCoherent(app) {\n app.engine('coherent', expressEngine());\n app.set('view engine', 'coherent');\n}\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/index.js"],
4
+ "sourcesContent": ["// src/express/index.js\nimport { render } from '@coherent.js/core';\n\nexport function expressEngine() {\n return (filePath, options, callback) => {\n try {\n // options contains the Coherent object structure\n const html = render(options);\n callback(null, html);\n } catch (_error) {\n callback(_error);\n }\n };\n}\n\n// Helper for Express apps\nexport function setupCoherent(app) {\n app.engine('coherent', expressEngine());\n app.set('view engine', 'coherent');\n}\n"],
5
+ "mappings": ";AACA,SAAS,cAAc;AAEhB,SAAS,gBAAgB;AAC5B,SAAO,CAAC,UAAU,SAAS,aAAa;AACpC,QAAI;AAEA,YAAM,OAAO,OAAO,OAAO;AAC3B,eAAS,MAAM,IAAI;AAAA,IACvB,SAAS,QAAQ;AACb,eAAS,MAAM;AAAA,IACnB;AAAA,EACJ;AACJ;AAGO,SAAS,cAAc,KAAK;AAC/B,MAAI,OAAO,YAAY,cAAc,CAAC;AACtC,MAAI,IAAI,eAAe,UAAU;AACrC;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coherent.js/express",
3
- "version": "1.0.0-beta.5",
3
+ "version": "1.0.0-beta.6",
4
4
  "description": "Express adapter for Coherent.js",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "peerDependencies": {
30
30
  "express": ">=4.18.0 < 6.0.0",
31
- "@coherent.js/core": "1.0.0-beta.5"
31
+ "@coherent.js/core": "1.0.0-beta.6"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public"
package/types/index.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { Application, RequestHandler, Request, Response, NextFunction } from 'express';
9
- import { CoherentNode } from '@coherent/core';
9
+ import { CoherentNode, RenderOptions } from '@coherent.js/core';
10
10
 
11
11
  // ============================================================================
12
12
  // Express Engine Types
@@ -45,7 +45,7 @@ export interface CoherentExpressOptions {
45
45
  viewsDirectory?: string;
46
46
  cache?: boolean;
47
47
  development?: boolean;
48
- renderOptions?: {
48
+ renderOptions?: RenderOptions & {
49
49
  pretty?: boolean;
50
50
  doctype?: string;
51
51
  compileDebug?: boolean;
@@ -55,7 +55,7 @@ export interface CoherentExpressOptions {
55
55
 
56
56
  /** Express application with Coherent.js support */
57
57
  export interface CoherentExpressApplication extends Application {
58
- renderCoherent(view: CoherentNode, options?: any): void;
58
+ renderCoherent(view: CoherentNode, options?: RenderOptions): void;
59
59
  }
60
60
 
61
61
  /** Enhanced Express request with Coherent.js utilities */
@@ -66,7 +66,7 @@ export interface CoherentRequest extends Request {
66
66
 
67
67
  /** Enhanced Express response with Coherent.js utilities */
68
68
  export interface CoherentResponse extends Response {
69
- renderCoherent(component: CoherentNode, options?: any): void;
69
+ renderCoherent(component: CoherentNode, options?: RenderOptions): void;
70
70
  sendComponent<P = any>(component: (props: P) => CoherentNode, props?: P): void;
71
71
  streamComponent<P = any>(component: (props: P) => CoherentNode, props?: P): void;
72
72
  }
@@ -78,6 +78,24 @@ export interface CoherentResponse extends Response {
78
78
  /** Coherent middleware factory */
79
79
  export type CoherentMiddleware = (options?: CoherentExpressOptions) => RequestHandler;
80
80
 
81
+ /**
82
+ * Create middleware that enables Coherent.js rendering on Express responses.
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * import express from 'express';
87
+ * import { coherentMiddleware } from '@coherent.js/express';
88
+ *
89
+ * const app = express();
90
+ * app.use(coherentMiddleware({ development: true }));
91
+ *
92
+ * app.get('/', (req, res) => {
93
+ * res.renderCoherent({ div: { text: 'Hello World' } });
94
+ * });
95
+ * ```
96
+ */
97
+ export function coherentMiddleware(options?: CoherentExpressOptions): RequestHandler;
98
+
81
99
  /** Component rendering middleware options */
82
100
  export interface ComponentMiddlewareOptions {
83
101
  componentDirectory?: string;
@@ -208,6 +226,18 @@ export function ssrMiddleware(config?: SSRConfig): RequestHandler;
208
226
  /** Development middleware with HMR */
209
227
  export function devMiddleware(options?: DevServerOptions & HMRConfig): RequestHandler;
210
228
 
229
+ /**
230
+ * Render a CoherentNode to HTML string.
231
+ *
232
+ * @example
233
+ * ```typescript
234
+ * import { renderComponent } from '@coherent.js/express';
235
+ *
236
+ * const html = renderComponent({ div: { text: 'Hello' } });
237
+ * ```
238
+ */
239
+ export function renderComponent(component: CoherentNode, options?: RenderOptions): string;
240
+
211
241
  // ============================================================================
212
242
  // Utility Functions
213
243
  // ============================================================================
@@ -236,12 +266,14 @@ declare const coherentExpress: {
236
266
  setupCoherent: typeof setupCoherent;
237
267
  createComponentRoute: typeof createComponentRoute;
238
268
  coherentStatic: typeof coherentStatic;
269
+ coherentMiddleware: typeof coherentMiddleware;
239
270
  componentMiddleware: typeof componentMiddleware;
240
271
  ssrMiddleware: typeof ssrMiddleware;
241
272
  devMiddleware: typeof devMiddleware;
242
273
  createCoherentApp: typeof createCoherentApp;
243
274
  registerRoutes: typeof registerRoutes;
244
275
  createErrorHandler: typeof createErrorHandler;
276
+ renderComponent: typeof renderComponent;
245
277
  };
246
278
 
247
279
  export default coherentExpress;