@abreen/tada 1.11.2 → 1.13.2
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.
- package/README.md +65 -64
- package/bin/tada.ts +61 -66
- package/build/build-manifest.ts +14 -3
- package/build/bundle.ts +0 -1
- package/build/config-files.ts +183 -0
- package/build/config-loader.ts +159 -0
- package/build/copy.ts +0 -83
- package/build/generate-content-assets.ts +75 -160
- package/build/globals.ts +48 -89
- package/build/log.ts +27 -18
- package/build/pagefind.ts +33 -26
- package/build/pipeline.ts +98 -79
- package/build/reachability.ts +51 -248
- package/build/serve.ts +35 -6
- package/build/site-variables.ts +20 -11
- package/build/source-model.ts +400 -0
- package/build/{watch/records.ts → source-records.ts} +111 -49
- package/build/template-globals.ts +91 -0
- package/build/templates.ts +50 -40
- package/build/test-helpers.ts +15 -0
- package/build/toc-plugin.ts +5 -1
- package/build/types.d.ts +9 -1
- package/build/util.ts +8 -0
- package/build/utils/code.ts +6 -16
- package/build/utils/content-files.ts +57 -126
- package/build/utils/final-html.ts +239 -0
- package/build/utils/markdown.ts +237 -17
- package/build/utils/paths.ts +2 -1
- package/build/utils/render.ts +108 -99
- package/build/validate-config-links.ts +91 -14
- package/build/watch/assets.ts +0 -2
- package/build/watch/build-full.ts +14 -15
- package/build/watch/build-incremental.ts +15 -8
- package/build/watch/compiler-types.d.ts +6 -1
- package/build/watch/compiler.ts +27 -15
- package/build/watch/index.ts +2 -7
- package/build/watch/planner.ts +32 -16
- package/build/watch/reload.ts +4 -0
- package/build/watch/runtime.ts +29 -45
- package/build/watch/snapshot.ts +50 -402
- package/build/watch/validation.ts +6 -3
- package/build/watch-reachability-state.ts +16 -23
- package/build/watch-reload-client.ts +11 -4
- package/init/content/index.md +1 -1
- package/init/content/labs/02/index.md +61 -0
- package/init/content/labs/02/selection_sort.py +23 -0
- package/init/content/labs/index.md +4 -2
- package/init/content/lectures/01/index.md +1 -1
- package/init/content/markdown.md +1 -1
- package/package.json +3 -4
- package/src/code/index.ts +46 -18
- package/src/code.scss +2 -1
- package/src/globals.ts +47 -0
- package/src/index.ts +1 -0
- package/src/navigate/index.ts +2 -5
- package/src/navigate/lifecycle.ts +3 -1
- package/src/navigate/runtime.ts +6 -5
- package/src/page-update/index.ts +20 -16
- package/src/search/index.ts +53 -25
- package/src/search/style.scss +1 -1
- package/src/slides/index.ts +467 -0
- package/src/slides/style.scss +104 -0
- package/src/style.scss +8 -3
- package/src/timezone/index.ts +16 -20
- package/src/top/index.ts +2 -4
- package/src/trace/index.ts +91 -7
- package/src/trace/style.scss +1 -1
- package/src/util.ts +6 -2
- package/templates/_author.html +2 -2
- package/templates/_heading.html +1 -1
- package/templates/_nav.html +2 -2
- package/templates/_theme.scss +3 -3
- package/templates/_top.html +14 -14
- package/templates/default.html +8 -0
- package/types/dev.d.ts +1 -1
- package/types/site-variables.d.ts +4 -5
- package/watch/fs-commit.ts +63 -10
- package/build/apply-base-path-plugin.ts +0 -186
- package/build/content-watch.ts +0 -104
- package/build/validate-internal-links-plugin.ts +0 -207
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
@use '../mixins' as *;
|
|
2
|
+
|
|
3
|
+
.slide-deck,
|
|
4
|
+
.slide {
|
|
5
|
+
display: block;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
body.is-presenting {
|
|
9
|
+
--slides-scale: clamp(150%, 3.6vmin, 250%);
|
|
10
|
+
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body.is-presenting.is-presentation-cursor-hidden,
|
|
15
|
+
body.is-presenting.is-presentation-cursor-hidden * {
|
|
16
|
+
cursor: none !important;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
body.is-presenting header,
|
|
20
|
+
body.is-presenting .title-and-info,
|
|
21
|
+
body.is-presenting nav.toc,
|
|
22
|
+
body.is-presenting footer,
|
|
23
|
+
body.is-presenting .slides-header,
|
|
24
|
+
body.is-presenting .trace-toolbar {
|
|
25
|
+
display: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@media (hover: none) {
|
|
29
|
+
.slides-header {
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
body.is-presenting [data-slides-close] {
|
|
35
|
+
position: fixed;
|
|
36
|
+
top: var(--gap);
|
|
37
|
+
right: var(--gap);
|
|
38
|
+
z-index: 1001;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@media print {
|
|
42
|
+
[data-slides-close] {
|
|
43
|
+
display: none;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
body.is-presenting .slide-deck {
|
|
48
|
+
position: fixed;
|
|
49
|
+
inset: 0;
|
|
50
|
+
z-index: 999;
|
|
51
|
+
background: var(--bg-color);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
body.is-presenting .slide {
|
|
55
|
+
@include user-select(none);
|
|
56
|
+
|
|
57
|
+
position: fixed;
|
|
58
|
+
top: 50%;
|
|
59
|
+
left: 50%;
|
|
60
|
+
z-index: 1000;
|
|
61
|
+
box-sizing: border-box;
|
|
62
|
+
display: none;
|
|
63
|
+
width: min(100vw, calc(100vh * 4 / 3));
|
|
64
|
+
height: min(100vh, calc(100vw * 3 / 4));
|
|
65
|
+
padding: calc(3 * var(--gap));
|
|
66
|
+
overflow: auto;
|
|
67
|
+
font-size: var(--slides-scale);
|
|
68
|
+
letter-spacing: 0.2px;
|
|
69
|
+
outline: none;
|
|
70
|
+
background: var(--bg-color);
|
|
71
|
+
transform: translate(-50%, -50%);
|
|
72
|
+
|
|
73
|
+
> :first-child {
|
|
74
|
+
margin-top: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
> h2:first-child {
|
|
78
|
+
text-align: center;
|
|
79
|
+
|
|
80
|
+
a.heading-anchor {
|
|
81
|
+
color: var(--theme-color-text);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
body.is-presenting .slide.is-active {
|
|
87
|
+
display: block;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
body.is-presenting .slide.is-active:has(> .trace-widget) {
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
body.is-presenting .slide:has(> .trace-widget) > .trace-widget {
|
|
96
|
+
flex: 1 1 auto;
|
|
97
|
+
min-height: 0;
|
|
98
|
+
font-size: 66.6%;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
body.is-presenting .slide:has(> .trace-widget) > .trace-widget > .trace-body {
|
|
102
|
+
height: 100%;
|
|
103
|
+
min-height: 0;
|
|
104
|
+
}
|
package/src/style.scss
CHANGED
|
@@ -235,12 +235,17 @@ ul.styled-list {
|
|
|
235
235
|
|
|
236
236
|
ul.styled-list {
|
|
237
237
|
// Make bullet points slightly bigger
|
|
238
|
-
font-size: 1.
|
|
238
|
+
font-size: 1.2em;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
ol li .styled-list-item {
|
|
242
|
+
font-size: 1em;
|
|
243
|
+
font-weight: var(--font-weight);
|
|
244
|
+
color: var(--fg-color);
|
|
239
245
|
}
|
|
240
246
|
|
|
241
|
-
ol li .styled-list-item,
|
|
242
247
|
ul li .styled-list-item {
|
|
243
|
-
font-size:
|
|
248
|
+
font-size: 0.8333em;
|
|
244
249
|
font-weight: var(--font-weight);
|
|
245
250
|
color: var(--fg-color);
|
|
246
251
|
}
|
package/src/timezone/index.ts
CHANGED
|
@@ -45,6 +45,11 @@ export function normalizeHM(totalMinutes: number) {
|
|
|
45
45
|
return [h, m] as const;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
function getDayShift(totalMinutes: number) {
|
|
49
|
+
// Negative partial days like -30 minutes should still count as the previous day.
|
|
50
|
+
return Math.floor(totalMinutes / 1440);
|
|
51
|
+
}
|
|
52
|
+
|
|
48
53
|
function parseHHMM(hhmm: string) {
|
|
49
54
|
const [h, m] = hhmm.split(':');
|
|
50
55
|
if (h == null || m == null) {
|
|
@@ -85,26 +90,16 @@ function getOffsetMinutes(tz: string, date: Date): number {
|
|
|
85
90
|
return (utcTs - date.getTime()) / 60000;
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
// Read lazily so tests can set __SITE_TIMEZONES__ before the first call.
|
|
89
|
-
// Cache the result so mutations (like computeOffsets adding offsetMinutes)
|
|
90
|
-
// persist across calls. The bundler inlines __SITE_TIMEZONES__ as a JSON
|
|
91
|
-
// literal, so each raw access would create a fresh array.
|
|
92
|
-
let _timezones: TimeZone[] | null = null;
|
|
93
93
|
function getTimezones(): TimeZone[] {
|
|
94
|
-
|
|
95
|
-
_timezones =
|
|
96
|
-
typeof __SITE_TIMEZONES__ !== 'undefined' ? __SITE_TIMEZONES__ : [];
|
|
97
|
-
}
|
|
98
|
-
return _timezones;
|
|
94
|
+
return __SITE_TIMEZONES__.map(tz => ({ ...tz }));
|
|
99
95
|
}
|
|
100
96
|
|
|
101
|
-
function getDefaultTimezone() {
|
|
102
|
-
|
|
103
|
-
return getTimezones().find(tz => tz.value === value)!;
|
|
97
|
+
function getDefaultTimezone(timezones: TimeZone[]): TimeZone {
|
|
98
|
+
return timezones.find(tz => tz.value === __SITE_DEFAULT_TIMEZONE__)!;
|
|
104
99
|
}
|
|
105
100
|
|
|
106
|
-
function computeOffsets(baseDate: Date) {
|
|
107
|
-
|
|
101
|
+
function computeOffsets(timezones: TimeZone[], baseDate: Date) {
|
|
102
|
+
timezones.forEach(tz => {
|
|
108
103
|
tz.offsetMinutes = getOffsetMinutes(tz.value, baseDate);
|
|
109
104
|
});
|
|
110
105
|
}
|
|
@@ -143,14 +138,15 @@ function dominantPeriodStyle(
|
|
|
143
138
|
}
|
|
144
139
|
|
|
145
140
|
export default (window: Window) => {
|
|
146
|
-
const
|
|
141
|
+
const timezones = getTimezones();
|
|
142
|
+
const defaultTz = getDefaultTimezone(timezones);
|
|
147
143
|
const resetTitle = `Reset time zone to ${defaultTz.abbreviation} (default)`;
|
|
148
144
|
|
|
149
145
|
// determine initial time zone (from storage or default)
|
|
150
146
|
let initialTz = defaultTz.value;
|
|
151
147
|
try {
|
|
152
148
|
const stored = window.localStorage.getItem(STORAGE_KEY);
|
|
153
|
-
if (stored &&
|
|
149
|
+
if (stored && timezones.some(t => t.value === stored)) {
|
|
154
150
|
initialTz = stored;
|
|
155
151
|
}
|
|
156
152
|
} catch {
|
|
@@ -158,7 +154,7 @@ export default (window: Window) => {
|
|
|
158
154
|
}
|
|
159
155
|
|
|
160
156
|
const now = new Date();
|
|
161
|
-
computeOffsets(now);
|
|
157
|
+
computeOffsets(timezones, now);
|
|
162
158
|
const defaultOffset = defaultTz.offsetMinutes ?? 0;
|
|
163
159
|
|
|
164
160
|
// Snapshot the original AM/PM style from each <time> element's text
|
|
@@ -173,7 +169,7 @@ export default (window: Window) => {
|
|
|
173
169
|
const pagePeriodStyle = dominantPeriodStyle(periodStyles);
|
|
174
170
|
|
|
175
171
|
function updateTimes(targetTz: string) {
|
|
176
|
-
const target =
|
|
172
|
+
const target = timezones.find(t => t.value === targetTz) || defaultTz;
|
|
177
173
|
const targetOffset = target.offsetMinutes ?? 0;
|
|
178
174
|
const deltaMinutes = targetOffset - defaultOffset;
|
|
179
175
|
|
|
@@ -196,7 +192,7 @@ export default (window: Window) => {
|
|
|
196
192
|
|
|
197
193
|
// raw (can be < 0 or > 1439)
|
|
198
194
|
const rawMinutes = baseMinutes + deltaMinutes;
|
|
199
|
-
const dayShift =
|
|
195
|
+
const dayShift = getDayShift(rawMinutes);
|
|
200
196
|
// Normalize after computing dayShift
|
|
201
197
|
const [h, m] = normalizeHM(rawMinutes);
|
|
202
198
|
|
package/src/top/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { debounce, removeClass } from '../util';
|
|
2
|
+
import { globals } from '../globals';
|
|
2
3
|
|
|
3
4
|
/** Show the "Back to top" button once the user is past this scroll position */
|
|
4
5
|
const SHOW_THRESHOLD_PX = 250;
|
|
@@ -30,10 +31,7 @@ export default (window: Window) => {
|
|
|
30
31
|
e.preventDefault();
|
|
31
32
|
const cleanUrl = window.location.pathname + window.location.search;
|
|
32
33
|
if (window.location.hash) {
|
|
33
|
-
|
|
34
|
-
// hashchange fires. location.hash = '' may leave a trailing '#';
|
|
35
|
-
// strip it with replaceState.
|
|
36
|
-
window.location.hash = '';
|
|
34
|
+
globals.setLocationHash(window, '');
|
|
37
35
|
window.history.replaceState(null, '', cleanUrl);
|
|
38
36
|
} else {
|
|
39
37
|
window.history.replaceState(null, '', cleanUrl);
|
package/src/trace/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TraceManifest, TraceChunkEntry } from './types';
|
|
2
|
+
import { globals } from '../globals';
|
|
2
3
|
|
|
3
4
|
interface WidgetState {
|
|
4
5
|
manifest: TraceManifest;
|
|
@@ -33,7 +34,7 @@ async function loadChunk(
|
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
const url = chunkUrlFromManifest(manifestUrl, chunkIndex);
|
|
36
|
-
const res = await fetch(url);
|
|
37
|
+
const res = await globals.fetch(url);
|
|
37
38
|
const chunk: TraceChunkEntry[] = await res.json();
|
|
38
39
|
state.chunks.set(chunkIndex, chunk);
|
|
39
40
|
}
|
|
@@ -135,6 +136,63 @@ function updateStepControls(
|
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
138
|
|
|
139
|
+
function parsePositiveNumber(
|
|
140
|
+
rawValue: string | null | undefined,
|
|
141
|
+
): number | null {
|
|
142
|
+
if (!rawValue) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const parsed = Number.parseFloat(rawValue);
|
|
147
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function getPresentationScale(diagram: HTMLElement, doc: Document): number {
|
|
151
|
+
if (!doc.body.classList.contains('is-presenting')) {
|
|
152
|
+
return 1;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const view = doc.defaultView;
|
|
156
|
+
const traceWidget = diagram.closest('.trace-widget') as HTMLElement | null;
|
|
157
|
+
const traceFontSize = parsePositiveNumber(
|
|
158
|
+
traceWidget && view ? view.getComputedStyle(traceWidget).fontSize : null,
|
|
159
|
+
);
|
|
160
|
+
const baseFontSize = parsePositiveNumber(
|
|
161
|
+
view ? view.getComputedStyle(doc.body).fontSize : null,
|
|
162
|
+
);
|
|
163
|
+
if (traceFontSize && baseFontSize) {
|
|
164
|
+
return traceFontSize / baseFontSize;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return 1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function scaleDiagramSvg(diagram: HTMLElement, doc: Document): void {
|
|
171
|
+
const svg = diagram.querySelector('.trace-memory') as SVGElement | null;
|
|
172
|
+
if (!svg) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const width = svg.dataset.traceBaseWidth ?? svg.getAttribute('width');
|
|
177
|
+
const height = svg.dataset.traceBaseHeight ?? svg.getAttribute('height');
|
|
178
|
+
if (!width || !height) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
svg.dataset.traceBaseWidth = width;
|
|
183
|
+
svg.dataset.traceBaseHeight = height;
|
|
184
|
+
|
|
185
|
+
const baseWidth = Number.parseFloat(width);
|
|
186
|
+
const baseHeight = Number.parseFloat(height);
|
|
187
|
+
if (!Number.isFinite(baseWidth) || !Number.isFinite(baseHeight)) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const scale = getPresentationScale(diagram, doc);
|
|
192
|
+
svg.setAttribute('width', String(baseWidth * scale));
|
|
193
|
+
svg.setAttribute('height', String(baseHeight * scale));
|
|
194
|
+
}
|
|
195
|
+
|
|
138
196
|
function renderWidgetState(
|
|
139
197
|
state: WidgetState,
|
|
140
198
|
elements: WidgetElements,
|
|
@@ -161,6 +219,7 @@ function renderWidgetState(
|
|
|
161
219
|
|
|
162
220
|
const prevHeight = elements.diagram.scrollHeight;
|
|
163
221
|
elements.diagram.innerHTML = entry.svg;
|
|
222
|
+
scaleDiagramSvg(elements.diagram, doc);
|
|
164
223
|
|
|
165
224
|
// If the diagram grew past the visible area, scroll to show the new content
|
|
166
225
|
if (elements.diagram.scrollHeight > prevHeight) {
|
|
@@ -177,7 +236,7 @@ async function initWidget(root: HTMLElement, doc: Document): Promise<void> {
|
|
|
177
236
|
|
|
178
237
|
let res: Response;
|
|
179
238
|
try {
|
|
180
|
-
res = await fetch(manifestUrl);
|
|
239
|
+
res = await globals.fetch(manifestUrl);
|
|
181
240
|
} catch {
|
|
182
241
|
return;
|
|
183
242
|
}
|
|
@@ -239,20 +298,45 @@ async function initWidget(root: HTMLElement, doc: Document): Promise<void> {
|
|
|
239
298
|
|
|
240
299
|
const elements: WidgetElements = { root, source, controls, output, diagram };
|
|
241
300
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
diagram.innerHTML = entry.svg;
|
|
245
|
-
updateSourceHighlight(source, entry.line);
|
|
301
|
+
renderWidgetState(state, elements, doc);
|
|
246
302
|
}
|
|
247
303
|
|
|
248
|
-
export default function mountTrace(window: Window): void {
|
|
304
|
+
export default function mountTrace(window: Window): void | (() => void) {
|
|
249
305
|
const widgets = window.document.querySelectorAll('.trace-widget');
|
|
250
306
|
|
|
251
307
|
if (widgets.length === 0) {
|
|
252
308
|
return;
|
|
253
309
|
}
|
|
254
310
|
|
|
311
|
+
const refreshDiagramScales = (): void => {
|
|
312
|
+
for (const widget of widgets) {
|
|
313
|
+
const diagram = (widget as HTMLElement).querySelector(
|
|
314
|
+
'.trace-diagram',
|
|
315
|
+
) as HTMLElement | null;
|
|
316
|
+
if (diagram) {
|
|
317
|
+
scaleDiagramSvg(diagram, window.document);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const MutationObserverCtor = (window as Window & typeof globalThis)
|
|
323
|
+
.MutationObserver;
|
|
324
|
+
const bodyClassObserver = MutationObserverCtor
|
|
325
|
+
? new MutationObserverCtor(() => {
|
|
326
|
+
refreshDiagramScales();
|
|
327
|
+
})
|
|
328
|
+
: null;
|
|
329
|
+
|
|
330
|
+
bodyClassObserver?.observe(window.document.body, {
|
|
331
|
+
attributes: true,
|
|
332
|
+
attributeFilter: ['class'],
|
|
333
|
+
});
|
|
334
|
+
|
|
255
335
|
for (const widget of widgets) {
|
|
256
336
|
initWidget(widget as HTMLElement, window.document);
|
|
257
337
|
}
|
|
338
|
+
|
|
339
|
+
return () => {
|
|
340
|
+
bodyClassObserver?.disconnect();
|
|
341
|
+
};
|
|
258
342
|
}
|
package/src/trace/style.scss
CHANGED
package/src/util.ts
CHANGED
|
@@ -30,18 +30,22 @@ export function getElement(
|
|
|
30
30
|
return el as HTMLElement;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
function applyBasePathWithBasePath(subPath: string, basePath: string): string {
|
|
34
34
|
if (!subPath.startsWith('/')) {
|
|
35
35
|
throw new Error('invalid internal path, must start with "/": ' + subPath);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
let path =
|
|
38
|
+
let path = basePath;
|
|
39
39
|
if (path.endsWith('/')) {
|
|
40
40
|
path = path.slice(0, -1);
|
|
41
41
|
}
|
|
42
42
|
return path + subPath;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export function applyBasePath(subPath: string): string {
|
|
46
|
+
return applyBasePathWithBasePath(subPath, __SITE_BASE_PATH__);
|
|
47
|
+
}
|
|
48
|
+
|
|
45
49
|
export function scheduleTask(win: Window, fn: () => void) {
|
|
46
50
|
if (typeof win.requestIdleCallback === 'function') {
|
|
47
51
|
win.requestIdleCallback(fn);
|
package/templates/_author.html
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<aside class="author">
|
|
2
2
|
Written by
|
|
3
3
|
<% if (page.author.url) { %>
|
|
4
|
-
<a href="<%=
|
|
4
|
+
<a href="<%= page.author.url %>">
|
|
5
5
|
<% } %>
|
|
6
6
|
<span class="text"><%= page.author.name %></span>
|
|
7
7
|
<% if (page.author.avatar) { %>
|
|
8
8
|
<img
|
|
9
9
|
width="32"
|
|
10
10
|
height="32"
|
|
11
|
-
src="<%=
|
|
11
|
+
src="<%= page.author.avatar %>"
|
|
12
12
|
alt="Picture of <%= page.author.name %>"
|
|
13
13
|
class="avatar"
|
|
14
14
|
/>
|
package/templates/_heading.html
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="title-and-info" data-pagefind-body>
|
|
2
2
|
<% if (page.parent) { %>
|
|
3
|
-
<a class="breadcrumb" href="<%=
|
|
3
|
+
<a class="breadcrumb" href="<%= page.parent %>" data-pagefind-ignore><%= page.parentLabel %></a>
|
|
4
4
|
<% } %>
|
|
5
5
|
<h1 data-pagefind-weight="10" data-pagefind-meta="title_html[data-title-html]" data-title-html="<%- page.titleHtml %>"><%= page.titleHtml %></h1>
|
|
6
6
|
|
package/templates/_nav.html
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<nav>
|
|
2
|
-
<%
|
|
2
|
+
<% config('nav').forEach(function(section) { %>
|
|
3
3
|
<div>
|
|
4
4
|
<p><%= section.title %></p>
|
|
5
5
|
<ul>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<li>
|
|
8
8
|
<a
|
|
9
9
|
class="<%= cx({disabled: link.disabled, external: link.external}) %>"
|
|
10
|
-
<% if (!link.disabled) { %>href="<%= link.internal
|
|
10
|
+
<% if (!link.disabled) { %>href="<%= link.internal || link.external %>"<% } %>
|
|
11
11
|
<% if (link.external) { %>target="_blank"<% } %>
|
|
12
12
|
>
|
|
13
13
|
<%= link.text %></a>
|
package/templates/_theme.scss
CHANGED
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
--heading-font: var(--font);
|
|
43
43
|
--heading-line-height: 1.3;
|
|
44
44
|
--mono-font: 'Google Sans Code', 'Consolas', 'Courier', monospace;
|
|
45
|
-
--font-size:
|
|
46
|
-
--font-size-smaller:
|
|
47
|
-
--font-size-small:
|
|
45
|
+
--font-size: 1rem;
|
|
46
|
+
--font-size-smaller: 0.9375em;
|
|
47
|
+
--font-size-small: 0.8125em;
|
|
48
48
|
--font-weight: 400;
|
|
49
49
|
--line-height: 1.7;
|
|
50
50
|
--mono-font-size: 0.94em;
|
package/templates/_top.html
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<% if (site.features.favicon) { %>
|
|
5
|
-
<link rel="icon" href="
|
|
6
|
-
<link rel="icon" type="image/svg+xml" href="
|
|
7
|
-
<link rel="icon" type="image/png" sizes="512x512" href="
|
|
8
|
-
<link rel="icon" type="image/png" sizes="256x256" href="
|
|
9
|
-
<link rel="icon" type="image/png" sizes="192x192" href="
|
|
10
|
-
<link rel="icon" type="image/png" sizes="128x128" href="
|
|
11
|
-
<link rel="icon" type="image/png" sizes="64x64" href="
|
|
12
|
-
<link rel="icon" type="image/png" sizes="48x48" href="
|
|
13
|
-
<link rel="icon" type="image/png" sizes="32x32" href="
|
|
14
|
-
<link rel="icon" type="image/png" sizes="16x16" href="
|
|
15
|
-
<link rel="apple-touch-icon" sizes="512x512" href="
|
|
16
|
-
<link rel="apple-touch-icon" sizes="256x256" href="
|
|
17
|
-
<link rel="manifest" href="
|
|
5
|
+
<link rel="icon" href="/favicon.ico" sizes="any" />
|
|
6
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
|
+
<link rel="icon" type="image/png" sizes="512x512" href="/favicon-512.png" />
|
|
8
|
+
<link rel="icon" type="image/png" sizes="256x256" href="/favicon-256.png" />
|
|
9
|
+
<link rel="icon" type="image/png" sizes="192x192" href="/favicon-192.png" />
|
|
10
|
+
<link rel="icon" type="image/png" sizes="128x128" href="/favicon-128.png" />
|
|
11
|
+
<link rel="icon" type="image/png" sizes="64x64" href="/favicon-64.png" />
|
|
12
|
+
<link rel="icon" type="image/png" sizes="48x48" href="/favicon-48.png" />
|
|
13
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
|
|
14
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" />
|
|
15
|
+
<link rel="apple-touch-icon" sizes="512x512" href="/favicon-512.png" />
|
|
16
|
+
<link rel="apple-touch-icon" sizes="256x256" href="/favicon-256.png" />
|
|
17
|
+
<link rel="manifest" href="/manifest.json" />
|
|
18
18
|
<meta name="apple-mobile-web-app-title" content="<%= site.symbol %>">
|
|
19
19
|
<meta name="mobile-web-app-capable" content="yes">
|
|
20
20
|
<% } %>
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
{
|
|
39
39
|
"prerender": [{
|
|
40
40
|
"where": {
|
|
41
|
-
"href_matches": "<%=
|
|
41
|
+
"href_matches": "<%= speculationRulesHrefMatches %>"
|
|
42
42
|
},
|
|
43
43
|
"eagerness": "moderate"
|
|
44
44
|
}]
|
package/templates/default.html
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
<div class="main-content">
|
|
4
4
|
<%= render('_heading.html') %>
|
|
5
5
|
<main class="body" data-pagefind-body>
|
|
6
|
+
<% if (page.slides) { %>
|
|
7
|
+
<div class="slides-header" data-pagefind-ignore>
|
|
8
|
+
<button type="button" data-slides-present disabled>Present</button>
|
|
9
|
+
<button type="button" data-slides-present-fullscreen disabled>
|
|
10
|
+
Present (Full Screen)
|
|
11
|
+
</button>
|
|
12
|
+
</div>
|
|
13
|
+
<% } %>
|
|
6
14
|
<%= content %>
|
|
7
15
|
<%= render('_footer.html') %>
|
|
8
16
|
</main>
|
package/types/dev.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
declare
|
|
1
|
+
declare var __IS_DEV__: boolean;
|
|
@@ -5,8 +5,7 @@ interface TimeZone {
|
|
|
5
5
|
offsetMinutes?: number;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
declare
|
|
9
|
-
declare
|
|
10
|
-
declare
|
|
11
|
-
declare
|
|
12
|
-
declare const __SITE_TIMEZONES__: TimeZone[];
|
|
8
|
+
declare var __SITE_BASE_PATH__: string;
|
|
9
|
+
declare var __SITE_TITLE_POSTFIX__: string;
|
|
10
|
+
declare var __SITE_DEFAULT_TIMEZONE__: string;
|
|
11
|
+
declare var __SITE_TIMEZONES__: TimeZone[];
|