@abreen/tada 1.13.7 → 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/generate-content-assets.ts +37 -175
- package/build/pipeline.ts +1 -1
- package/build/source-model.ts +2 -14
- package/build/types.d.ts +0 -12
- 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.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/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
|
@@ -6,16 +6,14 @@ import { createContentRecord } from './source-records';
|
|
|
6
6
|
import { validateConfigLinks } from './validate-config-links';
|
|
7
7
|
import { config, getConfigFileName } from './templates';
|
|
8
8
|
import { initHighlighter } from './utils/shiki-highlighter';
|
|
9
|
-
import { checkTraceToolAvailability
|
|
9
|
+
import { checkTraceToolAvailability } from './utils/trace';
|
|
10
10
|
import type {
|
|
11
11
|
SiteVariables,
|
|
12
12
|
ContentRenderOptions,
|
|
13
13
|
ContentRenderResult,
|
|
14
14
|
HtmlOutputAnalysis,
|
|
15
15
|
TraceToolAvailability,
|
|
16
|
-
WatchState,
|
|
17
16
|
} from './types';
|
|
18
|
-
import type { TadaSourceRecord } from './watch/snapshot';
|
|
19
17
|
|
|
20
18
|
const log = makeLogger(import.meta.url);
|
|
21
19
|
|
|
@@ -25,11 +23,19 @@ function cloneHtmlOutputAnalysis(
|
|
|
25
23
|
return { outgoingTargets: new Set(analysis.outgoingTargets) };
|
|
26
24
|
}
|
|
27
25
|
|
|
26
|
+
function writeRecordOutputs(
|
|
27
|
+
distDir: string,
|
|
28
|
+
outputs: Map<string, string | Buffer>,
|
|
29
|
+
): void {
|
|
30
|
+
for (const [outputPath, content] of outputs) {
|
|
31
|
+
const outPath = path.join(distDir, outputPath);
|
|
32
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
33
|
+
fs.writeFileSync(outPath, content);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
export class ContentRenderer {
|
|
29
38
|
private siteVariables: SiteVariables;
|
|
30
|
-
private sourceFileCache: Map<string, TadaSourceRecord>;
|
|
31
|
-
private lastBuildFiles: Set<string>;
|
|
32
|
-
private javacAvailable: boolean | undefined;
|
|
33
39
|
private traceToolAvailability: TraceToolAvailability | undefined;
|
|
34
40
|
private traceCache: Map<
|
|
35
41
|
string,
|
|
@@ -44,133 +50,23 @@ export class ContentRenderer {
|
|
|
44
50
|
|
|
45
51
|
constructor(siteVariables: SiteVariables) {
|
|
46
52
|
this.siteVariables = siteVariables;
|
|
47
|
-
this.sourceFileCache = new Map();
|
|
48
|
-
this.lastBuildFiles = new Set();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
private getCachedRecord(filePath: string): TadaSourceRecord | undefined {
|
|
52
|
-
return this.sourceFileCache.get(filePath);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
async initHighlighter(): Promise<void> {
|
|
56
56
|
await initHighlighter(getRuntimeBundledShikiLanguages(this.siteVariables));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
getDirtySourceFiles(
|
|
60
|
-
buildContentFiles: string[],
|
|
61
|
-
{ changedContentFiles, jsonDataChanged, partialsChanged }: WatchState = {},
|
|
62
|
-
): Set<string> {
|
|
63
|
-
if (
|
|
64
|
-
this.lastBuildFiles.size === 0 ||
|
|
65
|
-
!changedContentFiles ||
|
|
66
|
-
jsonDataChanged ||
|
|
67
|
-
partialsChanged
|
|
68
|
-
) {
|
|
69
|
-
return new Set(buildContentFiles);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// If any trace source changed, the trace cache will be stale, so rebuild
|
|
73
|
-
// all content pages to pick up the new trace output.
|
|
74
|
-
const traceFileChanged = [...changedContentFiles].some(isTraceSourceFile);
|
|
75
|
-
if (traceFileChanged) {
|
|
76
|
-
return new Set(buildContentFiles);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const buildFileSet = new Set(buildContentFiles);
|
|
80
|
-
const dirtySourceFiles = new Set<string>();
|
|
81
|
-
for (const filePath of changedContentFiles) {
|
|
82
|
-
if (buildFileSet.has(filePath)) {
|
|
83
|
-
dirtySourceFiles.add(filePath);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return dirtySourceFiles;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
updateSourceCache(
|
|
90
|
-
filePath: string,
|
|
91
|
-
record: TadaSourceRecord,
|
|
92
|
-
changedOutputRelPaths: Set<string>,
|
|
93
|
-
removedOutputRelPaths: Set<string>,
|
|
94
|
-
changedHtmlAssetPaths: Set<string>,
|
|
95
|
-
removedHtmlAssetPaths: Set<string>,
|
|
96
|
-
): void {
|
|
97
|
-
const previousRecord = this.getCachedRecord(filePath);
|
|
98
|
-
const nextOutputPaths = new Set(record.outputs.keys());
|
|
99
|
-
|
|
100
|
-
for (const outputPath of previousRecord?.outputs.keys() ?? []) {
|
|
101
|
-
if (nextOutputPaths.has(outputPath)) {
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
removedOutputRelPaths.add(outputPath);
|
|
105
|
-
if (outputPath.endsWith('.html')) {
|
|
106
|
-
removedHtmlAssetPaths.add(outputPath);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
for (const outputPath of record.outputs.keys()) {
|
|
111
|
-
changedOutputRelPaths.add(outputPath);
|
|
112
|
-
if (outputPath.endsWith('.html')) {
|
|
113
|
-
changedHtmlAssetPaths.add(outputPath);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
this.sourceFileCache.set(filePath, record);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
writeCachedAssets(distDir: string, buildContentFiles: string[]): void {
|
|
121
|
-
for (const filePath of buildContentFiles) {
|
|
122
|
-
const record = this.getCachedRecord(filePath);
|
|
123
|
-
if (!record) {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
for (const [outputPath, content] of record.outputs) {
|
|
127
|
-
const outPath = path.join(distDir, outputPath);
|
|
128
|
-
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
129
|
-
fs.writeFileSync(outPath, content);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
pruneRemovedSources(
|
|
135
|
-
buildFileSet: Set<string>,
|
|
136
|
-
removedOutputRelPaths: Set<string>,
|
|
137
|
-
removedHtmlAssetPaths: Set<string>,
|
|
138
|
-
): void {
|
|
139
|
-
for (const filePath of [...this.lastBuildFiles]) {
|
|
140
|
-
if (buildFileSet.has(filePath)) {
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const previousRecord = this.getCachedRecord(filePath);
|
|
145
|
-
for (const outputPath of previousRecord?.outputs.keys() ?? []) {
|
|
146
|
-
removedOutputRelPaths.add(outputPath);
|
|
147
|
-
if (outputPath.endsWith('.html')) {
|
|
148
|
-
removedHtmlAssetPaths.add(outputPath);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
this.sourceFileCache.delete(filePath);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
59
|
processContent({
|
|
156
60
|
distDir,
|
|
157
61
|
assetFiles,
|
|
158
62
|
scan,
|
|
159
|
-
watchState,
|
|
160
63
|
}: ContentRenderOptions): ContentRenderResult {
|
|
161
64
|
const buildContentFiles = [...scan.buildContentFiles];
|
|
162
|
-
const buildFileSet = new Set<string>(buildContentFiles);
|
|
163
|
-
const dirtySourceFiles = this.getDirtySourceFiles(
|
|
164
|
-
buildContentFiles,
|
|
165
|
-
watchState,
|
|
166
|
-
);
|
|
167
|
-
const changedOutputRelPaths = new Set<string>();
|
|
168
|
-
const removedOutputRelPaths = new Set<string>();
|
|
169
|
-
const changedHtmlAssetPaths = new Set<string>();
|
|
170
|
-
const removedHtmlAssetPaths = new Set<string>();
|
|
171
65
|
const validInternalTargets = scan.validTargets;
|
|
172
66
|
|
|
173
67
|
const errors: Error[] = [];
|
|
68
|
+
const htmlAssetsByPath = new Map<string, string>();
|
|
69
|
+
const htmlAnalysisByPath = new Map<string, HtmlOutputAnalysis>();
|
|
174
70
|
|
|
175
71
|
const configLinkErrors = validateConfigLinks(
|
|
176
72
|
validInternalTargets,
|
|
@@ -185,29 +81,21 @@ export class ContentRenderer {
|
|
|
185
81
|
errors.push(new Error(msg));
|
|
186
82
|
}
|
|
187
83
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
removedHtmlAssetPaths,
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
if (dirtySourceFiles.size > 0) {
|
|
195
|
-
const noun = dirtySourceFiles.size === 1 ? 'file' : 'files';
|
|
196
|
-
log.info`Processing ${dirtySourceFiles.size} content ${noun}`;
|
|
84
|
+
if (buildContentFiles.length > 0) {
|
|
85
|
+
const noun = buildContentFiles.length === 1 ? 'file' : 'files';
|
|
86
|
+
log.info`Processing ${buildContentFiles.length} content ${noun}`;
|
|
197
87
|
}
|
|
198
88
|
|
|
199
|
-
if (this.
|
|
89
|
+
if (!this.traceToolAvailability && buildContentFiles.length > 0) {
|
|
200
90
|
this.traceToolAvailability = checkTraceToolAvailability();
|
|
201
|
-
|
|
202
|
-
if (!this.javacAvailable) {
|
|
91
|
+
if (!this.traceToolAvailability.java) {
|
|
203
92
|
log.warn`javac was not found; literate Java pages will not include execution output`;
|
|
204
93
|
}
|
|
205
94
|
}
|
|
206
95
|
|
|
207
|
-
for (const filePath of
|
|
208
|
-
let record: TadaSourceRecord;
|
|
96
|
+
for (const filePath of buildContentFiles) {
|
|
209
97
|
try {
|
|
210
|
-
record = createContentRecord({
|
|
98
|
+
const record = createContentRecord({
|
|
211
99
|
filePath,
|
|
212
100
|
siteVariables: this.siteVariables,
|
|
213
101
|
scan,
|
|
@@ -215,53 +103,27 @@ export class ContentRenderer {
|
|
|
215
103
|
outputDir: distDir,
|
|
216
104
|
traceCache: this.traceCache,
|
|
217
105
|
traceToolAvailability: this.traceToolAvailability,
|
|
218
|
-
skipLiterateJavaExecution: !this.
|
|
106
|
+
skipLiterateJavaExecution: !this.traceToolAvailability?.java,
|
|
219
107
|
});
|
|
108
|
+
writeRecordOutputs(distDir, record.outputs);
|
|
109
|
+
for (const [outputPath, content] of record.outputs) {
|
|
110
|
+
if (!outputPath.endsWith('.html') || typeof content !== 'string') {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
htmlAssetsByPath.set(outputPath, content);
|
|
114
|
+
const analysis = record.htmlAnalysisByOutputPath?.get(outputPath);
|
|
115
|
+
if (analysis) {
|
|
116
|
+
htmlAnalysisByPath.set(
|
|
117
|
+
outputPath,
|
|
118
|
+
cloneHtmlOutputAnalysis(analysis),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
220
122
|
} catch (err) {
|
|
221
123
|
errors.push(err as Error);
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
this.updateSourceCache(
|
|
225
|
-
filePath,
|
|
226
|
-
record,
|
|
227
|
-
changedOutputRelPaths,
|
|
228
|
-
removedOutputRelPaths,
|
|
229
|
-
changedHtmlAssetPaths,
|
|
230
|
-
removedHtmlAssetPaths,
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
this.writeCachedAssets(distDir, buildContentFiles);
|
|
235
|
-
this.lastBuildFiles = buildFileSet;
|
|
236
|
-
|
|
237
|
-
// Collect HTML asset content and analysis for Pagefind
|
|
238
|
-
const htmlAssetsByPath = new Map<string, string>();
|
|
239
|
-
const htmlAnalysisByPath = new Map<string, HtmlOutputAnalysis>();
|
|
240
|
-
for (const filePath of buildContentFiles) {
|
|
241
|
-
const record = this.getCachedRecord(filePath);
|
|
242
|
-
if (!record) {
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
|
-
for (const [outputPath, content] of record.outputs) {
|
|
246
|
-
if (!outputPath.endsWith('.html') || typeof content !== 'string') {
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
htmlAssetsByPath.set(outputPath, content);
|
|
250
|
-
const analysis = record.htmlAnalysisByOutputPath?.get(outputPath);
|
|
251
|
-
if (analysis) {
|
|
252
|
-
htmlAnalysisByPath.set(outputPath, cloneHtmlOutputAnalysis(analysis));
|
|
253
|
-
}
|
|
254
124
|
}
|
|
255
125
|
}
|
|
256
126
|
|
|
257
|
-
return {
|
|
258
|
-
errors,
|
|
259
|
-
changedHtmlAssetPaths,
|
|
260
|
-
removedHtmlAssetPaths,
|
|
261
|
-
removedOutputRelPaths,
|
|
262
|
-
htmlAssetsByPath,
|
|
263
|
-
htmlAnalysisByPath,
|
|
264
|
-
buildContentFiles,
|
|
265
|
-
};
|
|
127
|
+
return { errors, htmlAssetsByPath, htmlAnalysisByPath };
|
|
266
128
|
}
|
|
267
129
|
}
|
package/build/pipeline.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { makeLogger, printFlair } from './log';
|
|
|
15
15
|
import { generateBuildManifest, getNextVersion } from './build-manifest';
|
|
16
16
|
import { scanProject } from './source-model';
|
|
17
17
|
import { validateConfig } from './watch/validation';
|
|
18
|
-
import { applyCommitPlan } from '
|
|
18
|
+
import { applyCommitPlan } from './watch/fs-commit';
|
|
19
19
|
import path from 'path';
|
|
20
20
|
|
|
21
21
|
const log = makeLogger(import.meta.url);
|
package/build/source-model.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
normalizeOutputPath,
|
|
16
16
|
toPosix,
|
|
17
17
|
} from './utils/paths';
|
|
18
|
-
import type { ChangeBatch } from '
|
|
18
|
+
import type { ChangeBatch } from './watch/types';
|
|
19
19
|
import type { SiteVariables } from './types';
|
|
20
20
|
|
|
21
21
|
export interface TadaProjectScan {
|
|
@@ -34,18 +34,6 @@ export interface TadaProjectScan {
|
|
|
34
34
|
sourceTargetPaths: Map<string, Set<string>>;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export interface TadaProjectScanSnapshotLike {
|
|
38
|
-
processedExts: Set<string>;
|
|
39
|
-
contentFiles: Set<string>;
|
|
40
|
-
buildContentFiles: Set<string>;
|
|
41
|
-
publicFiles: Set<string>;
|
|
42
|
-
literateJavaOutputPaths: Set<string>;
|
|
43
|
-
contentOwners: Map<string, string>;
|
|
44
|
-
publicOwners: Map<string, string>;
|
|
45
|
-
sourceOutputPaths: Map<string, Set<string>>;
|
|
46
|
-
sourceTargetPaths: Map<string, Set<string>>;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
37
|
export function shouldSkipContentFile(filePath: string): boolean {
|
|
50
38
|
const ext = path.extname(filePath).toLowerCase();
|
|
51
39
|
if (!(extensionIsMarkdown(ext) || ext === '.html')) {
|
|
@@ -333,7 +321,7 @@ export function scanProject(siteVariables: SiteVariables): TadaProjectScan {
|
|
|
333
321
|
}
|
|
334
322
|
|
|
335
323
|
export function updateProjectScan(
|
|
336
|
-
snapshot:
|
|
324
|
+
snapshot: TadaProjectScan,
|
|
337
325
|
batch: ChangeBatch,
|
|
338
326
|
): TadaProjectScan {
|
|
339
327
|
const scan = createEmptyScan(snapshot.processedExts);
|
package/build/types.d.ts
CHANGED
|
@@ -49,25 +49,13 @@ export interface ContentRenderOptions {
|
|
|
49
49
|
distDir: string;
|
|
50
50
|
assetFiles: string[];
|
|
51
51
|
scan: TadaProjectScan;
|
|
52
|
-
watchState?: WatchState;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** State passed from watch mode to control incremental rebuilds */
|
|
56
|
-
export interface WatchState {
|
|
57
|
-
changedContentFiles?: Set<string>;
|
|
58
|
-
jsonDataChanged?: boolean;
|
|
59
|
-
partialsChanged?: boolean;
|
|
60
52
|
}
|
|
61
53
|
|
|
62
54
|
/** Result from ContentRenderer.processContent() */
|
|
63
55
|
export interface ContentRenderResult {
|
|
64
56
|
errors: Error[];
|
|
65
|
-
changedHtmlAssetPaths: Set<string>;
|
|
66
|
-
removedHtmlAssetPaths: Set<string>;
|
|
67
|
-
removedOutputRelPaths: Set<string>;
|
|
68
57
|
htmlAssetsByPath: Map<string, string>;
|
|
69
58
|
htmlAnalysisByPath: Map<string, HtmlOutputAnalysis>;
|
|
70
|
-
buildContentFiles: string[];
|
|
71
59
|
}
|
|
72
60
|
|
|
73
61
|
/** Logger returned by makeLogger() */
|
|
@@ -1,34 +1,24 @@
|
|
|
1
1
|
import { compileTemplates, config } from '../templates';
|
|
2
2
|
import { getDevSiteVariables } from '../site-variables';
|
|
3
|
-
import { createContentRecord, createPublicRecord } from '../source-records';
|
|
4
3
|
import { getDistDir } from '../util';
|
|
5
|
-
import type { CompilerBuildResult } from '
|
|
6
|
-
import {
|
|
7
|
-
collectHtmlAnalysisByPath,
|
|
8
|
-
collectHtmlAssetsByPath,
|
|
9
|
-
createSnapshot,
|
|
10
|
-
type TadaSourceRecord,
|
|
11
|
-
type TadaSnapshot,
|
|
12
|
-
} from './snapshot';
|
|
4
|
+
import type { CompilerBuildResult } from './types';
|
|
5
|
+
import { createSnapshot, type TadaSourceRecord } from './snapshot';
|
|
13
6
|
import { scanProject } from '../source-model';
|
|
14
|
-
import type {
|
|
15
|
-
TadaBuildMeta,
|
|
16
|
-
TraceCache,
|
|
17
|
-
WatchTraceOptions,
|
|
18
|
-
} from './compiler-types';
|
|
7
|
+
import type { TraceCache, WatchTraceOptions } from './compiler-types';
|
|
19
8
|
import {
|
|
20
9
|
bundleWatchAssets,
|
|
21
10
|
ensureHighlighter,
|
|
22
11
|
makeTempBuildDir,
|
|
23
12
|
populateStaticAssets,
|
|
24
13
|
removeDirIfExists,
|
|
25
|
-
writeAssets,
|
|
26
14
|
} from './assets';
|
|
15
|
+
import { validateConfig, validateProjectConfigLinks } from './validation';
|
|
16
|
+
import { buildFailedFromError, buildSucceeded } from './build-result';
|
|
27
17
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
} from './
|
|
18
|
+
buildFailedWithDiagnostics,
|
|
19
|
+
renderContentRecord,
|
|
20
|
+
renderPublicRecord,
|
|
21
|
+
} from './build-helpers';
|
|
32
22
|
|
|
33
23
|
export async function buildFull({
|
|
34
24
|
traceCache,
|
|
@@ -36,7 +26,7 @@ export async function buildFull({
|
|
|
36
26
|
}: {
|
|
37
27
|
traceCache: TraceCache;
|
|
38
28
|
traceOptions: WatchTraceOptions;
|
|
39
|
-
}): Promise<CompilerBuildResult
|
|
29
|
+
}): Promise<CompilerBuildResult> {
|
|
40
30
|
const distDir = getDistDir();
|
|
41
31
|
const outputDir = makeTempBuildDir(distDir);
|
|
42
32
|
try {
|
|
@@ -44,8 +34,7 @@ export async function buildFull({
|
|
|
44
34
|
const scan = scanProject(siteVariables);
|
|
45
35
|
const configDiagnostics = validateConfig(scan);
|
|
46
36
|
if (configDiagnostics.length > 0) {
|
|
47
|
-
|
|
48
|
-
return { ok: false, diagnostics: configDiagnostics };
|
|
37
|
+
return buildFailedWithDiagnostics(outputDir, configDiagnostics);
|
|
49
38
|
}
|
|
50
39
|
|
|
51
40
|
compileTemplates(siteVariables);
|
|
@@ -56,33 +45,34 @@ export async function buildFull({
|
|
|
56
45
|
|
|
57
46
|
const contentRecords = new Map<string, TadaSourceRecord>();
|
|
58
47
|
for (const filePath of scan.contentFiles) {
|
|
59
|
-
const record =
|
|
48
|
+
const record = renderContentRecord({
|
|
60
49
|
filePath,
|
|
61
50
|
siteVariables,
|
|
62
51
|
scan,
|
|
63
52
|
assetFiles,
|
|
64
53
|
outputDir,
|
|
65
54
|
traceCache,
|
|
66
|
-
|
|
55
|
+
traceOptions,
|
|
67
56
|
cachedTraceSourceDir: distDir,
|
|
68
57
|
});
|
|
69
|
-
if (record
|
|
70
|
-
writeAssets(outputDir, record.outputs);
|
|
58
|
+
if (record) {
|
|
71
59
|
contentRecords.set(filePath, record);
|
|
72
60
|
}
|
|
73
61
|
}
|
|
74
62
|
|
|
75
63
|
const publicRecords = new Map<string, TadaSourceRecord>();
|
|
76
64
|
for (const filePath of scan.publicFiles) {
|
|
77
|
-
const record =
|
|
78
|
-
|
|
65
|
+
const record = renderPublicRecord({
|
|
66
|
+
filePath,
|
|
67
|
+
publicDir: scan.publicDir,
|
|
68
|
+
outputDir,
|
|
69
|
+
});
|
|
79
70
|
publicRecords.set(filePath, record);
|
|
80
71
|
}
|
|
81
72
|
|
|
82
73
|
const linkDiagnostics = validateProjectConfigLinks(scan.validTargets);
|
|
83
74
|
if (linkDiagnostics.length > 0) {
|
|
84
|
-
|
|
85
|
-
return { ok: false, diagnostics: linkDiagnostics };
|
|
75
|
+
return buildFailedWithDiagnostics(outputDir, linkDiagnostics);
|
|
86
76
|
}
|
|
87
77
|
|
|
88
78
|
const nextSnapshot = createSnapshot({
|
|
@@ -95,29 +85,13 @@ export async function buildFull({
|
|
|
95
85
|
publicRecords,
|
|
96
86
|
});
|
|
97
87
|
|
|
98
|
-
return {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
stagedPath: outputDir,
|
|
104
|
-
targetPath: distDir,
|
|
105
|
-
},
|
|
106
|
-
meta: {
|
|
107
|
-
htmlAssetsByPath: collectHtmlAssetsByPath(nextSnapshot.contentRecords),
|
|
108
|
-
htmlAnalysisByPath: collectHtmlAnalysisByPath(
|
|
109
|
-
nextSnapshot.contentRecords,
|
|
110
|
-
),
|
|
111
|
-
siteVariables,
|
|
112
|
-
},
|
|
113
|
-
};
|
|
88
|
+
return buildSucceeded(nextSnapshot, {
|
|
89
|
+
kind: 'replace-root',
|
|
90
|
+
stagedPath: outputDir,
|
|
91
|
+
targetPath: distDir,
|
|
92
|
+
});
|
|
114
93
|
} catch (error) {
|
|
115
94
|
removeDirIfExists(outputDir);
|
|
116
|
-
return
|
|
117
|
-
ok: false,
|
|
118
|
-
diagnostics: diagnosticsFromMessages([
|
|
119
|
-
error instanceof Error ? error.message : String(error),
|
|
120
|
-
]),
|
|
121
|
-
};
|
|
95
|
+
return buildFailedFromError(error);
|
|
122
96
|
}
|
|
123
97
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createContentRecord, createPublicRecord } from '../source-records';
|
|
2
|
+
import type { SiteVariables } from '../types';
|
|
3
|
+
import type { TadaProjectScan, TadaSourceRecord } from './snapshot';
|
|
4
|
+
import type { CompilerBuildResult, WatchDiagnostic } from './types';
|
|
5
|
+
import type { TraceCache, WatchTraceOptions } from './compiler-types';
|
|
6
|
+
import { removeDirIfExists, writeAssets } from './assets';
|
|
7
|
+
|
|
8
|
+
export function buildFailedWithDiagnostics(
|
|
9
|
+
outputDir: string,
|
|
10
|
+
diagnostics: WatchDiagnostic[],
|
|
11
|
+
): CompilerBuildResult {
|
|
12
|
+
removeDirIfExists(outputDir);
|
|
13
|
+
return { ok: false, diagnostics };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function renderContentRecord({
|
|
17
|
+
filePath,
|
|
18
|
+
siteVariables,
|
|
19
|
+
scan,
|
|
20
|
+
assetFiles,
|
|
21
|
+
outputDir,
|
|
22
|
+
traceCache,
|
|
23
|
+
traceOptions,
|
|
24
|
+
cachedTraceSourceDir,
|
|
25
|
+
}: {
|
|
26
|
+
filePath: string;
|
|
27
|
+
siteVariables: SiteVariables;
|
|
28
|
+
scan: TadaProjectScan;
|
|
29
|
+
assetFiles: string[];
|
|
30
|
+
outputDir: string;
|
|
31
|
+
traceCache: TraceCache;
|
|
32
|
+
traceOptions: WatchTraceOptions;
|
|
33
|
+
cachedTraceSourceDir: string;
|
|
34
|
+
}): TadaSourceRecord | undefined {
|
|
35
|
+
const record = createContentRecord({
|
|
36
|
+
filePath,
|
|
37
|
+
siteVariables,
|
|
38
|
+
scan,
|
|
39
|
+
assetFiles,
|
|
40
|
+
outputDir,
|
|
41
|
+
traceCache,
|
|
42
|
+
traceToolAvailability: traceOptions.toolAvailability,
|
|
43
|
+
cachedTraceSourceDir,
|
|
44
|
+
});
|
|
45
|
+
if (record.outputs.size === 0) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
writeAssets(outputDir, record.outputs);
|
|
49
|
+
return record;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function renderPublicRecord({
|
|
53
|
+
filePath,
|
|
54
|
+
publicDir,
|
|
55
|
+
outputDir,
|
|
56
|
+
}: {
|
|
57
|
+
filePath: string;
|
|
58
|
+
publicDir: string;
|
|
59
|
+
outputDir?: string;
|
|
60
|
+
}): TadaSourceRecord {
|
|
61
|
+
const record = createPublicRecord(filePath, publicDir);
|
|
62
|
+
if (outputDir) {
|
|
63
|
+
writeAssets(outputDir, record.outputs);
|
|
64
|
+
}
|
|
65
|
+
return record;
|
|
66
|
+
}
|