hono
Version:
Web framework built on Web Standards
353 lines (352 loc) • 10.4 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var base_exports = {};
__export(base_exports, {
Fragment: () => Fragment,
JSXFragmentNode: () => JSXFragmentNode,
JSXNode: () => JSXNode,
cloneElement: () => cloneElement,
getNameSpaceContext: () => getNameSpaceContext,
isValidElement: () => isValidElement,
jsx: () => jsx,
jsxFn: () => jsxFn,
memo: () => memo,
reactAPICompatVersion: () => reactAPICompatVersion
});
module.exports = __toCommonJS(base_exports);
var import_html = require("../helper/html");
var import_html2 = require("../utils/html");
var import_context = require("./context");
var import_constants = require("./constants");
var import_utils = require("./utils");
var intrinsicElementTags = __toESM(require("./intrinsic-element/components"), 1);
var import_common = require("./intrinsic-element/common");
let nameSpaceContext = void 0;
const getNameSpaceContext = () => nameSpaceContext;
const toSVGAttributeName = (key) => /[A-Z]/.test(key) && key.match(
/^(?:al|basel|clip(?:Path|Rule)$|co|do|fill|fl|fo|gl|let|lig|i|marker[EMS]|o|pai|pointe|sh|st[or]|text[^L]|tr|u|ve|w)/
) ? key.replace(/([A-Z])/g, "-$1").toLowerCase() : key;
const emptyTags = [
"area",
"base",
"br",
"col",
"embed",
"hr",
"img",
"input",
"keygen",
"link",
"meta",
"param",
"source",
"track",
"wbr"
];
const booleanAttributes = [
"allowfullscreen",
"async",
"autofocus",
"autoplay",
"checked",
"controls",
"default",
"defer",
"disabled",
"download",
"formnovalidate",
"hidden",
"inert",
"ismap",
"itemscope",
"loop",
"multiple",
"muted",
"nomodule",
"novalidate",
"open",
"playsinline",
"readonly",
"required",
"reversed",
"selected"
];
const childrenToStringToBuffer = (children, buffer) => {
for (let i = 0, len = children.length; i < len; i++) {
const child = children[i];
if (typeof child === "string") {
(0, import_html2.escapeToBuffer)(child, buffer);
} else if (typeof child === "boolean" || child === null || child === void 0) {
continue;
} else if (child instanceof JSXNode) {
child.toStringToBuffer(buffer);
} else if (typeof child === "number" || child.isEscaped) {
;
buffer[0] += child;
} else if (child instanceof Promise) {
buffer.unshift("", child);
} else {
childrenToStringToBuffer(child, buffer);
}
}
};
class JSXNode {
tag;
props;
key;
children;
isEscaped = true;
localContexts;
constructor(tag, props, children) {
this.tag = tag;
this.props = props;
this.children = children;
}
get type() {
return this.tag;
}
get ref() {
return this.props.ref || null;
}
toString() {
const buffer = [""];
this.localContexts?.forEach(([context, value]) => {
context.values.push(value);
});
try {
this.toStringToBuffer(buffer);
} finally {
this.localContexts?.forEach(([context]) => {
context.values.pop();
});
}
return buffer.length === 1 ? "callbacks" in buffer ? (0, import_html2.resolveCallbackSync)((0, import_html.raw)(buffer[0], buffer.callbacks)).toString() : buffer[0] : (0, import_html2.stringBufferToString)(buffer, buffer.callbacks);
}
toStringToBuffer(buffer) {
const tag = this.tag;
const props = this.props;
let { children } = this;
buffer[0] += `<${tag}`;
const normalizeKey = nameSpaceContext && (0, import_context.useContext)(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName((0, import_utils.normalizeIntrinsicElementKey)(key)) : (key) => (0, import_utils.normalizeIntrinsicElementKey)(key);
for (let [key, v] of Object.entries(props)) {
key = normalizeKey(key);
if (key === "children") {
} else if (key === "style" && typeof v === "object") {
let styleStr = "";
(0, import_utils.styleObjectForEach)(v, (property, value) => {
if (value != null) {
styleStr += `${styleStr ? ";" : ""}${property}:${value}`;
}
});
buffer[0] += ' style="';
(0, import_html2.escapeToBuffer)(styleStr, buffer);
buffer[0] += '"';
} else if (typeof v === "string") {
buffer[0] += ` ${key}="`;
(0, import_html2.escapeToBuffer)(v, buffer);
buffer[0] += '"';
} else if (v === null || v === void 0) {
} else if (typeof v === "number" || v.isEscaped) {
buffer[0] += ` ${key}="${v}"`;
} else if (typeof v === "boolean" && booleanAttributes.includes(key)) {
if (v) {
buffer[0] += ` ${key}=""`;
}
} else if (key === "dangerouslySetInnerHTML") {
if (children.length > 0) {
throw "Can only set one of `children` or `props.dangerouslySetInnerHTML`.";
}
children = [(0, import_html.raw)(v.__html)];
} else if (v instanceof Promise) {
buffer[0] += ` ${key}="`;
buffer.unshift('"', v);
} else if (typeof v === "function") {
if (!key.startsWith("on")) {
throw `Invalid prop '${key}' of type 'function' supplied to '${tag}'.`;
}
} else {
buffer[0] += ` ${key}="`;
(0, import_html2.escapeToBuffer)(v.toString(), buffer);
buffer[0] += '"';
}
}
if (emptyTags.includes(tag) && children.length === 0) {
buffer[0] += "/>";
return;
}
buffer[0] += ">";
childrenToStringToBuffer(children, buffer);
buffer[0] += `</${tag}>`;
}
}
class JSXFunctionNode extends JSXNode {
toStringToBuffer(buffer) {
const { children } = this;
const res = this.tag.call(null, {
...this.props,
children: children.length <= 1 ? children[0] : children
});
if (typeof res === "boolean" || res == null) {
return;
} else if (res instanceof Promise) {
if (import_context.globalContexts.length === 0) {
buffer.unshift("", res);
} else {
const currentContexts = import_context.globalContexts.map((c) => [c, c.values.at(-1)]);
buffer.unshift(
"",
res.then((childRes) => {
if (childRes instanceof JSXNode) {
childRes.localContexts = currentContexts;
}
return childRes;
})
);
}
} else if (res instanceof JSXNode) {
res.toStringToBuffer(buffer);
} else if (typeof res === "number" || res.isEscaped) {
buffer[0] += res;
if (res.callbacks) {
buffer.callbacks ||= [];
buffer.callbacks.push(...res.callbacks);
}
} else {
(0, import_html2.escapeToBuffer)(res, buffer);
}
}
}
class JSXFragmentNode extends JSXNode {
toStringToBuffer(buffer) {
childrenToStringToBuffer(this.children, buffer);
}
}
const jsx = (tag, props, ...children) => {
props ??= {};
if (children.length) {
props.children = children.length === 1 ? children[0] : children;
}
const key = props.key;
delete props["key"];
const node = jsxFn(tag, props, children);
node.key = key;
return node;
};
let initDomRenderer = false;
const jsxFn = (tag, props, children) => {
if (!initDomRenderer) {
for (const k in import_common.domRenderers) {
;
intrinsicElementTags[k][import_constants.DOM_RENDERER] = import_common.domRenderers[k];
}
initDomRenderer = true;
}
if (typeof tag === "function") {
return new JSXFunctionNode(tag, props, children);
} else if (intrinsicElementTags[tag]) {
return new JSXFunctionNode(
intrinsicElementTags[tag],
props,
children
);
} else if (tag === "svg") {
nameSpaceContext ||= (0, import_context.createContext)("");
return new JSXNode(tag, props, [
new JSXFunctionNode(
nameSpaceContext,
{
value: tag
},
children
)
]);
} else {
return new JSXNode(tag, props, children);
}
};
const shallowEqual = (a, b) => {
if (a === b) {
return true;
}
const aKeys = Object.keys(a).sort();
const bKeys = Object.keys(b).sort();
if (aKeys.length !== bKeys.length) {
return false;
}
for (let i = 0, len = aKeys.length; i < len; i++) {
if (aKeys[i] === "children" && bKeys[i] === "children" && !a.children?.length && !b.children?.length) {
continue;
} else if (a[aKeys[i]] !== b[aKeys[i]]) {
return false;
}
}
return true;
};
const memo = (component, propsAreEqual = shallowEqual) => {
let computed = null;
let prevProps = void 0;
return (props) => {
if (prevProps && !propsAreEqual(prevProps, props)) {
computed = null;
}
prevProps = props;
return computed ||= component(props);
};
};
const Fragment = ({
children
}) => {
return new JSXFragmentNode(
"",
{
children
},
Array.isArray(children) ? children : children ? [children] : []
);
};
const isValidElement = (element) => {
return !!(element && typeof element === "object" && "tag" in element && "props" in element);
};
const cloneElement = (element, props, ...children) => {
return jsx(
element.tag,
{ ...element.props, ...props },
...children
);
};
const reactAPICompatVersion = "19.0.0-hono-jsx";
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Fragment,
JSXFragmentNode,
JSXNode,
cloneElement,
getNameSpaceContext,
isValidElement,
jsx,
jsxFn,
memo,
reactAPICompatVersion
});
;