@withl5e/l5e 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +24 -0
- package/dist/action.js +10 -0
- package/dist/action.js.map +1 -0
- package/dist/client-D67hK4Yy.js +9 -0
- package/dist/client-D67hK4Yy.js.map +1 -0
- package/dist/entry-server-Ckh6zfgm.js +258 -0
- package/dist/entry-server-Ckh6zfgm.js.map +1 -0
- package/dist/entry-server.js +12 -0
- package/dist/entry-server.js.map +1 -0
- package/dist/generateMetadata-C5QsMS-H.js +144 -0
- package/dist/generateMetadata-C5QsMS-H.js.map +1 -0
- package/dist/index-BIt7MJT9.js +163 -0
- package/dist/index-BIt7MJT9.js.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/island/client.js +5 -0
- package/dist/island/client.js.map +1 -0
- package/dist/island/runtime.js +98 -0
- package/dist/island/runtime.js.map +1 -0
- package/dist/island.js +39 -0
- package/dist/island.js.map +1 -0
- package/dist/jsx-runtime-C2Vw67N2.js +256 -0
- package/dist/jsx-runtime-C2Vw67N2.js.map +1 -0
- package/dist/jsx-runtime.js +26 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/middleware.js +9 -0
- package/dist/middleware.js.map +1 -0
- package/dist/seo.js +7 -0
- package/dist/seo.js.map +1 -0
- package/dist/server.js +489 -0
- package/dist/server.js.map +1 -0
- package/dist/swap/server.js +15 -0
- package/dist/swap/server.js.map +1 -0
- package/dist/swap.js +121 -0
- package/dist/swap.js.map +1 -0
- package/dist/tooltip.js +129 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/vite-plugin.js +381 -0
- package/dist/vite-plugin.js.map +1 -0
- package/index.ts +1 -0
- package/package.json +129 -0
- package/src/action/define-action.ts +8 -0
- package/src/action/index.ts +2 -0
- package/src/action/types.ts +21 -0
- package/src/core/bundler.ts +275 -0
- package/src/core/const.ts +2 -0
- package/src/core/entry-server.d.ts +1 -0
- package/src/core/entry-server.ts +381 -0
- package/src/core/exceptions.ts +80 -0
- package/src/core/head-priority.ts +15 -0
- package/src/core/index.ts +40 -0
- package/src/core/jsx-runtime.ts +325 -0
- package/src/core/jsx-types.d.ts +548 -0
- package/src/core/render.ts +181 -0
- package/src/core/request.ts +31 -0
- package/src/core/server.ts +740 -0
- package/src/core/vite-plugin.ts +779 -0
- package/src/island/ClientIsland.ts +71 -0
- package/src/island/client.ts +3 -0
- package/src/island/index.ts +3 -0
- package/src/island/runtime.ts +149 -0
- package/src/island/strategy-registry.ts +10 -0
- package/src/island/types.ts +28 -0
- package/src/middleware/defineMiddleware.ts +5 -0
- package/src/middleware/index.ts +133 -0
- package/src/middleware/sequence.ts +105 -0
- package/src/middleware/types.ts +28 -0
- package/src/seo/generateMetadata.tsx +559 -0
- package/src/seo/index.ts +10 -0
- package/src/seo/mergeMetadata.ts +200 -0
- package/src/seo/types.ts +316 -0
- package/src/swap/SwapResponse.tsx +16 -0
- package/src/swap/create-swap.ts +121 -0
- package/src/swap/index.ts +8 -0
- package/src/swap/parse.ts +12 -0
- package/src/swap/server.ts +1 -0
- package/src/swap/swap.ts +57 -0
- package/src/swap/types.ts +47 -0
- package/src/swap/utils.ts +7 -0
- package/src/tooltip/index.ts +2 -0
- package/src/tooltip/tooltip-loader.ts +108 -0
- package/src/tooltip/tooltip-runtime.ts +173 -0
- package/types.d.ts +14 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { RAW_HTML_MARKER } from './const';
|
|
2
|
+
import {
|
|
3
|
+
addCacheTag,
|
|
4
|
+
type HtmlContentObject,
|
|
5
|
+
type JSXChild,
|
|
6
|
+
type JSXNode,
|
|
7
|
+
type RenderedNode,
|
|
8
|
+
} from './jsx-runtime';
|
|
9
|
+
|
|
10
|
+
if (true) {
|
|
11
|
+
console.log('render.ts');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const VOID_ELEMENTS = new Set<string>([
|
|
15
|
+
'area',
|
|
16
|
+
'base',
|
|
17
|
+
'br',
|
|
18
|
+
'col',
|
|
19
|
+
'embed',
|
|
20
|
+
'hr',
|
|
21
|
+
'img',
|
|
22
|
+
'input',
|
|
23
|
+
'link',
|
|
24
|
+
'meta',
|
|
25
|
+
'param',
|
|
26
|
+
'source',
|
|
27
|
+
'track',
|
|
28
|
+
'wbr',
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
function classList(input: unknown): string {
|
|
32
|
+
if (!input) return '';
|
|
33
|
+
if (typeof input === 'string') return input;
|
|
34
|
+
if (Array.isArray(input)) {
|
|
35
|
+
return input.map(classList).filter(Boolean).join(' ');
|
|
36
|
+
}
|
|
37
|
+
if (typeof input === 'object') {
|
|
38
|
+
return Object.keys(input as Record<string, boolean>)
|
|
39
|
+
.filter((key) => (input as Record<string, boolean>)[key])
|
|
40
|
+
.join(' ');
|
|
41
|
+
}
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function escapeProp(value: string): string {
|
|
46
|
+
return value
|
|
47
|
+
.replaceAll('&', '&')
|
|
48
|
+
.replaceAll('"', '"')
|
|
49
|
+
.replaceAll('<', '<')
|
|
50
|
+
.replaceAll('>', '>')
|
|
51
|
+
.replaceAll('\n', ' ')
|
|
52
|
+
.trim();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function escapeHTML(value: string): string {
|
|
56
|
+
return value
|
|
57
|
+
.replaceAll('&', '&')
|
|
58
|
+
.replaceAll('"', '"')
|
|
59
|
+
.replaceAll("'", ''')
|
|
60
|
+
.replaceAll('<', '<')
|
|
61
|
+
.replaceAll('>', '>')
|
|
62
|
+
.replaceAll('\n', '<br/>');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function renderAttributes(props?: Record<string, any>): string {
|
|
66
|
+
if (!props) return '';
|
|
67
|
+
|
|
68
|
+
let classValue = '';
|
|
69
|
+
if (props.classList !== undefined) {
|
|
70
|
+
classValue = classList(props.classList);
|
|
71
|
+
}
|
|
72
|
+
if (props.class) {
|
|
73
|
+
const existingClass = typeof props.class === 'string' ? props.class : '';
|
|
74
|
+
classValue = classValue ? `${classValue} ${existingClass}`.trim() : existingClass;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const attrs = Object.entries(props)
|
|
78
|
+
.filter(
|
|
79
|
+
([key]) =>
|
|
80
|
+
key !== 'children' &&
|
|
81
|
+
key !== 'classList' &&
|
|
82
|
+
key !== 'setHtml' &&
|
|
83
|
+
key !== 'setText' &&
|
|
84
|
+
key !== 'class' &&
|
|
85
|
+
key !== 'key' &&
|
|
86
|
+
key !== 'cacheTag',
|
|
87
|
+
)
|
|
88
|
+
.map(([key, value]) => {
|
|
89
|
+
// HTML standard behavior with function execution support
|
|
90
|
+
if (value === false || value === null || value === undefined) return '';
|
|
91
|
+
if (value === true) return key;
|
|
92
|
+
|
|
93
|
+
// Execute function props and get result (new feature)
|
|
94
|
+
if (typeof value === 'function') {
|
|
95
|
+
const result = value();
|
|
96
|
+
return `${key}="${escapeProp(result?.toString() || '')}"`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return `${key}="${escapeProp(value?.toString() || '')}"`;
|
|
100
|
+
})
|
|
101
|
+
.filter(Boolean) as string[];
|
|
102
|
+
|
|
103
|
+
if (classValue) {
|
|
104
|
+
attrs.push(`class="${escapeProp(classValue)}"`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return attrs.join(' ');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function renderJsxToHtmlStringInternal(element: JSXChild): string {
|
|
111
|
+
// HTML standard: skip boolean, null, undefined children
|
|
112
|
+
if (element === null || typeof element === 'boolean' || element === undefined) return '';
|
|
113
|
+
|
|
114
|
+
if (element && typeof element === 'object' && (element as any)[RAW_HTML_MARKER]) {
|
|
115
|
+
return (element as any).content || '';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Support htmlContent object (new feature)
|
|
119
|
+
if (element && typeof element === 'object' && 'htmlContent' in element) {
|
|
120
|
+
return (element as HtmlContentObject).htmlContent;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (typeof element === 'string') return escapeHTML(element.toString());
|
|
124
|
+
if (typeof element === 'number') return element.toString();
|
|
125
|
+
|
|
126
|
+
if (Array.isArray(element)) {
|
|
127
|
+
return (element as JSXChild[]).map((el) => renderJsxToHtmlStringInternal(el)).join('');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const { type, props, children } = element as JSXNode;
|
|
131
|
+
|
|
132
|
+
// Collect cache tags from props
|
|
133
|
+
if (props?.cacheTag) {
|
|
134
|
+
addCacheTag(props.cacheTag);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (typeof type === 'function') {
|
|
138
|
+
const componentResult = (type as any)({ ...(props || {}), children });
|
|
139
|
+
// Check if component returned a RenderedNode
|
|
140
|
+
if (componentResult && typeof componentResult === 'object' && 'string' in componentResult) {
|
|
141
|
+
return (componentResult as RenderedNode).string;
|
|
142
|
+
}
|
|
143
|
+
return renderJsxToHtmlStringInternal(componentResult as JSXChild);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const attrs = renderAttributes(props);
|
|
147
|
+
const isVoidElement = VOID_ELEMENTS.has((type as string).toLowerCase());
|
|
148
|
+
|
|
149
|
+
if (isVoidElement) {
|
|
150
|
+
return `<${type}${attrs ? ' ' + attrs : ''} />`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let childrenHtml = '';
|
|
154
|
+
if (props?.setHtml !== undefined) {
|
|
155
|
+
childrenHtml = props.setHtml?.toString() || '';
|
|
156
|
+
} else if (props?.setText !== undefined) {
|
|
157
|
+
childrenHtml = escapeHTML(props.setText?.toString() || '');
|
|
158
|
+
} else {
|
|
159
|
+
childrenHtml = (children as JSXChild[]).map((el) => renderJsxToHtmlStringInternal(el)).join('');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return `<${type}${attrs ? ' ' + attrs : ''}>${childrenHtml}</${type}>`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function renderJsxToHtmlString(element: JSXChild | RenderedNode): string {
|
|
166
|
+
// If already a RenderedNode, return its string
|
|
167
|
+
if (element && typeof element === 'object' && 'string' in element) {
|
|
168
|
+
return (element as RenderedNode).string;
|
|
169
|
+
}
|
|
170
|
+
return renderJsxToHtmlStringInternal(element as JSXChild);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function renderToRenderedNode(element: JSXChild | RenderedNode): RenderedNode {
|
|
174
|
+
// If already a RenderedNode, return as is
|
|
175
|
+
if (element && typeof element === 'object' && 'string' in element) {
|
|
176
|
+
return element as RenderedNode;
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
string: renderJsxToHtmlStringInternal(element as JSXChild),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
|
|
3
|
+
export function parseCookies(cookieHeader?: string): Record<string, string> {
|
|
4
|
+
if (!cookieHeader) return {};
|
|
5
|
+
|
|
6
|
+
return cookieHeader.split(';').reduce(
|
|
7
|
+
(cookies, cookie) => {
|
|
8
|
+
const [name, ...rest] = cookie.split('=');
|
|
9
|
+
if (name && rest.length > 0) {
|
|
10
|
+
cookies[name.trim()] = decodeURIComponent(rest.join('=').trim());
|
|
11
|
+
}
|
|
12
|
+
return cookies;
|
|
13
|
+
},
|
|
14
|
+
{} as Record<string, string>,
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createHeadersFromExpressRequest(req: Request): Headers {
|
|
19
|
+
const headers = new Headers();
|
|
20
|
+
|
|
21
|
+
Object.entries(req.headers).forEach(([key, value]) => {
|
|
22
|
+
if (value === undefined) return;
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
value.forEach((item) => headers.append(key, item));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
headers.set(key, value);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return headers;
|
|
31
|
+
}
|