@abreen/tada 1.13.4 → 1.13.9
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/build/bundle.ts +17 -2
- package/build/generate-content-assets.ts +38 -175
- package/build/pipeline.ts +1 -1
- package/build/source-model.ts +2 -14
- package/build/types.d.ts +1 -12
- package/build/utils/derive-theme.ts +10 -0
- package/build/utils/render.ts +1 -0
- package/build/utils/trace-core.ts +75 -22
- package/build/utils/trace.ts +27 -10
- package/build/watch/assets.ts +2 -2
- package/build/watch/build-full.ts +26 -52
- package/build/watch/build-helpers.ts +66 -0
- package/build/watch/build-incremental.ts +32 -60
- package/build/watch/build-result.ts +19 -0
- package/build/watch/compiler-types.d.ts +1 -0
- package/build/watch/compiler.ts +25 -61
- package/build/watch/config-paths.ts +56 -0
- package/build/watch/engine.ts +199 -0
- package/{watch → build/watch}/fs-commit.ts +1 -3
- package/build/watch/index.ts +1 -1
- package/build/watch/mutations.ts +23 -25
- package/build/watch/planner.ts +14 -78
- package/build/watch/runtime.ts +26 -38
- package/build/watch/snapshot.ts +26 -47
- package/build/watch/types.d.ts +84 -0
- package/build/watch/validation.ts +1 -1
- package/package.json +1 -2
- package/src/_base.scss +6 -5
- package/src/slides/index.ts +34 -0
- package/src/style.scss +1 -1
- package/src/trace/index.ts +14 -7
- package/src/trace/style.scss +11 -10
- package/templates/_theme.scss +2 -0
- package/templates/default.html +1 -1
- package/build/watch-reachability-state.ts +0 -305
- package/watch/engine.ts +0 -296
- package/watch/events.ts +0 -10
- package/watch/types.d.ts +0 -103
package/build/watch/snapshot.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
updateProjectScan,
|
|
9
9
|
} from '../source-model';
|
|
10
10
|
import type { Asset, HtmlOutputAnalysis, SiteVariables } from '../types';
|
|
11
|
+
import type { TadaBuildMeta } from './compiler-types';
|
|
11
12
|
|
|
12
13
|
export interface TadaSourceRecord {
|
|
13
14
|
sourcePath: string;
|
|
@@ -21,28 +22,24 @@ export interface TadaSourceRecord {
|
|
|
21
22
|
authorKey?: string;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
export interface TadaOutputOwner {
|
|
26
|
+
kind: 'content' | 'public';
|
|
27
|
+
sourcePath: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
24
30
|
export interface TadaSnapshot {
|
|
25
31
|
siteVariables: SiteVariables;
|
|
26
32
|
assetFiles: string[];
|
|
27
33
|
navData: unknown;
|
|
28
34
|
authorsData: unknown;
|
|
29
|
-
processedExts: Set<string>;
|
|
30
35
|
contentRecords: Map<string, TadaSourceRecord>;
|
|
31
36
|
publicRecords: Map<string, TadaSourceRecord>;
|
|
32
|
-
outputOwners: Map<string,
|
|
37
|
+
outputOwners: Map<string, TadaOutputOwner>;
|
|
33
38
|
reversePartialDeps: Map<string, Set<string>>;
|
|
34
39
|
reverseTraceDeps: Map<string, Set<string>>;
|
|
35
40
|
reverseInternalTargetDeps: Map<string, Set<string>>;
|
|
36
41
|
reverseAuthorDeps: Map<string, Set<string>>;
|
|
37
|
-
|
|
38
|
-
buildContentFiles: Set<string>;
|
|
39
|
-
publicFiles: Set<string>;
|
|
40
|
-
literateJavaOutputPaths: Set<string>;
|
|
41
|
-
contentOwners: Map<string, string>;
|
|
42
|
-
publicOwners: Map<string, string>;
|
|
43
|
-
sourceOutputPaths: Map<string, Set<string>>;
|
|
44
|
-
sourceTargetPaths: Map<string, Set<string>>;
|
|
45
|
-
validTargets: Set<string>;
|
|
42
|
+
scan: TadaProjectScan;
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
function buildReverseMap(
|
|
@@ -63,22 +60,11 @@ function buildReverseMap(
|
|
|
63
60
|
return reverse;
|
|
64
61
|
}
|
|
65
62
|
|
|
66
|
-
function cloneSetMap(
|
|
67
|
-
source: Map<string, Set<string>>,
|
|
68
|
-
): Map<string, Set<string>> {
|
|
69
|
-
return new Map(
|
|
70
|
-
[...source.entries()].map(([key, values]) => [key, new Set(values)]),
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
63
|
export function collectOutputOwners(snapshot: {
|
|
75
64
|
contentRecords: Map<string, TadaSourceRecord>;
|
|
76
65
|
publicRecords: Map<string, TadaSourceRecord>;
|
|
77
|
-
}): Map<string,
|
|
78
|
-
const owners = new Map<
|
|
79
|
-
string,
|
|
80
|
-
{ kind: 'content' | 'public'; sourcePath: string }
|
|
81
|
-
>();
|
|
66
|
+
}): Map<string, TadaOutputOwner> {
|
|
67
|
+
const owners = new Map<string, TadaOutputOwner>();
|
|
82
68
|
|
|
83
69
|
for (const record of snapshot.contentRecords.values()) {
|
|
84
70
|
for (const outputPath of record.outputs.keys()) {
|
|
@@ -116,23 +102,12 @@ export function createSnapshot({
|
|
|
116
102
|
publicRecords: Map<string, TadaSourceRecord>;
|
|
117
103
|
}): TadaSnapshot {
|
|
118
104
|
const allRecords = [...contentRecords.values()];
|
|
119
|
-
const reverseAuthorDeps = new Map<string, Set<string>>();
|
|
120
|
-
for (const record of allRecords) {
|
|
121
|
-
if (!record.authorKey) {
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
if (!reverseAuthorDeps.has(record.authorKey)) {
|
|
125
|
-
reverseAuthorDeps.set(record.authorKey, new Set());
|
|
126
|
-
}
|
|
127
|
-
reverseAuthorDeps.get(record.authorKey)!.add(record.sourcePath);
|
|
128
|
-
}
|
|
129
105
|
|
|
130
106
|
return {
|
|
131
107
|
siteVariables,
|
|
132
108
|
assetFiles,
|
|
133
109
|
navData,
|
|
134
110
|
authorsData,
|
|
135
|
-
processedExts: scan.processedExts,
|
|
136
111
|
contentRecords,
|
|
137
112
|
publicRecords,
|
|
138
113
|
outputOwners: collectOutputOwners({ contentRecords, publicRecords }),
|
|
@@ -145,16 +120,10 @@ export function createSnapshot({
|
|
|
145
120
|
allRecords,
|
|
146
121
|
record => record.internalTargets,
|
|
147
122
|
),
|
|
148
|
-
reverseAuthorDeps,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
literateJavaOutputPaths: new Set(scan.literateJavaOutputPaths),
|
|
153
|
-
contentOwners: new Map(scan.contentOwners),
|
|
154
|
-
publicOwners: new Map(scan.publicOwners),
|
|
155
|
-
sourceOutputPaths: cloneSetMap(scan.sourceOutputPaths),
|
|
156
|
-
sourceTargetPaths: cloneSetMap(scan.sourceTargetPaths),
|
|
157
|
-
validTargets: new Set(scan.validTargets),
|
|
123
|
+
reverseAuthorDeps: buildReverseMap(allRecords, record =>
|
|
124
|
+
record.authorKey ? [record.authorKey] : [],
|
|
125
|
+
),
|
|
126
|
+
scan,
|
|
158
127
|
};
|
|
159
128
|
}
|
|
160
129
|
|
|
@@ -214,14 +183,24 @@ export function collectHtmlAnalysisByPath(
|
|
|
214
183
|
): Map<string, HtmlOutputAnalysis> {
|
|
215
184
|
const htmlAnalysisByPath = new Map<string, HtmlOutputAnalysis>();
|
|
216
185
|
for (const record of contentRecords.values()) {
|
|
217
|
-
|
|
218
|
-
|
|
186
|
+
if (!record.htmlAnalysisByOutputPath) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
for (const [outputPath, analysis] of record.htmlAnalysisByOutputPath) {
|
|
219
190
|
htmlAnalysisByPath.set(outputPath, cloneHtmlOutputAnalysis(analysis));
|
|
220
191
|
}
|
|
221
192
|
}
|
|
222
193
|
return htmlAnalysisByPath;
|
|
223
194
|
}
|
|
224
195
|
|
|
196
|
+
export function createBuildMeta(snapshot: TadaSnapshot): TadaBuildMeta {
|
|
197
|
+
return {
|
|
198
|
+
htmlAssetsByPath: collectHtmlAssetsByPath(snapshot.contentRecords),
|
|
199
|
+
htmlAnalysisByPath: collectHtmlAnalysisByPath(snapshot.contentRecords),
|
|
200
|
+
siteVariables: snapshot.siteVariables,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
225
204
|
export function normalizeInternalTarget(target: string): string {
|
|
226
205
|
return normalizeOutputPath(target);
|
|
227
206
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ChokidarOptions } from 'chokidar';
|
|
2
|
+
import type { TadaBuildMeta } from './compiler-types';
|
|
3
|
+
import type { TadaSnapshot } from './snapshot';
|
|
4
|
+
|
|
5
|
+
export type WatchEventKind = 'add' | 'change' | 'unlink';
|
|
6
|
+
|
|
7
|
+
export interface FileChange {
|
|
8
|
+
path: string;
|
|
9
|
+
kind: WatchEventKind;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ChangeBatch {
|
|
13
|
+
changes: FileChange[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface WatchTarget {
|
|
17
|
+
path: string;
|
|
18
|
+
chokidar?: ChokidarOptions;
|
|
19
|
+
filter?: (filePath: string) => boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WatchDiagnostic {
|
|
23
|
+
message: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface WriteFileMutation {
|
|
27
|
+
kind: 'write';
|
|
28
|
+
path: string;
|
|
29
|
+
content: string | Buffer;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface DeleteFileMutation {
|
|
33
|
+
kind: 'delete';
|
|
34
|
+
path: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type FileMutation = WriteFileMutation | DeleteFileMutation;
|
|
38
|
+
|
|
39
|
+
export interface ReplaceRootCommitPlan {
|
|
40
|
+
kind: 'replace-root';
|
|
41
|
+
stagedPath: string;
|
|
42
|
+
targetPath: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ApplyMutationsCommitPlan {
|
|
46
|
+
kind: 'apply-mutations';
|
|
47
|
+
rootDir: string;
|
|
48
|
+
mutations: FileMutation[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type CommitPlan = ReplaceRootCommitPlan | ApplyMutationsCommitPlan;
|
|
52
|
+
|
|
53
|
+
export type CompilerBuildResult =
|
|
54
|
+
| {
|
|
55
|
+
ok: true;
|
|
56
|
+
snapshot: TadaSnapshot;
|
|
57
|
+
commit: CommitPlan;
|
|
58
|
+
meta: TadaBuildMeta;
|
|
59
|
+
}
|
|
60
|
+
| { ok: false; diagnostics: WatchDiagnostic[] };
|
|
61
|
+
|
|
62
|
+
export interface WatchCompiler {
|
|
63
|
+
getWatchTargets(): WatchTarget[];
|
|
64
|
+
build(
|
|
65
|
+
snapshot: TadaSnapshot | undefined,
|
|
66
|
+
batch?: ChangeBatch,
|
|
67
|
+
): Promise<CompilerBuildResult>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type WatchLifecycleEvent =
|
|
71
|
+
| { kind: 'watching' }
|
|
72
|
+
| { kind: 'build-started'; batch?: ChangeBatch }
|
|
73
|
+
| { kind: 'build-succeeded'; batch?: ChangeBatch; meta: TadaBuildMeta }
|
|
74
|
+
| {
|
|
75
|
+
kind: 'build-failed';
|
|
76
|
+
batch?: ChangeBatch;
|
|
77
|
+
diagnostics: WatchDiagnostic[];
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export interface WatchEngineOptions {
|
|
81
|
+
compiler: WatchCompiler;
|
|
82
|
+
debounceMs?: number;
|
|
83
|
+
onEvent?: (event: WatchLifecycleEvent) => void | Promise<void>;
|
|
84
|
+
}
|
|
@@ -2,7 +2,7 @@ import { B } from '../colors';
|
|
|
2
2
|
import { makeLogger } from '../log';
|
|
3
3
|
import { config, getConfigFileName } from '../templates';
|
|
4
4
|
import { validateConfigLinks } from '../validate-config-links';
|
|
5
|
-
import type { WatchDiagnostic } from '
|
|
5
|
+
import type { WatchDiagnostic } from './types';
|
|
6
6
|
import { assertNoOutputPathConflicts, type TadaProjectScan } from './snapshot';
|
|
7
7
|
|
|
8
8
|
const log = makeLogger(import.meta.url);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abreen/tada",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A static site generator",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"bin/",
|
|
17
17
|
"build/",
|
|
18
|
-
"watch/",
|
|
19
18
|
"src/",
|
|
20
19
|
"templates/",
|
|
21
20
|
"fonts/",
|
package/src/_base.scss
CHANGED
|
@@ -38,12 +38,13 @@ body {
|
|
|
38
38
|
* Enable Inter's features:
|
|
39
39
|
* liga - standard ligatures
|
|
40
40
|
* calt - contextual alternates
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
41
|
+
* ss07 - square punctuation
|
|
42
|
+
* ss08 - square quotes
|
|
43
|
+
* cv01 - alternate 1
|
|
44
|
+
* cv08 - uppercase I with serif
|
|
45
|
+
* cv10 - capital G with spur
|
|
45
46
|
*/
|
|
46
|
-
font-feature-settings: 'liga', 'calt', '
|
|
47
|
+
font-feature-settings: 'liga', 'calt', 'ss07', 'ss08', 'cv01', 'cv08', 'cv10';
|
|
47
48
|
line-height: var(--line-height);
|
|
48
49
|
color: var(--fg-color);
|
|
49
50
|
background-color: var(--bg-color);
|
package/src/slides/index.ts
CHANGED
|
@@ -9,6 +9,8 @@ interface SlidesPresentDetail {
|
|
|
9
9
|
slideIndex?: number;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
const FULLSCREEN_STORAGE_KEY = 'slidesFullscreen';
|
|
13
|
+
|
|
12
14
|
function isInteractive(
|
|
13
15
|
view: Window & typeof globalThis,
|
|
14
16
|
target: EventTarget | null,
|
|
@@ -83,6 +85,16 @@ export default function mountSlides(window: Window): void | (() => void) {
|
|
|
83
85
|
presentButton.disabled = false;
|
|
84
86
|
}
|
|
85
87
|
if (fullscreenCheckbox) {
|
|
88
|
+
try {
|
|
89
|
+
const stored = window.localStorage.getItem(FULLSCREEN_STORAGE_KEY);
|
|
90
|
+
if (stored === 'false') {
|
|
91
|
+
fullscreenCheckbox.checked = false;
|
|
92
|
+
} else if (stored === 'true') {
|
|
93
|
+
fullscreenCheckbox.checked = true;
|
|
94
|
+
}
|
|
95
|
+
} catch {
|
|
96
|
+
// ignored
|
|
97
|
+
}
|
|
86
98
|
fullscreenCheckbox.disabled = false;
|
|
87
99
|
}
|
|
88
100
|
|
|
@@ -365,6 +377,20 @@ export default function mountSlides(window: Window): void | (() => void) {
|
|
|
365
377
|
exitPresentation();
|
|
366
378
|
}
|
|
367
379
|
|
|
380
|
+
function handleFullscreenPreferenceChange(): void {
|
|
381
|
+
if (!fullscreenCheckbox) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
try {
|
|
385
|
+
window.localStorage.setItem(
|
|
386
|
+
FULLSCREEN_STORAGE_KEY,
|
|
387
|
+
String(fullscreenCheckbox.checked),
|
|
388
|
+
);
|
|
389
|
+
} catch {
|
|
390
|
+
// Ignore storage errors so the checkbox remains usable.
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
368
394
|
function handleFullscreenChange(): void {
|
|
369
395
|
if (
|
|
370
396
|
isPresenting &&
|
|
@@ -460,6 +486,10 @@ export default function mountSlides(window: Window): void | (() => void) {
|
|
|
460
486
|
}
|
|
461
487
|
|
|
462
488
|
presentButton?.addEventListener('click', handlePresentClick);
|
|
489
|
+
fullscreenCheckbox?.addEventListener(
|
|
490
|
+
'change',
|
|
491
|
+
handleFullscreenPreferenceChange,
|
|
492
|
+
);
|
|
463
493
|
closeButton.addEventListener('click', handleCloseClick);
|
|
464
494
|
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
|
465
495
|
window.addEventListener('keydown', handleKeydown);
|
|
@@ -470,6 +500,10 @@ export default function mountSlides(window: Window): void | (() => void) {
|
|
|
470
500
|
return () => {
|
|
471
501
|
exitPresentation();
|
|
472
502
|
presentButton?.removeEventListener('click', handlePresentClick);
|
|
503
|
+
fullscreenCheckbox?.removeEventListener(
|
|
504
|
+
'change',
|
|
505
|
+
handleFullscreenPreferenceChange,
|
|
506
|
+
);
|
|
473
507
|
closeButton.removeEventListener('click', handleCloseClick);
|
|
474
508
|
document.removeEventListener('fullscreenchange', handleFullscreenChange);
|
|
475
509
|
window.removeEventListener('keydown', handleKeydown);
|
package/src/style.scss
CHANGED
package/src/trace/index.ts
CHANGED
|
@@ -58,13 +58,20 @@ async function goToStep(
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
function updateSourceHighlight(panel: HTMLElement, currentLine: number): void {
|
|
61
|
-
panel
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
panel
|
|
62
|
+
.querySelectorAll(
|
|
63
|
+
'.code-row.trace-line-active, .line-number.trace-line-active',
|
|
64
|
+
)
|
|
65
|
+
.forEach(el => {
|
|
66
|
+
el.classList.remove('trace-line-active');
|
|
67
|
+
});
|
|
68
|
+
const lineNumber = panel.querySelector(
|
|
69
|
+
`.line-number[data-line="${currentLine}"]`,
|
|
70
|
+
);
|
|
71
|
+
const row = lineNumber?.closest('.code-row') as HTMLElement | null;
|
|
72
|
+
if (row) {
|
|
73
|
+
row.classList.add('trace-line-active');
|
|
74
|
+
const elRect = row.getBoundingClientRect();
|
|
68
75
|
const panelRect = panel.getBoundingClientRect();
|
|
69
76
|
panel.scrollTop += elRect.top - panelRect.top - panel.clientHeight / 2;
|
|
70
77
|
}
|
package/src/trace/style.scss
CHANGED
|
@@ -112,16 +112,17 @@
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
115
|
+
.code-row.trace-line-active {
|
|
116
|
+
background: var(--bg-trace-line-active);
|
|
117
|
+
|
|
118
|
+
.line-number {
|
|
119
|
+
font-weight: bold;
|
|
120
|
+
color: var(--fg-color);
|
|
121
|
+
background: var(--bg-trace-line-active);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
code {
|
|
125
|
+
background: none;
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
}
|
package/templates/_theme.scss
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
--bg2-color-translucent: hsl(
|
|
33
33
|
var(--tint-hue) calc(12% * var(--tint-amount)) 92% / 66%
|
|
34
34
|
);
|
|
35
|
+
--bg-trace-line-active: <%= bgTraceLineActive %>;
|
|
35
36
|
--box-shadow: 0 2px 9px
|
|
36
37
|
hsl(var(--tint-hue) calc(85% * var(--tint-amount)) 10% / 25%);
|
|
37
38
|
--backdrop-filter: blur(10px);
|
|
@@ -87,6 +88,7 @@
|
|
|
87
88
|
--bg2-color-translucent: hsl(
|
|
88
89
|
var(--tint-hue) calc(12% * var(--tint-amount)) 12% / 66%
|
|
89
90
|
);
|
|
91
|
+
--bg-trace-line-active: <%= bgTraceLineActiveDark %>;
|
|
90
92
|
--box-shadow: 0 3px 8px
|
|
91
93
|
hsl(var(--tint-hue) calc(33% * var(--tint-amount)) 8% / 70%);
|
|
92
94
|
--link-active-color: #fff;
|
package/templates/default.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<div class="slides-header" data-pagefind-ignore>
|
|
8
8
|
<button type="button" data-slides-present disabled>Present</button>
|
|
9
9
|
<label>
|
|
10
|
-
<input type="checkbox" data-slides-fullscreen checked disabled>
|
|
10
|
+
<input id="slides-fullscreen" type="checkbox" data-slides-fullscreen checked disabled>
|
|
11
11
|
Full screen
|
|
12
12
|
</label>
|
|
13
13
|
</div>
|