authorgravatar for me@paperdave.netdave caruso <me@paperdave.net> 2024-09-21 14:03:37-07:00
committergravatar for me@paperdave.netdave caruso <me@paperdave.net> 2024-09-21 14:03:37-07:00
logf0f7c6e0da14e600e621576558c77cc999160801
treef4ac3312eeb2fc8267807b37c89d52ad82c62cba
parentdaf7e3a223445a0020d0ffa52a54f26bf4374126
signature Commit is signed but in an unrecognized format.

chore: separate manual's html and css


8 files changed, 595 insertions(+), 592 deletions(-)

README.md+2-3
...@@ -1,8 +1,7 @@...@@ -1,8 +1,7 @@
1# Ix1# Ix
22
3Ix (***I***nferable E***x***pression) is a high-level, general purpose3Ix (`I`nferable E`x`pression) is a high-level, general purpose programming
4programming language. It features a mix of Rust, Zig, and JavaScript's great4language. It features a mix of Rust, Zig, and JavaScript's great points.
5points.
65
7For a guide on how to use Ix, see the manual included in the binary6For a guide on how to use Ix, see the manual included in the binary
8distribution. Additionally, the latest commit of the manual is hosted online at7distribution. Additionally, the latest commit of the manual is hosted online at
build.zig+1
...@@ -465,6 +465,7 @@ pub fn build(b: *Build) !void {...@@ -465,6 +465,7 @@ pub fn build(b: *Build) !void {
465 }465 }
466 manual_run.addFileArg(b.path("doc/language-manual.md"));466 manual_run.addFileArg(b.path("doc/language-manual.md"));
467 manual_run.addFileArg(b.path("src/manual/template.html"));467 manual_run.addFileArg(b.path("src/manual/template.html"));
468 manual_run.addFileArg(b.path("src/manual/style.css"));
468 const manual_out = manual_run.addOutputFileArg("language-reference.html");469 const manual_out = manual_run.addOutputFileArg("language-reference.html");
469 const install_manual = b.addInstallFile(manual_out, "doc/README.html");470 const install_manual = b.addInstallFile(manual_out, "doc/README.html");
470471
doc/language-manual.md+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# Ix Programming Language1# Ix Programming Language
22
3Ix (***I***nferable E***x***pression) is a high-level programming language for3Ix (**I**nferable E**x**pression) is a high-level programming language for
4developing web applications and games.4developing web applications and games.
55
6Key goals of this project are:6Key goals of this project are:
dprint.jsonc+1
...@@ -2,6 +2,7 @@...@@ -2,6 +2,7 @@
2 "plugins": [2 "plugins": [
3 // sort-lines: start3 // sort-lines: start
4 "https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0",4 "https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0",
5 "https://plugins.dprint.dev/g-plane/malva-v0.10.1.wasm",
5 "https://plugins.dprint.dev/g-plane/markup_fmt-v0.12.0.wasm",6 "https://plugins.dprint.dev/g-plane/markup_fmt-v0.12.0.wasm",
6 "https://plugins.dprint.dev/json-0.19.3.wasm",7 "https://plugins.dprint.dev/json-0.19.3.wasm",
7 "https://plugins.dprint.dev/markdown-0.17.2.wasm",8 "https://plugins.dprint.dev/markdown-0.17.2.wasm",
src/manual/NaiveHtmlMinifier.zig+10-1
...@@ -46,7 +46,16 @@ fn processHtml(m: *NaiveHtmlMinifier) !void {...@@ -46,7 +46,16 @@ fn processHtml(m: *NaiveHtmlMinifier) !void {
46 ' ', '\t', '\n', '\r' => unreachable, // did not skip whitespace46 ' ', '\t', '\n', '\r' => unreachable, // did not skip whitespace
4747
48 '<' => switch (m.input[1]) {48 '<' => switch (m.input[1]) {
49 '!' => try m.moveTokenWith(">"),49 '!' => {
50 if (m.input[2] == '-' and m.input[3] == '-') {
51 // <!-- comment -->
52 m.input = m.input[(mem.indexOfPos(u8, m.input, 4, "-->") orelse @panic("no comment end")) + 3 ..];
53 return;
54 } else {
55 // <!DOCTYPE ...>
56 try m.moveTokenWith(">");
57 }
58 },
50 '/' => try m.moveTokenWith(">"),59 '/' => try m.moveTokenWith(">"),
51 else => {60 else => {
52 const first_tok = getToken(m, ws);61 const first_tok = getToken(m, ws);
src/manual/generate_manual.zig+27-14
...@@ -16,10 +16,8 @@ comptime {...@@ -16,10 +16,8 @@ comptime {
16 assert(@import("builtin").mode == .Debug);16 assert(@import("builtin").mode == .Debug);
17}17}
1818
19const cli_name = "wlang";19const minify_html = true;
20const build_cli = cli_name ++ " build";20const minify_css = false;
21const test_cli = cli_name ++ " test";
22const run_cli = cli_name ++ " run";
2321
24pub fn main() !void {22pub fn main() !void {
25 comptime std.debug.assert(@import("builtin").mode == .Debug);23 comptime std.debug.assert(@import("builtin").mode == .Debug);
...@@ -37,6 +35,7 @@ pub fn main() !void {...@@ -37,6 +35,7 @@ pub fn main() !void {
37 const runtime_path = args.next().?;35 const runtime_path = args.next().?;
38 const markdown_src = try std.fs.cwd().readFileAlloc(gpa, args.next().?, std.math.maxInt(usize));36 const markdown_src = try std.fs.cwd().readFileAlloc(gpa, args.next().?, std.math.maxInt(usize));
39 const template_src = try std.fs.cwd().readFileAlloc(gpa, args.next().?, std.math.maxInt(usize));37 const template_src = try std.fs.cwd().readFileAlloc(gpa, args.next().?, std.math.maxInt(usize));
38 const style_src_raw = try std.fs.cwd().readFileAlloc(gpa, args.next().?, std.math.maxInt(usize));
40 const out_path = args.next().?;39 const out_path = args.next().?;
4140
42 assert(args.next() == null);41 assert(args.next() == null);
...@@ -44,8 +43,6 @@ pub fn main() !void {...@@ -44,8 +43,6 @@ pub fn main() !void {
44 var contents = ArrayList(u8).init(gpa);43 var contents = ArrayList(u8).init(gpa);
45 var header: HeaderWriter = .{};44 var header: HeaderWriter = .{};
4645
47 const minify = false;
48
49 try processMarkdown(46 try processMarkdown(
50 gpa,47 gpa,
51 progress,48 progress,
...@@ -58,16 +55,23 @@ pub fn main() !void {...@@ -58,16 +55,23 @@ pub fn main() !void {
5855
59 try header.end(gpa);56 try header.end(gpa);
6057
61 const minified_template = if (minify)58 const minified_template = if (minify_html)
62 try NaiveHtmlMinifier.minify(template_src, gpa)59 try NaiveHtmlMinifier.minify(template_src, gpa)
63 else60 else
64 template_src;61 template_src;
6562
63 const style_src = try std.fmt.allocPrint(gpa, "<style>{s}</style>", .{style_src_raw});
64 const minified_style = if (minify_css)
65 try NaiveHtmlMinifier.minify(style_src, gpa)
66 else
67 style_src;
68
66 const applied_template = try replaceInTemplate(gpa, minified_template, .{69 const applied_template = try replaceInTemplate(gpa, minified_template, .{
67 .contents = contents.items,70 .contents = contents.items,
68 .navigation = header.data.items,71 .navigation = header.data.items,
69 .nav_h1 = "Ix Language",72 .nav_h1 = "Ix Language",
70 .repository = "https://github.com/paperdave/wl",73 .repository = "https://github.com/paperdave/wl",
74 .style = minified_style,
71 });75 });
7276
73 const out_file = try std.fs.createFileAbsolute(out_path, .{});77 const out_file = try std.fs.createFileAbsolute(out_path, .{});
...@@ -103,6 +107,7 @@ const InlineType = enum {...@@ -103,6 +107,7 @@ const InlineType = enum {
103 bold,107 bold,
104 code,108 code,
105 link,109 link,
110 comment,
106};111};
107112
108const MarkdownTokenizer = struct {113const MarkdownTokenizer = struct {
...@@ -396,7 +401,7 @@ fn processMarkdown(...@@ -396,7 +401,7 @@ fn processMarkdown(
396 }401 }
397402
398 var example: CodeExample = .{403 var example: CodeExample = .{
399 .filename = "example.wl",404 .filename = "example.ix",
400 .source = .{ .raw = code.items },405 .source = .{ .raw = code.items },
401 };406 };
402407
...@@ -444,8 +449,8 @@ fn processMarkdown(...@@ -444,8 +449,8 @@ fn processMarkdown(
444 example.terminal = try mem.concat(gpa, u8, &.{449 example.terminal = try mem.concat(gpa, u8, &.{
445 "$ ",450 "$ ",
446 switch (tag) {451 switch (tag) {
447 .code_run => run_cli,452 .code_run => "ix run",
448 .code_build => build_cli,453 .code_build => "ix build",
449 else => unreachable,454 else => unreachable,
450 },455 },
451 " ",456 " ",
...@@ -592,9 +597,9 @@ fn processMarkdown(...@@ -592,9 +597,9 @@ fn processMarkdown(
592 try para.appendSlice(t.advanceLine());597 try para.appendSlice(t.advanceLine());
593598
594 var next_line = t.advanceLine();599 var next_line = t.advanceLine();
595 while (t.str.len > 0 and next_line.len > 0) {600 while (t.str.len > 0 and next_line.len > 0 and next_line[0] == '>') {
596 try para.append(' ');601 try para.append(' ');
597 try para.appendSlice(next_line);602 try para.appendSlice(next_line[1..]);
598 next_line = t.advanceLine();603 next_line = t.advanceLine();
599 }604 }
600605
...@@ -609,7 +614,7 @@ fn processMarkdown(...@@ -609,7 +614,7 @@ fn processMarkdown(
609pub fn nextInlineToken(src: []const u8) ?struct { InlineType, usize } {614pub fn nextInlineToken(src: []const u8) ?struct { InlineType, usize } {
610 var pos: usize = 0;615 var pos: usize = 0;
611 while (true) : (pos += 1) {616 while (true) : (pos += 1) {
612 pos = mem.indexOfAnyPos(u8, src, pos, "*`[") orelse return null;617 pos = mem.indexOfAnyPos(u8, src, pos, "*`[<") orelse return null;
613618
614 switch (src[pos]) {619 switch (src[pos]) {
615 '*' => switch (src[pos + 1]) {620 '*' => switch (src[pos + 1]) {
...@@ -618,6 +623,10 @@ pub fn nextInlineToken(src: []const u8) ?struct { InlineType, usize } {...@@ -618,6 +623,10 @@ pub fn nextInlineToken(src: []const u8) ?struct { InlineType, usize } {
618 },623 },
619 '`' => return .{ .code, pos },624 '`' => return .{ .code, pos },
620 '[' => return .{ .link, pos },625 '[' => return .{ .link, pos },
626 '<' => if (src[pos + 1] == '!' and src[pos + 2] == '-' and src[pos + 3] == '-')
627 return .{ .comment, pos }
628 else
629 continue,
621 else => unreachable,630 else => unreachable,
622 }631 }
623 }632 }
...@@ -666,6 +675,10 @@ fn processInlineMarkdown(gpa: Allocator, src: []const u8, writer: anytype) !void...@@ -666,6 +675,10 @@ fn processInlineMarkdown(gpa: Allocator, src: []const u8, writer: anytype) !void
666 try writer.writeAll("</a>");675 try writer.writeAll("</a>");
667 remain = remain[href_end + 1 ..];676 remain = remain[href_end + 1 ..];
668 },677 },
678 .comment => {
679 const end = mem.indexOfPos(u8, remain, 4, "-->") orelse @panic("missing comment end");
680 remain = remain[1 .. end + "-->".len];
681 },
669 }682 }
670 }683 }
671 try writer.writeAll(remain);684 try writer.writeAll(remain);
...@@ -676,7 +689,7 @@ fn processInlineMarkdown(gpa: Allocator, src: []const u8, writer: anytype) !void...@@ -676,7 +689,7 @@ fn processInlineMarkdown(gpa: Allocator, src: []const u8, writer: anytype) !void
676}689}
677690
678// TODO: Change this to use Tree-sitter, which would also make it very simple691// TODO: Change this to use Tree-sitter, which would also make it very simple
679// to highlight JavaScript code in addition to the language.692// to highlight JavaScript code in addition to Ix source code
680fn writeTokenizedCode(gpa: Allocator, code: []const u8, writer: anytype) !void {693fn writeTokenizedCode(gpa: Allocator, code: []const u8, writer: anytype) !void {
681 const code_z = try gpa.dupeZ(u8, code);694 const code_z = try gpa.dupeZ(u8, code);
682 defer gpa.free(code_z);695 defer gpa.free(code_z);
src/manual/style.css created+551
...@@ -0,0 +1,551 @@
1:root {
2 /* Catppuccin Latte (light) & Mocha (dark) */
3 --mantle: light-dark(#e6e9ef, #181825);
4 --crust: light-dark(#dce0e8, #11111b);
5 --base: light-dark(#eff1f5, #1e1e2e);
6 --surface-0: light-dark(#ccd0da, #313244);
7 --surface-1: light-dark(#bcc0cc, #45475a);
8 --surface-2: light-dark(#acb0be, #585b70);
9 --overlay-0: light-dark(#9ca0b0, #6c7086);
10 --overlay-1: light-dark(#8c8fa1, #7f849c);
11 --overlay-2: light-dark(#7c7f93, #9399b2);
12 --subtext-0: light-dark(#6c6f85, #a6adc8);
13 --subtext-1: light-dark(#5c5f77, #bac2de);
14 --text: light-dark(#4c4f69, #cdd6f4);
15 --accent: light-dark(#179299, #94e2d5);
16 --link: light-dark(#179299, #94e2d5);
17
18 --font-text:
19 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
20 Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
21 --font-code:
22 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
23 "Courier New", monospace;
24}
25
26* {
27 margin: 0;
28 padding: 0;
29 box-sizing: border-box;
30}
31
32body {
33 background-color: var(--base);
34 color: var(--text);
35 font-family: var(--font-text);
36 color-scheme: light dark;
37 display: flex;
38}
39
40main {
41 width: 100%;
42 max-width: 80ch;
43 padding: 1rem;
44 padding-top: 2rem;
45 margin: auto;
46 line-height: 1.5;
47}
48
49h1, h2, h3, h4, h5, h6, p, ul, pre, blockquote, table {
50 margin-bottom: 1rem;
51}
52
53h2, h3, h4, h5, h6 {
54 padding-top: 0.8rem;
55 margin-top: -0.8rem;
56}
57
58ul {
59 padding-left: 2rem;
60}
61
62li {
63 margin-bottom: 0.25rem;
64}
65
66blockquote {
67 background-color: var(--surface-0);
68 border-left: 4px solid var(--overlay-2);
69 padding-left: 16px;
70 padding-top: 8px;
71 padding-bottom: 8px;
72}
73
74a {
75 color: inherit;
76}
77
78table, th, td {
79 border: 1px solid #9ca0b0;
80 border-collapse: collapse;
81}
82
83th, td {
84 padding: 0.5rem;
85}
86
87.ansi-1 {
88 font-weight: bold;
89}
90
91.ansi-31 {
92 color: light-dark(#d20f39, #f38ba8);
93}
94
95.ansi-32 {
96 color: light-dark(#40a02b, #a6e3a1);
97}
98
99.ansi-33 {
100 color: light-dark(#de8d1c, #f9e2af);
101}
102
103.ansi-34 {
104 color: light-dark(#1e66f5, #89b4fa);
105}
106
107.ansi-35 {
108 color: light-dark(#ea76cb, #f5c2e7);
109}
110
111.ansi-36 {
112 color: light-dark(#179299, #94e2d5);
113}
114
115.ansi-2 {
116 color: light-dark(#bcc0cc, #8087a2);
117}
118
119.kw {
120 color: light-dark(#8839ef, #cba6f7);
121 font-weight: bold;
122}
123
124.tok-string {
125 color: light-dark(#40a02b, #a6e3a1);
126}
127
128.tok-builtin_id {
129 color: light-dark(#d20f39, #f38ba8);
130 font-weight: bold;
131}
132
133.tok-number_int, .tok-number_float {
134 color: light-dark(#fe640b, #fab387);
135}
136
137.tok-semi,
138.tok-end_paren,
139.tok-start_paren,
140.tok-equal,
141.tok-colon,
142.tok-start_brace,
143.tok-end_brace,
144.tok-dot {
145 color: light-dark(#7c7f93, #9399b2);
146}
147
148aside {
149 position: sticky;
150 top: 0;
151 left: 0;
152 height: 100dvh;
153 height: 100vh;
154}
155
156#sidebar-content {
157 display: flex;
158 flex-direction: column;
159 background-color: var(--mantle);
160 height: 100%;
161 padding: 1rem;
162 border-radius: 0 1rem 1rem 0;
163 overflow-y: auto;
164 width: 40ch;
165}
166
167#toc, #toc ul, #links {
168 list-style: none;
169}
170
171nav header {
172 font-weight: bold;
173 font-size: 1.5rem;
174}
175
176#toc {
177 padding: 0;
178}
179
180#toc ul {
181 margin: 0rem;
182 padding-left: 1rem;
183 margin-bottom: 0;
184}
185
186#toc li {
187 margin: 0;
188}
189
190#toc ul li {
191 border-left: 1px solid var(--surface-2);
192 padding-left: 0.5rem;
193}
194
195#toc ul li:hover {
196 border-left: 1px solid var(--overlay-2);
197}
198
199#toc .number {
200 color: var(--accent);
201 font-weight: bold;
202}
203
204aside a {
205 position: relative;
206 /* anchor point for 'aside a::before' */
207 display: block;
208 text-decoration: none;
209 color: var(--text);
210 padding: 0.45rem 0.75rem;
211 border-radius: 0.25rem;
212}
213
214/* this invisible hitbox lets you click in the left gutter */
215aside a::before {
216 content: " ";
217 position: absolute;
218 display: block;
219 right: 100%;
220 top: 0;
221 bottom: 0;
222 width: 100vw;
223}
224
225aside a:hover {
226 background-color: var(--surface-0);
227}
228
229#links {
230 list-style: none;
231 padding: 0;
232 margin-top: auto;
233}
234
235#links li {
236 margin: 0;
237}
238
239#hidden-menu-checkbox, [name="tabs"] {
240 display: block;
241 width: 1px;
242 height: 1px;
243 position: fixed;
244 top: -3px;
245 left: -3px;
246}
247
248#menu-btn, #clickable-background {
249 display: none;
250}
251
252main a {
253 color: var(--link);
254}
255
256main a:active {
257 background-color: var(--accent);
258 color: var(--base);
259 border-radius: 0.25rem;
260 text-decoration: none;
261}
262
263.external::after {
264 background-color: var(--link);
265 content: "";
266 display: inline-flex;
267 height: 10px;
268 margin-left: 4px;
269 mask-image: url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTYgMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTcuNSAxLjVWMEgxNnY4LjVoLTEuNVYyLjZMNyAxMC4xIDYgOWw3LjUtNy42aC02Wk0xMyAxNmMuNiAwIDEtLjQgMS0xdi01aC0xLjV2NC41aC0xMXYtMTFINlYySDFhMSAxIDAgMCAwLTEgMXYxMmMwIC42LjQgMSAxIDFoMTJaIiBmaWxsPSJyZWQiLz48L3N2Zz4=");
270 mask-size: cover;
271 width: 10px;
272}
273.external:active::after {
274 background-color: var(--base);
275}
276
277.heading {
278 color: inherit;
279 text-decoration: none;
280}
281
282.heading:hover, .heading:focus-visible {
283 text-decoration: underline;
284 position: relative;
285}
286
287.heading:hover::before, .heading:focus-visible::before {
288 content: " #";
289 color: var(--subtext-0);
290 position: absolute;
291 right: calc(100% + 0.5rem);
292 top: -0.125em;
293}
294
295/* Tablet/small screen layout */
296@media screen and (max-width: 1000px) {
297 html {
298 scroll-padding-top: 5rem;
299 }
300
301 main {
302 padding-top: 5rem;
303 }
304
305 #hidden-menu-checkbox:focus-visible + aside #menu-btn {
306 outline: 2px solid var(--text);
307 }
308
309 aside {
310 position: fixed;
311 left: -100%;
312 transition: left 500ms, bottom 300ms;
313 z-index: 9;
314 padding-top: 3rem;
315 }
316
317 aside a {
318 padding: 0.5rem 0.75rem;
319 }
320
321 #top-part {
322 position: fixed;
323 inset: 0;
324 height: fit-content;
325 background-color: var(--mantle);
326 padding: 0.5rem;
327 box-shadow: 0 4px 4px rgba(0, 0, 0, 0.3);
328 z-index: 9;
329 }
330
331 #menu-btn {
332 display: grid;
333 padding: 0.5rem;
334 width: fit-content;
335 cursor: pointer;
336 border-radius: 0.25rem;
337 user-select: none;
338 }
339
340 #close {
341 display: none;
342 }
343
344 #chevron {
345 display: none;
346 }
347
348 #menu-btn:hover {
349 background-color: var(--surface-0);
350 }
351
352 #hidden-menu-checkbox:checked ~ aside {
353 left: 0;
354 transition: left 300ms, bottom 300ms;
355 }
356
357 #hidden-menu-checkbox:checked ~ aside #clickable-background {
358 display: block;
359 position: fixed;
360 width: 100%;
361 height: 100%;
362 inset: 0;
363 background-color: rgba(0, 0, 0, 0.5);
364 z-index: -1;
365 }
366
367 #hidden-menu-checkbox:checked ~ aside #menu-btn .open {
368 display: none;
369 }
370
371 #hidden-menu-checkbox:checked ~ aside #menu-btn .close {
372 display: block;
373 }
374}
375
376/* Mobile layout */
377@media screen and (max-width: 600px) {
378 main {
379 padding: 3rem 1rem;
380 }
381
382 aside {
383 position: fixed;
384 top: initial;
385 left: 0;
386 bottom: calc(-100% + 6rem);
387 width: 100%;
388 display: flex;
389 flex-direction: column;
390 }
391
392 aside a {
393 padding: 0.8rem 0.75rem;
394 }
395
396 aside a:hover {
397 background-color: var(--surface-1);
398 }
399
400 #sidebar-content {
401 border-radius: 0px;
402 padding: 1rem;
403 width: 100%;
404 background-color: var(--surface-0);
405 }
406
407 #top-part {
408 position: initial;
409 padding: 0;
410 border-radius: 1.5rem 1.5rem 0 0;
411 box-shadow: 0 -4px 5px rgba(0, 0, 0, 0.15);
412 border-bottom: var(--overlay-2) 1px solid;
413 background-color: var(--surface-0);
414 }
415
416 #open, #close {
417 display: none !important;
418 }
419
420 #chevron {
421 display: block;
422 transition: transform 300ms;
423 }
424
425 #menu-btn {
426 display: flex;
427 justify-content: center;
428 width: 100%;
429 padding: 1.5rem 0;
430 border-radius: 1.5rem 1.5rem 0 0;
431 }
432
433 #hidden-menu-checkbox:checked ~ aside {
434 bottom: 0;
435 }
436
437 #hidden-menu-checkbox:checked ~ aside #chevron {
438 transform: rotateX(180deg);
439 }
440
441 #hidden-menu-checkbox:checked ~ aside #top-part {
442 box-shadow: none;
443 }
444}
445
446pre > code {
447 border: none;
448 padding: 0;
449}
450
451pre, code {
452 border: 0;
453 background-color: transparent;
454 font-family: var(--font-code);
455 font-size: 0.9rem;
456}
457
458.file {
459 border: 1px solid var(--surface-1);
460 background-color: var(--crust);
461 border-radius: 0.5rem;
462 overflow: hidden;
463 margin-bottom: 0.5rem;
464}
465
466.file figcaption {
467 padding: 0.25rem 0.5rem;
468 font-size: 0.75rem;
469 border-bottom: 1px solid var(--surface-1);
470 /* background-color: var(--crust); */
471 background-color: var(--accent);
472 color: var(--base);
473}
474
475.file pre {
476 margin: 0;
477 padding: 0.75rem 0.5rem;
478 overflow-y: scroll;
479 color: var(--text);
480 position: relative;
481}
482
483.file pre.terminal {
484 background-color: #24273a;
485 color: #cdd6f4;
486 border-radius: 0 0 0.5rem 0.5rem;
487}
488
489.file [role="tablist"] {
490 display: flex;
491 border-top: 1px solid var(--surface-1);
492 border-bottom: 1px solid var(--surface-1);
493 background-color: var(--surface-0);
494}
495
496.file [role="tab"] {
497 padding: 0.25rem 0.75rem;
498 cursor: pointer;
499 /* flex: 1; */
500 border-top: 2px solid transparent;
501 text-align: center;
502 font-size: 0.9rem;
503}
504
505.file .bottom {
506 display: none;
507}
508
509[name="tabs"][value="output"]:checked ~ main .file .tabs .output {
510 display: block;
511}
512
513[name="tabs"][value="output"]:checked
514 ~ main
515 .file
516 .tabs
517 [role="tab"][for="output"] {
518 font-weight: bold;
519 background-color: var(--base);
520 border-top: 2px solid var(--accent);
521}
522
523[name="tabs"][value="js"]:checked ~ main .file .tabs .js {
524 display: block;
525}
526
527[name="tabs"][value="js"]:checked ~ main .file .tabs [role="tab"][for="js"] {
528 font-weight: bold;
529 border-top: 2px solid var(--accent);
530 background-color: var(--base);
531}
532
533.file .copy-button {
534 position: absolute;
535 top: 0.25rem;
536 right: 0.25rem;
537 padding: 0.25rem;
538 border: 1px solid var(--surface-1);
539 border-radius: 0.25rem;
540 background-color: var(--base);
541 cursor: pointer;
542 display: grid;
543}
544
545.file .copy-button:hover {
546 background-color: var(--crust);
547}
548
549.file .copy-button .hidden {
550 display: none;
551}
src/manual/template.html+2-573
...@@ -3,581 +3,10 @@...@@ -3,581 +3,10 @@
3 <head>3 <head>
4 <meta charset="UTF-8" />4 <meta charset="UTF-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6 <meta name="robots" content="noindex">
6 <title>Ix Language Manual</title>7 <title>Ix Language Manual</title>
7 <style>8 {style}
8 :root {
9 /* Catppuccin Latte (light) & Mocha (dark) */
10 --mantle: light-dark(#e6e9ef, #181825);
11 --crust: light-dark(#dce0e8, #11111b);
12 --base: light-dark(#eff1f5, #1e1e2e);
13 --surface-0: light-dark(#ccd0da, #313244);
14 --surface-1: light-dark(#bcc0cc, #45475a);
15 --surface-2: light-dark(#acb0be, #585b70);
16 --overlay-0: light-dark(#9ca0b0, #6c7086);
17 --overlay-1: light-dark(#8c8fa1, #7f849c);
18 --overlay-2: light-dark(#7c7f93, #9399b2);
19 --subtext-0: light-dark(#6c6f85, #a6adc8);
20 --subtext-1: light-dark(#5c5f77, #bac2de);
21 --text: light-dark(#4c4f69, #cdd6f4);
22 --accent: light-dark(#179299, #94e2d5);
23 --link: light-dark(#179299, #94e2d5);
24 }
25
26 * {
27 margin: 0;
28 padding: 0;
29 box-sizing: border-box;
30 }
31
32 body {
33 background-color: var(--base);
34 color: var(--text);
35 font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
36 Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue",
37 sans-serif;
38 color-scheme: light dark;
39 display: flex;
40 }
41
42 main {
43 width: 100%;
44 max-width: 80ch;
45 padding: 1rem;
46 padding-top: 2rem;
47 margin: auto;
48 line-height: 1.5;
49 }
50
51 h1,
52 h2,
53 h3,
54 h4,
55 h5,
56 h6,
57 p,
58 ul,
59 pre,
60 blockquote,
61 table {
62 margin-bottom: 1rem;
63 }
64
65 h2,
66 h3,
67 h4,
68 h5,
69 h6 {
70 padding-top: 0.8rem;
71 margin-top: -0.8rem;
72 }
73
74 ul {
75 padding-left: 2rem;
76 }
77
78 li {
79 margin-bottom: 0.25rem;
80 }
81
82 blockquote {
83 background-color: var(--surface-0);
84 border-left: 4px solid var(--overlay-2);
85 padding-left: 16px;
86 padding-top: 8px;
87 padding-bottom: 8px;
88 }
89
90 a {
91 color: inherit;
92 }
93
94 table,
95 th,
96 td {
97 border: 1px solid #9ca0b0;
98 border-collapse: collapse;
99 }
100
101 th,
102 td {
103 padding: 0.5rem;
104 }
105
106 .ansi-1 {
107 font-weight: bold;
108 }
109
110 .ansi-31 {
111 color: light-dark(#d20f39, #f38ba8);
112 }
113
114 .ansi-32 {
115 color: light-dark(#40a02b, #a6e3a1);
116 }
117
118 .ansi-33 {
119 color: light-dark(#de8d1c, #f9e2af);
120 }
121
122 .ansi-34 {
123 color: light-dark(#1e66f5, #89b4fa);
124 }
125
126 .ansi-35 {
127 color: light-dark(#ea76cb, #f5c2e7);
128 }
129
130 .ansi-36 {
131 color: light-dark(#179299, #94e2d5);
132 }
133
134 .ansi-2 {
135 color: light-dark(#bcc0cc, #8087a2);
136 }
137
138 .kw {
139 color: light-dark(#8839ef, #cba6f7);
140 font-weight: bold;
141 }
142
143 .tok-string {
144 color: light-dark(#40a02b, #a6e3a1);
145 }
146
147 .tok-builtin_id {
148 color: light-dark(#d20f39, #f38ba8);
149 font-weight: bold;
150 }
151
152 .tok-number_int,
153 .tok-number_float {
154 color: light-dark(#fe640b, #fab387);
155 }
156
157 .tok-semi,
158 .tok-end_paren,
159 .tok-start_paren,
160 .tok-equal,
161 .tok-colon,
162 .tok-start_brace,
163 .tok-end_brace,
164 .tok-dot {
165 color: light-dark(#7c7f93, #9399b2);
166 }
167
168 aside {
169 position: sticky;
170 top: 0;
171 left: 0;
172 height: 100dvh;
173 height: 100vh;
174 }
175
176 #sidebar-content {
177 display: flex;
178 flex-direction: column;
179 background-color: var(--mantle);
180 height: 100%;
181 padding: 1rem;
182 border-radius: 0 1rem 1rem 0;
183 overflow-y: auto;
184 width: 40ch;
185 }
186
187 #toc,
188 #toc ul,
189 #links {
190 list-style: none;
191 }
192
193 nav header {
194 font-weight: bold;
195 font-size: 1.5rem;
196 }
197
198 #toc {
199 padding: 0;
200 }
201
202 #toc ul {
203 margin: 0rem;
204 padding-left: 1rem;
205 margin-bottom: 0;
206 }
207
208 #toc li {
209 margin: 0;
210 }
211
212 #toc ul li {
213 border-left: 1px solid var(--surface-2);
214 padding-left: 0.5rem;
215 }
216
217 #toc ul li:hover {
218 border-left: 1px solid var(--overlay-2);
219 }
220
221 #toc .number {
222 color: var(--accent);
223 font-weight: bold;
224 }
225
226 aside a {
227 position: relative;
228 /* anchor point for 'aside a::before' */
229 display: block;
230 text-decoration: none;
231 color: var(--text);
232 padding: 0.45rem 0.75rem;
233 border-radius: 0.25rem;
234 }
235
236 /* this invisible hitbox lets you click in the left gutter */
237 aside a::before {
238 content: " ";
239 position: absolute;
240 display: block;
241 right: 100%;
242 top: 0;
243 bottom: 0;
244 width: 100vw;
245 }
246
247 aside a:hover {
248 background-color: var(--surface-0);
249 }
250
251 #links {
252 list-style: none;
253 padding: 0;
254 margin-top: auto;
255 }
256
257 #links li {
258 margin: 0;
259 }
260
261 #hidden-menu-checkbox,
262 [name="tabs"] {
263 display: block;
264 width: 1px;
265 height: 1px;
266 position: fixed;
267 top: -3px;
268 left: -3px;
269 }
270
271 #menu-btn,
272 #clickable-background {
273 display: none;
274 }
275
276 main a {
277 color: var(--link);
278 }
279
280 main a:active {
281 background-color: var(--accent);
282 color: var(--base);
283 border-radius: 0.25rem;
284 text-decoration: none;
285 }
286
287 .external::after {
288 background-color: var(--link);
289 content: "";
290 display: inline-flex;
291 height: 10px;
292 margin-left: 4px;
293 mask-image: url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTYgMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTcuNSAxLjVWMEgxNnY4LjVoLTEuNVYyLjZMNyAxMC4xIDYgOWw3LjUtNy42aC02Wk0xMyAxNmMuNiAwIDEtLjQgMS0xdi01aC0xLjV2NC41aC0xMXYtMTFINlYySDFhMSAxIDAgMCAwLTEgMXYxMmMwIC42LjQgMSAxIDFoMTJaIiBmaWxsPSJyZWQiLz48L3N2Zz4=");
294 mask-size: cover;
295 width: 10px;
296 }
297 .external:active::after {
298 background-color: var(--base);
299 }
300
301 .heading {
302 color: inherit;
303 text-decoration: none;
304 }
305
306 .heading:hover,
307 .heading:focus-visible {
308 text-decoration: underline;
309 position: relative;
310 }
311
312 .heading:hover::before,
313 .heading:focus-visible::before {
314 content: " #";
315 color: var(--subtext-0);
316 position: absolute;
317 right: calc(100% + 0.5rem);
318 top: -0.125em;
319 }
320
321 /* Tablet/small screen layout */
322 @media screen and (max-width: 1000px) {
323 html {
324 scroll-padding-top: 5rem;
325 }
326
327 main {
328 padding-top: 5rem;
329 }
330
331 #hidden-menu-checkbox:focus-visible+aside #menu-btn {
332 outline: 2px solid var(--text);
333 }
334
335 aside {
336 position: fixed;
337 left: -100%;
338 transition: left 500ms, bottom 300ms;
339 z-index: 9;
340 padding-top: 3rem;
341 }
342
343 aside a {
344 padding: 0.5rem 0.75rem;
345 }
346
347 #top-part {
348 position: fixed;
349 inset: 0;
350 height: fit-content;
351 background-color: var(--mantle);
352 padding: 0.5rem;
353 box-shadow: 0 4px 4px rgba(0, 0, 0, 0.3);
354 z-index: 9;
355 }
356
357 #menu-btn {
358 display: grid;
359 padding: 0.5rem;
360 width: fit-content;
361 cursor: pointer;
362 border-radius: 0.25rem;
363 user-select: none;
364 }
365
366
367 #close {
368 display: none;
369 }
370
371 #chevron {
372 display: none;
373 }
374
375 #menu-btn:hover {
376 background-color: var(--surface-0);
377 }
378
379 #hidden-menu-checkbox:checked~aside {
380 left: 0;
381 transition: left 300ms, bottom 300ms;
382 }
383
384 #hidden-menu-checkbox:checked~aside #clickable-background {
385 display: block;
386 position: fixed;
387 width: 100%;
388 height: 100%;
389 inset: 0;
390 background-color: rgba(0, 0, 0, 0.5);
391 z-index: -1;
392 }
393
394 #hidden-menu-checkbox:checked~aside #menu-btn .open {
395 display: none;
396 }
397
398 #hidden-menu-checkbox:checked~aside #menu-btn .close {
399 display: block;
400 }
401 }
402
403 /* Mobile layout */
404 @media screen and (max-width: 600px) {
405 main {
406 padding: 3rem 1rem;
407 }
408
409 aside {
410 position: fixed;
411 top: initial;
412 left: 0;
413 bottom: calc(-100% + 6rem);
414 width: 100%;
415 display: flex;
416 flex-direction: column;
417 }
418
419 aside a {
420 padding: 0.8rem 0.75rem;
421 }
422
423 aside a:hover {
424 background-color: var(--surface-1);
425 }
426
427 #sidebar-content {
428 border-radius: 0px;
429 padding: 1rem;
430 width: 100%;
431 background-color: var(--surface-0);
432 }
433
434 #top-part {
435 position: initial;
436 padding: 0;
437 border-radius: 1.5rem 1.5rem 0 0;
438 box-shadow: 0 -4px 5px rgba(0, 0, 0, 0.15);
439 border-bottom: var(--overlay-2) 1px solid;
440 background-color: var(--surface-0);
441 }
442
443 #open,
444 #close {
445 display: none !important;
446 }
447
448 #chevron {
449 display: block;
450 transition: transform 300ms;
451 }
452
453 #menu-btn {
454 display: flex;
455 justify-content: center;
456 width: 100%;
457 padding: 1.5rem 0;
458 border-radius: 1.5rem 1.5rem 0 0;
459 }
460
461 #hidden-menu-checkbox:checked~aside {
462 bottom: 0;
463 }
464
465 #hidden-menu-checkbox:checked~aside #chevron {
466 transform: rotateX(180deg);
467 }
468
469 #hidden-menu-checkbox:checked~aside #top-part {
470 box-shadow: none;
471 }
472 }
473
474 pre>code {
475 border: none;
476 padding: 0;
477 }
478
479 pre,
480 code {
481 border: 0;
482 background-color: transparent;
483 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
484 "Liberation Mono", "Courier New", monospace;
485 font-size: 0.9rem;
486 }
487
488 .file {
489 border: 1px solid var(--surface-1);
490 background-color: var(--crust);
491 border-radius: 0.5rem;
492 overflow: hidden;
493 margin-bottom: 0.5rem;
494 }
495
496 .file figcaption {
497 padding: 0.25rem 0.5rem;
498 font-size: 0.75rem;
499 border-bottom: 1px solid var(--surface-1);
500 /* background-color: var(--crust); */
501 background-color: var(--accent);
502 color: var(--base);
503 }
504
505 .file pre {
506 margin: 0;
507 padding: 0.75rem 0.5rem;
508 overflow-y: scroll;
509 color: var(--text);
510 position: relative;
511 }
512
513 .file pre.terminal {
514 background-color: #24273a;
515 color: #cdd6f4;
516 border-radius: 0 0 0.5rem 0.5rem;
517 }
518
519 .file [role="tablist"] {
520 display: flex;
521 border-top: 1px solid var(--surface-1);
522 border-bottom: 1px solid var(--surface-1);
523 background-color: var(--surface-0);
524 }
525
526 .file [role="tab"] {
527 padding: 0.25rem 0.75rem;
528 cursor: pointer;
529 /* flex: 1; */
530 border-top: 2px solid transparent;
531 text-align: center;
532 font-size: 0.9rem;
533 }
534
535 .file .bottom {
536 display: none;
537 }
538
539 [name="tabs"][value="output"]:checked~main .file .tabs .output {
540 display: block;
541 }
542
543 [name="tabs"][value="output"]:checked~main .file .tabs [role="tab"][for="output"] {
544 font-weight: bold;
545 background-color: var(--base);
546 border-top: 2px solid var(--accent);
547 }
548
549 [name="tabs"][value="js"]:checked~main .file .tabs .js {
550 display: block;
551 }
552
553 [name="tabs"][value="js"]:checked~main .file .tabs [role="tab"][for="js"] {
554 font-weight: bold;
555 border-top: 2px solid var(--accent);
556 background-color: var(--base);
557 }
558
559 .file .copy-button {
560 position: absolute;
561 top: 0.25rem;
562 right: 0.25rem;
563 padding: 0.25rem;
564 border: 1px solid var(--surface-1);
565 border-radius: 0.25rem;
566 background-color: var(--base);
567 cursor: pointer;
568 display: grid;
569 }
570
571 .file .copy-button:hover {
572 background-color: var(--crust);
573 }
574
575 .file .copy-button .hidden {
576 display: none;
577 }
578 </style>
579 </head>9 </head>
580
581 <body>10 <body>
582 <input type="checkbox" id="hidden-menu-checkbox" />11 <input type="checkbox" id="hidden-menu-checkbox" />
583 <input name="tabs" type="radio" id="output" value="output" checked="true" />12 <input name="tabs" type="radio" id="output" value="output" checked="true" />