nattoppet 2.1.0 → 4.0.1
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/common.ymd +33 -13
- package/compiler.ts +169 -0
- package/form.css +87 -0
- package/form.js +64 -0
- package/form.ymd +36 -0
- package/katex.css +1 -0
- package/katex.ymd +13 -0
- package/koa.css +157 -0
- package/{koa/after.ymd → koa.ymd} +18 -1
- package/nattoppet-dev.ts +94 -0
- package/nattoppet-init.ts +142 -0
- package/nattoppet-native.ts +116 -0
- package/nattoppet.ts +35 -0
- package/package.json +54 -14
- package/ppt.css +304 -0
- package/ppt.js +83 -0
- package/{ppt/after.ymd → ppt.ymd} +17 -1
- package/readme.md +39 -3
- package/stdlib.ts +120 -0
- package/tml.css +125 -0
- package/tml.js +3 -0
- package/{tml/after.ymd → tml.ymd} +19 -1
- package/vue.css +91 -0
- package/vue.ymd +23 -0
- package/.editorconfig +0 -15
- package/assets/katex.css +0 -1
- package/assets/manuscript.cls +0 -30
- 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/katex.ymd
ADDED
package/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
|
package/nattoppet-dev.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as fs from "node:fs"
|
|
2
|
+
import * as path from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
|
|
5
|
+
const file = process.argv[2]
|
|
6
|
+
|
|
7
|
+
if (process.argv.length < 3 || file == "--help") {
|
|
8
|
+
console.log("Usage: nattoppet-dev [file] [hook cmd]...")
|
|
9
|
+
process.exit(0)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const nattoppetPath = fileURLToPath(new URL("nattoppet.ts", import.meta.url))
|
|
13
|
+
|
|
14
|
+
Bun.serve({
|
|
15
|
+
port: 3939,
|
|
16
|
+
async fetch(request) {
|
|
17
|
+
const url = new URL(request.url)
|
|
18
|
+
|
|
19
|
+
// Static file serving
|
|
20
|
+
if (url.pathname !== '/') {
|
|
21
|
+
try {
|
|
22
|
+
const filePath = path.join(process.cwd(), decodeURIComponent(url.pathname))
|
|
23
|
+
const file = Bun.file(filePath)
|
|
24
|
+
if (await file.exists()) {
|
|
25
|
+
return new Response(file)
|
|
26
|
+
}
|
|
27
|
+
} catch (e) {
|
|
28
|
+
console.error(e)
|
|
29
|
+
}
|
|
30
|
+
return new Response(null, { status: 404 })
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Run build hooks if specified
|
|
34
|
+
if (process.argv.length > 3) {
|
|
35
|
+
const hookProc = Bun.spawn(process.argv.slice(3))
|
|
36
|
+
const exitCode = await hookProc.exited
|
|
37
|
+
|
|
38
|
+
if (exitCode !== 0) {
|
|
39
|
+
console.warn("!!! hook command exit with non-0 status")
|
|
40
|
+
return new Response("Hook command failed", { status: 500 })
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Compile the nattoppet file
|
|
45
|
+
const compileProc = Bun.spawn([
|
|
46
|
+
process.execPath,
|
|
47
|
+
"run",
|
|
48
|
+
nattoppetPath,
|
|
49
|
+
file,
|
|
50
|
+
"--dev"
|
|
51
|
+
], {
|
|
52
|
+
stdout: 'pipe',
|
|
53
|
+
stderr: 'pipe'
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const [stdout, stderr] = await Promise.all([
|
|
57
|
+
new Response(compileProc.stdout).arrayBuffer(),
|
|
58
|
+
new Response(compileProc.stderr).text()
|
|
59
|
+
])
|
|
60
|
+
|
|
61
|
+
const exitCode = await compileProc.exited
|
|
62
|
+
|
|
63
|
+
if (stderr) {
|
|
64
|
+
console.error(stderr)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const content = exitCode === 0 ? new Uint8Array(stdout) : new TextEncoder().encode("Compilation failed")
|
|
68
|
+
|
|
69
|
+
return new Response(content, {
|
|
70
|
+
headers: {
|
|
71
|
+
"Content-Type": "text/html"
|
|
72
|
+
},
|
|
73
|
+
status: 200
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
console.log("Server running at http://127.0.0.1:3939")
|
|
79
|
+
|
|
80
|
+
// Open browser
|
|
81
|
+
const platform = process.platform
|
|
82
|
+
const browser = process.env.BROWSER ?? (
|
|
83
|
+
platform === 'darwin' ? 'open' :
|
|
84
|
+
platform === 'win32' ? 'start' :
|
|
85
|
+
'xdg-open'
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
const browserCmd = browser.includes('chrom')
|
|
89
|
+
? [browser, "--app=http://127.0.0.1:3939"]
|
|
90
|
+
: [browser, "http://127.0.0.1:3939"]
|
|
91
|
+
|
|
92
|
+
Bun.spawn(browserCmd, {
|
|
93
|
+
stdio: ['ignore', 'ignore', 'ignore']
|
|
94
|
+
})
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import * as fs from "node:fs"
|
|
2
|
+
|
|
3
|
+
const type = process.argv[2]
|
|
4
|
+
|
|
5
|
+
const avaliable_templates = ["form"]
|
|
6
|
+
|
|
7
|
+
if (process.argv.length < 3 || !avaliable_templates.includes(type)) {
|
|
8
|
+
console.log("Usage: nattoppet-init form")
|
|
9
|
+
process.exit(0)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
fs.writeFileSync("main.ymd", `\
|
|
13
|
+
[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
|
+
|
|
28
|
+
fs.writeFileSync("main.js", `\
|
|
29
|
+
async function run(args) {
|
|
30
|
+
return JSON.stringify(args)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (typeof Deno != 'undefined')
|
|
34
|
+
run({}).then(console.log)
|
|
35
|
+
`)
|
|
36
|
+
|
|
37
|
+
const gen_wasm = prompt("Generate wasm? (give lib name or empty to cancel): ")
|
|
38
|
+
|
|
39
|
+
if (gen_wasm) {
|
|
40
|
+
fs.writeFileSync(`${gen_wasm}.rs`, `\
|
|
41
|
+
#[no_mangle]
|
|
42
|
+
pub unsafe extern fn sum(data: *const u32, len: usize) -> u32 {
|
|
43
|
+
let mut sum = 0;
|
|
44
|
+
for i in 0..len {
|
|
45
|
+
sum += *data.add(i);
|
|
46
|
+
}
|
|
47
|
+
sum
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#[no_mangle]
|
|
51
|
+
pub unsafe extern "C" fn alloc_memory(byte_size: usize, alignment: usize) -> *mut u8 {
|
|
52
|
+
let layout = std::alloc::Layout::from_size_align_unchecked(byte_size, alignment);
|
|
53
|
+
std::alloc::alloc(layout)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#[no_mangle]
|
|
57
|
+
pub unsafe extern "C" fn free_memory(ptr: *mut u8, byte_size: usize, alignment: usize) {
|
|
58
|
+
let layout = std::alloc::Layout::from_size_align_unchecked(byte_size, alignment);
|
|
59
|
+
std::alloc::dealloc(ptr, layout)
|
|
60
|
+
}
|
|
61
|
+
`)
|
|
62
|
+
|
|
63
|
+
fs.writeFileSync("Cargo.toml", `\
|
|
64
|
+
[package]
|
|
65
|
+
name = "${gen_wasm}"
|
|
66
|
+
version = "0.1.0"
|
|
67
|
+
authors = ["Shiwei Zhang <ylxdzsw@gmail.com>"]
|
|
68
|
+
edition = "2024"
|
|
69
|
+
|
|
70
|
+
[lib]
|
|
71
|
+
crate-type = ["cdylib"]
|
|
72
|
+
path = "${gen_wasm}.rs"
|
|
73
|
+
|
|
74
|
+
[profile.release]
|
|
75
|
+
codegen-units = 1
|
|
76
|
+
lto = true
|
|
77
|
+
strip = true
|
|
78
|
+
|
|
79
|
+
[dependencies]
|
|
80
|
+
absurd = { git = "https://github.com/ylxdzsw/absurd" }
|
|
81
|
+
`)
|
|
82
|
+
|
|
83
|
+
fs.appendFileSync("main.js", `
|
|
84
|
+
|
|
85
|
+
async function call_wasm() {
|
|
86
|
+
await window.wasm_ready
|
|
87
|
+
const buffer_ptr = ${gen_wasm}.alloc_memory(4 * 8, 4)
|
|
88
|
+
const buffer_view = new Uint32Array(${gen_wasm}.memory.buffer, buffer_ptr, 8)
|
|
89
|
+
buffer_view.set([1, 2, 3, 4, 5, 6, 7, 8])
|
|
90
|
+
const sum = ${gen_wasm}.sum(buffer_ptr, 8)
|
|
91
|
+
${gen_wasm}.free_memory(buffer_ptr, 4 * 8, 4)
|
|
92
|
+
console.log(sum)
|
|
93
|
+
}
|
|
94
|
+
`)
|
|
95
|
+
|
|
96
|
+
fs.appendFileSync("main.ymd", `
|
|
97
|
+
[require](target/wasm32-unknown-unknown/release/${gen_wasm}.wasm)
|
|
98
|
+
`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
const gen_workflow = prompt("Generate github workflow? (y/n): ")
|
|
103
|
+
|
|
104
|
+
if (gen_workflow == "y") {
|
|
105
|
+
fs.mkdirSync(".github", { recursive: true })
|
|
106
|
+
fs.mkdirSync(".github/workflows", { recursive: true })
|
|
107
|
+
fs.writeFileSync(".github/workflows/pages.yml", `\
|
|
108
|
+
name: Build and deploy to pages
|
|
109
|
+
on: [push]
|
|
110
|
+
|
|
111
|
+
jobs:
|
|
112
|
+
build-and-deploy:
|
|
113
|
+
runs-on: ubuntu-latest
|
|
114
|
+
steps:
|
|
115
|
+
- name: Checkout
|
|
116
|
+
uses: actions/checkout@v4
|
|
117
|
+
|
|
118
|
+
- name: Install Bun
|
|
119
|
+
uses: oven-sh/setup-bun@v2
|
|
120
|
+
with:
|
|
121
|
+
bun-version: latest
|
|
122
|
+
${gen_wasm ? `
|
|
123
|
+
- name: Install Rust
|
|
124
|
+
uses: dtolnay/rust-toolchain@nightly
|
|
125
|
+
with:
|
|
126
|
+
targets: wasm32-unknown-unknown
|
|
127
|
+
|
|
128
|
+
- name: Compile WASM
|
|
129
|
+
run: cargo build --release --target wasm32-unknown-unknown
|
|
130
|
+
` : ''}
|
|
131
|
+
- name: Build HTML
|
|
132
|
+
run: bun run nattoppet.ts main.ymd > index.html
|
|
133
|
+
|
|
134
|
+
- name: Deploy
|
|
135
|
+
uses: JamesIves/github-pages-deploy-action@v4
|
|
136
|
+
with:
|
|
137
|
+
branch: gh-pages
|
|
138
|
+
folder: "."
|
|
139
|
+
`)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
console.info("Finished")
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as fs from "node:fs"
|
|
2
|
+
import * as path from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
|
|
5
|
+
const main_source = `\
|
|
6
|
+
#![windows_subsystem = "windows"]
|
|
7
|
+
|
|
8
|
+
use web_view::*;
|
|
9
|
+
|
|
10
|
+
fn main() {
|
|
11
|
+
static HTML_CONTENT: &str = include_str!("../target/bundle.html");
|
|
12
|
+
|
|
13
|
+
web_view::builder()
|
|
14
|
+
.title("Nattoppet Native")
|
|
15
|
+
.content(Content::Html(HTML_CONTENT))
|
|
16
|
+
.size(600, 480)
|
|
17
|
+
.resizable(false)
|
|
18
|
+
.debug(cfg!(debug_assertions))
|
|
19
|
+
.user_data(())
|
|
20
|
+
.invoke_handler(handler)
|
|
21
|
+
.run()
|
|
22
|
+
.unwrap();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
fn handler(webview: &mut WebView<()>, arg: &str) -> WVResult {
|
|
26
|
+
Ok(())
|
|
27
|
+
}
|
|
28
|
+
`
|
|
29
|
+
|
|
30
|
+
const build_source = `\
|
|
31
|
+
#[cfg(windows)]
|
|
32
|
+
extern crate winres;
|
|
33
|
+
|
|
34
|
+
#[cfg(windows)]
|
|
35
|
+
fn main() {
|
|
36
|
+
let mut res = winres::WindowsResource::new();
|
|
37
|
+
res.set_icon("../icon.ico");
|
|
38
|
+
res.compile().unwrap();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#[cfg(not(windows))]
|
|
42
|
+
fn main() {}
|
|
43
|
+
`
|
|
44
|
+
|
|
45
|
+
const cargo_source = `\
|
|
46
|
+
[package]
|
|
47
|
+
name = "nattoppet_native"
|
|
48
|
+
version = "0.1.0"
|
|
49
|
+
edition = "2021"
|
|
50
|
+
|
|
51
|
+
[dependencies]
|
|
52
|
+
web-view = { version = "0.7", features = ["edge"] }
|
|
53
|
+
|
|
54
|
+
[target.'cfg(windows)'.build-dependencies]
|
|
55
|
+
winres = "0.1"
|
|
56
|
+
|
|
57
|
+
[package.metadata.winres]
|
|
58
|
+
ProductName = "A nattoppet native app"
|
|
59
|
+
`
|
|
60
|
+
|
|
61
|
+
const init = () => {
|
|
62
|
+
fs.mkdirSync('native', { recursive: true })
|
|
63
|
+
fs.mkdirSync('native/src', { recursive: true })
|
|
64
|
+
fs.mkdirSync('native/target', { recursive: true })
|
|
65
|
+
fs.writeFileSync("native/src/main.rs", main_source)
|
|
66
|
+
fs.writeFileSync("native/build.rs", build_source)
|
|
67
|
+
fs.writeFileSync("native/Cargo.toml", cargo_source)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const bundle = async () => {
|
|
71
|
+
const nattoppetPath = fileURLToPath(new URL("nattoppet.ts", import.meta.url))
|
|
72
|
+
const proc = Bun.spawn([
|
|
73
|
+
process.execPath,
|
|
74
|
+
"run",
|
|
75
|
+
nattoppetPath,
|
|
76
|
+
process.argv[3]
|
|
77
|
+
], {
|
|
78
|
+
stdout: 'pipe',
|
|
79
|
+
stderr: 'pipe'
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const [stdout, stderr] = await Promise.all([
|
|
83
|
+
new Response(proc.stdout).arrayBuffer(),
|
|
84
|
+
new Response(proc.stderr).text()
|
|
85
|
+
])
|
|
86
|
+
|
|
87
|
+
if (stderr)
|
|
88
|
+
console.error(stderr)
|
|
89
|
+
|
|
90
|
+
await Bun.write('native/target/bundle.html', stdout)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const build = async () => {
|
|
94
|
+
await bundle()
|
|
95
|
+
const proc = Bun.spawn(['cargo', 'build', '--release'], {
|
|
96
|
+
cwd: 'native'
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
const exitCode = await proc.exited
|
|
100
|
+
if (exitCode != 0) {
|
|
101
|
+
console.error("Cargo exit with code: " + exitCode)
|
|
102
|
+
} else {
|
|
103
|
+
console.log("building finished. Check native/target/release/")
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const help = () => {
|
|
108
|
+
console.log("Usage: nattoppet-native [init|bundle|build] <file.ymd>")
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
switch (process.argv[2]) {
|
|
112
|
+
case 'init': init(); break
|
|
113
|
+
case 'bundle': bundle(); break
|
|
114
|
+
case 'build': build(); break
|
|
115
|
+
default: help(); break
|
|
116
|
+
}
|
package/nattoppet.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as path from "node:path"
|
|
2
|
+
import * as fs from "node:fs"
|
|
3
|
+
import minifier from "html-minifier-terser"
|
|
4
|
+
|
|
5
|
+
import stdlib from "./stdlib.ts"
|
|
6
|
+
import * as compiler from "./compiler.ts"
|
|
7
|
+
|
|
8
|
+
const compiled = await (async () => {
|
|
9
|
+
const file = process.argv[2]
|
|
10
|
+
if (file) {
|
|
11
|
+
const dir = path.dirname(path.resolve(file))
|
|
12
|
+
const code = fs.readFileSync(file, 'utf-8')
|
|
13
|
+
return await compiler.compile(code, { ...stdlib, base_dir: dir })
|
|
14
|
+
} else {
|
|
15
|
+
const dir = process.cwd()
|
|
16
|
+
const chunks: Uint8Array[] = []
|
|
17
|
+
for await (const chunk of process.stdin) {
|
|
18
|
+
chunks.push(chunk)
|
|
19
|
+
}
|
|
20
|
+
const code = Buffer.concat(chunks).toString('utf-8')
|
|
21
|
+
return await compiler.compile(code, { ...stdlib, base_dir: dir })
|
|
22
|
+
}
|
|
23
|
+
})()
|
|
24
|
+
|
|
25
|
+
const minified = process.argv.includes('--dev') ? compiled : await minifier.minify(compiled, {
|
|
26
|
+
collapseWhitespace: true,
|
|
27
|
+
removeAttributeQuotes: true,
|
|
28
|
+
removeComments: true,
|
|
29
|
+
removeRedundantAttributes: true,
|
|
30
|
+
removeOptionalTags: true,
|
|
31
|
+
minifyCSS: true,
|
|
32
|
+
minifyJS: true,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
process.stdout.write(minified)
|
package/package.json
CHANGED
|
@@ -1,20 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nattoppet",
|
|
3
|
+
"version": "4.0.1",
|
|
3
4
|
"description": "A tiny macro-based markup language for blogging",
|
|
4
|
-
"author": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
5
|
+
"author": "ylxdzsw <ylxdzsw@gmail.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"nattoppet.ts",
|
|
10
|
+
"nattoppet-dev.ts",
|
|
11
|
+
"nattoppet-init.ts",
|
|
12
|
+
"nattoppet-native.ts",
|
|
13
|
+
"compiler.ts",
|
|
14
|
+
"stdlib.ts",
|
|
15
|
+
"common.ymd",
|
|
16
|
+
"vue.ymd",
|
|
17
|
+
"form.ymd",
|
|
18
|
+
"katex.ymd",
|
|
19
|
+
"koa.ymd",
|
|
20
|
+
"ppt.ymd",
|
|
21
|
+
"tml.ymd",
|
|
22
|
+
"vue.css",
|
|
23
|
+
"form.css",
|
|
24
|
+
"form.js",
|
|
25
|
+
"koa.css",
|
|
26
|
+
"ppt.css",
|
|
27
|
+
"ppt.js",
|
|
28
|
+
"tml.css",
|
|
29
|
+
"tml.js",
|
|
30
|
+
"katex.css",
|
|
31
|
+
"GUIDE.md",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
13
34
|
"bin": {
|
|
14
|
-
"nattoppet": "./nattoppet.
|
|
15
|
-
"nattoppet-dev": "./nattoppet-dev.
|
|
16
|
-
"nattoppet-
|
|
35
|
+
"nattoppet": "./nattoppet.ts",
|
|
36
|
+
"nattoppet-dev": "./nattoppet-dev.ts",
|
|
37
|
+
"nattoppet-init": "./nattoppet-init.ts",
|
|
38
|
+
"nattoppet-native": "./nattoppet-native.ts"
|
|
17
39
|
},
|
|
18
|
-
"
|
|
19
|
-
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "bun build ./nattoppet.ts --outdir=./dist --target=bun",
|
|
42
|
+
"dev": "bun run --watch ./nattoppet-dev.ts",
|
|
43
|
+
"test": "bun test",
|
|
44
|
+
"test:watch": "bun test --watch",
|
|
45
|
+
"compile": "bun run ./nattoppet.ts",
|
|
46
|
+
"init": "bun run ./nattoppet-init.ts",
|
|
47
|
+
"native": "bun run ./nattoppet-native.ts"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"coffeescript": "^2.7.0",
|
|
51
|
+
"html-minifier-terser": "^7.2.0",
|
|
52
|
+
"katex": "0.16.45",
|
|
53
|
+
"less": "^4.2.0",
|
|
54
|
+
"marked": "^9.1.6"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": { },
|
|
57
|
+
"engines": {
|
|
58
|
+
"bun": ">=1.0.0"
|
|
59
|
+
}
|
|
20
60
|
}
|