@abreen/tada 1.0.2 → 1.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.
Files changed (120) hide show
  1. package/README.md +29 -33
  2. package/bin/tada.ts +356 -0
  3. package/bin/validators.test.ts +204 -0
  4. package/bin/validators.ts +83 -0
  5. package/{webpack/apply-base-path-plugin.js → build/apply-base-path-plugin.ts} +16 -7
  6. package/build/bundle.ts +117 -0
  7. package/{webpack/code.test.js → build/code.test.ts} +6 -7
  8. package/build/colors.ts +25 -0
  9. package/build/content-watch.ts +107 -0
  10. package/build/copy.ts +118 -0
  11. package/{webpack/deflist-id-plugin.js → build/deflist-id-plugin.ts} +7 -6
  12. package/{webpack/external-links-plugin.js → build/external-links-plugin.ts} +14 -5
  13. package/build/features.ts +11 -0
  14. package/build/generate-content-assets.ts +315 -0
  15. package/build/generate-favicon.ts +165 -0
  16. package/build/generate-fonts.ts +31 -0
  17. package/{webpack/generate-manifest-plugin.js → build/generate-manifest.ts} +29 -36
  18. package/build/globals.test.ts +101 -0
  19. package/{webpack/globals.js → build/globals.ts} +28 -13
  20. package/{webpack/heading-subtitle-plugin.js → build/heading-subtitle-plugin.ts} +4 -2
  21. package/build/json-schema.test.ts +57 -0
  22. package/build/json-schema.ts +33 -0
  23. package/build/log.test.ts +111 -0
  24. package/build/log.ts +167 -0
  25. package/{webpack/markdown-plugins.test.js → build/markdown-plugins.test.ts} +94 -9
  26. package/{webpack/pagefind-plugin.test.js → build/pagefind.test.ts} +74 -13
  27. package/build/pagefind.ts +339 -0
  28. package/{webpack/pdf-text.js → build/pdf-text.ts} +47 -27
  29. package/build/pipeline.ts +93 -0
  30. package/{webpack/reachability.test.js → build/reachability.test.ts} +3 -3
  31. package/{webpack/reachability.js → build/reachability.ts} +77 -34
  32. package/build/serve.ts +112 -0
  33. package/{webpack/site-variables.js → build/site-variables.ts} +22 -15
  34. package/{webpack → build}/site.schema.json +3 -10
  35. package/{webpack/templates.js → build/templates.ts} +35 -33
  36. package/{webpack/text-to-id.js → build/text-to-id.ts} +2 -2
  37. package/build/toc-plugin.test.ts +105 -0
  38. package/{webpack/toc-plugin.js → build/toc-plugin.ts} +32 -13
  39. package/build/types.ts +172 -0
  40. package/build/util.ts +26 -0
  41. package/{webpack/utils/code.js → build/utils/code.ts} +119 -60
  42. package/{webpack/utils/content-files.js → build/utils/content-files.ts} +40 -35
  43. package/build/utils/derive-theme.test.ts +111 -0
  44. package/build/utils/derive-theme.ts +85 -0
  45. package/build/utils/file-types.test.ts +61 -0
  46. package/build/utils/file-types.ts +13 -0
  47. package/build/utils/front-matter.test.ts +80 -0
  48. package/{webpack/utils/front-matter.js → build/utils/front-matter.ts} +22 -9
  49. package/{webpack → build}/utils/jdi-runner/LiterateRunner.java +1 -1
  50. package/{webpack/utils/literate-java.js → build/utils/literate-java.ts} +63 -34
  51. package/{webpack/utils/markdown.js → build/utils/markdown.ts} +94 -49
  52. package/build/utils/paths.test.ts +91 -0
  53. package/{webpack/utils/paths.js → build/utils/paths.ts} +14 -22
  54. package/{webpack/utils/render.js → build/utils/render.ts} +188 -123
  55. package/build/utils/shiki-highlighter.ts +29 -0
  56. package/build/validate-internal-links-plugin.test.ts +106 -0
  57. package/{webpack/validate-internal-links-plugin.js → build/validate-internal-links-plugin.ts} +47 -20
  58. package/{webpack/watch-reachability-state.test.js → build/watch-reachability-state.test.ts} +8 -8
  59. package/{webpack/watch-reachability-state.js → build/watch-reachability-state.ts} +63 -24
  60. package/{webpack/watch-reload-client.js → build/watch-reload-client.ts} +3 -1
  61. package/build/watch.ts +573 -0
  62. package/content/index.md +9 -3
  63. package/content/markdown.md +2 -1
  64. package/content/problem_sets/index.html +14 -0
  65. package/fonts/google-sans-code/woff2/GoogleSansCodeVariable-Italic.woff2 +0 -0
  66. package/fonts/google-sans-code/woff2/GoogleSansCodeVariable.woff2 +0 -0
  67. package/fonts/inter/woff2/InterVariable-Italic.woff2 +0 -0
  68. package/fonts/inter/woff2/InterVariable.woff2 +0 -0
  69. package/package.json +28 -19
  70. package/src/_alerts.scss +92 -0
  71. package/src/_base.scss +106 -0
  72. package/src/{layout.scss → _layout.scss} +0 -2
  73. package/src/anchor/style.scss +1 -9
  74. package/src/code/index.ts +3 -3
  75. package/src/code.scss +1 -1
  76. package/src/critical.scss +5 -0
  77. package/src/header/_base.scss +129 -0
  78. package/src/header/style.scss +3 -131
  79. package/src/index.ts +1 -2
  80. package/src/question/style.scss +1 -1
  81. package/src/search/index.ts +36 -15
  82. package/src/search/style.scss +9 -15
  83. package/src/style.scss +6 -269
  84. package/src/toc/style.scss +5 -39
  85. package/src/util.ts +8 -5
  86. package/templates/_theme.scss +38 -14
  87. package/tsconfig.json +10 -6
  88. package/types/file-system-access.d.ts +5 -0
  89. package/types/markdown-it-plugins.d.ts +11 -0
  90. package/types/untyped-modules.d.ts +40 -0
  91. package/bin/tada.js +0 -361
  92. package/content/problem_sets/index.md +0 -6
  93. package/webpack/build-state.js +0 -97
  94. package/webpack/colors.js +0 -15
  95. package/webpack/config.base.js +0 -151
  96. package/webpack/config.dev.js +0 -23
  97. package/webpack/config.prod.js +0 -32
  98. package/webpack/content-watch-plugin.js +0 -153
  99. package/webpack/features.js +0 -5
  100. package/webpack/generate-content-assets-plugin.js +0 -308
  101. package/webpack/generate-favicon-plugin.js +0 -198
  102. package/webpack/generate-fonts-plugin.js +0 -69
  103. package/webpack/json-schema.js +0 -19
  104. package/webpack/log.js +0 -143
  105. package/webpack/pagefind-plugin.js +0 -379
  106. package/webpack/print-flair-plugin.js +0 -22
  107. package/webpack/serve.js +0 -104
  108. package/webpack/util.js +0 -49
  109. package/webpack/utils/define-plugin.js +0 -20
  110. package/webpack/utils/file-types.js +0 -26
  111. package/webpack/utils/parse-hsl.js +0 -8
  112. package/webpack/utils/shiki-highlighter.js +0 -26
  113. package/webpack/watch.js +0 -166
  114. /package/{webpack → build}/flair.json +0 -0
  115. /package/{webpack → build}/utils/jdi-runner/LiterateRunner.class +0 -0
  116. /package/fonts/google-sans-code/{GoogleSansCodeVariable-Italic.ttf → ttf/GoogleSansCodeVariable-Italic.ttf} +0 -0
  117. /package/fonts/google-sans-code/{GoogleSansCodeVariable.ttf → ttf/GoogleSansCodeVariable.ttf} +0 -0
  118. /package/fonts/inter/{InterVariable-Italic.ttf → ttf/InterVariable-Italic.ttf} +0 -0
  119. /package/fonts/inter/{InterVariable.ttf → ttf/InterVariable.ttf} +0 -0
  120. /package/types/{dev.ts → dev.d.ts} +0 -0
@@ -2,8 +2,30 @@ import { getElement, applyBasePath } from '../util';
2
2
 
3
3
  const MAX_RESULTS = 24;
4
4
 
5
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
- let pagefind: any = null;
5
+ interface PagefindSubResult {
6
+ title?: string;
7
+ url: string;
8
+ excerpt?: string;
9
+ }
10
+
11
+ interface PagefindResult {
12
+ meta?: { title?: string; page?: string };
13
+ url: string;
14
+ excerpt?: string;
15
+ score: number;
16
+ sub_results?: PagefindSubResult[];
17
+ }
18
+
19
+ interface PagefindSearchResult {
20
+ data(): Promise<PagefindResult>;
21
+ }
22
+
23
+ interface Pagefind {
24
+ init(): Promise<void>;
25
+ search(query: string): Promise<{ results: PagefindSearchResult[] }>;
26
+ }
27
+
28
+ let pagefind: Pagefind | null = null;
7
29
 
8
30
  type SubResult = { title: string; url: string; excerpt: string };
9
31
  type Result = {
@@ -105,27 +127,23 @@ async function doSearch(state: State) {
105
127
 
106
128
  const search = await pagefind.search(state.value);
107
129
  const slice = search.results.slice(0, MAX_RESULTS);
108
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
109
- const data = await Promise.all(slice.map((r: any) => r.data()));
130
+ const data = await Promise.all(slice.map(r => r.data()));
110
131
 
111
132
  const titlePostfix = window.siteVariables.titlePostfix ?? '';
112
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
- const results: Result[] = data.map((d: any) => {
133
+ const results: Result[] = data.map((d: PagefindResult) => {
114
134
  let title: string = d.meta?.title ?? d.url;
115
135
  if (titlePostfix && title.endsWith(titlePostfix)) {
116
136
  title = title.slice(0, -titlePostfix.length);
117
137
  }
118
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
138
  const subResults: SubResult[] = (d.sub_results ?? [])
120
- .filter((s: any) => {
139
+ .filter((s: PagefindSubResult) => {
121
140
  try {
122
141
  return new URL(s.url, window.location.href).hash !== '';
123
142
  } catch {
124
143
  return s.url !== d.url;
125
144
  }
126
145
  })
127
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
- .map((s: any) => ({
146
+ .map((s: PagefindSubResult) => ({
129
147
  title: s.title ?? '',
130
148
  url: s.url,
131
149
  excerpt: s.excerpt ?? '',
@@ -133,7 +151,7 @@ async function doSearch(state: State) {
133
151
  return {
134
152
  title,
135
153
  url: d.url,
136
- excerpt: d.excerpt,
154
+ excerpt: d.excerpt ?? '',
137
155
  score: d.score ?? 0,
138
156
  subResults,
139
157
  pageNumber: getPdfPageNumber(d.url, d.meta?.page),
@@ -324,14 +342,17 @@ export default (window: Window) => {
324
342
  if (pagefind) {
325
343
  return;
326
344
  }
327
- // @ts-ignore pagefind.js is generated post-build, not resolvable at compile time
328
- pagefind = await import(
329
- /* webpackIgnore: true */ applyBasePath('/pagefind/pagefind.js')
330
- );
345
+
346
+ pagefind = (await import(
347
+ applyBasePath('/pagefind/pagefind.js')
348
+ )) as Pagefind;
349
+
331
350
  await pagefind.init();
351
+
332
352
  const res = await fetch(applyBasePath('/pagefind/pagefind-entry.json'), {
333
353
  cache: 'no-cache',
334
354
  });
355
+
335
356
  if (res.ok) {
336
357
  entryETag = res.headers.get('ETag');
337
358
  entryLastModified = res.headers.get('Last-Modified');
@@ -1,4 +1,4 @@
1
- @import '../_mixins.scss';
1
+ @use '../mixins' as *;
2
2
 
3
3
  header {
4
4
  .search-controls {
@@ -9,7 +9,7 @@ header {
9
9
 
10
10
  input.search {
11
11
  background-color: var(--bg-color);
12
- background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><circle cx='11' cy='11' r='7' stroke='hsl(20deg 8% 8%)' stroke-width='2' fill='none'/><line x1='16.5' y1='16.5' x2='22' y2='22' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/></svg>");
12
+ background-image: var(--icon-search);
13
13
  background-repeat: no-repeat;
14
14
  background-position: left 6px center;
15
15
  background-size: 16px 16px;
@@ -24,12 +24,6 @@ header {
24
24
  cursor: not-allowed;
25
25
  }
26
26
  }
27
-
28
- @media (prefers-color-scheme: dark) {
29
- input.search {
30
- background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><circle cx='11' cy='11' r='7' stroke='hsl(20deg 20% 90%)' stroke-width='2' fill='none'/><line x1='16.5' y1='16.5' x2='22' y2='22' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/></svg>");
31
- }
32
- }
33
27
  }
34
28
 
35
29
  .results-container.is-showing .results {
@@ -48,13 +42,6 @@ header {
48
42
  .results {
49
43
  opacity: 0;
50
44
  pointer-events: none;
51
-
52
- @media (prefers-reduced-motion: no-preference) {
53
- transform: translateY(-8px);
54
- transition:
55
- opacity 0.25s ease,
56
- transform 0.25s ease;
57
- }
58
45
  margin: 0 auto;
59
46
  background: var(--bg-color);
60
47
  color: var(--fg-color);
@@ -68,6 +55,13 @@ header {
68
55
  min-height: 80px;
69
56
  @include user-select(none);
70
57
 
58
+ @media (prefers-reduced-motion: no-preference) {
59
+ transform: translateY(-8px);
60
+ transition:
61
+ opacity 0.25s ease,
62
+ transform 0.25s ease;
63
+ }
64
+
71
65
  .results-info {
72
66
  display: flex;
73
67
  align-items: center;
package/src/style.scss CHANGED
@@ -1,5 +1,8 @@
1
- @import './_mixins.scss';
2
- @import 'config/theme';
1
+ @use 'mixins' as *;
2
+ @use 'config/theme';
3
+ @use 'base';
4
+ @use 'layout';
5
+ @use 'alerts';
3
6
 
4
7
  @font-face {
5
8
  font-family: 'Inter';
@@ -34,38 +37,6 @@
34
37
  format('woff2');
35
38
  }
36
39
 
37
- :root {
38
- --box-border-width: 5px;
39
-
40
- --gap: 12px;
41
- --border-radius: 12px;
42
- --control-border-width: 2px;
43
- --label-border-width: 2px;
44
- --focus-border-width: 3px;
45
- --table-padding: 12px;
46
- --details-padding: 12px;
47
- --section-padding: 64px;
48
-
49
- --main-width: 900px;
50
-
51
- --icon-external-link: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><rect x='3' y='3' width='18' height='18' stroke='hsl(20deg 8% 8%)' stroke-width='2' fill='none' rx='2'/><path d='M9 15 L15 9' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round' fill='none'/><path d='M9 9 H15 V15' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round' fill='none'/></svg>");
52
- --icon-external-link-dark: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><rect x='3' y='3' width='18' height='18' stroke='hsl(20deg 20% 90%)' stroke-width='2' fill='none' rx='2'/><path d='M9 15 L15 9' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round' fill='none'/><path d='M9 9 H15 V15' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round' fill='none'/></svg>");
53
- --icon-external-link-hover: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><rect x='3' y='3' width='18' height='18' stroke='hsl(20deg 6% 60%)' stroke-width='2' fill='none' rx='2'/><path d='M9 15 L15 9' stroke='hsl(20deg 6% 60%)' stroke-width='2' stroke-linecap='round' fill='none'/><path d='M9 9 H15 V15' stroke='hsl(20deg 6% 60%)' stroke-width='2' stroke-linecap='round' fill='none'/></svg>");
54
- --icon-external-link-dark-hover: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><rect x='3' y='3' width='18' height='18' stroke='hsl(20deg 6% 55%)' stroke-width='2' fill='none' rx='2'/><path d='M9 15 L15 9' stroke='hsl(20deg 6% 55%)' stroke-width='2' stroke-linecap='round' fill='none'/><path d='M9 9 H15 V15' stroke='hsl(20deg 6% 55%)' stroke-width='2' stroke-linecap='round' fill='none'/></svg>");
55
- --icon-external-link-active: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><rect x='3' y='3' width='18' height='18' stroke='black' stroke-width='2' fill='none' rx='2'/><path d='M9 15 L15 9' stroke='black' stroke-width='2' stroke-linecap='round' fill='none'/><path d='M9 9 H15 V15' stroke='black' stroke-width='2' stroke-linecap='round' fill='none'/></svg>");
56
- --icon-external-link-dark-active: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><rect x='3' y='3' width='18' height='18' stroke='white' stroke-width='2' fill='none' rx='2'/><path d='M9 15 L15 9' stroke='white' stroke-width='2' stroke-linecap='round' fill='none'/><path d='M9 9 H15 V15' stroke='white' stroke-width='2' stroke-linecap='round' fill='none'/></svg>");
57
-
58
- --icon-external-translucent: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><g opacity='0.3' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round' fill='none'><rect x='3' y='3' width='18' height='18' rx='2'/><path d='M9 15 L15 9' stroke-linecap='round'/><path d='M9 9 H15 V15' stroke-linecap='round'/></g></svg>");
59
- --icon-external-translucent-dark: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><g opacity='0.3' stroke='hsl(20deg 85% 90%)' stroke-width='2' stroke-linecap='round' fill='none'><rect x='3' y='3' width='18' height='18' rx='2'/><path d='M9 15 L15 9' stroke-linecap='round'/><path d='M9 9 H15 V15' stroke-linecap='round'/></g></svg>");
60
-
61
- --icon-warning: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 24 24'><polygon points='12,2 22,20 2,20' fill='none' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linejoin='round'/><line x1='12' y1='9' x2='12' y2='13' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='16' x2='12' y2='16' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/></svg>");
62
- --icon-warning-dark: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 24 24'><polygon points='12,2 22,20 2,20' fill='none' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linejoin='round'/><line x1='12' y1='9' x2='12' y2='13' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='16' x2='12' y2='16' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/></svg>");
63
- }
64
-
65
- p {
66
- margin: 0 0 1rem 0;
67
- }
68
-
69
40
  ::selection {
70
41
  color: var(--bg-color);
71
42
  background: var(--fg-color);
@@ -76,26 +47,6 @@ p {
76
47
  outline-offset: 1px;
77
48
  }
78
49
 
79
- h1,
80
- h2,
81
- h3,
82
- h4,
83
- h5,
84
- h6 {
85
- font-family: var(--heading-font);
86
- -webkit-break-after: avoid;
87
- break-after: avoid;
88
- line-height: 1.3;
89
-
90
- // Enable Inter's ligatures (for style)
91
- font-feature-settings: 'dlig';
92
- }
93
-
94
- h1 {
95
- font-size: 250%;
96
- font-weight: 700;
97
- }
98
-
99
50
  .info {
100
51
  @include user-select(none);
101
52
  display: grid;
@@ -130,42 +81,6 @@ h1 {
130
81
  }
131
82
  }
132
83
 
133
- body {
134
- color: var(--fg-color);
135
- background-color: var(--bg-color);
136
-
137
- font-family: var(--font);
138
- font-size: var(--font-size);
139
- font-weight: var(--font-weight);
140
- line-height: var(--line-height);
141
-
142
- /*
143
- * Enable Inter's features for legibility:
144
- * ss03 - round quotes & commas
145
- * ss04 - disambiguation (make uppercase i and lowercase L distinct)
146
- */
147
- font-feature-settings: 'ss03', 'ss04';
148
-
149
- @media (prefers-color-scheme: dark) {
150
- & {
151
- text-rendering: optimizeLegibility;
152
- -webkit-font-smoothing: antialiased;
153
- }
154
- }
155
- }
156
-
157
- html {
158
- overscroll-behavior: none;
159
- background: var(--bg-color);
160
- }
161
-
162
- a {
163
- color: var(--fg-color);
164
- text-decoration-color: var(--fg2-color);
165
- text-decoration-thickness: 1px;
166
- text-underline-offset: 3px;
167
- }
168
-
169
84
  a.disabled {
170
85
  color: var(--fg-color-translucent);
171
86
  text-decoration-color: var(--fg-color-translucent);
@@ -196,15 +111,6 @@ a.external::after {
196
111
  padding-right: 18px;
197
112
  }
198
113
 
199
- @media (prefers-color-scheme: dark) {
200
- a.external::after {
201
- background: var(--icon-external-link-dark);
202
- background-size: contain;
203
- background-repeat: no-repeat;
204
- background-position: center center;
205
- }
206
- }
207
-
208
114
  @media (hover: hover) {
209
115
  a.external:hover::after {
210
116
  background: var(--icon-external-link-hover);
@@ -214,15 +120,6 @@ a.external::after {
214
120
  }
215
121
  }
216
122
 
217
- @media (hover: hover) and (prefers-color-scheme: dark) {
218
- a.external:hover::after {
219
- background: var(--icon-external-link-dark-hover);
220
- background-size: contain;
221
- background-repeat: no-repeat;
222
- background-position: center center;
223
- }
224
- }
225
-
226
123
  a.external:active::after {
227
124
  background: var(--icon-external-link-active) !important;
228
125
  background-size: contain !important;
@@ -230,15 +127,6 @@ a.external:active::after {
230
127
  background-position: center center !important;
231
128
  }
232
129
 
233
- @media (prefers-color-scheme: dark) {
234
- a.external:active::after {
235
- background: var(--icon-external-link-dark-active) !important;
236
- background-size: contain !important;
237
- background-repeat: no-repeat !important;
238
- background-position: center center !important;
239
- }
240
- }
241
-
242
130
  a.external.disabled::after,
243
131
  a.external.disabled:active::after {
244
132
  background: var(--icon-external-translucent) !important;
@@ -247,16 +135,6 @@ a.external.disabled:active::after {
247
135
  background-position: center center !important;
248
136
  }
249
137
 
250
- @media (prefers-color-scheme: dark) {
251
- a.external.disabled::after,
252
- a.external.disabled:active::after {
253
- background: var(--icon-external-translucent-dark) !important;
254
- background-size: contain !important;
255
- background-repeat: no-repeat !important;
256
- background-position: center center !important;
257
- }
258
- }
259
-
260
138
  .footnotes {
261
139
  margin-top: calc(var(--thematic-break-margin) / 2);
262
140
  padding-top: 32px;
@@ -508,114 +386,6 @@ tbody tr:last-child td {
508
386
  border-bottom: none;
509
387
  }
510
388
 
511
- .alert {
512
- border: 3px solid var(--bg2-color);
513
- position: relative;
514
- margin: 1rem 0;
515
- }
516
-
517
- .alert.warning {
518
- background: var(--warning-bg-color);
519
- border-color: var(--warning-bg-color);
520
- }
521
-
522
- .alert.note {
523
- background: var(--note-bg-color);
524
- border-color: var(--note-bg-color);
525
- }
526
-
527
- .alert .title {
528
- padding: 10px 6px;
529
- }
530
-
531
- .alert .content {
532
- padding: 12px;
533
-
534
- .styled-list {
535
- color: var(--fg-color);
536
- }
537
-
538
- tt,
539
- code {
540
- background: inherit;
541
- padding: inherit;
542
- }
543
-
544
- time[datetime].is-modified {
545
- // Reset the underline color
546
- text-decoration: underline dotted;
547
- }
548
-
549
- a {
550
- text-decoration-color: var(--fg-color);
551
- }
552
-
553
- dfn {
554
- color: inherit;
555
- }
556
- }
557
-
558
- .alert .content > *:first-child {
559
- margin-top: 0;
560
- }
561
-
562
- .alert .content > *:last-child {
563
- margin-bottom: 0;
564
- }
565
-
566
- .alert .title::before {
567
- left: 8px;
568
- top: 8px;
569
- position: absolute;
570
- width: 32px;
571
- height: 32px;
572
- }
573
-
574
- .alert.warning .title::before {
575
- content: var(--icon-warning);
576
- }
577
-
578
- i.warning {
579
- background: var(--icon-warning);
580
- background-size: contain;
581
- display: inline-block;
582
- height: 1em;
583
- width: 1em;
584
- vertical-align: sub;
585
- }
586
-
587
- @media (prefers-color-scheme: dark) {
588
- .alert.warning .title::before {
589
- content: var(--icon-warning-dark);
590
- }
591
-
592
- i.warning {
593
- background: var(--icon-warning-dark);
594
- background-size: contain;
595
- }
596
- }
597
-
598
- .alert.note .title::before {
599
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 24 24'><circle cx='12' cy='12' r='10' fill='none' stroke='hsl(20deg 8% 8%)' stroke-width='2'/><line x1='12' y1='10' x2='12' y2='16' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='7' x2='12' y2='7' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/></svg>");
600
- }
601
-
602
- @media (prefers-color-scheme: dark) {
603
- .alert.note .title::before {
604
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 24 24'><circle cx='12' cy='12' r='10' fill='none' stroke='hsl(20deg 20% 90%)' stroke-width='2'/><line x1='12' y1='10' x2='12' y2='16' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='7' x2='12' y2='7' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/></svg>");
605
- }
606
- }
607
-
608
- .alert .title {
609
- font-weight: 700;
610
- @include user-select(none);
611
- padding-left: 48px;
612
- margin: 0;
613
- }
614
-
615
- .alert > p:last-child {
616
- margin-bottom: 0;
617
- }
618
-
619
389
  section {
620
390
  background: linear-gradient(
621
391
  0deg,
@@ -718,15 +488,9 @@ dfn {
718
488
  @include user-select(none);
719
489
 
720
490
  &::after {
721
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><path d='M3 7 H17 V22' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/><polyline points='11 16 17 22 23 16' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>");
491
+ content: var(--icon-breadcrumb);
722
492
  vertical-align: middle;
723
493
  }
724
-
725
- @media (prefers-color-scheme: dark) {
726
- &::after {
727
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><path d='M3 7 H17 V22' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/><polyline points='11 16 17 22 23 16' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>");
728
- }
729
- }
730
494
  }
731
495
 
732
496
  img {
@@ -775,33 +539,6 @@ select {
775
539
  font-size: inherit;
776
540
  }
777
541
 
778
- pre,
779
- tt,
780
- code {
781
- font-family: var(--mono-font);
782
- }
783
-
784
- tt,
785
- code {
786
- font-size: var(--mono-font-size);
787
- background: var(--bg2-color);
788
- border-radius: var(--mono-border-radius);
789
- padding: 0.12em 0.25em;
790
- overflow-wrap: anywhere;
791
- }
792
-
793
- pre {
794
- background: var(--bg2-color);
795
- border-radius: var(--mono-border-radius);
796
- line-height: var(--mono-line-height);
797
- overflow: auto;
798
- padding: var(--gap);
799
-
800
- code {
801
- padding: 0;
802
- }
803
- }
804
-
805
542
  // Shiki dual-theme support (defaultColor: false — CSS custom properties only,
806
543
  // no inline color/background-color, so no !important needed)
807
544
  .shiki span {
@@ -1,4 +1,4 @@
1
- @import '../_mixins.scss';
1
+ @use '../mixins' as *;
2
2
 
3
3
  :root {
4
4
  --highlight-hue: 59deg;
@@ -136,58 +136,24 @@ body.code .toc ol a {
136
136
  }
137
137
 
138
138
  .toc ol li.alert-item.warning a::before {
139
- // fg-color
140
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'><polygon points='12,2 22,20 2,20' fill='none' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linejoin='round'/><line x1='12' y1='9' x2='12' y2='13' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='16' x2='12' y2='16' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/></svg>");
141
- }
142
-
143
- @media (prefers-color-scheme: dark) {
144
- .toc ol li.alert-item.warning a::before {
145
- // fg2-color
146
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'><polygon points='12,2 22,20 2,20' fill='none' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linejoin='round'/><line x1='12' y1='9' x2='12' y2='13' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='16' x2='12' y2='16' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/></svg>");
147
- }
139
+ content: var(--icon-warning-sm);
148
140
  }
149
141
 
150
142
  @media (hover: hover) {
151
143
  .toc ol li.alert-item.warning:hover a::before,
152
144
  .toc ol li.alert-item.warning a:hover::before {
153
- // fg2-color
154
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'><polygon points='12,2 22,20 2,20' fill='none' stroke='hsl(20deg 6% 60%)' stroke-width='2' stroke-linejoin='round'/><line x1='12' y1='9' x2='12' y2='13' stroke='hsl(20deg 6% 60%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='16' x2='12' y2='16' stroke='hsl(20deg 6% 60%)' stroke-width='2' stroke-linecap='round'/></svg>");
155
- }
156
- }
157
-
158
- @media (hover: hover) and (prefers-color-scheme: dark) {
159
- .toc ol li.alert-item.warning:hover a::before,
160
- .toc ol li.alert-item.warning a:hover::before {
161
- // fg2-color
162
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'><polygon points='12,2 22,20 2,20' fill='none' stroke='hsl(20deg 6% 55%)' stroke-width='2' stroke-linejoin='round'/><line x1='12' y1='9' x2='12' y2='13' stroke='hsl(20deg 6% 55%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='16' x2='12' y2='16' stroke='hsl(20deg 6% 55%)' stroke-width='2' stroke-linecap='round'/></svg>");
145
+ content: var(--icon-warning-sm-hover);
163
146
  }
164
147
  }
165
148
 
166
149
  .toc ol li.alert-item.note a::before {
167
- // fg-color
168
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'><circle cx='12' cy='12' r='10' fill='none' stroke='hsl(20deg 8% 8%)' stroke-width='2'/><line x1='12' y1='10' x2='12' y2='16' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='7' x2='12' y2='7' stroke='hsl(20deg 8% 8%)' stroke-width='2' stroke-linecap='round'/></svg>");
169
- }
170
-
171
- @media (prefers-color-scheme: dark) {
172
- .toc ol li.alert-item.note a::before {
173
- // fg-color
174
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'><circle cx='12' cy='12' r='10' fill='none' stroke='hsl(20deg 20% 90%)' stroke-width='2'/><line x1='12' y1='10' x2='12' y2='16' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='7' x2='12' y2='7' stroke='hsl(20deg 20% 90%)' stroke-width='2' stroke-linecap='round'/></svg>");
175
- }
150
+ content: var(--icon-note-sm);
176
151
  }
177
152
 
178
153
  @media (hover: hover) {
179
154
  .toc ol li.alert-item.note:hover a::before,
180
155
  .toc ol li.alert-item.note a:hover::before {
181
- // fg2-color
182
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'><circle cx='12' cy='12' r='10' fill='none' stroke='hsl(20deg 6% 60%)' stroke-width='2'/><line x1='12' y1='10' x2='12' y2='16' stroke='hsl(20deg 6% 60%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='7' x2='12' y2='7' stroke='hsl(20deg 6% 60%)' stroke-width='2' stroke-linecap='round'/></svg>");
183
- }
184
- }
185
-
186
- @media (hover: hover) and (prefers-color-scheme: dark) {
187
- .toc ol li.alert-item.note:hover a::before,
188
- .toc ol li.alert-item.note a:hover::before {
189
- // fg2-color
190
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'><circle cx='12' cy='12' r='10' fill='none' stroke='hsl(20deg 6% 55%)' stroke-width='2'/><line x1='12' y1='10' x2='12' y2='16' stroke='hsl(20deg 6% 55%)' stroke-width='2' stroke-linecap='round'/><line x1='12' y1='7' x2='12' y2='7' stroke='hsl(20deg 6% 55%)' stroke-width='2' stroke-linecap='round'/></svg>");
156
+ content: var(--icon-note-sm-hover);
191
157
  }
192
158
  }
193
159
 
package/src/util.ts CHANGED
@@ -1,9 +1,12 @@
1
- export function debounce(fn: Function, time: number) {
1
+ export function debounce<T extends (...args: unknown[]) => void>(
2
+ fn: T,
3
+ time: number,
4
+ ) {
2
5
  let timer: number;
3
- return (...args: any[]) => {
6
+ return (...args: Parameters<T>) => {
4
7
  window.clearTimeout(timer);
5
8
  timer = window.setTimeout(() => {
6
- fn.apply(null, args);
9
+ fn(...args);
7
10
  }, time);
8
11
  };
9
12
  }
@@ -106,8 +109,8 @@ export function formatDuration(ms: number): string {
106
109
 
107
110
  if (absMs < 1000) {
108
111
  // 0.0000ms - 999.99ms
109
- let decimals = absMs < 10 ? 4 : absMs < 100 ? 3 : 2;
110
- let val = roundTo(absMs, decimals);
112
+ const decimals = absMs < 10 ? 4 : absMs < 100 ? 3 : 2;
113
+ const val = roundTo(absMs, decimals);
111
114
  if (val >= 1000) {
112
115
  return sign + formatSecondsFromMs(absMs);
113
116
  }