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/ppt.css
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
html {
|
|
2
|
+
font-family: sans-serif;
|
|
3
|
+
font-size: 20px;
|
|
4
|
+
line-height: 1.5;
|
|
5
|
+
min-height: 100vh;
|
|
6
|
+
color: #233;
|
|
7
|
+
}
|
|
8
|
+
@media (min-width: 1200px) {
|
|
9
|
+
html {
|
|
10
|
+
font-size: 24px;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
body {
|
|
14
|
+
padding: 0;
|
|
15
|
+
margin: 0;
|
|
16
|
+
overflow-x: hidden;
|
|
17
|
+
overflow-y: scroll;
|
|
18
|
+
}
|
|
19
|
+
pre {
|
|
20
|
+
background: white;
|
|
21
|
+
border-top: 1px solid #eee;
|
|
22
|
+
border-bottom: 1px solid #eee;
|
|
23
|
+
padding: 20px;
|
|
24
|
+
font-size: 0.9rem;
|
|
25
|
+
line-height: 1.2;
|
|
26
|
+
text-align: left;
|
|
27
|
+
overflow-x: auto;
|
|
28
|
+
}
|
|
29
|
+
@media (min-width: 1200px) {
|
|
30
|
+
pre {
|
|
31
|
+
padding: 25px;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
code {
|
|
35
|
+
font-family: monospace;
|
|
36
|
+
font-size: 0.9rem;
|
|
37
|
+
}
|
|
38
|
+
h2,
|
|
39
|
+
h3 {
|
|
40
|
+
color: #42b8a6;
|
|
41
|
+
}
|
|
42
|
+
h2 {
|
|
43
|
+
margin-top: 5vh;
|
|
44
|
+
font-size: 2rem;
|
|
45
|
+
}
|
|
46
|
+
h3 {
|
|
47
|
+
margin-top: 6vh;
|
|
48
|
+
font-size: 1.2rem;
|
|
49
|
+
}
|
|
50
|
+
p {
|
|
51
|
+
text-indent: 2rem;
|
|
52
|
+
}
|
|
53
|
+
blockquote p {
|
|
54
|
+
text-indent: 0;
|
|
55
|
+
}
|
|
56
|
+
img {
|
|
57
|
+
max-width: 100%;
|
|
58
|
+
}
|
|
59
|
+
img.full {
|
|
60
|
+
width: 100%;
|
|
61
|
+
}
|
|
62
|
+
img.small {
|
|
63
|
+
width: 40%;
|
|
64
|
+
}
|
|
65
|
+
@media (max-width: 625px) {
|
|
66
|
+
img.small {
|
|
67
|
+
width: 60%;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
img.mid {
|
|
71
|
+
width: 60%;
|
|
72
|
+
}
|
|
73
|
+
img.big {
|
|
74
|
+
width: 80%;
|
|
75
|
+
}
|
|
76
|
+
li {
|
|
77
|
+
font-size: 1.2rem;
|
|
78
|
+
}
|
|
79
|
+
footer {
|
|
80
|
+
font-weight: 300;
|
|
81
|
+
font-size: 0.7rem;
|
|
82
|
+
color: #888;
|
|
83
|
+
}
|
|
84
|
+
.banner > h2 {
|
|
85
|
+
position: absolute;
|
|
86
|
+
left: 10vw;
|
|
87
|
+
top: 45%;
|
|
88
|
+
width: 80vw;
|
|
89
|
+
transform: translateY(-50%);
|
|
90
|
+
text-align: center;
|
|
91
|
+
margin: 0;
|
|
92
|
+
font-family: serif;
|
|
93
|
+
font-size: 3rem;
|
|
94
|
+
font-weight: normal;
|
|
95
|
+
}
|
|
96
|
+
@media (min-width: 1200px) {
|
|
97
|
+
.banner > h2 {
|
|
98
|
+
font-size: 3.2rem;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
a {
|
|
102
|
+
text-decoration: none;
|
|
103
|
+
}
|
|
104
|
+
a:hover {
|
|
105
|
+
text-decoration: underline;
|
|
106
|
+
}
|
|
107
|
+
.scen {
|
|
108
|
+
position: relative;
|
|
109
|
+
margin: 0;
|
|
110
|
+
background-color: #eee;
|
|
111
|
+
transition: background-color 1s ease;
|
|
112
|
+
padding: 10vh 8vw;
|
|
113
|
+
width: 84vw;
|
|
114
|
+
min-height: 60vh;
|
|
115
|
+
}
|
|
116
|
+
.scen.active {
|
|
117
|
+
background-color: white;
|
|
118
|
+
}
|
|
119
|
+
.scen.wide {
|
|
120
|
+
width: 96vw;
|
|
121
|
+
padding: 10vh 2vw;
|
|
122
|
+
}
|
|
123
|
+
.scen::after {
|
|
124
|
+
content: "";
|
|
125
|
+
display: table;
|
|
126
|
+
clear: both;
|
|
127
|
+
}
|
|
128
|
+
@media (min-width: 1200px) {
|
|
129
|
+
.scen {
|
|
130
|
+
width: 76vw;
|
|
131
|
+
padding: 10vh 12vw;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
.col-12 {
|
|
135
|
+
float: left;
|
|
136
|
+
width: 100%;
|
|
137
|
+
}
|
|
138
|
+
.col-11 {
|
|
139
|
+
float: left;
|
|
140
|
+
width: 91.66666667%;
|
|
141
|
+
}
|
|
142
|
+
.col-10 {
|
|
143
|
+
float: left;
|
|
144
|
+
width: 83.33333333%;
|
|
145
|
+
}
|
|
146
|
+
.col-9 {
|
|
147
|
+
float: left;
|
|
148
|
+
width: 75%;
|
|
149
|
+
}
|
|
150
|
+
.col-8 {
|
|
151
|
+
float: left;
|
|
152
|
+
width: 66.66666667%;
|
|
153
|
+
}
|
|
154
|
+
.col-7 {
|
|
155
|
+
float: left;
|
|
156
|
+
width: 58.33333333%;
|
|
157
|
+
}
|
|
158
|
+
.col-6 {
|
|
159
|
+
float: left;
|
|
160
|
+
width: 50%;
|
|
161
|
+
}
|
|
162
|
+
.col-5 {
|
|
163
|
+
float: left;
|
|
164
|
+
width: 41.66666667%;
|
|
165
|
+
}
|
|
166
|
+
.col-4 {
|
|
167
|
+
float: left;
|
|
168
|
+
width: 33.33333333%;
|
|
169
|
+
}
|
|
170
|
+
.col-3 {
|
|
171
|
+
float: left;
|
|
172
|
+
width: 25%;
|
|
173
|
+
}
|
|
174
|
+
.col-2 {
|
|
175
|
+
float: left;
|
|
176
|
+
width: 16.66666667%;
|
|
177
|
+
}
|
|
178
|
+
.col-1 {
|
|
179
|
+
float: left;
|
|
180
|
+
width: 8.33333333%;
|
|
181
|
+
}
|
|
182
|
+
.plum {
|
|
183
|
+
color: #ae81ff;
|
|
184
|
+
}
|
|
185
|
+
.fx-plum {
|
|
186
|
+
transition: color 400ms;
|
|
187
|
+
}
|
|
188
|
+
.fx-plum.fast {
|
|
189
|
+
transition: color 200ms;
|
|
190
|
+
}
|
|
191
|
+
.fx-plum.slow {
|
|
192
|
+
transition: color 600ms;
|
|
193
|
+
}
|
|
194
|
+
.fx-plum.active {
|
|
195
|
+
color: #ae81ff !important;
|
|
196
|
+
}
|
|
197
|
+
.chartreuse {
|
|
198
|
+
color: #a6e22e;
|
|
199
|
+
}
|
|
200
|
+
.fx-chartreuse {
|
|
201
|
+
transition: color 400ms;
|
|
202
|
+
}
|
|
203
|
+
.fx-chartreuse.fast {
|
|
204
|
+
transition: color 200ms;
|
|
205
|
+
}
|
|
206
|
+
.fx-chartreuse.slow {
|
|
207
|
+
transition: color 600ms;
|
|
208
|
+
}
|
|
209
|
+
.fx-chartreuse.active {
|
|
210
|
+
color: #a6e22e !important;
|
|
211
|
+
}
|
|
212
|
+
.cyan {
|
|
213
|
+
color: #66d9ef;
|
|
214
|
+
}
|
|
215
|
+
.fx-cyan {
|
|
216
|
+
transition: color 400ms;
|
|
217
|
+
}
|
|
218
|
+
.fx-cyan.fast {
|
|
219
|
+
transition: color 200ms;
|
|
220
|
+
}
|
|
221
|
+
.fx-cyan.slow {
|
|
222
|
+
transition: color 600ms;
|
|
223
|
+
}
|
|
224
|
+
.fx-cyan.active {
|
|
225
|
+
color: #66d9ef !important;
|
|
226
|
+
}
|
|
227
|
+
.tomato {
|
|
228
|
+
color: #f13c1a;
|
|
229
|
+
}
|
|
230
|
+
.fx-tomato {
|
|
231
|
+
transition: color 400ms;
|
|
232
|
+
}
|
|
233
|
+
.fx-tomato.fast {
|
|
234
|
+
transition: color 200ms;
|
|
235
|
+
}
|
|
236
|
+
.fx-tomato.slow {
|
|
237
|
+
transition: color 600ms;
|
|
238
|
+
}
|
|
239
|
+
.fx-tomato.active {
|
|
240
|
+
color: #f13c1a !important;
|
|
241
|
+
}
|
|
242
|
+
.moccasin {
|
|
243
|
+
color: #ffe4b5;
|
|
244
|
+
}
|
|
245
|
+
.fx-moccasin {
|
|
246
|
+
transition: color 400ms;
|
|
247
|
+
}
|
|
248
|
+
.fx-moccasin.fast {
|
|
249
|
+
transition: color 200ms;
|
|
250
|
+
}
|
|
251
|
+
.fx-moccasin.slow {
|
|
252
|
+
transition: color 600ms;
|
|
253
|
+
}
|
|
254
|
+
.fx-moccasin.active {
|
|
255
|
+
color: #ffe4b5 !important;
|
|
256
|
+
}
|
|
257
|
+
.slide {
|
|
258
|
+
transition: transform 400ms;
|
|
259
|
+
transform: translateX(-100vw);
|
|
260
|
+
}
|
|
261
|
+
.slide.fast {
|
|
262
|
+
transition: transform 200ms;
|
|
263
|
+
}
|
|
264
|
+
.slide.slow {
|
|
265
|
+
transition: transform 600ms;
|
|
266
|
+
}
|
|
267
|
+
.slide.active {
|
|
268
|
+
transform: translateX(0);
|
|
269
|
+
}
|
|
270
|
+
.fade {
|
|
271
|
+
transition: opacity 400ms;
|
|
272
|
+
opacity: 0;
|
|
273
|
+
}
|
|
274
|
+
.fade.fast {
|
|
275
|
+
transition: opacity 200ms;
|
|
276
|
+
}
|
|
277
|
+
.fade.slow {
|
|
278
|
+
transition: opacity 600ms;
|
|
279
|
+
}
|
|
280
|
+
.fade.active {
|
|
281
|
+
opacity: 1;
|
|
282
|
+
}
|
|
283
|
+
.rise {
|
|
284
|
+
transition: opacity 400ms;
|
|
285
|
+
transition: transform 400ms;
|
|
286
|
+
opacity: 0;
|
|
287
|
+
transform: translateY(10vh);
|
|
288
|
+
}
|
|
289
|
+
.rise.fast {
|
|
290
|
+
transition: opacity 200ms;
|
|
291
|
+
}
|
|
292
|
+
.rise.slow {
|
|
293
|
+
transition: opacity 600ms;
|
|
294
|
+
}
|
|
295
|
+
.rise.fast {
|
|
296
|
+
transition: transform 200ms;
|
|
297
|
+
}
|
|
298
|
+
.rise.slow {
|
|
299
|
+
transition: transform 600ms;
|
|
300
|
+
}
|
|
301
|
+
.rise.active {
|
|
302
|
+
opacity: 1;
|
|
303
|
+
transform: translateY(0);
|
|
304
|
+
}
|
package/ppt.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// events: click, delay, sim
|
|
2
|
+
// time-for-delay: short, long
|
|
3
|
+
// fx: slide, fade, fx-[color]
|
|
4
|
+
// time-for-fx: fast, slow
|
|
5
|
+
var init;
|
|
6
|
+
|
|
7
|
+
init = function() {
|
|
8
|
+
var clickListener, current, enter, fx, inview, scens, timeline, update;
|
|
9
|
+
scens = [].slice.call(document.querySelectorAll('.scen'));
|
|
10
|
+
current = scens[0];
|
|
11
|
+
timeline = 0;
|
|
12
|
+
clickListener = function() {};
|
|
13
|
+
enter = function(x) {
|
|
14
|
+
x.classList.add('active');
|
|
15
|
+
return fx(++timeline, [].slice.call(x.querySelectorAll('.click, .delay, .sim')));
|
|
16
|
+
};
|
|
17
|
+
inview = function(x) {
|
|
18
|
+
var height, ref, top;
|
|
19
|
+
({top, height} = x.getBoundingClientRect());
|
|
20
|
+
return (top <= (ref = innerHeight / 2) && ref <= top + height);
|
|
21
|
+
};
|
|
22
|
+
update = function() {
|
|
23
|
+
var e, i, j, len, len1, ref, results, x;
|
|
24
|
+
if (!inview(current)) {
|
|
25
|
+
results = [];
|
|
26
|
+
for (i = 0, len = scens.length; i < len; i++) {
|
|
27
|
+
x = scens[i];
|
|
28
|
+
if (inview(x)) {
|
|
29
|
+
ref = document.querySelectorAll('.active');
|
|
30
|
+
for (j = 0, len1 = ref.length; j < len1; j++) {
|
|
31
|
+
e = ref[j];
|
|
32
|
+
e.classList.remove('active');
|
|
33
|
+
}
|
|
34
|
+
enter(x);
|
|
35
|
+
current = x;
|
|
36
|
+
break;
|
|
37
|
+
} else {
|
|
38
|
+
results.push(void 0);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return results;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
fx = function(t, [head, ...tail]) {
|
|
45
|
+
var cb;
|
|
46
|
+
if (head == null) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
cb = function() {
|
|
50
|
+
if (t !== timeline) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
head.classList.add('active');
|
|
54
|
+
return fx(t, tail);
|
|
55
|
+
};
|
|
56
|
+
if (head.classList.contains('click')) {
|
|
57
|
+
return clickListener = cb;
|
|
58
|
+
} else if (head.classList.contains('delay')) {
|
|
59
|
+
if (head.classList.contains('long')) {
|
|
60
|
+
return setTimeout(cb, 800);
|
|
61
|
+
} else if (head.classList.contains('short')) {
|
|
62
|
+
return setTimeout(cb, 200);
|
|
63
|
+
} else {
|
|
64
|
+
return setTimeout(cb, 400);
|
|
65
|
+
}
|
|
66
|
+
} else if (head.classList.contains('sim')) {
|
|
67
|
+
return cb();
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
enter(current);
|
|
71
|
+
addEventListener('click', function() {
|
|
72
|
+
return clickListener();
|
|
73
|
+
});
|
|
74
|
+
addEventListener('scroll', update);
|
|
75
|
+
addEventListener('resize', update);
|
|
76
|
+
return setInterval(update, 2000);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
if (document.readyState === 'loading') {
|
|
80
|
+
document.addEventListener('DOMContentLoaded', init);
|
|
81
|
+
} else {
|
|
82
|
+
init();
|
|
83
|
+
}
|
|
@@ -1,3 +1,19 @@
|
|
|
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] ppt.css
|
|
9
|
+
</style>
|
|
10
|
+
|
|
11
|
+
<script>
|
|
12
|
+
[mixin] ppt.js
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
[#slot]
|
|
16
|
+
|
|
1
17
|
[eval] this.inited ? "</section>" : ''
|
|
2
18
|
|
|
3
19
|
[section]=
|
|
@@ -18,4 +34,4 @@ const content = capture_until('\n')
|
|
|
18
34
|
const {args:[length]} = std_call()
|
|
19
35
|
;`<div style="height: ${length}; min-width: 1px"></div>`
|
|
20
36
|
|
|
21
|
-
[mixin]
|
|
37
|
+
[mixin] common.ymd
|
package/readme.md
CHANGED
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
nattoppet
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
-
A tiny markup language and
|
|
4
|
+
A tiny markup language and themes for making documents, slides, or web apps as single-file bundled html or executables.
|
|
5
5
|
|
|
6
|
-
### Usage
|
|
6
|
+
### Usage
|
|
7
7
|
|
|
8
|
+
Compile a nattoppet file:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
bun run nattoppet.ts in.ymd > out.html
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Compile a nattoppet file but don't minimize (for debugging):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bun run nattoppet.ts in.ymd --dev > out.html
|
|
8
18
|
```
|
|
9
|
-
|
|
19
|
+
|
|
20
|
+
Open a browser to preview a nattoppet file; rebuild every time the page is refreshed:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
bun run nattoppet-dev.ts in.ymd
|
|
10
24
|
```
|
|
25
|
+
|
|
26
|
+
Initialize a new project:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bun run nattoppet-init.ts form
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Build a double-clickable executable for the page:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bun run nattoppet-native.ts init
|
|
36
|
+
# (edit the metadata as needed)
|
|
37
|
+
bun run nattoppet-native.ts build in.ymd
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### History
|
|
42
|
+
|
|
43
|
+
- 1.0: This project started as an experiment of co.js to replicate gulp.js, when async/await was not a thing and wind.js was the cool guy that everyone was talking about.
|
|
44
|
+
- 2.0: Later I decided to build ymd.js, a custom LaTeX-style macro-based markup language for blogging, and turned nattoppet a bundler. Promise landed on JavaScript, and async/await became available with babel.
|
|
45
|
+
- 3.0: I became a minimalist and stripped down all dependencies, merged ymd.js and nattoppet, and flattened the directory. I have also migrated to Deno to further remove the nodejs clutters.
|
|
46
|
+
- 4.0: AI came. As an experimental project, nattoppet was put to test AI. Kimi 2.5 successfully ported it from Deno to Bun in half an hour, with all posts on my blog builds without error. It made me feel empty, but I have to embrace it. This project will be fully vibed from now on.
|
package/stdlib.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import * as path from "node:path"
|
|
2
|
+
import * as fs from "node:fs"
|
|
3
|
+
import * as zlib from "node:zlib"
|
|
4
|
+
|
|
5
|
+
import { marked } from "marked"
|
|
6
|
+
import coffee from "coffeescript"
|
|
7
|
+
import katex from "katex"
|
|
8
|
+
import less from "less"
|
|
9
|
+
|
|
10
|
+
function compress_sync(data: ArrayBuffer) {
|
|
11
|
+
// Keep using zlib.deflateRawSync for browser compatibility
|
|
12
|
+
// Browser uses DecompressionStream("deflate-raw") which expects raw deflate
|
|
13
|
+
return zlib.deflateRawSync(new Uint8Array(data), {
|
|
14
|
+
flush: zlib.constants.Z_FINISH,
|
|
15
|
+
level: zlib.constants.Z_BEST_COMPRESSION
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default {
|
|
20
|
+
skip(n: number) {
|
|
21
|
+
this.remaining = this.remaining.substring(n)
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
capture_until(delimiter: string) {
|
|
25
|
+
const p = this.remaining.indexOf(delimiter)
|
|
26
|
+
if (p < 0) {
|
|
27
|
+
const result = this.remaining
|
|
28
|
+
this.remaining = ""
|
|
29
|
+
return result
|
|
30
|
+
}
|
|
31
|
+
const result = this.remaining.substring(0, p)
|
|
32
|
+
this.remaining = this.remaining.substring(p + delimiter.length)
|
|
33
|
+
return result
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
std_call(hascontent = false) {
|
|
37
|
+
const opts: string[] = [], args: string[] = []
|
|
38
|
+
const parse_option = () => {
|
|
39
|
+
const m = this.remaining.match(/^\.([\w\-]+)/)
|
|
40
|
+
this.skip(m[0].length)
|
|
41
|
+
opts.push(m[1])
|
|
42
|
+
}
|
|
43
|
+
const parse_argument = () => {
|
|
44
|
+
const m = this.remaining.match(/^\((.*?)\)|{(.*?)}/)
|
|
45
|
+
this.skip(m[0].length)
|
|
46
|
+
args.push(m[1] || m[2])
|
|
47
|
+
}
|
|
48
|
+
const parse_block = () => {
|
|
49
|
+
const m = this.remaining.match(/^(>+)\n?/)
|
|
50
|
+
this.skip(m[0].length)
|
|
51
|
+
return this.capture_until('<'.repeat(m[1].length))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
while (true) {
|
|
55
|
+
switch (this.remaining[0]) {
|
|
56
|
+
case '.':
|
|
57
|
+
parse_option()
|
|
58
|
+
break
|
|
59
|
+
case '(':
|
|
60
|
+
case '{':
|
|
61
|
+
parse_argument()
|
|
62
|
+
break
|
|
63
|
+
case '>':
|
|
64
|
+
return { opts, args, block: parse_block() }
|
|
65
|
+
case ' ':
|
|
66
|
+
if (hascontent)
|
|
67
|
+
return { opts, args, block: this.capture_until('\n').slice(1) }
|
|
68
|
+
default:
|
|
69
|
+
return { opts, args }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
rpath(file: string) {
|
|
75
|
+
if (!path.isAbsolute(file))
|
|
76
|
+
return path.join(this.base_dir, file)
|
|
77
|
+
return file
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
read(file: string, encoding = "utf-8") {
|
|
81
|
+
const filePath = this.rpath(file)
|
|
82
|
+
switch (encoding) {
|
|
83
|
+
case "utf8":
|
|
84
|
+
case "utf-8":
|
|
85
|
+
return fs.readFileSync(filePath, 'utf-8')
|
|
86
|
+
case "base64":
|
|
87
|
+
return Buffer.from(fs.readFileSync(filePath)).toString('base64')
|
|
88
|
+
case "compressed-base64":
|
|
89
|
+
return Buffer.from(compress_sync(fs.readFileSync(filePath))).toString('base64')
|
|
90
|
+
default:
|
|
91
|
+
throw "unknown encoding: " + encoding
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
extname(file: string) {
|
|
96
|
+
return path.extname(file).slice(1)
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
basename(file: string) {
|
|
100
|
+
return path.basename(file)
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
render_coffee(str: string, options: any) {
|
|
104
|
+
return coffee.compile(str, options)
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
render_less(str: string) {
|
|
108
|
+
let x: any; less.render(str, {}, (err: any, out: any) => !err && (x = out))
|
|
109
|
+
if (!x) throw "less failed to compile synchronously"
|
|
110
|
+
return x.css
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
render_markdown(str: string) {
|
|
114
|
+
return marked.parse(str)
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
render_katex(str: string, displayMode = false) {
|
|
118
|
+
return katex.renderToString(str, { displayMode, output: 'html' })
|
|
119
|
+
}
|
|
120
|
+
} as any
|
package/tml.css
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
html {
|
|
2
|
+
font-family: sans-serif;
|
|
3
|
+
font-size: 18px;
|
|
4
|
+
line-height: 1.5;
|
|
5
|
+
text-align: justify;
|
|
6
|
+
color: #33333d;
|
|
7
|
+
-webkit-user-select: none;
|
|
8
|
+
hyphens: auto;
|
|
9
|
+
}
|
|
10
|
+
@media (max-width: 625px) {
|
|
11
|
+
html {
|
|
12
|
+
font-size: 14px;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
body {
|
|
16
|
+
margin: 15px 0;
|
|
17
|
+
}
|
|
18
|
+
@media (min-width: 1200px) {
|
|
19
|
+
body {
|
|
20
|
+
height: calc(100vh - 45px);
|
|
21
|
+
column-width: 540px;
|
|
22
|
+
column-gap: 0;
|
|
23
|
+
column-fill: auto;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
article {
|
|
27
|
+
margin: 40px 0 0 15px;
|
|
28
|
+
padding: 0 20px;
|
|
29
|
+
}
|
|
30
|
+
@media (max-width: 625px) {
|
|
31
|
+
article {
|
|
32
|
+
margin-left: 8px;
|
|
33
|
+
padding-left: 10px;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
article:first-child {
|
|
37
|
+
margin-top: 0;
|
|
38
|
+
}
|
|
39
|
+
article:nth-child(3n) {
|
|
40
|
+
border-left: solid #ECE335;
|
|
41
|
+
}
|
|
42
|
+
article:nth-child(3n+1) {
|
|
43
|
+
border-left: solid #1CBF5F;
|
|
44
|
+
}
|
|
45
|
+
article:nth-child(3n+2) {
|
|
46
|
+
border-left: solid #2C8DD5;
|
|
47
|
+
}
|
|
48
|
+
h2 {
|
|
49
|
+
position: relative;
|
|
50
|
+
margin: 0;
|
|
51
|
+
padding: 0.8rem 0 0.7rem;
|
|
52
|
+
break-inside: avoid;
|
|
53
|
+
border-bottom: 0.5px solid #ddd;
|
|
54
|
+
}
|
|
55
|
+
h2:before {
|
|
56
|
+
top: 0.9rem;
|
|
57
|
+
font-size: 1.4rem;
|
|
58
|
+
}
|
|
59
|
+
@media (max-width: 625px) {
|
|
60
|
+
h2:before {
|
|
61
|
+
left: -0.8rem;
|
|
62
|
+
top: 1rem;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
h2:hover:before {
|
|
66
|
+
opacity: 1;
|
|
67
|
+
}
|
|
68
|
+
h2 a {
|
|
69
|
+
color: #2c3e50;
|
|
70
|
+
}
|
|
71
|
+
h3 {
|
|
72
|
+
position: relative;
|
|
73
|
+
margin: 0;
|
|
74
|
+
padding: 0.8rem 0 0;
|
|
75
|
+
break-inside: avoid;
|
|
76
|
+
}
|
|
77
|
+
p {
|
|
78
|
+
margin: 1.2rem 0;
|
|
79
|
+
}
|
|
80
|
+
pre {
|
|
81
|
+
background-color: #fafaf9;
|
|
82
|
+
}
|
|
83
|
+
code {
|
|
84
|
+
font-family: monospace;
|
|
85
|
+
font-size: 0.8rem;
|
|
86
|
+
padding: 0.1rem;
|
|
87
|
+
}
|
|
88
|
+
a {
|
|
89
|
+
color: #42b983;
|
|
90
|
+
text-decoration: none;
|
|
91
|
+
}
|
|
92
|
+
a:hover {
|
|
93
|
+
text-decoration: underline;
|
|
94
|
+
}
|
|
95
|
+
blockquote {
|
|
96
|
+
margin: 2rem 0;
|
|
97
|
+
padding: 0 1.2rem;
|
|
98
|
+
font-style: italic;
|
|
99
|
+
}
|
|
100
|
+
blockquote p {
|
|
101
|
+
margin-left: 0;
|
|
102
|
+
}
|
|
103
|
+
img {
|
|
104
|
+
break-inside: avoid;
|
|
105
|
+
}
|
|
106
|
+
.full {
|
|
107
|
+
display: block;
|
|
108
|
+
margin: 1rem 0;
|
|
109
|
+
width: 100%;
|
|
110
|
+
}
|
|
111
|
+
.half {
|
|
112
|
+
display: block;
|
|
113
|
+
margin: 1rem 0;
|
|
114
|
+
width: 50%;
|
|
115
|
+
}
|
|
116
|
+
.end-symbol {
|
|
117
|
+
text-align: center;
|
|
118
|
+
display: none;
|
|
119
|
+
margin-top: 1rem;
|
|
120
|
+
}
|
|
121
|
+
@media (min-width: 1200px) {
|
|
122
|
+
.end-symbol {
|
|
123
|
+
display: block;
|
|
124
|
+
}
|
|
125
|
+
}
|
package/tml.js
ADDED