@thestarweb/star-framework-app-web 0.1.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/dist/browser/index.js +8 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/cli/dev-server.js +64 -0
- package/dist/cli/dev-server.js.map +1 -0
- package/dist/cli/index.js +117 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli-helper.js +2 -0
- package/dist/cli-helper.js.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptor/index.js +26 -0
- package/dist/interceptor/index.js.map +1 -0
- package/dist/interceptor/middleware-to-interceptor/index.js +32 -0
- package/dist/interceptor/middleware-to-interceptor/index.js.map +1 -0
- package/dist/interceptor/middleware-to-interceptor/mock-res.js +241 -0
- package/dist/interceptor/middleware-to-interceptor/mock-res.js.map +1 -0
- package/dist/interceptor/middleware-to-interceptor/mook-req.js +180 -0
- package/dist/interceptor/middleware-to-interceptor/mook-req.js.map +1 -0
- package/dist/interceptor/types.js +6 -0
- package/dist/interceptor/types.js.map +1 -0
- package/dist/params/index.js +10 -0
- package/dist/params/index.js.map +1 -0
- package/dist/request/index.js +46 -0
- package/dist/request/index.js.map +1 -0
- package/dist/return-types/index.js +2 -0
- package/dist/return-types/index.js.map +1 -0
- package/dist/return-types/response-with-meta.js +25 -0
- package/dist/return-types/response-with-meta.js.map +1 -0
- package/dist/route/index.js +20 -0
- package/dist/route/index.js.map +1 -0
- package/dist/route/types.js +17 -0
- package/dist/route/types.js.map +1 -0
- package/dist/runtime/index.js +84 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/type.js +11 -0
- package/dist/runtime/type.js.map +1 -0
- package/dist/server/body/helper.js +118 -0
- package/dist/server/body/helper.js.map +1 -0
- package/dist/server/body/json.js +211 -0
- package/dist/server/body/json.js.map +1 -0
- package/dist/server/body/types.js +6 -0
- package/dist/server/body/types.js.map +1 -0
- package/dist/server/dump-api-type.js +59 -0
- package/dist/server/dump-api-type.js.map +1 -0
- package/dist/server/index.js +103 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/types.js +8 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/utils/pass-through-readable.js +13 -0
- package/dist/server/utils/pass-through-readable.js.map +1 -0
- package/dist/view/const.js +2 -0
- package/dist/view/const.js.map +1 -0
- package/dist/view/data-context/conetext.js +70 -0
- package/dist/view/data-context/conetext.js.map +1 -0
- package/dist/view/data-context/index.js +13 -0
- package/dist/view/data-context/index.js.map +1 -0
- package/dist/view/html/create-element.js +20 -0
- package/dist/view/html/create-element.js.map +1 -0
- package/dist/view/html/index.js +4 -0
- package/dist/view/html/index.js.map +1 -0
- package/dist/view/html/parse-html-to-v-dom.js +317 -0
- package/dist/view/html/parse-html-to-v-dom.js.map +1 -0
- package/dist/view/html/render-v-dom-to-string.js +46 -0
- package/dist/view/html/render-v-dom-to-string.js.map +1 -0
- package/dist/view/html/types.js +21 -0
- package/dist/view/html/types.js.map +1 -0
- package/dist/view/index.js +7 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/layout.js +24 -0
- package/dist/view/layout.js.map +1 -0
- package/dist/view/render/html-render.js +21 -0
- package/dist/view/render/html-render.js.map +1 -0
- package/dist/view/render/index.js +3 -0
- package/dist/view/render/index.js.map +1 -0
- package/dist/view/render/render.js +183 -0
- package/dist/view/render/render.js.map +1 -0
- package/dist/view/render/sf-v-dom-render.js +40 -0
- package/dist/view/render/sf-v-dom-render.js.map +1 -0
- package/dist/view/types.js +10 -0
- package/dist/view/types.js.map +1 -0
- package/dist/view/utils/find-route-dom.js +22 -0
- package/dist/view/utils/find-route-dom.js.map +1 -0
- package/dist/view/utils/get-render/client.js +77 -0
- package/dist/view/utils/get-render/client.js.map +1 -0
- package/dist/view/utils/get-render/common.js +87 -0
- package/dist/view/utils/get-render/common.js.map +1 -0
- package/dist/view/utils/get-render/index.js +4 -0
- package/dist/view/utils/get-render/index.js.map +1 -0
- package/dist/view/utils/get-render/server.js +60 -0
- package/dist/view/utils/get-render/server.js.map +1 -0
- package/dist/view/utils/index.js +3 -0
- package/dist/view/utils/index.js.map +1 -0
- package/dist/view/view.js +10 -0
- package/dist/view/view.js.map +1 -0
- package/package.json +41 -0
- package/resource/default-index.html +11 -0
- package/src/browser/index.ts +7 -0
- package/src/cli/dev-server.ts +66 -0
- package/src/cli/index.ts +122 -0
- package/src/cli/types.ts +7 -0
- package/src/cli-helper.ts +5 -0
- package/src/index.ts +24 -0
- package/src/interceptor/index.ts +26 -0
- package/src/interceptor/middleware-to-interceptor/index.ts +29 -0
- package/src/interceptor/middleware-to-interceptor/mock-res.ts +255 -0
- package/src/interceptor/middleware-to-interceptor/mook-req.ts +218 -0
- package/src/interceptor/types.ts +7 -0
- package/src/params/index.ts +12 -0
- package/src/request/index.ts +65 -0
- package/src/return-types/index.ts +1 -0
- package/src/return-types/response-with-meta.ts +17 -0
- package/src/route/index.ts +43 -0
- package/src/route/types.ts +11 -0
- package/src/server/body/helper.ts +110 -0
- package/src/server/body/json.ts +217 -0
- package/src/server/body/types.ts +6 -0
- package/src/server/dump-api-type.ts +64 -0
- package/src/server/index.ts +113 -0
- package/src/server/types.ts +11 -0
- package/src/server/utils/pass-through-readable.ts +10 -0
- package/src/view/const.ts +1 -0
- package/src/view/data-context/conetext.ts +59 -0
- package/src/view/data-context/index.ts +18 -0
- package/src/view/html/create-element.ts +20 -0
- package/src/view/html/index.ts +3 -0
- package/src/view/html/parse-html-to-v-dom.ts +348 -0
- package/src/view/html/render-v-dom-to-string.ts +79 -0
- package/src/view/html/types.ts +32 -0
- package/src/view/index.ts +6 -0
- package/src/view/layout.ts +20 -0
- package/src/view/render/html-render.ts +21 -0
- package/src/view/render/index.ts +2 -0
- package/src/view/render/render.ts +225 -0
- package/src/view/render/sf-v-dom-render.ts +34 -0
- package/src/view/types.ts +18 -0
- package/src/view/utils/find-route-dom.ts +19 -0
- package/src/view/utils/get-render/client.ts +76 -0
- package/src/view/utils/get-render/common.ts +113 -0
- package/src/view/utils/get-render/index.ts +3 -0
- package/src/view/utils/get-render/server.ts +71 -0
- package/src/view/utils/index.ts +2 -0
- package/src/view/view.ts +7 -0
- package/test/body.test.ts +29 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 基于txml根据需要进行调整
|
|
3
|
+
*/
|
|
4
|
+
import { HTMLVElement, HTMLVNode, VNodeType } from "./types.js";
|
|
5
|
+
|
|
6
|
+
const openBracket = "<";
|
|
7
|
+
/**
|
|
8
|
+
* <
|
|
9
|
+
*/
|
|
10
|
+
const openBracketCC = "<".charCodeAt(0);
|
|
11
|
+
const closeBracket = ">";
|
|
12
|
+
/**
|
|
13
|
+
* >
|
|
14
|
+
*/
|
|
15
|
+
const closeBracketCC = ">".charCodeAt(0);
|
|
16
|
+
const minusCC = "-".charCodeAt(0);
|
|
17
|
+
/**
|
|
18
|
+
* /
|
|
19
|
+
*/
|
|
20
|
+
const slashCC = "/".charCodeAt(0);
|
|
21
|
+
/**
|
|
22
|
+
* ?
|
|
23
|
+
*/
|
|
24
|
+
const questionMarkCC = "?".charCodeAt(0);
|
|
25
|
+
/**
|
|
26
|
+
* !
|
|
27
|
+
*/
|
|
28
|
+
const exclamationCC = "!".charCodeAt(0);
|
|
29
|
+
/**
|
|
30
|
+
* '
|
|
31
|
+
*/
|
|
32
|
+
const singleQuoteCC = "'".charCodeAt(0);
|
|
33
|
+
/**
|
|
34
|
+
* "
|
|
35
|
+
*/
|
|
36
|
+
const doubleQuoteCC = '"'.charCodeAt(0);
|
|
37
|
+
/**
|
|
38
|
+
* =
|
|
39
|
+
*/
|
|
40
|
+
const equalSignCC = "=".charCodeAt(0);
|
|
41
|
+
/**
|
|
42
|
+
* [
|
|
43
|
+
*/
|
|
44
|
+
const openCornerBracketCC = "[".charCodeAt(0);
|
|
45
|
+
/**
|
|
46
|
+
* ]
|
|
47
|
+
*/
|
|
48
|
+
const closeCornerBracketCC = "]".charCodeAt(0);
|
|
49
|
+
/**
|
|
50
|
+
* ?
|
|
51
|
+
*/
|
|
52
|
+
const questionCC = "?".charCodeAt(0);
|
|
53
|
+
|
|
54
|
+
const nameSpacer = "\r\n\t>/= ";
|
|
55
|
+
|
|
56
|
+
const noChildTag = ["script", "style"];
|
|
57
|
+
|
|
58
|
+
const SelfClosingTags = ["img", "br", "input", "meta", "link", "hr"];
|
|
59
|
+
|
|
60
|
+
export function parseHtmlToVDom(html: string, { keepWhitespace = false } = {}) {
|
|
61
|
+
var pos = 0;
|
|
62
|
+
function parseChildren(tagName: string) {
|
|
63
|
+
var children: HTMLVNode[] = [];
|
|
64
|
+
while (html[pos]) {
|
|
65
|
+
if (html.charCodeAt(pos) == openBracketCC) {
|
|
66
|
+
// 检查是标签
|
|
67
|
+
if (html.charCodeAt(pos + 1) === slashCC) {
|
|
68
|
+
// 检查是否是关闭标签
|
|
69
|
+
var closeStart = pos + 2;
|
|
70
|
+
pos = html.indexOf(closeBracket, pos);
|
|
71
|
+
|
|
72
|
+
var closeTag = html.substring(closeStart, pos);
|
|
73
|
+
if (closeTag.indexOf(tagName) == -1) {
|
|
74
|
+
// 如果不是关闭当前标签则报错
|
|
75
|
+
var parsedText = html.substring(0, pos).split("\n");
|
|
76
|
+
throw new Error(
|
|
77
|
+
"Unexpected close tag\nLine: " +
|
|
78
|
+
(parsedText.length - 1) +
|
|
79
|
+
"\nColumn: " +
|
|
80
|
+
(parsedText[parsedText.length - 1].length + 1) +
|
|
81
|
+
"\nChar: " +
|
|
82
|
+
html[pos],
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (pos + 1) pos += 1;
|
|
87
|
+
|
|
88
|
+
return children;
|
|
89
|
+
} else if (html.charCodeAt(pos + 1) === exclamationCC) {
|
|
90
|
+
if (
|
|
91
|
+
html.charCodeAt(pos + 2) == minusCC &&
|
|
92
|
+
html.charCodeAt(pos + 3) == minusCC
|
|
93
|
+
) {
|
|
94
|
+
// 评论
|
|
95
|
+
const startCommentPos = pos;
|
|
96
|
+
do {
|
|
97
|
+
pos = html.indexOf(closeBracket, pos + 1);
|
|
98
|
+
} while (
|
|
99
|
+
pos !== -1 &&
|
|
100
|
+
!(
|
|
101
|
+
html.charCodeAt(pos) === closeBracketCC &&
|
|
102
|
+
html.charCodeAt(pos - 1) == minusCC &&
|
|
103
|
+
html.charCodeAt(pos - 2) == minusCC &&
|
|
104
|
+
pos != -1
|
|
105
|
+
)
|
|
106
|
+
);
|
|
107
|
+
children.push({
|
|
108
|
+
type: VNodeType.Comment,
|
|
109
|
+
conetnt: html.substring(
|
|
110
|
+
startCommentPos + 4,
|
|
111
|
+
pos === -1 ? undefined : pos - 3,
|
|
112
|
+
),
|
|
113
|
+
});
|
|
114
|
+
if (pos === -1) {
|
|
115
|
+
pos = html.length;
|
|
116
|
+
}
|
|
117
|
+
} else if (
|
|
118
|
+
html.charCodeAt(pos + 2) === openCornerBracketCC &&
|
|
119
|
+
html.charCodeAt(pos + 8) === openCornerBracketCC &&
|
|
120
|
+
html.substring(pos + 3, pos + 8).toLowerCase() === "cdata"
|
|
121
|
+
) {
|
|
122
|
+
// cdata
|
|
123
|
+
var cdataEndIndex = html.indexOf("]]>", pos);
|
|
124
|
+
if (cdataEndIndex == -1) {
|
|
125
|
+
// children.push(html.substring(pos + 9));
|
|
126
|
+
pos = html.length;
|
|
127
|
+
} else {
|
|
128
|
+
// children.push(html.substring(pos + 9, cdataEndIndex));
|
|
129
|
+
pos = cdataEndIndex + 3;
|
|
130
|
+
}
|
|
131
|
+
console.warn("cdata is not support now, it will be ignore.");
|
|
132
|
+
continue;
|
|
133
|
+
} else {
|
|
134
|
+
// doctype
|
|
135
|
+
const startDoctype = pos;
|
|
136
|
+
pos += 2;
|
|
137
|
+
var encapsuled = false;
|
|
138
|
+
while (
|
|
139
|
+
(html.charCodeAt(pos) !== closeBracketCC ||
|
|
140
|
+
encapsuled === true) &&
|
|
141
|
+
html[pos]
|
|
142
|
+
) {
|
|
143
|
+
if (html.charCodeAt(pos) === openCornerBracketCC) {
|
|
144
|
+
encapsuled = true;
|
|
145
|
+
} else if (
|
|
146
|
+
encapsuled === true &&
|
|
147
|
+
html.charCodeAt(pos) === closeCornerBracketCC
|
|
148
|
+
) {
|
|
149
|
+
encapsuled = false;
|
|
150
|
+
}
|
|
151
|
+
pos++;
|
|
152
|
+
}
|
|
153
|
+
children.push({
|
|
154
|
+
type: VNodeType.Outher,
|
|
155
|
+
text: html.substring(startDoctype, pos + 1),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
pos++;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
var node = parseNode();
|
|
162
|
+
// XML能力,暂时不保留
|
|
163
|
+
// if (skipXmlDeclaration && isXmlDeclarationTag(node.tagName)) {
|
|
164
|
+
// continue;
|
|
165
|
+
// }
|
|
166
|
+
children.push(node);
|
|
167
|
+
} else {
|
|
168
|
+
var text = parseText();
|
|
169
|
+
if (keepWhitespace) {
|
|
170
|
+
if (text.length > 0) {
|
|
171
|
+
children.push(text);
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
var trimmed = text.trim();
|
|
175
|
+
if (trimmed.length > 0) {
|
|
176
|
+
children.push(trimmed);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
pos++;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return children;
|
|
183
|
+
}
|
|
184
|
+
function parseName() {
|
|
185
|
+
var start = pos;
|
|
186
|
+
while (nameSpacer.indexOf(html[pos]) === -1 && html[pos]) {
|
|
187
|
+
pos++;
|
|
188
|
+
}
|
|
189
|
+
return html.slice(start, pos);
|
|
190
|
+
}
|
|
191
|
+
function parseString() {
|
|
192
|
+
var startChar = html[pos];
|
|
193
|
+
var startpos = pos + 1;
|
|
194
|
+
pos = html.indexOf(startChar, startpos);
|
|
195
|
+
var value = html.slice(startpos, pos);
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
function parseNode(): HTMLVElement {
|
|
199
|
+
pos++;
|
|
200
|
+
const tagName = parseName();
|
|
201
|
+
const isProcessingInstruction = tagName[0] === "?";
|
|
202
|
+
const instructionContentStart = pos;
|
|
203
|
+
const attributes: Record<string, string | null> = {};
|
|
204
|
+
let children: HTMLVNode[] = [];
|
|
205
|
+
|
|
206
|
+
// parsing attributes
|
|
207
|
+
while (
|
|
208
|
+
html[pos] &&
|
|
209
|
+
html.charCodeAt(pos) !== closeBracketCC &&
|
|
210
|
+
!(
|
|
211
|
+
isProcessingInstruction &&
|
|
212
|
+
html.charCodeAt(pos) === questionMarkCC &&
|
|
213
|
+
html.charCodeAt(pos + 1) === closeBracketCC
|
|
214
|
+
)
|
|
215
|
+
) {
|
|
216
|
+
var c = html.charCodeAt(pos);
|
|
217
|
+
if ((c > 64 && c < 91) || (c > 96 && c < 123)) {
|
|
218
|
+
var name = parseName();
|
|
219
|
+
var value: string | null = null;
|
|
220
|
+
|
|
221
|
+
// Skip whitespace after the attribute name.
|
|
222
|
+
while (
|
|
223
|
+
html.charCodeAt(pos) === 32 ||
|
|
224
|
+
html.charCodeAt(pos) === 9 ||
|
|
225
|
+
html.charCodeAt(pos) === 10 ||
|
|
226
|
+
html.charCodeAt(pos) === 13
|
|
227
|
+
) {
|
|
228
|
+
pos++;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (html.charCodeAt(pos) === equalSignCC) {
|
|
232
|
+
pos++;
|
|
233
|
+
|
|
234
|
+
// Skip whitespace after '='.
|
|
235
|
+
while (
|
|
236
|
+
html.charCodeAt(pos) === 32 ||
|
|
237
|
+
html.charCodeAt(pos) === 9 ||
|
|
238
|
+
html.charCodeAt(pos) === 10 ||
|
|
239
|
+
html.charCodeAt(pos) === 13
|
|
240
|
+
) {
|
|
241
|
+
pos++;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
var code = html.charCodeAt(pos);
|
|
245
|
+
if (code === singleQuoteCC || code === doubleQuoteCC) {
|
|
246
|
+
value = parseString();
|
|
247
|
+
if (pos === -1) {
|
|
248
|
+
return {
|
|
249
|
+
type: VNodeType.Element,
|
|
250
|
+
tagName,
|
|
251
|
+
attributes,
|
|
252
|
+
children,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
} else if (code && code !== closeBracketCC) {
|
|
256
|
+
// HTML-style unquoted attribute value: read until whitespace, '/', or '>'.
|
|
257
|
+
var valueStart = pos;
|
|
258
|
+
while (html[pos] && nameSpacer.indexOf(html[pos]) === -1) {
|
|
259
|
+
pos++;
|
|
260
|
+
}
|
|
261
|
+
value = html.slice(valueStart, pos);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
attributes[name] = value;
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
pos++;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const isExplicitSelfClosed =
|
|
271
|
+
!isProcessingInstruction && html.charCodeAt(pos - 1) === slashCC;
|
|
272
|
+
|
|
273
|
+
if (isProcessingInstruction) {
|
|
274
|
+
var instructionContent = html.slice(instructionContentStart, pos).trim();
|
|
275
|
+
|
|
276
|
+
if (
|
|
277
|
+
instructionContent.length > 0 &&
|
|
278
|
+
Object.keys(attributes).length === 0
|
|
279
|
+
) {
|
|
280
|
+
children = [instructionContent];
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (
|
|
284
|
+
html.charCodeAt(pos) === questionMarkCC &&
|
|
285
|
+
html.charCodeAt(pos + 1) === closeBracketCC
|
|
286
|
+
) {
|
|
287
|
+
pos += 2;
|
|
288
|
+
} else if (html.charCodeAt(pos) === closeBracketCC) {
|
|
289
|
+
pos += 1;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
type: VNodeType.Element,
|
|
294
|
+
tagName,
|
|
295
|
+
attributes,
|
|
296
|
+
children,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// optional parsing of children
|
|
301
|
+
if (
|
|
302
|
+
html.charCodeAt(pos - 1) !== slashCC &&
|
|
303
|
+
html.charCodeAt(pos - 1) !== questionCC
|
|
304
|
+
) {
|
|
305
|
+
if (noChildTag.includes(tagName)) {
|
|
306
|
+
// TODO: 这里其实要检查是否在字符串中
|
|
307
|
+
const endTag = `</${tagName}>`;
|
|
308
|
+
var start = pos + 1;
|
|
309
|
+
pos = html.indexOf(endTag, pos);
|
|
310
|
+
children = [html.slice(start, pos)];
|
|
311
|
+
pos += endTag.length;
|
|
312
|
+
} else if (SelfClosingTags.indexOf(tagName) === -1) {
|
|
313
|
+
pos++;
|
|
314
|
+
children = parseChildren(tagName);
|
|
315
|
+
} else {
|
|
316
|
+
pos++;
|
|
317
|
+
}
|
|
318
|
+
} else {
|
|
319
|
+
pos++;
|
|
320
|
+
}
|
|
321
|
+
const node: HTMLVElement = {
|
|
322
|
+
type: VNodeType.Element,
|
|
323
|
+
tagName,
|
|
324
|
+
attributes,
|
|
325
|
+
children,
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
if (isExplicitSelfClosed) {
|
|
329
|
+
Object.defineProperty(node, "selfClosed", {
|
|
330
|
+
value: true,
|
|
331
|
+
enumerable: false,
|
|
332
|
+
writable: true,
|
|
333
|
+
configurable: true,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return node;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function parseText() {
|
|
341
|
+
var start = pos;
|
|
342
|
+
pos = html.indexOf(openBracket, pos) - 1;
|
|
343
|
+
if (pos === -2) pos = html.length;
|
|
344
|
+
var text = html.slice(start, pos + 1);
|
|
345
|
+
return text;
|
|
346
|
+
}
|
|
347
|
+
return parseChildren("");
|
|
348
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { HTMLVElement, HTMLVNode, VNodeType } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export function renderVDomToString(
|
|
4
|
+
vDom: HTMLVNode | HTMLVNode[],
|
|
5
|
+
config?: {
|
|
6
|
+
customizeRender?: (
|
|
7
|
+
dom: HTMLVNode,
|
|
8
|
+
) => null | undefined | ((dom: HTMLVNode) => string);
|
|
9
|
+
customizeChildrenRender?: (
|
|
10
|
+
dom: HTMLVElement,
|
|
11
|
+
) => null | undefined | ((dom: HTMLVElement, raw: () => string) => string);
|
|
12
|
+
},
|
|
13
|
+
): string;
|
|
14
|
+
export function renderVDomToString(
|
|
15
|
+
vDom: HTMLVNode | HTMLVNode[],
|
|
16
|
+
config: {
|
|
17
|
+
customizeRender?: (
|
|
18
|
+
dom: HTMLVNode,
|
|
19
|
+
) => null | undefined | ((dom: HTMLVNode) => string | Promise<string>);
|
|
20
|
+
customizeChildrenRender?: (
|
|
21
|
+
dom: HTMLVElement,
|
|
22
|
+
) =>
|
|
23
|
+
| null
|
|
24
|
+
| undefined
|
|
25
|
+
| ((
|
|
26
|
+
dom: HTMLVElement,
|
|
27
|
+
raw: () => string | Promise<string>,
|
|
28
|
+
) => string | Promise<string>);
|
|
29
|
+
},
|
|
30
|
+
): string | Promise<string>;
|
|
31
|
+
export function renderVDomToString(
|
|
32
|
+
vDom: HTMLVNode | HTMLVNode[],
|
|
33
|
+
config: {
|
|
34
|
+
customizeRender?: (
|
|
35
|
+
dom: HTMLVNode,
|
|
36
|
+
) => null | undefined | ((dom: HTMLVNode) => string | Promise<string>);
|
|
37
|
+
customizeChildrenRender?: (
|
|
38
|
+
dom: HTMLVElement,
|
|
39
|
+
) =>
|
|
40
|
+
| null
|
|
41
|
+
| undefined
|
|
42
|
+
| ((dom: HTMLVElement, raw: () => any) => string | Promise<string>);
|
|
43
|
+
} = {},
|
|
44
|
+
): string | Promise<string> {
|
|
45
|
+
if (Array.isArray(vDom)) {
|
|
46
|
+
const allDom = vDom.map((d) => renderVDomToString(d, config));
|
|
47
|
+
const render = (res: string[]) => res.join("");
|
|
48
|
+
if (allDom.some((i) => i instanceof Promise))
|
|
49
|
+
return Promise.all(allDom).then(render);
|
|
50
|
+
return render(allDom as string[]);
|
|
51
|
+
}
|
|
52
|
+
const customizeRender = config.customizeRender?.(vDom);
|
|
53
|
+
if (customizeRender) return customizeRender(vDom);
|
|
54
|
+
if (typeof vDom === "string") return vDom;
|
|
55
|
+
switch (vDom.type) {
|
|
56
|
+
case VNodeType.Element:
|
|
57
|
+
const attt = Object.entries(vDom.attributes)
|
|
58
|
+
.map(([k, v]) => ` ${k}=${JSON.stringify(v)}`)
|
|
59
|
+
.join("");
|
|
60
|
+
const customizeChildrenRender = config.customizeChildrenRender?.(vDom);
|
|
61
|
+
const children = customizeChildrenRender
|
|
62
|
+
? customizeChildrenRender(vDom, () =>
|
|
63
|
+
renderVDomToString(vDom.children, config),
|
|
64
|
+
)
|
|
65
|
+
: renderVDomToString(vDom.children, config);
|
|
66
|
+
const render = (children: string) =>
|
|
67
|
+
`<${vDom.tagName}${attt}>${children}</${vDom.tagName}>`;
|
|
68
|
+
if (children instanceof Promise) {
|
|
69
|
+
return children.then(render);
|
|
70
|
+
}
|
|
71
|
+
return render(children);
|
|
72
|
+
case VNodeType.Comment:
|
|
73
|
+
return `<!--${vDom.conetnt}-->`;
|
|
74
|
+
case VNodeType.Text:
|
|
75
|
+
return vDom.conetnt;
|
|
76
|
+
case VNodeType.Outher:
|
|
77
|
+
return vDom.text;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export enum VNodeType {
|
|
2
|
+
Element = 1,
|
|
3
|
+
Comment = 2,
|
|
4
|
+
Text = 3,
|
|
5
|
+
Outher = 999,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface HTMLVElement {
|
|
9
|
+
type: VNodeType.Element;
|
|
10
|
+
tagName: string;
|
|
11
|
+
attributes: Record<string, any>;
|
|
12
|
+
children: HTMLVNode[];
|
|
13
|
+
}
|
|
14
|
+
export interface HTMLVComment {
|
|
15
|
+
type: VNodeType.Comment;
|
|
16
|
+
conetnt: string;
|
|
17
|
+
}
|
|
18
|
+
export interface HTMLVText {
|
|
19
|
+
type: VNodeType.Text;
|
|
20
|
+
conetnt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface OtherVElement {
|
|
23
|
+
type: VNodeType.Outher;
|
|
24
|
+
text: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type HTMLVNode =
|
|
28
|
+
| OtherVElement
|
|
29
|
+
| HTMLVElement
|
|
30
|
+
| HTMLVComment
|
|
31
|
+
| HTMLVText
|
|
32
|
+
| string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getMetadata, initMetadata } from "@thestarweb/star-framework-utils";
|
|
2
|
+
import { IRender } from "./render/render.js";
|
|
3
|
+
import { ViewInfo, ViewMeta } from "./types.js";
|
|
4
|
+
|
|
5
|
+
const mateKey = "$sf:app-web:view:layout";
|
|
6
|
+
|
|
7
|
+
export function Layout(
|
|
8
|
+
render: IRender,
|
|
9
|
+
meta?: ViewInfo<ViewMeta>["meta"],
|
|
10
|
+
): ClassDecorator {
|
|
11
|
+
return function (target) {
|
|
12
|
+
initMetadata<ViewInfo<ViewMeta>[]>(target, mateKey, undefined, []).push({
|
|
13
|
+
render,
|
|
14
|
+
meta,
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function getLayots(target: any) {
|
|
19
|
+
return getMetadata<ViewInfo<ViewMeta>[]>(target, mateKey, undefined, []);
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { parseHtmlToVDom } from "../html/index.js";
|
|
2
|
+
import { SFVDomRender } from "./sf-v-dom-render.js";
|
|
3
|
+
|
|
4
|
+
export class HTMLRender extends SFVDomRender {
|
|
5
|
+
constructor(
|
|
6
|
+
private readonly htmlFn:
|
|
7
|
+
| string
|
|
8
|
+
| (() => Promise<string | { default: string }>),
|
|
9
|
+
) {
|
|
10
|
+
super(async () => {
|
|
11
|
+
if (typeof this.htmlFn === "function") {
|
|
12
|
+
const res = await this.htmlFn();
|
|
13
|
+
this.html = typeof res === "string" ? res : res.default;
|
|
14
|
+
} else {
|
|
15
|
+
this.html = this.htmlFn;
|
|
16
|
+
}
|
|
17
|
+
return parseHtmlToVDom(this.html);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
private html = "";
|
|
21
|
+
}
|