@dongmingzhixiu/vuexir-compiler 0.5.7 → 0.7.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/codegen/bindings.d.ts +11 -0
- package/dist/codegen/bindings.js +32 -0
- package/dist/codegen/compose.d.ts +10 -1
- package/dist/codegen/compose.js +297 -65
- package/dist/codegen/dynamic-vector.d.ts +3 -0
- package/dist/codegen/dynamic-vector.js +81 -0
- package/dist/codegen/page-js-android.d.ts +2 -0
- package/dist/codegen/page-js-android.js +59 -0
- package/dist/codegen/project-assets.d.ts +5 -0
- package/dist/codegen/project-assets.js +31 -0
- package/dist/codegen/project-styles.d.ts +2 -0
- package/dist/codegen/project-styles.js +41 -0
- package/dist/codegen/swiftui.d.ts +4 -25
- package/dist/codegen/swiftui.js +251 -71
- package/dist/codegen/vector.d.ts +3 -0
- package/dist/codegen/vector.js +165 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +8 -2
- package/dist/ir/schema.d.ts +41 -1
- package/dist/ir/schema.js +39 -20
- package/dist/transform/css.d.ts +21 -1
- package/dist/transform/css.js +217 -14
- package/dist/transform/dynamic-svg.d.ts +3 -0
- package/dist/transform/dynamic-svg.js +53 -0
- package/dist/transform/svg.d.ts +16 -0
- package/dist/transform/svg.js +96 -0
- package/dist/transform/tab-bar.d.ts +17 -0
- package/dist/transform/tab-bar.js +44 -0
- package/dist/transform/visuals.d.ts +17 -0
- package/dist/transform/visuals.js +91 -0
- package/dist/transform/vue2ir.d.ts +12 -1
- package/dist/transform/vue2ir.js +581 -188
- package/package.json +4 -2
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** CSS 函数参数分割,保留 rgba()/var() 内的逗号。 */
|
|
2
|
+
export function splitCssArgs(value) {
|
|
3
|
+
const parts = [];
|
|
4
|
+
let depth = 0, quote = '', start = 0;
|
|
5
|
+
for (let i = 0; i < value.length; i++) {
|
|
6
|
+
const ch = value[i];
|
|
7
|
+
if (quote) {
|
|
8
|
+
if (ch === quote && value[i - 1] !== '\\')
|
|
9
|
+
quote = '';
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
if (ch === '"' || ch === "'")
|
|
13
|
+
quote = ch;
|
|
14
|
+
else if (ch === '(')
|
|
15
|
+
depth++;
|
|
16
|
+
else if (ch === ')')
|
|
17
|
+
depth--;
|
|
18
|
+
else if (ch === ',' && depth === 0) {
|
|
19
|
+
parts.push(value.slice(start, i).trim());
|
|
20
|
+
start = i + 1;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
parts.push(value.slice(start).trim());
|
|
24
|
+
return parts;
|
|
25
|
+
}
|
|
26
|
+
export function parseLinearGradient(value) {
|
|
27
|
+
if (splitCssArgs(value).length !== 1)
|
|
28
|
+
return null;
|
|
29
|
+
const match = value.match(/^(linear|radial)-gradient\(([\s\S]*)\)$/i);
|
|
30
|
+
if (!match)
|
|
31
|
+
return null;
|
|
32
|
+
const args = splitCssArgs(match[2]);
|
|
33
|
+
const kind = match[1].toLowerCase();
|
|
34
|
+
let center;
|
|
35
|
+
if (kind === 'radial') {
|
|
36
|
+
center = { x: .5, y: .5 };
|
|
37
|
+
if (!/^(#|rgba?\(|hsla?\(|var\(|transparent)/.test(args[0])) {
|
|
38
|
+
const header = args.shift();
|
|
39
|
+
const at = header.match(/at\s+([\d.]+)%\s+([\d.]+)%/);
|
|
40
|
+
if (at)
|
|
41
|
+
center = { x: Number(at[1]) / 100, y: Number(at[2]) / 100 };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
let angle = 180;
|
|
45
|
+
const directions = { 'to top': 0, 'to right': 90, 'to bottom': 180, 'to left': 270,
|
|
46
|
+
'to top right': 45, 'to right top': 45, 'to bottom right': 135, 'to right bottom': 135,
|
|
47
|
+
'to bottom left': 225, 'to left bottom': 225, 'to top left': 315, 'to left top': 315 };
|
|
48
|
+
if (/^-?[\d.]+deg$/.test(args[0]))
|
|
49
|
+
angle = Number(args.shift().slice(0, -3));
|
|
50
|
+
else if (args[0] in directions)
|
|
51
|
+
angle = directions[args.shift()];
|
|
52
|
+
const parsed = args.map((arg) => {
|
|
53
|
+
const m = arg.match(/^([\s\S]*?)(?:\s+(-?[\d.]+)%)?$/);
|
|
54
|
+
return { color: m[1] === 'transparent' ? 'rgba(0,0,0,0)' : m[1], offset: m[2] === undefined ? undefined : Number(m[2]) / 100 };
|
|
55
|
+
});
|
|
56
|
+
if (parsed.length < 2 || parsed.some((s) => !/^(?:#[\da-f]{3,8}|rgba?\(.*\)|hsla?\(.*\)|var\(.*\)|transparent)$/i.test(s.color)))
|
|
57
|
+
return null;
|
|
58
|
+
parsed[0].offset ??= 0;
|
|
59
|
+
parsed[parsed.length - 1].offset ??= 1;
|
|
60
|
+
for (let i = 1; i < parsed.length; i++) {
|
|
61
|
+
if (parsed[i].offset === undefined)
|
|
62
|
+
continue;
|
|
63
|
+
let prev = i - 1;
|
|
64
|
+
while (parsed[prev].offset === undefined)
|
|
65
|
+
prev--;
|
|
66
|
+
const end = Math.max(parsed[prev].offset, parsed[i].offset);
|
|
67
|
+
for (let j = prev + 1; j <= i; j++)
|
|
68
|
+
parsed[j].offset ??= parsed[prev].offset + (end - parsed[prev].offset) * (j - prev) / (i - prev);
|
|
69
|
+
parsed[i].offset = end;
|
|
70
|
+
}
|
|
71
|
+
return { kind, ...(center ? { center } : {}), angle: ((angle % 360) + 360) % 360, stops: parsed };
|
|
72
|
+
}
|
|
73
|
+
/** 按顶层空白拆 CSS 简写,calc()/rgba() 内的空格不拆开。 */
|
|
74
|
+
export function splitCssWords(value) {
|
|
75
|
+
const out = [];
|
|
76
|
+
let depth = 0, start = 0;
|
|
77
|
+
for (let i = 0; i < value.length; i++) {
|
|
78
|
+
if (value[i] === '(')
|
|
79
|
+
depth++;
|
|
80
|
+
else if (value[i] === ')')
|
|
81
|
+
depth--;
|
|
82
|
+
else if (/\s/.test(value[i]) && depth === 0) {
|
|
83
|
+
if (i > start)
|
|
84
|
+
out.push(value.slice(start, i));
|
|
85
|
+
start = i + 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (start < value.length)
|
|
89
|
+
out.push(value.slice(start));
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
@@ -43,6 +43,7 @@ export declare function extractFunctions(script: string): {
|
|
|
43
43
|
export declare function extractOnMounted(script: string): string | undefined;
|
|
44
44
|
/** body 重写:<script setup> 的 ref 名.value → stateStore.<名>(JS 侧状态注册表) */
|
|
45
45
|
export declare function rewriteStateRefs(body: string, names: string[]): string;
|
|
46
|
+
export declare const RUNTIME_BOOTSTRAP_SOURCE = "\nif (!globalThis.__vrnBootstrapReady) {\n globalThis.__vrnBootstrapReady = true;\n // \u5BBF\u4E3B\u6CA1\u6709\u6D4F\u89C8\u5668 window\uFF1B\u4EC5\u63D0\u4F9B\u4E1A\u52A1\u5E38\u7528\u7684\u5168\u5C40\u522B\u540D\u4E0E\u89C6\u53E3\u4E8B\u4EF6\u63A5\u53E3\uFF0C\u4E0D\u5F15\u5165 DOM \u6E32\u67D3\u3002\n if (typeof window === \"undefined\") {\n var window = globalThis;\n window.innerWidth = 390;\n window.innerHeight = 844;\n window.location = {hash:'',href:'app://vuexir'};\n window.history = {replaceState:function(_state,_title,url){window.location.hash=String(url);}};\n window.addEventListener = function() {};\n window.removeEventListener = function() {};\n }\n// R72 \u5B9A\u65F6\u5668\u5BBF\u4E3B shim\uFF1A\u5BBF\u4E3B\uFF08JavaScriptCore\uFF09\u672A\u6CE8\u5165\u65F6\u7528\u5BBF\u4E3B\u6865\u5B9E\u73B0\uFF0C\u4FDD\u8BC1 Promise/await \u5EF6\u65F6\u53EF\u7528\uFF1B\n// \u6D4F\u89C8\u5668\u9884\u89C8\u5668\u5DF2\u6709\u539F\u751F setTimeout\uFF0C\u6B64\u5904\u4E0D\u8986\u76D6\u3002\nvar __timerSeq = 0;\nvar __timers = {};\nif (typeof setTimeout !== \"function\") {\n var setTimeout = function (fn, ms) {\n var id = ++__timerSeq;\n if (typeof __nativeSetTimeout === \"function\") {\n __nativeSetTimeout(id, Number(ms) || 0);\n __timers[id] = fn;\n return id;\n }\n return 0;\n };\n var clearTimeout = function (id) {\n delete __timers[id];\n if (typeof __nativeClearTimeout === \"function\") __nativeClearTimeout(Number(id));\n };\n // \u5BBF\u4E3B\u56DE\u8C03\u5165\u53E3\uFF08__nativeSetTimeout \u5230\u671F\u540E\u7531\u539F\u751F\u8C03\u7528\uFF09\n var __vrnRunTimer = function (id) {\n var fn = __timers[id];\n delete __timers[id];\n if (typeof fn === \"function\") fn();\n };\n var setInterval = function (fn, ms) {\n var id = ++__timerSeq;\n __timers[id] = { fn: fn, ms: Number(ms) || 0, repeat: true };\n if (typeof __nativeSetInterval === \"function\") __nativeSetInterval(id, Number(ms) || 0);\n return id;\n };\n var clearInterval = function (id) {\n delete __timers[id];\n if (typeof __nativeClearInterval === \"function\") __nativeClearInterval(Number(id));\n };\n var __vrnRunInterval = function (id) {\n var t = __timers[id];\n if (t && t.repeat && typeof t.fn === \"function\") t.fn();\n };\n}\nif (typeof queueMicrotask !== \"function\") {\n var queueMicrotask = function (fn) {\n Promise.resolve().then(fn);\n };\n}\n\n\n if (typeof localStorage === \"undefined\") {\n var localStorage = {\n getItem: function(k) { return typeof __lsGet === \"function\" ? __lsGet(\"vrn.\" + k) : null; },\n setItem: function(k,v) { if(typeof __lsSet === \"function\") __lsSet(\"vrn.\" + k,String(v)); },\n removeItem: function(k) { if(typeof __lsSet === \"function\") __lsSet(\"vrn.\" + k,null); }\n };\n }\n}\n";
|
|
46
47
|
/** 生成 runtime.js 完整内容(M3:stateStore Proxy + handlers + onMounted + localStorage shim) */
|
|
47
48
|
export declare function generateRuntimeSource(states: {
|
|
48
49
|
name: string;
|
|
@@ -55,7 +56,7 @@ export declare function generateRuntimeSource(states: {
|
|
|
55
56
|
params: string;
|
|
56
57
|
body: string;
|
|
57
58
|
async?: boolean;
|
|
58
|
-
}[], onMounted: string | undefined, onMountedAsync?: boolean): string;
|
|
59
|
+
}[], onMounted: string | undefined, onMountedAsync?: boolean, externalScript?: boolean): string;
|
|
59
60
|
export declare function swiftExpr(exp: string): string | null;
|
|
60
61
|
export declare function resolveSetCall(handler: string, state: ScreenStateInfo, warn?: (msg: string) => void): {
|
|
61
62
|
var: string;
|
|
@@ -63,6 +64,16 @@ export declare function resolveSetCall(handler: string, state: ScreenStateInfo,
|
|
|
63
64
|
kind: 'literal' | 'expr';
|
|
64
65
|
} | null;
|
|
65
66
|
export interface Vue2IrOptions {
|
|
67
|
+
/** 按导入顺序提供项目全局 CSS;页面局部样式随后参与级联。 */
|
|
68
|
+
globalStyles?: string[];
|
|
69
|
+
/** 图片 import 标识符 → 可携带到原生的 src(data URI 或远程 URL)。 */
|
|
70
|
+
assets?: Record<string, string>;
|
|
71
|
+
/** 将组件模板及插槽直接展开到页面 IR,适用于高还原生成。 */
|
|
72
|
+
inlineComponents?: boolean;
|
|
73
|
+
/** 页面脚本 bundle 已提供真实 store 对象时启用。 */
|
|
74
|
+
liveStoreObjects?: boolean;
|
|
75
|
+
/** 逻辑由页面 bundle 执行,避免再把 TS 函数体当 JS 拼接。 */
|
|
76
|
+
pageScriptBundle?: boolean;
|
|
66
77
|
/** R86 Pinia store 源码(文件名 → 源码);提供后页面可用 `const ui = useUiStore()` 读状态 */
|
|
67
78
|
storeSources?: Record<string, string>;
|
|
68
79
|
/** R115:允许未注册的自定义组件降级为占位(工程迁移用;库默认仍按 R13 报错) */
|