@stati/core 1.9.0 → 1.10.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 (35) hide show
  1. package/README.md +6 -6
  2. package/dist/core/build.d.ts.map +1 -1
  3. package/dist/core/build.js +39 -4
  4. package/dist/core/dev.d.ts.map +1 -1
  5. package/dist/core/dev.js +70 -2
  6. package/dist/core/isg/hash.d.ts +14 -0
  7. package/dist/core/isg/hash.d.ts.map +1 -1
  8. package/dist/core/isg/hash.js +32 -1
  9. package/dist/core/isg/index.d.ts +1 -1
  10. package/dist/core/isg/index.d.ts.map +1 -1
  11. package/dist/core/isg/index.js +1 -1
  12. package/dist/core/isg/manifest.d.ts.map +1 -1
  13. package/dist/core/isg/manifest.js +7 -1
  14. package/dist/core/templates.d.ts.map +1 -1
  15. package/dist/core/templates.js +37 -6
  16. package/dist/core/utils/index.d.ts +2 -0
  17. package/dist/core/utils/index.d.ts.map +1 -1
  18. package/dist/core/utils/index.js +4 -0
  19. package/dist/core/utils/navigation-helpers.d.ts +124 -0
  20. package/dist/core/utils/navigation-helpers.d.ts.map +1 -0
  21. package/dist/core/utils/navigation-helpers.js +219 -0
  22. package/dist/core/utils/server.d.ts +1 -1
  23. package/dist/core/utils/server.d.ts.map +1 -1
  24. package/dist/core/utils/server.js +14 -1
  25. package/dist/core/utils/tailwind-inventory.d.ts +91 -0
  26. package/dist/core/utils/tailwind-inventory.d.ts.map +1 -0
  27. package/dist/core/utils/tailwind-inventory.js +228 -0
  28. package/dist/core/utils/template-utils.d.ts +3 -0
  29. package/dist/core/utils/template-utils.d.ts.map +1 -1
  30. package/dist/core/utils/template-utils.js +27 -3
  31. package/dist/types/content.d.ts +24 -3
  32. package/dist/types/content.d.ts.map +1 -1
  33. package/dist/types/isg.d.ts +4 -1
  34. package/dist/types/isg.d.ts.map +1 -1
  35. package/package.json +1 -1
package/README.md CHANGED
@@ -327,7 +327,7 @@ export default defineConfig({
327
327
  });
328
328
  ```
329
329
 
330
- > **For the complete configuration reference** including all options, advanced features, and detailed explanations, see the [Configuration Guide](https://docs.stati.build/configuration/).
330
+ > **For the complete configuration reference** including all options, advanced features, and detailed explanations, see the [Configuration Guide](https://docs.stati.build/configuration/file/).
331
331
 
332
332
  ---
333
333
 
@@ -621,14 +621,14 @@ Automatic navigation hierarchy based on your file structure:
621
621
  ```html
622
622
  <!-- Show breadcrumbs -->
623
623
  <nav>
624
- <% stati.page.breadcrumbs.forEach(crumb => { %>
624
+ <% stati.nav.getBreadcrumbs().forEach(crumb => { %>
625
625
  <a href="<%= crumb.url %>"><%= crumb.title %></a>
626
626
  <% }) %>
627
627
  </nav>
628
628
 
629
629
  <!-- Show navigation tree -->
630
630
  <ul>
631
- <% stati.navigation.forEach(item => { %>
631
+ <% stati.nav.tree.forEach(item => { %>
632
632
  <li><a href="<%= item.url %>"><%= item.title %></a></li>
633
633
  <% }) %>
634
634
  </ul>
@@ -739,9 +739,9 @@ export default defineConfig({
739
739
  ## Learn More
740
740
 
741
741
  - [**Full Documentation**](https://docs.stati.build) — Complete guides and tutorials
742
- - [**Configuration Guide**](https://docs.stati.build/configuration/) — All options explained
743
- - [**API Reference**](https://docs.stati.build/api/) — Detailed API docs
744
- - [**Examples**](https://docs.stati.build/examples/) — Real-world projects
742
+ - [**Configuration Guide**](https://docs.stati.build/configuration/file/) — All options explained
743
+ - [**API Reference**](https://docs.stati.build/api/reference/) — Detailed API docs
744
+ - [**Examples**](https://docs.stati.build/examples/list/) — Real-world projects
745
745
  - [**Contributing**](https://github.com/ianchak/stati/blob/main/CONTRIBUTING.md) — Help improve Stati
746
746
 
747
747
  ---
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/core/build.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAEV,UAAU,EACV,MAAM,EAKP,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAW3E"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/core/build.ts"],"names":[],"mappings":"AAyCA,OAAO,KAAK,EAEV,UAAU,EACV,MAAM,EAKP,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAW3E"}
@@ -1,4 +1,4 @@
1
- import { ensureDir, writeFile, remove, pathExists, stat, readdir, copyFile, resolveOutDir, resolveStaticDir, resolveCacheDir, } from './utils/index.js';
1
+ import { ensureDir, writeFile, remove, pathExists, stat, readdir, copyFile, resolveOutDir, resolveStaticDir, resolveCacheDir, enableInventoryTracking, disableInventoryTracking, clearInventory, writeTailwindClassInventory, getInventorySize, isTailwindUsed, loadPreviousInventory, } from './utils/index.js';
2
2
  import { join, dirname, relative } from 'path';
3
3
  import { posix } from 'path';
4
4
  import { loadConfig } from '../config/loader.js';
@@ -6,7 +6,7 @@ import { loadContent } from './content.js';
6
6
  import { createMarkdownProcessor, renderMarkdown } from './markdown.js';
7
7
  import { createTemplateEngine, renderPage } from './templates.js';
8
8
  import { buildNavigation } from './navigation.js';
9
- import { loadCacheManifest, saveCacheManifest, shouldRebuildPage, createCacheEntry, updateCacheEntry, withBuildLock, } from './isg/index.js';
9
+ import { loadCacheManifest, saveCacheManifest, shouldRebuildPage, createCacheEntry, updateCacheEntry, withBuildLock, computeNavigationHash, } from './isg/index.js';
10
10
  import { generateSitemap, generateRobotsTxtFromConfig, autoInjectSEO, } from '../seo/index.js';
11
11
  /**
12
12
  * Recursively calculates the total size of a directory in bytes.
@@ -172,10 +172,12 @@ async function loadContentAndBuildNavigation(config, options, logger) {
172
172
  if (logger.navigationTree) {
173
173
  logger.navigationTree(navigation);
174
174
  }
175
+ // Compute navigation hash for change detection in dev server
176
+ const navigationHash = computeNavigationHash(navigation);
175
177
  // Create processors
176
178
  const md = await createMarkdownProcessor(config);
177
179
  const eta = createTemplateEngine(config);
178
- return { pages, navigation, md, eta };
180
+ return { pages, navigation, md, eta, navigationHash };
179
181
  }
180
182
  /**
181
183
  * Processes pages with ISG caching logic.
@@ -362,17 +364,50 @@ async function buildInternal(options = {}) {
362
364
  await remove(cacheDir);
363
365
  }
364
366
  await ensureDir(outDir);
367
+ // Enable Tailwind class inventory tracking only if Tailwind is detected
368
+ const hasTailwind = await isTailwindUsed();
369
+ if (hasTailwind) {
370
+ enableInventoryTracking();
371
+ clearInventory(); // Clear any previous inventory
372
+ // Try to load from existing inventory file
373
+ const loadedCount = await loadPreviousInventory(cacheDir);
374
+ if (loadedCount > 0) {
375
+ // Write the initial inventory file immediately so Tailwind can scan it
376
+ // This is critical for dev server where Tailwind starts watching before template rendering
377
+ await writeTailwindClassInventory(cacheDir);
378
+ logger.info(`📦 Loaded ${loadedCount} classes from previous build for Tailwind scanner`);
379
+ }
380
+ else {
381
+ // No previous inventory found - write an empty placeholder file
382
+ // This ensures Tailwind has a file to scan even on first build
383
+ // It will be populated with actual classes after template rendering
384
+ await writeTailwindClassInventory(cacheDir);
385
+ logger.info(`📦 Created inventory file for Tailwind scanner (will be populated after rendering)`);
386
+ }
387
+ }
365
388
  // Load cache manifest for ISG (after potential clean operation)
366
389
  const { manifest } = await setupCacheAndManifest(cacheDir);
367
390
  // Load content and build navigation
368
391
  console.log(); // Add spacing before content loading
369
- const { pages, navigation, md, eta } = await loadContentAndBuildNavigation(config, options, logger);
392
+ const { pages, navigation, md, eta, navigationHash } = await loadContentAndBuildNavigation(config, options, logger);
393
+ // Store navigation hash in manifest for change detection in dev server
394
+ manifest.navigationHash = navigationHash;
370
395
  // Process pages with ISG caching logic
371
396
  console.log(); // Add spacing before page processing
372
397
  const buildTime = new Date();
373
398
  const pageProcessingResult = await processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger);
374
399
  cacheHits = pageProcessingResult.cacheHits;
375
400
  cacheMisses = pageProcessingResult.cacheMisses;
401
+ // Write Tailwind class inventory after all templates have been rendered (if Tailwind is used)
402
+ if (hasTailwind) {
403
+ const inventorySize = getInventorySize();
404
+ if (inventorySize > 0) {
405
+ await writeTailwindClassInventory(cacheDir);
406
+ logger.info(`📝 Generated Tailwind class inventory (${inventorySize} classes tracked)`);
407
+ }
408
+ // Disable inventory tracking after build
409
+ disableInventoryTracking();
410
+ }
376
411
  // Save updated cache manifest
377
412
  await saveCacheManifest(cacheDir, manifest);
378
413
  // Copy static assets and count them
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAiB7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAoOD,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CA2XxF"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAmB7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AA4SD,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CA2XxF"}
package/dist/core/dev.js CHANGED
@@ -7,7 +7,9 @@ import chokidar from 'chokidar';
7
7
  import { build } from './build.js';
8
8
  import { invalidate } from './invalidate.js';
9
9
  import { loadConfig } from '../config/loader.js';
10
- import { loadCacheManifest, saveCacheManifest } from './isg/index.js';
10
+ import { loadCacheManifest, saveCacheManifest, computeNavigationHash } from './isg/index.js';
11
+ import { loadContent } from './content.js';
12
+ import { buildNavigation } from './navigation.js';
11
13
  import { resolveDevPaths, resolveCacheDir, resolvePrettyUrl, createErrorOverlay, parseErrorDetails, TemplateError, } from './utils/index.js';
12
14
  import { setEnv, getEnv } from '../env.js';
13
15
  import { DEFAULT_DEV_PORT, DEFAULT_DEV_HOST, TEMPLATE_EXTENSION } from '../constants.js';
@@ -88,8 +90,11 @@ async function performIncrementalRebuild(changedPath, configPath, logger, wsServ
88
90
  if (changedPath.endsWith(TEMPLATE_EXTENSION) || changedPath.includes('_partials')) {
89
91
  await handleTemplateChange(changedPath, configPath, devLogger);
90
92
  }
93
+ else if (changedPath.endsWith('.md')) {
94
+ await handleMarkdownChange(changedPath, configPath, devLogger);
95
+ }
91
96
  else {
92
- // Content or static file changed - use normal rebuild
97
+ // Static file changed - use normal rebuild
93
98
  await build({
94
99
  logger: devLogger,
95
100
  force: false,
@@ -198,6 +203,69 @@ async function handleTemplateChange(templatePath, configPath, logger) {
198
203
  }
199
204
  }
200
205
  }
206
+ /**
207
+ * Handles markdown file changes by comparing navigation hashes.
208
+ * Only performs a full rebuild if navigation structure actually changed.
209
+ * Navigation changes come from frontmatter modifications (title, order, description).
210
+ * Content-only changes use incremental rebuilds.
211
+ */
212
+ async function handleMarkdownChange(_markdownPath, configPath, logger) {
213
+ const cacheDir = resolveCacheDir();
214
+ try {
215
+ // Load existing cache manifest
216
+ const cacheManifest = await loadCacheManifest(cacheDir);
217
+ if (!cacheManifest || !cacheManifest.navigationHash) {
218
+ // No cache or no navigation hash exists, perform full rebuild
219
+ await build({
220
+ logger,
221
+ force: false,
222
+ clean: false,
223
+ ...(configPath && { configPath }),
224
+ });
225
+ return;
226
+ }
227
+ // Load config and content to rebuild navigation tree
228
+ const config = await loadConfig(configPath);
229
+ const pages = await loadContent(config);
230
+ const newNavigation = buildNavigation(pages);
231
+ const newNavigationHash = computeNavigationHash(newNavigation);
232
+ // Compare navigation hashes
233
+ if (newNavigationHash !== cacheManifest.navigationHash) {
234
+ // Navigation structure changed - clear cache and force full rebuild
235
+ logger.info?.('📊 Navigation structure changed, performing full rebuild...');
236
+ // Force rebuild bypasses ISG cache entirely
237
+ await build({
238
+ logger,
239
+ force: true, // Force rebuild to bypass cache
240
+ clean: false,
241
+ ...(configPath && { configPath }),
242
+ });
243
+ }
244
+ else {
245
+ // Navigation unchanged - use incremental rebuild for content changes
246
+ await build({
247
+ logger,
248
+ force: false,
249
+ clean: false,
250
+ ...(configPath && { configPath }),
251
+ });
252
+ }
253
+ }
254
+ catch (_error) {
255
+ try {
256
+ // Fallback to full rebuild
257
+ await build({
258
+ logger,
259
+ force: false,
260
+ clean: false,
261
+ ...(configPath && { configPath }),
262
+ });
263
+ }
264
+ catch (fallbackError) {
265
+ throw fallbackError instanceof Error ? fallbackError : new Error(String(fallbackError));
266
+ }
267
+ }
268
+ }
201
269
  export async function createDevServer(options = {}) {
202
270
  const { port = DEFAULT_DEV_PORT, host = DEFAULT_DEV_HOST, open = false, configPath, logger = {
203
271
  info: (msg) => console.log(msg),
@@ -45,4 +45,18 @@ export declare function computeFileHash(filePath: string): Promise<string | null
45
45
  * ```
46
46
  */
47
47
  export declare function computeInputsHash(contentHash: string, depsHashes: string[]): string;
48
+ /**
49
+ * Computes a hash of the navigation tree structure.
50
+ * Used to detect when navigation has changed (title, url, order, children structure).
51
+ *
52
+ * @param navigation - The navigation tree to hash
53
+ * @returns SHA-256 hash as a hex string
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const hash = computeNavigationHash(navigationTree);
58
+ * console.log(hash); // "sha256-abc123..."
59
+ * ```
60
+ */
61
+ export declare function computeNavigationHash(navigation: unknown[]): string;
48
62
  //# sourceMappingURL=hash.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../../src/core/isg/hash.ts"],"names":[],"mappings":"AAwBA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAiBhG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiB9E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAKnF"}
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../../src/core/isg/hash.ts"],"names":[],"mappings":"AAwBA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAiBhG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiB9E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAKnF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,CAqCnE"}
@@ -97,7 +97,38 @@ export async function computeFileHash(filePath) {
97
97
  * ```
98
98
  */
99
99
  export function computeInputsHash(contentHash, depsHashes) {
100
- // Hash each dependency hash in sorted order for consistency
100
+ // Sort dependency hashes for consistency
101
101
  const sortedDepsHashes = [...depsHashes].sort();
102
102
  return createSha256Hash([contentHash, ...sortedDepsHashes]);
103
103
  }
104
+ /**
105
+ * Computes a hash of the navigation tree structure.
106
+ * Used to detect when navigation has changed (title, url, order, children structure).
107
+ *
108
+ * @param navigation - The navigation tree to hash
109
+ * @returns SHA-256 hash as a hex string
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const hash = computeNavigationHash(navigationTree);
114
+ * console.log(hash); // "sha256-abc123..."
115
+ * ```
116
+ */
117
+ export function computeNavigationHash(navigation) {
118
+ const normalizeNavNode = (node) => {
119
+ const normalized = {
120
+ title: String(node.title ?? ''),
121
+ url: String(node.url ?? ''),
122
+ };
123
+ if (node.order !== undefined && typeof node.order === 'number') {
124
+ normalized.order = node.order;
125
+ }
126
+ if (node.children && Array.isArray(node.children) && node.children.length > 0) {
127
+ normalized.children = node.children.map((child) => normalizeNavNode(child));
128
+ }
129
+ return normalized;
130
+ };
131
+ const normalizedNav = navigation.map((node) => normalizeNavNode(node));
132
+ const navJson = JSON.stringify(normalizedNav);
133
+ return createSha256Hash(navJson);
134
+ }
@@ -10,7 +10,7 @@ export { loadCacheManifest, saveCacheManifest, createEmptyManifest } from './man
10
10
  export { shouldRebuildPage, createCacheEntry, updateCacheEntry } from './builder.js';
11
11
  export { BuildLockManager, withBuildLock } from './build-lock.js';
12
12
  export { CircularDependencyError, trackTemplateDependencies, findPartialDependencies, resolveTemplatePath, } from './deps.js';
13
- export { computeContentHash, computeFileHash, computeInputsHash } from './hash.js';
13
+ export { computeContentHash, computeFileHash, computeInputsHash, computeNavigationHash, } from './hash.js';
14
14
  export { getSafeCurrentTime, parseSafeDate, computeEffectiveTTL, computeNextRebuildAt, isPageFrozen, applyAgingRules, } from './ttl.js';
15
15
  export { ISGConfigurationError, validateISGConfig, validatePageISGOverrides, extractNumericOverride, } from './validation.js';
16
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/isg/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAG1F,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrF,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGlE,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGnF,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/isg/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAG1F,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrF,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGlE,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC"}
@@ -15,7 +15,7 @@ export { BuildLockManager, withBuildLock } from './build-lock.js';
15
15
  // Dependency tracking
16
16
  export { CircularDependencyError, trackTemplateDependencies, findPartialDependencies, resolveTemplatePath, } from './deps.js';
17
17
  // Hash computation
18
- export { computeContentHash, computeFileHash, computeInputsHash } from './hash.js';
18
+ export { computeContentHash, computeFileHash, computeInputsHash, computeNavigationHash, } from './hash.js';
19
19
  // TTL and aging
20
20
  export { getSafeCurrentTime, parseSafeDate, computeEffectiveTTL, computeNextRebuildAt, isPageFrozen, applyAgingRules, } from './ttl.js';
21
21
  // Validation
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/core/isg/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,sBAAsB,CAAC;AAUtE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA8FvF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEhG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAInD"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/core/isg/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,sBAAsB,CAAC;AAUtE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAsGvF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEhG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAInD"}
@@ -71,7 +71,13 @@ export async function loadCacheManifest(cacheDir) {
71
71
  if (invalidEntryCount > 0) {
72
72
  console.warn(`Removed ${invalidEntryCount} invalid cache entries`);
73
73
  }
74
- return { entries: validatedEntries };
74
+ // Return manifest with entries AND navigationHash (if present)
75
+ const resultManifest = { entries: validatedEntries };
76
+ // Preserve navigationHash if it exists
77
+ if (typeof manifestObj.navigationHash === 'string') {
78
+ resultManifest.navigationHash = manifestObj.navigationHash;
79
+ }
80
+ return resultManifest;
75
81
  }
76
82
  catch (error) {
77
83
  const nodeError = error;
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/core/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG1B,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAkB,MAAM,mBAAmB,CAAC;AAwLzF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,GAAG,CAW7D;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,GAAG,EACR,UAAU,CAAC,EAAE,OAAO,EAAE,EACtB,QAAQ,CAAC,EAAE,SAAS,EAAE,GACrB,OAAO,CAAC,MAAM,CAAC,CAyKjB"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/core/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG1B,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAkB,MAAM,mBAAmB,CAAC;AAmNzF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,GAAG,CAW7D;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,GAAG,EACR,UAAU,CAAC,EAAE,OAAO,EAAE,EACtB,QAAQ,CAAC,EAAE,SAAS,EAAE,GACrB,OAAO,CAAC,MAAM,CAAC,CAsLjB"}
@@ -2,7 +2,7 @@ import { Eta } from 'eta';
2
2
  import { join, dirname, relative, basename, posix } from 'path';
3
3
  import glob from 'fast-glob';
4
4
  import { TEMPLATE_EXTENSION } from '../constants.js';
5
- import { getStatiVersion, isCollectionIndexPage, discoverLayout, getCollectionPathForPage, resolveSrcDir, createTemplateError, createValidatingPartialsProxy, propValue, wrapPartialsAsCallable, } from './utils/index.js';
5
+ import { getStatiVersion, isCollectionIndexPage, discoverLayout, getCollectionPathForPage, resolveSrcDir, createTemplateError, createValidatingPartialsProxy, propValue, wrapPartialsAsCallable, createNavigationHelpers, } from './utils/index.js';
6
6
  import { getEnv } from '../env.js';
7
7
  import { generateSEO } from '../seo/index.js';
8
8
  /**
@@ -100,6 +100,25 @@ function buildCollectionData(currentPage, allPages) {
100
100
  },
101
101
  };
102
102
  }
103
+ /**
104
+ * Builds collection data for a child page (showing parent collection data).
105
+ * Finds the parent collection and returns its data.
106
+ *
107
+ * @param currentPage - The current page being rendered
108
+ * @param allPages - All pages in the site
109
+ * @returns Collection data for the parent collection or undefined
110
+ */
111
+ function buildParentCollectionData(currentPage, allPages) {
112
+ // Get the parent collection path
113
+ const parentPath = getCollectionPathForPage(currentPage.url);
114
+ // Find the index page for the parent collection
115
+ const parentIndexPage = allPages.find((p) => p.url === parentPath);
116
+ if (parentIndexPage) {
117
+ // Build collection data for the parent
118
+ return buildCollectionData(parentIndexPage, allPages);
119
+ }
120
+ return undefined;
121
+ }
103
122
  /**
104
123
  * Discovers partials in the hierarchy for a given page path.
105
124
  * Scans all parent directories for folders starting with underscore.
@@ -168,15 +187,26 @@ export async function renderPage(page, body, config, eta, navigation, allPages)
168
187
  const srcDir = resolveSrcDir(config);
169
188
  const relativePath = relative(srcDir, page.sourcePath);
170
189
  const partialPaths = await discoverPartials(relativePath, config);
171
- // Build collection data if this is an index page and all pages are provided
190
+ // Build collection data based on page type
172
191
  let collectionData;
173
192
  const isIndexPage = allPages && isCollectionIndexPage(page, allPages);
174
- if (isIndexPage) {
175
- collectionData = buildCollectionData(page, allPages);
193
+ if (allPages) {
194
+ if (isIndexPage) {
195
+ // For index pages, show their own collection data
196
+ collectionData = buildCollectionData(page, allPages);
197
+ }
198
+ else {
199
+ // For child pages, show parent collection data
200
+ collectionData = buildParentCollectionData(page, allPages);
201
+ }
176
202
  }
177
203
  // Discover the appropriate layout using hierarchical layout.eta convention
178
204
  // Pass isIndexPage flag to enable index.eta lookup for aggregation pages
179
205
  const layoutPath = await discoverLayout(relativePath, config, page.frontMatter.layout, isIndexPage);
206
+ // Create navigation helpers
207
+ const navTree = navigation || [];
208
+ const navHelpers = createNavigationHelpers(navTree, page);
209
+ const currentNavNode = navHelpers.getCurrentNode();
180
210
  // Create base context for partial rendering
181
211
  const baseContext = {
182
212
  site: config.site,
@@ -185,10 +215,11 @@ export async function renderPage(page, body, config, eta, navigation, allPages)
185
215
  path: page.url,
186
216
  url: page.url, // Add url property for compatibility
187
217
  content: body,
218
+ navNode: currentNavNode, // Add current page's navigation node
188
219
  },
189
220
  content: body,
190
- navigation: navigation || [],
191
- collection: collectionData, // Add collection data for index pages
221
+ nav: navHelpers, // Replace navigation with nav helpers
222
+ collection: collectionData, // Add collection data
192
223
  // Add custom filters to context
193
224
  ...(config.eta?.filters || {}),
194
225
  generator: {
@@ -6,10 +6,12 @@ export { readFile, writeFile, pathExists, ensureDir, remove, copyFile, readdir,
6
6
  export { resolveSrcDir, resolveOutDir, resolveStaticDir, resolveCacheDir, resolveDevPaths, normalizeTemplatePath, resolveSrcPath, resolveOutPath, resolveStaticPath, } from './paths.js';
7
7
  export { discoverLayout, isCollectionIndexPage, getCollectionPathForPage, } from './template-discovery.js';
8
8
  export { propValue } from './template-utils.js';
9
+ export { trackTailwindClass, enableInventoryTracking, disableInventoryTracking, clearInventory, getInventory, getInventorySize, isTrackingEnabled, writeTailwindClassInventory, isTailwindUsed, resetTailwindDetection, loadPreviousInventory, } from './tailwind-inventory.js';
9
10
  export { createValidatingPartialsProxy } from './partial-validation.js';
10
11
  export { makeCallablePartial, wrapPartialsAsCallable } from './callable-partials.js';
11
12
  export type { CallablePartial } from './callable-partials.js';
12
13
  export { TemplateError, parseEtaError, createTemplateError } from './template-errors.js';
14
+ export { createNavigationHelpers } from './navigation-helpers.js';
13
15
  export { resolvePrettyUrl } from './server.js';
14
16
  export type { PrettyUrlResult } from './server.js';
15
17
  export { createErrorOverlay, parseErrorDetails } from './error-overlay.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,GACL,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAGxE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrF,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,GACL,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACd,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAGxE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrF,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGzF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -10,12 +10,16 @@ export { resolveSrcDir, resolveOutDir, resolveStaticDir, resolveCacheDir, resolv
10
10
  export { discoverLayout, isCollectionIndexPage, getCollectionPathForPage, } from './template-discovery.js';
11
11
  // Template utilities
12
12
  export { propValue } from './template-utils.js';
13
+ // Tailwind inventory utilities
14
+ export { trackTailwindClass, enableInventoryTracking, disableInventoryTracking, clearInventory, getInventory, getInventorySize, isTrackingEnabled, writeTailwindClassInventory, isTailwindUsed, resetTailwindDetection, loadPreviousInventory, } from './tailwind-inventory.js';
13
15
  // Partial validation utilities
14
16
  export { createValidatingPartialsProxy } from './partial-validation.js';
15
17
  // Callable partial utilities
16
18
  export { makeCallablePartial, wrapPartialsAsCallable } from './callable-partials.js';
17
19
  // Template error utilities
18
20
  export { TemplateError, parseEtaError, createTemplateError } from './template-errors.js';
21
+ // Navigation helper utilities
22
+ export { createNavigationHelpers } from './navigation-helpers.js';
19
23
  // Server utilities
20
24
  export { resolvePrettyUrl } from './server.js';
21
25
  // Error overlay utilities
@@ -0,0 +1,124 @@
1
+ import type { NavNode, PageModel } from '../../types/index.js';
2
+ /**
3
+ * Navigation helper utilities for template context.
4
+ * Provides methods for querying and traversing the navigation tree.
5
+ */
6
+ /**
7
+ * Finds a navigation node by its path or URL.
8
+ *
9
+ * @param tree - Navigation tree to search
10
+ * @param path - Path or URL to find
11
+ * @returns The found node or undefined
12
+ */
13
+ export declare function findNode(tree: NavNode[], path: string): NavNode | undefined;
14
+ /**
15
+ * Gets the children of a specific navigation node by path.
16
+ *
17
+ * @param tree - Navigation tree to search
18
+ * @param path - Path of the parent node
19
+ * @returns Array of child nodes or empty array if not found or no children
20
+ */
21
+ export declare function getChildren(tree: NavNode[], path: string): NavNode[];
22
+ /**
23
+ * Gets the parent node of a specific path.
24
+ *
25
+ * @param tree - Navigation tree to search
26
+ * @param path - Path to find parent for
27
+ * @returns The parent node or undefined
28
+ */
29
+ export declare function getParent(tree: NavNode[], path: string): NavNode | undefined;
30
+ /**
31
+ * Gets the siblings of a specific path (nodes at the same level).
32
+ *
33
+ * @param tree - Navigation tree to search
34
+ * @param path - Path to find siblings for
35
+ * @param includeSelf - Whether to include the node itself in the results
36
+ * @returns Array of sibling nodes or empty array
37
+ */
38
+ export declare function getSiblings(tree: NavNode[], path: string, includeSelf?: boolean): NavNode[];
39
+ /**
40
+ * Gets a subtree starting from a specific path.
41
+ *
42
+ * @param tree - Navigation tree to search
43
+ * @param path - Root path for the subtree
44
+ * @returns The subtree as an array (single node with its children) or empty array
45
+ */
46
+ export declare function getSubtree(tree: NavNode[], path: string): NavNode[];
47
+ /**
48
+ * Gets the breadcrumb trail from root to a specific path.
49
+ *
50
+ * @param tree - Navigation tree to search
51
+ * @param path - Path to get breadcrumbs for
52
+ * @returns Array of nodes from root to the target path
53
+ */
54
+ export declare function getBreadcrumbs(tree: NavNode[], path: string): NavNode[];
55
+ /**
56
+ * Finds the current page's navigation node.
57
+ *
58
+ * @param tree - Navigation tree to search
59
+ * @param currentPage - Current page model
60
+ * @returns The navigation node for the current page or undefined
61
+ */
62
+ export declare function getCurrentNode(tree: NavNode[], currentPage: PageModel): NavNode | undefined;
63
+ /**
64
+ * Creates a navigation helpers object for template context.
65
+ *
66
+ * @param tree - The full navigation tree
67
+ * @param currentPage - The current page being rendered
68
+ * @returns Object with navigation helper methods
69
+ */
70
+ export declare function createNavigationHelpers(tree: NavNode[], currentPage: PageModel): {
71
+ /**
72
+ * The full navigation tree.
73
+ * Use stati.nav.tree to access the global navigation.
74
+ */
75
+ tree: NavNode[];
76
+ /**
77
+ * Gets the full navigation tree.
78
+ * @returns The complete navigation tree
79
+ */
80
+ getTree: () => NavNode[];
81
+ /**
82
+ * Finds a navigation node by path or URL.
83
+ * @param path - The path or URL to find
84
+ * @returns The found node or undefined
85
+ */
86
+ findNode: (path: string) => NavNode | undefined;
87
+ /**
88
+ * Gets the children of a navigation node.
89
+ * @param path - The path of the parent node
90
+ * @returns Array of child navigation nodes
91
+ */
92
+ getChildren: (path: string) => NavNode[];
93
+ /**
94
+ * Gets the parent of a navigation node.
95
+ * @param path - The path to find the parent for (defaults to current page)
96
+ * @returns The parent node or undefined
97
+ */
98
+ getParent: (path?: string) => NavNode | undefined;
99
+ /**
100
+ * Gets the siblings of a navigation node.
101
+ * @param path - The path to find siblings for (defaults to current page)
102
+ * @param includeSelf - Whether to include the node itself
103
+ * @returns Array of sibling nodes
104
+ */
105
+ getSiblings: (path?: string, includeSelf?: boolean) => NavNode[];
106
+ /**
107
+ * Gets a subtree starting from a specific path.
108
+ * @param path - The root path for the subtree
109
+ * @returns Array containing the subtree
110
+ */
111
+ getSubtree: (path: string) => NavNode[];
112
+ /**
113
+ * Gets the breadcrumb trail for a path.
114
+ * @param path - The path to get breadcrumbs for (defaults to current page)
115
+ * @returns Array of nodes from root to the target
116
+ */
117
+ getBreadcrumbs: (path?: string) => NavNode[];
118
+ /**
119
+ * Gets the current page's navigation node.
120
+ * @returns The navigation node for the current page or undefined
121
+ */
122
+ getCurrentNode: () => NavNode | undefined;
123
+ };
124
+ //# sourceMappingURL=navigation-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-helpers.d.ts","sourceRoot":"","sources":["../../../src/core/utils/navigation-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;GAGG;AAEH;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAiB3E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAGpE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAE5E;AAiCD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,OAAO,EAAE,CAiBzF;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAGnE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAIvE;AAkCD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAE3F;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,SAAS;IAE3E;;;OAGG;;IAGH;;;OAGG;;IAGH;;;;OAIG;qBACc,MAAM;IAEvB;;;;OAIG;wBACiB,MAAM;IAE1B;;;;OAIG;uBACgB,MAAM;IAEzB;;;;;OAKG;yBACkB,MAAM;IAG3B;;;;OAIG;uBACgB,MAAM;IAEzB;;;;OAIG;4BACqB,MAAM;IAE9B;;;OAGG;;EAGN"}