nattoppet 2.1.1 → 4.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/GUIDE.md +732 -0
- package/LICENSE +21 -0
- package/dist/common.ymd +94 -0
- package/dist/form.css +87 -0
- package/dist/form.js +64 -0
- package/dist/form.ymd +36 -0
- package/dist/katex.css +1 -0
- package/dist/katex.ymd +13 -0
- package/dist/koa.css +157 -0
- package/{koa/after.ymd → dist/koa.ymd} +18 -1
- package/dist/nattoppet-dev.js +84 -0
- package/dist/nattoppet-init.js +140 -0
- package/dist/nattoppet-native.js +116 -0
- package/dist/nattoppet.js +87083 -0
- package/dist/ppt.css +304 -0
- package/dist/ppt.js +83 -0
- package/{ppt/after.ymd → dist/ppt.ymd} +17 -1
- package/dist/tml.css +125 -0
- package/dist/tml.js +3 -0
- package/{tml/after.ymd → dist/tml.ymd} +19 -1
- package/dist/vue.css +91 -0
- package/dist/vue.ymd +23 -0
- package/package.json +37 -13
- package/readme.md +33 -14
- package/.editorconfig +0 -15
- package/assets/katex.css +0 -1
- package/assets/manuscript.cls +0 -30
- package/common.ymd +0 -74
- package/compiler.js +0 -120
- package/koa/before.ymd +0 -12
- package/koa/koa.less +0 -179
- package/native/Cargo.toml +0 -13
- package/native/build.rs +0 -12
- package/native/src/main.rs +0 -22
- package/nattoppet-dev.js +0 -58
- package/nattoppet-native.js +0 -49
- package/nattoppet.js +0 -26
- package/ppt/before.ymd +0 -8
- package/ppt/ppt.coffee +0 -61
- package/ppt/ppt.less +0 -222
- package/stdlib.js +0 -108
- package/tml/before.ymd +0 -10
- package/tml/tml.coffee +0 -1
- package/tml/tml.less +0 -145
- package/vue/after.ymd +0 -9
- package/vue/before.ymd +0 -9
- package/vue/vue.less +0 -101
package/dist/katex.ymd
ADDED
package/dist/koa.css
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
html {
|
|
2
|
+
font-family: serif;
|
|
3
|
+
font-size: 18px;
|
|
4
|
+
line-height: 1.5;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
background: white;
|
|
8
|
+
color: #33333d;
|
|
9
|
+
}
|
|
10
|
+
@media (max-width: 625px) {
|
|
11
|
+
html {
|
|
12
|
+
font-size: 16px;
|
|
13
|
+
text-align: justify;
|
|
14
|
+
hyphens: auto;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
body {
|
|
18
|
+
height: 100%;
|
|
19
|
+
width: 100%;
|
|
20
|
+
padding: 0;
|
|
21
|
+
margin: 0;
|
|
22
|
+
overflow-y: scroll;
|
|
23
|
+
}
|
|
24
|
+
a {
|
|
25
|
+
color: #027AD2;
|
|
26
|
+
}
|
|
27
|
+
section {
|
|
28
|
+
min-height: 50%;
|
|
29
|
+
padding: 150px 10vw;
|
|
30
|
+
}
|
|
31
|
+
@media (max-width: 625px) {
|
|
32
|
+
section {
|
|
33
|
+
padding: 25px 1.25rem;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
section:nth-child(2n-1) {
|
|
37
|
+
background: #fbfbfb;
|
|
38
|
+
box-shadow: inset 0 1px 0 0 white;
|
|
39
|
+
}
|
|
40
|
+
section:not(:last-child) {
|
|
41
|
+
border-bottom: 1px solid #eee;
|
|
42
|
+
}
|
|
43
|
+
pre {
|
|
44
|
+
background: white;
|
|
45
|
+
border-top: 1px solid #eee;
|
|
46
|
+
border-bottom: 1px solid #eee;
|
|
47
|
+
padding: 25px;
|
|
48
|
+
font-size: 0.8rem;
|
|
49
|
+
text-align: left;
|
|
50
|
+
overflow-x: auto;
|
|
51
|
+
}
|
|
52
|
+
code {
|
|
53
|
+
font-family: monospace;
|
|
54
|
+
}
|
|
55
|
+
h2 {
|
|
56
|
+
margin-top: 40px;
|
|
57
|
+
font-size: 2rem;
|
|
58
|
+
}
|
|
59
|
+
h3 {
|
|
60
|
+
margin-top: 80px;
|
|
61
|
+
font-size: 1.2rem;
|
|
62
|
+
}
|
|
63
|
+
h4 {
|
|
64
|
+
margin-top: 40px;
|
|
65
|
+
font-size: 1rem;
|
|
66
|
+
}
|
|
67
|
+
ul li {
|
|
68
|
+
font-size: 0.9rem;
|
|
69
|
+
}
|
|
70
|
+
p {
|
|
71
|
+
text-indent: 2rem;
|
|
72
|
+
}
|
|
73
|
+
#title {
|
|
74
|
+
padding: 0;
|
|
75
|
+
height: 100%;
|
|
76
|
+
text-align: center;
|
|
77
|
+
position: relative;
|
|
78
|
+
}
|
|
79
|
+
@media (max-width: 625px) {
|
|
80
|
+
#title {
|
|
81
|
+
height: 40vh;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
#title h1 {
|
|
85
|
+
position: absolute;
|
|
86
|
+
top: 45%;
|
|
87
|
+
width: 100%;
|
|
88
|
+
transform: translateY(-50%);
|
|
89
|
+
margin: 0;
|
|
90
|
+
font-size: 6rem;
|
|
91
|
+
font-weight: normal;
|
|
92
|
+
}
|
|
93
|
+
@media (max-width: 625px) {
|
|
94
|
+
#title h1 {
|
|
95
|
+
font-size: 3rem;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
#nav {
|
|
99
|
+
position: fixed;
|
|
100
|
+
top: 35px;
|
|
101
|
+
right: 30px;
|
|
102
|
+
z-index: 5;
|
|
103
|
+
}
|
|
104
|
+
@media (max-width: 625px) {
|
|
105
|
+
#nav {
|
|
106
|
+
top: 15px;
|
|
107
|
+
right: 10px;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
#nav #nav-icon {
|
|
111
|
+
position: absolute;
|
|
112
|
+
top: 0;
|
|
113
|
+
right: 0;
|
|
114
|
+
padding: 6px;
|
|
115
|
+
background: rgba(255, 255, 255, 0.9);
|
|
116
|
+
border-radius: 2px;
|
|
117
|
+
border: 1px solid transparent;
|
|
118
|
+
font-size: 0;
|
|
119
|
+
z-index: 4;
|
|
120
|
+
}
|
|
121
|
+
#nav #nav-menu {
|
|
122
|
+
display: none;
|
|
123
|
+
position: relative;
|
|
124
|
+
top: 35px;
|
|
125
|
+
right: 0;
|
|
126
|
+
margin: 0;
|
|
127
|
+
border: 1px solid #efefef;
|
|
128
|
+
border-bottom: 1px solid #ddd;
|
|
129
|
+
border-radius: 2px;
|
|
130
|
+
padding: 25px;
|
|
131
|
+
background: rgba(255, 255, 255, 0.95);
|
|
132
|
+
box-shadow: 0 1px 3px 0 #eee;
|
|
133
|
+
z-index: 3;
|
|
134
|
+
}
|
|
135
|
+
#nav #nav-menu li {
|
|
136
|
+
list-style: none;
|
|
137
|
+
}
|
|
138
|
+
#nav #nav-menu li a {
|
|
139
|
+
display: block;
|
|
140
|
+
text-decoration: none;
|
|
141
|
+
padding: 3px 0;
|
|
142
|
+
color: inherit;
|
|
143
|
+
font-size: 1rem;
|
|
144
|
+
}
|
|
145
|
+
#nav #nav-menu li a:hover {
|
|
146
|
+
text-decoration: underline;
|
|
147
|
+
}
|
|
148
|
+
#nav:hover ul {
|
|
149
|
+
display: block;
|
|
150
|
+
}
|
|
151
|
+
#nav:hover #nav-icon {
|
|
152
|
+
border: 1px solid #efefef;
|
|
153
|
+
border-bottom: none;
|
|
154
|
+
}
|
|
155
|
+
#nav:hover #nav-menu {
|
|
156
|
+
display: block;
|
|
157
|
+
}
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<meta name=viewport content="width=device-width, initial-scale=1.0">
|
|
3
|
+
<meta name=author content="ylxdzsw@gmail.com">
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>[title] | ylxdzsw's blog</title>
|
|
6
|
+
|
|
7
|
+
<style>
|
|
8
|
+
[mixin] koa.css
|
|
9
|
+
</style>
|
|
10
|
+
|
|
11
|
+
<section id="title">
|
|
12
|
+
<h1>[title]</h1>
|
|
13
|
+
|
|
14
|
+
[eval*] this.sections = []
|
|
15
|
+
|
|
16
|
+
[#slot]
|
|
17
|
+
|
|
1
18
|
</section>
|
|
2
19
|
|
|
3
20
|
<div id="nav">
|
|
@@ -19,4 +36,4 @@ const index = this.sections.length
|
|
|
19
36
|
this.sections.push(title)
|
|
20
37
|
;`</section><section><h2 id="sec${index}">${title}</h2>`
|
|
21
38
|
|
|
22
|
-
[mixin]
|
|
39
|
+
[mixin] common.ymd
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// nattoppet-dev.ts
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import * as http from "node:http";
|
|
8
|
+
import * as cp from "node:child_process";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
var file = process.argv[2];
|
|
11
|
+
if (process.argv.length < 3 || file == "--help") {
|
|
12
|
+
console.log("Usage: nattoppet-dev [file] [hook cmd]...");
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
var runtimeExt = path.extname(fileURLToPath(import.meta.url)) === ".js" ? ".js" : ".ts";
|
|
16
|
+
var nattoppetPath = fileURLToPath(new URL(`nattoppet${runtimeExt}`, import.meta.url));
|
|
17
|
+
var mimeTypes = {
|
|
18
|
+
".html": "text/html",
|
|
19
|
+
".css": "text/css",
|
|
20
|
+
".js": "text/javascript",
|
|
21
|
+
".wasm": "application/wasm",
|
|
22
|
+
".json": "application/json",
|
|
23
|
+
".png": "image/png",
|
|
24
|
+
".svg": "image/svg+xml"
|
|
25
|
+
};
|
|
26
|
+
http.createServer(async (req, res) => {
|
|
27
|
+
try {
|
|
28
|
+
const url = new URL(req.url, "http://localhost");
|
|
29
|
+
if (url.pathname !== "/") {
|
|
30
|
+
const filePath = path.join(process.cwd(), decodeURIComponent(url.pathname));
|
|
31
|
+
await fs.promises.access(filePath);
|
|
32
|
+
const ext = path.extname(filePath);
|
|
33
|
+
const contentType = mimeTypes[ext] || "application/octet-stream";
|
|
34
|
+
res.writeHead(200, { "Content-Type": contentType });
|
|
35
|
+
fs.createReadStream(filePath).pipe(res);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (process.argv.length > 3) {
|
|
39
|
+
const exitCode = await new Promise((resolve) => {
|
|
40
|
+
const hookProc = cp.spawn(process.argv[3], process.argv.slice(4), {
|
|
41
|
+
stdio: "inherit"
|
|
42
|
+
});
|
|
43
|
+
hookProc.on("close", resolve);
|
|
44
|
+
});
|
|
45
|
+
if (exitCode !== 0) {
|
|
46
|
+
console.warn("!!! hook command exit with non-0 status");
|
|
47
|
+
res.writeHead(500);
|
|
48
|
+
res.end("Hook command failed");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const { stdout, stderr } = await new Promise((resolve, reject) => {
|
|
53
|
+
const proc = cp.spawn(process.execPath, [nattoppetPath, file, "--dev"]);
|
|
54
|
+
let stdout2 = "";
|
|
55
|
+
let stderr2 = "";
|
|
56
|
+
proc.stdout.on("data", (d) => stdout2 += d);
|
|
57
|
+
proc.stderr.on("data", (d) => stderr2 += d);
|
|
58
|
+
proc.on("close", (code) => {
|
|
59
|
+
if (code !== 0) reject(new Error(`compilation failed with code ${code}`));
|
|
60
|
+
else resolve({ stdout: stdout2, stderr: stderr2 });
|
|
61
|
+
});
|
|
62
|
+
proc.on("error", reject);
|
|
63
|
+
});
|
|
64
|
+
if (stderr)
|
|
65
|
+
console.error(stderr);
|
|
66
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
67
|
+
res.end(stdout);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
if (e instanceof Error && "code" in e && e.code !== "ENOENT") {
|
|
70
|
+
console.error(e);
|
|
71
|
+
}
|
|
72
|
+
res.writeHead(404);
|
|
73
|
+
res.end("Not found");
|
|
74
|
+
}
|
|
75
|
+
}).listen(3939, () => {
|
|
76
|
+
console.log("Server running at http://127.0.0.1:3939");
|
|
77
|
+
});
|
|
78
|
+
var platform = process.platform;
|
|
79
|
+
var browser = process.env.BROWSER ?? (platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open");
|
|
80
|
+
var browserArgs = browser.includes("chrom") ? [browser, "--app=http://127.0.0.1:3939"] : [browser, "http://127.0.0.1:3939"];
|
|
81
|
+
cp.spawn(browserArgs[0], browserArgs.slice(1), {
|
|
82
|
+
stdio: "ignore",
|
|
83
|
+
detached: true
|
|
84
|
+
}).unref();
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// nattoppet-init.ts
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
import * as readline from "node:readline";
|
|
7
|
+
var type = process.argv[2];
|
|
8
|
+
var avaliable_templates = ["form"];
|
|
9
|
+
if (process.argv.length < 3 || !avaliable_templates.includes(type)) {
|
|
10
|
+
console.log("Usage: nattoppet-init form");
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|
|
13
|
+
fs.writeFileSync("main.ymd", `[mixin] ${type}
|
|
14
|
+
|
|
15
|
+
[title]: Page Title
|
|
16
|
+
|
|
17
|
+
[h3] Section Header
|
|
18
|
+
[text].first_name First Name
|
|
19
|
+
[text](placeholder="LastName").last_name Last Name
|
|
20
|
+
[number].age Age
|
|
21
|
+
|
|
22
|
+
[checkbox].male Male
|
|
23
|
+
[checkbox].female Female
|
|
24
|
+
|
|
25
|
+
[require](main.js)
|
|
26
|
+
`);
|
|
27
|
+
fs.writeFileSync("main.js", `async function run(args) {
|
|
28
|
+
return JSON.stringify(args)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (typeof Deno != 'undefined')
|
|
32
|
+
run({}).then(console.log)
|
|
33
|
+
`);
|
|
34
|
+
var rl = readline.createInterface({
|
|
35
|
+
input: process.stdin,
|
|
36
|
+
output: process.stdout
|
|
37
|
+
});
|
|
38
|
+
var question = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
39
|
+
var gen_wasm = await question("Generate wasm? (give lib name or empty to cancel): ");
|
|
40
|
+
rl.close();
|
|
41
|
+
if (gen_wasm) {
|
|
42
|
+
fs.writeFileSync(`${gen_wasm}.rs`, `#[no_mangle]
|
|
43
|
+
pub unsafe extern fn sum(data: *const u32, len: usize) -> u32 {
|
|
44
|
+
let mut sum = 0;
|
|
45
|
+
for i in 0..len {
|
|
46
|
+
sum += *data.add(i);
|
|
47
|
+
}
|
|
48
|
+
sum
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#[no_mangle]
|
|
52
|
+
pub unsafe extern "C" fn alloc_memory(byte_size: usize, alignment: usize) -> *mut u8 {
|
|
53
|
+
let layout = std::alloc::Layout::from_size_align_unchecked(byte_size, alignment);
|
|
54
|
+
std::alloc::alloc(layout)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#[no_mangle]
|
|
58
|
+
pub unsafe extern "C" fn free_memory(ptr: *mut u8, byte_size: usize, alignment: usize) {
|
|
59
|
+
let layout = std::alloc::Layout::from_size_align_unchecked(byte_size, alignment);
|
|
60
|
+
std::alloc::dealloc(ptr, layout)
|
|
61
|
+
}
|
|
62
|
+
`);
|
|
63
|
+
fs.writeFileSync("Cargo.toml", `[package]
|
|
64
|
+
name = "${gen_wasm}"
|
|
65
|
+
version = "0.1.0"
|
|
66
|
+
authors = ["Shiwei Zhang <ylxdzsw@gmail.com>"]
|
|
67
|
+
edition = "2024"
|
|
68
|
+
|
|
69
|
+
[lib]
|
|
70
|
+
crate-type = ["cdylib"]
|
|
71
|
+
path = "${gen_wasm}.rs"
|
|
72
|
+
|
|
73
|
+
[profile.release]
|
|
74
|
+
codegen-units = 1
|
|
75
|
+
lto = true
|
|
76
|
+
strip = true
|
|
77
|
+
|
|
78
|
+
[dependencies]
|
|
79
|
+
absurd = { git = "https://github.com/ylxdzsw/absurd" }
|
|
80
|
+
`);
|
|
81
|
+
fs.appendFileSync("main.js", `
|
|
82
|
+
|
|
83
|
+
async function call_wasm() {
|
|
84
|
+
await window.wasm_ready
|
|
85
|
+
const buffer_ptr = ${gen_wasm}.alloc_memory(4 * 8, 4)
|
|
86
|
+
const buffer_view = new Uint32Array(${gen_wasm}.memory.buffer, buffer_ptr, 8)
|
|
87
|
+
buffer_view.set([1, 2, 3, 4, 5, 6, 7, 8])
|
|
88
|
+
const sum = ${gen_wasm}.sum(buffer_ptr, 8)
|
|
89
|
+
${gen_wasm}.free_memory(buffer_ptr, 4 * 8, 4)
|
|
90
|
+
console.log(sum)
|
|
91
|
+
}
|
|
92
|
+
`);
|
|
93
|
+
fs.appendFileSync("main.ymd", `
|
|
94
|
+
[require](target/wasm32-unknown-unknown/release/${gen_wasm}.wasm)
|
|
95
|
+
`);
|
|
96
|
+
}
|
|
97
|
+
var rl2 = readline.createInterface({
|
|
98
|
+
input: process.stdin,
|
|
99
|
+
output: process.stdout
|
|
100
|
+
});
|
|
101
|
+
var gen_workflow = await new Promise((resolve) => rl2.question("Generate github workflow? (y/n): ", resolve));
|
|
102
|
+
rl2.close();
|
|
103
|
+
if (gen_workflow == "y") {
|
|
104
|
+
fs.mkdirSync(".github", { recursive: true });
|
|
105
|
+
fs.mkdirSync(".github/workflows", { recursive: true });
|
|
106
|
+
fs.writeFileSync(".github/workflows/pages.yml", `name: Build and deploy to pages
|
|
107
|
+
on: [push]
|
|
108
|
+
|
|
109
|
+
jobs:
|
|
110
|
+
build-and-deploy:
|
|
111
|
+
runs-on: ubuntu-latest
|
|
112
|
+
steps:
|
|
113
|
+
- name: Checkout
|
|
114
|
+
uses: actions/checkout@v4
|
|
115
|
+
|
|
116
|
+
- name: Install Node.js
|
|
117
|
+
uses: actions/setup-node@v4
|
|
118
|
+
with:
|
|
119
|
+
node-version: 22
|
|
120
|
+
|
|
121
|
+
${gen_wasm ? `
|
|
122
|
+
- name: Install Rust
|
|
123
|
+
uses: dtolnay/rust-toolchain@nightly
|
|
124
|
+
with:
|
|
125
|
+
targets: wasm32-unknown-unknown
|
|
126
|
+
|
|
127
|
+
- name: Compile WASM
|
|
128
|
+
run: cargo build --release --target wasm32-unknown-unknown
|
|
129
|
+
` : ""}
|
|
130
|
+
- name: Build HTML
|
|
131
|
+
run: npx --yes nattoppet main.ymd > index.html
|
|
132
|
+
|
|
133
|
+
- name: Deploy
|
|
134
|
+
uses: JamesIves/github-pages-deploy-action@v4
|
|
135
|
+
with:
|
|
136
|
+
branch: gh-pages
|
|
137
|
+
folder: "."
|
|
138
|
+
`);
|
|
139
|
+
}
|
|
140
|
+
console.info("Finished");
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// nattoppet-native.ts
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import * as cp from "node:child_process";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
var main_source = `#![windows_subsystem = "windows"]
|
|
10
|
+
|
|
11
|
+
use web_view::*;
|
|
12
|
+
|
|
13
|
+
fn main() {
|
|
14
|
+
static HTML_CONTENT: &str = include_str!("../target/bundle.html");
|
|
15
|
+
|
|
16
|
+
web_view::builder()
|
|
17
|
+
.title("Nattoppet Native")
|
|
18
|
+
.content(Content::Html(HTML_CONTENT))
|
|
19
|
+
.size(600, 480)
|
|
20
|
+
.resizable(false)
|
|
21
|
+
.debug(cfg!(debug_assertions))
|
|
22
|
+
.user_data(())
|
|
23
|
+
.invoke_handler(handler)
|
|
24
|
+
.run()
|
|
25
|
+
.unwrap();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fn handler(webview: &mut WebView<()>, arg: &str) -> WVResult {
|
|
29
|
+
Ok(())
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
var build_source = `#[cfg(windows)]
|
|
33
|
+
extern crate winres;
|
|
34
|
+
|
|
35
|
+
#[cfg(windows)]
|
|
36
|
+
fn main() {
|
|
37
|
+
let mut res = winres::WindowsResource::new();
|
|
38
|
+
res.set_icon("../icon.ico");
|
|
39
|
+
res.compile().unwrap();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#[cfg(not(windows))]
|
|
43
|
+
fn main() {}
|
|
44
|
+
`;
|
|
45
|
+
var cargo_source = `[package]
|
|
46
|
+
name = "nattoppet_native"
|
|
47
|
+
version = "0.1.0"
|
|
48
|
+
edition = "2021"
|
|
49
|
+
|
|
50
|
+
[dependencies]
|
|
51
|
+
web-view = { version = "0.7", features = ["edge"] }
|
|
52
|
+
|
|
53
|
+
[target.'cfg(windows)'.build-dependencies]
|
|
54
|
+
winres = "0.1"
|
|
55
|
+
|
|
56
|
+
[package.metadata.winres]
|
|
57
|
+
ProductName = "A nattoppet native app"
|
|
58
|
+
`;
|
|
59
|
+
var init = () => {
|
|
60
|
+
fs.mkdirSync("native", { recursive: true });
|
|
61
|
+
fs.mkdirSync("native/src", { recursive: true });
|
|
62
|
+
fs.mkdirSync("native/target", { recursive: true });
|
|
63
|
+
fs.writeFileSync("native/src/main.rs", main_source);
|
|
64
|
+
fs.writeFileSync("native/build.rs", build_source);
|
|
65
|
+
fs.writeFileSync("native/Cargo.toml", cargo_source);
|
|
66
|
+
};
|
|
67
|
+
var spawn2 = (cmd, args, opts) => {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
const proc = cp.spawn(cmd, args, opts);
|
|
70
|
+
let stdout = "";
|
|
71
|
+
let stderr = "";
|
|
72
|
+
proc.stdout.on("data", (d) => stdout += d);
|
|
73
|
+
proc.stderr.on("data", (d) => stderr += d);
|
|
74
|
+
proc.on("close", (code) => {
|
|
75
|
+
if (code !== 0) reject(new Error(stderr));
|
|
76
|
+
else resolve(stdout);
|
|
77
|
+
});
|
|
78
|
+
proc.on("error", reject);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
var bundle = async () => {
|
|
82
|
+
const runtimeExt = path.extname(fileURLToPath(import.meta.url)) === ".js" ? ".js" : ".ts";
|
|
83
|
+
const nattoppetPath = fileURLToPath(new URL(`nattoppet${runtimeExt}`, import.meta.url));
|
|
84
|
+
const stdout = await spawn2(process.execPath, [nattoppetPath, process.argv[3]]);
|
|
85
|
+
fs.writeFileSync("native/target/bundle.html", stdout);
|
|
86
|
+
};
|
|
87
|
+
var build = async () => {
|
|
88
|
+
await bundle();
|
|
89
|
+
await spawn2("cargo", ["build", "--release"], {
|
|
90
|
+
cwd: "native"
|
|
91
|
+
});
|
|
92
|
+
console.log("building finished. Check native/target/release/");
|
|
93
|
+
};
|
|
94
|
+
var help = () => {
|
|
95
|
+
console.log("Usage: nattoppet-native [init|bundle|build] <file.ymd>");
|
|
96
|
+
};
|
|
97
|
+
switch (process.argv[2]) {
|
|
98
|
+
case "init":
|
|
99
|
+
init();
|
|
100
|
+
break;
|
|
101
|
+
case "bundle":
|
|
102
|
+
bundle().catch((e) => {
|
|
103
|
+
console.error(e.message);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
});
|
|
106
|
+
break;
|
|
107
|
+
case "build":
|
|
108
|
+
build().catch((e) => {
|
|
109
|
+
console.error(e.message);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
});
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
help();
|
|
115
|
+
break;
|
|
116
|
+
}
|