@stati/core 1.13.0 → 1.14.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/dist/core/build.js
CHANGED
|
@@ -9,7 +9,7 @@ import { loadCacheManifest, saveCacheManifest, shouldRebuildPage, createCacheEnt
|
|
|
9
9
|
import { generateSitemap, generateRobotsTxtFromConfig, autoInjectSEO, } from '../seo/index.js';
|
|
10
10
|
import { generateRSSFeeds, validateRSSConfig } from '../rss/index.js';
|
|
11
11
|
import { getEnv } from '../env.js';
|
|
12
|
-
import { DEFAULT_TS_OUT_DIR } from '../constants.js';
|
|
12
|
+
import { DEFAULT_TS_OUT_DIR, DEFAULT_OUT_DIR } from '../constants.js';
|
|
13
13
|
/**
|
|
14
14
|
* Recursively calculates the total size of a directory in bytes.
|
|
15
15
|
* Used for build statistics.
|
|
@@ -244,23 +244,12 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
|
|
|
244
244
|
// Cache miss - need to rebuild
|
|
245
245
|
cacheMisses++;
|
|
246
246
|
const startTime = Date.now();
|
|
247
|
-
// Add rendering substeps to tree
|
|
248
|
-
const markdownId = `${pageId}-markdown`;
|
|
249
|
-
const templateId = `${pageId}-template`;
|
|
250
|
-
if (logger.addTreeNode) {
|
|
251
|
-
logger.addTreeNode(pageId, markdownId, 'Processing Markdown', 'running');
|
|
252
|
-
logger.addTreeNode(pageId, templateId, 'Applying Template', 'pending');
|
|
253
|
-
}
|
|
254
247
|
// Run beforeRender hook
|
|
255
248
|
if (config.hooks?.beforeRender) {
|
|
256
249
|
await config.hooks.beforeRender({ page, config });
|
|
257
250
|
}
|
|
258
251
|
// Render markdown to HTML
|
|
259
252
|
const htmlContent = renderMarkdown(page.content, md);
|
|
260
|
-
if (logger.updateTreeNode) {
|
|
261
|
-
logger.updateTreeNode(markdownId, 'completed');
|
|
262
|
-
logger.updateTreeNode(templateId, 'running');
|
|
263
|
-
}
|
|
264
253
|
// Render with template
|
|
265
254
|
let finalHtml = await renderPage(page, htmlContent, config, eta, navigation, pages, assets);
|
|
266
255
|
// Auto-inject SEO tags if enabled
|
|
@@ -282,7 +271,6 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
|
|
|
282
271
|
}
|
|
283
272
|
const renderTime = Date.now() - startTime;
|
|
284
273
|
if (logger.updateTreeNode) {
|
|
285
|
-
logger.updateTreeNode(templateId, 'completed');
|
|
286
274
|
logger.updateTreeNode(pageId, 'completed', {
|
|
287
275
|
timing: renderTime,
|
|
288
276
|
url: page.url,
|
|
@@ -407,7 +395,7 @@ async function buildInternal(options = {}) {
|
|
|
407
395
|
tsResult = await compileTypeScript({
|
|
408
396
|
projectRoot: process.cwd(),
|
|
409
397
|
config: config.typescript,
|
|
410
|
-
outDir: config.outDir ||
|
|
398
|
+
outDir: config.outDir || DEFAULT_OUT_DIR,
|
|
411
399
|
mode: getEnv() === 'production' ? 'production' : 'development',
|
|
412
400
|
logger,
|
|
413
401
|
});
|
|
@@ -432,6 +420,7 @@ async function buildInternal(options = {}) {
|
|
|
432
420
|
const inventorySize = getInventorySize();
|
|
433
421
|
if (inventorySize > 0) {
|
|
434
422
|
await writeTailwindClassInventory(cacheDir);
|
|
423
|
+
logger.info('');
|
|
435
424
|
logger.info(`📝 Generated Tailwind class inventory (${inventorySize} classes tracked)`);
|
|
436
425
|
}
|
|
437
426
|
// Disable inventory tracking after build
|
package/dist/core/dev.d.ts.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AA2B7D,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,CAwaxF"}
|
package/dist/core/dev.js
CHANGED
|
@@ -11,7 +11,7 @@ import { loadContent } from './content.js';
|
|
|
11
11
|
import { buildNavigation } from './navigation.js';
|
|
12
12
|
import { resolveDevPaths, resolveCacheDir, resolvePrettyUrl, createErrorOverlay, parseErrorDetails, TemplateError, createFallbackLogger, mergeServerOptions, createTypeScriptWatcher, } from './utils/index.js';
|
|
13
13
|
import { setEnv, getEnv } from '../env.js';
|
|
14
|
-
import { DEFAULT_DEV_PORT, DEFAULT_DEV_HOST, TEMPLATE_EXTENSION } from '../constants.js';
|
|
14
|
+
import { DEFAULT_DEV_PORT, DEFAULT_DEV_HOST, TEMPLATE_EXTENSION, DEFAULT_OUT_DIR, } from '../constants.js';
|
|
15
15
|
/**
|
|
16
16
|
* Loads and validates configuration for the dev server.
|
|
17
17
|
*/
|
|
@@ -527,11 +527,11 @@ export async function createDevServer(options = {}) {
|
|
|
527
527
|
tsWatcher = await createTypeScriptWatcher({
|
|
528
528
|
projectRoot: process.cwd(),
|
|
529
529
|
config: config.typescript,
|
|
530
|
-
outDir: config.outDir ||
|
|
530
|
+
outDir: config.outDir || DEFAULT_OUT_DIR,
|
|
531
531
|
mode: 'development',
|
|
532
532
|
logger,
|
|
533
|
-
onRebuild: () => {
|
|
534
|
-
logger.info?.(
|
|
533
|
+
onRebuild: (bundlePath, compileTimeMs) => {
|
|
534
|
+
logger.info?.(`⚡ ${bundlePath} recompiled in ${compileTimeMs}ms`);
|
|
535
535
|
// Broadcast reload to WebSocket clients
|
|
536
536
|
if (wsServer) {
|
|
537
537
|
wsServer.clients.forEach((client) => {
|
|
@@ -31,9 +31,19 @@ export interface CompileResult {
|
|
|
31
31
|
/**
|
|
32
32
|
* Options for TypeScript file watcher.
|
|
33
33
|
*/
|
|
34
|
-
export interface WatchOptions
|
|
35
|
-
/**
|
|
36
|
-
|
|
34
|
+
export interface WatchOptions {
|
|
35
|
+
/** Project root directory */
|
|
36
|
+
projectRoot: string;
|
|
37
|
+
/** TypeScript configuration */
|
|
38
|
+
config: TypeScriptConfig;
|
|
39
|
+
/** Output directory for the build */
|
|
40
|
+
outDir?: string;
|
|
41
|
+
/** Build mode */
|
|
42
|
+
mode: 'development' | 'production';
|
|
43
|
+
/** Logger instance */
|
|
44
|
+
logger: Logger;
|
|
45
|
+
/** Callback when rebuild completes, receives bundle path and compile time in ms */
|
|
46
|
+
onRebuild: (bundlePath: string, compileTimeMs: number) => void;
|
|
37
47
|
}
|
|
38
48
|
/**
|
|
39
49
|
* Compile TypeScript files using esbuild.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/typescript.utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAInC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"typescript.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/typescript.utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAInC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AASrD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,0GAA0G;IAC1G,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;CAChE;AAiCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA+CvF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAsD/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB5E;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAsCzE"}
|
|
@@ -7,7 +7,7 @@ import * as esbuild from 'esbuild';
|
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
import * as fs from 'node:fs/promises';
|
|
9
9
|
import { pathExists } from './fs.utils.js';
|
|
10
|
-
import { DEFAULT_TS_SRC_DIR, DEFAULT_TS_OUT_DIR, DEFAULT_TS_ENTRY_POINT, DEFAULT_TS_BUNDLE_NAME, } from '../../constants.js';
|
|
10
|
+
import { DEFAULT_TS_SRC_DIR, DEFAULT_TS_OUT_DIR, DEFAULT_TS_ENTRY_POINT, DEFAULT_TS_BUNDLE_NAME, DEFAULT_OUT_DIR, } from '../../constants.js';
|
|
11
11
|
function resolveConfig(config, mode) {
|
|
12
12
|
const isProduction = mode === 'production';
|
|
13
13
|
return {
|
|
@@ -46,13 +46,14 @@ export async function compileTypeScript(options) {
|
|
|
46
46
|
const resolved = resolveConfig(config, mode);
|
|
47
47
|
const entryPath = path.join(projectRoot, resolved.srcDir, resolved.entryPoint);
|
|
48
48
|
// Output to configured build output directory (default: dist)
|
|
49
|
-
const outDir = path.join(projectRoot, globalOutDir ||
|
|
49
|
+
const outDir = path.join(projectRoot, globalOutDir || DEFAULT_OUT_DIR, resolved.outDir);
|
|
50
50
|
// Validate entry point exists
|
|
51
51
|
if (!(await pathExists(entryPath))) {
|
|
52
52
|
logger.warning(`TypeScript entry point not found: ${entryPath}`);
|
|
53
53
|
logger.warning('Skipping TypeScript compilation.');
|
|
54
54
|
return {};
|
|
55
55
|
}
|
|
56
|
+
logger.info(''); // Add empty line before TypeScript compilation
|
|
56
57
|
logger.info('Compiling TypeScript...');
|
|
57
58
|
try {
|
|
58
59
|
const result = await esbuild.build({
|
|
@@ -108,7 +109,7 @@ export async function createTypeScriptWatcher(options) {
|
|
|
108
109
|
const resolved = resolveConfig(config, mode);
|
|
109
110
|
const entryPath = path.join(projectRoot, resolved.srcDir, resolved.entryPoint);
|
|
110
111
|
// Output to configured build output directory (default: dist)
|
|
111
|
-
const outDir = path.join(projectRoot, globalOutDir ||
|
|
112
|
+
const outDir = path.join(projectRoot, globalOutDir || DEFAULT_OUT_DIR, resolved.outDir);
|
|
112
113
|
// Validate entry point exists
|
|
113
114
|
if (!(await pathExists(entryPath))) {
|
|
114
115
|
logger.warning(`TypeScript entry point not found: ${entryPath}`);
|
|
@@ -129,15 +130,20 @@ export async function createTypeScriptWatcher(options) {
|
|
|
129
130
|
{
|
|
130
131
|
name: 'stati-rebuild-notify',
|
|
131
132
|
setup(build) {
|
|
133
|
+
let startTime;
|
|
134
|
+
build.onStart(() => {
|
|
135
|
+
startTime = Date.now();
|
|
136
|
+
});
|
|
132
137
|
build.onEnd((result) => {
|
|
138
|
+
const compileTime = Date.now() - startTime;
|
|
133
139
|
if (result.errors.length > 0) {
|
|
134
140
|
result.errors.forEach((err) => {
|
|
135
141
|
logger.error(`TypeScript error: ${err.text}`);
|
|
136
142
|
});
|
|
137
143
|
}
|
|
138
144
|
else {
|
|
139
|
-
|
|
140
|
-
onRebuild();
|
|
145
|
+
const bundlePath = `${globalOutDir || DEFAULT_OUT_DIR}/${resolved.outDir}/${resolved.bundleName}.js`;
|
|
146
|
+
onRebuild(bundlePath, compileTime);
|
|
141
147
|
}
|
|
142
148
|
});
|
|
143
149
|
},
|
|
@@ -219,8 +225,11 @@ export function autoInjectBundle(html, bundlePath) {
|
|
|
219
225
|
// Invalid path format, skip injection to prevent potential XSS
|
|
220
226
|
return html;
|
|
221
227
|
}
|
|
222
|
-
// Check if the bundle is already included (avoid duplicate injection)
|
|
223
|
-
|
|
228
|
+
// Check if the bundle script tag is already included (avoid duplicate injection)
|
|
229
|
+
// Must check for actual script tag, not just any occurrence of the path
|
|
230
|
+
// (e.g., modulepreload links should not prevent script injection)
|
|
231
|
+
const scriptTagPattern = new RegExp(`<script[^>]*\\ssrc=["']${bundlePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}["'][^>]*>`, 'i');
|
|
232
|
+
if (scriptTagPattern.test(html)) {
|
|
224
233
|
return html;
|
|
225
234
|
}
|
|
226
235
|
// Find </body> tag (case-insensitive)
|