@stati/core 1.28.0 → 1.29.1
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 +6 -1
- package/dist/core/build.d.ts.map +1 -1
- package/dist/core/build.js +192 -71
- package/dist/core/collections.d.ts +139 -0
- package/dist/core/collections.d.ts.map +1 -0
- package/dist/core/collections.js +342 -0
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/content.js +2 -1
- package/dist/core/dev.d.ts.map +1 -1
- package/dist/core/dev.js +32 -93
- package/dist/core/expand.d.ts +86 -0
- package/dist/core/expand.d.ts.map +1 -0
- package/dist/core/expand.js +484 -0
- package/dist/core/isg/builder.d.ts +15 -2
- package/dist/core/isg/builder.d.ts.map +1 -1
- package/dist/core/isg/builder.js +44 -6
- package/dist/core/isg/hash.d.ts +4 -2
- package/dist/core/isg/hash.d.ts.map +1 -1
- package/dist/core/isg/hash.js +16 -2
- package/dist/core/isg/index.d.ts +2 -1
- package/dist/core/isg/index.d.ts.map +1 -1
- package/dist/core/isg/index.js +3 -1
- package/dist/core/isg/manifest.js +6 -0
- package/dist/core/isg/prune.d.ts +32 -0
- package/dist/core/isg/prune.d.ts.map +1 -0
- package/dist/core/isg/prune.js +113 -0
- package/dist/core/navigation.d.ts +4 -2
- package/dist/core/navigation.d.ts.map +1 -1
- package/dist/core/navigation.js +17 -2
- package/dist/core/preview.d.ts.map +1 -1
- package/dist/core/preview.js +21 -32
- package/dist/core/templates.d.ts +3 -0
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +67 -127
- package/dist/core/utils/bundle-matching.utils.d.ts +8 -8
- package/dist/core/utils/bundle-matching.utils.d.ts.map +1 -1
- package/dist/core/utils/bundle-matching.utils.js +10 -10
- package/dist/core/utils/fs.utils.d.ts +8 -0
- package/dist/core/utils/fs.utils.d.ts.map +1 -1
- package/dist/core/utils/fs.utils.js +13 -1
- package/dist/core/utils/index.d.ts +6 -6
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core/utils/index.js +5 -5
- package/dist/core/utils/paths.utils.d.ts +15 -0
- package/dist/core/utils/paths.utils.d.ts.map +1 -1
- package/dist/core/utils/paths.utils.js +20 -0
- package/dist/core/utils/server.utils.d.ts +38 -3
- package/dist/core/utils/server.utils.d.ts.map +1 -1
- package/dist/core/utils/server.utils.js +132 -44
- package/dist/core/utils/template-discovery.utils.d.ts +25 -1
- package/dist/core/utils/template-discovery.utils.d.ts.map +1 -1
- package/dist/core/utils/template-discovery.utils.js +61 -11
- package/dist/core/utils/typescript.utils.d.ts +27 -0
- package/dist/core/utils/typescript.utils.d.ts.map +1 -1
- package/dist/core/utils/typescript.utils.js +34 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/rss/generator.d.ts.map +1 -1
- package/dist/rss/generator.js +5 -2
- package/dist/search/generator.d.ts +27 -7
- package/dist/search/generator.d.ts.map +1 -1
- package/dist/search/generator.js +55 -12
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -1
- package/dist/types/config.d.ts +61 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/content.d.ts +129 -1
- package/dist/types/content.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/isg.d.ts +12 -0
- package/dist/types/isg.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -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;AAInE;;;GAGG;AAEH;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAEtD;AAiED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,SAAS,EAAE,GACpB,SAAS,GAAG,SAAS,CAMvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAoBrF;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"}
|
|
@@ -2,6 +2,23 @@ import { join, dirname, posix } from 'node:path';
|
|
|
2
2
|
import { pathExists } from './fs.utils.js';
|
|
3
3
|
import { LAYOUT_TEMPLATE } from '../../constants.js';
|
|
4
4
|
import { resolveSrcDir } from './paths.utils.js';
|
|
5
|
+
/**
|
|
6
|
+
* Shared template discovery utilities.
|
|
7
|
+
* Extracted from templates.ts and isg/deps.ts to eliminate duplication.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Whether a page was created by Stati rather than loaded from a Markdown file: a page expanded
|
|
11
|
+
* from a `[param].md` template, or page 2 or later of a paginated listing.
|
|
12
|
+
*
|
|
13
|
+
* Virtual pages are never collection members, never make a folder a collection, and are left
|
|
14
|
+
* out of navigation, search and RSS unless they opt in.
|
|
15
|
+
*
|
|
16
|
+
* @param page - The page to check
|
|
17
|
+
* @returns True for generated pages and for pagination pages after the first
|
|
18
|
+
*/
|
|
19
|
+
export function isVirtualPage(page) {
|
|
20
|
+
return page.generated !== undefined || (page.pagination?.pageNumber ?? 1) > 1;
|
|
21
|
+
}
|
|
5
22
|
/**
|
|
6
23
|
* Directory prefix index per page list, so a build computes it once instead of
|
|
7
24
|
* scanning every page for every page.
|
|
@@ -13,51 +30,84 @@ import { resolveSrcDir } from './paths.utils.js';
|
|
|
13
30
|
* loads a new array and gets a new snapshot. Taking one snapshot keeps rendering and
|
|
14
31
|
* ISG dependency tracking in agreement for the whole build.
|
|
15
32
|
*/
|
|
16
|
-
const
|
|
17
|
-
function
|
|
18
|
-
const cached =
|
|
33
|
+
const pageListCache = new WeakMap();
|
|
34
|
+
function getPageListIndex(allPages) {
|
|
35
|
+
const cached = pageListCache.get(allPages);
|
|
19
36
|
if (cached) {
|
|
20
37
|
return cached;
|
|
21
38
|
}
|
|
22
|
-
const
|
|
23
|
-
|
|
39
|
+
const prefixes = new Map();
|
|
40
|
+
const byUrl = new Map();
|
|
41
|
+
for (const page of allPages) {
|
|
42
|
+
if (!byUrl.has(page.url)) {
|
|
43
|
+
byUrl.set(page.url, page);
|
|
44
|
+
}
|
|
45
|
+
// Generated and pagination pages don't turn the folders they live in into collections
|
|
46
|
+
if (isVirtualPage(page)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const { url } = page;
|
|
24
50
|
// Every prefix ending at a '/' is a directory this URL lives in (or is, for trailing-slash URLs)
|
|
25
51
|
for (let i = url.indexOf('/'); i !== -1; i = url.indexOf('/', i + 1)) {
|
|
26
52
|
const prefix = url.slice(0, i + 1);
|
|
27
|
-
const existing =
|
|
53
|
+
const existing = prefixes.get(prefix);
|
|
28
54
|
if (existing === undefined) {
|
|
29
|
-
|
|
55
|
+
prefixes.set(prefix, url);
|
|
30
56
|
}
|
|
31
57
|
else if (existing !== null && existing !== url) {
|
|
32
|
-
|
|
58
|
+
prefixes.set(prefix, null);
|
|
33
59
|
}
|
|
34
60
|
}
|
|
35
61
|
}
|
|
36
|
-
|
|
62
|
+
const index = { prefixes, byUrl };
|
|
63
|
+
pageListCache.set(allPages, index);
|
|
37
64
|
return index;
|
|
38
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Finds the first page of a paginated listing, which later pages render like.
|
|
68
|
+
*
|
|
69
|
+
* @param page - A page with `pagination`
|
|
70
|
+
* @param allPages - All pages in the site
|
|
71
|
+
* @returns The listing's first page, or undefined when it is not in the list
|
|
72
|
+
*/
|
|
73
|
+
export function getFirstPaginationPage(page, allPages) {
|
|
74
|
+
const firstUrl = page.pagination?.urls[0];
|
|
75
|
+
if (firstUrl === undefined || firstUrl === page.url) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
return getPageListIndex(allPages).byUrl.get(firstUrl);
|
|
79
|
+
}
|
|
39
80
|
/**
|
|
40
81
|
* Determines if the given page is a collection index page.
|
|
41
82
|
* A collection index page is one whose URL matches a directory path that contains other pages.
|
|
83
|
+
* Generated pages never are; pagination pages after the first are when their first page is.
|
|
42
84
|
*
|
|
43
85
|
* Rendering and ISG dependency tracking must both call this with the same page list,
|
|
44
86
|
* otherwise they can pick different layouts for the same page.
|
|
45
87
|
*
|
|
46
88
|
* Page URLs are read once per `allPages` array, at the first call; see
|
|
47
|
-
* `
|
|
89
|
+
* `pageListCache` for when changes to the pages are picked up.
|
|
48
90
|
*
|
|
49
91
|
* @param page - The page to check
|
|
50
92
|
* @param allPages - All pages in the site (treated as unchanging after the first call)
|
|
51
93
|
* @returns True if the page is a collection index page
|
|
52
94
|
*/
|
|
53
95
|
export function isCollectionIndexPage(page, allPages) {
|
|
96
|
+
if (page.generated) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
// Later pages of a listing render with the layout of its first page
|
|
100
|
+
if ((page.pagination?.pageNumber ?? 1) > 1) {
|
|
101
|
+
const first = getFirstPaginationPage(page, allPages);
|
|
102
|
+
return first !== undefined && !isVirtualPage(first) && isCollectionIndexPage(first, allPages);
|
|
103
|
+
}
|
|
54
104
|
// Root index page is always a collection index
|
|
55
105
|
if (page.url === '/') {
|
|
56
106
|
return true;
|
|
57
107
|
}
|
|
58
108
|
// The page is an index when a different page's URL lives under this page's URL as a directory
|
|
59
109
|
const pageUrlAsDir = page.url.endsWith('/') ? page.url : page.url + '/';
|
|
60
|
-
const containingUrl =
|
|
110
|
+
const containingUrl = getPageListIndex(allPages).prefixes.get(pageUrlAsDir);
|
|
61
111
|
return containingUrl === null || (containingUrl !== undefined && containingUrl !== page.url);
|
|
62
112
|
}
|
|
63
113
|
/**
|
|
@@ -57,6 +57,33 @@ export interface WatchOptions {
|
|
|
57
57
|
* @returns Array of detected bundle info
|
|
58
58
|
*/
|
|
59
59
|
export declare function detectExistingBundles(options: Omit<CompileOptions, 'logger'>): Promise<CompiledBundleInfo[]>;
|
|
60
|
+
/**
|
|
61
|
+
* Options for {@link removeStaleBundleFiles}.
|
|
62
|
+
*/
|
|
63
|
+
export interface RemoveStaleBundlesOptions {
|
|
64
|
+
/** Root directory of the project */
|
|
65
|
+
projectRoot: string;
|
|
66
|
+
/** TypeScript configuration */
|
|
67
|
+
config: TypeScriptConfig;
|
|
68
|
+
/** Output directory (defaults to 'dist') */
|
|
69
|
+
outDir?: string;
|
|
70
|
+
/** The bundles this build compiled */
|
|
71
|
+
compiled: CompiledBundleInfo[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Deletes the files of compiled bundles that earlier builds left in the bundle output
|
|
75
|
+
* directory: hashed copies from builds whose code differed, and the unhashed file and source
|
|
76
|
+
* map the dev server writes, which production pages never load. Only files named after a
|
|
77
|
+
* bundle compiled in this build are deleted, and never a file this build wrote, so other files
|
|
78
|
+
* in the directory stay.
|
|
79
|
+
*
|
|
80
|
+
* The build calls this after every page is written: until then, pages from the previous
|
|
81
|
+
* build still load the old files.
|
|
82
|
+
*
|
|
83
|
+
* @param options - The project, its TypeScript config and output directory, and the bundles
|
|
84
|
+
* this build compiled
|
|
85
|
+
*/
|
|
86
|
+
export declare function removeStaleBundleFiles(options: RemoveStaleBundlesOptions): Promise<void>;
|
|
60
87
|
/**
|
|
61
88
|
* Compile TypeScript files using esbuild.
|
|
62
89
|
* Supports multiple bundles with parallel compilation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/typescript.utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAInC,OAAO,EAA6B,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChG,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,uBAAuB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAQrD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,SAAS,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAuCD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,GACtC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAyC/B;AAuED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAkD9F;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAyHjC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB5E;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAqC7D;AAiBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CA8B7E"}
|
|
1
|
+
{"version":3,"file":"typescript.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/typescript.utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAInC,OAAO,EAA6B,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChG,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,uBAAuB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAQrD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,SAAS,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAuCD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,GACtC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAyC/B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;CAChC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB9F;AAuED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAkD9F;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAyHjC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB5E;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAqC7D;AAiBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CA8B7E"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import * as esbuild from 'esbuild';
|
|
8
8
|
import * as path from 'node:path';
|
|
9
9
|
import * as fs from 'node:fs/promises';
|
|
10
|
-
import { pathExists } from './fs.utils.js';
|
|
10
|
+
import { pathExists, readdir, remove } from './fs.utils.js';
|
|
11
11
|
import { validateUniqueBundleNames } from './bundle-matching.utils.js';
|
|
12
12
|
import { DEFAULT_TS_SRC_DIR, DEFAULT_TS_OUT_DIR, DEFAULT_BUNDLES, DEFAULT_OUT_DIR, } from '../../constants.js';
|
|
13
13
|
/**
|
|
@@ -83,6 +83,39 @@ export async function detectExistingBundles(options) {
|
|
|
83
83
|
}
|
|
84
84
|
return results;
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Deletes the files of compiled bundles that earlier builds left in the bundle output
|
|
88
|
+
* directory: hashed copies from builds whose code differed, and the unhashed file and source
|
|
89
|
+
* map the dev server writes, which production pages never load. Only files named after a
|
|
90
|
+
* bundle compiled in this build are deleted, and never a file this build wrote, so other files
|
|
91
|
+
* in the directory stay.
|
|
92
|
+
*
|
|
93
|
+
* The build calls this after every page is written: until then, pages from the previous
|
|
94
|
+
* build still load the old files.
|
|
95
|
+
*
|
|
96
|
+
* @param options - The project, its TypeScript config and output directory, and the bundles
|
|
97
|
+
* this build compiled
|
|
98
|
+
*/
|
|
99
|
+
export async function removeStaleBundleFiles(options) {
|
|
100
|
+
const { projectRoot, config, outDir: globalOutDir = DEFAULT_OUT_DIR, compiled } = options;
|
|
101
|
+
if (compiled.length === 0) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const outDir = path.join(projectRoot, globalOutDir, resolveConfig(config, 'production').outDir);
|
|
105
|
+
const current = new Set(compiled.map((bundle) => bundle.filename));
|
|
106
|
+
// name.js, name-HASH.js (esbuild's 8-character hash) and their source maps
|
|
107
|
+
const patterns = compiled.map(({ config }) => {
|
|
108
|
+
const name = config.bundleName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
109
|
+
return new RegExp(`^${name}(?:-[A-Z0-9]{8})?\\.js(?:\\.map)?$`);
|
|
110
|
+
});
|
|
111
|
+
const entries = await readdir(outDir, { withFileTypes: true }).catch(() => []);
|
|
112
|
+
// Files only: remove() deletes folders with their contents, and links are left alone
|
|
113
|
+
const stale = entries
|
|
114
|
+
.filter((entry) => entry.isFile())
|
|
115
|
+
.map((entry) => entry.name)
|
|
116
|
+
.filter((file) => !current.has(file) && patterns.some((pattern) => pattern.test(file)));
|
|
117
|
+
await Promise.all(stale.map((file) => remove(path.join(outDir, file))));
|
|
118
|
+
}
|
|
86
119
|
/**
|
|
87
120
|
* Compile a single bundle using esbuild.
|
|
88
121
|
* @internal
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* await build({ clean: true });
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
|
-
export type { SiteConfig, StatiConfig, PageModel, FrontMatter, BuildContext, PageContext, BuildHooks, NavNode, ISGConfig, AgingRule, BuildStats, BundleConfig, } from './types/index.js';
|
|
22
|
+
export type { SiteConfig, StatiConfig, PageModel, FrontMatter, BuildContext, PageContext, BuildHooks, NavNode, ISGConfig, AgingRule, BuildStats, BundleConfig, CollectionData, CollectionsConfig, GeneratedPageEntry, PaginationData, GeneratedPageData, PaginateOptions, GenerateOptions, } from './types/index.js';
|
|
23
23
|
export type { SEOMetadata, SEOConfig, SEOContext, SEOValidationResult, SEOTagType, RobotsConfig, OpenGraphConfig, OpenGraphImage, OpenGraphArticle, TwitterCardConfig, AuthorConfig, } from './types/index.js';
|
|
24
24
|
export type { SitemapConfig, SitemapEntry, SitemapGenerationResult, ChangeFrequency, } from './types/index.js';
|
|
25
25
|
export type { RSSConfig, RSSFeedConfig, RSSGenerationResult } from './types/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,YAAY,EACV,UAAU,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,UAAU,EACV,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,YAAY,EACV,UAAU,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,UAAU,EACV,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,WAAW,EACX,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,aAAa,EACb,YAAY,EACZ,uBAAuB,EACvB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGtF,YAAY,EACV,YAAY,EACZ,sBAAsB,EACtB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,aAAa,EACb,cAAc,EACd,MAAM,EACN,UAAU,EACV,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,YAAY,EACZ,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG1F,YAAY,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EACb,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,SAAS,EACT,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG5F,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,UAAU,EACV,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAG/E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAE7D"}
|
|
@@ -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;AA+KlD;;;;;;;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,7 +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
|
+
import { getFrontMatterDate, isVirtualPage } from '../core/utils/index.js';
|
|
8
8
|
/**
|
|
9
9
|
* Formats a date for RSS pubDate field (RFC 822)
|
|
10
10
|
* @param date - Date to format
|
|
@@ -47,7 +47,10 @@ function filterPages(pages, feedConfig) {
|
|
|
47
47
|
if (feedConfig.excludePatterns) {
|
|
48
48
|
options.excludePatterns = feedConfig.excludePatterns;
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
// Generated and pagination pages share their template's source path, so patterns can't
|
|
51
|
+
// tell them apart from content; feeds list content only
|
|
52
|
+
const contentPages = pages.filter((page) => !isVirtualPage(page));
|
|
53
|
+
let filtered = filterByPatterns(contentPages, (page) => page.sourcePath, options);
|
|
51
54
|
// Apply custom filter function if provided
|
|
52
55
|
if (feedConfig.filter) {
|
|
53
56
|
filtered = filtered.filter(feedConfig.filter);
|
|
@@ -50,6 +50,15 @@ export declare function extractSectionsFromMarkdown(toc: TocEntry[], markdownCon
|
|
|
50
50
|
* @returns true if the page should be excluded
|
|
51
51
|
*/
|
|
52
52
|
export declare function shouldExcludePage(page: PageModel, config: SearchConfig): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether a page created by Stati stays out of the search index. Pages generated from a
|
|
55
|
+
* `[param].md` template are left out unless the template sets `search: true`; later pages
|
|
56
|
+
* of a paginated listing are always left out, since they repeat the first page's content.
|
|
57
|
+
*
|
|
58
|
+
* @param page - Page model to check
|
|
59
|
+
* @returns true for generated and pagination pages that are not indexed
|
|
60
|
+
*/
|
|
61
|
+
export declare function isGeneratedPageExcludedFromSearch(page: PageModel): boolean;
|
|
53
62
|
/**
|
|
54
63
|
* Page data for search indexing using markdown and TOC entries.
|
|
55
64
|
* Uses structured data already available from the markdown processing pipeline.
|
|
@@ -73,21 +82,32 @@ export declare function generateSearchIndex(searchablePages: SearchablePage[], c
|
|
|
73
82
|
export declare function writeSearchIndex(searchIndex: SearchIndex, outDir: string, filename: string, skipIfUnchanged?: boolean): Promise<SearchIndexMetadata>;
|
|
74
83
|
/**
|
|
75
84
|
* Computes the search index filename based on configuration.
|
|
76
|
-
* When hashFilename is true,
|
|
77
|
-
*
|
|
78
|
-
*
|
|
85
|
+
* When hashFilename is true, the name carries a hash of `hashInput`. Production builds pass
|
|
86
|
+
* the index content, so the name changes only when the indexed text does; every page links to
|
|
87
|
+
* the index, so the name is part of each page's cache hash.
|
|
79
88
|
*
|
|
80
89
|
* @param config - Search configuration
|
|
81
|
-
* @param
|
|
90
|
+
* @param hashInput - The value the hash is computed from, such as the serialized documents
|
|
82
91
|
* @returns The search index filename (without leading slash)
|
|
83
92
|
*
|
|
84
93
|
* @example
|
|
85
94
|
* ```typescript
|
|
86
|
-
*
|
|
87
|
-
* const filename = computeSearchIndexFilename(config.search, Date.now().toString());
|
|
95
|
+
* const filename = computeSearchIndexFilename(config.search, JSON.stringify(index.documents));
|
|
88
96
|
* // filename: 'search-index-a1b2c3d4.json' (when hashFilename is true)
|
|
89
97
|
* // filename: 'search-index.json' (when hashFilename is false)
|
|
90
98
|
* ```
|
|
91
99
|
*/
|
|
92
|
-
export declare function computeSearchIndexFilename(config: SearchConfig,
|
|
100
|
+
export declare function computeSearchIndexFilename(config: SearchConfig, hashInput?: string): string;
|
|
101
|
+
/**
|
|
102
|
+
* Deletes search index files that earlier builds wrote under another name: hashed files from
|
|
103
|
+
* builds whose indexed text differed, and the file of a build with the other `hashFilename`
|
|
104
|
+
* setting. Only files in the output directory named after `indexName` are deleted, never the
|
|
105
|
+
* current one.
|
|
106
|
+
*
|
|
107
|
+
* @param outDir - The output directory
|
|
108
|
+
* @param config - Search configuration
|
|
109
|
+
* @param currentFilename - The index file this build wrote
|
|
110
|
+
* @returns The deleted file names
|
|
111
|
+
*/
|
|
112
|
+
export declare function removeStaleSearchIndexes(outDir: string, config: SearchConfig, currentFilename: string): Promise<string[]>;
|
|
93
113
|
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/search/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/search/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,WAAW,EACX,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAqBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CA2BtE;AAKD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA8DtD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,QAAQ,EAAE,EACf,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACnC,MAAM,EAAE,YAAY,GACnB,cAAc,EAAE,CAiGlB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CA2BhF;AAED;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAM1E;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,IAAI,EAAE,SAAS,CAAC;IAChB,oEAAoE;IACpE,GAAG,EAAE,QAAQ,EAAE,CAAC;IAChB,kDAAkD;IAClD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,eAAe,EAAE,cAAc,EAAE,EACjC,MAAM,EAAE,YAAY,GACnB,WAAW,CA6Bb;AAiBD,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,eAAe,UAAQ,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAqC9B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAW3F;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,EACpB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,EAAE,CAAC,CAoBnB"}
|
package/dist/search/generator.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { createHash } from 'node:crypto';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
|
-
import { writeFile, ensureDir } from '../core/utils/fs.utils.js';
|
|
7
|
+
import { writeFile, ensureDir, readdir, remove } from '../core/utils/fs.utils.js';
|
|
8
8
|
import { matchesGlob } from '../core/utils/glob-patterns.utils.js';
|
|
9
|
+
import { isVirtualPage } from '../core/utils/template-discovery.utils.js';
|
|
9
10
|
import { SEARCH_INDEX_VERSION, SEARCH_DEFAULTS } from './constants.js';
|
|
10
11
|
/**
|
|
11
12
|
* Generates a short content hash for cache busting.
|
|
@@ -218,6 +219,10 @@ export function shouldExcludePage(page, config) {
|
|
|
218
219
|
if (page.frontMatter.draft) {
|
|
219
220
|
return true;
|
|
220
221
|
}
|
|
222
|
+
// Exclude generated and pagination pages unless their template opts in
|
|
223
|
+
if (isGeneratedPageExcludedFromSearch(page)) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
221
226
|
// Check home page exclusion
|
|
222
227
|
const isHomePage = page.url === '/' || page.url === '';
|
|
223
228
|
const includeHomePage = config.includeHomePage ?? SEARCH_DEFAULTS.includeHomePage;
|
|
@@ -233,6 +238,21 @@ export function shouldExcludePage(page, config) {
|
|
|
233
238
|
}
|
|
234
239
|
return false;
|
|
235
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Whether a page created by Stati stays out of the search index. Pages generated from a
|
|
243
|
+
* `[param].md` template are left out unless the template sets `search: true`; later pages
|
|
244
|
+
* of a paginated listing are always left out, since they repeat the first page's content.
|
|
245
|
+
*
|
|
246
|
+
* @param page - Page model to check
|
|
247
|
+
* @returns true for generated and pagination pages that are not indexed
|
|
248
|
+
*/
|
|
249
|
+
export function isGeneratedPageExcludedFromSearch(page) {
|
|
250
|
+
if (!isVirtualPage(page)) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
const firstPage = (page.pagination?.pageNumber ?? 1) === 1;
|
|
254
|
+
return !(page.generated && firstPage && page.frontMatter.search === true);
|
|
255
|
+
}
|
|
236
256
|
/**
|
|
237
257
|
* Generates a search index from searchable pages using markdown and TOC data.
|
|
238
258
|
*
|
|
@@ -307,32 +327,55 @@ export async function writeSearchIndex(searchIndex, outDir, filename, skipIfUnch
|
|
|
307
327
|
}
|
|
308
328
|
/**
|
|
309
329
|
* Computes the search index filename based on configuration.
|
|
310
|
-
* When hashFilename is true,
|
|
311
|
-
*
|
|
312
|
-
*
|
|
330
|
+
* When hashFilename is true, the name carries a hash of `hashInput`. Production builds pass
|
|
331
|
+
* the index content, so the name changes only when the indexed text does; every page links to
|
|
332
|
+
* the index, so the name is part of each page's cache hash.
|
|
313
333
|
*
|
|
314
334
|
* @param config - Search configuration
|
|
315
|
-
* @param
|
|
335
|
+
* @param hashInput - The value the hash is computed from, such as the serialized documents
|
|
316
336
|
* @returns The search index filename (without leading slash)
|
|
317
337
|
*
|
|
318
338
|
* @example
|
|
319
339
|
* ```typescript
|
|
320
|
-
*
|
|
321
|
-
* const filename = computeSearchIndexFilename(config.search, Date.now().toString());
|
|
340
|
+
* const filename = computeSearchIndexFilename(config.search, JSON.stringify(index.documents));
|
|
322
341
|
* // filename: 'search-index-a1b2c3d4.json' (when hashFilename is true)
|
|
323
342
|
* // filename: 'search-index.json' (when hashFilename is false)
|
|
324
343
|
* ```
|
|
325
344
|
*/
|
|
326
|
-
export function computeSearchIndexFilename(config,
|
|
345
|
+
export function computeSearchIndexFilename(config, hashInput) {
|
|
327
346
|
const indexName = config.indexName ?? SEARCH_DEFAULTS.indexName;
|
|
328
347
|
const hashFilename = config.hashFilename ?? SEARCH_DEFAULTS.hashFilename;
|
|
329
348
|
if (hashFilename) {
|
|
330
|
-
|
|
331
|
-
// This allows the filename to be known before content is generated
|
|
332
|
-
const hashInput = buildId ?? Date.now().toString();
|
|
333
|
-
const hash = generateContentHash(hashInput);
|
|
349
|
+
const hash = generateContentHash(hashInput ?? Date.now().toString());
|
|
334
350
|
return `${indexName}-${hash}.json`;
|
|
335
351
|
}
|
|
336
352
|
// Return base filename (without hash)
|
|
337
353
|
return `${indexName}.json`;
|
|
338
354
|
}
|
|
355
|
+
/**
|
|
356
|
+
* Deletes search index files that earlier builds wrote under another name: hashed files from
|
|
357
|
+
* builds whose indexed text differed, and the file of a build with the other `hashFilename`
|
|
358
|
+
* setting. Only files in the output directory named after `indexName` are deleted, never the
|
|
359
|
+
* current one.
|
|
360
|
+
*
|
|
361
|
+
* @param outDir - The output directory
|
|
362
|
+
* @param config - Search configuration
|
|
363
|
+
* @param currentFilename - The index file this build wrote
|
|
364
|
+
* @returns The deleted file names
|
|
365
|
+
*/
|
|
366
|
+
export async function removeStaleSearchIndexes(outDir, config, currentFilename) {
|
|
367
|
+
const indexName = (config.indexName ?? SEARCH_DEFAULTS.indexName).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
368
|
+
// name.json and name-HASH.json (generateContentHash's 8 hex characters)
|
|
369
|
+
const pattern = new RegExp(`^${indexName}(?:-[0-9a-f]{8})?\\.json$`);
|
|
370
|
+
const entries = await readdir(outDir, { withFileTypes: true }).catch(() => null);
|
|
371
|
+
if (!entries) {
|
|
372
|
+
return [];
|
|
373
|
+
}
|
|
374
|
+
// Files only: remove() deletes folders with their contents, and links are left alone
|
|
375
|
+
const stale = entries
|
|
376
|
+
.filter((entry) => entry.isFile())
|
|
377
|
+
.map((entry) => entry.name)
|
|
378
|
+
.filter((file) => file !== currentFilename && pattern.test(file));
|
|
379
|
+
await Promise.all(stale.map((file) => remove(join(outDir, file))));
|
|
380
|
+
return stale;
|
|
381
|
+
}
|
package/dist/search/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* console.log(`Generated search index at ${metadata.indexPath}`);
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
-
export { generateSearchIndex, writeSearchIndex, extractSectionsFromMarkdown, stripMarkdown, shouldExcludePage, generateContentHash, buildBreadcrumb, computeSearchIndexFilename, } from './generator.js';
|
|
19
|
+
export { generateSearchIndex, writeSearchIndex, extractSectionsFromMarkdown, stripMarkdown, shouldExcludePage, isGeneratedPageExcludedFromSearch, generateContentHash, buildBreadcrumb, computeSearchIndexFilename, removeStaleSearchIndexes, } from './generator.js';
|
|
20
20
|
export type { SearchablePage } from './generator.js';
|
|
21
21
|
export { autoInjectSearchMeta } from './auto-inject.js';
|
|
22
22
|
export { SEARCH_INDEX_META_NAME, SEARCH_INDEX_VERSION, SEARCH_DEFAULTS } from './constants.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,2BAA2B,EAC3B,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,0BAA0B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,2BAA2B,EAC3B,aAAa,EACb,iBAAiB,EACjB,iCAAiC,EACjC,mBAAmB,EACnB,eAAe,EACf,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE/F,YAAY,EACV,YAAY,EACZ,cAAc,EACd,WAAW,EACX,mBAAmB,GACpB,MAAM,oBAAoB,CAAC"}
|
package/dist/search/index.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* console.log(`Generated search index at ${metadata.indexPath}`);
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
-
export { generateSearchIndex, writeSearchIndex, extractSectionsFromMarkdown, stripMarkdown, shouldExcludePage, generateContentHash, buildBreadcrumb, computeSearchIndexFilename, } from './generator.js';
|
|
19
|
+
export { generateSearchIndex, writeSearchIndex, extractSectionsFromMarkdown, stripMarkdown, shouldExcludePage, isGeneratedPageExcludedFromSearch, generateContentHash, buildBreadcrumb, computeSearchIndexFilename, removeStaleSearchIndexes, } from './generator.js';
|
|
20
20
|
// Auto-injection
|
|
21
21
|
export { autoInjectSearchMeta } from './auto-inject.js';
|
|
22
22
|
export { SEARCH_INDEX_META_NAME, SEARCH_INDEX_VERSION, SEARCH_DEFAULTS } from './constants.js';
|
package/dist/types/config.d.ts
CHANGED
|
@@ -73,6 +73,8 @@ export interface StatiConfig {
|
|
|
73
73
|
};
|
|
74
74
|
/** Incremental Static Generation configuration */
|
|
75
75
|
isg?: import('./isg.js').ISGConfig;
|
|
76
|
+
/** Collection listings: which fields rebuild them, and pages generated from data */
|
|
77
|
+
collections?: CollectionsConfig;
|
|
76
78
|
/** SEO configuration */
|
|
77
79
|
seo?: SEOConfig;
|
|
78
80
|
/** Sitemap generation configuration */
|
|
@@ -111,6 +113,59 @@ export interface StatiConfig {
|
|
|
111
113
|
/** Build lifecycle hooks */
|
|
112
114
|
hooks?: BuildHooks;
|
|
113
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Collection settings.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* const collections: CollectionsConfig = {
|
|
122
|
+
* // Listings also show each post's image, so changing it rebuilds them
|
|
123
|
+
* summaryFields: ['title', 'description', 'tags', 'draft', 'image'],
|
|
124
|
+
* // One page per author, rendered with site/authors/[author].md
|
|
125
|
+
* generate: ({ pages }) => [
|
|
126
|
+
* {
|
|
127
|
+
* url: '/authors/ada',
|
|
128
|
+
* template: 'authors/[author].md',
|
|
129
|
+
* label: 'Ada Lovelace',
|
|
130
|
+
* items: pages.filter((page) => page.frontMatter.author === 'ada'),
|
|
131
|
+
* },
|
|
132
|
+
* ],
|
|
133
|
+
* };
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export interface CollectionsConfig {
|
|
137
|
+
/**
|
|
138
|
+
* Front matter fields of collection pages that listings show. A page that reads
|
|
139
|
+
* `stati.collection` rebuilds when one of these fields changes on a page in the collection,
|
|
140
|
+
* and so do paginated and generated pages that list it. Each page's URL and publish date
|
|
141
|
+
* always count. `content` stands for the Markdown body, for listings that show excerpts.
|
|
142
|
+
*
|
|
143
|
+
* @default ['title', 'description', 'tags', 'draft']
|
|
144
|
+
*/
|
|
145
|
+
summaryFields?: string[];
|
|
146
|
+
/**
|
|
147
|
+
* Pages to create from data, each rendered with a `[param].md` template. Runs once per build,
|
|
148
|
+
* after content is loaded and before navigation is built.
|
|
149
|
+
*/
|
|
150
|
+
generate?: (ctx: BuildContext) => GeneratedPageEntry[] | Promise<GeneratedPageEntry[]>;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* A page returned by `collections.generate`.
|
|
154
|
+
*/
|
|
155
|
+
export interface GeneratedPageEntry {
|
|
156
|
+
/** URL of the page, such as `/authors/ada` */
|
|
157
|
+
url: string;
|
|
158
|
+
/** The `[param].md` template that renders it, relative to the source directory */
|
|
159
|
+
template: string;
|
|
160
|
+
/** `stati.generated.key`; defaults to the last segment of `url` */
|
|
161
|
+
key?: string;
|
|
162
|
+
/** `stati.generated.label` and the value of `{param}` placeholders; defaults to `key` */
|
|
163
|
+
label?: string;
|
|
164
|
+
/** Pages the page lists (`stati.generated.items`), split up by the template's `generate.paginate` */
|
|
165
|
+
items?: import('./content.js').PageModel[];
|
|
166
|
+
/** Any JSON-serializable data, as `stati.generated.data`; changing it rebuilds the page */
|
|
167
|
+
data?: Record<string, unknown>;
|
|
168
|
+
}
|
|
114
169
|
/**
|
|
115
170
|
* SEO configuration for the site.
|
|
116
171
|
* Controls automatic SEO metadata injection and site-wide defaults.
|
|
@@ -157,16 +212,18 @@ export interface BundleConfig {
|
|
|
157
212
|
bundleName: string;
|
|
158
213
|
/**
|
|
159
214
|
* Glob patterns for pages that should include this bundle.
|
|
160
|
-
* Matches against page
|
|
215
|
+
* Matches against the page URL (e.g., '/docs/api/hooks', or '/' for the home page),
|
|
216
|
+
* not its output file. A pattern must match the whole URL: '/docs/**' does not match
|
|
217
|
+
* the '/docs' index page itself.
|
|
161
218
|
* If omitted, bundle is included on ALL pages (global bundle).
|
|
162
219
|
*
|
|
163
|
-
* Supports glob syntax: `*`, `**`, `?`, `[abc]
|
|
220
|
+
* Supports glob syntax: `*`, `**`, `?`, `[abc]` (no `{a,b}`; list each pattern instead)
|
|
164
221
|
*
|
|
165
|
-
* @example ['/docs/**', '/api/**']
|
|
222
|
+
* @example ['/docs', '/docs/**', '/api/**']
|
|
166
223
|
*/
|
|
167
224
|
include?: string[];
|
|
168
225
|
/**
|
|
169
|
-
* Glob patterns for
|
|
226
|
+
* Glob patterns for page URLs to exclude from this bundle.
|
|
170
227
|
* Takes precedence over include patterns.
|
|
171
228
|
*
|
|
172
229
|
* @example ['/docs/legacy/**']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"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"}
|