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/katex.ymd ADDED
@@ -0,0 +1,13 @@
1
+ <style>
2
+ [mixin] katex.css
3
+ </style>
4
+
5
+ [#slot]
6
+
7
+ [$]=
8
+ const tex = capture_until('$')
9
+ render_katex(tex, false)
10
+
11
+ [$$]=
12
+ const {block} = std_call(true)
13
+ render_katex(block, true)
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] @std/common.ymd
39
+ [mixin] common.ymd
@@ -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": "Shiwei Zhang <ylxdzsw@gmail.com>",
5
- "version": "2.1.0",
6
- "dependencies": {
7
- "coffeescript": "^2.5.1",
8
- "html-minifier": "^4.0.0",
9
- "katex": "^0.13.0",
10
- "less": "^4.1.1",
11
- "marked": "^2.0.1"
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.js",
15
- "nattoppet-dev": "./nattoppet-dev.js",
16
- "nattoppet-native": "./nattoppet-native.js"
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
- "license": "MIT",
19
- "repository": "https://github.com/ylxdzsw/nattoppet.git"
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
  }