@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
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@abreen/tada",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
+ "type": "module",
4
5
  "description": "A static site generator",
6
+ "license": "MIT",
5
7
  "bin": {
6
- "tada": "bin/tada.js"
8
+ "tada": "bin/tada.ts"
7
9
  },
8
10
  "files": [
9
11
  "bin/",
10
- "webpack/",
12
+ "build/",
11
13
  "src/",
12
14
  "templates/",
13
15
  "fonts/",
@@ -18,20 +20,20 @@
18
20
  "tsconfig.json"
19
21
  ],
20
22
  "scripts": {
21
- "format": "bunx prettier --write \"**/*.(t|j)s\" \"**/*.scss\" \"**/*.json\"",
22
- "init-example": "bun run bin/tada.js init example --default"
23
+ "prepare": "husky",
24
+ "init-example": "bun run bin/tada.ts init example --default",
25
+ "lint": "eslint src/ build/ bin/",
26
+ "typecheck": "tsc --noEmit",
27
+ "test:functional": "python3 -m pip install -q -r functional_tests/requirements.txt && python3 -m pytest functional_tests/ -v -n auto"
23
28
  },
24
29
  "engines": {
25
30
  "bun": ">=1.0.0"
26
31
  },
27
32
  "dependencies": {
28
- "@babel/core": "^7.26.10",
29
- "@babel/preset-env": "^7.26.9",
30
33
  "@tsconfig/node23": "^23.0.2",
31
34
  "ajv": "^8.17.1",
32
- "babel-loader": "^10.0.0",
33
- "copy-webpack-plugin": "^13.0.1",
34
- "css-loader": "^7.1.2",
35
+ "chokidar": "^4.0.0",
36
+ "culori": "^4.0.2",
35
37
  "fontkit": "^2.0.4",
36
38
  "front-matter": "^4.0.2",
37
39
  "java-parser": "^3.0.1",
@@ -42,29 +44,36 @@
42
44
  "markdown-it-container": "^4.0.0",
43
45
  "markdown-it-deflist": "^3.0.0",
44
46
  "markdown-it-footnote": "^4.0.0",
45
- "mini-css-extract-plugin": "^2.9.4",
46
47
  "pagefind": "^1.4.0",
47
48
  "png-to-ico": "^3.0.1",
48
49
  "quote-quote": "^1.2.0",
49
50
  "sass": "^1.91.0",
50
- "sass-loader": "^16.0.5",
51
51
  "sharp": "^0.34.5",
52
52
  "shiki": "^4.0.1",
53
53
  "string-strip-html": "^8.5.0",
54
- "terser-webpack-plugin": "^5.3.14",
55
- "ts-loader": "^9.5.2",
56
- "typescript": "^5.4.5",
57
- "wawoff2": "^2.0.1",
58
- "webpack": "^5.99.6",
59
- "webpack-cli": "^6.0.1",
60
54
  "ws": "^8.18.0"
61
55
  },
56
+ "lint-staged": {
57
+ "*.{ts,js}": "prettier --write",
58
+ "*.scss": "prettier --write",
59
+ "*.json": "prettier --write"
60
+ },
62
61
  "devDependencies": {
62
+ "@eslint/js": "^10.0.1",
63
63
  "@playwright/test": "^1.43.0",
64
64
  "@types/bun": "^1.3.10",
65
+ "@types/culori": "^4.0.1",
65
66
  "@types/fontkit": "^2.0.8",
67
+ "@types/lodash": "^4.17.24",
68
+ "@types/markdown-it-container": "^4.0.0",
69
+ "@types/ws": "^8.18.1",
70
+ "eslint": "^10.0.3",
71
+ "husky": "^9.1.7",
72
+ "lint-staged": "^16.4.0",
66
73
  "prettier": "^3.6.2",
67
74
  "prettier-plugin-curly": "^0.4.1",
68
- "rimraf": "^6.1.3"
75
+ "rimraf": "^6.1.3",
76
+ "typescript": "^5.4.5",
77
+ "typescript-eslint": "^8.57.1"
69
78
  }
70
79
  }
@@ -0,0 +1,92 @@
1
+ @use 'mixins' as *;
2
+
3
+ .alert {
4
+ border: 3px solid var(--bg2-color);
5
+ position: relative;
6
+ margin: 1rem 0;
7
+ }
8
+
9
+ .alert.warning {
10
+ background: var(--warning-bg-color);
11
+ border-color: var(--warning-bg-color);
12
+ }
13
+
14
+ .alert.note {
15
+ background: var(--note-bg-color);
16
+ border-color: var(--note-bg-color);
17
+ }
18
+
19
+ .alert .title {
20
+ padding: 10px 6px;
21
+ }
22
+
23
+ .alert .content {
24
+ padding: 12px;
25
+
26
+ .styled-list {
27
+ color: var(--fg-color);
28
+ }
29
+
30
+ tt,
31
+ code {
32
+ background: inherit;
33
+ padding: inherit;
34
+ }
35
+
36
+ time[datetime].is-modified {
37
+ // Reset the underline color
38
+ text-decoration: underline dotted;
39
+ }
40
+
41
+ a {
42
+ text-decoration-color: var(--fg-color);
43
+ }
44
+
45
+ dfn {
46
+ color: inherit;
47
+ }
48
+ }
49
+
50
+ .alert .content > *:first-child {
51
+ margin-top: 0;
52
+ }
53
+
54
+ .alert .content > *:last-child {
55
+ margin-bottom: 0;
56
+ }
57
+
58
+ .alert .title::before {
59
+ left: 8px;
60
+ top: 8px;
61
+ position: absolute;
62
+ width: 32px;
63
+ height: 32px;
64
+ }
65
+
66
+ .alert.warning .title::before {
67
+ content: var(--icon-warning);
68
+ }
69
+
70
+ i.warning {
71
+ background: var(--icon-warning);
72
+ background-size: contain;
73
+ display: inline-block;
74
+ height: 1em;
75
+ width: 1em;
76
+ vertical-align: sub;
77
+ }
78
+
79
+ .alert.note .title::before {
80
+ content: var(--icon-note);
81
+ }
82
+
83
+ .alert .title {
84
+ font-weight: 700;
85
+ @include user-select(none);
86
+ padding-left: 48px;
87
+ margin: 0;
88
+ }
89
+
90
+ .alert > p:last-child {
91
+ margin-bottom: 0;
92
+ }
package/src/_base.scss ADDED
@@ -0,0 +1,106 @@
1
+ :root {
2
+ --box-border-width: 5px;
3
+
4
+ --gap: 12px;
5
+ --border-radius: 12px;
6
+ --control-border-width: 2px;
7
+ --label-border-width: 2px;
8
+ --focus-border-width: 3px;
9
+ --table-padding: 12px;
10
+ --details-padding: 12px;
11
+ --section-padding: 64px;
12
+
13
+ --main-width: 900px;
14
+ }
15
+
16
+ p {
17
+ margin: 0 0 1rem 0;
18
+ }
19
+
20
+ h1,
21
+ h2,
22
+ h3,
23
+ h4,
24
+ h5,
25
+ h6 {
26
+ font-family: var(--heading-font);
27
+ -webkit-break-after: avoid;
28
+ break-after: avoid;
29
+ line-height: 1.3;
30
+
31
+ /*
32
+ * Enable Inter's features:
33
+ * ss03 - round quotes & commas
34
+ * ss04 - disambiguation (make uppercase i and lowercase L distinct)
35
+ * dlig - discretionary ligatures (for style)
36
+ */
37
+ font-feature-settings: 'ss03', 'ss04', 'dlig';
38
+ }
39
+
40
+ h1 {
41
+ font-size: 250%;
42
+ font-weight: 700;
43
+ }
44
+
45
+ body {
46
+ color: var(--fg-color);
47
+ background-color: var(--bg-color);
48
+
49
+ font-family: var(--font);
50
+ font-size: var(--font-size);
51
+ font-weight: var(--font-weight);
52
+ line-height: var(--line-height);
53
+
54
+ /*
55
+ * Enable Inter's features for legibility:
56
+ * ss03 - round quotes & commas
57
+ * ss04 - disambiguation (make uppercase i and lowercase L distinct)
58
+ */
59
+ font-feature-settings: 'ss03', 'ss04';
60
+
61
+ @media (prefers-color-scheme: dark) {
62
+ & {
63
+ text-rendering: optimizeLegibility;
64
+ -webkit-font-smoothing: antialiased;
65
+ }
66
+ }
67
+ }
68
+
69
+ html {
70
+ overscroll-behavior: none;
71
+ background: var(--bg-color);
72
+ }
73
+
74
+ a {
75
+ color: var(--fg-color);
76
+ text-decoration-color: var(--fg2-color);
77
+ text-decoration-thickness: 1px;
78
+ text-underline-offset: 3px;
79
+ }
80
+
81
+ pre,
82
+ tt,
83
+ code {
84
+ font-family: var(--mono-font);
85
+ }
86
+
87
+ tt,
88
+ code {
89
+ font-size: var(--mono-font-size);
90
+ background: var(--bg2-color);
91
+ border-radius: var(--mono-border-radius);
92
+ padding: 0.12em 0.25em;
93
+ overflow-wrap: anywhere;
94
+ }
95
+
96
+ pre {
97
+ background: var(--bg2-color);
98
+ border-radius: var(--mono-border-radius);
99
+ line-height: var(--mono-line-height);
100
+ overflow: auto;
101
+ padding: var(--gap);
102
+
103
+ code {
104
+ padding: 0;
105
+ }
106
+ }
@@ -1,5 +1,3 @@
1
- @import './_mixins.scss';
2
-
3
1
  :root {
4
2
  --toc-width: 260px;
5
3
  }
@@ -1,5 +1,3 @@
1
- @import '../_mixins.scss';
2
-
3
1
  .heading-anchor {
4
2
  position: relative;
5
3
  display: inline-block;
@@ -8,7 +6,7 @@
8
6
  }
9
7
 
10
8
  .heading-anchor::after {
11
- content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="hsl(20 8% 8%)" fill-rule="evenodd" clip-rule="evenodd" d="M10.975 14.51a1.05 1.05 0 0 0 0-1.485 2.95 2.95 0 0 1 0-4.172l3.536-3.535a2.95 2.95 0 1 1 4.172 4.172l-1.093 1.092a1.05 1.05 0 0 0 1.485 1.485l1.093-1.092a5.05 5.05 0 0 0-7.142-7.142L9.49 7.368a5.05 5.05 0 0 0 0 7.142c.41.41 1.075.41 1.485 0zm2.05-5.02a1.05 1.05 0 0 0 0 1.485 2.95 2.95 0 0 1 0 4.172l-3.5 3.5a2.95 2.95 0 1 1-4.171-4.172l1.025-1.025a1.05 1.05 0 0 0-1.485-1.485L3.87 12.99a5.05 5.05 0 0 0 7.142 7.142l3.5-3.5a5.05 5.05 0 0 0 0-7.142 1.05 1.05 0 0 0-1.485 0z"/></svg>');
9
+ content: var(--icon-anchor);
12
10
  display: inline-block;
13
11
  height: 0.75em;
14
12
  width: 0.75em;
@@ -16,12 +14,6 @@
16
14
  opacity: 0;
17
15
  }
18
16
 
19
- @media (prefers-color-scheme: dark) {
20
- .heading-anchor::after {
21
- content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="hsl(20 20% 90%)" fill-rule="evenodd" clip-rule="evenodd" d="M10.975 14.51a1.05 1.05 0 0 0 0-1.485 2.95 2.95 0 0 1 0-4.172l3.536-3.535a2.95 2.95 0 1 1 4.172 4.172l-1.093 1.092a1.05 1.05 0 0 0 1.485 1.485l1.093-1.092a5.05 5.05 0 0 0-7.142-7.142L9.49 7.368a5.05 5.05 0 0 0 0 7.142c.41.41 1.075.41 1.485 0zm2.05-5.02a1.05 1.05 0 0 0 0 1.485 2.95 2.95 0 0 1 0 4.172l-3.5 3.5a2.95 2.95 0 1 1-4.171-4.172l1.025-1.025a1.05 1.05 0 0 0-1.485-1.485L3.87 12.99a5.05 5.05 0 0 0 7.142 7.142l3.5-3.5a5.05 5.05 0 0 0 0-7.142 1.05 1.05 0 0 0-1.485 0z"/></svg>');
22
- }
23
- }
24
-
25
17
  .heading-anchor:focus::after,
26
18
  .heading-anchor:focus-visible::after {
27
19
  opacity: 1;
package/src/code/index.ts CHANGED
@@ -60,15 +60,15 @@ export default async function mount(window: Window): Promise<void> {
60
60
  downloadLink.addEventListener('click', async (e: MouseEvent) => {
61
61
  e.preventDefault();
62
62
  try {
63
- const handle = await (window as any).showSaveFilePicker({
63
+ const handle = await window.showSaveFilePicker!({
64
64
  suggestedName: downloadLink.download,
65
65
  });
66
66
  const response = await fetch(downloadLink.href);
67
67
  const writable = await handle.createWritable();
68
68
  await writable.write(await response.blob());
69
69
  await writable.close();
70
- } catch (err: any) {
71
- if (err.name !== 'AbortError') {
70
+ } catch (err: unknown) {
71
+ if (err instanceof Error && err.name !== 'AbortError') {
72
72
  throw err;
73
73
  }
74
74
  }
package/src/code.scss CHANGED
@@ -1,4 +1,4 @@
1
- @import './_mixins.scss';
1
+ @use 'mixins' as *;
2
2
 
3
3
  body.code,
4
4
  body.literate {
@@ -0,0 +1,5 @@
1
+ @use 'config/theme';
2
+ @use 'base';
3
+ @use 'layout';
4
+ @use 'alerts';
5
+ @use 'header/base' as *;
@@ -0,0 +1,129 @@
1
+ :root {
2
+ --header-collapsed-height: 45px;
3
+ }
4
+
5
+ header {
6
+ backdrop-filter: var(--backdrop-filter);
7
+ background: var(--bg-color-translucent);
8
+
9
+ width: 100%;
10
+ position: fixed;
11
+ top: 0;
12
+
13
+ z-index: 1000;
14
+
15
+ display: grid;
16
+ grid-template-columns: 1fr;
17
+
18
+ view-transition-name: site-header;
19
+ }
20
+
21
+ header details summary {
22
+ display: flex;
23
+ align-items: center;
24
+ height: var(--header-collapsed-height);
25
+ padding: 0;
26
+ list-style-type: none;
27
+ cursor: pointer;
28
+ position: relative;
29
+ container-type: inline-size;
30
+
31
+ @media (hover: hover) {
32
+ &:hover {
33
+ color: inherit;
34
+ }
35
+ }
36
+
37
+ &:focus-visible {
38
+ outline-offset: -2px;
39
+ }
40
+ }
41
+
42
+ header details summary::-webkit-details-marker {
43
+ display: none;
44
+ }
45
+
46
+ header details summary::marker {
47
+ content: '';
48
+ }
49
+
50
+ header summary::after {
51
+ order: -1;
52
+ height: 24px;
53
+ content: var(--icon-chevron);
54
+ margin-left: var(--gap);
55
+ margin-right: 8px;
56
+ }
57
+
58
+ header details[open] summary::after {
59
+ transform: rotate(90deg);
60
+ }
61
+
62
+ header .content {
63
+ position: relative;
64
+ }
65
+
66
+ header summary .logo {
67
+ flex: 0 0 auto;
68
+ color: var(--text-on-theme);
69
+ background: var(--theme-color);
70
+ padding: 1px 6px;
71
+ margin: 0 8px 0 0;
72
+ font-size: var(--font-size-smaller);
73
+ font-weight: 600;
74
+ pointer-events: none;
75
+ }
76
+
77
+ header summary .site-title {
78
+ flex: 1 1 0;
79
+ overflow: hidden;
80
+ text-overflow: ellipsis;
81
+ white-space: nowrap;
82
+ min-width: 0;
83
+ font-weight: 500;
84
+ pointer-events: none;
85
+ margin: 0 8px 0 0;
86
+ }
87
+
88
+ @container (max-width: 520px) {
89
+ header summary .site-title {
90
+ display: none;
91
+ }
92
+ }
93
+
94
+ header summary .to-top-container {
95
+ display: none;
96
+ align-items: center;
97
+ height: var(--header-collapsed-height);
98
+ pointer-events: none;
99
+ white-space: nowrap;
100
+
101
+ &:has(.is-visible) {
102
+ display: flex;
103
+ pointer-events: auto;
104
+ }
105
+ }
106
+
107
+ // Hide until the full stylesheet loads (prevents FOUC where the container
108
+ // is visible as a block element before it gets position: absolute)
109
+ header .results-container {
110
+ display: none;
111
+ }
112
+
113
+ header summary .search-controls {
114
+ margin-left: auto;
115
+ pointer-events: auto;
116
+ display: flex;
117
+ align-items: center;
118
+ height: var(--header-collapsed-height);
119
+ padding: 0 var(--gap);
120
+ min-width: 0;
121
+
122
+ input.search {
123
+ width: 180px;
124
+
125
+ @container (max-width: 280px) {
126
+ display: none;
127
+ }
128
+ }
129
+ }
@@ -1,45 +1,5 @@
1
- @import '../_mixins.scss';
2
-
3
- :root {
4
- --header-collapsed-height: 45px;
5
- }
6
-
7
- header {
8
- backdrop-filter: var(--backdrop-filter);
9
- background: var(--bg-color-translucent);
10
-
11
- width: 100%;
12
- position: fixed;
13
- top: 0;
14
-
15
- z-index: 1000;
16
-
17
- display: grid;
18
- grid-template-columns: 1fr;
19
-
20
- view-transition-name: site-header;
21
- }
22
-
23
- header details summary {
24
- display: flex;
25
- align-items: center;
26
- height: var(--header-collapsed-height);
27
- padding: 0;
28
- list-style-type: none;
29
- cursor: pointer;
30
- position: relative;
31
- container-type: inline-size;
32
-
33
- @media (hover: hover) {
34
- &:hover {
35
- color: inherit;
36
- }
37
- }
38
-
39
- &:focus-visible {
40
- outline-offset: -2px;
41
- }
42
- }
1
+ @use '../mixins' as *;
2
+ @use 'base';
43
3
 
44
4
  header nav {
45
5
  display: flex;
@@ -99,28 +59,6 @@ header nav div > p {
99
59
  padding-bottom: 2px;
100
60
  }
101
61
 
102
- header details summary::-webkit-details-marker {
103
- display: none;
104
- }
105
-
106
- header details summary::marker {
107
- content: '';
108
- }
109
-
110
- header summary::after {
111
- order: -1;
112
- height: 24px;
113
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><polyline points='9 18 15 12 9 6' stroke='hsl(20deg 8% 8%)' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
114
- margin-left: var(--gap);
115
- margin-right: 8px;
116
- }
117
-
118
- @media (prefers-color-scheme: dark) {
119
- header summary::after {
120
- content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><polyline points='9 18 15 12 9 6' stroke='hsl(20deg 20% 90%)' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
121
- }
122
- }
123
-
124
62
  @media (hover: hover) {
125
63
  header details summary:hover:not(:has(.results-container:hover)) {
126
64
  background: var(--bg2-color);
@@ -131,74 +69,8 @@ header summary::after {
131
69
  }
132
70
  }
133
71
 
134
- header details[open] summary::after {
135
- transform: rotate(90deg);
136
- }
137
-
138
- header .content {
139
- position: relative;
140
- }
141
-
142
- header summary .logo {
143
- flex: 0 0 auto;
144
- color: #fff;
145
- background: var(--theme-color);
146
- padding: 1px 6px;
147
- margin: 0 8px 0 0;
148
- font-size: var(--font-size-smaller);
149
- font-weight: 600;
150
- pointer-events: none;
151
- }
152
-
153
- header summary .site-title {
154
- flex: 1 1 0;
155
- overflow: hidden;
156
- text-overflow: ellipsis;
157
- white-space: nowrap;
158
- min-width: 0;
159
- font-weight: 500;
160
- pointer-events: none;
161
- margin: 0 8px 0 0;
162
- }
163
-
164
- @container (max-width: 520px) {
165
- header summary .site-title {
166
- display: none;
167
- }
168
- }
169
-
170
- header summary .to-top-container {
171
- display: none;
172
- align-items: center;
173
- height: var(--header-collapsed-height);
174
- pointer-events: none;
175
- white-space: nowrap;
176
-
177
- &:has(.is-visible) {
178
- display: flex;
179
- pointer-events: auto;
180
- }
181
- }
182
-
183
- header summary .search-controls {
184
- margin-left: auto;
185
- pointer-events: auto;
186
- display: flex;
187
- align-items: center;
188
- height: var(--header-collapsed-height);
189
- padding: 0 var(--gap);
190
- min-width: 0;
191
-
192
- input.search {
193
- width: 180px;
194
-
195
- @container (max-width: 280px) {
196
- display: none;
197
- }
198
- }
199
- }
200
-
201
72
  header .results-container {
73
+ display: block;
202
74
  position: absolute;
203
75
  top: var(--header-collapsed-height);
204
76
  left: 0;
package/src/index.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import './style.scss';
2
- import './layout.scss';
3
2
 
4
3
  import './anchor/style.scss';
5
4
  import './code.scss';
@@ -43,7 +42,7 @@ document.addEventListener('DOMContentLoaded', async () => {
43
42
 
44
43
  const entries = Object.entries(COMPONENTS);
45
44
 
46
- const failed: Record<string, any> = {};
45
+ const failed: Record<string, string> = {};
47
46
 
48
47
  const mountPromises = entries.map(([name, mount]) => {
49
48
  return new Promise<void>((resolve, reject) => {
@@ -1,4 +1,4 @@
1
- @import '../_mixins.scss';
1
+ @use '../mixins' as *;
2
2
 
3
3
  .question {
4
4
  margin-bottom: 2rem;