@stati/core 1.7.1 → 1.8.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.
@@ -352,8 +352,6 @@ async function buildInternal(options = {}) {
352
352
  logger.building('Building your site...');
353
353
  // Load configuration
354
354
  const { config, outDir, cacheDir } = await loadAndValidateConfig(options);
355
- // Load cache manifest for ISG
356
- const { manifest } = await setupCacheAndManifest(cacheDir);
357
355
  // Initialize cache stats
358
356
  let cacheHits = 0;
359
357
  let cacheMisses = 0;
@@ -364,6 +362,8 @@ async function buildInternal(options = {}) {
364
362
  await remove(cacheDir);
365
363
  }
366
364
  await ensureDir(outDir);
365
+ // Load cache manifest for ISG (after potential clean operation)
366
+ const { manifest } = await setupCacheAndManifest(cacheDir);
367
367
  // Load content and build navigation
368
368
  console.log(); // Add spacing before content loading
369
369
  const { pages, navigation, md, eta } = await loadContentAndBuildNavigation(config, options, logger);
@@ -86,8 +86,8 @@ export function autoInjectSEO(html, options) {
86
86
  // Inject SEO metadata before </head>
87
87
  const before = html.substring(0, headClosePos);
88
88
  const after = html.substring(headClosePos);
89
- // Add proper indentation (2 spaces) and newline
90
- const injected = `${before} ${seoMetadata}\n${after}`;
89
+ // Add proper indentation (4 spaces) and newline
90
+ const injected = `${before} ${seoMetadata}\n${after}`;
91
91
  logDebug(`Injected ${existingTags.size === 0 ? 'all' : 'missing'} SEO tags into ${page.url}`, {
92
92
  debug,
93
93
  config,
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/seo/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAsH3D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAyE/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAuDjE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE;IACP,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,EACD,IAAI,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,GAChC,MAAM,CA6CR"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/seo/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAS7C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAsH3D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAyE/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAuDjE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE;IACP,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,EACD,IAAI,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,GAChC,MAAM,CA6CR"}
@@ -3,7 +3,7 @@
3
3
  * Generates meta tags, Open Graph tags, Twitter Cards, and structured data
4
4
  */
5
5
  import { SEOTagType } from '../types/seo.js';
6
- import { escapeHtml, validateSEOMetadata, generateRobotsContent } from './utils/index.js';
6
+ import { escapeHtml, validateSEOMetadata, generateRobotsContent, resolveAbsoluteUrl, } from './utils/index.js';
7
7
  import { sanitizeStructuredData } from './utils/escape-and-validation.js';
8
8
  /**
9
9
  * Generate complete SEO metadata for a page.
@@ -94,7 +94,7 @@ export function generateSEOMetadata(ctx) {
94
94
  }
95
95
  // Canonical link
96
96
  if (shouldGenerate(SEOTagType.Canonical)) {
97
- const canonical = seo.canonical || `${siteUrl}${page.url}`;
97
+ const canonical = seo.canonical || resolveAbsoluteUrl(page.url || '/', siteUrl);
98
98
  meta.push(`<link rel="canonical" href="${escapeHtml(canonical)}">`);
99
99
  }
100
100
  // Robots meta tag
@@ -125,7 +125,7 @@ export function generateSEOMetadata(ctx) {
125
125
  const sanitized = sanitizeStructuredData(seo.structuredData, logger);
126
126
  meta.push(`<script type="application/ld+json">${JSON.stringify(sanitized)}</script>`);
127
127
  }
128
- return meta.join('\n ');
128
+ return meta.join('\n ');
129
129
  }
130
130
  /**
131
131
  * Generate Open Graph protocol meta tags.
@@ -148,7 +148,7 @@ export function generateOpenGraphTags(ctx) {
148
148
  // Basic OG tags with fallback chain
149
149
  const ogTitle = og.title || seo.title || page.frontMatter.title || config.site.title;
150
150
  const ogDescription = og.description || seo.description || page.frontMatter.description;
151
- const ogUrl = og.url || seo.canonical || `${siteUrl}${page.url}`;
151
+ const ogUrl = og.url || seo.canonical || resolveAbsoluteUrl(page.url || '/', siteUrl);
152
152
  const ogType = og.type || 'website';
153
153
  const ogSiteName = og.siteName || config.site.title;
154
154
  tags.push(`<meta property="og:title" content="${escapeHtml(ogTitle)}">`);
@@ -1 +1 @@
1
- {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../src/seo/sitemap.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EAEb,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA6ItD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,WAAW,EACnB,aAAa,EAAE,aAAa,GAC3B,YAAY,GAAG,IAAI,CA4ErB;AA2BD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAUlE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAatF;AAoBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAAE,EAClB,MAAM,EAAE,WAAW,EACnB,aAAa,EAAE,aAAa,GAC3B,uBAAuB,CA8CzB"}
1
+ {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../src/seo/sitemap.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EAEb,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAqJtD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,WAAW,EACnB,aAAa,EAAE,aAAa,GAC3B,YAAY,GAAG,IAAI,CA4ErB;AA2BD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAUlE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAatF;AAoBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAAE,EAClB,MAAM,EAAE,WAAW,EACnB,aAAa,EAAE,aAAa,GAC3B,uBAAuB,CA8CzB"}
@@ -122,8 +122,16 @@ function determinePriority(page, rules, defaultPriority = 0.5) {
122
122
  return validatePriority(rule.priority);
123
123
  }
124
124
  }
125
- else if (page.url === pattern || page.url.startsWith(pattern)) {
126
- return validatePriority(rule.priority);
125
+ else {
126
+ // For non-glob patterns, check exact match or path prefix
127
+ if (page.url === pattern) {
128
+ return validatePriority(rule.priority);
129
+ }
130
+ // For path prefix matching, ensure we match at path boundaries
131
+ // e.g., "/api" matches "/api/foo" but "/" only matches "/" exactly
132
+ if (pattern !== '/' && page.url.startsWith(pattern + '/')) {
133
+ return validatePriority(rule.priority);
134
+ }
127
135
  }
128
136
  }
129
137
  return defaultPriority;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stati/core",
3
- "version": "1.7.1",
3
+ "version": "1.8.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",