cj-tauri 2.0.0 → 2.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/README.md +113 -99
- package/bin/cj-tauri.js +287 -287
- package/cjpm.toml +63 -52
- package/cli/cjpm.toml +22 -22
- package/cli/src/doctor.cj +308 -306
- package/cli/src/main.cj +129 -129
- package/cli/src/manifest.cj +632 -558
- package/cli/src/manifest_test.cj +87 -0
- package/cli/src/project.cj +770 -770
- package/cli/src/resolve.cj +348 -348
- package/cli/src/scaffold.cj +369 -369
- package/cli/src/sync.cj +526 -526
- package/cli/src/util.cj +168 -168
- package/cli/templates/app/README.md +51 -48
- package/cli/templates/app/assets/capabilities/default.json +7 -7
- package/cli/templates/app/assets/ui/index.html +120 -118
- package/cli/templates/app/cj-tauri.toml +32 -22
- package/cli/templates/app/cjpm.toml +34 -34
- package/cli/templates/app/src/main.cj +101 -90
- package/cli/templates/app-react/README.md +56 -56
- package/cli/templates/app-react/assets/capabilities/default.json +7 -7
- package/cli/templates/app-react/assets/ui/index.html +25 -25
- package/cli/templates/app-react/assets/ui/package.json +19 -19
- package/cli/templates/app-react/assets/ui/src/App.css +67 -67
- package/cli/templates/app-react/assets/ui/src/App.jsx +124 -124
- package/cli/templates/app-react/assets/ui/src/main.jsx +6 -6
- package/cli/templates/app-react/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-react/cj-tauri.toml +33 -23
- package/cli/templates/app-react/cjpm.toml +34 -34
- package/cli/templates/app-react/src/main.cj +91 -91
- package/cli/templates/app-vue/README.md +56 -56
- package/cli/templates/app-vue/assets/capabilities/default.json +7 -7
- package/cli/templates/app-vue/assets/ui/index.html +25 -25
- package/cli/templates/app-vue/assets/ui/package.json +18 -18
- package/cli/templates/app-vue/assets/ui/src/App.vue +176 -176
- package/cli/templates/app-vue/assets/ui/src/main.js +4 -4
- package/cli/templates/app-vue/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-vue/cj-tauri.toml +33 -23
- package/cli/templates/app-vue/cjpm.toml +34 -34
- package/cli/templates/app-vue/src/main.cj +91 -91
- package/cli/templates/ohos-skeleton/AppScope/app.json5 +13 -13
- package/cli/templates/ohos-skeleton/AppScope/resources/base/element/string.json +8 -8
- package/cli/templates/ohos-skeleton/AppScope/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/README.md +84 -79
- package/cli/templates/ohos-skeleton/build-hap.sh +15 -0
- package/cli/templates/ohos-skeleton/build-profile.json5 +46 -46
- package/cli/templates/ohos-skeleton/entry/build-profile.json5 +26 -26
- package/cli/templates/ohos-skeleton/entry/cjpm.toml +51 -43
- package/cli/templates/ohos-skeleton/entry/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/entry/oh-package.json5 +9 -9
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/ability_stage.cj +17 -17
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/app_host.cj +94 -94
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/dialog_host.cj +217 -0
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/index.cj +527 -167
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/main_ability.cj +139 -139
- package/cli/templates/ohos-skeleton/entry/src/main/module.json5 +57 -49
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/color.json +8 -8
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/string.json +16 -16
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/profile/main_pages.json +2 -2
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/capabilities.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/index.html +92 -92
- package/cli/templates/ohos-skeleton/hvigor/hvigor-config.json5 +5 -5
- package/cli/templates/ohos-skeleton/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/oh-package.json5 +10 -10
- package/native/build_win.bat +62 -62
- package/native/core/bridge_core.c +1681 -1626
- package/native/core/bridge_core.h +675 -618
- package/native/core/bridge_js.h +108 -108
- package/native/platforms/harmonyos/README.md +115 -6
- package/native/platforms/linux/bridge_linux.c +2787 -2485
- package/native/platforms/windows/bridge_win.c +3740 -3248
- package/native/tests/gtk_threading_probe.c +143 -143
- package/native/tests/test_bridge_core.c +1339 -1228
- package/package.json +53 -53
- package/prebuilt/linux-x64/cj-tauri +0 -0
- package/src/api_system.cj +67 -67
- package/src/app.cj +325 -969
- package/src/app_events.cj +166 -0
- package/src/app_host_ops.cj +287 -0
- package/src/app_run.cj +283 -0
- package/src/app_spec.cj +76 -76
- package/src/arkweb_menu.cj +216 -0
- package/src/arkweb_script.cj +142 -142
- package/src/capability.cj +409 -409
- package/src/clipboard_bridge.cj +178 -0
- package/src/dialog_spec.cj +79 -0
- package/src/dragdrop.cj +26 -26
- package/src/embedded_assets.cj +98 -98
- package/src/host.cj +752 -607
- package/src/host_arkweb.cj +924 -778
- package/src/host_webkit.cj +663 -570
- package/src/host_webview2.cj +663 -570
- package/src/hotkey.cj +66 -66
- package/src/ipc_hub.cj +337 -337
- package/src/ipc_message.cj +286 -286
- package/src/launch.cj +62 -62
- package/src/logging.cj +127 -127
- package/src/menu.cj +197 -197
- package/src/platform/platform_app_context.cj +77 -77
- package/src/platform/platform_assets.cj +33 -33
- package/src/platform/platform_discover.cj +176 -176
- package/src/platform/platform_env.cj +29 -29
- package/src/platform/platform_feature.cj +31 -31
- package/src/platform/platform_page_source.cj +87 -87
- package/src/platform/platform_target_info.cj +32 -32
- package/src/platform_host_provider.cj +87 -87
- package/src/plugin.cj +333 -333
- package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
- package/src/plugins/dialog/plugin_dialog.cj +209 -209
- package/src/plugins/fs/plugin_fs.cj +105 -1
- package/src/plugins/http/http_backend.cj +131 -0
- package/src/plugins/http/http_desktop.cj +195 -0
- package/src/plugins/http/http_ohos.cj +204 -0
- package/src/plugins/http/plugin_http.cj +310 -459
- package/src/plugins/log/plugin_log.cj +105 -105
- package/src/plugins/menu/plugin_menu.cj +158 -158
- package/src/plugins/notification/plugin_notification.cj +154 -154
- package/src/plugins/serial/plugin_serial.cj +458 -454
- package/src/plugins/serial/serial_bridge.cj +194 -194
- package/src/plugins/serial/serial_manager_ohos.cj +92 -0
- package/src/plugins/serial/serial_ohos.cj +529 -0
- package/src/plugins/shell/plugin_shell.cj +258 -258
- package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
- package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
- package/src/plugins/ws/plugin_ws.cj +488 -470
- package/src/process_hidden.cj +174 -174
- package/src/scope.cj +391 -391
- package/src/shell_event.cj +69 -69
- package/src/tests/app_spec_test.cj +126 -127
- package/src/tests/capability_test.cj +243 -243
- package/src/tests/dialog_spec_test.cj +73 -0
- package/src/tests/fake_host.cj +201 -201
- package/src/tests/ipc_hub_test.cj +487 -487
- package/src/tests/logging_test.cj +62 -62
- package/src/tests/platform_contract_test.cj +251 -251
- package/src/tests/plugin_clipboard_test.cj +222 -222
- package/src/tests/plugin_dialog_test.cj +237 -237
- package/src/tests/plugin_fs_test.cj +207 -0
- package/src/tests/plugin_http_test.cj +124 -124
- package/src/tests/plugin_notification_test.cj +205 -205
- package/src/tests/plugin_serial_test.cj +48 -0
- package/src/tests/plugin_test.cj +605 -585
- package/src/tests/plugin_ws_test.cj +40 -40
- package/src/tests/process_hidden_test.cj +129 -129
- package/src/tests/scope_test.cj +350 -350
- package/src/tests/system_host_test.cj +99 -81
- package/src/tests/urlutil_test.cj +53 -53
- package/src/tests/version_test.cj +75 -75
- package/src/tests/window_registry_test.cj +123 -123
- package/src/tray.cj +90 -90
- package/src/urlutil.cj +159 -159
- package/src/version.cj +44 -44
- package/src/window.cj +51 -51
- package/src/window_registry.cj +116 -116
- package/prebuilt/win32-x64/cj-tauri.exe +0 -0
- package/src/plugins/serial/serial_ohos_stub.cj +0 -61
- package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
|
@@ -1,176 +1,176 @@
|
|
|
1
|
-
package cjTauri.platform
|
|
2
|
-
|
|
3
|
-
import std.env.*
|
|
4
|
-
import std.collection.ArrayList
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 平台发现(RFC-002 §4.2 / §5.3)——全框架唯一的「端在哪儿」知识入口
|
|
8
|
-
*
|
|
9
|
-
* 按约定(RFC §5.3),os 名匹配的 @When 只允许出现在本文件与 targets 目录下的生成胶水;
|
|
10
|
-
* CI 用 `grep -r '@When\[os' src/ | grep -v src/platform/` 守这条线。
|
|
11
|
-
* @When 分支一律成对出现(本仓库惯例,参照 host_webview2.cj),保证任何目标下每个
|
|
12
|
-
* 符号恰好有一个定义;跨平台文件里只用短名。
|
|
13
|
-
*
|
|
14
|
-
* 批次 0 边界:本文件只提供**可编译的默认实现**(桌面 Linux / Windows 实测,
|
|
15
|
-
* 鸿蒙走 mobile(filesDir)),特性位清单是占位值,接端时按实测修正。
|
|
16
|
-
*/
|
|
17
|
-
public class Platform {
|
|
18
|
-
/**
|
|
19
|
-
* 桌面端默认发现:paths 走平台规范目录(RFC §5.2),dev 看 CJ_TAURI_DEV_URL
|
|
20
|
-
*
|
|
21
|
-
* arch 默认 x86_64;ARM64 Linux 桌面请显式传 arch(它的 os 与 x86_64 Linux 相同,
|
|
22
|
-
* 这是仓库已知的「同 os 多宿主」来源,见 RFC §5.1)。
|
|
23
|
-
* appId 由 launch() 从清单传入(清单解析在批次 1 落地,见 RFC §3/§13.1 风险 1)。
|
|
24
|
-
*/
|
|
25
|
-
public static func discover(appId: String, arch: String): AppContext {
|
|
26
|
-
return desktop(appId, arch)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public static func desktop(appId: String, arch: String): AppContext {
|
|
30
|
-
let data = "${dataRoot()}/${appId}"
|
|
31
|
-
let target = TargetInfo(desktopOs(), arch, desktopHostKind(), "desktop")
|
|
32
|
-
let fs = ArrayList<PlatformFeature>()
|
|
33
|
-
fs.add(PlatformFeature.MultiWindow)
|
|
34
|
-
fs.add(PlatformFeature.FilePicker)
|
|
35
|
-
fs.add(PlatformFeature.ClipboardImage)
|
|
36
|
-
fs.add(PlatformFeature.Tray)
|
|
37
|
-
return AppContext(
|
|
38
|
-
AppPaths(data, "${cacheRoot()}/${appId}", "${cacheRoot()}/${appId}/tmp"),
|
|
39
|
-
target, devMode(), fs)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 移动端发现:沙箱目录由系统能力入口传入(鸿蒙 Ability 的 filesDir / Android 的 filesDir)
|
|
44
|
-
*
|
|
45
|
-
* 沙箱端没有 dev server,dev 恒为 false;hostKind 是占位(鸿蒙 ArkWeb,
|
|
46
|
-
* Android 接入时由其 Provider 决定),特性位清单接端实测后修正。
|
|
47
|
-
*/
|
|
48
|
-
public static func mobile(filesDir: String, arch: String): AppContext {
|
|
49
|
-
let target = TargetInfo("Linux", arch, "arkweb", "mobile")
|
|
50
|
-
let fs = ArrayList<PlatformFeature>()
|
|
51
|
-
fs.add(PlatformFeature.MultiWindow)
|
|
52
|
-
fs.add(PlatformFeature.ClipboardImage)
|
|
53
|
-
fs.add(PlatformFeature.SoftKeyboardInset)
|
|
54
|
-
return AppContext(
|
|
55
|
-
AppPaths(filesDir, "${filesDir}/cache", "${filesDir}/cache/tmp"),
|
|
56
|
-
target, false, fs)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ---- 平台名与目录根:@When 成对门禁,只落在这几个函数(RFC §5.3)----
|
|
60
|
-
|
|
61
|
-
/** dev server 探测:子包不引用父包,直接读环境变量(与 TauriApp.devUrl() 同语义) */
|
|
62
|
-
private static func devMode(): Bool {
|
|
63
|
-
if (let Some(v) <- getVariable("CJ_TAURI_DEV_URL")) {
|
|
64
|
-
if (v.size > 0) {
|
|
65
|
-
return true
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return false
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* 当前目标的 TargetInfo(批次 1:装配层 resolveHost 用它选宿主)
|
|
73
|
-
*
|
|
74
|
-
* ohos 报 HarmonyOS/arkweb/mobile(运行时 os 虽取 Linux,语义归鸿蒙);
|
|
75
|
-
* arch 从 CJ_TAURI_ARCH 环境变量取——编译期拿不到可靠的 arch,
|
|
76
|
-
* 由 hvigor / CLI 构建时注入(未注入为 unknown,宿主选择请勿依赖 arch,
|
|
77
|
-
* 用 hostKind/display 区分——它们正是为「同 os 多宿主」设计的)。
|
|
78
|
-
*/
|
|
79
|
-
public static func guessTarget(): TargetInfo {
|
|
80
|
-
let arch = getVariable("CJ_TAURI_ARCH") ?? "unknown"
|
|
81
|
-
return TargetInfo(currentOs(), arch, currentHostKind(), currentDisplay())
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
@When[env == "ohos"]
|
|
85
|
-
private static func currentOs(): String {
|
|
86
|
-
return "HarmonyOS"
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
@When[env != "ohos"]
|
|
90
|
-
private static func currentOs(): String {
|
|
91
|
-
return desktopOs()
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
@When[env == "ohos"]
|
|
95
|
-
private static func currentHostKind(): String {
|
|
96
|
-
return "arkweb"
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
@When[env != "ohos"]
|
|
100
|
-
private static func currentHostKind(): String {
|
|
101
|
-
return desktopHostKind()
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
@When[env == "ohos"]
|
|
105
|
-
private static func currentDisplay(): String {
|
|
106
|
-
return "mobile"
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
@When[env != "ohos"]
|
|
110
|
-
private static func currentDisplay(): String {
|
|
111
|
-
return "desktop"
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
@When[os == "Windows"]
|
|
115
|
-
private static func desktopOs(): String {
|
|
116
|
-
return "Windows"
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
@When[os != "Windows"]
|
|
120
|
-
private static func desktopOs(): String {
|
|
121
|
-
return "Linux"
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
@When[os == "Windows"]
|
|
125
|
-
private static func desktopHostKind(): String {
|
|
126
|
-
return "webview2"
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
@When[os != "Windows"]
|
|
130
|
-
private static func desktopHostKind(): String {
|
|
131
|
-
return "webkitgtk"
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
@When[os == "Windows"]
|
|
135
|
-
private static func dataRoot(): String {
|
|
136
|
-
return getVariable("APPDATA") ?? "."
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
@When[os == "Windows"]
|
|
140
|
-
private static func cacheRoot(): String {
|
|
141
|
-
return getVariable("LOCALAPPDATA") ?? "."
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
@When[os == "Linux" && env != "ohos"]
|
|
145
|
-
private static func dataRoot(): String {
|
|
146
|
-
return getVariable("XDG_DATA_HOME") ?? "${getVariable("HOME") ?? "."}/.local/share"
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
@When[os == "Linux" && env != "ohos"]
|
|
150
|
-
private static func cacheRoot(): String {
|
|
151
|
-
return getVariable("XDG_CACHE_HOME") ?? "${getVariable("HOME") ?? "."}/.cache"
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// ohos 目标上 desktop() 不会被调用,但符号必须存在才能编译;
|
|
155
|
-
// 返回占位值,真机路径由 mobile(filesDir) 提供。
|
|
156
|
-
@When[env == "ohos"]
|
|
157
|
-
private static func dataRoot(): String {
|
|
158
|
-
return "."
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
@When[env == "ohos"]
|
|
162
|
-
private static func cacheRoot(): String {
|
|
163
|
-
return "."
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// 其余目标(macOS 等)暂按 HOME 兜底:接入对应端时在这里补实现并真机验证。
|
|
167
|
-
@When[os != "Windows" && os != "Linux"]
|
|
168
|
-
private static func dataRoot(): String {
|
|
169
|
-
return "${getVariable("HOME") ?? "."}/.local/share"
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
@When[os != "Windows" && os != "Linux"]
|
|
173
|
-
private static func cacheRoot(): String {
|
|
174
|
-
return "${getVariable("HOME") ?? "."}/.cache"
|
|
175
|
-
}
|
|
176
|
-
}
|
|
1
|
+
package cjTauri.platform
|
|
2
|
+
|
|
3
|
+
import std.env.*
|
|
4
|
+
import std.collection.ArrayList
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 平台发现(RFC-002 §4.2 / §5.3)——全框架唯一的「端在哪儿」知识入口
|
|
8
|
+
*
|
|
9
|
+
* 按约定(RFC §5.3),os 名匹配的 @When 只允许出现在本文件与 targets 目录下的生成胶水;
|
|
10
|
+
* CI 用 `grep -r '@When\[os' src/ | grep -v src/platform/` 守这条线。
|
|
11
|
+
* @When 分支一律成对出现(本仓库惯例,参照 host_webview2.cj),保证任何目标下每个
|
|
12
|
+
* 符号恰好有一个定义;跨平台文件里只用短名。
|
|
13
|
+
*
|
|
14
|
+
* 批次 0 边界:本文件只提供**可编译的默认实现**(桌面 Linux / Windows 实测,
|
|
15
|
+
* 鸿蒙走 mobile(filesDir)),特性位清单是占位值,接端时按实测修正。
|
|
16
|
+
*/
|
|
17
|
+
public class Platform {
|
|
18
|
+
/**
|
|
19
|
+
* 桌面端默认发现:paths 走平台规范目录(RFC §5.2),dev 看 CJ_TAURI_DEV_URL
|
|
20
|
+
*
|
|
21
|
+
* arch 默认 x86_64;ARM64 Linux 桌面请显式传 arch(它的 os 与 x86_64 Linux 相同,
|
|
22
|
+
* 这是仓库已知的「同 os 多宿主」来源,见 RFC §5.1)。
|
|
23
|
+
* appId 由 launch() 从清单传入(清单解析在批次 1 落地,见 RFC §3/§13.1 风险 1)。
|
|
24
|
+
*/
|
|
25
|
+
public static func discover(appId: String, arch: String): AppContext {
|
|
26
|
+
return desktop(appId, arch)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public static func desktop(appId: String, arch: String): AppContext {
|
|
30
|
+
let data = "${dataRoot()}/${appId}"
|
|
31
|
+
let target = TargetInfo(desktopOs(), arch, desktopHostKind(), "desktop")
|
|
32
|
+
let fs = ArrayList<PlatformFeature>()
|
|
33
|
+
fs.add(PlatformFeature.MultiWindow)
|
|
34
|
+
fs.add(PlatformFeature.FilePicker)
|
|
35
|
+
fs.add(PlatformFeature.ClipboardImage)
|
|
36
|
+
fs.add(PlatformFeature.Tray)
|
|
37
|
+
return AppContext(
|
|
38
|
+
AppPaths(data, "${cacheRoot()}/${appId}", "${cacheRoot()}/${appId}/tmp"),
|
|
39
|
+
target, devMode(), fs)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 移动端发现:沙箱目录由系统能力入口传入(鸿蒙 Ability 的 filesDir / Android 的 filesDir)
|
|
44
|
+
*
|
|
45
|
+
* 沙箱端没有 dev server,dev 恒为 false;hostKind 是占位(鸿蒙 ArkWeb,
|
|
46
|
+
* Android 接入时由其 Provider 决定),特性位清单接端实测后修正。
|
|
47
|
+
*/
|
|
48
|
+
public static func mobile(filesDir: String, arch: String): AppContext {
|
|
49
|
+
let target = TargetInfo("Linux", arch, "arkweb", "mobile")
|
|
50
|
+
let fs = ArrayList<PlatformFeature>()
|
|
51
|
+
fs.add(PlatformFeature.MultiWindow)
|
|
52
|
+
fs.add(PlatformFeature.ClipboardImage)
|
|
53
|
+
fs.add(PlatformFeature.SoftKeyboardInset)
|
|
54
|
+
return AppContext(
|
|
55
|
+
AppPaths(filesDir, "${filesDir}/cache", "${filesDir}/cache/tmp"),
|
|
56
|
+
target, false, fs)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ---- 平台名与目录根:@When 成对门禁,只落在这几个函数(RFC §5.3)----
|
|
60
|
+
|
|
61
|
+
/** dev server 探测:子包不引用父包,直接读环境变量(与 TauriApp.devUrl() 同语义) */
|
|
62
|
+
private static func devMode(): Bool {
|
|
63
|
+
if (let Some(v) <- getVariable("CJ_TAURI_DEV_URL")) {
|
|
64
|
+
if (v.size > 0) {
|
|
65
|
+
return true
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 当前目标的 TargetInfo(批次 1:装配层 resolveHost 用它选宿主)
|
|
73
|
+
*
|
|
74
|
+
* ohos 报 HarmonyOS/arkweb/mobile(运行时 os 虽取 Linux,语义归鸿蒙);
|
|
75
|
+
* arch 从 CJ_TAURI_ARCH 环境变量取——编译期拿不到可靠的 arch,
|
|
76
|
+
* 由 hvigor / CLI 构建时注入(未注入为 unknown,宿主选择请勿依赖 arch,
|
|
77
|
+
* 用 hostKind/display 区分——它们正是为「同 os 多宿主」设计的)。
|
|
78
|
+
*/
|
|
79
|
+
public static func guessTarget(): TargetInfo {
|
|
80
|
+
let arch = getVariable("CJ_TAURI_ARCH") ?? "unknown"
|
|
81
|
+
return TargetInfo(currentOs(), arch, currentHostKind(), currentDisplay())
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@When[env == "ohos"]
|
|
85
|
+
private static func currentOs(): String {
|
|
86
|
+
return "HarmonyOS"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@When[env != "ohos"]
|
|
90
|
+
private static func currentOs(): String {
|
|
91
|
+
return desktopOs()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@When[env == "ohos"]
|
|
95
|
+
private static func currentHostKind(): String {
|
|
96
|
+
return "arkweb"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@When[env != "ohos"]
|
|
100
|
+
private static func currentHostKind(): String {
|
|
101
|
+
return desktopHostKind()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@When[env == "ohos"]
|
|
105
|
+
private static func currentDisplay(): String {
|
|
106
|
+
return "mobile"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@When[env != "ohos"]
|
|
110
|
+
private static func currentDisplay(): String {
|
|
111
|
+
return "desktop"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@When[os == "Windows"]
|
|
115
|
+
private static func desktopOs(): String {
|
|
116
|
+
return "Windows"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@When[os != "Windows"]
|
|
120
|
+
private static func desktopOs(): String {
|
|
121
|
+
return "Linux"
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@When[os == "Windows"]
|
|
125
|
+
private static func desktopHostKind(): String {
|
|
126
|
+
return "webview2"
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@When[os != "Windows"]
|
|
130
|
+
private static func desktopHostKind(): String {
|
|
131
|
+
return "webkitgtk"
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@When[os == "Windows"]
|
|
135
|
+
private static func dataRoot(): String {
|
|
136
|
+
return getVariable("APPDATA") ?? "."
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@When[os == "Windows"]
|
|
140
|
+
private static func cacheRoot(): String {
|
|
141
|
+
return getVariable("LOCALAPPDATA") ?? "."
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@When[os == "Linux" && env != "ohos"]
|
|
145
|
+
private static func dataRoot(): String {
|
|
146
|
+
return getVariable("XDG_DATA_HOME") ?? "${getVariable("HOME") ?? "."}/.local/share"
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@When[os == "Linux" && env != "ohos"]
|
|
150
|
+
private static func cacheRoot(): String {
|
|
151
|
+
return getVariable("XDG_CACHE_HOME") ?? "${getVariable("HOME") ?? "."}/.cache"
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ohos 目标上 desktop() 不会被调用,但符号必须存在才能编译;
|
|
155
|
+
// 返回占位值,真机路径由 mobile(filesDir) 提供。
|
|
156
|
+
@When[env == "ohos"]
|
|
157
|
+
private static func dataRoot(): String {
|
|
158
|
+
return "."
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@When[env == "ohos"]
|
|
162
|
+
private static func cacheRoot(): String {
|
|
163
|
+
return "."
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 其余目标(macOS 等)暂按 HOME 兜底:接入对应端时在这里补实现并真机验证。
|
|
167
|
+
@When[os != "Windows" && os != "Linux"]
|
|
168
|
+
private static func dataRoot(): String {
|
|
169
|
+
return "${getVariable("HOME") ?? "."}/.local/share"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@When[os != "Windows" && os != "Linux"]
|
|
173
|
+
private static func cacheRoot(): String {
|
|
174
|
+
return "${getVariable("HOME") ?? "."}/.cache"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
package cjTauri.platform
|
|
2
|
-
|
|
3
|
-
import std.collection.ArrayList
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* L0 适配层契约(RFC-002 §5.1)——每端各实现一份,框架只依赖这些接口
|
|
7
|
-
*
|
|
8
|
-
* 这些接口**不是给业务用的**:业务拿到的只有 AppContext。
|
|
9
|
-
* 批次 1 接入装配层时,Platform.discover() 会按端挑选实现。
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
/** 资产读取:按逻辑名取内容(读盘 / 内嵌常量 / rawfile 由实现决定) */
|
|
13
|
-
public interface AssetResolver {
|
|
14
|
-
func readText(name: String): Option<String>
|
|
15
|
-
func exists(name: String): Bool
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/** 目录与特性发现:沙箱端必须实现,桌面端由 Platform 给默认 */
|
|
19
|
-
public interface PlatformEnv {
|
|
20
|
-
func paths(appId: String): AppPaths
|
|
21
|
-
func assets(root: String): AssetResolver
|
|
22
|
-
/** RFC 写 Set<PlatformFeature>;批次 0 用 ArrayList 近似,接口定型时统一替换 */
|
|
23
|
-
func features(): ArrayList<PlatformFeature>
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** 页面材化:把 Asset 逻辑名变成宿主可加载的形态(L0 内部细节) */
|
|
27
|
-
public interface PageMaterializer {
|
|
28
|
-
func resolve(asset: String, page: String): PageSource
|
|
29
|
-
}
|
|
1
|
+
package cjTauri.platform
|
|
2
|
+
|
|
3
|
+
import std.collection.ArrayList
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* L0 适配层契约(RFC-002 §5.1)——每端各实现一份,框架只依赖这些接口
|
|
7
|
+
*
|
|
8
|
+
* 这些接口**不是给业务用的**:业务拿到的只有 AppContext。
|
|
9
|
+
* 批次 1 接入装配层时,Platform.discover() 会按端挑选实现。
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** 资产读取:按逻辑名取内容(读盘 / 内嵌常量 / rawfile 由实现决定) */
|
|
13
|
+
public interface AssetResolver {
|
|
14
|
+
func readText(name: String): Option<String>
|
|
15
|
+
func exists(name: String): Bool
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** 目录与特性发现:沙箱端必须实现,桌面端由 Platform 给默认 */
|
|
19
|
+
public interface PlatformEnv {
|
|
20
|
+
func paths(appId: String): AppPaths
|
|
21
|
+
func assets(root: String): AssetResolver
|
|
22
|
+
/** RFC 写 Set<PlatformFeature>;批次 0 用 ArrayList 近似,接口定型时统一替换 */
|
|
23
|
+
func features(): ArrayList<PlatformFeature>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** 页面材化:把 Asset 逻辑名变成宿主可加载的形态(L0 内部细节) */
|
|
27
|
+
public interface PageMaterializer {
|
|
28
|
+
func resolve(asset: String, page: String): PageSource
|
|
29
|
+
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
package cjTauri.platform
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 平台特性位(RFC-002 §4.5)——业务判断"这个端有没有某设施"的唯一手段
|
|
5
|
-
*
|
|
6
|
-
* 命名约定(评审定稿):**看到 PlatformFeature 只谈可用性,看到 Capability 只谈权限**。
|
|
7
|
-
* - 平台特性 = 本枚举:这个端的系统设施有没有(托盘、文件选择器……);
|
|
8
|
-
* - 安全能力 = CapabilitySet(capability.cj):哪条命令允许被前端调用。
|
|
9
|
-
* 两者中文都容易被叫成"能力",类型名必须分开,否则会退化回 os 分支。
|
|
10
|
-
*
|
|
11
|
-
* 治理规则(RFC §13.2 问题 4):新增一个特性位,必须同时写清三端语义与缺省降级行为,
|
|
12
|
-
* 否则业务会把它当成按 OS 名分支的马甲。
|
|
13
|
-
*/
|
|
14
|
-
public enum PlatformFeature {
|
|
15
|
-
| Tray // 托盘
|
|
16
|
-
| MultiWindow // 多窗口(桌面)/ 多任务(移动端)
|
|
17
|
-
| FilePicker // 系统文件选择器
|
|
18
|
-
| ClipboardImage // 剪贴板图片读写
|
|
19
|
-
| SoftKeyboardInset // 软键盘遮挡可感知(移动端)
|
|
20
|
-
|
|
21
|
-
/** 枚举无内建 ==(1.2.0 实测),比较走模式匹配 */
|
|
22
|
-
public static func same(a: PlatformFeature, b: PlatformFeature): Bool {
|
|
23
|
-
match (a) {
|
|
24
|
-
case Tray => match (b) { case Tray => true case _ => false }
|
|
25
|
-
case MultiWindow => match (b) { case MultiWindow => true case _ => false }
|
|
26
|
-
case FilePicker => match (b) { case FilePicker => true case _ => false }
|
|
27
|
-
case ClipboardImage => match (b) { case ClipboardImage => true case _ => false }
|
|
28
|
-
case SoftKeyboardInset => match (b) { case SoftKeyboardInset => true case _ => false }
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
1
|
+
package cjTauri.platform
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 平台特性位(RFC-002 §4.5)——业务判断"这个端有没有某设施"的唯一手段
|
|
5
|
+
*
|
|
6
|
+
* 命名约定(评审定稿):**看到 PlatformFeature 只谈可用性,看到 Capability 只谈权限**。
|
|
7
|
+
* - 平台特性 = 本枚举:这个端的系统设施有没有(托盘、文件选择器……);
|
|
8
|
+
* - 安全能力 = CapabilitySet(capability.cj):哪条命令允许被前端调用。
|
|
9
|
+
* 两者中文都容易被叫成"能力",类型名必须分开,否则会退化回 os 分支。
|
|
10
|
+
*
|
|
11
|
+
* 治理规则(RFC §13.2 问题 4):新增一个特性位,必须同时写清三端语义与缺省降级行为,
|
|
12
|
+
* 否则业务会把它当成按 OS 名分支的马甲。
|
|
13
|
+
*/
|
|
14
|
+
public enum PlatformFeature {
|
|
15
|
+
| Tray // 托盘
|
|
16
|
+
| MultiWindow // 多窗口(桌面)/ 多任务(移动端)
|
|
17
|
+
| FilePicker // 系统文件选择器
|
|
18
|
+
| ClipboardImage // 剪贴板图片读写
|
|
19
|
+
| SoftKeyboardInset // 软键盘遮挡可感知(移动端)
|
|
20
|
+
|
|
21
|
+
/** 枚举无内建 ==(1.2.0 实测),比较走模式匹配 */
|
|
22
|
+
public static func same(a: PlatformFeature, b: PlatformFeature): Bool {
|
|
23
|
+
match (a) {
|
|
24
|
+
case Tray => match (b) { case Tray => true case _ => false }
|
|
25
|
+
case MultiWindow => match (b) { case MultiWindow => true case _ => false }
|
|
26
|
+
case FilePicker => match (b) { case FilePicker => true case _ => false }
|
|
27
|
+
case ClipboardImage => match (b) { case ClipboardImage => true case _ => false }
|
|
28
|
+
case SoftKeyboardInset => match (b) { case SoftKeyboardInset => true case _ => false }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
package cjTauri.platform
|
|
2
|
-
|
|
3
|
-
import std.fs.*
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 页面来源(RFC-002 §4.3)——取代 run(html) / runUrl(url) 双入口的唯一表达
|
|
7
|
-
*
|
|
8
|
-
* 业务与清单只写 Asset("ui/index.html") 这一种;devMode 下由框架改写为
|
|
9
|
-
* DevServer;Asset 在各端怎么落地(读盘 / rawfile 材化 / assets base URL)
|
|
10
|
-
* 是 L0 适配层(PageMaterializer)的事,业务与骨架都不接触沙箱路径。
|
|
11
|
-
*/
|
|
12
|
-
public enum PageSource {
|
|
13
|
-
/** 代码里直接给的 HTML 字符串(探针、错误页用) */
|
|
14
|
-
| Inline(String)
|
|
15
|
-
/** 资产逻辑名,如 "ui/index.html"(sync 生成期校验存在,见 RFC §6.1) */
|
|
16
|
-
| Asset(String)
|
|
17
|
-
/** http(s):// 或 file:// 直载 */
|
|
18
|
-
| Url(String)
|
|
19
|
-
/** 开发期前端 dev server(HMR),由 CJ_TAURI_DEV_URL 注入 */
|
|
20
|
-
| DevServer(String)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** 解析结果:宿主最终执行的动作(纯数据,可测) */
|
|
24
|
-
public enum PageLoad {
|
|
25
|
-
| StartHtml(String) // host.start(html)
|
|
26
|
-
| StartUrl(String) // host.startUrl(url)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* PageSource → PageLoad 的唯一决策点(批次 1,RFC §4.3)
|
|
31
|
-
*
|
|
32
|
-
* - Inline / Url / DevServer:直接映射
|
|
33
|
-
* - Asset:优先走注入的 AssetResolver;未注入时按 cwd 相对路径读盘——与现有模板
|
|
34
|
-
* textOrFile 的桌面行为等价,鸿蒙 rawfile / 内嵌常量的实现在批次 2 随清单接入
|
|
35
|
-
* - 找不到资产:抛可照做的错误,不静默白屏(与宿主装配「不静默回落」同约定)
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
/** 资产解析异常:message 即面向用户的措辞。子包不引用根包的 CommandException
|
|
39
|
-
* (那会构成父↔子互引),独立定义;传播路径与原先一致(run() 路径上无人
|
|
40
|
-
* 按具体类型捕获,message 原样抛到顶层) */
|
|
41
|
-
public class AssetResolutionException <: Exception {
|
|
42
|
-
public init(msg: String) {
|
|
43
|
-
super(msg)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
public func resolvePage(source: PageSource, resolver: Option<AssetResolver>): PageLoad {
|
|
48
|
-
match (source) {
|
|
49
|
-
case Inline(html) => return PageLoad.StartHtml(html)
|
|
50
|
-
case Url(url) => return PageLoad.StartUrl(url)
|
|
51
|
-
case DevServer(url) => return PageLoad.StartUrl(url)
|
|
52
|
-
case Asset(name) =>
|
|
53
|
-
match (resolver) {
|
|
54
|
-
case Some(r) =>
|
|
55
|
-
match (r.readText(name)) {
|
|
56
|
-
case Some(html) => return PageLoad.StartHtml(html)
|
|
57
|
-
case None =>
|
|
58
|
-
throw AssetResolutionException("资产未找到:${name}(请检查注入的 AssetResolver 与清单 [assets] 配置)")
|
|
59
|
-
}
|
|
60
|
-
case None =>
|
|
61
|
-
var text = ""
|
|
62
|
-
try {
|
|
63
|
-
text = String.fromUtf8(File.readFrom(name))
|
|
64
|
-
} catch (e: Exception) {
|
|
65
|
-
throw AssetResolutionException("资产未找到:${name}(未注入 AssetResolver,按相对路径读盘失败:${e};鸿蒙 rawfile / 内嵌场景请注入对应解析器)")
|
|
66
|
-
}
|
|
67
|
-
return PageLoad.StartHtml(text)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* devMode 改写(RFC §4.3):CJ_TAURI_DEV_URL 存在时,Asset 页面自动改走 dev server
|
|
74
|
-
*
|
|
75
|
-
* 只改 Asset:显式 Inline(探针)/ Url / DevServer 是业务明说的意图,不改写。
|
|
76
|
-
* 纯函数,可测。
|
|
77
|
-
*/
|
|
78
|
-
public func rewriteForDev(source: PageSource, devUrl: Option<String>): PageSource {
|
|
79
|
-
match (devUrl) {
|
|
80
|
-
case Some(url) =>
|
|
81
|
-
match (source) {
|
|
82
|
-
case Asset(_) => return PageSource.DevServer(url)
|
|
83
|
-
case _ => return source
|
|
84
|
-
}
|
|
85
|
-
case None => return source
|
|
86
|
-
}
|
|
87
|
-
}
|
|
1
|
+
package cjTauri.platform
|
|
2
|
+
|
|
3
|
+
import std.fs.*
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 页面来源(RFC-002 §4.3)——取代 run(html) / runUrl(url) 双入口的唯一表达
|
|
7
|
+
*
|
|
8
|
+
* 业务与清单只写 Asset("ui/index.html") 这一种;devMode 下由框架改写为
|
|
9
|
+
* DevServer;Asset 在各端怎么落地(读盘 / rawfile 材化 / assets base URL)
|
|
10
|
+
* 是 L0 适配层(PageMaterializer)的事,业务与骨架都不接触沙箱路径。
|
|
11
|
+
*/
|
|
12
|
+
public enum PageSource {
|
|
13
|
+
/** 代码里直接给的 HTML 字符串(探针、错误页用) */
|
|
14
|
+
| Inline(String)
|
|
15
|
+
/** 资产逻辑名,如 "ui/index.html"(sync 生成期校验存在,见 RFC §6.1) */
|
|
16
|
+
| Asset(String)
|
|
17
|
+
/** http(s):// 或 file:// 直载 */
|
|
18
|
+
| Url(String)
|
|
19
|
+
/** 开发期前端 dev server(HMR),由 CJ_TAURI_DEV_URL 注入 */
|
|
20
|
+
| DevServer(String)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** 解析结果:宿主最终执行的动作(纯数据,可测) */
|
|
24
|
+
public enum PageLoad {
|
|
25
|
+
| StartHtml(String) // host.start(html)
|
|
26
|
+
| StartUrl(String) // host.startUrl(url)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* PageSource → PageLoad 的唯一决策点(批次 1,RFC §4.3)
|
|
31
|
+
*
|
|
32
|
+
* - Inline / Url / DevServer:直接映射
|
|
33
|
+
* - Asset:优先走注入的 AssetResolver;未注入时按 cwd 相对路径读盘——与现有模板
|
|
34
|
+
* textOrFile 的桌面行为等价,鸿蒙 rawfile / 内嵌常量的实现在批次 2 随清单接入
|
|
35
|
+
* - 找不到资产:抛可照做的错误,不静默白屏(与宿主装配「不静默回落」同约定)
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/** 资产解析异常:message 即面向用户的措辞。子包不引用根包的 CommandException
|
|
39
|
+
* (那会构成父↔子互引),独立定义;传播路径与原先一致(run() 路径上无人
|
|
40
|
+
* 按具体类型捕获,message 原样抛到顶层) */
|
|
41
|
+
public class AssetResolutionException <: Exception {
|
|
42
|
+
public init(msg: String) {
|
|
43
|
+
super(msg)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public func resolvePage(source: PageSource, resolver: Option<AssetResolver>): PageLoad {
|
|
48
|
+
match (source) {
|
|
49
|
+
case Inline(html) => return PageLoad.StartHtml(html)
|
|
50
|
+
case Url(url) => return PageLoad.StartUrl(url)
|
|
51
|
+
case DevServer(url) => return PageLoad.StartUrl(url)
|
|
52
|
+
case Asset(name) =>
|
|
53
|
+
match (resolver) {
|
|
54
|
+
case Some(r) =>
|
|
55
|
+
match (r.readText(name)) {
|
|
56
|
+
case Some(html) => return PageLoad.StartHtml(html)
|
|
57
|
+
case None =>
|
|
58
|
+
throw AssetResolutionException("资产未找到:${name}(请检查注入的 AssetResolver 与清单 [assets] 配置)")
|
|
59
|
+
}
|
|
60
|
+
case None =>
|
|
61
|
+
var text = ""
|
|
62
|
+
try {
|
|
63
|
+
text = String.fromUtf8(File.readFrom(name))
|
|
64
|
+
} catch (e: Exception) {
|
|
65
|
+
throw AssetResolutionException("资产未找到:${name}(未注入 AssetResolver,按相对路径读盘失败:${e};鸿蒙 rawfile / 内嵌场景请注入对应解析器)")
|
|
66
|
+
}
|
|
67
|
+
return PageLoad.StartHtml(text)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* devMode 改写(RFC §4.3):CJ_TAURI_DEV_URL 存在时,Asset 页面自动改走 dev server
|
|
74
|
+
*
|
|
75
|
+
* 只改 Asset:显式 Inline(探针)/ Url / DevServer 是业务明说的意图,不改写。
|
|
76
|
+
* 纯函数,可测。
|
|
77
|
+
*/
|
|
78
|
+
public func rewriteForDev(source: PageSource, devUrl: Option<String>): PageSource {
|
|
79
|
+
match (devUrl) {
|
|
80
|
+
case Some(url) =>
|
|
81
|
+
match (source) {
|
|
82
|
+
case Asset(_) => return PageSource.DevServer(url)
|
|
83
|
+
case _ => return source
|
|
84
|
+
}
|
|
85
|
+
case None => return source
|
|
86
|
+
}
|
|
87
|
+
}
|