@stati/core 1.3.2 → 1.5.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.
- package/README.md +1 -1
- package/dist/core/dev.d.ts.map +1 -1
- package/dist/core/dev.js +176 -48
- package/dist/core/isg/hash.d.ts.map +1 -1
- package/dist/core/isg/hash.js +13 -1
- package/dist/core/markdown.d.ts.map +1 -1
- package/dist/core/markdown.js +21 -2
- package/dist/core/preview.d.ts +19 -0
- package/dist/core/preview.d.ts.map +1 -0
- package/dist/core/preview.js +159 -0
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +83 -11
- package/dist/core/utils/error-overlay.d.ts +31 -0
- package/dist/core/utils/error-overlay.d.ts.map +1 -0
- package/dist/core/utils/error-overlay.js +562 -0
- package/dist/core/utils/partial-validation.d.ts +6 -0
- package/dist/core/utils/partial-validation.d.ts.map +1 -0
- package/dist/core/utils/partial-validation.js +129 -0
- package/dist/core/utils/server.d.ts +23 -0
- package/dist/core/utils/server.d.ts.map +1 -0
- package/dist/core/utils/server.js +61 -0
- package/dist/core/utils/template-errors.d.ts +28 -0
- package/dist/core/utils/template-errors.d.ts.map +1 -0
- package/dist/core/utils/template-errors.js +128 -0
- package/dist/core/utils/version.d.ts +6 -0
- package/dist/core/utils/version.d.ts.map +1 -0
- package/dist/core/utils/version.js +20 -0
- package/dist/env.d.ts +3 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +7 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/package.json +1 -1
package/dist/core/templates.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { Eta } from 'eta';
|
|
2
|
-
import { join, dirname, relative, basename } from 'path';
|
|
2
|
+
import { join, dirname, relative, basename, posix } from 'path';
|
|
3
3
|
import glob from 'fast-glob';
|
|
4
4
|
import { TEMPLATE_EXTENSION } from '../constants.js';
|
|
5
|
+
import { getStatiVersion } from './utils/version.js';
|
|
6
|
+
import { getEnv } from '../env.js';
|
|
5
7
|
import { isCollectionIndexPage, discoverLayout, getCollectionPathForPage, } from './utils/template-discovery.js';
|
|
6
8
|
import { resolveSrcDir } from './utils/paths.js';
|
|
9
|
+
import { createTemplateError } from './utils/template-errors.js';
|
|
10
|
+
import { createValidatingPartialsProxy } from './utils/partial-validation.js';
|
|
7
11
|
/**
|
|
8
12
|
* Groups pages by their tags for aggregation purposes.
|
|
9
13
|
*
|
|
@@ -146,7 +150,7 @@ async function discoverPartials(pagePath, config) {
|
|
|
146
150
|
const fullPath = join(folderPath, etaFile);
|
|
147
151
|
// Get relative path from srcDir to the partial file
|
|
148
152
|
const relativePath = relative(srcDir, fullPath);
|
|
149
|
-
partials[partialName] = relativePath;
|
|
153
|
+
partials[partialName] = posix.normalize(relativePath);
|
|
150
154
|
}
|
|
151
155
|
}
|
|
152
156
|
}
|
|
@@ -156,7 +160,9 @@ export function createTemplateEngine(config) {
|
|
|
156
160
|
const templateDir = resolveSrcDir(config);
|
|
157
161
|
const eta = new Eta({
|
|
158
162
|
views: templateDir,
|
|
159
|
-
cache:
|
|
163
|
+
cache: getEnv() === 'production',
|
|
164
|
+
cacheFilepaths: getEnv() === 'production',
|
|
165
|
+
varName: 'stati',
|
|
160
166
|
});
|
|
161
167
|
return eta;
|
|
162
168
|
}
|
|
@@ -188,22 +194,83 @@ export async function renderPage(page, body, config, eta, navigation, allPages)
|
|
|
188
194
|
collection: collectionData, // Add collection data for index pages
|
|
189
195
|
// Add custom filters to context
|
|
190
196
|
...(config.eta?.filters || {}),
|
|
197
|
+
generator: {
|
|
198
|
+
version: getStatiVersion(),
|
|
199
|
+
},
|
|
191
200
|
};
|
|
192
201
|
// Render partials and store their content
|
|
202
|
+
// Use multiple passes to allow partials to reference other partials
|
|
193
203
|
const renderedPartials = {};
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
204
|
+
const maxPasses = 3; // Prevent infinite loops
|
|
205
|
+
for (let pass = 0; pass < maxPasses; pass++) {
|
|
206
|
+
let partialsToRender;
|
|
207
|
+
if (pass === 0) {
|
|
208
|
+
// First pass: render all partials
|
|
209
|
+
partialsToRender = { ...partialPaths };
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// Subsequent passes: re-render partials that might need updated dependencies
|
|
213
|
+
// For simplicity, re-render all partials to ensure they have access to all previously rendered ones
|
|
214
|
+
// TODO: Optimize by tracking which partials changed or have dependencies
|
|
215
|
+
partialsToRender = { ...partialPaths };
|
|
216
|
+
}
|
|
217
|
+
if (Object.keys(partialsToRender).length === 0) {
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
let progressMade = false;
|
|
221
|
+
const passRenderedPartials = {};
|
|
222
|
+
for (const [partialName, partialPath] of Object.entries(partialsToRender)) {
|
|
223
|
+
try {
|
|
224
|
+
// Create context with all previously rendered partials available
|
|
225
|
+
const combinedPartials = { ...renderedPartials, ...passRenderedPartials };
|
|
226
|
+
const partialContext = {
|
|
227
|
+
...baseContext,
|
|
228
|
+
partials: createValidatingPartialsProxy(combinedPartials), // Include both previous and current pass partials with validation
|
|
229
|
+
};
|
|
230
|
+
const renderedContent = await eta.renderAsync(partialPath, partialContext);
|
|
231
|
+
passRenderedPartials[partialName] = renderedContent;
|
|
232
|
+
progressMade = true;
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
// If this is the last pass, log the error and create placeholder
|
|
236
|
+
if (pass === maxPasses - 1) {
|
|
237
|
+
console.warn(`Warning: Failed to render partial ${partialName} at ${partialPath}:`, error);
|
|
238
|
+
// In development mode, throw enhanced template error for partials too
|
|
239
|
+
if (getEnv() === 'development') {
|
|
240
|
+
const templateError = createTemplateError(error instanceof Error ? error : new Error(String(error)), partialPath);
|
|
241
|
+
throw templateError;
|
|
242
|
+
}
|
|
243
|
+
passRenderedPartials[partialName] = `<!-- Error rendering partial: ${partialName} -->`;
|
|
244
|
+
progressMade = true;
|
|
245
|
+
}
|
|
246
|
+
// Otherwise, use existing content if available, or skip for retry
|
|
247
|
+
else if (renderedPartials[partialName]) {
|
|
248
|
+
passRenderedPartials[partialName] = renderedPartials[partialName];
|
|
249
|
+
}
|
|
250
|
+
// For failed partials on non-last pass, still count as progress to allow retries
|
|
251
|
+
else {
|
|
252
|
+
progressMade = true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
198
255
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
256
|
+
// Update the rendered partials with this pass's results
|
|
257
|
+
Object.assign(renderedPartials, passRenderedPartials);
|
|
258
|
+
// If no progress was made, break to avoid infinite loop
|
|
259
|
+
if (!progressMade) {
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
// If this is pass 0, always do at least one more pass to allow interdependencies
|
|
263
|
+
if (pass === 0) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
// For subsequent passes, only continue if we're not at max passes yet
|
|
267
|
+
if (pass >= maxPasses - 1) {
|
|
268
|
+
break;
|
|
202
269
|
}
|
|
203
270
|
}
|
|
204
271
|
const context = {
|
|
205
272
|
...baseContext,
|
|
206
|
-
partials: renderedPartials, // Add rendered partials
|
|
273
|
+
partials: createValidatingPartialsProxy(renderedPartials), // Add rendered partials with validation
|
|
207
274
|
};
|
|
208
275
|
try {
|
|
209
276
|
if (!layoutPath) {
|
|
@@ -214,6 +281,11 @@ export async function renderPage(page, body, config, eta, navigation, allPages)
|
|
|
214
281
|
}
|
|
215
282
|
catch (error) {
|
|
216
283
|
console.error(`Error rendering layout ${layoutPath || 'unknown'}:`, error);
|
|
284
|
+
// In development mode, throw enhanced template error for better debugging
|
|
285
|
+
if (getEnv() === 'development') {
|
|
286
|
+
const templateError = createTemplateError(error instanceof Error ? error : new Error(String(error)), layoutPath || undefined);
|
|
287
|
+
throw templateError;
|
|
288
|
+
}
|
|
217
289
|
return createFallbackHtml(page, body);
|
|
218
290
|
}
|
|
219
291
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error overlay utility for displaying pretty errors in development mode.
|
|
3
|
+
* Provides a user-friendly interface for template rendering and build errors.
|
|
4
|
+
*/
|
|
5
|
+
export interface ErrorDetails {
|
|
6
|
+
type: 'template' | 'build' | 'markdown' | 'config';
|
|
7
|
+
message: string;
|
|
8
|
+
stack?: string;
|
|
9
|
+
file?: string;
|
|
10
|
+
line?: number;
|
|
11
|
+
column?: number;
|
|
12
|
+
code?: string;
|
|
13
|
+
context?: {
|
|
14
|
+
before?: string[];
|
|
15
|
+
after?: string[];
|
|
16
|
+
};
|
|
17
|
+
suggestions?: string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates a styled error overlay HTML that displays comprehensive error information.
|
|
21
|
+
*
|
|
22
|
+
* @param error - The error details to display
|
|
23
|
+
* @param requestPath - The path that triggered the error
|
|
24
|
+
* @returns HTML string for the error overlay
|
|
25
|
+
*/
|
|
26
|
+
export declare function createErrorOverlay(error: ErrorDetails, requestPath: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Parses error information from various error types to create structured ErrorDetails.
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseErrorDetails(error: Error, type: ErrorDetails['type'], filePath?: string): ErrorDetails;
|
|
31
|
+
//# sourceMappingURL=error-overlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-overlay.d.ts","sourceRoot":"","sources":["../../../src/core/utils/error-overlay.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE;QACR,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAwbnF;AA0DD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAC1B,QAAQ,CAAC,EAAE,MAAM,GAChB,YAAY,CAkCd"}
|