methanol 0.0.8 → 0.0.10

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.
@@ -2,205 +2,88 @@
2
2
 
3
3
  :root {
4
4
  interpolate-size: allow-keywords;
5
- color-scheme: dark;
6
- --bg: #09090b;
7
- --surface: #0c0c0e;
8
- --surface-muted: #17171a;
9
- --surface-elevated: #1c1c21;
10
- --text: #fafafa;
11
- --muted: #a1a1aa;
12
- --border: #27272a;
13
- --accent: #ffa000;
5
+ color-scheme: light dark;
6
+ --bg: light-dark(#ffffff, #09090b);
7
+ --surface: light-dark(#fafafa, #0c0c0e);
8
+ --surface-muted: light-dark(#f4f4f5, #17171a);
9
+ --surface-elevated: light-dark(#ffffff, #1c1c21);
10
+ --text: light-dark(#09090b, #fafafa);
11
+ --muted: light-dark(#71717a, #a1a1aa);
12
+ --border: light-dark(#e4e4e7, #27272a);
13
+ --accent: light-dark(#ff8f00, #ffa000);
14
14
  --accent-foreground: #ffffff;
15
- --accent-soft: rgba(255, 160, 0, 0.1);
15
+ --accent-soft: light-dark(rgba(255, 143, 0, 0.08), rgba(255, 160, 0, 0.1));
16
16
  --radius: 8px;
17
17
  --sidebar-width: 260px;
18
18
  --toc-width: 240px;
19
19
  --header-height: 0px;
20
- --hover-bg: rgba(255, 255, 255, 0.05);
20
+ --hover-bg: light-dark(rgba(0, 0, 0, 0.04), rgba(255, 255, 255, 0.05));
21
+
22
+ /* Starry Night Syntax Highlighting */
23
+ --color-prettylights-syntax-brackethighlighter-angle: light-dark(#59636e, #9198a1);
24
+ --color-prettylights-syntax-brackethighlighter-unmatched: light-dark(#82071e, #f85149);
25
+ --color-prettylights-syntax-carriage-return-bg: light-dark(#cf222e, #b62324);
26
+ --color-prettylights-syntax-carriage-return-text: light-dark(#f6f8fa, #f0f6fc);
27
+ --color-prettylights-syntax-comment: light-dark(#59636e, #9198a1);
28
+ --color-prettylights-syntax-constant: light-dark(#0550ae, #79c0ff);
29
+ --color-prettylights-syntax-constant-other-reference-link: light-dark(#0a3069, #a5d6ff);
30
+ --color-prettylights-syntax-entity: light-dark(#6639ba, #d2a8ff);
31
+ --color-prettylights-syntax-entity-tag: light-dark(#0550ae, #7ee787);
32
+ --color-prettylights-syntax-invalid-illegal-bg: light-dark(#82071e, #8e1519);
33
+ --color-prettylights-syntax-invalid-illegal-text: light-dark(#f6f8fa, #f0f6fc);
34
+ --color-prettylights-syntax-keyword: light-dark(#cf222e, #ff7b72);
35
+ --color-prettylights-syntax-markup-changed-bg: light-dark(#ffd8b5, #5a1e02);
36
+ --color-prettylights-syntax-markup-changed-text: light-dark(#953800, #ffdfb6);
37
+ --color-prettylights-syntax-markup-deleted-bg: light-dark(#ffebe9, #67060c);
38
+ --color-prettylights-syntax-markup-deleted-text: light-dark(#82071e, #ffdcd7);
39
+ --color-prettylights-syntax-markup-heading: light-dark(#0550ae, #1f6feb);
40
+ --color-prettylights-syntax-markup-ignored-bg: light-dark(#0550ae, #1158c7);
41
+ --color-prettylights-syntax-markup-ignored-text: light-dark(#d1d9e0, #f0f6fc);
42
+ --color-prettylights-syntax-markup-inserted-bg: light-dark(#dafbe1, #033a16);
43
+ --color-prettylights-syntax-markup-inserted-text: light-dark(#116329, #aff5b4);
44
+ --color-prettylights-syntax-markup-list: light-dark(#3b2300, #f2cc60);
45
+ --color-prettylights-syntax-meta-diff-range: light-dark(#8250df, #d2a8ff);
46
+ --color-prettylights-syntax-string: light-dark(#0a3069, #a5d6ff);
47
+ --color-prettylights-syntax-string-regexp: light-dark(#116329, #7ee787);
48
+ --color-prettylights-syntax-sublimelinter-gutter-mark: light-dark(#818b98, #3d444d);
49
+ --color-prettylights-syntax-variable: light-dark(#953800, #ffa657);
50
+ --color-prettylights-syntax-markup-bold: light-dark(#1f2328, #f0f6fc);
51
+ --color-prettylights-syntax-markup-italic: light-dark(#1f2328, #f0f6fc);
52
+ --color-prettylights-syntax-storage-modifier-import: light-dark(#1f2328, #f0f6fc);
21
53
 
22
54
  @media (prefers-color-scheme: light) {
23
- & {
55
+ &:not(.dark) {
24
56
  color-scheme: light;
25
- --bg: #ffffff;
26
- --surface: #fafafa;
27
- --surface-muted: #f4f4f5;
28
- --surface-elevated: #ffffff;
29
- --text: #09090b;
30
- --muted: #71717a;
31
- --border: #e4e4e7;
32
- --accent: #ff8f00;
33
- --accent-foreground: #ffffff;
34
- --accent-soft: rgba(255, 143, 0, 0.08);
35
- --hover-bg: rgba(0, 0, 0, 0.04);
36
57
  }
37
58
  }
38
59
 
39
60
  &.light {
40
61
  color-scheme: light;
41
- --bg: #ffffff;
42
- --surface: #fafafa;
43
- --surface-muted: #f4f4f5;
44
- --surface-elevated: #ffffff;
45
- --text: #09090b;
46
- --muted: #71717a;
47
- --border: #e4e4e7;
48
- --accent: #ff8f00;
49
- --accent-foreground: #ffffff;
50
- --accent-soft: rgba(255, 143, 0, 0.08);
51
- --hover-bg: rgba(0, 0, 0, 0.04);
52
-
53
- /* Starry Night Light Theme */
54
- --color-prettylights-syntax-brackethighlighter-angle: #59636e;
55
- --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;
56
- --color-prettylights-syntax-carriage-return-bg: #cf222e;
57
- --color-prettylights-syntax-carriage-return-text: #f6f8fa;
58
- --color-prettylights-syntax-comment: #59636e;
59
- --color-prettylights-syntax-constant: #0550ae;
60
- --color-prettylights-syntax-constant-other-reference-link: #0a3069;
61
- --color-prettylights-syntax-entity: #6639ba;
62
- --color-prettylights-syntax-entity-tag: #0550ae;
63
- --color-prettylights-syntax-invalid-illegal-bg: #82071e;
64
- --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;
65
- --color-prettylights-syntax-keyword: #cf222e;
66
- --color-prettylights-syntax-markup-changed-bg: #ffd8b5;
67
- --color-prettylights-syntax-markup-changed-text: #953800;
68
- --color-prettylights-syntax-markup-deleted-bg: #ffebe9;
69
- --color-prettylights-syntax-markup-deleted-text: #82071e;
70
- --color-prettylights-syntax-markup-heading: #0550ae;
71
- --color-prettylights-syntax-markup-ignored-bg: #0550ae;
72
- --color-prettylights-syntax-markup-ignored-text: #d1d9e0;
73
- --color-prettylights-syntax-markup-inserted-bg: #dafbe1;
74
- --color-prettylights-syntax-markup-inserted-text: #116329;
75
- --color-prettylights-syntax-markup-list: #3b2300;
76
- --color-prettylights-syntax-meta-diff-range: #8250df;
77
- --color-prettylights-syntax-string: #0a3069;
78
- --color-prettylights-syntax-string-regexp: #116329;
79
- --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98;
80
- --color-prettylights-syntax-variable: #953800;
81
- --color-prettylights-syntax-markup-bold: #1f2328;
82
- --color-prettylights-syntax-markup-italic: #1f2328;
83
- --color-prettylights-syntax-storage-modifier-import: #1f2328;
84
62
  }
85
63
 
86
64
  &.dark {
87
65
  color-scheme: dark;
88
- --bg: #09090b;
89
- --surface: #0c0c0e;
90
- --surface-muted: #17171a;
91
- --surface-elevated: #1c1c21;
92
- --text: #fafafa;
93
- --muted: #a1a1aa;
94
- --border: #27272a;
95
- --accent: #ffa000;
96
- --accent-foreground: #ffffff;
97
- --accent-soft: rgba(255, 160, 0, 0.1);
98
- --radius: 8px;
99
- --hover-bg: rgba(255, 255, 255, 0.05);
100
-
101
- /* Starry Night Dark Theme */
102
- --color-prettylights-syntax-brackethighlighter-angle: #9198a1;
103
- --color-prettylights-syntax-brackethighlighter-unmatched: #f85149;
104
- --color-prettylights-syntax-carriage-return-bg: #b62324;
105
- --color-prettylights-syntax-carriage-return-text: #f0f6fc;
106
- --color-prettylights-syntax-comment: #9198a1;
107
- --color-prettylights-syntax-constant: #79c0ff;
108
- --color-prettylights-syntax-constant-other-reference-link: #a5d6ff;
109
- --color-prettylights-syntax-entity: #d2a8ff;
110
- --color-prettylights-syntax-entity-tag: #7ee787;
111
- --color-prettylights-syntax-invalid-illegal-bg: #8e1519;
112
- --color-prettylights-syntax-invalid-illegal-text: #f0f6fc;
113
- --color-prettylights-syntax-keyword: #ff7b72;
114
- --color-prettylights-syntax-markup-bold: #f0f6fc;
115
- --color-prettylights-syntax-markup-changed-bg: #5a1e02;
116
- --color-prettylights-syntax-markup-changed-text: #ffdfb6;
117
- --color-prettylights-syntax-markup-deleted-bg: #67060c;
118
- --color-prettylights-syntax-markup-deleted-text: #ffdcd7;
119
- --color-prettylights-syntax-markup-heading: #1f6feb;
120
- --color-prettylights-syntax-markup-ignored-bg: #1158c7;
121
- --color-prettylights-syntax-markup-ignored-text: #f0f6fc;
122
- --color-prettylights-syntax-markup-inserted-bg: #033a16;
123
- --color-prettylights-syntax-markup-inserted-text: #aff5b4;
124
- --color-prettylights-syntax-markup-italic: #f0f6fc;
125
- --color-prettylights-syntax-markup-list: #f2cc60;
126
- --color-prettylights-syntax-meta-diff-range: #d2a8ff;
127
- --color-prettylights-syntax-storage-modifier-import: #f0f6fc;
128
- --color-prettylights-syntax-string: #a5d6ff;
129
- --color-prettylights-syntax-string-regexp: #7ee787;
130
- --color-prettylights-syntax-sublimelinter-gutter-mark: #3d444d;
131
- --color-prettylights-syntax-variable: #ffa657;
132
66
  }
133
67
 
134
68
  /* Accent Colors */
135
69
  &.accent-rose {
136
- --accent: #f43f5e;
137
- --accent-soft: rgba(244, 63, 94, 0.15);
138
- @media (prefers-color-scheme: light) {
139
- --accent: #e11d48;
140
- --accent-soft: rgba(225, 29, 72, 0.1);
141
- }
142
- &.light {
143
- --accent: #e11d48;
144
- --accent-soft: rgba(225, 29, 72, 0.1);
145
- }
146
- &.dark {
147
- --accent: #f43f5e;
148
- --accent-soft: rgba(244, 63, 94, 0.15);
149
- }
70
+ --accent: light-dark(#e11d48, #f43f5e);
71
+ --accent-soft: light-dark(rgba(225, 29, 72, 0.1), rgba(244, 63, 94, 0.15));
150
72
  }
151
73
 
152
74
  &.accent-blue {
153
- /* Indigo-Blue */
154
- --accent: #818cf8;
155
- --accent-soft: rgba(129, 140, 248, 0.15);
156
- @media (prefers-color-scheme: light) {
157
- --accent: #4f46e5;
158
- --accent-soft: rgba(79, 70, 229, 0.1);
159
- }
160
- &.light {
161
- --accent: #4f46e5;
162
- --accent-soft: rgba(79, 70, 229, 0.1);
163
- }
164
- &.dark {
165
- --accent: #818cf8;
166
- --accent-soft: rgba(129, 140, 248, 0.15);
167
- }
75
+ --accent: light-dark(#4f46e5, #818cf8);
76
+ --accent-soft: light-dark(rgba(79, 70, 229, 0.1), rgba(129, 140, 248, 0.15));
168
77
  }
169
78
 
170
79
  &.accent-green {
171
- /* Teal-Emerald */
172
- --accent: #2dd4bf;
173
- --accent-soft: rgba(45, 212, 191, 0.15);
174
- @media (prefers-color-scheme: light) {
175
- --accent: #0d9488;
176
- --accent-soft: rgba(13, 148, 136, 0.1);
177
- }
178
- &.light {
179
- --accent: #0d9488;
180
- --accent-soft: rgba(13, 148, 136, 0.1);
181
- }
182
- &.dark {
183
- --accent: #2dd4bf;
184
- --accent-soft: rgba(45, 212, 191, 0.15);
185
- }
80
+ --accent: light-dark(#0d9488, #2dd4bf);
81
+ --accent-soft: light-dark(rgba(13, 148, 136, 0.1), rgba(45, 212, 191, 0.15));
186
82
  }
187
83
 
188
84
  &.accent-purple {
189
- /* Violet */
190
- --accent: #a78bfa;
191
- --accent-soft: rgba(167, 139, 250, 0.15);
192
- @media (prefers-color-scheme: light) {
193
- --accent: #7c3aed;
194
- --accent-soft: rgba(124, 58, 237, 0.1);
195
- }
196
- &.light {
197
- --accent: #7c3aed;
198
- --accent-soft: rgba(124, 58, 237, 0.1);
199
- }
200
- &.dark {
201
- --accent: #a78bfa;
202
- --accent-soft: rgba(167, 139, 250, 0.15);
203
- }
85
+ --accent: light-dark(#7c3aed, #a78bfa);
86
+ --accent-soft: light-dark(rgba(124, 58, 237, 0.1), rgba(167, 139, 250, 0.15));
204
87
  }
205
88
  }
206
89
 
@@ -1190,6 +1073,13 @@ a {
1190
1073
  margin-bottom: 1rem;
1191
1074
  }
1192
1075
 
1076
+ img {
1077
+ max-width: 100%;
1078
+ height: auto;
1079
+ border-radius: var(--radius);
1080
+ margin: 1rem 0;
1081
+ }
1082
+
1193
1083
  p {
1194
1084
  color: var(--muted);
1195
1085
  margin-bottom: 1.25rem;
@@ -1735,6 +1625,47 @@ a {
1735
1625
  justify-content: flex-end;
1736
1626
  }
1737
1627
 
1628
+ /* --- Tables (GFM) --- */
1629
+
1630
+ .main-content table {
1631
+ width: 100%;
1632
+ border-collapse: collapse;
1633
+ margin: 1.5rem 0;
1634
+ font-size: 0.95rem;
1635
+ overflow-x: auto;
1636
+ display: block; /* Enables horizontal scroll for large tables */
1637
+ }
1638
+
1639
+ .main-content table thead tr {
1640
+ border-bottom: 2px solid var(--border);
1641
+ }
1642
+
1643
+ .main-content table th {
1644
+ text-align: left;
1645
+ padding: 0.75rem 1rem;
1646
+ font-weight: 600;
1647
+ color: var(--text);
1648
+ white-space: nowrap;
1649
+ }
1650
+
1651
+ .main-content table tbody tr {
1652
+ border-bottom: 1px solid var(--border);
1653
+ transition: background-color 0.1s ease;
1654
+ }
1655
+
1656
+ .main-content table tbody tr:last-child {
1657
+ border-bottom: none;
1658
+ }
1659
+
1660
+ .main-content table td {
1661
+ padding: 0.75rem 1rem;
1662
+ color: var(--muted);
1663
+ }
1664
+
1665
+ .main-content table tbody tr:hover {
1666
+ background-color: var(--hover-bg);
1667
+ }
1668
+
1738
1669
  /* --- View Transitions --- */
1739
1670
 
1740
1671
  @view-transition {
@@ -1747,3 +1678,151 @@ a {
1747
1678
  view-transition-name: active-sidebar-bg;
1748
1679
  contain: layout paint;
1749
1680
  }
1681
+
1682
+ /* --- Print Styles --- */
1683
+
1684
+ @media print {
1685
+ :root {
1686
+ --bg: #ffffff;
1687
+ --surface: #ffffff;
1688
+ --surface-muted: #f4f4f5;
1689
+ --surface-elevated: #ffffff;
1690
+ --text: #09090b;
1691
+ --muted: #52525b;
1692
+ --border: #e4e4e7;
1693
+ --accent: #000000;
1694
+ --accent-soft: #f4f4f5;
1695
+ --hover-bg: transparent;
1696
+ }
1697
+
1698
+ body {
1699
+ background-color: white !important;
1700
+ background-image: none !important;
1701
+ color: black !important;
1702
+ width: 100% !important;
1703
+ margin: 0 !important;
1704
+ padding: 0 !important;
1705
+ overflow: visible !important;
1706
+ }
1707
+
1708
+ /* Hide UI Elements */
1709
+ .sidebar,
1710
+ .toc-panel,
1711
+ .nav-toggle-label,
1712
+ .toc-toggle-label,
1713
+ .search-toggle-label,
1714
+ .search-modal,
1715
+ .page-nav,
1716
+ .copy-btn,
1717
+ .heading-anchor,
1718
+ .theme-switch-wrapper,
1719
+ .lang-switch-wrapper,
1720
+ .page-meta {
1721
+ display: none !important;
1722
+ }
1723
+
1724
+ /* Layout Overrides */
1725
+ .layout-container,
1726
+ .layout-container.no-toc {
1727
+ display: block !important;
1728
+ max-width: none !important;
1729
+ width: 100% !important;
1730
+ margin: 0 !important;
1731
+ padding: 0 !important;
1732
+ }
1733
+
1734
+ .main-content {
1735
+ padding: 0 !important;
1736
+ width: 100% !important;
1737
+ max-width: none !important;
1738
+ }
1739
+
1740
+ /* Typography & Content */
1741
+ body {
1742
+ font-size: 11pt !important;
1743
+ line-height: 1.5 !important;
1744
+ }
1745
+
1746
+ .main-content {
1747
+ h1 {
1748
+ font-size: 24pt !important;
1749
+ margin-bottom: 1rem !important;
1750
+ }
1751
+
1752
+ h2 {
1753
+ font-size: 18pt !important;
1754
+ margin-top: 1.5rem !important;
1755
+ margin-bottom: 0.75rem !important;
1756
+ }
1757
+
1758
+ h3 {
1759
+ font-size: 14pt !important;
1760
+ margin-top: 1.25rem !important;
1761
+ margin-bottom: 0.5rem !important;
1762
+ }
1763
+
1764
+ p, li {
1765
+ font-size: 11pt !important;
1766
+ margin-bottom: 0.75rem !important;
1767
+ }
1768
+
1769
+ pre, code {
1770
+ font-size: 10pt !important;
1771
+ }
1772
+ }
1773
+
1774
+ h1, h2, h3, h4, h5, h6 {
1775
+ color: black !important;
1776
+ page-break-after: avoid;
1777
+ break-after: avoid;
1778
+ }
1779
+
1780
+ h2 {
1781
+ border-bottom: 1px solid #000 !important;
1782
+ }
1783
+
1784
+ p, li {
1785
+ orphans: 3;
1786
+ widows: 3;
1787
+ }
1788
+
1789
+ a {
1790
+ text-decoration: underline !important;
1791
+ color: black !important;
1792
+ }
1793
+
1794
+ /* Expand external links */
1795
+ a[href^="http"]::after {
1796
+ content: " (" attr(href) ")";
1797
+ font-size: 0.85em;
1798
+ color: #555;
1799
+ }
1800
+
1801
+ /* Clean up code blocks */
1802
+ pre {
1803
+ border: 1px solid #ccc !important;
1804
+ white-space: pre-wrap !important;
1805
+ break-inside: avoid;
1806
+ background: #fafafa !important;
1807
+ }
1808
+
1809
+ /* Blockquotes */
1810
+ blockquote {
1811
+ border-left: 3px solid #ccc !important;
1812
+ background: transparent !important;
1813
+ color: #333 !important;
1814
+ break-inside: avoid;
1815
+ }
1816
+
1817
+ /* Tables */
1818
+ table {
1819
+ break-inside: avoid;
1820
+ }
1821
+
1822
+ /* Page Setup */
1823
+ @page {
1824
+ margin: 2cm;
1825
+ size: auto;
1826
+ }
1827
+ }
1828
+
@@ -0,0 +1,112 @@
1
+ /* Copyright Yukino Song, SudoMaker Ltd.
2
+ *
3
+ * Licensed to the Apache Software Foundation (ASF) under one
4
+ * or more contributor license agreements. See the NOTICE file
5
+ * distributed with this work for additional information
6
+ * regarding copyright ownership. The ASF licenses this file
7
+ * to you under the Apache License, Version 2.0 (the
8
+ * "License"); you may not use this file except in compliance
9
+ * with the License. You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing,
14
+ * software distributed under the License is distributed on an
15
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ * KIND, either express or implied. See the License for the
17
+ * specific language governing permissions and limitations
18
+ * under the License.
19
+ */
20
+
21
+ import { If, For, $, signal, onCondition, read, extract } from 'refui'
22
+ import NullProtoObj from 'null-prototype-object'
23
+ import { HTMLRenderer } from 'methanol'
24
+
25
+ const navEntryMap = new Map()
26
+
27
+ const currentPath = signal('')
28
+ const matchCurrentPath = onCondition(currentPath)
29
+
30
+ const toSignal = (i) => {
31
+ const clone = Object.assign(new NullProtoObj(), i)
32
+
33
+ let sig = navEntryMap.get(clone.path)
34
+ if (!sig) {
35
+ sig = signal(clone)
36
+ navEntryMap.set(clone.path, sig)
37
+ } else {
38
+ sig.value = clone
39
+ }
40
+
41
+ if (clone.type === 'directory') {
42
+ clone.children = clone.children.map(toSignal)
43
+ }
44
+
45
+ return sig
46
+ }
47
+
48
+ const NavTree = ({ nodes, depth }) => (
49
+ <For entries={nodes}>
50
+ {({ item }) => {
51
+ const node = read(item)
52
+ const { routeHref: href, routePath, type, name, isRoot } = node
53
+ const { title } = extract(item, 'title')
54
+
55
+ const isActive = matchCurrentPath(routePath)
56
+
57
+ if (type === 'directory') {
58
+ const label = title.or(name)
59
+ const { children } = extract(item, 'children')
60
+
61
+ const isOpen = $(() => {
62
+ if (depth < 1) {
63
+ return true
64
+ }
65
+ const _active = isActive.value
66
+ const _currentPath = currentPath.value
67
+ return _active || _currentPath.startsWith(routePath)
68
+ })
69
+
70
+ const header = href ? (
71
+ <a class={isActive.choose('nav-dir-link active', 'nav-dir-link')} href={href}>
72
+ {label}
73
+ </a>
74
+ ) : (
75
+ <span class="nav-dir-label">{label}</span>
76
+ )
77
+
78
+ return (
79
+ <li class={isActive.choose('is-active', null)}>
80
+ <details class="sidebar-collapsible" open={isOpen.choose(true, null)}>
81
+ <summary class="sb-dir-header">{header}</summary>
82
+ <If condition={() => children.value.length}>{() => (
83
+ <ul data-depth={depth + 1}>
84
+ <NavTree nodes={children} depth={depth + 1} />
85
+ </ul>
86
+ )}
87
+ </If>
88
+ </details>
89
+ </li>
90
+ )
91
+ } else {
92
+ const label = title.or(node.isIndex ? 'Home' : name)
93
+ return (
94
+ <li>
95
+ <a class={isActive.choose('active', null)} href={href}>
96
+ {label}
97
+ </a>
98
+ </li>
99
+ )
100
+ }
101
+ }}
102
+ </For>
103
+ )
104
+
105
+ const rootNodes = signal()
106
+ const rootTree = HTMLRenderer.createElement(NavTree, { nodes: rootNodes, depth: 0 })
107
+
108
+ export const renderNavTree = (nodes, path) => {
109
+ currentPath.value = path
110
+ rootNodes.value = nodes.map(toSignal)
111
+ return rootTree
112
+ }
@@ -18,68 +18,22 @@
18
18
  * under the License.
19
19
  */
20
20
 
21
- import { HTMLRenderer as R } from 'methanol'
22
- import { renderToc } from './components/ThemeToCContainer.static.jsx'
21
+ import { HTMLRenderer as R, DOCTYPE_HTML } from 'methanol'
22
+ import { renderToc } from '../components/ThemeToCContainer.static.jsx'
23
+ import { renderNavTree } from './nav-tree.jsx'
23
24
 
24
- const DOCHTML = R.rawHTML`<!DOCTYPE html>`
25
-
26
- const renderPageTree = (nodes = [], currentRoute, depth = 0) => {
27
- const items = []
28
- let hasActive = false
29
- for (const node of nodes) {
30
- const nodeRoute = node.routeHref || ''
31
- if (node.type === 'directory') {
32
- const label = node.title || node.name
33
- const isActive = nodeRoute === currentRoute
34
- const href = node.routeHref
35
- const childResult = renderPageTree(node.children || [], currentRoute, depth + 1)
36
- const isOpen = depth < 1 || isActive || childResult.hasActive
37
- if (isOpen) hasActive = true
38
- const header = href ? (
39
- <a class={isActive ? 'nav-dir-link active' : 'nav-dir-link'} href={href}>
40
- {label}
41
- </a>
42
- ) : (
43
- <span class="nav-dir-label">{label}</span>
44
- )
45
- items.push(
46
- <li class={isActive ? 'is-active' : null}>
47
- <details class="sidebar-collapsible" open={isOpen ? true : null}>
48
- <summary class="sb-dir-header">{header}</summary>
49
- {childResult.items.length ? <ul data-depth={depth + 1}>{childResult.items}</ul> : null}
50
- </details>
51
- </li>
52
- )
53
- continue
54
- }
55
- const label = node.title || (node.isIndex ? 'Home' : node.name)
56
- const isActive = nodeRoute === currentRoute
57
- if (isActive) hasActive = true
58
- const href = node.routeHref
59
- items.push(
60
- <li>
61
- <a class={isActive ? 'active' : null} href={href}>
62
- {label}
63
- </a>
64
- </li>
65
- )
66
- }
67
- return { items, hasActive }
68
- }
69
-
70
- const PAGE_TEMPLATE = ({ PageContent, ExtraHead, components, ctx }) => {
25
+ const PAGE_TEMPLATE = async ({ PageContent, ExtraHead, components, ctx }) => {
71
26
  const page = ctx.page
72
27
  const pagesByRoute = ctx.pagesByRoute
73
28
  const pages = ctx.pages || []
74
29
  const pagesTree = ctx.pagesTree || []
75
30
  const siteName = ctx.site.name || 'Methanol Site'
76
31
  const title = page.title || siteName
77
- const currentRoute = page.routeHref || ''
78
- const baseHref = page.routeHref === '/404' ? ctx.site.base || '/' : null
32
+ const baseHref =
33
+ page.routeHref === '/404' || page.routeHref === '/offline' ? ctx.site.base || '/' : null
79
34
  const toc = page.toc?.length ? renderToc(page.toc) : null
80
35
  const hasToc = Boolean(toc)
81
36
  const layoutClass = hasToc ? 'layout-container' : 'layout-container no-toc'
82
- const tree = renderPageTree(pagesTree, currentRoute, 0)
83
37
  const { ThemeSearchBox, ThemeColorSwitch, ThemeAccentSwitch, ThemeToCContainer } = components
84
38
  const rootPage = pagesByRoute.get('/') || pages.find((entry) => entry.routeHref === '/')
85
39
  const pageFrontmatter = page.frontmatter || {}
@@ -146,9 +100,10 @@ const PAGE_TEMPLATE = ({ PageContent, ExtraHead, components, ctx }) => {
146
100
  </div>
147
101
  </div>
148
102
  ) : null
103
+
149
104
  return (
150
105
  <>
151
- {DOCHTML}
106
+ {DOCTYPE_HTML}
152
107
  <html lang={htmlLang}>
153
108
  <head>
154
109
  <meta charset="UTF-8" />
@@ -244,7 +199,7 @@ const PAGE_TEMPLATE = ({ PageContent, ExtraHead, components, ctx }) => {
244
199
  {pagefindEnabled ? <ThemeSearchBox options={pagefindOptions} /> : null}
245
200
  </div>
246
201
  <nav>
247
- <ul data-depth="0">{tree.items}</ul>
202
+ <ul data-depth="0">{renderNavTree(pagesTree, page.routePath)}</ul>
248
203
  </nav>
249
204
  <div class="sidebar-footer">
250
205
  {languageSelector}
@@ -294,7 +249,7 @@ const PAGE_TEMPLATE = ({ PageContent, ExtraHead, components, ctx }) => {
294
249
  <span style="margin: 0 0.5rem; opacity: 0.5;">•</span>
295
250
  </>
296
251
  ) : null}
297
- Updated: {page.updatedAt || '-'}
252
+ Updated: {page.stats.updatedAt || '-'}
298
253
  </div>
299
254
  <div class="page-meta-item">
300
255
  Powered by{' '}
File without changes