@stati/core 1.14.0 → 1.15.1
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/constants.d.ts +8 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +5 -4
- package/dist/core/build.d.ts.map +1 -1
- package/dist/core/build.js +13 -17
- package/dist/core/dev.d.ts.map +1 -1
- package/dist/core/dev.js +16 -10
- package/dist/core/utils/bundle-matching.utils.d.ts +99 -0
- package/dist/core/utils/bundle-matching.utils.d.ts.map +1 -0
- package/dist/core/utils/bundle-matching.utils.js +138 -0
- package/dist/core/utils/index.d.ts +4 -2
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core/utils/index.js +3 -1
- package/dist/core/utils/typescript.utils.d.ts +45 -33
- package/dist/core/utils/typescript.utils.d.ts.map +1 -1
- package/dist/core/utils/typescript.utils.js +230 -115
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types/config.d.ts +83 -17
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/content.d.ts +11 -5
- package/dist/types/content.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TypeScript compilation utilities using esbuild.
|
|
3
3
|
* Provides functions for compiling TypeScript files and watching for changes.
|
|
4
|
+
* Supports multiple bundles with per-page targeting.
|
|
4
5
|
* @module core/utils/typescript
|
|
5
6
|
*/
|
|
6
7
|
import * as esbuild from 'esbuild';
|
|
7
8
|
import * as path from 'node:path';
|
|
8
9
|
import * as fs from 'node:fs/promises';
|
|
9
10
|
import { pathExists } from './fs.utils.js';
|
|
10
|
-
import {
|
|
11
|
+
import { validateUniqueBundleNames } from './bundle-matching.utils.js';
|
|
12
|
+
import { DEFAULT_TS_SRC_DIR, DEFAULT_TS_OUT_DIR, DEFAULT_BUNDLES, DEFAULT_OUT_DIR, } from '../../constants.js';
|
|
13
|
+
/**
|
|
14
|
+
* Resolves TypeScript config with defaults based on mode.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
11
17
|
function resolveConfig(config, mode) {
|
|
12
18
|
const isProduction = mode === 'production';
|
|
13
19
|
return {
|
|
14
20
|
enabled: config.enabled,
|
|
15
21
|
srcDir: config.srcDir ?? DEFAULT_TS_SRC_DIR,
|
|
16
22
|
outDir: config.outDir ?? DEFAULT_TS_OUT_DIR,
|
|
17
|
-
|
|
18
|
-
bundleName: config.bundleName ?? DEFAULT_TS_BUNDLE_NAME,
|
|
23
|
+
bundles: config.bundles ?? [...DEFAULT_BUNDLES],
|
|
19
24
|
// hash/minify: always false in dev (config ignored), configurable in prod (default true)
|
|
20
25
|
hash: isProduction && (config.hash ?? true),
|
|
21
26
|
minify: isProduction && (config.minify ?? true),
|
|
@@ -24,136 +29,196 @@ function resolveConfig(config, mode) {
|
|
|
24
29
|
};
|
|
25
30
|
}
|
|
26
31
|
/**
|
|
27
|
-
* Compile
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* @param options - Compilation options
|
|
31
|
-
* @returns The compilation result with bundle filename
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```typescript
|
|
35
|
-
* const result = await compileTypeScript({
|
|
36
|
-
* projectRoot: process.cwd(),
|
|
37
|
-
* config: { enabled: true },
|
|
38
|
-
* mode: 'production',
|
|
39
|
-
* logger: console,
|
|
40
|
-
* });
|
|
41
|
-
* console.log(result.bundleFilename); // 'bundle-a1b2c3d4.js'
|
|
42
|
-
* ```
|
|
32
|
+
* Compile a single bundle using esbuild.
|
|
33
|
+
* @internal
|
|
43
34
|
*/
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const entryPath = path.join(projectRoot, resolved.srcDir, resolved.entryPoint);
|
|
48
|
-
// Output to configured build output directory (default: dist)
|
|
49
|
-
const outDir = path.join(projectRoot, globalOutDir || DEFAULT_OUT_DIR, resolved.outDir);
|
|
35
|
+
async function compileSingleBundle(bundleConfig, resolvedConfig, projectRoot, globalOutDir, logger) {
|
|
36
|
+
const entryPath = path.join(projectRoot, resolvedConfig.srcDir, bundleConfig.entryPoint);
|
|
37
|
+
const outDir = path.join(projectRoot, globalOutDir, resolvedConfig.outDir);
|
|
50
38
|
// Validate entry point exists
|
|
51
39
|
if (!(await pathExists(entryPath))) {
|
|
52
|
-
logger.warning(`TypeScript entry point not found: ${entryPath}`);
|
|
53
|
-
|
|
54
|
-
return {};
|
|
40
|
+
logger.warning(`TypeScript entry point not found: ${entryPath} (bundle: ${bundleConfig.bundleName})`);
|
|
41
|
+
return null;
|
|
55
42
|
}
|
|
56
|
-
logger.info(''); // Add empty line before TypeScript compilation
|
|
57
|
-
logger.info('Compiling TypeScript...');
|
|
58
43
|
try {
|
|
59
44
|
const result = await esbuild.build({
|
|
60
45
|
entryPoints: [entryPath],
|
|
61
46
|
bundle: true,
|
|
62
47
|
outdir: outDir,
|
|
63
|
-
entryNames:
|
|
64
|
-
|
|
65
|
-
|
|
48
|
+
entryNames: resolvedConfig.hash
|
|
49
|
+
? `${bundleConfig.bundleName}-[hash]`
|
|
50
|
+
: bundleConfig.bundleName,
|
|
51
|
+
minify: resolvedConfig.minify,
|
|
52
|
+
sourcemap: resolvedConfig.sourceMaps,
|
|
66
53
|
target: 'es2022',
|
|
67
54
|
format: 'esm',
|
|
68
55
|
platform: 'browser',
|
|
69
56
|
logLevel: 'silent',
|
|
70
57
|
metafile: true,
|
|
71
58
|
});
|
|
72
|
-
// Extract the generated filename for
|
|
59
|
+
// Extract the generated filename for this bundle
|
|
73
60
|
const outputs = Object.keys(result.metafile?.outputs ?? {});
|
|
74
61
|
const bundleFile = outputs.find((f) => f.endsWith('.js'));
|
|
75
|
-
const bundleFilename = bundleFile ? path.basename(bundleFile) : `${
|
|
76
|
-
|
|
77
|
-
|
|
62
|
+
const bundleFilename = bundleFile ? path.basename(bundleFile) : `${bundleConfig.bundleName}.js`;
|
|
63
|
+
// Construct the path relative to site root
|
|
64
|
+
const bundlePath = path.posix.join('/', resolvedConfig.outDir, bundleFilename);
|
|
65
|
+
return {
|
|
66
|
+
config: bundleConfig,
|
|
67
|
+
filename: bundleFilename,
|
|
68
|
+
path: bundlePath,
|
|
69
|
+
};
|
|
78
70
|
}
|
|
79
71
|
catch (error) {
|
|
80
72
|
if (error instanceof Error) {
|
|
81
|
-
logger.error(`
|
|
73
|
+
logger.error(`Bundle '${bundleConfig.bundleName}' compilation failed: ${error.message}`);
|
|
82
74
|
}
|
|
83
75
|
throw error;
|
|
84
76
|
}
|
|
85
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Compile TypeScript files using esbuild.
|
|
80
|
+
* Supports multiple bundles with parallel compilation.
|
|
81
|
+
*
|
|
82
|
+
* @param options - Compilation options
|
|
83
|
+
* @returns Array of compilation results for each bundle
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const results = await compileTypeScript({
|
|
88
|
+
* projectRoot: process.cwd(),
|
|
89
|
+
* config: {
|
|
90
|
+
* enabled: true,
|
|
91
|
+
* bundles: [
|
|
92
|
+
* { entryPoint: 'core.ts', bundleName: 'core' },
|
|
93
|
+
* { entryPoint: 'docs.ts', bundleName: 'docs', include: ['/docs/**'] }
|
|
94
|
+
* ]
|
|
95
|
+
* },
|
|
96
|
+
* mode: 'production',
|
|
97
|
+
* logger: console,
|
|
98
|
+
* });
|
|
99
|
+
* console.log(results[0].bundlePath); // '/_assets/core-a1b2c3d4.js'
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export async function compileTypeScript(options) {
|
|
103
|
+
const { projectRoot, config, mode, logger, outDir: globalOutDir } = options;
|
|
104
|
+
const resolved = resolveConfig(config, mode);
|
|
105
|
+
const outputDir = globalOutDir || DEFAULT_OUT_DIR;
|
|
106
|
+
// Handle empty bundles array
|
|
107
|
+
if (resolved.bundles.length === 0) {
|
|
108
|
+
logger.warning('TypeScript is enabled but no bundles are configured. Add bundles to your stati.config.ts or disable TypeScript.');
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
// Validate unique bundle names early - fail fast with clear error message
|
|
112
|
+
validateUniqueBundleNames(resolved.bundles);
|
|
113
|
+
logger.info('');
|
|
114
|
+
logger.info(`Compiling TypeScript (${resolved.bundles.length} bundle${resolved.bundles.length > 1 ? 's' : ''})...`);
|
|
115
|
+
// Compile all bundles in parallel
|
|
116
|
+
const compilationPromises = resolved.bundles.map((bundleConfig) => compileSingleBundle(bundleConfig, resolved, projectRoot, outputDir, logger));
|
|
117
|
+
const results = await Promise.all(compilationPromises);
|
|
118
|
+
// Filter out null results (skipped bundles) and collect successful ones
|
|
119
|
+
const successfulResults = results.filter((r) => r !== null);
|
|
120
|
+
if (successfulResults.length > 0) {
|
|
121
|
+
const bundleNames = successfulResults.map((r) => r.filename).join(', ');
|
|
122
|
+
logger.success(`TypeScript compiled: ${bundleNames}`);
|
|
123
|
+
}
|
|
124
|
+
else if (resolved.bundles.length > 0) {
|
|
125
|
+
logger.warning('No TypeScript bundles were compiled (all entry points missing).');
|
|
126
|
+
}
|
|
127
|
+
return successfulResults;
|
|
128
|
+
}
|
|
86
129
|
/**
|
|
87
130
|
* Create an esbuild watch context for development.
|
|
88
131
|
* Watches for TypeScript file changes and recompiles automatically.
|
|
132
|
+
* Supports multiple bundles with selective recompilation.
|
|
89
133
|
*
|
|
90
134
|
* @param options - Watch options including rebuild callback
|
|
91
|
-
* @returns
|
|
135
|
+
* @returns Array of esbuild build contexts for cleanup
|
|
92
136
|
*
|
|
93
137
|
* @example
|
|
94
138
|
* ```typescript
|
|
95
|
-
* const
|
|
139
|
+
* const watchers = await createTypeScriptWatcher({
|
|
96
140
|
* projectRoot: process.cwd(),
|
|
97
141
|
* config: { enabled: true },
|
|
98
|
-
* mode: 'development',
|
|
99
142
|
* logger: console,
|
|
100
|
-
* onRebuild: () => console.log(
|
|
143
|
+
* onRebuild: (results, compileTimeMs) => console.log(`Rebuilt ${results.length} bundles in ${compileTimeMs}ms`),
|
|
101
144
|
* });
|
|
102
145
|
*
|
|
103
146
|
* // Later, cleanup:
|
|
104
|
-
* await
|
|
147
|
+
* await Promise.all(watchers.map(w => w.dispose()));
|
|
105
148
|
* ```
|
|
106
149
|
*/
|
|
107
150
|
export async function createTypeScriptWatcher(options) {
|
|
108
|
-
const { projectRoot, config,
|
|
109
|
-
const resolved = resolveConfig(config,
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
151
|
+
const { projectRoot, config, logger, onRebuild, outDir: globalOutDir } = options;
|
|
152
|
+
const resolved = resolveConfig(config, 'development');
|
|
153
|
+
const outputDir = globalOutDir || DEFAULT_OUT_DIR;
|
|
154
|
+
const outDir = path.join(projectRoot, outputDir, resolved.outDir);
|
|
155
|
+
const contexts = [];
|
|
156
|
+
const latestResults = new Map();
|
|
157
|
+
for (const bundleConfig of resolved.bundles) {
|
|
158
|
+
const entryPath = path.join(projectRoot, resolved.srcDir, bundleConfig.entryPoint);
|
|
159
|
+
// Validate entry point exists
|
|
160
|
+
if (!(await pathExists(entryPath))) {
|
|
161
|
+
logger.warning(`TypeScript entry point not found: ${entryPath} (bundle: ${bundleConfig.bundleName})`);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const context = await esbuild.context({
|
|
165
|
+
entryPoints: [entryPath],
|
|
166
|
+
bundle: true,
|
|
167
|
+
outdir: outDir,
|
|
168
|
+
entryNames: bundleConfig.bundleName, // Stable filename in dev mode (no hash)
|
|
169
|
+
minify: false, // Dev mode: never minify for fast rebuilds
|
|
170
|
+
sourcemap: true, // Dev mode: always enable for debugging
|
|
171
|
+
target: 'es2022',
|
|
172
|
+
format: 'esm',
|
|
173
|
+
platform: 'browser',
|
|
174
|
+
logLevel: 'silent',
|
|
175
|
+
metafile: true,
|
|
176
|
+
plugins: [
|
|
177
|
+
{
|
|
178
|
+
name: 'stati-rebuild-notify',
|
|
179
|
+
setup(build) {
|
|
180
|
+
let startTime;
|
|
181
|
+
build.onStart(() => {
|
|
182
|
+
startTime = Date.now();
|
|
183
|
+
});
|
|
184
|
+
build.onEnd((result) => {
|
|
185
|
+
const compileTime = Date.now() - startTime;
|
|
186
|
+
if (result.errors.length > 0) {
|
|
187
|
+
result.errors.forEach((err) => {
|
|
188
|
+
logger.error(`TypeScript error in '${bundleConfig.bundleName}': ${err.text}`);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Extract the generated filename
|
|
193
|
+
const outputs = Object.keys(result.metafile?.outputs ?? {});
|
|
194
|
+
const bundleFile = outputs.find((f) => f.endsWith('.js'));
|
|
195
|
+
const bundleFilename = bundleFile
|
|
196
|
+
? path.basename(bundleFile)
|
|
197
|
+
: `${bundleConfig.bundleName}.js`;
|
|
198
|
+
const bundlePath = path.posix.join('/', resolved.outDir, bundleFilename);
|
|
199
|
+
const bundleResult = {
|
|
200
|
+
config: bundleConfig,
|
|
201
|
+
filename: bundleFilename,
|
|
202
|
+
path: bundlePath,
|
|
203
|
+
};
|
|
204
|
+
latestResults.set(bundleConfig.bundleName, bundleResult);
|
|
205
|
+
logger.info(`TypeScript '${bundleConfig.bundleName}' recompiled.`);
|
|
206
|
+
// Notify with all current results and compile time
|
|
207
|
+
onRebuild(Array.from(latestResults.values()), compileTime);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
},
|
|
149
211
|
},
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
212
|
+
],
|
|
213
|
+
});
|
|
214
|
+
// Start watching
|
|
215
|
+
await context.watch();
|
|
216
|
+
contexts.push(context);
|
|
217
|
+
}
|
|
218
|
+
if (contexts.length > 0) {
|
|
219
|
+
logger.info(`Watching TypeScript files in ${resolved.srcDir}/ (${contexts.length} bundle${contexts.length > 1 ? 's' : ''})`);
|
|
220
|
+
}
|
|
221
|
+
return contexts;
|
|
157
222
|
}
|
|
158
223
|
/**
|
|
159
224
|
* Compile stati.config.ts to a temporary JS file for import.
|
|
@@ -198,38 +263,86 @@ export async function cleanupCompiledConfig(compiledPath) {
|
|
|
198
263
|
}
|
|
199
264
|
}
|
|
200
265
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
266
|
+
* Validates a bundle path for safety against XSS attacks.
|
|
267
|
+
* Only allows safe ASCII characters: alphanumeric, hyphens, underscores, dots, and forward slashes.
|
|
268
|
+
* Must start with / and end with .js, no encoded characters or unicode allowed.
|
|
269
|
+
*
|
|
270
|
+
* @param bundlePath - The bundle path to validate
|
|
271
|
+
* @returns true if the path is safe, false otherwise
|
|
272
|
+
*
|
|
273
|
+
* @internal
|
|
274
|
+
*/
|
|
275
|
+
export function isValidBundlePath(bundlePath) {
|
|
276
|
+
// Reject non-string or empty paths
|
|
277
|
+
if (typeof bundlePath !== 'string' || bundlePath.length === 0) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
// Reject paths with null bytes (can bypass security checks)
|
|
281
|
+
if (bundlePath.includes('\0')) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
// Reject paths with control characters or non-ASCII characters
|
|
285
|
+
// Check that all characters are in printable ASCII range (32-126)
|
|
286
|
+
for (let i = 0; i < bundlePath.length; i++) {
|
|
287
|
+
const charCode = bundlePath.charCodeAt(i);
|
|
288
|
+
if (charCode < 32 || charCode > 126) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// Reject URL-encoded characters (e.g., %20, %3C) and unicode escapes (e.g., \u003C)
|
|
293
|
+
if (/%[0-9a-fA-F]{2}/.test(bundlePath) || /\\u[0-9a-fA-F]{4}/.test(bundlePath)) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
// Reject HTML entities (e.g., < < <)
|
|
297
|
+
if (/&#?[a-zA-Z0-9]+;/.test(bundlePath)) {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
// Reject path traversal attempts
|
|
301
|
+
if (bundlePath.includes('..') || bundlePath.includes('//')) {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
// Validate against strict safe pattern
|
|
305
|
+
const safePathPattern = /^\/[a-zA-Z0-9_\-./]+\.js$/;
|
|
306
|
+
return safePathPattern.test(bundlePath);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Checks if a bundle script tag is already present in the HTML.
|
|
310
|
+
*
|
|
311
|
+
* @param html - The HTML content to check
|
|
312
|
+
* @param bundlePath - The bundle path to look for
|
|
313
|
+
* @returns true if the bundle is already included, false otherwise
|
|
314
|
+
*
|
|
315
|
+
* @internal
|
|
316
|
+
*/
|
|
317
|
+
function isBundleAlreadyIncluded(html, bundlePath) {
|
|
318
|
+
const escapedPath = bundlePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
319
|
+
const scriptTagPattern = new RegExp(`<script[^>]*\\ssrc=["']${escapedPath}["'][^>]*>`, 'i');
|
|
320
|
+
return scriptTagPattern.test(html);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Auto-inject TypeScript bundle script tags into HTML before </body>.
|
|
324
|
+
* Similar to SEO auto-injection, this adds script tags automatically
|
|
203
325
|
* so users don't need to modify their templates.
|
|
326
|
+
* Supports multiple bundles - injects all matched bundles in order.
|
|
204
327
|
*
|
|
205
328
|
* @param html - Rendered HTML content
|
|
206
|
-
* @param
|
|
207
|
-
* @returns HTML with injected script
|
|
329
|
+
* @param bundlePaths - Array of paths to compiled bundles (e.g., ['/_assets/core.js', '/_assets/docs.js'])
|
|
330
|
+
* @returns HTML with injected script tags
|
|
208
331
|
*
|
|
209
332
|
* @example
|
|
210
333
|
* ```typescript
|
|
211
334
|
* const html = '<html><body>Content</body></html>';
|
|
212
|
-
* const enhanced =
|
|
213
|
-
* // Returns
|
|
335
|
+
* const enhanced = autoInjectBundles(html, ['/_assets/core.js', '/_assets/docs.js']);
|
|
336
|
+
* // Returns HTML with both script tags injected before </body>
|
|
214
337
|
* ```
|
|
215
338
|
*/
|
|
216
|
-
export function
|
|
217
|
-
if (!
|
|
218
|
-
return html;
|
|
219
|
-
}
|
|
220
|
-
// Sanitize bundlePath to prevent XSS attacks
|
|
221
|
-
// Only allow safe characters: alphanumeric, hyphens, underscores, dots, and forward slashes
|
|
222
|
-
// Must start with / and end with .js
|
|
223
|
-
const safePathPattern = /^\/[\w\-./]+\.js$/;
|
|
224
|
-
if (!safePathPattern.test(bundlePath)) {
|
|
225
|
-
// Invalid path format, skip injection to prevent potential XSS
|
|
339
|
+
export function autoInjectBundles(html, bundlePaths) {
|
|
340
|
+
if (!bundlePaths || bundlePaths.length === 0) {
|
|
226
341
|
return html;
|
|
227
342
|
}
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const scriptTagPattern = new RegExp(`<script[^>]*\\ssrc=["']${bundlePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}["'][^>]*>`, 'i');
|
|
232
|
-
if (scriptTagPattern.test(html)) {
|
|
343
|
+
// Filter paths: must be valid and not already included in HTML
|
|
344
|
+
const validPaths = bundlePaths.filter((bundlePath) => isValidBundlePath(bundlePath) && !isBundleAlreadyIncluded(html, bundlePath));
|
|
345
|
+
if (validPaths.length === 0) {
|
|
233
346
|
return html;
|
|
234
347
|
}
|
|
235
348
|
// Find </body> tag (case-insensitive)
|
|
@@ -240,7 +353,9 @@ export function autoInjectBundle(html, bundlePath) {
|
|
|
240
353
|
const bodyClosePos = bodyCloseMatch.index;
|
|
241
354
|
const before = html.substring(0, bodyClosePos);
|
|
242
355
|
const after = html.substring(bodyClosePos);
|
|
243
|
-
// Inject script
|
|
244
|
-
const
|
|
245
|
-
|
|
356
|
+
// Inject all script tags before </body>
|
|
357
|
+
const scriptTags = validPaths
|
|
358
|
+
.map((bundlePath) => `<script type="module" src="${bundlePath}"></script>`)
|
|
359
|
+
.join('\n');
|
|
360
|
+
return `${before}${scriptTags}\n${after}`;
|
|
246
361
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* await build({ clean: true });
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
|
-
export type { StatiConfig, PageModel, FrontMatter, BuildContext, PageContext, BuildHooks, NavNode, ISGConfig, AgingRule, BuildStats, } from './types/index.js';
|
|
22
|
+
export type { StatiConfig, PageModel, FrontMatter, BuildContext, PageContext, BuildHooks, NavNode, ISGConfig, AgingRule, BuildStats, BundleConfig, } 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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,YAAY,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,YAAY,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,UAAU,EACV,YAAY,GACb,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,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,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,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAG1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAE7D"}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -111,6 +111,56 @@ export interface SEOConfig {
|
|
|
111
111
|
/** Enable debug logging for SEO generation (default: false) */
|
|
112
112
|
debug?: boolean;
|
|
113
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Configuration for a single TypeScript bundle.
|
|
116
|
+
* Defines how a bundle is compiled and which pages should include it.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* // Global bundle (included on all pages)
|
|
121
|
+
* const coreBundle: BundleConfig = {
|
|
122
|
+
* entryPoint: 'core.ts',
|
|
123
|
+
* bundleName: 'core'
|
|
124
|
+
* };
|
|
125
|
+
*
|
|
126
|
+
* // Targeted bundle (only on specific pages)
|
|
127
|
+
* const docsBundle: BundleConfig = {
|
|
128
|
+
* entryPoint: 'docs.ts',
|
|
129
|
+
* bundleName: 'docs',
|
|
130
|
+
* include: ['/docs/**', '/api/**'],
|
|
131
|
+
* exclude: ['/docs/legacy/**']
|
|
132
|
+
* };
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export interface BundleConfig {
|
|
136
|
+
/**
|
|
137
|
+
* Entry point file name relative to srcDir.
|
|
138
|
+
* @example 'main.ts', 'features/playground.ts'
|
|
139
|
+
*/
|
|
140
|
+
entryPoint: string;
|
|
141
|
+
/**
|
|
142
|
+
* Output bundle file name (without extension).
|
|
143
|
+
* Final filename includes hash in production: `[bundleName]-[hash].js`
|
|
144
|
+
*/
|
|
145
|
+
bundleName: string;
|
|
146
|
+
/**
|
|
147
|
+
* Glob patterns for pages that should include this bundle.
|
|
148
|
+
* Matches against page output path (e.g., '/docs/api/hooks.html').
|
|
149
|
+
* If omitted, bundle is included on ALL pages (global bundle).
|
|
150
|
+
*
|
|
151
|
+
* Supports glob syntax: `*`, `**`, `?`, `[abc]`, `{a,b}`
|
|
152
|
+
*
|
|
153
|
+
* @example ['/docs/**', '/api/**']
|
|
154
|
+
*/
|
|
155
|
+
include?: string[];
|
|
156
|
+
/**
|
|
157
|
+
* Glob patterns for pages to exclude from this bundle.
|
|
158
|
+
* Takes precedence over include patterns.
|
|
159
|
+
*
|
|
160
|
+
* @example ['/docs/legacy/**']
|
|
161
|
+
*/
|
|
162
|
+
exclude?: string[];
|
|
163
|
+
}
|
|
114
164
|
/**
|
|
115
165
|
* TypeScript compilation configuration.
|
|
116
166
|
* Controls how Stati compiles TypeScript files using esbuild.
|
|
@@ -120,15 +170,23 @@ export interface SEOConfig {
|
|
|
120
170
|
*
|
|
121
171
|
* @example
|
|
122
172
|
* ```typescript
|
|
123
|
-
*
|
|
173
|
+
* // Simple configuration (defaults to single global bundle)
|
|
174
|
+
* const simpleConfig: StatiConfig = {
|
|
175
|
+
* typescript: {
|
|
176
|
+
* enabled: true
|
|
177
|
+
* // Defaults to: bundles: [{ entryPoint: 'main.ts', bundleName: 'main' }]
|
|
178
|
+
* }
|
|
179
|
+
* };
|
|
180
|
+
*
|
|
181
|
+
* // Multiple bundles with per-page targeting
|
|
182
|
+
* const multiConfig: StatiConfig = {
|
|
124
183
|
* typescript: {
|
|
125
184
|
* enabled: true,
|
|
126
185
|
* srcDir: 'src',
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* // set to false only if you need to debug production builds
|
|
186
|
+
* bundles: [
|
|
187
|
+
* { entryPoint: 'core.ts', bundleName: 'core' },
|
|
188
|
+
* { entryPoint: 'docs.ts', bundleName: 'docs', include: ['/docs/**'] }
|
|
189
|
+
* ]
|
|
132
190
|
* }
|
|
133
191
|
* };
|
|
134
192
|
* ```
|
|
@@ -151,17 +209,6 @@ export interface TypeScriptConfig {
|
|
|
151
209
|
* @default '_assets'
|
|
152
210
|
*/
|
|
153
211
|
outDir?: string;
|
|
154
|
-
/**
|
|
155
|
-
* Entry point file name (without path).
|
|
156
|
-
* @default 'main.ts'
|
|
157
|
-
*/
|
|
158
|
-
entryPoint?: string;
|
|
159
|
-
/**
|
|
160
|
-
* Output bundle file name (without extension).
|
|
161
|
-
* The final filename will include a content hash: `[bundleName]-[hash].js`
|
|
162
|
-
* @default 'bundle'
|
|
163
|
-
*/
|
|
164
|
-
bundleName?: string;
|
|
165
212
|
/**
|
|
166
213
|
* Include content hash in bundle filename for cache busting in production.
|
|
167
214
|
* When true, outputs `bundle-a1b2c3d4.js`. When false, outputs `bundle.js`.
|
|
@@ -175,6 +222,25 @@ export interface TypeScriptConfig {
|
|
|
175
222
|
* @default true
|
|
176
223
|
*/
|
|
177
224
|
minify?: boolean;
|
|
225
|
+
/**
|
|
226
|
+
* Array of bundle configurations.
|
|
227
|
+
* Each bundle can target specific pages using include/exclude patterns.
|
|
228
|
+
* If omitted, defaults to a single global bundle:
|
|
229
|
+
* `[{ entryPoint: 'main.ts', bundleName: 'main' }]`
|
|
230
|
+
*
|
|
231
|
+
* When defined, completely overrides the default.
|
|
232
|
+
*/
|
|
233
|
+
bundles?: BundleConfig[];
|
|
234
|
+
/**
|
|
235
|
+
* Automatically inject bundle script tags before </body>.
|
|
236
|
+
* When enabled (default), Stati automatically adds script tags for matched bundles.
|
|
237
|
+
* Disable if you want manual control over script placement in templates.
|
|
238
|
+
*
|
|
239
|
+
* When disabled, use `stati.assets.bundlePaths` in templates to access bundle paths.
|
|
240
|
+
*
|
|
241
|
+
* @default true
|
|
242
|
+
*/
|
|
243
|
+
autoInject?: boolean;
|
|
178
244
|
}
|
|
179
245
|
/**
|
|
180
246
|
* Robots.txt generation configuration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;GAEG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,wCAAwC;IACxC,QAAQ,CAAC,EAAE;QACT,oGAAoG;QACpG,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;QACzC,oDAAoD;QACpD,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,UAAU,KAAK,IAAI,CAAC;KACtC,CAAC;IACF,wCAAwC;IACxC,GAAG,CAAC,EAAE;QACJ,8BAA8B;QAC9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC;KACnD,CAAC;IACF,kDAAkD;IAClD,GAAG,CAAC,EAAE,OAAO,UAAU,EAAE,SAAS,CAAC;IACnC,wBAAwB;IACxB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,uCAAuC;IACvC,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,wCAAwC;IACxC,GAAG,CAAC,EAAE,OAAO,UAAU,EAAE,SAAS,CAAC;IACnC,sCAAsC;IACtC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,uCAAuC;IACvC,GAAG,CAAC,EAAE;QACJ,kDAAkD;QAClD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,yDAAyD;QACzD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,6DAA6D;QAC7D,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,mCAAmC;IACnC,OAAO,CAAC,EAAE;QACR,8CAA8C;QAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,qDAAqD;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,6DAA6D;QAC7D,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,4BAA4B;IAC5B,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,gEAAgE;IAChE,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"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"}
|
package/dist/types/content.d.ts
CHANGED
|
@@ -4,18 +4,24 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* TypeScript bundle asset information.
|
|
6
6
|
* Available when TypeScript compilation is enabled.
|
|
7
|
+
* Contains paths to all bundles matched for the current page.
|
|
7
8
|
*
|
|
8
9
|
* @example
|
|
9
10
|
* ```typescript
|
|
10
11
|
* // In Eta templates, access via stati.assets
|
|
11
|
-
*
|
|
12
|
+
* // Auto-injection handles most cases, but manual control is available:
|
|
13
|
+
* <% for (const path of stati.assets.bundlePaths) { %>
|
|
14
|
+
* <script type="module" src="<%= path %>"></script>
|
|
15
|
+
* <% } %>
|
|
12
16
|
* ```
|
|
13
17
|
*/
|
|
14
18
|
export interface StatiAssets {
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Array of all bundle paths matched for this page.
|
|
21
|
+
* Paths are in config order: ['/_assets/core-abc.js', '/_assets/docs-def.js']
|
|
22
|
+
* Always an array, empty [] if no TypeScript enabled or no bundles match.
|
|
23
|
+
*/
|
|
24
|
+
bundlePaths: string[];
|
|
19
25
|
}
|
|
20
26
|
/**
|
|
21
27
|
* Front matter metadata extracted from content files.
|