Skip to content

Commit 069c059

Browse files
committed
att
1 parent fc9c466 commit 069c059

File tree

3 files changed

+81
-9
lines changed

3 files changed

+81
-9
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@caeljs/jsx",
33
"type": "module",
44
"description": "ASYNC JSX/SSR framework for building modern web applications with component-based templates. It offers a lightweight virtual DOM, intelligent routing system, and reactive components with no external dependencies. Designed to generate optimized static websites or dynamic SSR applications with high performance",
5-
"version": "0.1.9",
5+
"version": "0.2.0",
66
"main": "cjs/JsxSSR.cjs",
77
"module": "esm/JsxSSR.js",
88
"types": "dist/JsxSSR.d.ts",

src/server/render.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ export const createElement = (
3838
...children: DOMNode[]
3939
): DOMNode => {
4040
const normalizedProps = props || {};
41-
normalizedProps.children = children.flat().filter(isValidNode);
41+
normalizedProps.children = children.flat()
42+
.filter((node) => node !== null && node !== undefined && node !== false);
4243

4344
// Special handling for script elements with client-side code
4445
if (type === 'script' && (normalizedProps.client || normalizedProps.loaded)) {

src/server/utils.ts

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { DOMElement, DOMNode, PrimitiveNode } from "./types";
1+
import type { DOMElement, DOMNode, FunctionComponent, PrimitiveNode } from "./types";
22

33
/**
44
* Extracts the body, parameters, and async status from a function
@@ -106,13 +106,84 @@ export const isElementNode = (node: unknown): node is DOMElement => (
106106
);
107107

108108
/**
109-
* Checks if a node is valid (not null, undefined, or false)
110-
* @param {unknown} node - The node to check
111-
* @returns {boolean} True if the node is valid
109+
* Enhanced DOM node validation with type-specific checks
110+
* @param node - The node to validate
111+
* @param options - Validation options
112+
* @returns True if the node is valid according to the specified criteria
112113
*/
113-
export const isValidNode = (node: unknown): boolean => (
114-
node !== null && node !== undefined && node !== false
115-
);
114+
export const isValidNode = (
115+
node: unknown,
116+
options: {
117+
allowEmptyString?: boolean;
118+
allowZero?: boolean;
119+
allowBoolean?: boolean;
120+
allowPromise?: boolean;
121+
allowFunction?: boolean;
122+
} = {}
123+
): node is DOMNode => {
124+
// Default options
125+
const {
126+
allowEmptyString = false,
127+
allowZero = true,
128+
allowBoolean = false,
129+
allowPromise = true,
130+
allowFunction = true,
131+
} = options;
132+
133+
// Null/undefined check
134+
if (node == null) return false;
135+
136+
// Boolean check
137+
if (typeof node === 'boolean') return allowBoolean;
138+
139+
// Number check (special handling for 0)
140+
if (typeof node === 'number') {
141+
if (node === 0) return allowZero;
142+
return !Number.isNaN(node);
143+
}
144+
145+
// String check (empty string handling)
146+
if (typeof node === 'string') return allowEmptyString || node.length > 0;
147+
148+
// Promise check
149+
if (node instanceof Promise) return allowPromise;
150+
151+
// Function check (for components)
152+
if (typeof node === 'function') return allowFunction;
153+
154+
// Array check (recursive validation)
155+
if (Array.isArray(node)) {
156+
return node.every(child => isValidNode(child, options));
157+
}
158+
159+
// DOM Node object check
160+
if (typeof node === 'object') {
161+
return (
162+
node !== null && 'type' in node &&
163+
node.type !== undefined && 'props' in node &&
164+
node.props !== undefined
165+
);
166+
}
167+
168+
// All other cases
169+
return true;
170+
};
171+
172+
// Type guard version for specific node types
173+
export const isValidNodeOfType = <T extends DOMNode>(
174+
node: unknown,
175+
typeGuard: (n: DOMNode) => n is T,
176+
options?: Parameters<typeof isValidNode>[1]
177+
): node is T => {
178+
return isValidNode(node, options) && typeGuard(node as DOMNode);
179+
};
180+
181+
export const isComponentNode = (node: unknown): node is { type: FunctionComponent; props: any } =>
182+
isValidNode(node) && typeof (node as any).type === 'function';
183+
184+
export const isTextNode = (node: unknown): node is string | number =>
185+
typeof node === 'string' || typeof node === 'number';
186+
116187

117188
// Set of HTML void elements that don't need closing tags
118189
const voidElements = new Set([

0 commit comments

Comments
 (0)