@stati/core 1.27.0 → 1.27.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/dist/core/build.js +5 -5
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/content.js +19 -3
- package/dist/core/isg/builder.d.ts +9 -6
- package/dist/core/isg/builder.d.ts.map +1 -1
- package/dist/core/isg/builder.js +23 -33
- package/dist/core/isg/deps.d.ts +14 -2
- package/dist/core/isg/deps.d.ts.map +1 -1
- package/dist/core/isg/deps.js +24 -7
- package/dist/core/isg/ttl.d.ts.map +1 -1
- package/dist/core/isg/ttl.js +3 -25
- package/dist/core/utils/date.utils.d.ts +31 -0
- package/dist/core/utils/date.utils.d.ts.map +1 -0
- package/dist/core/utils/date.utils.js +52 -0
- package/dist/core/utils/index.d.ts +1 -0
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core/utils/index.js +2 -0
- package/dist/core/utils/template-discovery.utils.d.ts +8 -6
- package/dist/core/utils/template-discovery.utils.d.ts.map +1 -1
- package/dist/core/utils/template-discovery.utils.js +43 -12
- package/dist/rss/generator.d.ts.map +1 -1
- package/dist/rss/generator.js +6 -4
- package/dist/types/content.d.ts +8 -5
- package/dist/types/content.d.ts.map +1 -1
- package/dist/types/rss.d.ts +1 -1
- package/package.json +1 -1
package/dist/core/build.js
CHANGED
|
@@ -273,7 +273,7 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
|
|
|
273
273
|
const shouldRebuild = options.force ||
|
|
274
274
|
config.isg?.enabled === false ||
|
|
275
275
|
!(await pathExists(outputPath)) ||
|
|
276
|
-
(await shouldRebuildPage(page, existingEntry, config, buildTime, renderInputsHash));
|
|
276
|
+
(await shouldRebuildPage(page, existingEntry, config, pages, buildTime, renderInputsHash));
|
|
277
277
|
const shouldRebuildTime = performance.now() - shouldRebuildStart;
|
|
278
278
|
totalShouldRebuildTime += shouldRebuildTime;
|
|
279
279
|
if (!shouldRebuild) {
|
|
@@ -357,10 +357,10 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
|
|
|
357
357
|
if (!options.skipCacheUpdate) {
|
|
358
358
|
const cacheEntryStart = performance.now();
|
|
359
359
|
if (existingEntry) {
|
|
360
|
-
manifest.entries[cacheKey] = await updateCacheEntry(existingEntry, page, config, buildTime, false, renderInputsHash);
|
|
360
|
+
manifest.entries[cacheKey] = await updateCacheEntry(existingEntry, page, config, pages, buildTime, false, renderInputsHash);
|
|
361
361
|
}
|
|
362
362
|
else {
|
|
363
|
-
manifest.entries[cacheKey] = await createCacheEntry(page, config, buildTime, renderInputsHash);
|
|
363
|
+
manifest.entries[cacheKey] = await createCacheEntry(page, config, pages, buildTime, renderInputsHash);
|
|
364
364
|
}
|
|
365
365
|
totalCacheEntryTime += performance.now() - cacheEntryStart;
|
|
366
366
|
}
|
|
@@ -393,11 +393,11 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
|
|
|
393
393
|
for (const { cacheKey, page, existingEntry, renderInputsHash } of pendingCacheUpdates) {
|
|
394
394
|
if (existingEntry) {
|
|
395
395
|
// Fast update: reuse existing deps, just update hashes and timestamp
|
|
396
|
-
manifest.entries[cacheKey] = await updateCacheEntry(existingEntry, page, config, buildTime, true, // fastUpdate = true in dev mode
|
|
396
|
+
manifest.entries[cacheKey] = await updateCacheEntry(existingEntry, page, config, pages, buildTime, true, // fastUpdate = true in dev mode
|
|
397
397
|
renderInputsHash);
|
|
398
398
|
}
|
|
399
399
|
else {
|
|
400
|
-
manifest.entries[cacheKey] = await createCacheEntry(page, config, buildTime, renderInputsHash);
|
|
400
|
+
manifest.entries[cacheKey] = await createCacheEntry(page, config, pages, buildTime, renderInputsHash);
|
|
401
401
|
}
|
|
402
402
|
}
|
|
403
403
|
totalCacheEntryTime = performance.now() - cacheEntryStart;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/core/content.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,aAAa,CAAC,EAAE,OAAO,GACtB,OAAO,CAAC,SAAS,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/core/content.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,aAAa,CAAC,EAAE,OAAO,GACtB,OAAO,CAAC,SAAS,EAAE,CAAC,CAgDtB"}
|
package/dist/core/content.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import glob from 'fast-glob';
|
|
2
|
-
import { readFile, resolveSrcDir } from './utils/index.js';
|
|
2
|
+
import { readFile, resolveSrcDir, getFrontMatterDate } from './utils/index.js';
|
|
3
3
|
import matter from 'gray-matter';
|
|
4
4
|
import { relative, dirname, basename } from 'node:path';
|
|
5
5
|
import { MARKDOWN_EXTENSION } from '../constants.js';
|
|
@@ -49,8 +49,11 @@ export async function loadContent(config, includeDrafts) {
|
|
|
49
49
|
frontMatter,
|
|
50
50
|
content: markdown,
|
|
51
51
|
};
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
const publishedAt = getFrontMatterDate(frontMatter, (field, value) => {
|
|
53
|
+
console.warn(`Ignoring invalid date in "${field}" of ${file}: ${describeDateValue(value)}`);
|
|
54
|
+
});
|
|
55
|
+
if (publishedAt) {
|
|
56
|
+
page.publishedAt = publishedAt;
|
|
54
57
|
}
|
|
55
58
|
pages.push(page);
|
|
56
59
|
}
|
|
@@ -64,6 +67,19 @@ function computeSlug(relativePath) {
|
|
|
64
67
|
}
|
|
65
68
|
return dir === '.' ? `/${name}` : `/${dir}/${name}`;
|
|
66
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Describes a rejected front matter date for a warning without calling the value's
|
|
72
|
+
* own conversion methods, which a YAML mapping such as `{ toString: x }` can break.
|
|
73
|
+
*/
|
|
74
|
+
function describeDateValue(value) {
|
|
75
|
+
if (typeof value === 'string') {
|
|
76
|
+
return JSON.stringify(value);
|
|
77
|
+
}
|
|
78
|
+
if (typeof value === 'object' && !(value instanceof Date)) {
|
|
79
|
+
return Array.isArray(value) ? 'a list' : 'a mapping';
|
|
80
|
+
}
|
|
81
|
+
return String(value);
|
|
82
|
+
}
|
|
67
83
|
function computeUrl(slug, frontMatter) {
|
|
68
84
|
if (frontMatter.permalink && typeof frontMatter.permalink === 'string') {
|
|
69
85
|
return frontMatter.permalink;
|
|
@@ -7,34 +7,36 @@ import type { PageModel, CacheEntry, StatiConfig } from '../../types/index.js';
|
|
|
7
7
|
* @param page - The page model to check
|
|
8
8
|
* @param entry - Existing cache entry, or undefined if not cached
|
|
9
9
|
* @param config - Stati configuration
|
|
10
|
+
* @param allPages - All pages in the site, used to resolve the same layout as rendering
|
|
10
11
|
* @param now - Current date/time
|
|
11
12
|
* @param renderInputsHash - Optional hash of asset URLs and injection settings
|
|
12
13
|
* @returns True if the page should be rebuilt
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
16
|
* ```typescript
|
|
16
|
-
* const shouldRebuild = await shouldRebuildPage(page, cacheEntry, config, new Date());
|
|
17
|
+
* const shouldRebuild = await shouldRebuildPage(page, cacheEntry, config, pages, new Date());
|
|
17
18
|
* if (shouldRebuild) {
|
|
18
19
|
* console.log('Page needs rebuilding');
|
|
19
20
|
* }
|
|
20
21
|
* ```
|
|
21
22
|
*/
|
|
22
|
-
export declare function shouldRebuildPage(page: PageModel, entry: CacheEntry | undefined, config: StatiConfig, now: Date, renderInputsHash?: string): Promise<boolean>;
|
|
23
|
+
export declare function shouldRebuildPage(page: PageModel, entry: CacheEntry | undefined, config: StatiConfig, allPages: PageModel[], now: Date, renderInputsHash?: string): Promise<boolean>;
|
|
23
24
|
/**
|
|
24
25
|
* Creates a new cache entry for a page after it has been rendered.
|
|
25
26
|
*
|
|
26
27
|
* @param page - The page model
|
|
27
28
|
* @param config - Stati configuration
|
|
29
|
+
* @param allPages - All pages in the site, used to resolve the same layout as rendering
|
|
28
30
|
* @param renderedAt - When the page was rendered
|
|
29
31
|
* @param renderInputsHash - Optional hash of asset URLs and injection settings
|
|
30
32
|
* @returns New cache entry
|
|
31
33
|
*
|
|
32
34
|
* @example
|
|
33
35
|
* ```typescript
|
|
34
|
-
* const entry = await createCacheEntry(page, config, new Date());
|
|
36
|
+
* const entry = await createCacheEntry(page, config, pages, new Date());
|
|
35
37
|
* ```
|
|
36
38
|
*/
|
|
37
|
-
export declare function createCacheEntry(page: PageModel, config: StatiConfig, renderedAt: Date, renderInputsHash?: string): Promise<CacheEntry>;
|
|
39
|
+
export declare function createCacheEntry(page: PageModel, config: StatiConfig, allPages: PageModel[], renderedAt: Date, renderInputsHash?: string): Promise<CacheEntry>;
|
|
38
40
|
/**
|
|
39
41
|
* Updates an existing cache entry with new information after rebuilding.
|
|
40
42
|
* In dev mode, this is optimized to reuse the existing deps array since
|
|
@@ -43,6 +45,7 @@ export declare function createCacheEntry(page: PageModel, config: StatiConfig, r
|
|
|
43
45
|
* @param entry - Existing cache entry
|
|
44
46
|
* @param page - The page model
|
|
45
47
|
* @param config - Stati configuration
|
|
48
|
+
* @param allPages - All pages in the site, used to resolve the same layout as rendering
|
|
46
49
|
* @param renderedAt - When the page was rendered
|
|
47
50
|
* @param fastUpdate - If true, skip expensive dep tracking (dev mode optimization)
|
|
48
51
|
* @param renderInputsHash - Optional hash of asset URLs and injection settings
|
|
@@ -50,8 +53,8 @@ export declare function createCacheEntry(page: PageModel, config: StatiConfig, r
|
|
|
50
53
|
*
|
|
51
54
|
* @example
|
|
52
55
|
* ```typescript
|
|
53
|
-
* const updatedEntry = await updateCacheEntry(existingEntry, page, config, new Date());
|
|
56
|
+
* const updatedEntry = await updateCacheEntry(existingEntry, page, config, pages, new Date());
|
|
54
57
|
* ```
|
|
55
58
|
*/
|
|
56
|
-
export declare function updateCacheEntry(entry: CacheEntry, page: PageModel, config: StatiConfig, renderedAt: Date, fastUpdate?: boolean, renderInputsHash?: string): Promise<CacheEntry>;
|
|
59
|
+
export declare function updateCacheEntry(entry: CacheEntry, page: PageModel, config: StatiConfig, allPages: PageModel[], renderedAt: Date, fastUpdate?: boolean, renderInputsHash?: string): Promise<CacheEntry>;
|
|
57
60
|
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/core/isg/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/core/isg/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAqE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,UAAU,GAAG,SAAS,EAC7B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,SAAS,EAAE,EACrB,GAAG,EAAE,IAAI,EACT,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,OAAO,CAAC,CAoKlB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,SAAS,EAAE,EACrB,UAAU,EAAE,IAAI,EAChB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,UAAU,CAAC,CAqFrB;AAkDD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,SAAS,EAAE,EACrB,UAAU,EAAE,IAAI,EAChB,UAAU,UAAQ,EAClB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,UAAU,CAAC,CAmDrB"}
|
package/dist/core/isg/builder.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { computeContentHash, computeFileHash, computeInputsHash } from './hash.js';
|
|
2
|
-
import { trackTemplateDependencies } from './deps.js';
|
|
2
|
+
import { trackTemplateDependencies, resolveLayoutDependency } from './deps.js';
|
|
3
3
|
import { computeEffectiveTTL, computeNextRebuildAt, isPageFrozen } from './ttl.js';
|
|
4
4
|
import { validatePageISGOverrides, extractNumericOverride } from './validation.js';
|
|
5
|
+
import { getFrontMatterDate } from '../utils/index.js';
|
|
5
6
|
import { performance } from 'node:perf_hooks';
|
|
6
7
|
/**
|
|
7
8
|
* Determines the output path for a page.
|
|
@@ -64,19 +65,20 @@ function isValidCacheEntry(entry) {
|
|
|
64
65
|
* @param page - The page model to check
|
|
65
66
|
* @param entry - Existing cache entry, or undefined if not cached
|
|
66
67
|
* @param config - Stati configuration
|
|
68
|
+
* @param allPages - All pages in the site, used to resolve the same layout as rendering
|
|
67
69
|
* @param now - Current date/time
|
|
68
70
|
* @param renderInputsHash - Optional hash of asset URLs and injection settings
|
|
69
71
|
* @returns True if the page should be rebuilt
|
|
70
72
|
*
|
|
71
73
|
* @example
|
|
72
74
|
* ```typescript
|
|
73
|
-
* const shouldRebuild = await shouldRebuildPage(page, cacheEntry, config, new Date());
|
|
75
|
+
* const shouldRebuild = await shouldRebuildPage(page, cacheEntry, config, pages, new Date());
|
|
74
76
|
* if (shouldRebuild) {
|
|
75
77
|
* console.log('Page needs rebuilding');
|
|
76
78
|
* }
|
|
77
79
|
* ```
|
|
78
80
|
*/
|
|
79
|
-
export async function shouldRebuildPage(page, entry, config, now, renderInputsHash) {
|
|
81
|
+
export async function shouldRebuildPage(page, entry, config, allPages, now, renderInputsHash) {
|
|
80
82
|
if (config.isg?.enabled === false) {
|
|
81
83
|
return true;
|
|
82
84
|
}
|
|
@@ -95,7 +97,7 @@ export async function shouldRebuildPage(page, entry, config, now, renderInputsHa
|
|
|
95
97
|
// Track dependencies with error handling
|
|
96
98
|
let deps;
|
|
97
99
|
try {
|
|
98
|
-
deps = await trackTemplateDependencies(page, config);
|
|
100
|
+
deps = await trackTemplateDependencies(page, config, allPages);
|
|
99
101
|
}
|
|
100
102
|
catch (error) {
|
|
101
103
|
if (error instanceof Error && error.name === 'CircularDependencyError') {
|
|
@@ -210,16 +212,17 @@ export async function shouldRebuildPage(page, entry, config, now, renderInputsHa
|
|
|
210
212
|
*
|
|
211
213
|
* @param page - The page model
|
|
212
214
|
* @param config - Stati configuration
|
|
215
|
+
* @param allPages - All pages in the site, used to resolve the same layout as rendering
|
|
213
216
|
* @param renderedAt - When the page was rendered
|
|
214
217
|
* @param renderInputsHash - Optional hash of asset URLs and injection settings
|
|
215
218
|
* @returns New cache entry
|
|
216
219
|
*
|
|
217
220
|
* @example
|
|
218
221
|
* ```typescript
|
|
219
|
-
* const entry = await createCacheEntry(page, config, new Date());
|
|
222
|
+
* const entry = await createCacheEntry(page, config, pages, new Date());
|
|
220
223
|
* ```
|
|
221
224
|
*/
|
|
222
|
-
export async function createCacheEntry(page, config, renderedAt, renderInputsHash) {
|
|
225
|
+
export async function createCacheEntry(page, config, allPages, renderedAt, renderInputsHash) {
|
|
223
226
|
const timings = {};
|
|
224
227
|
let start = performance.now();
|
|
225
228
|
// Validate page-level ISG overrides first
|
|
@@ -231,7 +234,7 @@ export async function createCacheEntry(page, config, renderedAt, renderInputsHas
|
|
|
231
234
|
timings.contentHash = performance.now() - start;
|
|
232
235
|
// Track all template dependencies
|
|
233
236
|
start = performance.now();
|
|
234
|
-
const deps = await trackTemplateDependencies(page, config);
|
|
237
|
+
const deps = await trackTemplateDependencies(page, config, allPages);
|
|
235
238
|
timings.trackDeps = performance.now() - start;
|
|
236
239
|
// Compute hashes for all dependencies
|
|
237
240
|
start = performance.now();
|
|
@@ -338,6 +341,7 @@ async function hasTemplateStructureChanged(entry) {
|
|
|
338
341
|
* @param entry - Existing cache entry
|
|
339
342
|
* @param page - The page model
|
|
340
343
|
* @param config - Stati configuration
|
|
344
|
+
* @param allPages - All pages in the site, used to resolve the same layout as rendering
|
|
341
345
|
* @param renderedAt - When the page was rendered
|
|
342
346
|
* @param fastUpdate - If true, skip expensive dep tracking (dev mode optimization)
|
|
343
347
|
* @param renderInputsHash - Optional hash of asset URLs and injection settings
|
|
@@ -345,19 +349,24 @@ async function hasTemplateStructureChanged(entry) {
|
|
|
345
349
|
*
|
|
346
350
|
* @example
|
|
347
351
|
* ```typescript
|
|
348
|
-
* const updatedEntry = await updateCacheEntry(existingEntry, page, config, new Date());
|
|
352
|
+
* const updatedEntry = await updateCacheEntry(existingEntry, page, config, pages, new Date());
|
|
349
353
|
* ```
|
|
350
354
|
*/
|
|
351
|
-
export async function updateCacheEntry(entry, page, config, renderedAt, fastUpdate = false, renderInputsHash) {
|
|
355
|
+
export async function updateCacheEntry(entry, page, config, allPages, renderedAt, fastUpdate = false, renderInputsHash) {
|
|
352
356
|
// In fast update mode (dev), reuse existing deps to avoid expensive tracking
|
|
353
357
|
if (fastUpdate && entry.deps.length > 0) {
|
|
354
358
|
// Detect if template structure has changed (new includes/extends added)
|
|
355
359
|
// by checking if the layout file has been modified or if template content
|
|
356
360
|
// contains different dependency patterns
|
|
357
361
|
const structureChanged = await hasTemplateStructureChanged(entry);
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
362
|
+
// The page can also switch layouts without any template file changing, for example
|
|
363
|
+
// when a collection gains its first child page or a front matter layout is edited.
|
|
364
|
+
// deps[0] is always the layout, so compare it against the layout used now.
|
|
365
|
+
const layoutChanged = !structureChanged &&
|
|
366
|
+
(await resolveLayoutDependency(page, config, allPages)) !== entry.deps[0];
|
|
367
|
+
if (structureChanged || layoutChanged) {
|
|
368
|
+
// Template structure or layout changed - fall through to full dependency tracking
|
|
369
|
+
// This ensures we pick up new includes/extends and the newly selected layout
|
|
361
370
|
}
|
|
362
371
|
else {
|
|
363
372
|
// Structure unchanged - safe to reuse existing deps
|
|
@@ -380,7 +389,7 @@ export async function updateCacheEntry(entry, page, config, renderedAt, fastUpda
|
|
|
380
389
|
}
|
|
381
390
|
}
|
|
382
391
|
// Full update - create new entry and preserve original publishedAt
|
|
383
|
-
const newEntry = await createCacheEntry(page, config, renderedAt, renderInputsHash);
|
|
392
|
+
const newEntry = await createCacheEntry(page, config, allPages, renderedAt, renderInputsHash);
|
|
384
393
|
// Preserve original publishedAt if no new one is specified
|
|
385
394
|
if (!newEntry.publishedAt && entry.publishedAt) {
|
|
386
395
|
newEntry.publishedAt = entry.publishedAt;
|
|
@@ -391,24 +400,5 @@ export async function updateCacheEntry(entry, page, config, renderedAt, fastUpda
|
|
|
391
400
|
* Helper function to get published date as ISO string from page front matter.
|
|
392
401
|
*/
|
|
393
402
|
function getPublishedDateISO(page) {
|
|
394
|
-
|
|
395
|
-
// Try common field names for published date
|
|
396
|
-
const dateFields = ['publishedAt', 'published', 'date', 'createdAt'];
|
|
397
|
-
for (const field of dateFields) {
|
|
398
|
-
const value = frontMatter[field];
|
|
399
|
-
if (value) {
|
|
400
|
-
// Handle string dates
|
|
401
|
-
if (typeof value === 'string') {
|
|
402
|
-
const date = new Date(value);
|
|
403
|
-
if (!isNaN(date.getTime())) {
|
|
404
|
-
return date.toISOString();
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
// Handle Date objects
|
|
408
|
-
if (value instanceof Date && !isNaN(value.getTime())) {
|
|
409
|
-
return value.toISOString();
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
return undefined;
|
|
403
|
+
return getFrontMatterDate(page.frontMatter)?.toISOString();
|
|
414
404
|
}
|
package/dist/core/isg/deps.d.ts
CHANGED
|
@@ -22,13 +22,14 @@ export declare class CircularDependencyError extends Error {
|
|
|
22
22
|
*
|
|
23
23
|
* @param page - The page model to track dependencies for
|
|
24
24
|
* @param config - Stati configuration
|
|
25
|
+
* @param allPages - All pages in the site, used to detect collection index pages the same way rendering does
|
|
25
26
|
* @returns Array of absolute paths to actually-used template files (POSIX format)
|
|
26
27
|
* @throws {CircularDependencyError} When circular dependencies are detected in templates
|
|
27
28
|
*
|
|
28
29
|
* @example
|
|
29
30
|
* ```typescript
|
|
30
31
|
* try {
|
|
31
|
-
* const deps = await trackTemplateDependencies(page, config);
|
|
32
|
+
* const deps = await trackTemplateDependencies(page, config, allPages);
|
|
32
33
|
* console.log(`Page depends on ${deps.length} template files`);
|
|
33
34
|
* } catch (error) {
|
|
34
35
|
* if (error instanceof CircularDependencyError) {
|
|
@@ -37,7 +38,18 @@ export declare class CircularDependencyError extends Error {
|
|
|
37
38
|
* }
|
|
38
39
|
* ```
|
|
39
40
|
*/
|
|
40
|
-
export declare function trackTemplateDependencies(page: PageModel, config: StatiConfig): Promise<string[]>;
|
|
41
|
+
export declare function trackTemplateDependencies(page: PageModel, config: StatiConfig, allPages: PageModel[]): Promise<string[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Resolves the layout a page renders with, in the form stored as the first entry of its
|
|
44
|
+
* cache dependencies. Uses the same lookup as rendering, so callers can tell whether the
|
|
45
|
+
* page's layout has changed since its dependencies were recorded.
|
|
46
|
+
*
|
|
47
|
+
* @param page - The page model to resolve the layout for
|
|
48
|
+
* @param config - Stati configuration
|
|
49
|
+
* @param allPages - All pages in the site, used to detect collection index pages the same way rendering does
|
|
50
|
+
* @returns Absolute path to the layout file (POSIX format), or null if no layout applies
|
|
51
|
+
*/
|
|
52
|
+
export declare function resolveLayoutDependency(page: PageModel, config: StatiConfig, allPages: PageModel[]): Promise<string | null>;
|
|
41
53
|
/**
|
|
42
54
|
* Resolves a template name to its file path.
|
|
43
55
|
* Used for explicit layout specifications in front matter.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../../src/core/isg/deps.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAenE;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;aAE9B,eAAe,EAAE,MAAM,EAAE;gBAAzB,eAAe,EAAE,MAAM,EAAE,EACzC,OAAO,EAAE,MAAM;CAKlB;AAED
|
|
1
|
+
{"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../../src/core/isg/deps.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAenE;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;aAE9B,eAAe,EAAE,MAAM,EAAE;gBAAzB,eAAe,EAAE,MAAM,EAAE,EACzC,OAAO,EAAE,MAAM;CAKlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,SAAS,EAAE,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CAuCnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,SAAS,EAAE,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAexB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASxB"}
|
package/dist/core/isg/deps.js
CHANGED
|
@@ -42,13 +42,14 @@ export class CircularDependencyError extends Error {
|
|
|
42
42
|
*
|
|
43
43
|
* @param page - The page model to track dependencies for
|
|
44
44
|
* @param config - Stati configuration
|
|
45
|
+
* @param allPages - All pages in the site, used to detect collection index pages the same way rendering does
|
|
45
46
|
* @returns Array of absolute paths to actually-used template files (POSIX format)
|
|
46
47
|
* @throws {CircularDependencyError} When circular dependencies are detected in templates
|
|
47
48
|
*
|
|
48
49
|
* @example
|
|
49
50
|
* ```typescript
|
|
50
51
|
* try {
|
|
51
|
-
* const deps = await trackTemplateDependencies(page, config);
|
|
52
|
+
* const deps = await trackTemplateDependencies(page, config, allPages);
|
|
52
53
|
* console.log(`Page depends on ${deps.length} template files`);
|
|
53
54
|
* } catch (error) {
|
|
54
55
|
* if (error instanceof CircularDependencyError) {
|
|
@@ -57,7 +58,7 @@ export class CircularDependencyError extends Error {
|
|
|
57
58
|
* }
|
|
58
59
|
* ```
|
|
59
60
|
*/
|
|
60
|
-
export async function trackTemplateDependencies(page, config) {
|
|
61
|
+
export async function trackTemplateDependencies(page, config, allPages) {
|
|
61
62
|
// Early return if required config values are missing
|
|
62
63
|
if (!config.srcDir) {
|
|
63
64
|
console.warn('Config srcDir is missing, cannot track template dependencies');
|
|
@@ -65,16 +66,13 @@ export async function trackTemplateDependencies(page, config) {
|
|
|
65
66
|
}
|
|
66
67
|
const deps = [];
|
|
67
68
|
const srcDir = resolveSrcDir(config);
|
|
68
|
-
const relativePath = relative(srcDir, page.sourcePath);
|
|
69
69
|
// Track dependencies with circular detection
|
|
70
70
|
// The visited set will contain all templates that are actually used (not just accessible)
|
|
71
71
|
const visited = new Set();
|
|
72
72
|
const currentPath = new Set();
|
|
73
73
|
// 1. Find the layout file that will be used for this page
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
-
// Normalize to POSIX format for consistent manifest output across platforms
|
|
77
|
-
const absoluteLayoutPath = posix.join(srcDir.replace(/\\/g, '/'), layoutPath);
|
|
74
|
+
const absoluteLayoutPath = await resolveLayoutDependency(page, config, allPages);
|
|
75
|
+
if (absoluteLayoutPath) {
|
|
78
76
|
deps.push(absoluteLayoutPath);
|
|
79
77
|
// Recursively traverse the template dependency tree
|
|
80
78
|
// This populates 'visited' with all actually-used templates (not just accessible ones)
|
|
@@ -93,6 +91,25 @@ export async function trackTemplateDependencies(page, config) {
|
|
|
93
91
|
}
|
|
94
92
|
return deps;
|
|
95
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Resolves the layout a page renders with, in the form stored as the first entry of its
|
|
96
|
+
* cache dependencies. Uses the same lookup as rendering, so callers can tell whether the
|
|
97
|
+
* page's layout has changed since its dependencies were recorded.
|
|
98
|
+
*
|
|
99
|
+
* @param page - The page model to resolve the layout for
|
|
100
|
+
* @param config - Stati configuration
|
|
101
|
+
* @param allPages - All pages in the site, used to detect collection index pages the same way rendering does
|
|
102
|
+
* @returns Absolute path to the layout file (POSIX format), or null if no layout applies
|
|
103
|
+
*/
|
|
104
|
+
export async function resolveLayoutDependency(page, config, allPages) {
|
|
105
|
+
if (!config.srcDir) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const srcDir = resolveSrcDir(config);
|
|
109
|
+
const layoutPath = await discoverLayout(relative(srcDir, page.sourcePath), config, page.frontMatter.layout, isCollectionIndexPage(page, allPages));
|
|
110
|
+
// Normalize to POSIX format for consistent manifest output across platforms
|
|
111
|
+
return layoutPath ? posix.join(srcDir.replace(/\\/g, '/'), layoutPath) : null;
|
|
112
|
+
}
|
|
96
113
|
/**
|
|
97
114
|
* Resolves a template name to its file path.
|
|
98
115
|
* Used for explicit layout specifications in front matter.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../../../src/core/isg/ttl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../../../src/core/isg/ttl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AASxF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,CAW5D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAqB5E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,SAAS,EACpB,WAAW,CAAC,EAAE,IAAI,GACjB,MAAM,CAkBR;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,GAAG,EAAE,IAAI,CAAC;IACV,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,IAAI,GAAG,IAAI,CAqBd;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAiBlE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,IAAI,GACR,MAAM,CAyBR"}
|
package/dist/core/isg/ttl.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CLOCK_DRIFT_TOLERANCE_MS, DEFAULT_TTL_SECONDS, MILLISECONDS_PER_DAY, } from '../../constants.js';
|
|
2
|
+
import { getFrontMatterDate } from '../utils/index.js';
|
|
2
3
|
// dedup: time constants centralized in constants.ts
|
|
3
4
|
/**
|
|
4
5
|
* Safely gets the current UTC time with drift protection.
|
|
@@ -189,31 +190,8 @@ export function applyAgingRules(publishedAt, agingRules, defaultTTL, now) {
|
|
|
189
190
|
}
|
|
190
191
|
/**
|
|
191
192
|
* Helper function to extract published date from page front matter.
|
|
192
|
-
*
|
|
193
|
-
* Uses safe date parsing to handle timezone issues.
|
|
193
|
+
* Uses the shared field order from {@link getFrontMatterDate}.
|
|
194
194
|
*/
|
|
195
195
|
function getPublishedDate(page) {
|
|
196
|
-
|
|
197
|
-
// Try common field names for published date
|
|
198
|
-
const dateFields = ['publishedAt', 'published', 'date', 'createdAt'];
|
|
199
|
-
for (const field of dateFields) {
|
|
200
|
-
const value = frontMatter[field];
|
|
201
|
-
if (value) {
|
|
202
|
-
// Handle string dates
|
|
203
|
-
if (typeof value === 'string') {
|
|
204
|
-
const safeDate = parseSafeDate(value, `front-matter field "${field}" in ${page.sourcePath}`);
|
|
205
|
-
if (safeDate) {
|
|
206
|
-
return safeDate;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
// Handle Date objects
|
|
210
|
-
if (value instanceof Date) {
|
|
211
|
-
const safeDate = getSafeCurrentTime(value);
|
|
212
|
-
if (!isNaN(safeDate.getTime())) {
|
|
213
|
-
return safeDate;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
return null;
|
|
196
|
+
return getFrontMatterDate(page.frontMatter) ?? null;
|
|
219
197
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date utilities for reading publish dates from front matter.
|
|
3
|
+
* @module core/utils/date
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Front matter fields checked for a page's publish date, in priority order.
|
|
7
|
+
* Collections, navigation, ISG aging and RSS all use this order.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PUBLISHED_DATE_FIELDS: readonly ["publishedAt", "published", "date", "createdAt"];
|
|
10
|
+
/**
|
|
11
|
+
* Returns the publish date from front matter, or `undefined` if none is usable.
|
|
12
|
+
*
|
|
13
|
+
* Checks {@link PUBLISHED_DATE_FIELDS} in order and returns the first valid value.
|
|
14
|
+
* Accepts strings (quoted YAML dates) and `Date` objects (unquoted YAML dates,
|
|
15
|
+
* which gray-matter parses into `Date`). Missing, `null` and empty values are skipped;
|
|
16
|
+
* other invalid values are reported through `onInvalid` and skipped, so a bad
|
|
17
|
+
* `publishedAt` does not hide a valid `date`.
|
|
18
|
+
*
|
|
19
|
+
* @param frontMatter - Parsed front matter of a page; `null`/`undefined` returns `undefined`
|
|
20
|
+
* @param onInvalid - Called for each present field whose value is not a valid date
|
|
21
|
+
* @returns A new `Date` instance, or `undefined`
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* getFrontMatterDate({ date: new Date('2026-01-01') }); // 2026-01-01T00:00:00.000Z
|
|
26
|
+
* getFrontMatterDate({ publishedAt: 'soon', date: '2026-06-01' }); // 2026-06-01T00:00:00.000Z
|
|
27
|
+
* getFrontMatterDate({ title: 'Undated' }); // undefined
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function getFrontMatterDate(frontMatter: Record<string, unknown> | null | undefined, onInvalid?: (field: string, value: unknown) => void): Date | undefined;
|
|
31
|
+
//# sourceMappingURL=date.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/date.utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,4DAA6D,CAAC;AAEhG;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EACvD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,GAClD,IAAI,GAAG,SAAS,CA0BlB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date utilities for reading publish dates from front matter.
|
|
3
|
+
* @module core/utils/date
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Front matter fields checked for a page's publish date, in priority order.
|
|
7
|
+
* Collections, navigation, ISG aging and RSS all use this order.
|
|
8
|
+
*/
|
|
9
|
+
export const PUBLISHED_DATE_FIELDS = ['publishedAt', 'published', 'date', 'createdAt'];
|
|
10
|
+
/**
|
|
11
|
+
* Returns the publish date from front matter, or `undefined` if none is usable.
|
|
12
|
+
*
|
|
13
|
+
* Checks {@link PUBLISHED_DATE_FIELDS} in order and returns the first valid value.
|
|
14
|
+
* Accepts strings (quoted YAML dates) and `Date` objects (unquoted YAML dates,
|
|
15
|
+
* which gray-matter parses into `Date`). Missing, `null` and empty values are skipped;
|
|
16
|
+
* other invalid values are reported through `onInvalid` and skipped, so a bad
|
|
17
|
+
* `publishedAt` does not hide a valid `date`.
|
|
18
|
+
*
|
|
19
|
+
* @param frontMatter - Parsed front matter of a page; `null`/`undefined` returns `undefined`
|
|
20
|
+
* @param onInvalid - Called for each present field whose value is not a valid date
|
|
21
|
+
* @returns A new `Date` instance, or `undefined`
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* getFrontMatterDate({ date: new Date('2026-01-01') }); // 2026-01-01T00:00:00.000Z
|
|
26
|
+
* getFrontMatterDate({ publishedAt: 'soon', date: '2026-06-01' }); // 2026-06-01T00:00:00.000Z
|
|
27
|
+
* getFrontMatterDate({ title: 'Undated' }); // undefined
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function getFrontMatterDate(frontMatter, onInvalid) {
|
|
31
|
+
if (!frontMatter) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
for (const field of PUBLISHED_DATE_FIELDS) {
|
|
35
|
+
const value = frontMatter[field];
|
|
36
|
+
if (value === undefined || value === null || (typeof value === 'string' && !value.trim())) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
let date;
|
|
40
|
+
if (typeof value === 'string') {
|
|
41
|
+
date = new Date(value);
|
|
42
|
+
}
|
|
43
|
+
else if (value instanceof Date) {
|
|
44
|
+
date = new Date(value.getTime());
|
|
45
|
+
}
|
|
46
|
+
if (date && !isNaN(date.getTime())) {
|
|
47
|
+
return date;
|
|
48
|
+
}
|
|
49
|
+
onInvalid?.(field, value);
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
@@ -27,6 +27,7 @@ export { createFallbackLogger } from './logger.utils.js';
|
|
|
27
27
|
export { compileTypeScript, createTypeScriptWatcher, compileStatiConfig, cleanupCompiledConfig, autoInjectBundles, formatBytes, detectExistingBundles, } from './typescript.utils.js';
|
|
28
28
|
export type { CompileOptions, WatchOptions } from './typescript.utils.js';
|
|
29
29
|
export { findHeadClosePosition, injectBeforeHeadClose } from './html.utils.js';
|
|
30
|
+
export { getFrontMatterDate, PUBLISHED_DATE_FIELDS } from './date.utils.js';
|
|
30
31
|
export { isEnabledEnvFlag } from './env.utils.js';
|
|
31
32
|
export { discoverOutputCssFiles, refreshCssOutputWatcher } from './dev-css-watcher.utils.js';
|
|
32
33
|
export type { RefreshCssOutputWatcherParams } from './dev-css-watcher.utils.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,GACL,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACd,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAG9E,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGpE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,WAAW,EACX,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC7F,YAAY,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,GACL,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACd,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAG9E,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGpE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,WAAW,EACX,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG/E,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC7F,YAAY,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/core/utils/index.js
CHANGED
|
@@ -42,6 +42,8 @@ export { createFallbackLogger } from './logger.utils.js';
|
|
|
42
42
|
export { compileTypeScript, createTypeScriptWatcher, compileStatiConfig, cleanupCompiledConfig, autoInjectBundles, formatBytes, detectExistingBundles, } from './typescript.utils.js';
|
|
43
43
|
// HTML manipulation utilities
|
|
44
44
|
export { findHeadClosePosition, injectBeforeHeadClose } from './html.utils.js';
|
|
45
|
+
// Date utilities
|
|
46
|
+
export { getFrontMatterDate, PUBLISHED_DATE_FIELDS } from './date.utils.js';
|
|
45
47
|
// Environment utilities
|
|
46
48
|
export { isEnabledEnvFlag } from './env.utils.js';
|
|
47
49
|
// Dev-server CSS watcher utilities
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import type { StatiConfig, PageModel } from '../../types/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Shared template discovery utilities.
|
|
4
|
-
* Extracted from templates.ts and isg/deps.ts to eliminate duplication.
|
|
5
|
-
*/
|
|
6
2
|
/**
|
|
7
3
|
* Determines if the given page is a collection index page.
|
|
8
4
|
* A collection index page is one whose URL matches a directory path that contains other pages.
|
|
9
5
|
*
|
|
6
|
+
* Rendering and ISG dependency tracking must both call this with the same page list,
|
|
7
|
+
* otherwise they can pick different layouts for the same page.
|
|
8
|
+
*
|
|
9
|
+
* Page URLs are read once per `allPages` array, at the first call; see
|
|
10
|
+
* `directoryPrefixCache` for when changes to the pages are picked up.
|
|
11
|
+
*
|
|
10
12
|
* @param page - The page to check
|
|
11
|
-
* @param allPages - All pages in the site (
|
|
13
|
+
* @param allPages - All pages in the site (treated as unchanging after the first call)
|
|
12
14
|
* @returns True if the page is a collection index page
|
|
13
15
|
*/
|
|
14
|
-
export declare function isCollectionIndexPage(page: PageModel, allPages
|
|
16
|
+
export declare function isCollectionIndexPage(page: PageModel, allPages: PageModel[]): boolean;
|
|
15
17
|
/**
|
|
16
18
|
* Discovers layout files by searching up the directory hierarchy.
|
|
17
19
|
* Supports both explicit layout specification and automatic discovery.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-discovery.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/template-discovery.utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"template-discovery.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/template-discovery.utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAoDnE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAUrF;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,EACnB,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsDxB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkBhE"}
|
|
@@ -3,15 +3,51 @@ import { pathExists } from './fs.utils.js';
|
|
|
3
3
|
import { LAYOUT_TEMPLATE } from '../../constants.js';
|
|
4
4
|
import { resolveSrcDir } from './paths.utils.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Directory prefix index per page list, so a build computes it once instead of
|
|
7
|
+
* scanning every page for every page.
|
|
8
|
+
*
|
|
9
|
+
* The index is a snapshot of the page URLs taken at the first lookup for a given array,
|
|
10
|
+
* and every later lookup for that array reuses it. In a build the first lookup happens
|
|
11
|
+
* in the render loop, after the `beforeAll` hook, so URL changes made there are included.
|
|
12
|
+
* Changes made to the same array or its pages after that are not seen; a fresh build
|
|
13
|
+
* loads a new array and gets a new snapshot. Taking one snapshot keeps rendering and
|
|
14
|
+
* ISG dependency tracking in agreement for the whole build.
|
|
8
15
|
*/
|
|
16
|
+
const directoryPrefixCache = new WeakMap();
|
|
17
|
+
function getDirectoryPrefixIndex(allPages) {
|
|
18
|
+
const cached = directoryPrefixCache.get(allPages);
|
|
19
|
+
if (cached) {
|
|
20
|
+
return cached;
|
|
21
|
+
}
|
|
22
|
+
const index = new Map();
|
|
23
|
+
for (const { url } of allPages) {
|
|
24
|
+
// Every prefix ending at a '/' is a directory this URL lives in (or is, for trailing-slash URLs)
|
|
25
|
+
for (let i = url.indexOf('/'); i !== -1; i = url.indexOf('/', i + 1)) {
|
|
26
|
+
const prefix = url.slice(0, i + 1);
|
|
27
|
+
const existing = index.get(prefix);
|
|
28
|
+
if (existing === undefined) {
|
|
29
|
+
index.set(prefix, url);
|
|
30
|
+
}
|
|
31
|
+
else if (existing !== null && existing !== url) {
|
|
32
|
+
index.set(prefix, null);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
directoryPrefixCache.set(allPages, index);
|
|
37
|
+
return index;
|
|
38
|
+
}
|
|
9
39
|
/**
|
|
10
40
|
* Determines if the given page is a collection index page.
|
|
11
41
|
* A collection index page is one whose URL matches a directory path that contains other pages.
|
|
12
42
|
*
|
|
43
|
+
* Rendering and ISG dependency tracking must both call this with the same page list,
|
|
44
|
+
* otherwise they can pick different layouts for the same page.
|
|
45
|
+
*
|
|
46
|
+
* Page URLs are read once per `allPages` array, at the first call; see
|
|
47
|
+
* `directoryPrefixCache` for when changes to the pages are picked up.
|
|
48
|
+
*
|
|
13
49
|
* @param page - The page to check
|
|
14
|
-
* @param allPages - All pages in the site (
|
|
50
|
+
* @param allPages - All pages in the site (treated as unchanging after the first call)
|
|
15
51
|
* @returns True if the page is a collection index page
|
|
16
52
|
*/
|
|
17
53
|
export function isCollectionIndexPage(page, allPages) {
|
|
@@ -19,15 +55,10 @@ export function isCollectionIndexPage(page, allPages) {
|
|
|
19
55
|
if (page.url === '/') {
|
|
20
56
|
return true;
|
|
21
57
|
}
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return allPages.some((otherPage) => otherPage.url !== page.url && otherPage.url.startsWith(pageUrlAsDir));
|
|
27
|
-
}
|
|
28
|
-
// Simplified version when we don't have all pages
|
|
29
|
-
// Assume any page ending in /index or at root is a collection page
|
|
30
|
-
return page.url.endsWith('/index') || page.slug === 'index';
|
|
58
|
+
// The page is an index when a different page's URL lives under this page's URL as a directory
|
|
59
|
+
const pageUrlAsDir = page.url.endsWith('/') ? page.url : page.url + '/';
|
|
60
|
+
const containingUrl = getDirectoryPrefixIndex(allPages).get(pageUrlAsDir);
|
|
61
|
+
return containingUrl === null || (containingUrl !== undefined && containingUrl !== page.url);
|
|
31
62
|
}
|
|
32
63
|
/**
|
|
33
64
|
* Discovers layout files by searching up the directory hierarchy.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/rss/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/rss/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA4KlD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAAE,EAClB,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,aAAa,EACzB,MAAM,CAAC,EAAE,MAAM,GACd,mBAAmB,CA4LrB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAAE,EAClB,MAAM,EAAE,WAAW,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,mBAAmB,EAAE,CAcvB"}
|
package/dist/rss/generator.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { escapeHtml } from '../seo/utils/index.js';
|
|
6
6
|
import { filterByPatterns } from './utils/index.js';
|
|
7
|
+
import { getFrontMatterDate } from '../core/utils/index.js';
|
|
7
8
|
/**
|
|
8
9
|
* Formats a date for RSS pubDate field (RFC 822)
|
|
9
10
|
* @param date - Date to format
|
|
@@ -59,7 +60,7 @@ function filterPages(pages, feedConfig) {
|
|
|
59
60
|
* @returns Date value or undefined
|
|
60
61
|
*/
|
|
61
62
|
function getPageDate(page) {
|
|
62
|
-
return page.frontMatter
|
|
63
|
+
return getFrontMatterDate(page.frontMatter);
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* Sorts pages based on feed configuration
|
|
@@ -85,7 +86,7 @@ function sortPages(pages, feedConfig) {
|
|
|
85
86
|
return 1;
|
|
86
87
|
if (!dateB)
|
|
87
88
|
return -1;
|
|
88
|
-
const comparison =
|
|
89
|
+
const comparison = dateA.getTime() - dateB.getTime();
|
|
89
90
|
return sortBy === 'date-asc' ? comparison : -comparison;
|
|
90
91
|
}
|
|
91
92
|
case 'title-asc':
|
|
@@ -254,8 +255,9 @@ export function generateRSSFeed(pages, config, feedConfig, logger) {
|
|
|
254
255
|
}
|
|
255
256
|
}
|
|
256
257
|
// Pub date
|
|
257
|
-
const pubDate =
|
|
258
|
-
getFieldValue(page, itemMapping.pubDate,
|
|
258
|
+
const pubDate = itemMapping.pubDate
|
|
259
|
+
? getFieldValue(page, itemMapping.pubDate, undefined, logger)
|
|
260
|
+
: getPageDate(page);
|
|
259
261
|
const formattedPubDate = parseAndFormatDate(pubDate);
|
|
260
262
|
if (formattedPubDate) {
|
|
261
263
|
xmlLines.push(` <pubDate>${formattedPubDate}</pubDate>`);
|
package/dist/types/content.d.ts
CHANGED
|
@@ -79,10 +79,13 @@ export interface FrontMatter {
|
|
|
79
79
|
layout?: string;
|
|
80
80
|
/** Numeric order for sorting (useful for navigation) */
|
|
81
81
|
order?: number;
|
|
82
|
-
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Publication date. A quoted YAML value is a string; an unquoted one
|
|
84
|
+
* (`publishedAt: 2024-01-01`) is parsed into a `Date`.
|
|
85
|
+
*/
|
|
86
|
+
publishedAt?: string | Date;
|
|
87
|
+
/** Publication date, used when `publishedAt` and `published` are absent or invalid */
|
|
88
|
+
date?: string | Date;
|
|
86
89
|
/** Last updated date as ISO string */
|
|
87
90
|
updated?: string;
|
|
88
91
|
/** Custom cache TTL in seconds (overrides global ISG settings) */
|
|
@@ -297,7 +300,7 @@ export interface PageModel {
|
|
|
297
300
|
frontMatter: FrontMatter;
|
|
298
301
|
/** Raw markdown content (before rendering) */
|
|
299
302
|
content: string;
|
|
300
|
-
/** Publication date
|
|
303
|
+
/** Publication date, from the first valid of `publishedAt`, `published`, `date`, `createdAt` */
|
|
301
304
|
publishedAt?: Date;
|
|
302
305
|
}
|
|
303
306
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/types/content.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACvB,qDAAqD;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/types/content.ts"],"names":[],"mappings":"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"}
|
package/dist/types/rss.d.ts
CHANGED
|
@@ -144,7 +144,7 @@ export interface RSSFeedConfig {
|
|
|
144
144
|
* Can be:
|
|
145
145
|
* - A string property name from frontMatter (e.g., 'publishedAt', 'date')
|
|
146
146
|
* - A function that returns a Date or string
|
|
147
|
-
* @default
|
|
147
|
+
* @default The first valid date in `publishedAt`, `published`, `date`, `createdAt`
|
|
148
148
|
*/
|
|
149
149
|
pubDate?: string | ((page: PageModel) => Date | string);
|
|
150
150
|
/**
|