@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.
Files changed (104) hide show
  1. package/README.md +10 -13
  2. package/dist/config/loader.d.ts +9 -0
  3. package/dist/config/loader.d.ts.map +1 -1
  4. package/dist/config/loader.js +77 -1
  5. package/dist/core/build.d.ts.map +1 -1
  6. package/dist/core/build.js +39 -29
  7. package/dist/core/content.d.ts.map +1 -1
  8. package/dist/core/content.js +9 -7
  9. package/dist/core/dev.d.ts.map +1 -1
  10. package/dist/core/dev.js +156 -197
  11. package/dist/core/eta-plugin.d.ts +60 -0
  12. package/dist/core/eta-plugin.d.ts.map +1 -0
  13. package/dist/core/eta-plugin.js +143 -0
  14. package/dist/core/isg/builder.d.ts +37 -19
  15. package/dist/core/isg/builder.d.ts.map +1 -1
  16. package/dist/core/isg/builder.js +70 -153
  17. package/dist/core/isg/deps.d.ts +8 -70
  18. package/dist/core/isg/deps.d.ts.map +1 -1
  19. package/dist/core/isg/deps.js +10 -401
  20. package/dist/core/isg/hash.d.ts.map +1 -1
  21. package/dist/core/isg/hash.js +2 -1
  22. package/dist/core/isg/index.d.ts +2 -2
  23. package/dist/core/isg/index.d.ts.map +1 -1
  24. package/dist/core/isg/index.js +3 -3
  25. package/dist/core/isg/manifest.d.ts.map +1 -1
  26. package/dist/core/isg/manifest.js +6 -1
  27. package/dist/core/markdown.d.ts +1 -1
  28. package/dist/core/markdown.d.ts.map +1 -1
  29. package/dist/core/markdown.js +3 -2
  30. package/dist/core/template-index.d.ts +209 -0
  31. package/dist/core/template-index.d.ts.map +1 -0
  32. package/dist/core/template-index.js +484 -0
  33. package/dist/core/template-render.d.ts +137 -0
  34. package/dist/core/template-render.d.ts.map +1 -0
  35. package/dist/core/template-render.js +444 -0
  36. package/dist/core/templates.d.ts +29 -11
  37. package/dist/core/templates.d.ts.map +1 -1
  38. package/dist/core/templates.js +115 -196
  39. package/dist/core/utils/context-validation.utils.d.ts +10 -6
  40. package/dist/core/utils/context-validation.utils.d.ts.map +1 -1
  41. package/dist/core/utils/context-validation.utils.js +39 -16
  42. package/dist/core/utils/date.utils.d.ts +1 -1
  43. package/dist/core/utils/date.utils.js +1 -1
  44. package/dist/core/utils/dev-css-watcher.utils.d.ts.map +1 -1
  45. package/dist/core/utils/dev-css-watcher.utils.js +3 -2
  46. package/dist/core/utils/error-overlay.utils.d.ts.map +1 -1
  47. package/dist/core/utils/error-overlay.utils.js +7 -45
  48. package/dist/core/utils/front-matter.utils.d.ts +50 -0
  49. package/dist/core/utils/front-matter.utils.d.ts.map +1 -0
  50. package/dist/core/utils/front-matter.utils.js +157 -0
  51. package/dist/core/utils/index.d.ts +4 -5
  52. package/dist/core/utils/index.d.ts.map +1 -1
  53. package/dist/core/utils/index.js +5 -7
  54. package/dist/core/utils/paths.utils.d.ts +3 -3
  55. package/dist/core/utils/paths.utils.js +6 -6
  56. package/dist/core/utils/tailwind-inventory.utils.d.ts +2 -2
  57. package/dist/core/utils/tailwind-inventory.utils.d.ts.map +1 -1
  58. package/dist/core/utils/tailwind-inventory.utils.js +15 -6
  59. package/dist/core/utils/template-discovery.utils.d.ts +3 -14
  60. package/dist/core/utils/template-discovery.utils.d.ts.map +1 -1
  61. package/dist/core/utils/template-discovery.utils.js +2 -62
  62. package/dist/core/utils/template-errors.utils.d.ts +14 -1
  63. package/dist/core/utils/template-errors.utils.d.ts.map +1 -1
  64. package/dist/core/utils/template-errors.utils.js +45 -4
  65. package/dist/core/utils/theme.utils.d.ts +17 -0
  66. package/dist/core/utils/theme.utils.d.ts.map +1 -0
  67. package/dist/core/utils/theme.utils.js +59 -0
  68. package/dist/images/index.d.ts +1 -2
  69. package/dist/images/index.d.ts.map +1 -1
  70. package/dist/images/index.js +0 -1
  71. package/dist/images/markdown-rule.d.ts +1 -2
  72. package/dist/images/markdown-rule.d.ts.map +1 -1
  73. package/dist/images/og.d.ts +2 -15
  74. package/dist/images/og.d.ts.map +1 -1
  75. package/dist/images/og.js +4 -47
  76. package/dist/images/runtime.d.ts +24 -5
  77. package/dist/images/runtime.d.ts.map +1 -1
  78. package/dist/images/runtime.js +14 -12
  79. package/dist/index.d.ts +2 -1
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/metrics/noop.d.ts.map +1 -1
  82. package/dist/metrics/noop.js +4 -1
  83. package/dist/metrics/recorder.d.ts.map +1 -1
  84. package/dist/metrics/recorder.js +11 -8
  85. package/dist/metrics/types.d.ts +31 -5
  86. package/dist/metrics/types.d.ts.map +1 -1
  87. package/dist/metrics/utils/html-report.utils.d.ts +2 -1
  88. package/dist/metrics/utils/html-report.utils.d.ts.map +1 -1
  89. package/dist/metrics/utils/html-report.utils.js +1115 -1136
  90. package/dist/types/config.d.ts +18 -6
  91. package/dist/types/config.d.ts.map +1 -1
  92. package/dist/types/content.d.ts +83 -16
  93. package/dist/types/content.d.ts.map +1 -1
  94. package/dist/types/index.d.ts +4 -3
  95. package/dist/types/index.d.ts.map +1 -1
  96. package/dist/types/isg.d.ts +48 -2
  97. package/dist/types/isg.d.ts.map +1 -1
  98. package/package.json +6 -6
  99. package/dist/core/utils/callable-partials.utils.d.ts +0 -60
  100. package/dist/core/utils/callable-partials.utils.d.ts.map +0 -1
  101. package/dist/core/utils/callable-partials.utils.js +0 -127
  102. package/dist/core/utils/partial-validation.utils.d.ts +0 -9
  103. package/dist/core/utils/partial-validation.utils.d.ts.map +0 -1
  104. package/dist/core/utils/partial-validation.utils.js +0 -107
@@ -92,6 +92,34 @@ export class TemplateError extends Error {
92
92
  return errorDetails;
93
93
  }
94
94
  }
95
+ /**
96
+ * Thrown by Stati's template functions, such as `stati.include()` and `stati.layout()`, for a
97
+ * mistake at the call: an unknown template name, props that are not an object, Eta's own
98
+ * `include()`. Thrown inside a template, so Eta's debug mode adds the calling template and line
99
+ * to the message, and keeps this error as its `cause`.
100
+ */
101
+ export class TemplateUsageError extends Error {
102
+ /** Fixes to show in the error overlay */
103
+ suggestions;
104
+ constructor(message, suggestions = []) {
105
+ super(message);
106
+ this.name = 'TemplateUsageError';
107
+ this.suggestions = suggestions;
108
+ }
109
+ }
110
+ /**
111
+ * The errors an error wraps through `cause`, outermost first. Eta 4 sets `cause` on the errors
112
+ * its debug mode rethrows, once per template the error passes through.
113
+ */
114
+ function causeChain(error) {
115
+ const chain = [];
116
+ let current = error;
117
+ while (current instanceof Error && !chain.includes(current) && chain.length < 64) {
118
+ chain.push(current);
119
+ current = current.cause;
120
+ }
121
+ return chain;
122
+ }
95
123
  /**
96
124
  * Header that Eta's debug mode prepends to runtime errors:
97
125
  * `<path>:<line>` (or `line <line>` without a path), a numbered excerpt of the
@@ -106,14 +134,19 @@ const CONTEXT_ROOT_NAMES = new Set([
106
134
  'site',
107
135
  'page',
108
136
  'content',
137
+ 'body',
109
138
  'nav',
110
- 'partials',
111
139
  'collection',
140
+ 'pagination',
141
+ 'generated',
112
142
  'props',
143
+ 'helpers',
113
144
  'assets',
114
145
  'generator',
115
146
  'generateSEO',
116
147
  'propValue',
148
+ 'slugify',
149
+ 'image',
117
150
  ]);
118
151
  function getReferenceErrorSuggestions(message) {
119
152
  const name = message.match(/^(\S+) is not defined$/)?.[1];
@@ -155,10 +188,14 @@ export function parseEtaError(error, templatePath) {
155
188
  }
156
189
  let suggestions = [];
157
190
  const unknownProperty = parseUnknownPropertyMessage(message);
191
+ const usageError = causeChain(error).find((cause) => cause instanceof TemplateUsageError);
158
192
  if (unknownProperty) {
159
193
  message = unknownProperty.message;
160
194
  suggestions = unknownProperty.suggestions;
161
195
  }
196
+ else if (usageError) {
197
+ suggestions = [...usageError.suggestions];
198
+ }
162
199
  else if (error.name === 'ReferenceError') {
163
200
  suggestions = getReferenceErrorSuggestions(message);
164
201
  }
@@ -178,11 +215,15 @@ export function parseEtaError(error, templatePath) {
178
215
  return new TemplateError(message, filePath, line, column, undefined, suggestions);
179
216
  }
180
217
  /**
181
- * Enhances a generic error with template-specific context.
218
+ * Enhances a generic error with template-specific context. An error that wraps a
219
+ * {@link TemplateError}, as Eta's debug mode does for an error from a nested template, returns
220
+ * the innermost one, which points at the template that failed.
182
221
  */
183
222
  export function createTemplateError(error, templatePath, _line, _column) {
184
- if (error instanceof TemplateError) {
185
- return error;
223
+ const chain = causeChain(error);
224
+ const innermost = chain.reverse().find((cause) => cause instanceof TemplateError);
225
+ if (innermost) {
226
+ return innermost;
186
227
  }
187
228
  return parseEtaError(error, templatePath);
188
229
  }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Look of the pages Stati shows about its own work: the development error overlay and the
3
+ * build metrics report. Both follow the design of the Stati documentation site: slate neutrals,
4
+ * one blue accent and hairline rules, in a light and a dark theme.
5
+ */
6
+ /** The Stati mark, a lightning bolt, as an SVG path on a 24 by 24 grid */
7
+ export declare const STATI_MARK_PATH = "M13 10V3L4 14h7v7l9-11h-7z";
8
+ /** Inline favicon, so these pages never request the site's own favicon. */
9
+ export declare const STATI_FAVICON_HREF: string;
10
+ /**
11
+ * Color tokens as RGB channels, for `rgb(var(--ink))` and `rgb(var(--ink) / 0.4)`, in the light
12
+ * theme and, when the system asks for it, the dark theme; and the three font stacks.
13
+ */
14
+ export declare const STATI_THEME_STYLES = "\n :root {\n --canvas: 255 255 255;\n --raised: 248 250 252;\n --sunken: 246 248 250;\n --ink: 11 13 18;\n --muted: 71 85 105;\n --faint: 91 101 119;\n --line: 226 232 240;\n --line-strong: 203 213 225;\n --accent: 37 99 235;\n --accent-ink: 29 78 216;\n --on-accent: 255 255 255;\n --danger: 185 28 28;\n --danger-wash: 254 242 242;\n color-scheme: light;\n --font-display: 'Archivo', 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n --font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --font-mono: 'Fira Code', ui-monospace, 'Cascadia Code', Menlo, Monaco, Consolas, 'Liberation Mono', monospace;\n }\n\n @media (prefers-color-scheme: dark) {\n :root {\n --canvas: 2 6 23;\n --raised: 15 23 42;\n --sunken: 11 18 32;\n --ink: 241 245 249;\n --muted: 148 163 184;\n --faint: 131 145 167;\n --line: 30 41 59;\n --line-strong: 51 65 85;\n --accent: 96 165 250;\n --accent-ink: 147 197 253;\n --on-accent: 2 6 23;\n --danger: 248 113 113;\n --danger-wash: 38 12 20;\n color-scheme: dark;\n }\n }";
15
+ /** The light theme on paper, so a page viewed in the dark theme does not print light on white. */
16
+ export declare const STATI_PRINT_STYLES = "\n @media print {\n :root {\n --canvas: 255 255 255;\n --raised: 248 250 252;\n --sunken: 246 248 250;\n --ink: 11 13 18;\n --muted: 71 85 105;\n --faint: 91 101 119;\n --line: 226 232 240;\n --line-strong: 203 213 225;\n --accent: 37 99 235;\n --accent-ink: 29 78 216;\n --on-accent: 255 255 255;\n --danger: 185 28 28;\n --danger-wash: 254 242 242;\n color-scheme: light;\n }\n }";
17
+ //# sourceMappingURL=theme.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/theme.utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,eAAe,+BAA+B,CAAC;AAE5D,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,QAE5B,CAAC;AAkBJ;;;GAGG;AACH,eAAO,MAAM,kBAAkB,yvCAwBzB,CAAC;AAEP,kGAAkG;AAClG,eAAO,MAAM,kBAAkB,wdAIzB,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Look of the pages Stati shows about its own work: the development error overlay and the
3
+ * build metrics report. Both follow the design of the Stati documentation site: slate neutrals,
4
+ * one blue accent and hairline rules, in a light and a dark theme.
5
+ */
6
+ /** The Stati mark, a lightning bolt, as an SVG path on a 24 by 24 grid */
7
+ export const STATI_MARK_PATH = 'M13 10V3L4 14h7v7l9-11h-7z';
8
+ /** Inline favicon, so these pages never request the site's own favicon. */
9
+ export const STATI_FAVICON_HREF = `data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="${STATI_MARK_PATH}"/></svg>`)}`;
10
+ const LIGHT_COLORS = `
11
+ --canvas: 255 255 255;
12
+ --raised: 248 250 252;
13
+ --sunken: 246 248 250;
14
+ --ink: 11 13 18;
15
+ --muted: 71 85 105;
16
+ --faint: 91 101 119;
17
+ --line: 226 232 240;
18
+ --line-strong: 203 213 225;
19
+ --accent: 37 99 235;
20
+ --accent-ink: 29 78 216;
21
+ --on-accent: 255 255 255;
22
+ --danger: 185 28 28;
23
+ --danger-wash: 254 242 242;
24
+ color-scheme: light;`;
25
+ /**
26
+ * Color tokens as RGB channels, for `rgb(var(--ink))` and `rgb(var(--ink) / 0.4)`, in the light
27
+ * theme and, when the system asks for it, the dark theme; and the three font stacks.
28
+ */
29
+ export const STATI_THEME_STYLES = `
30
+ :root {${LIGHT_COLORS}
31
+ --font-display: 'Archivo', 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
32
+ --font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
33
+ --font-mono: 'Fira Code', ui-monospace, 'Cascadia Code', Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
34
+ }
35
+
36
+ @media (prefers-color-scheme: dark) {
37
+ :root {
38
+ --canvas: 2 6 23;
39
+ --raised: 15 23 42;
40
+ --sunken: 11 18 32;
41
+ --ink: 241 245 249;
42
+ --muted: 148 163 184;
43
+ --faint: 131 145 167;
44
+ --line: 30 41 59;
45
+ --line-strong: 51 65 85;
46
+ --accent: 96 165 250;
47
+ --accent-ink: 147 197 253;
48
+ --on-accent: 2 6 23;
49
+ --danger: 248 113 113;
50
+ --danger-wash: 38 12 20;
51
+ color-scheme: dark;
52
+ }
53
+ }`;
54
+ /** The light theme on paper, so a page viewed in the dark theme does not print light on white. */
55
+ export const STATI_PRINT_STYLES = `
56
+ @media print {
57
+ :root {${LIGHT_COLORS}
58
+ }
59
+ }`;
@@ -6,9 +6,8 @@
6
6
  export { resolveImagesConfig, validateImagesConfig } from './config.js';
7
7
  export type { ResolvedImagesConfig, ResolvedResponsiveConfig, ResolvedOgConfig } from './config.js';
8
8
  export { ImageRuntime, PageImages, validateOgBaseUrl } from './runtime.js';
9
- export type { StatiImageOptions, SettleResult, ImageRuntimeOptions } from './runtime.js';
9
+ export type { StatiImageOptions, SettleResult, ImageRuntimeOptions, OgTemplateRenderer, } from './runtime.js';
10
10
  export { installImageRule, selectEagerImage } from './markdown-rule.js';
11
- export { findOgTemplatePath, clearOgTemplateCache } from './og.js';
12
11
  export { loadImageProvider, resolveImagesPackage, missingPackageMessage } from './provider.js';
13
12
  export { probeImage } from './utils/index.js';
14
13
  export type { ImageProbeResult } from './utils/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/images/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC3E,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/images/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC3E,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -6,6 +6,5 @@
6
6
  export { resolveImagesConfig, validateImagesConfig } from './config.js';
7
7
  export { ImageRuntime, PageImages, validateOgBaseUrl } from './runtime.js';
8
8
  export { installImageRule, selectEagerImage } from './markdown-rule.js';
9
- export { findOgTemplatePath, clearOgTemplateCache } from './og.js';
10
9
  export { loadImageProvider, resolveImagesPackage, missingPackageMessage } from './provider.js';
11
10
  export { probeImage } from './utils/index.js';
@@ -2,8 +2,7 @@
2
2
  * The markdown-it `image` rule that adds dimensions, lazy loading and responsive variants.
3
3
  * @module images/markdown-rule
4
4
  */
5
- import type MarkdownIt from 'markdown-it';
6
- import type Token from 'markdown-it/lib/token.mjs';
5
+ import type { MarkdownIt, Token } from 'markdown-it';
7
6
  /** Key of the page's image state in the markdown-it `env`. */
8
7
  export declare const IMAGES_ENV_KEY = "statiImages";
9
8
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-rule.d.ts","sourceRoot":"","sources":["../../src/images/markdown-rule.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,KAAK,MAAM,2BAA2B,CAAC;AAGnD,8DAA8D;AAC9D,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAO5C;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI,CAwBrD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,SAAS,CAanE"}
1
+ {"version":3,"file":"markdown-rule.d.ts","sourceRoot":"","sources":["../../src/images/markdown-rule.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGrD,8DAA8D;AAC9D,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAO5C;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI,CAwBrD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,SAAS,CAanE"}
@@ -1,22 +1,9 @@
1
1
  /**
2
- * Helpers for Open Graph image generation: template lookup, exclusions and inlining.
2
+ * Helpers for Open Graph image generation: exclusions and inlining. Core finds a page's
3
+ * template through the template index, nearest folder first.
3
4
  * @module images/og
4
5
  */
5
6
  import type { PageModel } from '../types/index.js';
6
- /**
7
- * Clears the Open Graph template lookup cache.
8
- */
9
- export declare function clearOgTemplateCache(): void;
10
- /**
11
- * Finds the Open Graph template for a page: the nearest file named `templateName` in the
12
- * page's directory or one of its parents, up to the source directory.
13
- *
14
- * @param pageSourcePath - Absolute path of the page's Markdown file
15
- * @param srcDir - Absolute source directory
16
- * @param templateName - Template file name, such as `og.eta`
17
- * @returns Absolute path of the template, or null when there is none
18
- */
19
- export declare function findOgTemplatePath(pageSourcePath: string, srcDir: string, templateName: string): Promise<string | null>;
20
7
  /**
21
8
  * Whether a page gets no generated Open Graph image: it sets its own image in front matter
22
9
  * (`seo.openGraph.image`, or `false` to have none) or matches an `exclude` pattern.
@@ -1 +1 @@
1
- {"version":3,"file":"og.d.ts","sourceRoot":"","sources":["../../src/images/og.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAKnD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyBxB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAOtF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAU/C;AAsCD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC5D,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GACrD,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAwC5C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE"}
1
+ {"version":3,"file":"og.d.ts","sourceRoot":"","sources":["../../src/images/og.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAOtF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAU/C;AAsCD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC5D,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GACrD,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAwC5C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE"}
package/dist/images/og.js CHANGED
@@ -1,54 +1,11 @@
1
1
  /**
2
- * Helpers for Open Graph image generation: template lookup, exclusions and inlining.
2
+ * Helpers for Open Graph image generation: exclusions and inlining. Core finds a page's
3
+ * template through the template index, nearest folder first.
3
4
  * @module images/og
4
5
  */
5
- import { dirname, extname, join, relative, resolve } from 'node:path';
6
- import { isPathWithinDirectory, pathExists, readFileBuffer } from '../core/utils/index.js';
6
+ import { extname, join, relative, resolve } from 'node:path';
7
+ import { isPathWithinDirectory, readFileBuffer } from '../core/utils/index.js';
7
8
  import { matchesGlob } from '../core/utils/glob-patterns.utils.js';
8
- /** Cache of template lookups per directory, cleared at the start of each build. */
9
- const templateCache = new Map();
10
- /**
11
- * Clears the Open Graph template lookup cache.
12
- */
13
- export function clearOgTemplateCache() {
14
- templateCache.clear();
15
- }
16
- /**
17
- * Finds the Open Graph template for a page: the nearest file named `templateName` in the
18
- * page's directory or one of its parents, up to the source directory.
19
- *
20
- * @param pageSourcePath - Absolute path of the page's Markdown file
21
- * @param srcDir - Absolute source directory
22
- * @param templateName - Template file name, such as `og.eta`
23
- * @returns Absolute path of the template, or null when there is none
24
- */
25
- export async function findOgTemplatePath(pageSourcePath, srcDir, templateName) {
26
- const root = resolve(srcDir);
27
- let dir = dirname(resolve(pageSourcePath));
28
- const visited = [];
29
- while (isPathWithinDirectory(root, dir)) {
30
- const cacheKey = `${dir}|${templateName}`;
31
- if (templateCache.has(cacheKey)) {
32
- const cached = templateCache.get(cacheKey);
33
- for (const key of visited)
34
- templateCache.set(key, cached);
35
- return cached;
36
- }
37
- visited.push(cacheKey);
38
- const candidate = join(dir, templateName);
39
- if (await pathExists(candidate)) {
40
- for (const key of visited)
41
- templateCache.set(key, candidate);
42
- return candidate;
43
- }
44
- if (dir === root)
45
- break;
46
- dir = dirname(dir);
47
- }
48
- for (const key of visited)
49
- templateCache.set(key, null);
50
- return null;
51
- }
52
9
  /**
53
10
  * Whether a page gets no generated Open Graph image: it sets its own image in front matter
54
11
  * (`seo.openGraph.image`, or `false` to have none) or matches an `exclude` pattern.
@@ -3,13 +3,32 @@
3
3
  * written pages need, recovers from failed jobs and prunes outputs no page uses.
4
4
  * @module images/runtime
5
5
  */
6
- import type { Eta } from 'eta';
7
- import type Token from 'markdown-it/lib/token.mjs';
6
+ import type { Token } from 'markdown-it';
8
7
  import type { CacheManifest, GeneratedOgImage, ImageProvider, Logger, OgFont, PageModel, StatiConfig } from '../types/index.js';
9
8
  import type { RenderedAssets } from '../core/isg/builder.js';
10
9
  import { type ResolvedImagesConfig, type ResolvedOgConfig, type ResolvedResponsiveConfig } from './config.js';
11
10
  import { type SourceInfo } from './sources.js';
12
11
  import { type CopyPlan, type VariantPlan } from './plan.js';
12
+ /**
13
+ * Finds and renders a page's Open Graph template, for {@link PageImages.renderOg}. Core's
14
+ * renderer resolves the template through the template index and renders it like any other
15
+ * template, so it can use `stati.include()` and `stati.layout()`.
16
+ */
17
+ export interface OgTemplateRenderer {
18
+ /**
19
+ * Finds the page's template by file name, such as `og.eta`: the nearest one in the page's
20
+ * folder or a parent folder.
21
+ *
22
+ * @returns The template's absolute path, or null when there is none
23
+ */
24
+ find(templateName: string): string | null;
25
+ /** Renders a template that `find` returned, or the source of the built-in template */
26
+ render(template: {
27
+ path: string;
28
+ } | {
29
+ source: string;
30
+ }): Promise<string>;
31
+ }
13
32
  /**
14
33
  * Options for `stati.image()` in templates.
15
34
  */
@@ -119,11 +138,11 @@ export declare class PageImages {
119
138
  /**
120
139
  * Renders this page's Open Graph template and registers the card.
121
140
  *
122
- * @param context - Template context: the layout's, with an empty body and `stati.og`
123
- * @param eta - The template engine
141
+ * @param renderer - Finds the page's template and renders it, or the built-in template, with
142
+ * the layout's values, an empty body and `stati.og`
124
143
  * @returns The generated image, or null when the page gets none
125
144
  */
126
- renderOg(context: object, eta: Eta): Promise<GeneratedOgImage | null>;
145
+ renderOg(renderer: OgTemplateRenderer): Promise<GeneratedOgImage | null>;
127
146
  }
128
147
  /**
129
148
  * Options for {@link ImageRuntime.create}.
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/images/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/images/runtime.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,7 @@ import { getSourceCacheEntries, inspectSourceSync, seedSourceCache, } from './so
17
17
  import { resolveImageSource } from './resolve.js';
18
18
  import { planCopy, planVariants } from './plan.js';
19
19
  import { renderImg, renderResponsiveImage } from './markup.js';
20
- import { displayTemplatePath, findOgTemplatePath, inlineLocalImages, isOgImageExcluded, ogImageSlug, } from './og.js';
20
+ import { displayTemplatePath, inlineLocalImages, isOgImageExcluded, ogImageSlug } from './og.js';
21
21
  /**
22
22
  * Bumped when the generated markup changes, so pages rendered by an older pipeline rebuild.
23
23
  */
@@ -104,10 +104,13 @@ export class PageImages {
104
104
  * is left as authored
105
105
  */
106
106
  renderMarkdownImage(token, alt) {
107
- const attributes = (token.attrs ?? []).filter(([name]) => !['src', 'alt', 'title', 'width', 'height'].includes(name.toLowerCase()));
108
- return this.renderImage(token.attrGet('src') ?? '', {
107
+ // markdown-it types attribute values as string | number; Stati handles them as text
108
+ const attributes = (token.attrs ?? [])
109
+ .filter(([name]) => !['src', 'alt', 'title', 'width', 'height'].includes(name.toLowerCase()))
110
+ .map(([name, value]) => [name, String(value)]);
111
+ return this.renderImage(token.attrGet('src')?.toString() ?? '', {
109
112
  alt,
110
- title: token.attrGet('title') ?? undefined,
113
+ title: token.attrGet('title')?.toString(),
111
114
  attributes,
112
115
  width: token.attrGet('width') ?? undefined,
113
116
  height: token.attrGet('height') ?? undefined,
@@ -212,18 +215,18 @@ export class PageImages {
212
215
  /**
213
216
  * Renders this page's Open Graph template and registers the card.
214
217
  *
215
- * @param context - Template context: the layout's, with an empty body and `stati.og`
216
- * @param eta - The template engine
218
+ * @param renderer - Finds the page's template and renders it, or the built-in template, with
219
+ * the layout's values, an empty body and `stati.og`
217
220
  * @returns The generated image, or null when the page gets none
218
221
  */
219
- async renderOg(context, eta) {
222
+ async renderOg(renderer) {
220
223
  const { og, ogState, provider } = this.runtime;
221
224
  if (!og || !ogState || !provider?.renderOgImage)
222
225
  return null;
223
226
  if (isOgImageExcluded(this.page, og.exclude))
224
227
  return null;
225
228
  const srcDir = this.runtime.srcDir;
226
- const templatePath = await findOgTemplatePath(this.page.sourcePath, srcDir, og.template);
229
+ const templatePath = renderer.find(og.template);
227
230
  if (!templatePath && !ogState.defaultTemplate)
228
231
  return null;
229
232
  const templateLabel = templatePath
@@ -231,9 +234,7 @@ export class PageImages {
231
234
  : 'built-in Open Graph template';
232
235
  let html;
233
236
  try {
234
- html = templatePath
235
- ? await eta.renderAsync(toPosix(relative(srcDir, templatePath)), context)
236
- : await eta.renderStringAsync(ogState.defaultTemplate, context);
237
+ html = await renderer.render(templatePath ? { path: templatePath } : { source: ogState.defaultTemplate });
237
238
  }
238
239
  catch (error) {
239
240
  const failure = error instanceof Error ? error : new Error(String(error));
@@ -423,7 +424,8 @@ export class ImageRuntime {
423
424
  * @returns The files to record on the page's cache entry
424
425
  */
425
426
  commitPage(pageImages, html, info) {
426
- // Partials are pre-rendered for every page, so keep only images the page really shows
427
+ // A template can render an image and then discard the output, so keep only images the
428
+ // written page really shows
427
429
  const used = pageImages.uses.filter((use) => html.includes(use.marker));
428
430
  for (const use of used) {
429
431
  this.startJob(use.jobKey);
package/dist/index.d.ts CHANGED
@@ -19,10 +19,11 @@
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, CollectionData, CollectionsConfig, GeneratedPageEntry, PaginationData, GeneratedPageData, PaginateOptions, GenerateOptions, } from './types/index.js';
22
+ export type { SiteConfig, StatiConfig, StatiHelpers, TemplateContext, TemplateIncludeFunction, TemplateLayoutFunction, 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';
26
+ export type { MarkdownIt } from './types/index.js';
26
27
  export type { ImagesConfig, ResponsiveImagesConfig, OgImagesConfig, OgImageFontConfig, ImagesQualityConfig, ImageVariantFormat, ImageOutputFormat, ImageSourceFormat, ImageProvider, VariantRequest, VariantOutput, OgImageRequest, OgFont, OgDefaults, GeneratedOgImage, } from './types/index.js';
27
28
  export type { BuildOptions, MetricsOptions, BuildResult, DevServerOptions, PreviewServerOptions, InvalidationResult, } from './core/index.js';
28
29
  export { build, createDevServer, createPreviewServer, invalidate } from './core/index.js';
@@ -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,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
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"noop.d.ts","sourceRoot":"","sources":["../../src/metrics/noop.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,cAAc,EAOf,MAAM,YAAY,CAAC;AAqGpB;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,cAAyC,CAAC"}
1
+ {"version":3,"file":"noop.d.ts","sourceRoot":"","sources":["../../src/metrics/noop.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,cAAc,EAOf,MAAM,YAAY,CAAC;AAyGpB;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,cAAyC,CAAC"}
@@ -31,7 +31,7 @@ class NoopMetricRecorder {
31
31
  setGauge(_name, _value) {
32
32
  /* noop */
33
33
  }
34
- recordPageTiming(_url, _durationMs, _cached, _templatesLoaded) {
34
+ recordPageTiming(_url, _durationMs, _cached, _templatesLoaded, _templateRenders) {
35
35
  /* noop */
36
36
  }
37
37
  snapshotMemory() {
@@ -71,6 +71,9 @@ class NoopMetricRecorder {
71
71
  cachedPages: 0,
72
72
  assetsCopied: 0,
73
73
  templatesLoaded: 0,
74
+ templateRenders: 0,
75
+ includeCacheHits: 0,
76
+ templatesIndexed: 0,
74
77
  markdownFilesProcessed: 0,
75
78
  imagesGenerated: 0,
76
79
  imagesCached: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/metrics/recorder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EAQtB,MAAM,YAAY,CAAC;AAsOpB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAaxF"}
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/metrics/recorder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EAQtB,MAAM,YAAY,CAAC;AAiPpB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAaxF"}
@@ -23,6 +23,9 @@ class ActiveMetricRecorder {
23
23
  cachedPages: 0,
24
24
  assetsCopied: 0,
25
25
  templatesLoaded: 0,
26
+ templateRenders: 0,
27
+ includeCacheHits: 0,
28
+ templatesIndexed: 0,
26
29
  markdownFilesProcessed: 0,
27
30
  imagesGenerated: 0,
28
31
  imagesCached: 0,
@@ -72,15 +75,15 @@ class ActiveMetricRecorder {
72
75
  const current = this.gauges.get(name) ?? 0;
73
76
  this.gauges.set(name, Math.max(current, value));
74
77
  }
75
- recordPageTiming(url, durationMs, cached, templatesLoaded) {
78
+ recordPageTiming(url, durationMs, cached, templatesLoaded, templateRenders) {
76
79
  if (this.detailed) {
77
- const timing = { url, durationMs, cached };
78
- if (templatesLoaded !== undefined) {
79
- this.pageTimings.push({ ...timing, templatesLoaded });
80
- }
81
- else {
82
- this.pageTimings.push(timing);
83
- }
80
+ this.pageTimings.push({
81
+ url,
82
+ durationMs,
83
+ cached,
84
+ ...(templatesLoaded !== undefined && { templatesLoaded }),
85
+ ...(templateRenders !== undefined && { templateRenders }),
86
+ });
84
87
  }
85
88
  }
86
89
  snapshotMemory() {
@@ -89,12 +89,24 @@ export interface MetricsPhases {
89
89
  readonly cacheManifestLoadMs?: number;
90
90
  /** TypeScript compilation */
91
91
  readonly typescriptCompileMs?: number;
92
- /** Total page rendering time (includes shouldRebuild + render + fileWrite + cacheEntry) */
92
+ /** Reading the names of every template in the source directory, once per build */
93
+ readonly templateIndexMs?: number;
94
+ /**
95
+ * Total page pipeline time; includes the beforeAll hook, the search index and the per-page
96
+ * totals below
97
+ */
93
98
  readonly pageRenderingMs?: number;
94
99
  /** Aggregate time checking if pages need rebuild (shouldRebuildPage) */
95
100
  readonly shouldRebuildTotalMs?: number;
96
- /** Aggregate time rendering pages (renderPage) */
101
+ /** Aggregate time rendering each page's Markdown to HTML */
102
+ readonly markdownRenderTotalMs?: number;
103
+ /** Aggregate time rendering pages through their templates (renderPage) */
97
104
  readonly renderPageTotalMs?: number;
105
+ /**
106
+ * Aggregate time spent on each rendered page between its templates and the file write: SEO,
107
+ * search and bundle tag injection, registering its images, and hashing what it read
108
+ */
109
+ readonly postRenderTotalMs?: number;
98
110
  /** Aggregate time writing HTML files to disk */
99
111
  readonly fileWriteTotalMs?: number;
100
112
  /** Aggregate time updating cache entries */
@@ -143,7 +155,18 @@ export interface MetricsCounts {
143
155
  readonly renderedPages: number;
144
156
  readonly cachedPages: number;
145
157
  readonly assetsCopied: number;
158
+ /** Distinct template files each rendered page used, summed over the rendered pages */
146
159
  readonly templatesLoaded: number;
160
+ /**
161
+ * Template renders across the rendered pages: each page's layout, the parents it names, every
162
+ * included template and the Open Graph template. An include served from the page's cache is
163
+ * not a render.
164
+ */
165
+ readonly templateRenders?: number;
166
+ /** Includes without props or children that reused the page's earlier render of the template */
167
+ readonly includeCacheHits?: number;
168
+ /** Templates in the source directory */
169
+ readonly templatesIndexed?: number;
147
170
  readonly markdownFilesProcessed: number;
148
171
  /** Image files generated or copied this build */
149
172
  readonly imagesGenerated?: number;
@@ -185,8 +208,10 @@ export interface PageTiming {
185
208
  readonly durationMs: number;
186
209
  /** Whether page was served from cache */
187
210
  readonly cached: boolean;
188
- /** Number of templates loaded for this page (undefined for cached pages) */
211
+ /** Distinct template files the page rendered (undefined for cached pages) */
189
212
  readonly templatesLoaded?: number;
213
+ /** Template renders for the page, repeated includes counted each time (undefined for cached pages) */
214
+ readonly templateRenders?: number;
190
215
  }
191
216
  /**
192
217
  * Incremental rebuild metrics for dev server.
@@ -249,9 +274,10 @@ export interface MetricRecorder {
249
274
  setGauge(name: GaugeName, value: number): void;
250
275
  /**
251
276
  * Record page timing (only when detailed mode enabled).
252
- * @param templatesLoaded - Number of templates loaded (optional, typically undefined for cached pages)
277
+ * @param templatesLoaded - Distinct template files the page rendered (undefined for cached pages)
278
+ * @param templateRenders - Template renders for the page (undefined for cached pages)
253
279
  */
254
- recordPageTiming(url: string, durationMs: number, cached: boolean, templatesLoaded?: number): void;
280
+ recordPageTiming(url: string, durationMs: number, cached: boolean, templatesLoaded?: number, templateRenders?: number): void;
255
281
  /**
256
282
  * Take memory snapshot to track peak RSS.
257
283
  */