@tishlang/tish-desktop 1.1.1 → 1.1.4
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/package.json +1 -1
- package/src/commands/build.tish +14 -14
- package/src/commands/dev.tish +85 -52
- package/src/commands/distribute.tish +25 -15
- package/src/commands/doctor.tish +34 -18
- package/src/commands/icon.tish +10 -11
- package/src/commands/info.tish +3 -1
- package/src/commands/init.tish +55 -17
- package/src/commands/ios.tish +13 -13
- package/src/main.tish +9 -3
- package/src/paths.tish +112 -37
- package/templates/app/scripts/build-css.tish +2 -2
- package/templates/app/ui/main.tish +2 -6
- package/templates/bare/app/App.tish +9 -9
- package/templates/bare/src/main.tish +1 -8
package/package.json
CHANGED
package/src/commands/build.tish
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { exit, cwd, exec } from "tish:process"
|
|
2
|
-
import {
|
|
3
|
-
firstPositional,
|
|
4
|
-
joinPath,
|
|
5
|
-
pathExists,
|
|
6
|
-
q,
|
|
7
|
-
repoRoot,
|
|
8
|
-
resolveTish,
|
|
9
|
-
} from "../paths.tish"
|
|
2
|
+
import { firstPositional, joinPath, pathExists, q, repoRoot, resolveTish } from "../paths.tish"
|
|
10
3
|
|
|
11
4
|
fn sh(cmd) {
|
|
12
5
|
console.log("-> " + cmd)
|
|
@@ -24,10 +17,16 @@ export fn runBuild(args) {
|
|
|
24
17
|
|
|
25
18
|
if (name !== null && pathExists(joinPath(root, "examples/" + name))) {
|
|
26
19
|
projectDir = joinPath(root, "examples/" + name)
|
|
27
|
-
} else
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
} else {
|
|
21
|
+
if (name !== null) {
|
|
22
|
+
let candidate = name
|
|
23
|
+
if (!String(name).startsWith("/")) {
|
|
24
|
+
candidate = joinPath(cwd(), name)
|
|
25
|
+
}
|
|
26
|
+
if (pathExists(candidate)) {
|
|
27
|
+
projectDir = candidate
|
|
28
|
+
}
|
|
29
|
+
}
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
if (!pathExists(joinPath(projectDir, "package.json"))) {
|
|
@@ -46,8 +45,9 @@ export fn runBuild(args) {
|
|
|
46
45
|
let out = "dist/app-shell"
|
|
47
46
|
console.log("[build] npm run build:shell missing/failed — compiling " + out)
|
|
48
47
|
sh(
|
|
49
|
-
"cd " + q(projectDir) + " && " + q(tishBin) +
|
|
50
|
-
|
|
48
|
+
"cd " + q(projectDir) + " && " + q(tishBin) + " build --target native --native-backend rust src/main.tish -o " + q(
|
|
49
|
+
out
|
|
50
|
+
)
|
|
51
51
|
)
|
|
52
52
|
}
|
|
53
53
|
|
package/src/commands/dev.tish
CHANGED
|
@@ -3,31 +3,40 @@
|
|
|
3
3
|
// backgrounded with `sh -c '… &'`. Pass --legacy-node to call the Node script.
|
|
4
4
|
import { exit, cwd, exec, env } from "tish:process"
|
|
5
5
|
import { readFile } from "tish:fs"
|
|
6
|
-
import {
|
|
7
|
-
flagValue,
|
|
8
|
-
firstPositional,
|
|
9
|
-
hasFlag,
|
|
10
|
-
joinPath,
|
|
11
|
-
pathExists,
|
|
12
|
-
q,
|
|
13
|
-
repoRoot,
|
|
14
|
-
resolveTish,
|
|
15
|
-
} from "../paths.tish"
|
|
6
|
+
import { flagValue, firstPositional, hasFlag, joinPath, pathExists, q, repoRoot, resolveTish } from "../paths.tish"
|
|
16
7
|
|
|
17
8
|
fn examplePort(name) {
|
|
18
|
-
if (name === "file-browser")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (name === "
|
|
9
|
+
if (name === "file-browser") {
|
|
10
|
+
return 5174
|
|
11
|
+
}
|
|
12
|
+
if (name === "native-chrome") {
|
|
13
|
+
return 5175
|
|
14
|
+
}
|
|
15
|
+
if (name === "byo-ui") {
|
|
16
|
+
return 5176
|
|
17
|
+
}
|
|
18
|
+
if (name === "hybrid") {
|
|
19
|
+
return 5177
|
|
20
|
+
}
|
|
22
21
|
return 5173
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
fn exampleShellOut(name) {
|
|
26
|
-
if (name === "basic")
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (name === "
|
|
30
|
-
|
|
25
|
+
if (name === "basic") {
|
|
26
|
+
return "dist/basic-shell"
|
|
27
|
+
}
|
|
28
|
+
if (name === "file-browser") {
|
|
29
|
+
return "dist/file-browser-shell"
|
|
30
|
+
}
|
|
31
|
+
if (name === "native-chrome") {
|
|
32
|
+
return "dist/native-chrome-shell"
|
|
33
|
+
}
|
|
34
|
+
if (name === "byo-ui") {
|
|
35
|
+
return "dist/byo-ui-shell"
|
|
36
|
+
}
|
|
37
|
+
if (name === "hybrid") {
|
|
38
|
+
return "dist/hybrid-shell"
|
|
39
|
+
}
|
|
31
40
|
return "dist/" + name + "-shell"
|
|
32
41
|
}
|
|
33
42
|
|
|
@@ -37,19 +46,29 @@ fn sleepMs(ms) {
|
|
|
37
46
|
|
|
38
47
|
fn httpCode(url) {
|
|
39
48
|
let out = "/tmp/tish-desktop-http-code.txt"
|
|
40
|
-
exec(
|
|
41
|
-
|
|
49
|
+
exec(
|
|
50
|
+
"curl -s -o /dev/null -w '%{http_code}' " + q(url) + " > " + q(out) + " 2>/dev/null || echo 000 > " + q(
|
|
51
|
+
out
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
if (!pathExists(out)) {
|
|
55
|
+
return "000"
|
|
56
|
+
}
|
|
42
57
|
return String(readFile(out)).trim()
|
|
43
58
|
}
|
|
44
59
|
|
|
45
60
|
fn waitForHttp(url, timeoutMs) {
|
|
46
61
|
let maxTries = Math.floor(timeoutMs / 250)
|
|
47
|
-
if (maxTries < 1)
|
|
62
|
+
if (maxTries < 1) {
|
|
63
|
+
maxTries = 1
|
|
64
|
+
}
|
|
48
65
|
let n = 0
|
|
49
66
|
while (n < maxTries) {
|
|
50
67
|
let code = httpCode(url)
|
|
51
68
|
let num = Number(code)
|
|
52
|
-
if (num >= 200 && num < 500)
|
|
69
|
+
if (num >= 200 && num < 500) {
|
|
70
|
+
return true
|
|
71
|
+
}
|
|
53
72
|
sleepMs(250)
|
|
54
73
|
n = n + 1
|
|
55
74
|
}
|
|
@@ -61,7 +80,7 @@ fn warmupVite(baseUrl) {
|
|
|
61
80
|
baseUrl + "/",
|
|
62
81
|
baseUrl + "/assets/app.css",
|
|
63
82
|
baseUrl + "/bridge-boot.js",
|
|
64
|
-
baseUrl + "/ui/main.tish"
|
|
83
|
+
baseUrl + "/ui/main.tish"
|
|
65
84
|
]
|
|
66
85
|
let i = 0
|
|
67
86
|
while (i < urls.length) {
|
|
@@ -70,28 +89,28 @@ fn warmupVite(baseUrl) {
|
|
|
70
89
|
}
|
|
71
90
|
let bodyFile = "/tmp/tish-desktop-vite-main.txt"
|
|
72
91
|
exec(
|
|
73
|
-
"curl -s -H 'Accept: text/javascript' " + q(baseUrl + "/ui/main.tish") +
|
|
74
|
-
" > " + q(bodyFile) + " 2>/dev/null || true"
|
|
92
|
+
"curl -s -H 'Accept: text/javascript' " + q(baseUrl + "/ui/main.tish") + " > " + q(bodyFile) + " 2>/dev/null || true"
|
|
75
93
|
)
|
|
76
94
|
if (pathExists(bodyFile)) {
|
|
77
95
|
let text = String(readFile(bodyFile))
|
|
78
|
-
let parts = text.split(
|
|
96
|
+
let parts = text.split("from \"")
|
|
79
97
|
let p = 1
|
|
80
98
|
while (p < parts.length) {
|
|
81
99
|
let rest = parts[p]
|
|
82
|
-
let end = rest.indexOf(
|
|
100
|
+
let end = rest.indexOf("\"")
|
|
83
101
|
if (end > 0) {
|
|
84
102
|
let spec = rest.slice(0, end)
|
|
85
103
|
let next = null
|
|
86
104
|
if (spec.startsWith("./")) {
|
|
87
105
|
next = baseUrl + "/ui/" + spec.slice(2)
|
|
88
|
-
} else
|
|
89
|
-
|
|
106
|
+
} else {
|
|
107
|
+
if (spec.startsWith("/")) {
|
|
108
|
+
next = baseUrl + spec
|
|
109
|
+
}
|
|
90
110
|
}
|
|
91
111
|
if (next !== null) {
|
|
92
112
|
exec(
|
|
93
|
-
"curl -s -o /dev/null -H 'Accept: text/javascript' " + q(next) +
|
|
94
|
-
" >/dev/null 2>&1 || true"
|
|
113
|
+
"curl -s -o /dev/null -H 'Accept: text/javascript' " + q(next) + " >/dev/null 2>&1 || true"
|
|
95
114
|
)
|
|
96
115
|
}
|
|
97
116
|
}
|
|
@@ -104,8 +123,9 @@ fn warmupVite(baseUrl) {
|
|
|
104
123
|
fn buildShell(tishBin, exampleDir, shellOut, shellPath) {
|
|
105
124
|
console.log("[dev] building shell with " + tishBin + " → " + shellOut)
|
|
106
125
|
let code = exec(
|
|
107
|
-
"cd " + q(exampleDir) + " && " + q(tishBin) +
|
|
108
|
-
|
|
126
|
+
"cd " + q(exampleDir) + " && " + q(tishBin) + " build --target native --native-backend rust src/main.tish -o " + q(
|
|
127
|
+
shellOut
|
|
128
|
+
)
|
|
109
129
|
)
|
|
110
130
|
if (code !== 0) {
|
|
111
131
|
console.error("[dev] shell build failed (exit " + String(code) + ")")
|
|
@@ -118,18 +138,22 @@ fn buildShell(tishBin, exampleDir, shellOut, shellPath) {
|
|
|
118
138
|
}
|
|
119
139
|
|
|
120
140
|
fn shellNeedsRebuild(root, exampleDir, shellPath) {
|
|
121
|
-
if (!pathExists(shellPath))
|
|
141
|
+
if (!pathExists(shellPath)) {
|
|
142
|
+
return true
|
|
143
|
+
}
|
|
122
144
|
// Recursive: any file under host/shell sources newer than the binary.
|
|
123
145
|
let marker = "/tmp/tish-desktop-shell-stale.txt"
|
|
124
146
|
let hostSrc = joinPath(root, "crates/tish_desktop/src")
|
|
125
147
|
let hostToml = joinPath(root, "crates/tish_desktop/Cargo.toml")
|
|
126
148
|
let shellSrc = joinPath(exampleDir, "src")
|
|
127
149
|
exec(
|
|
128
|
-
"if [ -n \"$(find " + q(hostSrc) + " " + q(shellSrc) + " " + q(hostToml) +
|
|
129
|
-
|
|
130
|
-
|
|
150
|
+
"if [ -n \"$(find " + q(hostSrc) + " " + q(shellSrc) + " " + q(hostToml) + " -type f -newer " + q(
|
|
151
|
+
shellPath
|
|
152
|
+
) + " 2>/dev/null | head -1)\" ]; then echo yes; else echo no; fi > " + q(marker)
|
|
131
153
|
)
|
|
132
|
-
if (!pathExists(marker))
|
|
154
|
+
if (!pathExists(marker)) {
|
|
155
|
+
return true
|
|
156
|
+
}
|
|
133
157
|
return String(readFile(marker)).trim() === "yes"
|
|
134
158
|
}
|
|
135
159
|
|
|
@@ -146,8 +170,12 @@ export fn runDev(args) {
|
|
|
146
170
|
}
|
|
147
171
|
|
|
148
172
|
let name = flagValue(args, "--example")
|
|
149
|
-
if (name === null)
|
|
150
|
-
|
|
173
|
+
if (name === null) {
|
|
174
|
+
name = firstPositional(args)
|
|
175
|
+
}
|
|
176
|
+
if (name === null) {
|
|
177
|
+
name = "basic"
|
|
178
|
+
}
|
|
151
179
|
|
|
152
180
|
if (legacyNode) {
|
|
153
181
|
let script = joinPath(root, "scripts/dev-example.mjs")
|
|
@@ -165,34 +193,39 @@ export fn runDev(args) {
|
|
|
165
193
|
name = "app"
|
|
166
194
|
} else {
|
|
167
195
|
console.error("[dev] example not found: " + exampleDir)
|
|
168
|
-
console.error(
|
|
196
|
+
console.error(
|
|
197
|
+
" pass --example basic|file-browser|native-chrome|byo-ui|hybrid, or run inside an app dir"
|
|
198
|
+
)
|
|
169
199
|
exit(1)
|
|
170
200
|
}
|
|
171
201
|
}
|
|
172
202
|
|
|
173
203
|
let port = examplePort(name)
|
|
174
|
-
if (name === "app")
|
|
204
|
+
if (name === "app") {
|
|
205
|
+
port = 5173
|
|
206
|
+
}
|
|
175
207
|
let shellOut = exampleShellOut(name)
|
|
176
|
-
if (name === "app")
|
|
208
|
+
if (name === "app") {
|
|
209
|
+
shellOut = "dist/app-shell"
|
|
210
|
+
}
|
|
177
211
|
let shellPath = joinPath(exampleDir, shellOut)
|
|
178
212
|
|
|
179
|
-
console.log(
|
|
213
|
+
console.log(
|
|
214
|
+
"[dev] " + name + " — starting Vite :" + String(port) + ", then native desktop shell"
|
|
215
|
+
)
|
|
180
216
|
|
|
181
217
|
let cssScript = joinPath(exampleDir, "scripts/build-css.tish")
|
|
182
218
|
if (pathExists(cssScript)) {
|
|
183
|
-
let cssCode = exec(
|
|
184
|
-
"cd " + q(exampleDir) + " && tish run --feature fs scripts/build-css.tish"
|
|
185
|
-
)
|
|
219
|
+
let cssCode = exec("cd " + q(exampleDir) + " && tish run --feature fs scripts/build-css.tish")
|
|
186
220
|
if (cssCode !== 0) {
|
|
187
221
|
console.log("[dev] build-css failed (continuing; styles may be stale)")
|
|
188
222
|
}
|
|
189
223
|
}
|
|
190
224
|
|
|
191
225
|
killVite(port)
|
|
192
|
-
let viteCmd =
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
String(port) + ".log 2>&1 &"
|
|
226
|
+
let viteCmd = "cd " + q(exampleDir) + " && npx vite --port " + String(port) + " --strictPort >/tmp/tish-desktop-vite-" + String(
|
|
227
|
+
port
|
|
228
|
+
) + ".log 2>&1 &"
|
|
196
229
|
exec(viteCmd)
|
|
197
230
|
|
|
198
231
|
let baseUrl = "http://localhost:" + String(port)
|
|
@@ -31,22 +31,32 @@ export fn runDistribute(args) {
|
|
|
31
31
|
let cmd = null
|
|
32
32
|
if (step === "build") {
|
|
33
33
|
cmd = "node " + q(joinPath(distDir, "build-release.mjs"))
|
|
34
|
-
} else if (step === "sign") {
|
|
35
|
-
cmd = "bash " + q(joinPath(distDir, "sign-macos.sh"))
|
|
36
|
-
} else if (step === "notarize") {
|
|
37
|
-
cmd = "bash " + q(joinPath(distDir, "notarize-macos.sh"))
|
|
38
|
-
} else if (step === "updater") {
|
|
39
|
-
cmd = "node " + q(joinPath(distDir, "publish-updater.mjs"))
|
|
40
|
-
} else if (step === "github") {
|
|
41
|
-
cmd = "node " + q(joinPath(distDir, "publish-github-release.mjs"))
|
|
42
|
-
} else if (step === "release") {
|
|
43
|
-
cmd =
|
|
44
|
-
"node " + q(joinPath(distDir, "build-release.mjs")) +
|
|
45
|
-
" && node " + q(joinPath(distDir, "publish-github-release.mjs"))
|
|
46
34
|
} else {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
35
|
+
if (step === "sign") {
|
|
36
|
+
cmd = "bash " + q(joinPath(distDir, "sign-macos.sh"))
|
|
37
|
+
} else {
|
|
38
|
+
if (step === "notarize") {
|
|
39
|
+
cmd = "bash " + q(joinPath(distDir, "notarize-macos.sh"))
|
|
40
|
+
} else {
|
|
41
|
+
if (step === "updater") {
|
|
42
|
+
cmd = "node " + q(joinPath(distDir, "publish-updater.mjs"))
|
|
43
|
+
} else {
|
|
44
|
+
if (step === "github") {
|
|
45
|
+
cmd = "node " + q(joinPath(distDir, "publish-github-release.mjs"))
|
|
46
|
+
} else {
|
|
47
|
+
if (step === "release") {
|
|
48
|
+
cmd = "node " + q(joinPath(distDir, "build-release.mjs")) + " && node " + q(
|
|
49
|
+
joinPath(distDir, "publish-github-release.mjs")
|
|
50
|
+
)
|
|
51
|
+
} else {
|
|
52
|
+
console.error("unknown distribute step: " + step)
|
|
53
|
+
usage()
|
|
54
|
+
exit(1)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
50
60
|
}
|
|
51
61
|
|
|
52
62
|
console.log("[distribute] " + step)
|
package/src/commands/doctor.tish
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { exit, env, cwd, exec } from "tish:process"
|
|
2
2
|
import { readFile } from "tish:fs"
|
|
3
|
-
import {
|
|
4
|
-
flagValue,
|
|
5
|
-
joinPath,
|
|
6
|
-
pathExists,
|
|
7
|
-
q,
|
|
8
|
-
resolveTish,
|
|
9
|
-
} from "../paths.tish"
|
|
3
|
+
import { flagValue, joinPath, pathExists, q, resolveTish } from "../paths.tish"
|
|
10
4
|
|
|
11
5
|
fn capLevel(name, surface, platform) {
|
|
12
6
|
if (name === "notification") {
|
|
13
|
-
if (surface === "web")
|
|
7
|
+
if (surface === "web") {
|
|
8
|
+
return "Partial"
|
|
9
|
+
}
|
|
14
10
|
return "Full"
|
|
15
11
|
}
|
|
16
12
|
if (name === "store") {
|
|
17
|
-
if (surface === "web" || platform === "ios")
|
|
13
|
+
if (surface === "web" || platform === "ios") {
|
|
14
|
+
return "Unsupported"
|
|
15
|
+
}
|
|
18
16
|
return "Full"
|
|
19
17
|
}
|
|
20
18
|
if (name === "tray") {
|
|
21
|
-
if (surface === "web" || platform === "ios" || surface === "native")
|
|
19
|
+
if (surface === "web" || platform === "ios" || surface === "native") {
|
|
20
|
+
return "Unsupported"
|
|
21
|
+
}
|
|
22
22
|
return "Full"
|
|
23
23
|
}
|
|
24
24
|
return "Unsupported"
|
|
@@ -38,12 +38,20 @@ export fn runDoctor(args) {
|
|
|
38
38
|
// `--desk-platform` / `--desk-surface` are rewritten from `--platform` /
|
|
39
39
|
// `--surface` by cli/bin/mode.js so `tish run` is not disrupted.
|
|
40
40
|
let platform = flagValue(args, "--desk-platform")
|
|
41
|
-
if (platform === null)
|
|
42
|
-
|
|
41
|
+
if (platform === null) {
|
|
42
|
+
platform = flagValue(args, "--platform")
|
|
43
|
+
}
|
|
44
|
+
if (platform === null) {
|
|
45
|
+
platform = "macos"
|
|
46
|
+
}
|
|
43
47
|
|
|
44
48
|
let surface = flagValue(args, "--desk-surface")
|
|
45
|
-
if (surface === null)
|
|
46
|
-
|
|
49
|
+
if (surface === null) {
|
|
50
|
+
surface = flagValue(args, "--surface")
|
|
51
|
+
}
|
|
52
|
+
if (surface === null) {
|
|
53
|
+
surface = "webview"
|
|
54
|
+
}
|
|
47
55
|
|
|
48
56
|
let tish = resolveTish()
|
|
49
57
|
console.log("mode doctor")
|
|
@@ -53,13 +61,19 @@ export fn runDoctor(args) {
|
|
|
53
61
|
console.log(" tish: " + tish)
|
|
54
62
|
|
|
55
63
|
let probe = flagValue(args, "--resolve")
|
|
56
|
-
if (probe === null)
|
|
64
|
+
if (probe === null) {
|
|
65
|
+
probe = "./Button"
|
|
66
|
+
}
|
|
57
67
|
let importer = flagValue(args, "--importer")
|
|
58
68
|
if (importer === null) {
|
|
59
69
|
let here = cwd()
|
|
60
70
|
importer = joinPath(here, "src/main.tish")
|
|
61
|
-
if (!pathExists(importer))
|
|
62
|
-
|
|
71
|
+
if (!pathExists(importer)) {
|
|
72
|
+
importer = joinPath(here, "ui/main.tish")
|
|
73
|
+
}
|
|
74
|
+
if (!pathExists(importer)) {
|
|
75
|
+
importer = joinPath(here, "app/App.tish")
|
|
76
|
+
}
|
|
63
77
|
}
|
|
64
78
|
|
|
65
79
|
console.log(" resolve: " + probe + " (importer " + importer + ")")
|
|
@@ -86,6 +100,8 @@ export fn runDoctor(args) {
|
|
|
86
100
|
console.log("Upgrade path (Web -> Webview -> Hybrid):")
|
|
87
101
|
console.log(" npm run build:web | build:shell | build:shell:apple / dev:hybrid")
|
|
88
102
|
console.log(" See docs/HYBRID.md · docs/UNIFIED_APP.md")
|
|
89
|
-
console.log(
|
|
103
|
+
console.log(
|
|
104
|
+
"HMR: platform file edits reload; switching TISH_PLATFORM/SURFACE needs Vite restart."
|
|
105
|
+
)
|
|
90
106
|
exit(0)
|
|
91
107
|
}
|
package/src/commands/icon.tish
CHANGED
|
@@ -6,8 +6,11 @@ export fn runIcon(args) {
|
|
|
6
6
|
let dir = firstPositional(args)
|
|
7
7
|
let projectDir = cwd()
|
|
8
8
|
if (dir !== null) {
|
|
9
|
-
if (String(dir).startsWith("/"))
|
|
10
|
-
|
|
9
|
+
if (String(dir).startsWith("/")) {
|
|
10
|
+
projectDir = dir
|
|
11
|
+
} else {
|
|
12
|
+
projectDir = joinPath(cwd(), dir)
|
|
13
|
+
}
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
let iconsDir = joinPath(projectDir, "icons")
|
|
@@ -15,12 +18,7 @@ export fn runIcon(args) {
|
|
|
15
18
|
|
|
16
19
|
// Minimal placeholder SVG icon set. Real raster generation can land later
|
|
17
20
|
// (sips / ImageMagick) once distribute scripts ship.
|
|
18
|
-
let svg =
|
|
19
|
-
'<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">' +
|
|
20
|
-
'<rect width="1024" height="1024" rx="192" fill="#18181b"/>' +
|
|
21
|
-
'<circle cx="512" cy="512" r="280" fill="#10b981"/>' +
|
|
22
|
-
'<text x="512" y="580" text-anchor="middle" font-family="DM Sans, sans-serif" font-size="320" font-weight="700" fill="#ffffff">T</text>' +
|
|
23
|
-
"</svg>"
|
|
21
|
+
let svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1024\" height=\"1024\" viewBox=\"0 0 1024 1024\">" + "<rect width=\"1024\" height=\"1024\" rx=\"192\" fill=\"#18181b\"/>" + "<circle cx=\"512\" cy=\"512\" r=\"280\" fill=\"#10b981\"/>" + "<text x=\"512\" y=\"580\" text-anchor=\"middle\" font-family=\"DM Sans, sans-serif\" font-size=\"320\" font-weight=\"700\" fill=\"#ffffff\">T</text>" + "</svg>"
|
|
24
22
|
|
|
25
23
|
let svgPath = joinPath(iconsDir, "icon.svg")
|
|
26
24
|
writeFile(svgPath, svg)
|
|
@@ -29,8 +27,7 @@ export fn runIcon(args) {
|
|
|
29
27
|
// Best-effort PNG via `sips` on macOS when available.
|
|
30
28
|
let pngPath = joinPath(iconsDir, "icon.png")
|
|
31
29
|
let code = exec(
|
|
32
|
-
"command -v sips >/dev/null 2>&1 && sips -s format png " +
|
|
33
|
-
q(svgPath) + " --out " + q(pngPath) + " >/dev/null 2>&1"
|
|
30
|
+
"command -v sips >/dev/null 2>&1 && sips -s format png " + q(svgPath) + " --out " + q(pngPath) + " >/dev/null 2>&1"
|
|
34
31
|
)
|
|
35
32
|
if (code === 0 && pathExists(pngPath)) {
|
|
36
33
|
console.log("[icon] wrote " + pngPath)
|
|
@@ -38,5 +35,7 @@ export fn runIcon(args) {
|
|
|
38
35
|
console.log("[icon] PNG skipped (install sips/ImageMagick or convert icon.svg manually)")
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
console.log(
|
|
38
|
+
console.log(
|
|
39
|
+
"[icon] place platform icons under " + iconsDir + " and point tauri.conf / bundler at them"
|
|
40
|
+
)
|
|
42
41
|
}
|
package/src/commands/info.tish
CHANGED
|
@@ -59,7 +59,9 @@ export fn runInfo(_args) {
|
|
|
59
59
|
platform = String(env["OSTYPE"])
|
|
60
60
|
} else {
|
|
61
61
|
let u = capture("uname -s")
|
|
62
|
-
if (u.text !== "")
|
|
62
|
+
if (u.text !== "") {
|
|
63
|
+
platform = u.text.split("\n")[0]
|
|
64
|
+
}
|
|
63
65
|
}
|
|
64
66
|
console.log("platform: " + platform)
|
|
65
67
|
console.log("")
|
package/src/commands/init.tish
CHANGED
|
@@ -10,19 +10,25 @@ import {
|
|
|
10
10
|
joinPath,
|
|
11
11
|
pathExists,
|
|
12
12
|
q,
|
|
13
|
-
repoRoot
|
|
13
|
+
repoRoot
|
|
14
14
|
} from "../paths.tish"
|
|
15
15
|
|
|
16
16
|
fn relPath(fromDir, toDir) {
|
|
17
|
-
if (fromDir === toDir)
|
|
17
|
+
if (fromDir === toDir) {
|
|
18
|
+
return "."
|
|
19
|
+
}
|
|
18
20
|
let prefix = fromDir
|
|
19
|
-
if (!prefix.endsWith("/"))
|
|
21
|
+
if (!prefix.endsWith("/")) {
|
|
22
|
+
prefix = prefix + "/"
|
|
23
|
+
}
|
|
20
24
|
if (String(toDir).startsWith(prefix)) {
|
|
21
25
|
return String(toDir).slice(prefix.length)
|
|
22
26
|
}
|
|
23
27
|
// Prefer absolute when the scaffold is outside the repo tree.
|
|
24
28
|
let rootPrefix = toDir
|
|
25
|
-
if (!rootPrefix.endsWith("/"))
|
|
29
|
+
if (!rootPrefix.endsWith("/")) {
|
|
30
|
+
rootPrefix = rootPrefix + "/"
|
|
31
|
+
}
|
|
26
32
|
if (!String(fromDir).startsWith(rootPrefix) && !String(fromDir).startsWith(String(toDir))) {
|
|
27
33
|
return toDir
|
|
28
34
|
}
|
|
@@ -43,13 +49,19 @@ fn relPath(fromDir, toDir) {
|
|
|
43
49
|
u = u + 1
|
|
44
50
|
}
|
|
45
51
|
// Too many hops → absolute (avoids ../../Users/... from /tmp).
|
|
46
|
-
if (ups > 3)
|
|
52
|
+
if (ups > 3) {
|
|
53
|
+
return toDir
|
|
54
|
+
}
|
|
47
55
|
let d = i
|
|
48
56
|
while (d < toParts.length) {
|
|
49
|
-
if (toParts[d] !== "")
|
|
57
|
+
if (toParts[d] !== "") {
|
|
58
|
+
parts.push(toParts[d])
|
|
59
|
+
}
|
|
50
60
|
d = d + 1
|
|
51
61
|
}
|
|
52
|
-
if (parts.length === 0)
|
|
62
|
+
if (parts.length === 0) {
|
|
63
|
+
return "."
|
|
64
|
+
}
|
|
53
65
|
return parts.join("/")
|
|
54
66
|
}
|
|
55
67
|
|
|
@@ -126,13 +138,31 @@ fn applyRegistryOverlay(templates, target, appName, shellOut, port, pkgVersion)
|
|
|
126
138
|
console.error("init: registry templates missing under " + templates)
|
|
127
139
|
exit(1)
|
|
128
140
|
}
|
|
129
|
-
copyTemplateFile(
|
|
130
|
-
|
|
141
|
+
copyTemplateFile(
|
|
142
|
+
pkgSrc,
|
|
143
|
+
joinPath(target, "package.json"),
|
|
144
|
+
appName,
|
|
145
|
+
".",
|
|
146
|
+
shellOut,
|
|
147
|
+
port,
|
|
148
|
+
pkgVersion
|
|
149
|
+
)
|
|
150
|
+
copyTemplateFile(
|
|
151
|
+
viteSrc,
|
|
152
|
+
joinPath(target, "vite.config.mjs"),
|
|
153
|
+
appName,
|
|
154
|
+
".",
|
|
155
|
+
shellOut,
|
|
156
|
+
port,
|
|
157
|
+
pkgVersion
|
|
158
|
+
)
|
|
131
159
|
}
|
|
132
160
|
|
|
133
161
|
export fn runInit(args) {
|
|
134
162
|
let dirArg = firstPositional(args)
|
|
135
|
-
if (dirArg === null)
|
|
163
|
+
if (dirArg === null) {
|
|
164
|
+
dirArg = "my-desktop-app"
|
|
165
|
+
}
|
|
136
166
|
let here = cwd()
|
|
137
167
|
let target = dirArg
|
|
138
168
|
if (!String(dirArg).startsWith("/")) {
|
|
@@ -159,19 +189,25 @@ export fn runInit(args) {
|
|
|
159
189
|
}
|
|
160
190
|
templateName = uiName
|
|
161
191
|
}
|
|
162
|
-
if (templateName === null)
|
|
192
|
+
if (templateName === null) {
|
|
193
|
+
templateName = "lattish"
|
|
194
|
+
}
|
|
163
195
|
let templateDir = "templates/app"
|
|
164
196
|
if (templateName === "bare" || templateName === "none" || templateName === "byo") {
|
|
165
197
|
templateDir = "templates/bare"
|
|
166
|
-
} else if (templateName === "lattish" || templateName === "app" || templateName === "default") {
|
|
167
|
-
templateDir = "templates/app"
|
|
168
198
|
} else {
|
|
169
|
-
|
|
170
|
-
|
|
199
|
+
if (templateName === "lattish" || templateName === "app" || templateName === "default") {
|
|
200
|
+
templateDir = "templates/app"
|
|
201
|
+
} else {
|
|
202
|
+
console.error("init: unknown --template/--ui " + templateName + " (use lattish|bare|none)")
|
|
203
|
+
exit(1)
|
|
204
|
+
}
|
|
171
205
|
}
|
|
172
206
|
let templates = joinPath(cliRoot(), templateDir)
|
|
173
207
|
let appName = basename(target)
|
|
174
|
-
if (appName === "" || appName === "." || appName === "/")
|
|
208
|
+
if (appName === "" || appName === "." || appName === "/") {
|
|
209
|
+
appName = "my-desktop-app"
|
|
210
|
+
}
|
|
175
211
|
|
|
176
212
|
let relRoot = monorepo ? relPath(target, root) : "."
|
|
177
213
|
let shellOut = "dist/" + appName + "-shell"
|
|
@@ -181,7 +217,9 @@ export fn runInit(args) {
|
|
|
181
217
|
if (monorepo) {
|
|
182
218
|
console.log("[init] monorepo mode — path deps → " + relRoot)
|
|
183
219
|
} else {
|
|
184
|
-
console.log(
|
|
220
|
+
console.log(
|
|
221
|
+
"[init] registry mode — @tishlang/tish-desktop*@" + pkgVersion + " (outside tish-mode checkout)"
|
|
222
|
+
)
|
|
185
223
|
}
|
|
186
224
|
mkdir(target, true)
|
|
187
225
|
walkCopy(templates, target, appName, relRoot, shellOut, port, pkgVersion, true)
|
package/src/commands/ios.tish
CHANGED
|
@@ -5,15 +5,7 @@
|
|
|
5
5
|
// mode ios --example hello-ios --launch-only
|
|
6
6
|
// mode ios --example hello-ios --device "iPhone 16"
|
|
7
7
|
import { exit, cwd, exec, env } from "tish:process"
|
|
8
|
-
import {
|
|
9
|
-
flagValue,
|
|
10
|
-
firstPositional,
|
|
11
|
-
hasFlag,
|
|
12
|
-
joinPath,
|
|
13
|
-
pathExists,
|
|
14
|
-
q,
|
|
15
|
-
repoRoot,
|
|
16
|
-
} from "../paths.tish"
|
|
8
|
+
import { flagValue, firstPositional, hasFlag, joinPath, pathExists, q, repoRoot } from "../paths.tish"
|
|
17
9
|
|
|
18
10
|
fn usage() {
|
|
19
11
|
console.log("mode ios — build + launch an iOS example on the Simulator")
|
|
@@ -34,16 +26,24 @@ fn usage() {
|
|
|
34
26
|
fn dirnameOf(p) {
|
|
35
27
|
let s = String(p)
|
|
36
28
|
let i = s.lastIndexOf("/")
|
|
37
|
-
if (i < 0)
|
|
38
|
-
|
|
29
|
+
if (i < 0) {
|
|
30
|
+
return "."
|
|
31
|
+
}
|
|
32
|
+
if (i === 0) {
|
|
33
|
+
return "/"
|
|
34
|
+
}
|
|
39
35
|
return s.slice(0, i)
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
fn resolveAppleRoot(args) {
|
|
43
39
|
let fromFlag = flagValue(args, "--apple")
|
|
44
|
-
if (fromFlag !== null)
|
|
40
|
+
if (fromFlag !== null) {
|
|
41
|
+
return fromFlag
|
|
42
|
+
}
|
|
45
43
|
let fromEnv = env !== null ? env["TISH_APPLE"] : null
|
|
46
|
-
if (fromEnv !== null && fromEnv !== undefined && fromEnv !== "")
|
|
44
|
+
if (fromEnv !== null && fromEnv !== undefined && fromEnv !== "") {
|
|
45
|
+
return fromEnv
|
|
46
|
+
}
|
|
47
47
|
let root = repoRoot()
|
|
48
48
|
let sibling = joinPath(dirnameOf(root), "tish-apple")
|
|
49
49
|
if (pathExists(joinPath(sibling, "crates/tish-ios/Cargo.toml"))) {
|
package/src/main.tish
CHANGED
|
@@ -21,13 +21,19 @@ fn usage() {
|
|
|
21
21
|
console.log("")
|
|
22
22
|
console.log("Commands:")
|
|
23
23
|
console.log(" init [dir] Scaffold a desktop app")
|
|
24
|
-
console.log(
|
|
24
|
+
console.log(
|
|
25
|
+
" dev [--example name] Vite UI + native shell (parity with scripts/dev-example.mjs)"
|
|
26
|
+
)
|
|
25
27
|
console.log(" build [dir] Production UI + native shell → dist/")
|
|
26
28
|
console.log(" ios [--example name] Build + launch iOS example on Simulator (no Xcode UI)")
|
|
27
|
-
console.log(
|
|
29
|
+
console.log(
|
|
30
|
+
" doctor Platform/surface, resolve probe, cap matrix (≡ tish app doctor)"
|
|
31
|
+
)
|
|
28
32
|
console.log(" info Print tish / rustc / platform summary")
|
|
29
33
|
console.log(" icon [dir] Generate icon set into project icons/")
|
|
30
|
-
console.log(
|
|
34
|
+
console.log(
|
|
35
|
+
" distribute <step> Run scripts/distribute/* (build|sign|notarize|updater|release)"
|
|
36
|
+
)
|
|
31
37
|
console.log(" help Show this message")
|
|
32
38
|
console.log("")
|
|
33
39
|
console.log("Init options:")
|
package/src/paths.tish
CHANGED
|
@@ -7,25 +7,43 @@ export fn pathExists(p) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export fn joinPath(a, b) {
|
|
10
|
-
if (a === null || a === "")
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (
|
|
10
|
+
if (a === null || a === "") {
|
|
11
|
+
return b
|
|
12
|
+
}
|
|
13
|
+
if (b === null || b === "") {
|
|
14
|
+
return a
|
|
15
|
+
}
|
|
16
|
+
if (a === ".") {
|
|
17
|
+
return b
|
|
18
|
+
}
|
|
19
|
+
if (a.endsWith("/")) {
|
|
20
|
+
return a + b
|
|
21
|
+
}
|
|
14
22
|
return a + "/" + b
|
|
15
23
|
}
|
|
16
24
|
|
|
17
25
|
export fn dirname(p) {
|
|
18
|
-
if (p === null || p === "")
|
|
26
|
+
if (p === null || p === "") {
|
|
27
|
+
return "."
|
|
28
|
+
}
|
|
19
29
|
let i = p.lastIndexOf("/")
|
|
20
|
-
if (i < 0)
|
|
21
|
-
|
|
30
|
+
if (i < 0) {
|
|
31
|
+
return "."
|
|
32
|
+
}
|
|
33
|
+
if (i === 0) {
|
|
34
|
+
return "/"
|
|
35
|
+
}
|
|
22
36
|
return p.slice(0, i)
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
export fn basename(p) {
|
|
26
|
-
if (p === null || p === "")
|
|
40
|
+
if (p === null || p === "") {
|
|
41
|
+
return ""
|
|
42
|
+
}
|
|
27
43
|
let i = p.lastIndexOf("/")
|
|
28
|
-
if (i < 0)
|
|
44
|
+
if (i < 0) {
|
|
45
|
+
return p
|
|
46
|
+
}
|
|
29
47
|
return p.slice(i + 1)
|
|
30
48
|
}
|
|
31
49
|
|
|
@@ -50,7 +68,9 @@ export fn userArgs() {
|
|
|
50
68
|
export fn hasFlag(args, flag) {
|
|
51
69
|
let i = 0
|
|
52
70
|
while (i < args.length) {
|
|
53
|
-
if (args[i] === flag)
|
|
71
|
+
if (args[i] === flag) {
|
|
72
|
+
return true
|
|
73
|
+
}
|
|
54
74
|
i = i + 1
|
|
55
75
|
}
|
|
56
76
|
return false
|
|
@@ -59,7 +79,9 @@ export fn hasFlag(args, flag) {
|
|
|
59
79
|
export fn flagValue(args, flag) {
|
|
60
80
|
let i = 0
|
|
61
81
|
while (i < args.length) {
|
|
62
|
-
if (args[i] === flag && i + 1 < args.length)
|
|
82
|
+
if (args[i] === flag && i + 1 < args.length) {
|
|
83
|
+
return args[i + 1]
|
|
84
|
+
}
|
|
63
85
|
if (String(args[i]).startsWith(flag + "=")) {
|
|
64
86
|
return String(args[i]).slice(flag.length + 1)
|
|
65
87
|
}
|
|
@@ -72,7 +94,9 @@ export fn firstPositional(args) {
|
|
|
72
94
|
let i = 0
|
|
73
95
|
while (i < args.length) {
|
|
74
96
|
let a = args[i]
|
|
75
|
-
if (!String(a).startsWith("-"))
|
|
97
|
+
if (!String(a).startsWith("-")) {
|
|
98
|
+
return a
|
|
99
|
+
}
|
|
76
100
|
if ((a === "--example" || a === "--dir" || a === "--out" || a === "--template" || a === "--ui" || a === "--platform" || a === "--surface" || a === "--desk-platform" || a === "--desk-surface" || a === "--resolve" || a === "--importer" || a === "--device" || a === "--apple") && i + 1 < args.length) {
|
|
77
101
|
i = i + 2
|
|
78
102
|
continue
|
|
@@ -84,9 +108,13 @@ export fn firstPositional(args) {
|
|
|
84
108
|
|
|
85
109
|
fn looksLikeCliRoot(dir) {
|
|
86
110
|
let pkg = joinPath(dir, "package.json")
|
|
87
|
-
if (!pathExists(pkg))
|
|
111
|
+
if (!pathExists(pkg)) {
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
88
114
|
let text = readFile(pkg)
|
|
89
|
-
if (text === null || String(text).startsWith("Error:"))
|
|
115
|
+
if (text === null || String(text).startsWith("Error:")) {
|
|
116
|
+
return false
|
|
117
|
+
}
|
|
90
118
|
return String(text).indexOf("@tishlang/tish-desktop") >= 0
|
|
91
119
|
}
|
|
92
120
|
|
|
@@ -103,19 +131,31 @@ export fn inMonorepoCheckout() {
|
|
|
103
131
|
export fn cliPackageVersion() {
|
|
104
132
|
let pkg = joinPath(cliRoot(), "package.json")
|
|
105
133
|
let text = readFile(pkg)
|
|
106
|
-
if (text === null || String(text).startsWith("Error:"))
|
|
134
|
+
if (text === null || String(text).startsWith("Error:")) {
|
|
135
|
+
return "0.1.0"
|
|
136
|
+
}
|
|
107
137
|
let s = String(text)
|
|
108
138
|
let key = "\"version\""
|
|
109
139
|
let i = s.indexOf(key)
|
|
110
|
-
if (i < 0)
|
|
140
|
+
if (i < 0) {
|
|
141
|
+
return "0.1.0"
|
|
142
|
+
}
|
|
111
143
|
let colon = s.indexOf(":", i + key.length)
|
|
112
|
-
if (colon < 0)
|
|
144
|
+
if (colon < 0) {
|
|
145
|
+
return "0.1.0"
|
|
146
|
+
}
|
|
113
147
|
let q1 = s.indexOf("\"", colon + 1)
|
|
114
|
-
if (q1 < 0)
|
|
148
|
+
if (q1 < 0) {
|
|
149
|
+
return "0.1.0"
|
|
150
|
+
}
|
|
115
151
|
let q2 = s.indexOf("\"", q1 + 1)
|
|
116
|
-
if (q2 < 0)
|
|
152
|
+
if (q2 < 0) {
|
|
153
|
+
return "0.1.0"
|
|
154
|
+
}
|
|
117
155
|
let ver = s.slice(q1 + 1, q2)
|
|
118
|
-
if (ver === "")
|
|
156
|
+
if (ver === "") {
|
|
157
|
+
return "0.1.0"
|
|
158
|
+
}
|
|
119
159
|
return ver
|
|
120
160
|
}
|
|
121
161
|
|
|
@@ -125,22 +165,33 @@ export fn cliRoot() {
|
|
|
125
165
|
let candidate = null
|
|
126
166
|
if (argv.length >= 2 && argv[1] !== null && String(argv[1]).endsWith(".tish")) {
|
|
127
167
|
let script = String(argv[1])
|
|
128
|
-
if (!script.startsWith("/"))
|
|
168
|
+
if (!script.startsWith("/")) {
|
|
169
|
+
script = joinPath(here, script)
|
|
170
|
+
}
|
|
129
171
|
let srcDir = dirname(script)
|
|
130
172
|
let root = dirname(srcDir)
|
|
131
|
-
if (looksLikeCliRoot(root))
|
|
173
|
+
if (looksLikeCliRoot(root)) {
|
|
174
|
+
candidate = root
|
|
175
|
+
}
|
|
132
176
|
}
|
|
133
177
|
if (candidate === null && argv.length >= 1 && argv[0] !== null) {
|
|
134
178
|
let exe = String(argv[0])
|
|
135
179
|
if (exe.indexOf("mode") >= 0 || exe.indexOf("tish-desktop") >= 0) {
|
|
136
180
|
let dist = dirname(exe)
|
|
137
181
|
let root = dirname(dist)
|
|
138
|
-
if (looksLikeCliRoot(root))
|
|
182
|
+
if (looksLikeCliRoot(root)) {
|
|
183
|
+
candidate = root
|
|
184
|
+
}
|
|
139
185
|
}
|
|
140
186
|
}
|
|
141
187
|
if (candidate === null) {
|
|
142
|
-
if (looksLikeCliRoot(here))
|
|
143
|
-
|
|
188
|
+
if (looksLikeCliRoot(here)) {
|
|
189
|
+
candidate = here
|
|
190
|
+
} else {
|
|
191
|
+
if (looksLikeCliRoot(joinPath(here, "cli"))) {
|
|
192
|
+
candidate = joinPath(here, "cli")
|
|
193
|
+
}
|
|
194
|
+
}
|
|
144
195
|
}
|
|
145
196
|
if (candidate === null) {
|
|
146
197
|
let walk = here
|
|
@@ -155,14 +206,20 @@ export fn cliRoot() {
|
|
|
155
206
|
break
|
|
156
207
|
}
|
|
157
208
|
let parent = dirname(walk)
|
|
158
|
-
if (parent === walk)
|
|
209
|
+
if (parent === walk) {
|
|
210
|
+
break
|
|
211
|
+
}
|
|
159
212
|
walk = parent
|
|
160
213
|
n = n + 1
|
|
161
214
|
}
|
|
162
215
|
}
|
|
163
|
-
if (candidate === null)
|
|
216
|
+
if (candidate === null) {
|
|
217
|
+
candidate = here
|
|
218
|
+
}
|
|
164
219
|
if (candidate === "." || !String(candidate).startsWith("/")) {
|
|
165
|
-
if (candidate === "." || candidate === "")
|
|
220
|
+
if (candidate === "." || candidate === "") {
|
|
221
|
+
return here
|
|
222
|
+
}
|
|
166
223
|
return joinPath(here, candidate)
|
|
167
224
|
}
|
|
168
225
|
return candidate
|
|
@@ -172,15 +229,23 @@ export fn cliRoot() {
|
|
|
172
229
|
export fn repoRoot() {
|
|
173
230
|
let cli = cliRoot()
|
|
174
231
|
let parent = dirname(cli)
|
|
175
|
-
if (looksLikeRepoRoot(parent))
|
|
232
|
+
if (looksLikeRepoRoot(parent)) {
|
|
233
|
+
return parent
|
|
234
|
+
}
|
|
176
235
|
let here = cwd()
|
|
177
|
-
if (looksLikeRepoRoot(here))
|
|
236
|
+
if (looksLikeRepoRoot(here)) {
|
|
237
|
+
return here
|
|
238
|
+
}
|
|
178
239
|
let walk = here
|
|
179
240
|
let n = 0
|
|
180
241
|
while (n < 8) {
|
|
181
|
-
if (looksLikeRepoRoot(walk))
|
|
242
|
+
if (looksLikeRepoRoot(walk)) {
|
|
243
|
+
return walk
|
|
244
|
+
}
|
|
182
245
|
let parent2 = dirname(walk)
|
|
183
|
-
if (parent2 === walk)
|
|
246
|
+
if (parent2 === walk) {
|
|
247
|
+
break
|
|
248
|
+
}
|
|
184
249
|
walk = parent2
|
|
185
250
|
n = n + 1
|
|
186
251
|
}
|
|
@@ -191,21 +256,31 @@ export fn resolveTish() {
|
|
|
191
256
|
// Prefer explicit override, then sibling monorepo debug build (has --platform / resolve-id).
|
|
192
257
|
if (env !== null) {
|
|
193
258
|
let custom = env["TISH_PATH"]
|
|
194
|
-
if (custom !== null && custom !== "" && fileExists(String(custom)))
|
|
259
|
+
if (custom !== null && custom !== "" && fileExists(String(custom))) {
|
|
260
|
+
return String(custom)
|
|
261
|
+
}
|
|
195
262
|
}
|
|
196
263
|
let root = repoRoot()
|
|
197
264
|
let localDebug = joinPath(root, "../tish/target/debug/tish")
|
|
198
|
-
if (fileExists(localDebug))
|
|
265
|
+
if (fileExists(localDebug)) {
|
|
266
|
+
return localDebug
|
|
267
|
+
}
|
|
199
268
|
let localRelease = joinPath(root, "../tish/target/release/tish")
|
|
200
|
-
if (fileExists(localRelease))
|
|
269
|
+
if (fileExists(localRelease)) {
|
|
270
|
+
return localRelease
|
|
271
|
+
}
|
|
201
272
|
let home = ""
|
|
202
273
|
if (env !== null) {
|
|
203
274
|
let h = env["HOME"]
|
|
204
|
-
if (h !== null && h !== "")
|
|
275
|
+
if (h !== null && h !== "") {
|
|
276
|
+
home = String(h)
|
|
277
|
+
}
|
|
205
278
|
}
|
|
206
279
|
if (home !== "") {
|
|
207
280
|
let cargoTish = home + "/.cargo/bin/tish"
|
|
208
|
-
if (fileExists(cargoTish))
|
|
281
|
+
if (fileExists(cargoTish)) {
|
|
282
|
+
return cargoTish
|
|
283
|
+
}
|
|
209
284
|
}
|
|
210
285
|
return "tish"
|
|
211
286
|
}
|
|
@@ -11,9 +11,9 @@ await emitStylesheet({
|
|
|
11
11
|
"__ROOT__/packages/ui-theme/src/ui/Badge.tish",
|
|
12
12
|
"__ROOT__/packages/ui-theme/src/ui/Separator.tish",
|
|
13
13
|
"__ROOT__/packages/ui-theme/src/ui/ScrollArea.tish",
|
|
14
|
-
"__ROOT__/packages/ui-theme/src/ui/Toolbar.tish"
|
|
14
|
+
"__ROOT__/packages/ui-theme/src/ui/Toolbar.tish"
|
|
15
15
|
],
|
|
16
|
-
outputPath: "public/assets/app.tw.css"
|
|
16
|
+
outputPath: "public/assets/app.tw.css"
|
|
17
17
|
})
|
|
18
18
|
|
|
19
19
|
mkdir("public/assets", { recursive: true })
|
|
@@ -31,12 +31,8 @@ fn App() {
|
|
|
31
31
|
|
|
32
32
|
{hello !== null ? <Card class="mt-4">
|
|
33
33
|
<CardHeader>
|
|
34
|
-
<h2 class="font-semibold">Response</h2>
|
|
35
|
-
|
|
36
|
-
<CardBody>
|
|
37
|
-
<pre class="text-sm whitespace-pre-wrap">{JSON.stringify(hello, null, 2)}</pre>
|
|
38
|
-
</CardBody>
|
|
39
|
-
</Card> : null}
|
|
34
|
+
<h2 class="font-semibold">Response</h2></CardHeader><CardBody>
|
|
35
|
+
<pre class="text-sm whitespace-pre-wrap">{JSON.stringify(hello, null, 2)}</pre></CardBody></Card> : null}
|
|
40
36
|
</div>
|
|
41
37
|
}
|
|
42
38
|
|
|
@@ -13,15 +13,15 @@ export fn mountApp(rootEl) {
|
|
|
13
13
|
rootEl.appendChild(p)
|
|
14
14
|
let out = document.createElement("pre")
|
|
15
15
|
let btn = Button({
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
title: "Hello",
|
|
17
|
+
onPress: () => {
|
|
18
|
+
invoke("app.hello", { from: "ui" }).then((r) => {
|
|
19
|
+
out.textContent = JSON.stringify(r, null, 2)
|
|
20
|
+
}, (e) => {
|
|
21
|
+
out.textContent = String(e)
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
25
|
rootEl.appendChild(btn)
|
|
26
26
|
rootEl.appendChild(out)
|
|
27
27
|
}
|
|
@@ -24,11 +24,4 @@ createSurface({
|
|
|
24
24
|
titleBarStyle: "transparent"
|
|
25
25
|
})
|
|
26
26
|
|
|
27
|
-
run({
|
|
28
|
-
plugins: {
|
|
29
|
-
dialog: true,
|
|
30
|
-
menu: true,
|
|
31
|
-
notification: true,
|
|
32
|
-
singleInstance: false
|
|
33
|
-
}
|
|
34
|
-
})
|
|
27
|
+
run({ plugins: { dialog: true, menu: true, notification: true, singleInstance: false } })
|