@stati/core 1.29.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -13
- package/dist/config/loader.d.ts +9 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +77 -1
- package/dist/core/build.d.ts.map +1 -1
- package/dist/core/build.js +39 -29
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/content.js +9 -7
- package/dist/core/dev.d.ts.map +1 -1
- package/dist/core/dev.js +156 -197
- package/dist/core/eta-plugin.d.ts +60 -0
- package/dist/core/eta-plugin.d.ts.map +1 -0
- package/dist/core/eta-plugin.js +143 -0
- package/dist/core/isg/builder.d.ts +37 -19
- package/dist/core/isg/builder.d.ts.map +1 -1
- package/dist/core/isg/builder.js +70 -153
- package/dist/core/isg/deps.d.ts +8 -70
- package/dist/core/isg/deps.d.ts.map +1 -1
- package/dist/core/isg/deps.js +10 -401
- package/dist/core/isg/hash.d.ts.map +1 -1
- package/dist/core/isg/hash.js +2 -1
- package/dist/core/isg/index.d.ts +2 -2
- package/dist/core/isg/index.d.ts.map +1 -1
- package/dist/core/isg/index.js +3 -3
- package/dist/core/isg/manifest.d.ts.map +1 -1
- package/dist/core/isg/manifest.js +6 -1
- package/dist/core/markdown.d.ts +1 -1
- package/dist/core/markdown.d.ts.map +1 -1
- package/dist/core/markdown.js +3 -2
- package/dist/core/template-index.d.ts +209 -0
- package/dist/core/template-index.d.ts.map +1 -0
- package/dist/core/template-index.js +484 -0
- package/dist/core/template-render.d.ts +137 -0
- package/dist/core/template-render.d.ts.map +1 -0
- package/dist/core/template-render.js +444 -0
- package/dist/core/templates.d.ts +29 -11
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +115 -196
- package/dist/core/utils/context-validation.utils.d.ts +10 -6
- package/dist/core/utils/context-validation.utils.d.ts.map +1 -1
- package/dist/core/utils/context-validation.utils.js +39 -16
- package/dist/core/utils/date.utils.d.ts +1 -1
- package/dist/core/utils/date.utils.js +1 -1
- package/dist/core/utils/dev-css-watcher.utils.d.ts.map +1 -1
- package/dist/core/utils/dev-css-watcher.utils.js +3 -2
- package/dist/core/utils/error-overlay.utils.d.ts.map +1 -1
- package/dist/core/utils/error-overlay.utils.js +7 -45
- package/dist/core/utils/front-matter.utils.d.ts +50 -0
- package/dist/core/utils/front-matter.utils.d.ts.map +1 -0
- package/dist/core/utils/front-matter.utils.js +157 -0
- package/dist/core/utils/index.d.ts +4 -5
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core/utils/index.js +5 -7
- package/dist/core/utils/paths.utils.d.ts +3 -3
- package/dist/core/utils/paths.utils.js +6 -6
- package/dist/core/utils/tailwind-inventory.utils.d.ts +2 -2
- package/dist/core/utils/tailwind-inventory.utils.d.ts.map +1 -1
- package/dist/core/utils/tailwind-inventory.utils.js +15 -6
- package/dist/core/utils/template-discovery.utils.d.ts +3 -14
- package/dist/core/utils/template-discovery.utils.d.ts.map +1 -1
- package/dist/core/utils/template-discovery.utils.js +2 -62
- package/dist/core/utils/template-errors.utils.d.ts +14 -1
- package/dist/core/utils/template-errors.utils.d.ts.map +1 -1
- package/dist/core/utils/template-errors.utils.js +45 -4
- package/dist/core/utils/theme.utils.d.ts +17 -0
- package/dist/core/utils/theme.utils.d.ts.map +1 -0
- package/dist/core/utils/theme.utils.js +59 -0
- package/dist/images/index.d.ts +1 -2
- package/dist/images/index.d.ts.map +1 -1
- package/dist/images/index.js +0 -1
- package/dist/images/markdown-rule.d.ts +1 -2
- package/dist/images/markdown-rule.d.ts.map +1 -1
- package/dist/images/og.d.ts +2 -15
- package/dist/images/og.d.ts.map +1 -1
- package/dist/images/og.js +4 -47
- package/dist/images/runtime.d.ts +24 -5
- package/dist/images/runtime.d.ts.map +1 -1
- package/dist/images/runtime.js +14 -12
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/metrics/noop.d.ts.map +1 -1
- package/dist/metrics/noop.js +4 -1
- package/dist/metrics/recorder.d.ts.map +1 -1
- package/dist/metrics/recorder.js +11 -8
- package/dist/metrics/types.d.ts +31 -5
- package/dist/metrics/types.d.ts.map +1 -1
- package/dist/metrics/utils/html-report.utils.d.ts +2 -1
- package/dist/metrics/utils/html-report.utils.d.ts.map +1 -1
- package/dist/metrics/utils/html-report.utils.js +1115 -1136
- package/dist/types/config.d.ts +18 -6
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/content.d.ts +83 -16
- package/dist/types/content.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/isg.d.ts +48 -2
- package/dist/types/isg.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/core/utils/callable-partials.utils.d.ts +0 -60
- package/dist/core/utils/callable-partials.utils.d.ts.map +0 -1
- package/dist/core/utils/callable-partials.utils.js +0 -127
- package/dist/core/utils/partial-validation.utils.d.ts +0 -9
- package/dist/core/utils/partial-validation.utils.d.ts.map +0 -1
- package/dist/core/utils/partial-validation.utils.js +0 -107
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The template index: every `.eta` file under the source directory, and the name lookup that
|
|
3
|
+
* `stati.include()`, `stati.layout()`, front matter `layout:`, layout discovery and the Open
|
|
4
|
+
* Graph template share, so rendering and the ISG cache resolve every name the same way.
|
|
5
|
+
* @module core/template-index
|
|
6
|
+
*/
|
|
7
|
+
import type { TemplateLookup } from '../types/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* A template name, parsed.
|
|
10
|
+
* - `lookup`: `header` or `partials/header`, searched from the page's folder up to the source
|
|
11
|
+
* directory, nearest match first.
|
|
12
|
+
* - `path`: one possible file, from `/partials/header` (`relative: false`) or from `./icon` and
|
|
13
|
+
* `../icons/arrow` resolved against the calling template (`relative: true`). `path` always
|
|
14
|
+
* starts with `/` and is relative to the source directory.
|
|
15
|
+
* - `invalid`: a name that can never resolve, with the reason.
|
|
16
|
+
*/
|
|
17
|
+
export type TemplateName = {
|
|
18
|
+
kind: 'lookup';
|
|
19
|
+
name: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'path';
|
|
22
|
+
path: string;
|
|
23
|
+
relative: boolean;
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'invalid';
|
|
26
|
+
reason: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Parses a name passed to `stati.include()`, `stati.layout()`, `.has()` or front matter `layout:`.
|
|
30
|
+
* Backslashes count as `/`, and an `.eta` suffix is dropped.
|
|
31
|
+
*
|
|
32
|
+
* @param raw - The name as written
|
|
33
|
+
* @param callerFile - The calling template, relative to the source directory, or null for a
|
|
34
|
+
* template without a file (the built-in Open Graph template)
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseTemplateName(raw: unknown, callerFile: string | null): TemplateName;
|
|
37
|
+
/**
|
|
38
|
+
* The folder of a file relative to the source directory, `''` for the source directory itself.
|
|
39
|
+
* Paths outside the source directory count as the source directory.
|
|
40
|
+
*
|
|
41
|
+
* @param relativeFile - A path relative to the source directory, with `/` or `\` separators
|
|
42
|
+
*/
|
|
43
|
+
export declare function templateFolderOf(relativeFile: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* The folders a looked-up name is searched in, nearest first: the folder itself, each parent,
|
|
46
|
+
* then the source directory (`''`).
|
|
47
|
+
*/
|
|
48
|
+
export declare function lookupFolders(from: string): string[];
|
|
49
|
+
/**
|
|
50
|
+
* A `./` or `../` name that reaches `target` from `fromFolder`, both relative to the source
|
|
51
|
+
* directory. Pure string work, unlike `path.relative`, which resolves against the process's
|
|
52
|
+
* working directory.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* relativeTemplateName('partials', 'partials/icon'); // './icon'
|
|
57
|
+
* relativeTemplateName('blog/2024', 'blog/post'); // '../post'
|
|
58
|
+
* relativeTemplateName('', 'layout'); // './layout'
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function relativeTemplateName(fromFolder: string, target: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Converts an absolute path to the index's form: relative to the source directory, `/`
|
|
64
|
+
* separators. Returns null for files outside it and for files that are not templates.
|
|
65
|
+
*
|
|
66
|
+
* @param srcDir - Absolute source directory
|
|
67
|
+
* @param absolutePath - Absolute path of a file, with either separator
|
|
68
|
+
*/
|
|
69
|
+
export declare function toTemplateFile(srcDir: string, absolutePath: string): string | null;
|
|
70
|
+
/**
|
|
71
|
+
* Whether a value read from the cache manifest is a list of template lookups.
|
|
72
|
+
*/
|
|
73
|
+
export declare function isTemplateLookupList(value: unknown): value is TemplateLookup[];
|
|
74
|
+
/**
|
|
75
|
+
* How a page's layout was chosen, from {@link TemplateIndex.resolvePageLayout}.
|
|
76
|
+
*/
|
|
77
|
+
export interface PageLayoutResolution {
|
|
78
|
+
/** The layout file, relative to the source directory, or null when no layout applies */
|
|
79
|
+
file: string | null;
|
|
80
|
+
/** The lookups that chose it, for the page's cache entry */
|
|
81
|
+
lookups: TemplateLookup[];
|
|
82
|
+
/**
|
|
83
|
+
* A front matter `layout:` value that names no template: the value, why, and templates it
|
|
84
|
+
* could have meant. Layout discovery chose `file` instead.
|
|
85
|
+
*/
|
|
86
|
+
unresolvedFrontMatter?: {
|
|
87
|
+
value: unknown;
|
|
88
|
+
problem: string;
|
|
89
|
+
suggestions: string[];
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Every `.eta` file under a source directory, with memoised name lookups.
|
|
94
|
+
* Paths are relative to the source directory, with `/` separators and the `.eta` extension.
|
|
95
|
+
*/
|
|
96
|
+
export declare class TemplateIndex {
|
|
97
|
+
readonly srcDir: string;
|
|
98
|
+
private readonly templates;
|
|
99
|
+
private readonly lookupCache;
|
|
100
|
+
private sorted;
|
|
101
|
+
/**
|
|
102
|
+
* @param srcDir - Absolute source directory
|
|
103
|
+
* @param files - Template files relative to it
|
|
104
|
+
*/
|
|
105
|
+
constructor(srcDir: string, files: Iterable<string>);
|
|
106
|
+
/**
|
|
107
|
+
* Globs the source directory once for its templates.
|
|
108
|
+
*
|
|
109
|
+
* @param srcDir - Absolute source directory
|
|
110
|
+
*/
|
|
111
|
+
static load(srcDir: string): Promise<TemplateIndex>;
|
|
112
|
+
/** Number of templates */
|
|
113
|
+
get size(): number;
|
|
114
|
+
/** Whether a template file exists, given relative to the source directory */
|
|
115
|
+
has(file: string): boolean;
|
|
116
|
+
/** Every template file, sorted */
|
|
117
|
+
files(): readonly string[];
|
|
118
|
+
/**
|
|
119
|
+
* Adds a template, for a file created during a dev session.
|
|
120
|
+
*
|
|
121
|
+
* @returns Whether the index changed
|
|
122
|
+
*/
|
|
123
|
+
add(file: string): boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Removes a template, for a file deleted during a dev session.
|
|
126
|
+
*
|
|
127
|
+
* @returns Whether the index changed
|
|
128
|
+
*/
|
|
129
|
+
remove(file: string): boolean;
|
|
130
|
+
private invalidate;
|
|
131
|
+
/**
|
|
132
|
+
* Finds the nearest template for a looked-up name, searching `from` and then each parent
|
|
133
|
+
* folder up to the source directory.
|
|
134
|
+
*
|
|
135
|
+
* @param name - A normalized looked-up name, such as `partials/header`
|
|
136
|
+
* @param from - The folder to start in, relative to the source directory
|
|
137
|
+
* @returns The template file, or null when no folder has one
|
|
138
|
+
*/
|
|
139
|
+
lookup(name: string, from: string): string | null;
|
|
140
|
+
/**
|
|
141
|
+
* Resolves a parsed name for a page.
|
|
142
|
+
*
|
|
143
|
+
* @param name - A parsed, valid name
|
|
144
|
+
* @param pageFolder - The page's folder, where looked-up names start
|
|
145
|
+
* @returns The file (or null) and the lookup to record
|
|
146
|
+
*/
|
|
147
|
+
resolve(name: Exclude<TemplateName, {
|
|
148
|
+
kind: 'invalid';
|
|
149
|
+
}>, pageFolder: string): {
|
|
150
|
+
file: string | null;
|
|
151
|
+
lookup: TemplateLookup;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Resolves a recorded lookup again, for the cache. Lookups with a `from` folder are searched
|
|
155
|
+
* like looked-up names; the others are a single path.
|
|
156
|
+
*
|
|
157
|
+
* @returns The file the lookup would resolve to now, or null
|
|
158
|
+
*/
|
|
159
|
+
resolveRecorded(lookup: TemplateLookup): string | null;
|
|
160
|
+
/**
|
|
161
|
+
* Whether any recorded lookup would now resolve to a different file than it did.
|
|
162
|
+
*/
|
|
163
|
+
lookupsChanged(lookups: readonly TemplateLookup[] | undefined): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Names a template could have meant, for an unknown name: templates with the same base name
|
|
166
|
+
* first, then similar names, written the way the name was written.
|
|
167
|
+
*
|
|
168
|
+
* @param name - The unknown name, parsed
|
|
169
|
+
* @param pageFolder - The page's folder
|
|
170
|
+
* @param callerFile - The calling template, relative to the source directory
|
|
171
|
+
* @param limit - Maximum number of suggestions
|
|
172
|
+
*/
|
|
173
|
+
suggest(name: Exclude<TemplateName, {
|
|
174
|
+
kind: 'invalid';
|
|
175
|
+
}>, pageFolder: string, callerFile: string | null, limit?: number): string[];
|
|
176
|
+
/**
|
|
177
|
+
* Picks a page's layout: its front matter `layout:` when that names a template, otherwise the
|
|
178
|
+
* nearest `layout.eta`, or for index pages the nearest `index.eta` or `layout.eta`, whichever
|
|
179
|
+
* is in a nearer folder (`index.eta` first within a folder).
|
|
180
|
+
*
|
|
181
|
+
* @param pageFile - The page's Markdown file, relative to the source directory
|
|
182
|
+
* @param frontMatterLayout - The page's front matter `layout:` value
|
|
183
|
+
* @param isIndexPage - Whether the page lists a collection, which enables `index.eta`
|
|
184
|
+
*/
|
|
185
|
+
resolvePageLayout(pageFile: string, frontMatterLayout: unknown, isIndexPage: boolean): PageLayoutResolution;
|
|
186
|
+
private discoverLayout;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Starts a dev server session for a source directory: builds reuse one index, and the dev
|
|
190
|
+
* server updates it on file events.
|
|
191
|
+
*/
|
|
192
|
+
export declare function startTemplateIndexSession(srcDir: string): void;
|
|
193
|
+
/**
|
|
194
|
+
* Ends the dev server session for a source directory; later builds read it again. A session
|
|
195
|
+
* another dev server started for a different directory is left alone.
|
|
196
|
+
*/
|
|
197
|
+
export declare function endTemplateIndexSession(srcDir: string): void;
|
|
198
|
+
/**
|
|
199
|
+
* Returns the template index for a build: the session's while a dev server watches the
|
|
200
|
+
* source directory, otherwise a new one.
|
|
201
|
+
*
|
|
202
|
+
* @param srcDir - Absolute source directory
|
|
203
|
+
*/
|
|
204
|
+
export declare function loadTemplateIndex(srcDir: string): Promise<TemplateIndex>;
|
|
205
|
+
/**
|
|
206
|
+
* The dev server session's index for a source directory, or null when there is none yet.
|
|
207
|
+
*/
|
|
208
|
+
export declare function getCachedTemplateIndex(srcDir: string): TemplateIndex | null;
|
|
209
|
+
//# sourceMappingURL=template-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-index.d.ts","sourceRoot":"","sources":["../../src/core/template-index.ts"],"names":[],"mappings":"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"}
|