@weapp-vite/web 0.0.2
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 +51 -0
- package/dist/index.cjs +15772 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +15747 -0
- package/dist/plugin-D_a0z32j.d.cts +24 -0
- package/dist/plugin-D_a0z32j.d.ts +24 -0
- package/dist/plugin.cjs +14634 -0
- package/dist/plugin.d.cts +2 -0
- package/dist/plugin.d.ts +2 -0
- package/dist/plugin.mjs +14624 -0
- package/dist/runtime/index.cjs +1155 -0
- package/dist/runtime/index.d.cts +89 -0
- package/dist/runtime/index.d.ts +89 -0
- package/dist/runtime/index.mjs +1115 -0
- package/package.json +58 -0
|
@@ -0,0 +1,1115 @@
|
|
|
1
|
+
// src/runtime/component.ts
|
|
2
|
+
var EVENT_TO_DOM = {
|
|
3
|
+
tap: "click",
|
|
4
|
+
input: "input",
|
|
5
|
+
change: "change",
|
|
6
|
+
submit: "submit",
|
|
7
|
+
blur: "blur",
|
|
8
|
+
focus: "focus"
|
|
9
|
+
};
|
|
10
|
+
function hyphenate(name) {
|
|
11
|
+
return name.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`);
|
|
12
|
+
}
|
|
13
|
+
function toCamelCase(name) {
|
|
14
|
+
return name.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
15
|
+
}
|
|
16
|
+
function cloneValue(value) {
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
return value.slice();
|
|
19
|
+
}
|
|
20
|
+
if (value && typeof value === "object") {
|
|
21
|
+
return { ...value };
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
function coerceValue(value, type) {
|
|
26
|
+
if (type === Boolean) {
|
|
27
|
+
if (value === "" || value === true) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (value === void 0 || value === null || value === false) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
if (typeof value === "string") {
|
|
34
|
+
return value !== "false";
|
|
35
|
+
}
|
|
36
|
+
return Boolean(value);
|
|
37
|
+
}
|
|
38
|
+
if (type === Number) {
|
|
39
|
+
if (value === void 0 || value === null) {
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
const numeric = Number(value);
|
|
43
|
+
return Number.isNaN(numeric) ? value : numeric;
|
|
44
|
+
}
|
|
45
|
+
if (type === Object || type === Array) {
|
|
46
|
+
if (value === void 0 || value === null) {
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
if (typeof value === "string") {
|
|
50
|
+
try {
|
|
51
|
+
return JSON.parse(value);
|
|
52
|
+
} catch {
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
function bindRuntimeEvents(root, methods, instance) {
|
|
61
|
+
if (typeof document === "undefined") {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
|
|
65
|
+
while (walker.nextNode()) {
|
|
66
|
+
const element = walker.currentNode;
|
|
67
|
+
for (const attribute of element.getAttributeNames()) {
|
|
68
|
+
if (!attribute.startsWith("data-wx-on-")) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const handlerName = element.getAttribute(attribute);
|
|
72
|
+
if (!handlerName) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const eventName = attribute.slice("data-wx-on-".length);
|
|
76
|
+
const handler = methods[handlerName];
|
|
77
|
+
if (!handler) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const domEvent = EVENT_TO_DOM[eventName] ?? eventName;
|
|
81
|
+
element.addEventListener(domEvent, (nativeEvent) => {
|
|
82
|
+
const dataset = { ...element.dataset };
|
|
83
|
+
const syntheticEvent = {
|
|
84
|
+
type: eventName,
|
|
85
|
+
timeStamp: nativeEvent.timeStamp,
|
|
86
|
+
detail: nativeEvent.detail ?? nativeEvent.data ?? void 0,
|
|
87
|
+
target: {
|
|
88
|
+
dataset
|
|
89
|
+
},
|
|
90
|
+
currentTarget: {
|
|
91
|
+
dataset
|
|
92
|
+
},
|
|
93
|
+
originalEvent: nativeEvent
|
|
94
|
+
};
|
|
95
|
+
handler.call(instance, syntheticEvent);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function defineComponent(tagName, options) {
|
|
101
|
+
if (!options || typeof options !== "object") {
|
|
102
|
+
throw new TypeError("[@weapp-vite/web] defineComponent \u9700\u8981\u63D0\u4F9B\u914D\u7F6E\u5BF9\u8C61\u3002");
|
|
103
|
+
}
|
|
104
|
+
if (customElements.get(tagName)) {
|
|
105
|
+
return customElements.get(tagName);
|
|
106
|
+
}
|
|
107
|
+
const { template, style = "", component = {} } = options;
|
|
108
|
+
if (!template) {
|
|
109
|
+
throw new Error("[@weapp-vite/web] defineComponent \u9700\u8981\u63D0\u4F9B\u6A21\u677F\u6E32\u67D3\u51FD\u6570\u3002");
|
|
110
|
+
}
|
|
111
|
+
const propertyEntries = Object.entries(component.properties ?? {});
|
|
112
|
+
const observedAttributes = propertyEntries.map(([name]) => hyphenate(name));
|
|
113
|
+
const defaultPropertyValues = propertyEntries.reduce((acc, [name, prop]) => {
|
|
114
|
+
if (Object.prototype.hasOwnProperty.call(prop, "value")) {
|
|
115
|
+
acc[name] = cloneValue(prop.value);
|
|
116
|
+
} else {
|
|
117
|
+
acc[name] = void 0;
|
|
118
|
+
}
|
|
119
|
+
return acc;
|
|
120
|
+
}, {});
|
|
121
|
+
const lifetimes = component.lifetimes ?? {};
|
|
122
|
+
class WeappWebComponent extends HTMLElement {
|
|
123
|
+
static get observedAttributes() {
|
|
124
|
+
return observedAttributes;
|
|
125
|
+
}
|
|
126
|
+
#state;
|
|
127
|
+
#properties;
|
|
128
|
+
#methods;
|
|
129
|
+
#shadow;
|
|
130
|
+
#contentRoot;
|
|
131
|
+
#styleElement;
|
|
132
|
+
#isMounted = false;
|
|
133
|
+
constructor() {
|
|
134
|
+
super();
|
|
135
|
+
const dataOption = typeof component.data === "function" ? component.data() : component.data ?? {};
|
|
136
|
+
this.#properties = { ...defaultPropertyValues };
|
|
137
|
+
this.#state = { ...cloneValue(this.#properties), ...cloneValue(dataOption) };
|
|
138
|
+
this.#shadow = this.attachShadow({ mode: "open" });
|
|
139
|
+
if (style) {
|
|
140
|
+
this.#styleElement = document.createElement("style");
|
|
141
|
+
this.#styleElement.textContent = style;
|
|
142
|
+
this.#shadow.append(this.#styleElement);
|
|
143
|
+
}
|
|
144
|
+
this.#contentRoot = document.createElement("div");
|
|
145
|
+
this.#contentRoot.setAttribute("part", "content");
|
|
146
|
+
this.#shadow.append(this.#contentRoot);
|
|
147
|
+
this.#methods = {};
|
|
148
|
+
for (const [name, fn] of Object.entries(component.methods ?? {})) {
|
|
149
|
+
if (typeof fn === "function") {
|
|
150
|
+
this.#methods[name] = fn.bind(this);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
for (const [propName] of propertyEntries) {
|
|
154
|
+
Object.defineProperty(this, propName, {
|
|
155
|
+
configurable: true,
|
|
156
|
+
enumerable: true,
|
|
157
|
+
get: () => this.#state[propName],
|
|
158
|
+
set: (value) => {
|
|
159
|
+
this.#setProperty(propName, value);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
lifetimes.created?.call(this);
|
|
164
|
+
}
|
|
165
|
+
get data() {
|
|
166
|
+
return this.#state;
|
|
167
|
+
}
|
|
168
|
+
get properties() {
|
|
169
|
+
return this.#properties;
|
|
170
|
+
}
|
|
171
|
+
setData(patch) {
|
|
172
|
+
this.#applyDataPatch(patch);
|
|
173
|
+
}
|
|
174
|
+
triggerEvent(name, detail) {
|
|
175
|
+
this.dispatchEvent(new CustomEvent(name, {
|
|
176
|
+
detail,
|
|
177
|
+
bubbles: true,
|
|
178
|
+
composed: true
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
connectedCallback() {
|
|
182
|
+
this.#applyAttributes();
|
|
183
|
+
this.#render();
|
|
184
|
+
lifetimes.attached?.call(this);
|
|
185
|
+
this.#isMounted = true;
|
|
186
|
+
lifetimes.ready?.call(this);
|
|
187
|
+
}
|
|
188
|
+
disconnectedCallback() {
|
|
189
|
+
this.#isMounted = false;
|
|
190
|
+
lifetimes.detached?.call(this);
|
|
191
|
+
}
|
|
192
|
+
attributeChangedCallback(attrName, _oldValue, newValue) {
|
|
193
|
+
const propName = toCamelCase(attrName);
|
|
194
|
+
if (!Object.prototype.hasOwnProperty.call(this.#properties, propName)) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const propOption = component.properties?.[propName];
|
|
198
|
+
const coerced = coerceValue(newValue, propOption?.type);
|
|
199
|
+
this.#setProperty(propName, coerced);
|
|
200
|
+
}
|
|
201
|
+
#applyAttributes() {
|
|
202
|
+
for (const attr of this.attributes) {
|
|
203
|
+
this.attributeChangedCallback(attr.name, null, attr.value);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
#applyDataPatch(patch) {
|
|
207
|
+
if (!patch || typeof patch !== "object") {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
let changed = false;
|
|
211
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
212
|
+
if (this.#state[key] !== value) {
|
|
213
|
+
const oldValue = this.#state[key];
|
|
214
|
+
this.#state[key] = value;
|
|
215
|
+
if (Object.prototype.hasOwnProperty.call(this.#properties, key)) {
|
|
216
|
+
this.#properties[key] = value;
|
|
217
|
+
component.properties?.[key]?.observer?.call(this, value, oldValue);
|
|
218
|
+
}
|
|
219
|
+
changed = true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (changed) {
|
|
223
|
+
this.#render();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
#setProperty(name, value) {
|
|
227
|
+
const propOption = component.properties?.[name];
|
|
228
|
+
const coerced = coerceValue(value, propOption?.type);
|
|
229
|
+
const oldValue = this.#properties[name];
|
|
230
|
+
if (oldValue === coerced) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this.#properties[name] = coerced;
|
|
234
|
+
this.#state[name] = coerced;
|
|
235
|
+
if (this.#isMounted) {
|
|
236
|
+
this.#render();
|
|
237
|
+
}
|
|
238
|
+
propOption?.observer?.call(this, coerced, oldValue);
|
|
239
|
+
}
|
|
240
|
+
#render() {
|
|
241
|
+
const html = template(this.#state);
|
|
242
|
+
if (!this.#contentRoot) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
this.#contentRoot.innerHTML = html;
|
|
246
|
+
bindRuntimeEvents(this.#contentRoot, this.#methods, this);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
customElements.define(tagName, WeappWebComponent);
|
|
250
|
+
return WeappWebComponent;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/runtime/polyfill.ts
|
|
254
|
+
var pageRegistry = /* @__PURE__ */ new Map();
|
|
255
|
+
var componentRegistry = /* @__PURE__ */ new Map();
|
|
256
|
+
var navigationHistory = [];
|
|
257
|
+
var pageOrder = [];
|
|
258
|
+
var activeEntry;
|
|
259
|
+
var appInstance;
|
|
260
|
+
var appLaunched = false;
|
|
261
|
+
var ROUTE_META_SYMBOL = Symbol("@weapp-vite/web:route-meta");
|
|
262
|
+
var PAGE_STATE_SYMBOL = Symbol("@weapp-vite/web:page-state");
|
|
263
|
+
var PAGE_LIFECYCLE_KEYS = /* @__PURE__ */ new Set(["onLoad", "onReady", "onShow", "onHide", "onUnload"]);
|
|
264
|
+
var RESERVED_PAGE_METHOD_KEYS = /* @__PURE__ */ new Set([
|
|
265
|
+
"data",
|
|
266
|
+
"methods",
|
|
267
|
+
"lifetimes",
|
|
268
|
+
"properties",
|
|
269
|
+
"behaviors",
|
|
270
|
+
"options",
|
|
271
|
+
"observers",
|
|
272
|
+
"mixins",
|
|
273
|
+
...PAGE_LIFECYCLE_KEYS
|
|
274
|
+
]);
|
|
275
|
+
var RESERVED_COMPONENT_METHOD_KEYS = /* @__PURE__ */ new Set([
|
|
276
|
+
"data",
|
|
277
|
+
"methods",
|
|
278
|
+
"lifetimes",
|
|
279
|
+
"properties",
|
|
280
|
+
"behaviors",
|
|
281
|
+
"options",
|
|
282
|
+
"observers",
|
|
283
|
+
"mixins"
|
|
284
|
+
]);
|
|
285
|
+
function slugify(id, prefix) {
|
|
286
|
+
const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
287
|
+
return `${prefix}-${normalized || "index"}`;
|
|
288
|
+
}
|
|
289
|
+
function ensureDocumentReady(callback) {
|
|
290
|
+
if (typeof document === "undefined") {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (document.readyState === "loading") {
|
|
294
|
+
document.addEventListener("DOMContentLoaded", () => callback(), { once: true });
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
callback();
|
|
298
|
+
}
|
|
299
|
+
function ensureContainer() {
|
|
300
|
+
if (typeof document === "undefined") {
|
|
301
|
+
return void 0;
|
|
302
|
+
}
|
|
303
|
+
return document.querySelector("#app") ?? document.body;
|
|
304
|
+
}
|
|
305
|
+
function cloneLifetimes(source) {
|
|
306
|
+
if (!source) {
|
|
307
|
+
return void 0;
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
...source
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function isRecord(value) {
|
|
314
|
+
return typeof value === "object" && value !== null;
|
|
315
|
+
}
|
|
316
|
+
function isMethodHandler(value) {
|
|
317
|
+
return typeof value === "function";
|
|
318
|
+
}
|
|
319
|
+
function normalizeMethodBag(source, reserved) {
|
|
320
|
+
const methods = {};
|
|
321
|
+
const sourceMethods = isRecord(source?.methods) ? source?.methods : void 0;
|
|
322
|
+
if (sourceMethods) {
|
|
323
|
+
for (const [key, value] of Object.entries(sourceMethods)) {
|
|
324
|
+
if (isMethodHandler(value)) {
|
|
325
|
+
methods[key] = value;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (source) {
|
|
330
|
+
for (const [key, value] of Object.entries(source)) {
|
|
331
|
+
if (reserved.has(key)) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (isMethodHandler(value) && methods[key] === void 0) {
|
|
335
|
+
methods[key] = value;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return methods;
|
|
340
|
+
}
|
|
341
|
+
function normalizePageOptions(raw) {
|
|
342
|
+
const component = { ...raw ?? {} };
|
|
343
|
+
component.methods = normalizeMethodBag(raw, RESERVED_PAGE_METHOD_KEYS);
|
|
344
|
+
if (raw?.lifetimes) {
|
|
345
|
+
component.lifetimes = cloneLifetimes(raw.lifetimes);
|
|
346
|
+
}
|
|
347
|
+
const hooks = {};
|
|
348
|
+
if (typeof raw?.onLoad === "function") {
|
|
349
|
+
hooks.onLoad = raw.onLoad;
|
|
350
|
+
}
|
|
351
|
+
if (typeof raw?.onReady === "function") {
|
|
352
|
+
hooks.onReady = raw.onReady;
|
|
353
|
+
}
|
|
354
|
+
if (typeof raw?.onShow === "function") {
|
|
355
|
+
hooks.onShow = raw.onShow;
|
|
356
|
+
}
|
|
357
|
+
if (typeof raw?.onHide === "function") {
|
|
358
|
+
hooks.onHide = raw.onHide;
|
|
359
|
+
}
|
|
360
|
+
if (typeof raw?.onUnload === "function") {
|
|
361
|
+
hooks.onUnload = raw.onUnload;
|
|
362
|
+
}
|
|
363
|
+
return { component, hooks };
|
|
364
|
+
}
|
|
365
|
+
function normalizeComponentOptions(raw) {
|
|
366
|
+
const component = { ...raw ?? {} };
|
|
367
|
+
component.methods = normalizeMethodBag(raw, RESERVED_COMPONENT_METHOD_KEYS);
|
|
368
|
+
if (raw?.lifetimes) {
|
|
369
|
+
component.lifetimes = cloneLifetimes(raw.lifetimes);
|
|
370
|
+
}
|
|
371
|
+
return component;
|
|
372
|
+
}
|
|
373
|
+
function getRouteMeta(instance) {
|
|
374
|
+
return instance[ROUTE_META_SYMBOL];
|
|
375
|
+
}
|
|
376
|
+
function getPageState(instance) {
|
|
377
|
+
const target = instance;
|
|
378
|
+
target[PAGE_STATE_SYMBOL] ??= { loaded: false };
|
|
379
|
+
return target[PAGE_STATE_SYMBOL];
|
|
380
|
+
}
|
|
381
|
+
function ensureAppLaunched(entry) {
|
|
382
|
+
if (!appInstance || appLaunched) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const launchOptions = {
|
|
386
|
+
path: entry.id,
|
|
387
|
+
scene: 0,
|
|
388
|
+
query: entry.query,
|
|
389
|
+
referrerInfo: {}
|
|
390
|
+
};
|
|
391
|
+
if (typeof appInstance.onLaunch === "function") {
|
|
392
|
+
appInstance.onLaunch(launchOptions);
|
|
393
|
+
}
|
|
394
|
+
if (typeof appInstance.onShow === "function") {
|
|
395
|
+
appInstance.onShow(launchOptions);
|
|
396
|
+
}
|
|
397
|
+
appLaunched = true;
|
|
398
|
+
}
|
|
399
|
+
function mountEntry(entry) {
|
|
400
|
+
const record = pageRegistry.get(entry.id);
|
|
401
|
+
if (!record) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
ensureDocumentReady(() => {
|
|
405
|
+
const container = ensureContainer();
|
|
406
|
+
if (!container) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
while (container.childNodes.length) {
|
|
410
|
+
container.removeChild(container.childNodes[0]);
|
|
411
|
+
}
|
|
412
|
+
const element = document.createElement(record.tag);
|
|
413
|
+
element[ROUTE_META_SYMBOL] = {
|
|
414
|
+
id: entry.id,
|
|
415
|
+
query: entry.query,
|
|
416
|
+
entry
|
|
417
|
+
};
|
|
418
|
+
container.append(element);
|
|
419
|
+
activeEntry = entry;
|
|
420
|
+
ensureAppLaunched(entry);
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
function pushEntry(id, query) {
|
|
424
|
+
if (!pageRegistry.has(id)) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const entry = { id, query };
|
|
428
|
+
navigationHistory.push(entry);
|
|
429
|
+
mountEntry(entry);
|
|
430
|
+
}
|
|
431
|
+
function replaceEntry(id, query) {
|
|
432
|
+
if (!pageRegistry.has(id)) {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const entry = { id, query };
|
|
436
|
+
if (navigationHistory.length) {
|
|
437
|
+
navigationHistory[navigationHistory.length - 1] = entry;
|
|
438
|
+
} else {
|
|
439
|
+
navigationHistory.push(entry);
|
|
440
|
+
}
|
|
441
|
+
mountEntry(entry);
|
|
442
|
+
}
|
|
443
|
+
function relaunchEntry(id, query) {
|
|
444
|
+
navigationHistory.length = 0;
|
|
445
|
+
pushEntry(id, query);
|
|
446
|
+
}
|
|
447
|
+
var PAGE_TEMPLATE_EXTENSIONS = [".wxml", ".axml", ".swan", ".ttml", ".qml", ".ksml", ".xhsml", ".html"];
|
|
448
|
+
function stripTemplateExtension(id) {
|
|
449
|
+
const lowered = id.toLowerCase();
|
|
450
|
+
for (const ext of PAGE_TEMPLATE_EXTENSIONS) {
|
|
451
|
+
if (lowered.endsWith(ext)) {
|
|
452
|
+
return id.slice(0, -ext.length);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return id;
|
|
456
|
+
}
|
|
457
|
+
function parsePageId(raw) {
|
|
458
|
+
const normalized = raw.replace(/^\//, "");
|
|
459
|
+
return stripTemplateExtension(normalized);
|
|
460
|
+
}
|
|
461
|
+
function parsePageUrl(url) {
|
|
462
|
+
const [path, search = ""] = url.split("?");
|
|
463
|
+
const query = {};
|
|
464
|
+
if (search) {
|
|
465
|
+
const params = new URLSearchParams(search);
|
|
466
|
+
for (const [key, value] of params.entries()) {
|
|
467
|
+
query[key] = value;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return {
|
|
471
|
+
id: parsePageId(path || ""),
|
|
472
|
+
query
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function augmentPageComponentOptions(component, record) {
|
|
476
|
+
const lifetimes = component.lifetimes ?? {};
|
|
477
|
+
const originalCreated = lifetimes?.created;
|
|
478
|
+
const originalAttached = lifetimes?.attached;
|
|
479
|
+
const originalReady = lifetimes?.ready;
|
|
480
|
+
const originalDetached = lifetimes?.detached;
|
|
481
|
+
const enhanced = {
|
|
482
|
+
...component,
|
|
483
|
+
lifetimes: {
|
|
484
|
+
...lifetimes,
|
|
485
|
+
created() {
|
|
486
|
+
originalCreated?.call(this);
|
|
487
|
+
getPageState(this);
|
|
488
|
+
record.instances.add(this);
|
|
489
|
+
},
|
|
490
|
+
attached() {
|
|
491
|
+
originalAttached?.call(this);
|
|
492
|
+
const meta = getRouteMeta(this);
|
|
493
|
+
if (meta?.entry) {
|
|
494
|
+
meta.entry.instance = this;
|
|
495
|
+
}
|
|
496
|
+
const state = getPageState(this);
|
|
497
|
+
if (!state.loaded) {
|
|
498
|
+
record.hooks.onLoad?.call(this, meta?.query ?? {});
|
|
499
|
+
state.loaded = true;
|
|
500
|
+
}
|
|
501
|
+
record.hooks.onShow?.call(this);
|
|
502
|
+
},
|
|
503
|
+
ready() {
|
|
504
|
+
originalReady?.call(this);
|
|
505
|
+
record.hooks.onReady?.call(this);
|
|
506
|
+
},
|
|
507
|
+
detached() {
|
|
508
|
+
originalDetached?.call(this);
|
|
509
|
+
const meta = getRouteMeta(this);
|
|
510
|
+
if (meta?.entry) {
|
|
511
|
+
meta.entry.instance = void 0;
|
|
512
|
+
}
|
|
513
|
+
record.hooks.onHide?.call(this);
|
|
514
|
+
record.hooks.onUnload?.call(this);
|
|
515
|
+
const state = getPageState(this);
|
|
516
|
+
state.loaded = false;
|
|
517
|
+
record.instances.delete(this);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
return enhanced;
|
|
522
|
+
}
|
|
523
|
+
function initializePageRoutes(ids) {
|
|
524
|
+
pageOrder = Array.from(new Set(ids));
|
|
525
|
+
if (!pageOrder.length) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
if (!navigationHistory.length) {
|
|
529
|
+
pushEntry(pageOrder[0], {});
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
function registerPage(options, meta) {
|
|
533
|
+
const tag = slugify(meta.id, "wv-page");
|
|
534
|
+
const template = meta.template ?? (() => "");
|
|
535
|
+
const normalized = normalizePageOptions(options);
|
|
536
|
+
const record = {
|
|
537
|
+
tag,
|
|
538
|
+
hooks: normalized.hooks,
|
|
539
|
+
instances: /* @__PURE__ */ new Set()
|
|
540
|
+
};
|
|
541
|
+
const component = augmentPageComponentOptions(normalized.component, record);
|
|
542
|
+
defineComponent(tag, {
|
|
543
|
+
template,
|
|
544
|
+
style: meta.style,
|
|
545
|
+
component
|
|
546
|
+
});
|
|
547
|
+
pageRegistry.set(meta.id, record);
|
|
548
|
+
return options;
|
|
549
|
+
}
|
|
550
|
+
function registerComponent(options, meta) {
|
|
551
|
+
const tag = slugify(meta.id, "wv-component");
|
|
552
|
+
const template = meta.template ?? (() => "");
|
|
553
|
+
const component = normalizeComponentOptions(options);
|
|
554
|
+
defineComponent(tag, {
|
|
555
|
+
template,
|
|
556
|
+
style: meta.style,
|
|
557
|
+
component
|
|
558
|
+
});
|
|
559
|
+
componentRegistry.set(meta.id, { tag });
|
|
560
|
+
return options;
|
|
561
|
+
}
|
|
562
|
+
function registerApp(options, _meta) {
|
|
563
|
+
const resolved = options ?? {};
|
|
564
|
+
appInstance = resolved;
|
|
565
|
+
appLaunched = false;
|
|
566
|
+
if (!isRecord(appInstance.globalData)) {
|
|
567
|
+
appInstance.globalData = {};
|
|
568
|
+
}
|
|
569
|
+
return options;
|
|
570
|
+
}
|
|
571
|
+
function navigateTo(options) {
|
|
572
|
+
if (!options?.url) {
|
|
573
|
+
return Promise.resolve();
|
|
574
|
+
}
|
|
575
|
+
const { id, query } = parsePageUrl(options.url);
|
|
576
|
+
pushEntry(id, query);
|
|
577
|
+
return Promise.resolve();
|
|
578
|
+
}
|
|
579
|
+
function redirectTo(options) {
|
|
580
|
+
if (!options?.url) {
|
|
581
|
+
return Promise.resolve();
|
|
582
|
+
}
|
|
583
|
+
const { id, query } = parsePageUrl(options.url);
|
|
584
|
+
replaceEntry(id, query);
|
|
585
|
+
return Promise.resolve();
|
|
586
|
+
}
|
|
587
|
+
function reLaunch(options) {
|
|
588
|
+
if (!options?.url) {
|
|
589
|
+
return Promise.resolve();
|
|
590
|
+
}
|
|
591
|
+
const { id, query } = parsePageUrl(options.url);
|
|
592
|
+
relaunchEntry(id, query);
|
|
593
|
+
return Promise.resolve();
|
|
594
|
+
}
|
|
595
|
+
function switchTab(options) {
|
|
596
|
+
return redirectTo(options);
|
|
597
|
+
}
|
|
598
|
+
function navigateBack(options) {
|
|
599
|
+
if (navigationHistory.length <= 1) {
|
|
600
|
+
return Promise.resolve();
|
|
601
|
+
}
|
|
602
|
+
const delta = Math.max(1, options?.delta ?? 1);
|
|
603
|
+
const targetIndex = Math.max(0, navigationHistory.length - 1 - delta);
|
|
604
|
+
const target = navigationHistory[targetIndex];
|
|
605
|
+
navigationHistory.length = targetIndex;
|
|
606
|
+
pushEntry(target.id, target.query);
|
|
607
|
+
return Promise.resolve();
|
|
608
|
+
}
|
|
609
|
+
function getCurrentPagesInternal() {
|
|
610
|
+
return navigationHistory.map((entry) => entry.instance).filter((instance) => Boolean(instance));
|
|
611
|
+
}
|
|
612
|
+
function getAppInstance() {
|
|
613
|
+
return appInstance;
|
|
614
|
+
}
|
|
615
|
+
var globalTarget = typeof globalThis !== "undefined" ? globalThis : {};
|
|
616
|
+
if (globalTarget) {
|
|
617
|
+
const wxBridge = globalTarget.wx ?? {};
|
|
618
|
+
Object.assign(wxBridge, {
|
|
619
|
+
navigateTo,
|
|
620
|
+
navigateBack,
|
|
621
|
+
redirectTo,
|
|
622
|
+
switchTab,
|
|
623
|
+
reLaunch
|
|
624
|
+
});
|
|
625
|
+
globalTarget.wx = wxBridge;
|
|
626
|
+
if (typeof globalTarget.getApp !== "function") {
|
|
627
|
+
globalTarget.getApp = getAppInstance;
|
|
628
|
+
}
|
|
629
|
+
if (typeof globalTarget.getCurrentPages !== "function") {
|
|
630
|
+
globalTarget.getCurrentPages = getCurrentPagesInternal;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// src/runtime/style.ts
|
|
635
|
+
var injected = /* @__PURE__ */ new Map();
|
|
636
|
+
function createStyleId(css) {
|
|
637
|
+
let hash = 2166136261;
|
|
638
|
+
for (let i = 0; i < css.length; i++) {
|
|
639
|
+
hash ^= css.charCodeAt(i);
|
|
640
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
641
|
+
}
|
|
642
|
+
return `weapp-web-style-${(hash >>> 0).toString(36)}`;
|
|
643
|
+
}
|
|
644
|
+
function removeStyle(id) {
|
|
645
|
+
if (typeof document === "undefined") {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
const style = injected.get(id);
|
|
649
|
+
if (style) {
|
|
650
|
+
style.remove();
|
|
651
|
+
injected.delete(id);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
function injectStyle(css, id) {
|
|
655
|
+
if (typeof document === "undefined") {
|
|
656
|
+
return () => {
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
const styleId = id ?? createStyleId(css);
|
|
660
|
+
const existing = injected.get(styleId);
|
|
661
|
+
if (existing) {
|
|
662
|
+
existing.textContent = css;
|
|
663
|
+
return () => removeStyle(styleId);
|
|
664
|
+
}
|
|
665
|
+
const style = document.createElement("style");
|
|
666
|
+
style.id = styleId;
|
|
667
|
+
style.textContent = css;
|
|
668
|
+
document.head.append(style);
|
|
669
|
+
injected.set(styleId, style);
|
|
670
|
+
return () => removeStyle(styleId);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// src/runtime/template.ts
|
|
674
|
+
import { parseDocument } from "htmlparser2";
|
|
675
|
+
var CONTROL_ATTRS = /* @__PURE__ */ new Set([
|
|
676
|
+
"wx:if",
|
|
677
|
+
"wx:elif",
|
|
678
|
+
"wx:else",
|
|
679
|
+
"wx:for",
|
|
680
|
+
"wx:for-item",
|
|
681
|
+
"wx:for-index",
|
|
682
|
+
"wx:key"
|
|
683
|
+
]);
|
|
684
|
+
var EVENT_PREFIX_RE = /^(?:bind|catch|mut-bind|capture-bind|capture-catch)([\w-]+)$/;
|
|
685
|
+
var EVENT_KIND_ALIAS = {
|
|
686
|
+
tap: "click"
|
|
687
|
+
};
|
|
688
|
+
var SELF_CLOSING_TAGS = /* @__PURE__ */ new Set([
|
|
689
|
+
"area",
|
|
690
|
+
"base",
|
|
691
|
+
"br",
|
|
692
|
+
"col",
|
|
693
|
+
"embed",
|
|
694
|
+
"hr",
|
|
695
|
+
"img",
|
|
696
|
+
"image",
|
|
697
|
+
"input",
|
|
698
|
+
"link",
|
|
699
|
+
"meta",
|
|
700
|
+
"param",
|
|
701
|
+
"source",
|
|
702
|
+
"track",
|
|
703
|
+
"wbr"
|
|
704
|
+
]);
|
|
705
|
+
var templateCache = /* @__PURE__ */ new Map();
|
|
706
|
+
var expressionCache = /* @__PURE__ */ new Map();
|
|
707
|
+
function filterRenderableNode(node) {
|
|
708
|
+
if (node.type === "directive" || node.type === "comment") {
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
if (node.type === "text") {
|
|
712
|
+
const data = node.data ?? "";
|
|
713
|
+
return data.trim().length > 0;
|
|
714
|
+
}
|
|
715
|
+
return true;
|
|
716
|
+
}
|
|
717
|
+
function getOrParseTemplate(source) {
|
|
718
|
+
let cached = templateCache.get(source);
|
|
719
|
+
if (!cached) {
|
|
720
|
+
const document2 = parseDocument(source, {
|
|
721
|
+
xmlMode: true,
|
|
722
|
+
decodeEntities: true,
|
|
723
|
+
recognizeSelfClosing: true
|
|
724
|
+
});
|
|
725
|
+
cached = (document2.children ?? []).filter(filterRenderableNode);
|
|
726
|
+
templateCache.set(source, cached);
|
|
727
|
+
}
|
|
728
|
+
return cached;
|
|
729
|
+
}
|
|
730
|
+
function createScope(initial) {
|
|
731
|
+
return Object.assign(/* @__PURE__ */ Object.create(null), initial ?? {});
|
|
732
|
+
}
|
|
733
|
+
function createChildScope(parent) {
|
|
734
|
+
return Object.assign(Object.create(parent), {});
|
|
735
|
+
}
|
|
736
|
+
function normalizeList(value) {
|
|
737
|
+
if (Array.isArray(value)) {
|
|
738
|
+
return value;
|
|
739
|
+
}
|
|
740
|
+
if (value == null) {
|
|
741
|
+
return [];
|
|
742
|
+
}
|
|
743
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
744
|
+
const length = Math.max(0, Math.floor(value));
|
|
745
|
+
return Array.from({ length }, (_, index) => index);
|
|
746
|
+
}
|
|
747
|
+
if (typeof value === "object") {
|
|
748
|
+
return Object.values(value);
|
|
749
|
+
}
|
|
750
|
+
return [];
|
|
751
|
+
}
|
|
752
|
+
function normalizeTagName(name) {
|
|
753
|
+
switch (name) {
|
|
754
|
+
case "view":
|
|
755
|
+
case "cover-view":
|
|
756
|
+
case "navigator":
|
|
757
|
+
case "scroll-view":
|
|
758
|
+
case "swiper":
|
|
759
|
+
case "swiper-item":
|
|
760
|
+
case "movable-area":
|
|
761
|
+
case "movable-view":
|
|
762
|
+
case "cover-image":
|
|
763
|
+
return "div";
|
|
764
|
+
case "text":
|
|
765
|
+
case "icon":
|
|
766
|
+
return "span";
|
|
767
|
+
case "image":
|
|
768
|
+
return "img";
|
|
769
|
+
case "button":
|
|
770
|
+
return "button";
|
|
771
|
+
case "input":
|
|
772
|
+
return "input";
|
|
773
|
+
case "textarea":
|
|
774
|
+
return "textarea";
|
|
775
|
+
case "form":
|
|
776
|
+
return "form";
|
|
777
|
+
case "label":
|
|
778
|
+
return "label";
|
|
779
|
+
case "picker":
|
|
780
|
+
case "picker-view":
|
|
781
|
+
return "select";
|
|
782
|
+
case "block":
|
|
783
|
+
return "#fragment";
|
|
784
|
+
default:
|
|
785
|
+
return name || "div";
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
function normalizeAttributeName(name) {
|
|
789
|
+
if (name === "class" || name === "style" || name.startsWith("data-")) {
|
|
790
|
+
return name;
|
|
791
|
+
}
|
|
792
|
+
if (name === "hover-class") {
|
|
793
|
+
return "data-hover-class";
|
|
794
|
+
}
|
|
795
|
+
return name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
796
|
+
}
|
|
797
|
+
function escapeHtml(value) {
|
|
798
|
+
return value.replace(/[&<>"']/g, (match) => {
|
|
799
|
+
switch (match) {
|
|
800
|
+
case "&":
|
|
801
|
+
return "&";
|
|
802
|
+
case "<":
|
|
803
|
+
return "<";
|
|
804
|
+
case ">":
|
|
805
|
+
return ">";
|
|
806
|
+
case '"':
|
|
807
|
+
return """;
|
|
808
|
+
case "'":
|
|
809
|
+
return "'";
|
|
810
|
+
default:
|
|
811
|
+
return match;
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
function escapeAttribute(value) {
|
|
816
|
+
return escapeHtml(value);
|
|
817
|
+
}
|
|
818
|
+
function toDisplayString(value) {
|
|
819
|
+
if (value == null) {
|
|
820
|
+
return "";
|
|
821
|
+
}
|
|
822
|
+
if (typeof value === "object") {
|
|
823
|
+
if (value instanceof Date) {
|
|
824
|
+
return value.toISOString();
|
|
825
|
+
}
|
|
826
|
+
try {
|
|
827
|
+
return JSON.stringify(value);
|
|
828
|
+
} catch {
|
|
829
|
+
return String(value);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
return String(value);
|
|
833
|
+
}
|
|
834
|
+
function unwrapExpression(expression) {
|
|
835
|
+
const trimmed = expression.trim();
|
|
836
|
+
if (trimmed.startsWith("{{") && trimmed.endsWith("}}")) {
|
|
837
|
+
return trimmed.slice(2, -2).trim();
|
|
838
|
+
}
|
|
839
|
+
return trimmed;
|
|
840
|
+
}
|
|
841
|
+
function evaluateExpression(expression, scope) {
|
|
842
|
+
if (!expression) {
|
|
843
|
+
return void 0;
|
|
844
|
+
}
|
|
845
|
+
const trimmed = unwrapExpression(expression);
|
|
846
|
+
if (!trimmed) {
|
|
847
|
+
return void 0;
|
|
848
|
+
}
|
|
849
|
+
let evaluator = expressionCache.get(trimmed);
|
|
850
|
+
if (!evaluator) {
|
|
851
|
+
try {
|
|
852
|
+
evaluator = new Function("scope", `with(scope){ return (${trimmed}); }`);
|
|
853
|
+
} catch (error) {
|
|
854
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
855
|
+
throw new SyntaxError(`[@weapp-vite/web] \u65E0\u6CD5\u89E3\u6790\u8868\u8FBE\u5F0F "${trimmed}": ${reason}`);
|
|
856
|
+
}
|
|
857
|
+
expressionCache.set(trimmed, evaluator);
|
|
858
|
+
}
|
|
859
|
+
try {
|
|
860
|
+
return evaluator(scope);
|
|
861
|
+
} catch {
|
|
862
|
+
return void 0;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
function interpolateText(source, scope, escapeResult) {
|
|
866
|
+
if (!source.includes("{{")) {
|
|
867
|
+
return escapeResult ? escapeHtml(source) : source;
|
|
868
|
+
}
|
|
869
|
+
let cursor = 0;
|
|
870
|
+
let buffer = "";
|
|
871
|
+
while (cursor < source.length) {
|
|
872
|
+
const start = source.indexOf("{{", cursor);
|
|
873
|
+
if (start === -1) {
|
|
874
|
+
buffer += source.slice(cursor);
|
|
875
|
+
break;
|
|
876
|
+
}
|
|
877
|
+
buffer += source.slice(cursor, start);
|
|
878
|
+
const end = source.indexOf("}}", start + 2);
|
|
879
|
+
if (end === -1) {
|
|
880
|
+
buffer += source.slice(start);
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
const expression = source.slice(start + 2, end).trim();
|
|
884
|
+
const evaluated = toDisplayString(evaluateExpression(expression, scope));
|
|
885
|
+
buffer += evaluated;
|
|
886
|
+
cursor = end + 2;
|
|
887
|
+
}
|
|
888
|
+
return escapeResult ? escapeHtml(buffer) : buffer;
|
|
889
|
+
}
|
|
890
|
+
function resolveAttributeValue(value, scope) {
|
|
891
|
+
return interpolateText(value ?? "", scope, false);
|
|
892
|
+
}
|
|
893
|
+
function extractFor(attribs) {
|
|
894
|
+
const expr = attribs["wx:for"];
|
|
895
|
+
const restAttribs = {};
|
|
896
|
+
const itemName = attribs["wx:for-item"]?.trim() || "item";
|
|
897
|
+
let indexName = attribs["wx:for-index"]?.trim() || "index";
|
|
898
|
+
for (const [key, val] of Object.entries(attribs)) {
|
|
899
|
+
if (key === "wx:for" || key === "wx:for-item" || key === "wx:for-index" || key === "wx:key") {
|
|
900
|
+
continue;
|
|
901
|
+
}
|
|
902
|
+
restAttribs[key] = val;
|
|
903
|
+
}
|
|
904
|
+
if (itemName === indexName) {
|
|
905
|
+
indexName = `${indexName}Index`;
|
|
906
|
+
}
|
|
907
|
+
return {
|
|
908
|
+
expr,
|
|
909
|
+
itemName,
|
|
910
|
+
indexName,
|
|
911
|
+
restAttribs
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
function buildAttributeString(attribs, scope) {
|
|
915
|
+
let result = "";
|
|
916
|
+
for (const [name, rawValue] of Object.entries(attribs)) {
|
|
917
|
+
if (CONTROL_ATTRS.has(name)) {
|
|
918
|
+
continue;
|
|
919
|
+
}
|
|
920
|
+
const eventMatch = EVENT_PREFIX_RE.exec(name);
|
|
921
|
+
if (eventMatch) {
|
|
922
|
+
const [, rawEvent] = eventMatch;
|
|
923
|
+
const event = rawEvent.toLowerCase();
|
|
924
|
+
const handlerName = resolveAttributeValue(rawValue, scope).trim();
|
|
925
|
+
if (!handlerName) {
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
928
|
+
const runtimeEvent = EVENT_KIND_ALIAS[event] ?? event;
|
|
929
|
+
result += ` data-wx-on-${runtimeEvent}="${escapeAttribute(handlerName)}"`;
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
const value = resolveAttributeValue(rawValue, scope);
|
|
933
|
+
if (value === "") {
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
const normalizedName = normalizeAttributeName(name);
|
|
937
|
+
result += ` ${normalizedName}="${escapeAttribute(value)}"`;
|
|
938
|
+
}
|
|
939
|
+
return result;
|
|
940
|
+
}
|
|
941
|
+
function stripControlAttributes(attribs) {
|
|
942
|
+
const result = {};
|
|
943
|
+
for (const [name, value] of Object.entries(attribs)) {
|
|
944
|
+
if (!CONTROL_ATTRS.has(name)) {
|
|
945
|
+
result[name] = value;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
return result;
|
|
949
|
+
}
|
|
950
|
+
function isConditionalElement(node) {
|
|
951
|
+
if (node.type !== "tag") {
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
const attribs = node.attribs ?? {};
|
|
955
|
+
return "wx:if" in attribs || "wx:elif" in attribs || "wx:else" in attribs;
|
|
956
|
+
}
|
|
957
|
+
function renderConditionalSequence(nodes, startIndex, scope, renderChildren) {
|
|
958
|
+
const branches = [];
|
|
959
|
+
let cursor = startIndex;
|
|
960
|
+
while (cursor < nodes.length) {
|
|
961
|
+
const candidate = nodes[cursor];
|
|
962
|
+
if (!isConditionalElement(candidate)) {
|
|
963
|
+
break;
|
|
964
|
+
}
|
|
965
|
+
const element = candidate;
|
|
966
|
+
const attribs = element.attribs ?? {};
|
|
967
|
+
if (branches.length === 0 && !("wx:if" in attribs)) {
|
|
968
|
+
break;
|
|
969
|
+
}
|
|
970
|
+
if (branches.length > 0 && !("wx:elif" in attribs) && !("wx:else" in attribs)) {
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
branches.push({ node: element, attribs });
|
|
974
|
+
cursor += 1;
|
|
975
|
+
if ("wx:else" in attribs) {
|
|
976
|
+
break;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
if (!branches.length) {
|
|
980
|
+
const node = nodes[startIndex];
|
|
981
|
+
return {
|
|
982
|
+
rendered: renderChildren(node, scope),
|
|
983
|
+
endIndex: startIndex
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
for (const { node, attribs } of branches) {
|
|
987
|
+
if ("wx:else" in attribs) {
|
|
988
|
+
return {
|
|
989
|
+
rendered: renderElement(
|
|
990
|
+
node,
|
|
991
|
+
scope,
|
|
992
|
+
renderChildren,
|
|
993
|
+
{ overrideAttribs: stripControlAttributes(attribs) }
|
|
994
|
+
),
|
|
995
|
+
endIndex: startIndex + branches.length - 1
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
const conditionExpr = attribs["wx:if"] ?? attribs["wx:elif"];
|
|
999
|
+
if (!conditionExpr) {
|
|
1000
|
+
continue;
|
|
1001
|
+
}
|
|
1002
|
+
const condition = evaluateExpression(conditionExpr, scope);
|
|
1003
|
+
if (condition) {
|
|
1004
|
+
return {
|
|
1005
|
+
rendered: renderElement(
|
|
1006
|
+
node,
|
|
1007
|
+
scope,
|
|
1008
|
+
renderChildren,
|
|
1009
|
+
{ overrideAttribs: stripControlAttributes(attribs) }
|
|
1010
|
+
),
|
|
1011
|
+
endIndex: startIndex + branches.length - 1
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
return {
|
|
1016
|
+
rendered: "",
|
|
1017
|
+
endIndex: startIndex + branches.length - 1
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
function renderElement(node, scope, renderChildren, options = {}) {
|
|
1021
|
+
const attribs = node.attribs ?? {};
|
|
1022
|
+
if (!options.skipFor) {
|
|
1023
|
+
const forExtract = extractFor(attribs);
|
|
1024
|
+
if (forExtract.expr) {
|
|
1025
|
+
const list = normalizeList(evaluateExpression(forExtract.expr, scope));
|
|
1026
|
+
if (!list.length) {
|
|
1027
|
+
return "";
|
|
1028
|
+
}
|
|
1029
|
+
let buffer = "";
|
|
1030
|
+
for (let idx = 0; idx < list.length; idx++) {
|
|
1031
|
+
const item = list[idx];
|
|
1032
|
+
const childScope = createChildScope(scope);
|
|
1033
|
+
childScope[forExtract.itemName] = item;
|
|
1034
|
+
childScope[forExtract.indexName] = idx;
|
|
1035
|
+
buffer += renderElement(node, childScope, renderChildren, {
|
|
1036
|
+
skipFor: true,
|
|
1037
|
+
overrideAttribs: forExtract.restAttribs
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
return buffer;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
const effectiveAttribs = options.overrideAttribs ?? attribs;
|
|
1044
|
+
const normalizedTag = normalizeTagName(node.name);
|
|
1045
|
+
if (normalizedTag === "#fragment") {
|
|
1046
|
+
return renderChildren(node.children, scope);
|
|
1047
|
+
}
|
|
1048
|
+
const attrs = buildAttributeString(effectiveAttribs, scope);
|
|
1049
|
+
const children = renderChildren(node.children, scope);
|
|
1050
|
+
if (SELF_CLOSING_TAGS.has(normalizedTag) && !children) {
|
|
1051
|
+
return `<${normalizedTag}${attrs} />`;
|
|
1052
|
+
}
|
|
1053
|
+
return `<${normalizedTag}${attrs}>${children}</${normalizedTag}>`;
|
|
1054
|
+
}
|
|
1055
|
+
function renderTextNode(node, scope) {
|
|
1056
|
+
const value = node.data ?? "";
|
|
1057
|
+
if (!value.trim()) {
|
|
1058
|
+
return "";
|
|
1059
|
+
}
|
|
1060
|
+
return interpolateText(value, scope, true);
|
|
1061
|
+
}
|
|
1062
|
+
function renderTree(input, scope) {
|
|
1063
|
+
if (!input) {
|
|
1064
|
+
return "";
|
|
1065
|
+
}
|
|
1066
|
+
if (Array.isArray(input)) {
|
|
1067
|
+
let buffer = "";
|
|
1068
|
+
for (let index = 0; index < input.length; index++) {
|
|
1069
|
+
const node2 = input[index];
|
|
1070
|
+
if (isConditionalElement(node2)) {
|
|
1071
|
+
const { rendered, endIndex } = renderConditionalSequence(input, index, scope, renderTree);
|
|
1072
|
+
buffer += rendered;
|
|
1073
|
+
index = endIndex;
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
1076
|
+
buffer += renderTree(node2, scope);
|
|
1077
|
+
}
|
|
1078
|
+
return buffer;
|
|
1079
|
+
}
|
|
1080
|
+
const node = input;
|
|
1081
|
+
if (node.type === "text") {
|
|
1082
|
+
return renderTextNode(node, scope);
|
|
1083
|
+
}
|
|
1084
|
+
if (node.type === "tag" || node.type === "script" || node.type === "style") {
|
|
1085
|
+
return renderElement(node, scope, renderTree);
|
|
1086
|
+
}
|
|
1087
|
+
if ("children" in node && node.children?.length) {
|
|
1088
|
+
return renderTree(node.children, scope);
|
|
1089
|
+
}
|
|
1090
|
+
return "";
|
|
1091
|
+
}
|
|
1092
|
+
function renderTemplate(nodes, scope) {
|
|
1093
|
+
const renderScope = createScope(scope);
|
|
1094
|
+
return renderTree(nodes, renderScope);
|
|
1095
|
+
}
|
|
1096
|
+
function createTemplate(source) {
|
|
1097
|
+
const nodes = getOrParseTemplate(source);
|
|
1098
|
+
return (scope) => renderTemplate(nodes, scope);
|
|
1099
|
+
}
|
|
1100
|
+
export {
|
|
1101
|
+
createTemplate,
|
|
1102
|
+
defineComponent,
|
|
1103
|
+
initializePageRoutes,
|
|
1104
|
+
injectStyle,
|
|
1105
|
+
navigateBack,
|
|
1106
|
+
navigateTo,
|
|
1107
|
+
reLaunch,
|
|
1108
|
+
redirectTo,
|
|
1109
|
+
registerApp,
|
|
1110
|
+
registerComponent,
|
|
1111
|
+
registerPage,
|
|
1112
|
+
removeStyle,
|
|
1113
|
+
renderTemplate,
|
|
1114
|
+
switchTab
|
|
1115
|
+
};
|