@abreen/tada 1.6.4 → 1.7.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.
@@ -57,11 +57,39 @@ function parseFrontMatterPlainText(rawContent: string): RawParsedFrontMatter {
57
57
  };
58
58
  }
59
59
 
60
+ function parseFrontMatterStandard(rawContent: string): RawParsedFrontMatter {
61
+ const lines = rawContent.split(/\r?\n/);
62
+
63
+ // Caller has already verified lines[0] === '---'
64
+ for (let i = 1; i < lines.length; i++) {
65
+ if (lines[i].trimEnd() === '---') {
66
+ return {
67
+ frontMatter: lines.slice(1, i).join('\n'),
68
+ content: lines.slice(i + 1).join('\n'),
69
+ };
70
+ }
71
+ }
72
+
73
+ throw new Error(
74
+ 'Front matter starts with --- but no closing --- delimiter was found',
75
+ );
76
+ }
77
+
60
78
  export function parseFrontMatter(
61
79
  rawContent: string,
62
80
  ext: string,
63
81
  ): RawParsedFrontMatter {
64
82
  if (extensionIsMarkdown(ext) || ext === '.html') {
83
+ // Detect standard YAML front matter (first line is exactly ---,
84
+ // ignoring trailing whitespace and \r)
85
+ const firstNewline = rawContent.indexOf('\n');
86
+ const firstLine =
87
+ firstNewline === -1 ? rawContent : rawContent.slice(0, firstNewline);
88
+
89
+ if (firstLine.trimEnd() === '---') {
90
+ return parseFrontMatterStandard(rawContent);
91
+ }
92
+
65
93
  return parseFrontMatterPlainText(rawContent);
66
94
  } else {
67
95
  // unknown type, return raw
@@ -1,8 +1,10 @@
1
+ ---
1
2
  title: Home
2
3
  description: The home page for <%= site.title %>.
3
4
  author: alex
4
5
  published: 2026-03-20
5
6
  toolName: Tada
7
+ ---
6
8
 
7
9
  ## Welcome
8
10
 
@@ -1,9 +1,11 @@
1
+ ---
1
2
  parent: /labs/00/index.html
2
3
  parentLabel: Lab 0
3
4
  title: Counting vowels
4
5
  author: alex
5
6
  description: An example of a literate Java program that takes predefined input.
6
7
  stdin: "hello, world!\n"
8
+ ---
7
9
 
8
10
  A Java program can process input in different ways: it could open a file and
9
11
  read it; it could open a network connection and wait for data from another
@@ -1,8 +1,10 @@
1
+ ---
1
2
  parent: /labs/index.html
2
3
  parentLabel: Labs
3
4
  title: Lab 0
4
5
  author: alex
5
6
  description: An example lab page for <%= site.title %>.
7
+ ---
6
8
 
7
9
  In this lab, we'll explore the [`VowelCounter` program](./VowelCounter.java.html).
8
10
 
@@ -1,8 +1,10 @@
1
+ ---
1
2
  parent: /labs/index.html
2
3
  parentLabel: Labs
3
4
  title: Lab 1
4
5
  author: alex
5
6
  description: A lab page for <%= site.title %> demonstrating the trace feature.
7
+ ---
6
8
 
7
9
  In this lab, we'll examine memory diagrams.
8
10
 
@@ -1,6 +1,8 @@
1
+ ---
1
2
  title: Labs
2
3
  author: alex
3
4
  description: An example page for <%= site.title %>.
5
+ ---
4
6
 
5
7
  In each one-hour lab, we'll dive deeper and write code together, exploring how
6
8
  to apply the concepts we learned in lecture to solve real-world problems and
@@ -1,6 +1,8 @@
1
+ ---
1
2
  title: A generic `Pair` class
2
3
  author: alex
3
4
  description: An example of a literate Java program.
5
+ ---
4
6
 
5
7
  <!---
6
8
  You may hide code from the generated HTML page but still include it in the
@@ -1,8 +1,10 @@
1
+ ---
1
2
  parentLabel: Lectures
2
3
  parent: /lectures/index.html
3
4
  title: Lecture 1
4
5
  description: An example lecture page.
5
6
  author: alex
7
+ ---
6
8
 
7
9
  Here is a sample description of the topics covered at the first lecture.
8
10
 
@@ -1,8 +1,10 @@
1
+ ---
1
2
  parentLabel: Lectures
2
3
  parent: /lectures/index.html
3
4
  title: Lecture 2
4
5
  description: An example lecture page demonstrating partials.
5
6
  author: alex
7
+ ---
6
8
 
7
9
  Here is a page constructed from multiple partials.
8
10
 
@@ -1,6 +1,8 @@
1
+ ---
1
2
  title: Lectures
2
3
  author: alex
3
4
  description: An example page for <%= site.title %>.
5
+ ---
4
6
 
5
7
  <%= renderTimeZoneChooser() %>
6
8
 
@@ -1,18 +1,22 @@
1
+ ---
1
2
  title: Markdown Examples
2
3
  description: Examples of Markdown syntax supported by Tada.
3
4
  author: alex
4
5
  published: 2026-03-20
5
6
  toc: true
7
+ ---
6
8
 
7
9
  Markdown and HTML files in the `content/` directory
8
10
  must contain ["front matter"][front-matter] (YAML-formatted metadata).
9
11
  For example, this file's first five lines look like this:
10
12
 
11
13
  ```text
14
+ ---
12
15
  title: Markdown Examples
13
- description: Examples of Markdown syntax supported by tada.
16
+ description: Examples of Markdown syntax supported by Tada.
14
17
  toc: true
15
18
  author: alex
19
+ ---
16
20
  ```
17
21
 
18
22
  This page contains a table of contents because the front matter
@@ -1,7 +1,9 @@
1
+ ---
1
2
  title: Problem Sets
2
3
  author: alex
3
4
  description: An example page for <%= site.title %> which is not generated.
4
5
  skip: true
6
+ ---
5
7
 
6
8
  <p>
7
9
  For convenience or backwards compatibility, you can write standard HTML
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abreen/tada",
3
- "version": "1.6.4",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "description": "A static site generator",
6
6
  "license": "MIT",
package/src/_alerts.scss CHANGED
@@ -1,7 +1,7 @@
1
1
  @use 'mixins' as *;
2
2
 
3
3
  .alert {
4
- border: 3px solid var(--bg2-color);
4
+ border: 2px solid var(--bg2-color);
5
5
  position: relative;
6
6
  margin: 1rem 0;
7
7
  }
package/src/_base.scss CHANGED
@@ -92,7 +92,7 @@ code {
92
92
  font-size: var(--mono-font-size);
93
93
  background: var(--bg2-color);
94
94
  border-radius: var(--mono-border-radius);
95
- padding: 0.12em 0.25em;
95
+ padding: var(--mono-padding);
96
96
  overflow-wrap: anywhere;
97
97
  }
98
98
 
@@ -139,18 +139,16 @@ details .content {
139
139
  }
140
140
 
141
141
  @media (hover: hover) {
142
- details summary {
143
- &:hover {
144
- color: var(--fg2-color);
145
- @include link-underline;
146
- }
147
-
148
- &:active {
149
- color: var(--link-active-color);
150
- }
142
+ details summary:hover {
143
+ color: var(--fg2-color);
144
+ @include link-underline;
151
145
  }
152
146
  }
153
147
 
148
+ details summary:active {
149
+ color: var(--link-active-color);
150
+ }
151
+
154
152
  main details {
155
153
  margin-bottom: 1rem;
156
154
  border-radius: var(--border-radius);
package/src/_mixins.scss CHANGED
@@ -42,4 +42,8 @@
42
42
  -webkit-mask-position: center center;
43
43
  mask-position: center center;
44
44
  background-color: currentColor;
45
+ // The icon's visible fill is the background color, which browsers strip
46
+ // when printing by default. Preserve it so masked icons remain visible.
47
+ -webkit-print-color-adjust: exact;
48
+ print-color-adjust: exact;
45
49
  }
@@ -1,13 +1,10 @@
1
- :root {
2
- --print-font-size: 15px;
3
- }
1
+ @use '../mixins' as *;
4
2
 
5
3
  @media print {
6
4
  html,
7
- body,
8
- main,
9
- section {
5
+ body {
10
6
  background: none !important;
7
+ color: #000;
11
8
  }
12
9
 
13
10
  hr {
@@ -27,15 +24,22 @@
27
24
  margin-top: 0;
28
25
  }
29
26
 
30
- body {
31
- font-size: var(--print-font-size);
32
- color: #000;
27
+ main a:not(.heading-anchor):not(.footnote-ref):not(.line-number) {
28
+ @include link-underline;
33
29
  }
34
30
 
35
- pre {
36
- font-size: var(--print-font-size);
37
- border: none;
38
- padding: 0;
31
+ pre,
32
+ tt,
33
+ :not(pre) > code {
34
+ border: 1px solid #ccc;
35
+ }
36
+
37
+ // .alert strips the default padding from inline code (since it also
38
+ // strips the background). In print we add a border, so restore the
39
+ // padding so the border doesn't hug the text.
40
+ .alert .content tt,
41
+ .alert .content code {
42
+ padding: var(--mono-padding);
39
43
  }
40
44
 
41
45
  .footnotes {
@@ -50,18 +54,15 @@
50
54
  display: none !important;
51
55
  }
52
56
 
53
- main details {
54
- border: 2px solid #000;
55
- }
56
-
57
- main details .alert {
58
- border: none;
59
- padding: 0;
57
+ details,
58
+ .alert {
59
+ border-color: #000 !important;
60
60
  }
61
61
 
62
62
  section {
63
63
  border: none;
64
64
  padding: 0;
65
+ margin: 0;
65
66
  width: 100%;
66
67
  }
67
68
 
@@ -69,7 +70,8 @@
69
70
  display: none;
70
71
  }
71
72
 
72
- a.external::after {
73
- display: none;
73
+ .external-link-tail::after,
74
+ a.external:not(:has(.external-link-tail))::after {
75
+ content: none;
74
76
  }
75
77
  }
@@ -61,10 +61,11 @@ body.code .toc ol a {
61
61
  .toc ol li:has(a):hover a {
62
62
  color: var(--fg2-color);
63
63
  }
64
+ }
64
65
 
65
- .toc ol li a:active {
66
- color: var(--link-active-color);
67
- }
66
+ .toc ol li:has(a):active,
67
+ .toc ol li:has(a):active a {
68
+ color: var(--link-active-color);
68
69
  }
69
70
 
70
71
  @media (min-width: 900px) {
@@ -57,6 +57,7 @@
57
57
  --mono-font-size: 0.94em;
58
58
  --mono-line-height: 1.5;
59
59
  --mono-border-radius: 0.375em;
60
+ --mono-padding: 0.12em 0.25em;
60
61
 
61
62
  // SVG icons
62
63
  // Mask icons (color-agnostic, painted via background-color: currentColor)