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/assets/manuscript.cls
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
\NeedsTeXFormat{LaTeX2e}
|
|
2
|
-
\ProvidesClass{myarticle}[Article class of ylxdzsw's favor]
|
|
3
|
-
|
|
4
|
-
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
|
|
5
|
-
\ProcessOptions
|
|
6
|
-
|
|
7
|
-
\LoadClass[a4paper, 11pt]{article}
|
|
8
|
-
|
|
9
|
-
\RequirePackage[left=1.1in,right=1.1in,top=1in,bottom=1in]{geometry}
|
|
10
|
-
\RequirePackage[utf8]{inputenc}
|
|
11
|
-
|
|
12
|
-
\makeatletter
|
|
13
|
-
\def\@maketitle{%
|
|
14
|
-
\newpage
|
|
15
|
-
\null
|
|
16
|
-
\begin{center}%
|
|
17
|
-
\let \footnote \thanks
|
|
18
|
-
{\LARGE \@title \par}%
|
|
19
|
-
\vskip 1.5em%
|
|
20
|
-
{\large
|
|
21
|
-
\lineskip .5em%
|
|
22
|
-
\begin{tabular}[t]{c}%
|
|
23
|
-
\@author\quad\textbar\quad\@date
|
|
24
|
-
\end{tabular}\par}%
|
|
25
|
-
\end{center}%
|
|
26
|
-
\par
|
|
27
|
-
\vskip 1.5em}
|
|
28
|
-
\makeatother
|
|
29
|
-
|
|
30
|
-
\endinput
|
package/common.ymd
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
[require]=
|
|
2
|
-
const {args: [file]} = std_call()
|
|
3
|
-
const content = read(file)
|
|
4
|
-
switch (extname(file)) {
|
|
5
|
-
case 'less':
|
|
6
|
-
`<style>${render_less(content)}</style>`; break
|
|
7
|
-
case 'css':
|
|
8
|
-
`<style>${content}</style>`; break
|
|
9
|
-
case 'coffee':
|
|
10
|
-
`<script>${render_coffee(content, { bare: true })}</script>`; break
|
|
11
|
-
case 'js':
|
|
12
|
-
`<script>${content}</script>`; break
|
|
13
|
-
case 'md':
|
|
14
|
-
render_markdown(content); break
|
|
15
|
-
default:
|
|
16
|
-
content; break
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
[img]=
|
|
20
|
-
const {opts, args: [file, alt]} = std_call()
|
|
21
|
-
const classes = opts.join(' ')
|
|
22
|
-
const mimesuf = extname(file) == 'svg' ? 'svg+xml' : extname(file)
|
|
23
|
-
const content = `data:image/${mimesuf};base64,` + read(file, 'base64')
|
|
24
|
-
const htmltag = `<img class="${classes}" src="${content}" alt="${alt || ''}"/>`
|
|
25
|
-
opts.includes('center') ? `<div style="text-align:center">${htmltag}</div>` : htmltag
|
|
26
|
-
|
|
27
|
-
[h2]= `<h2>${interpret(capture_until('\n'))}</h2>`
|
|
28
|
-
[h3]= `<h3>${interpret(capture_until('\n'))}</h3>`
|
|
29
|
-
[h4]= `<h4>${interpret(capture_until('\n'))}</h4>`
|
|
30
|
-
|
|
31
|
-
[quote]=
|
|
32
|
-
const {opts, block} = std_call(true)
|
|
33
|
-
;`<blockquote class="${opts.join(' ')}">${interpret(block)}</blockquote>`
|
|
34
|
-
|
|
35
|
-
[#]= std_call(true), ''
|
|
36
|
-
|
|
37
|
-
[-]=
|
|
38
|
-
const {opts, block} = std_call(true)
|
|
39
|
-
;`<li class="${opts.join(' ')}">${interpret(block)}</li>`
|
|
40
|
-
|
|
41
|
-
[file]=
|
|
42
|
-
const {args: [file, text]} = std_call()
|
|
43
|
-
const content = "data:application/octet-stream;base64," + read(file, 'base64')
|
|
44
|
-
;`<a download="${basename(file)}" href="${content}">${text ? interpret(text) : basename(file)}</a>`
|
|
45
|
-
|
|
46
|
-
[code]=
|
|
47
|
-
const {opts: [language], args: [content], block} = std_call()
|
|
48
|
-
const code = `<code ${language ? `class="language-${language}"` : ''}>${content || block.slice(1)}</code>`
|
|
49
|
-
content ? code : `<pre>${code}</pre>`
|
|
50
|
-
|
|
51
|
-
[link]=
|
|
52
|
-
const {opts: [id], args: [href, text]} = std_call()
|
|
53
|
-
const content = text || capture_until('\n').trim() || href
|
|
54
|
-
;`<a ${id ? `id="${id}"` : ''} href="${href}">${interpret(content)}</a>`
|
|
55
|
-
|
|
56
|
-
[sup]=
|
|
57
|
-
const {args: [text]} = std_call()
|
|
58
|
-
;`<sup>${interpret(text)}</sup>`
|
|
59
|
-
|
|
60
|
-
[$]=
|
|
61
|
-
const tex = capture_until('$')
|
|
62
|
-
render_katex(tex, false)
|
|
63
|
-
|
|
64
|
-
[$$]=
|
|
65
|
-
const {block} = std_call(true)
|
|
66
|
-
render_katex(block, true)
|
|
67
|
-
|
|
68
|
-
[eval]=
|
|
69
|
-
const {block} = std_call(true)
|
|
70
|
-
eval(block)
|
|
71
|
-
|
|
72
|
-
[eval*]=
|
|
73
|
-
const {block} = std_call(true)
|
|
74
|
-
eval(block); ''
|
package/compiler.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const vm = require("vm")
|
|
4
|
-
|
|
5
|
-
const pattern = /^(?:\[(.+?)\]([:=])|\[mixin\] (.+?)\n)/m
|
|
6
|
-
|
|
7
|
-
const tokenize = (str, rpath=x=>x) => {
|
|
8
|
-
const tokens = []
|
|
9
|
-
|
|
10
|
-
while (true) {
|
|
11
|
-
const m = str.match(pattern)
|
|
12
|
-
if (!m) {
|
|
13
|
-
if (str) tokens.push({ type: 'text', content: str })
|
|
14
|
-
break
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (m.index > 0) {
|
|
18
|
-
tokens.push({ type: 'text', content: str.substring(0, m.index) })
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (m[3]) {
|
|
22
|
-
tokens.push({ type: 'mixin', path: m[3] })
|
|
23
|
-
str = str.substring(m.index + m[0].length)
|
|
24
|
-
continue
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const name = m[1]
|
|
28
|
-
const type = m[2] == ':' ? 'ref' : 'fn'
|
|
29
|
-
str = str.substring(m.index + m[0].length)
|
|
30
|
-
|
|
31
|
-
const p1 = str.indexOf('\n\n')
|
|
32
|
-
const p2 = str.search(pattern)
|
|
33
|
-
const p = p1 >= 0 && p2 >= 0 ? Math.min(p1+1, p2) :
|
|
34
|
-
p1 < 0 && p2 < 0 ? str.length : Math.max(p1+1, p2)
|
|
35
|
-
|
|
36
|
-
const content = str.substring(0, p).trim()
|
|
37
|
-
str = str.substring(p)
|
|
38
|
-
|
|
39
|
-
tokens.push({ type, name, content })
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
for (let i = 0; i < tokens.length; i++) if (tokens[i].type == 'mixin') {
|
|
43
|
-
const fs = require('fs')
|
|
44
|
-
const path = rpath(tokens[i].path)
|
|
45
|
-
const stat = fs.statSync(path)
|
|
46
|
-
if (stat.isDirectory()) { // include before and after
|
|
47
|
-
const before = tokenize(fs.readFileSync(path + '/before.ymd', 'utf8'), rpath)
|
|
48
|
-
const after = tokenize(fs.readFileSync(path + '/after.ymd', 'utf8'), rpath)
|
|
49
|
-
tokens.splice(i, 1, ...before)
|
|
50
|
-
tokens.push(...after)
|
|
51
|
-
} else {
|
|
52
|
-
const mixins = tokenize(fs.readFileSync(path, 'utf8'), rpath)
|
|
53
|
-
tokens.splice(i, 1, ...mixins)
|
|
54
|
-
}
|
|
55
|
-
i -= 1 // revisit i since we replaced it
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return tokens
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const interpret = (str, env, defs) => {
|
|
62
|
-
const p1 = str.search(/^ /m)
|
|
63
|
-
const p2 = str.search(/\[(.+?)\]/)
|
|
64
|
-
if (p1 < 0 && p2 < 0) return str
|
|
65
|
-
|
|
66
|
-
if (p2 < 0 || (p1 >= 0 && p1 < p2)) {
|
|
67
|
-
const head = str.substring(0, p1)
|
|
68
|
-
str = str.substring(p1+2)
|
|
69
|
-
let p = str.indexOf('\n\n')
|
|
70
|
-
if (p < 0) p = str.length
|
|
71
|
-
return head + '<p>' + interpret(str.substring(0, p), env, defs) + '</p>' + interpret(str.substring(p+1), env, defs)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const name = str.match(/\[(.+?)\]/)[1]
|
|
75
|
-
const i = defs.findIndex(x => x.name == name)
|
|
76
|
-
if (i < 0) throw `definition ${name} not found`
|
|
77
|
-
|
|
78
|
-
const def = defs[i]
|
|
79
|
-
switch (def.type) {
|
|
80
|
-
case 'fn':
|
|
81
|
-
env.remaining = str.substring(p2 + name.length + 2)
|
|
82
|
-
env.interpret = str => { // a "scoped" interpret function capable for interpreting substrings. We preserve the "remaining" property outside.
|
|
83
|
-
const remaining = env.remaining
|
|
84
|
-
const result = interpret(str, env, defs) // We gaved full defs available on the call site (dynamic scoping) as the text to be interpreted is part of the call site text.
|
|
85
|
-
env.remaining = remaining
|
|
86
|
-
return result
|
|
87
|
-
}
|
|
88
|
-
const result = vm.runInContext('{' + def.content + '}', env)
|
|
89
|
-
return str.substring(0, p2) + result + interpret(env.remaining, env, defs)
|
|
90
|
-
case 'ref':
|
|
91
|
-
return str.substring(0, p2) +
|
|
92
|
-
interpret(def.content, env, defs.slice(i+1)) + // However for ref we use lexical scoping. Exclude self to prevent recusion
|
|
93
|
-
interpret(str.substring(p2 + name.length + 2), env, defs)
|
|
94
|
-
default: throw 'unknown defs type'
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
exports.compile = (str, locals={}) => {
|
|
99
|
-
const env = vm.createContext(locals)
|
|
100
|
-
for (const k in env) if (typeof(env[k]) == 'function')
|
|
101
|
-
env[k] = env[k].bind(env)
|
|
102
|
-
|
|
103
|
-
let tokens = tokenize(str, env.rpath)
|
|
104
|
-
let output = ''
|
|
105
|
-
while (true) {
|
|
106
|
-
const token = tokens.shift()
|
|
107
|
-
if (!token) return output
|
|
108
|
-
if (token.type == 'text') {
|
|
109
|
-
output += interpret(token.content, env, tokens)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/*
|
|
115
|
-
TODO:
|
|
116
|
-
1. support first-class markdown-like nestable lists
|
|
117
|
-
2. cleanup the spaces, carefully define when to trim
|
|
118
|
-
3. require a newline before indent to open paragraph?
|
|
119
|
-
4. provide relative path resolution inside mixins
|
|
120
|
-
*/
|
package/koa/before.ymd
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
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
|
-
[require](@std/koa/koa.less)
|
|
8
|
-
|
|
9
|
-
<section id="title">
|
|
10
|
-
<h1>[title]</h1>
|
|
11
|
-
|
|
12
|
-
[eval*] this.sections = []
|
package/koa/koa.less
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
html {
|
|
2
|
-
font-family: serif;
|
|
3
|
-
font-size: 18px;
|
|
4
|
-
line-height: 1.5;
|
|
5
|
-
width: 100%;
|
|
6
|
-
height: 100%;
|
|
7
|
-
|
|
8
|
-
background: white;
|
|
9
|
-
color: #33333d;
|
|
10
|
-
|
|
11
|
-
@media (max-width: 625px) {
|
|
12
|
-
font-size: 16px;
|
|
13
|
-
text-align: justify;
|
|
14
|
-
hyphens: auto;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
body {
|
|
19
|
-
height: 100%;
|
|
20
|
-
width: 100%;
|
|
21
|
-
padding: 0;
|
|
22
|
-
margin: 0;
|
|
23
|
-
overflow-y: scroll;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
a {
|
|
27
|
-
color: #027AD2;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
section {
|
|
31
|
-
min-height: 50%;
|
|
32
|
-
padding: 150px 10vw;
|
|
33
|
-
|
|
34
|
-
@media (max-width: 625px) {
|
|
35
|
-
padding: 25px 1.25rem;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
&:nth-child(2n-1) {
|
|
39
|
-
background: #fbfbfb;
|
|
40
|
-
box-shadow: inset 0 1px 0 0 white;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
&:not(:last-child) {
|
|
44
|
-
border-bottom: 1px solid #eee;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
pre {
|
|
49
|
-
background: white;
|
|
50
|
-
border-top: 1px solid #eee;
|
|
51
|
-
border-bottom: 1px solid #eee;
|
|
52
|
-
padding: 25px;
|
|
53
|
-
font-size: .8rem;
|
|
54
|
-
text-align: left;
|
|
55
|
-
overflow-x: auto;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
code {
|
|
59
|
-
font-family: monospace;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
h2 {
|
|
63
|
-
margin-top: 40px;
|
|
64
|
-
font-size: 2rem;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
h3 {
|
|
68
|
-
margin-top: 80px;
|
|
69
|
-
font-size: 1.2rem;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
h4 {
|
|
73
|
-
margin-top: 40px;
|
|
74
|
-
font-size: 1rem;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
ul li {
|
|
78
|
-
font-size: .9rem;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
p {
|
|
82
|
-
text-indent: 2rem;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
#title {
|
|
86
|
-
padding: 0;
|
|
87
|
-
height: 100%;
|
|
88
|
-
text-align: center;
|
|
89
|
-
position: relative;
|
|
90
|
-
|
|
91
|
-
@media (max-width: 625px) {
|
|
92
|
-
height: 40vh;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
h1 {
|
|
96
|
-
position: absolute;
|
|
97
|
-
top: 45%;
|
|
98
|
-
width: 100%;
|
|
99
|
-
transform: translateY(-50%);
|
|
100
|
-
margin: 0;
|
|
101
|
-
|
|
102
|
-
font-size: 6rem;
|
|
103
|
-
font-weight: normal;
|
|
104
|
-
|
|
105
|
-
@media (max-width: 625px) {
|
|
106
|
-
font-size: 3rem;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
#nav {
|
|
112
|
-
position: fixed;
|
|
113
|
-
top: 35px;
|
|
114
|
-
right: 30px;
|
|
115
|
-
z-index: 5;
|
|
116
|
-
|
|
117
|
-
@media (max-width: 625px) {
|
|
118
|
-
top: 15px;
|
|
119
|
-
right: 10px;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
#nav-icon {
|
|
123
|
-
position: absolute;
|
|
124
|
-
top: 0;
|
|
125
|
-
right: 0;
|
|
126
|
-
padding: 6px;
|
|
127
|
-
background: rgba(255,255,255,.9);
|
|
128
|
-
border-radius: 2px;
|
|
129
|
-
border: 1px solid transparent;
|
|
130
|
-
font-size: 0;
|
|
131
|
-
z-index: 4;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
#nav-menu {
|
|
135
|
-
display: none;
|
|
136
|
-
position: relative;
|
|
137
|
-
top: 35px;
|
|
138
|
-
right: 0;
|
|
139
|
-
margin: 0;
|
|
140
|
-
border: 1px solid #efefef;
|
|
141
|
-
border-bottom: 1px solid #ddd;
|
|
142
|
-
border-radius: 2px;
|
|
143
|
-
padding: 25px;
|
|
144
|
-
background: rgba(255,255,255,.95);
|
|
145
|
-
box-shadow: 0 1px 3px 0 #eee;
|
|
146
|
-
z-index: 3;
|
|
147
|
-
|
|
148
|
-
li {
|
|
149
|
-
list-style: none;
|
|
150
|
-
|
|
151
|
-
a {
|
|
152
|
-
display: block;
|
|
153
|
-
text-decoration: none;
|
|
154
|
-
padding: 3px 0;
|
|
155
|
-
color: inherit;
|
|
156
|
-
font-size: 1rem;
|
|
157
|
-
|
|
158
|
-
&:hover {
|
|
159
|
-
text-decoration: underline;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
&:hover {
|
|
166
|
-
ul {
|
|
167
|
-
display: block;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
#nav-icon {
|
|
171
|
-
border: 1px solid #efefef;
|
|
172
|
-
border-bottom: none;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
#nav-menu {
|
|
176
|
-
display: block;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
package/native/Cargo.toml
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "nattoppet_native"
|
|
3
|
-
version = "0.1.0"
|
|
4
|
-
edition = "2021"
|
|
5
|
-
|
|
6
|
-
[dependencies]
|
|
7
|
-
web-view = { version = "0.7", features = ["edge"] }
|
|
8
|
-
|
|
9
|
-
[target.'cfg(windows)'.build-dependencies]
|
|
10
|
-
winres = "0.1"
|
|
11
|
-
|
|
12
|
-
[package.metadata.winres]
|
|
13
|
-
ProductName = "A nattoppet native app"
|
package/native/build.rs
DELETED
package/native/src/main.rs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#![windows_subsystem = "windows"]
|
|
2
|
-
|
|
3
|
-
use web_view::*;
|
|
4
|
-
|
|
5
|
-
fn main() {
|
|
6
|
-
static HTML_CONTENT: &str = include_str!("../target/bundle.html");
|
|
7
|
-
|
|
8
|
-
web_view::builder()
|
|
9
|
-
.title("Nattoppet Native")
|
|
10
|
-
.content(Content::Html(HTML_CONTENT))
|
|
11
|
-
.size(600, 480)
|
|
12
|
-
.resizable(false)
|
|
13
|
-
.debug(cfg!(debug_assertions))
|
|
14
|
-
.user_data(())
|
|
15
|
-
.invoke_handler(handler)
|
|
16
|
-
.run()
|
|
17
|
-
.unwrap();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
fn handler(webview: &mut WebView<()>, arg: &str) -> WVResult {
|
|
21
|
-
Ok(())
|
|
22
|
-
}
|
package/nattoppet-dev.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
'use strict'
|
|
4
|
-
|
|
5
|
-
const file = process.argv[2]
|
|
6
|
-
|
|
7
|
-
if (process.argv.length != 3 || file == "--help")
|
|
8
|
-
return console.log("Usage: nattoppet-dev [file]")
|
|
9
|
-
|
|
10
|
-
const fs = require('fs')
|
|
11
|
-
const cp = require('child_process')
|
|
12
|
-
const http = require('http')
|
|
13
|
-
|
|
14
|
-
let content = "start watching..."
|
|
15
|
-
let busy = 0
|
|
16
|
-
let queued = false
|
|
17
|
-
let lastevent = Date.now()
|
|
18
|
-
|
|
19
|
-
const done = () => {
|
|
20
|
-
busy = (busy + 1) % 3
|
|
21
|
-
!busy && queued && start(queued = false)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const start = (init=false) => {
|
|
25
|
-
const child = cp.spawn(__dirname + '/nattoppet.js', [file, '--dev'])
|
|
26
|
-
let buffer = ''
|
|
27
|
-
child.stdout.on('data', chunk => buffer += chunk)
|
|
28
|
-
child.on('close', code => {
|
|
29
|
-
if (code == 0) {
|
|
30
|
-
console.log(init ? "rendered" : "updated")
|
|
31
|
-
content = buffer
|
|
32
|
-
} else
|
|
33
|
-
console.error("failed") // todo: print time
|
|
34
|
-
done()
|
|
35
|
-
})
|
|
36
|
-
setTimeout(done, 500)
|
|
37
|
-
busy++
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
fs.watch(file).addListener("change", () => {
|
|
41
|
-
if (Date.now() - lastevent < 50) return // hard throttle, not even queue it
|
|
42
|
-
lastevent = Date.now()
|
|
43
|
-
if (busy) return queued = true // soft throttle, queue at most one task
|
|
44
|
-
start()
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
http.createServer((req, res) => {
|
|
48
|
-
res.writeHead(200, { 'Content-Type': 'text/html' })
|
|
49
|
-
res.end(content)
|
|
50
|
-
}).listen(3939)
|
|
51
|
-
|
|
52
|
-
const browser = process.env.BROWSER || ({ darwin: 'open', win32: 'start', win64: 'start' })[process.platform] || 'xdg-open'
|
|
53
|
-
|
|
54
|
-
browser.includes('chrom')
|
|
55
|
-
? cp.exec(`${browser} --app=http://127.0.0.1:3939`)
|
|
56
|
-
: cp.exec(`${browser} http://127.0.0.1:3939`)
|
|
57
|
-
|
|
58
|
-
start(true)
|
package/nattoppet-native.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
'use strict'
|
|
4
|
-
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const cp = require('child_process')
|
|
7
|
-
const path = require('path')
|
|
8
|
-
|
|
9
|
-
const init = () => {
|
|
10
|
-
fs.mkdirSync('native')
|
|
11
|
-
fs.mkdirSync('native/src')
|
|
12
|
-
fs.mkdirSync('native/target')
|
|
13
|
-
fs.copyFileSync(path.join(__dirname, 'native', 'src', 'main.rs'), 'native/src/main.rs')
|
|
14
|
-
fs.copyFileSync(path.join(__dirname, 'native', 'build.rs'), 'native/build.rs')
|
|
15
|
-
fs.copyFileSync(path.join(__dirname, 'native', 'Cargo.toml'), 'native/Cargo.toml')
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const bundle = () => {
|
|
19
|
-
const child = cp.spawnSync(__dirname + '/nattoppet.js', [process.argv[3]])
|
|
20
|
-
if (child.stderr.length) {
|
|
21
|
-
console.error(child.stderr.toString())
|
|
22
|
-
}
|
|
23
|
-
fs.writeFileSync('native/target/bundle.html', child.stdout)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const build = () => {
|
|
27
|
-
bundle()
|
|
28
|
-
const child = cp.spawn('cargo', ['build', '--release'], { cwd: 'native' })
|
|
29
|
-
child.stdout.pipe(process.stdout)
|
|
30
|
-
child.stderr.pipe(process.stderr)
|
|
31
|
-
child.on('exit', (code) => {
|
|
32
|
-
if (code != 0) {
|
|
33
|
-
console.error("Cargo exit with code: " + code)
|
|
34
|
-
} else {
|
|
35
|
-
console.log("building finished. Check native/target/release/")
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const help = () => {
|
|
41
|
-
console.log("Usage: nattoppet-native [init|bundle|build]")
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
switch (process.argv[2]) {
|
|
45
|
-
case 'init': return init()
|
|
46
|
-
case 'bundle': return bundle()
|
|
47
|
-
case 'build': return build()
|
|
48
|
-
default: return help()
|
|
49
|
-
}
|
package/nattoppet.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
'use strict'
|
|
4
|
-
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const path = require('path')
|
|
7
|
-
const stdlib = require('./stdlib')
|
|
8
|
-
const compiler = require('./compiler')
|
|
9
|
-
const minifier = require('html-minifier')
|
|
10
|
-
|
|
11
|
-
const file = process.argv[2] || 0
|
|
12
|
-
const dir = file ? path.dirname(path.resolve(file)) : process.cwd()
|
|
13
|
-
const str = fs.readFileSync(file, 'utf8')
|
|
14
|
-
const env = { ...stdlib, base_dir: dir }
|
|
15
|
-
const raw = compiler.compile(str, env)
|
|
16
|
-
const out = process.argv.includes('--dev', 1) ? raw : minifier.minify(raw, {
|
|
17
|
-
collapseWhitespace: true,
|
|
18
|
-
removeAttributeQuotes: true,
|
|
19
|
-
removeComments: true,
|
|
20
|
-
removeRedundantAttributes: true,
|
|
21
|
-
removeOptionalTags: true,
|
|
22
|
-
minifyCSS: true,
|
|
23
|
-
minifyJS: true,
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
process.stdout.write(out)
|
package/ppt/before.ymd
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
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
|
-
[require](@std/ppt/ppt.less)
|
|
8
|
-
[require](@std/ppt/ppt.coffee)
|
package/ppt/ppt.coffee
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# events: click, delay, sim
|
|
2
|
-
# time-for-delay: short, long
|
|
3
|
-
# fx: slide, fade, fx-[color]
|
|
4
|
-
# time-for-fx: fast, slow
|
|
5
|
-
|
|
6
|
-
init = ->
|
|
7
|
-
scens = [].slice.call document.querySelectorAll '.scen'
|
|
8
|
-
current = scens[0]
|
|
9
|
-
timeline = 0
|
|
10
|
-
clickListener = ->
|
|
11
|
-
|
|
12
|
-
enter = (x) ->
|
|
13
|
-
x.classList.add 'active'
|
|
14
|
-
fx ++timeline, [].slice.call x.querySelectorAll '.click, .delay, .sim'
|
|
15
|
-
|
|
16
|
-
inview = (x) ->
|
|
17
|
-
{ top, height } = do x.getBoundingClientRect
|
|
18
|
-
top <= innerHeight / 2 <= top + height
|
|
19
|
-
|
|
20
|
-
update = ->
|
|
21
|
-
if not inview current
|
|
22
|
-
for x in scens
|
|
23
|
-
if inview x
|
|
24
|
-
for e in document.querySelectorAll('.active')
|
|
25
|
-
e.classList.remove 'active'
|
|
26
|
-
enter x
|
|
27
|
-
current = x
|
|
28
|
-
break
|
|
29
|
-
|
|
30
|
-
fx = (t, [head, tail...]) ->
|
|
31
|
-
if not head?
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
cb = ->
|
|
35
|
-
if t isnt timeline
|
|
36
|
-
return
|
|
37
|
-
head.classList.add 'active'
|
|
38
|
-
fx t, tail
|
|
39
|
-
|
|
40
|
-
if head.classList.contains 'click'
|
|
41
|
-
clickListener = cb
|
|
42
|
-
else if head.classList.contains 'delay'
|
|
43
|
-
if head.classList.contains 'long'
|
|
44
|
-
setTimeout cb, 800
|
|
45
|
-
else if head.classList.contains 'short'
|
|
46
|
-
setTimeout cb, 200
|
|
47
|
-
else
|
|
48
|
-
setTimeout cb, 400
|
|
49
|
-
else if head.classList.contains 'sim'
|
|
50
|
-
do cb
|
|
51
|
-
|
|
52
|
-
enter current
|
|
53
|
-
addEventListener 'click', -> do clickListener
|
|
54
|
-
addEventListener 'scroll', update
|
|
55
|
-
addEventListener 'resize', update
|
|
56
|
-
setInterval update, 2000
|
|
57
|
-
|
|
58
|
-
if document.readyState == 'loading'
|
|
59
|
-
document.addEventListener 'DOMContentLoaded', init
|
|
60
|
-
else
|
|
61
|
-
do init
|