portapack 0.3.1 → 0.3.3

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 (74) hide show
  1. package/.eslintrc.json +67 -8
  2. package/.releaserc.js +25 -27
  3. package/CHANGELOG.md +14 -22
  4. package/LICENSE.md +21 -0
  5. package/README.md +22 -53
  6. package/commitlint.config.js +30 -34
  7. package/dist/cli/cli-entry.cjs +183 -98
  8. package/dist/cli/cli-entry.cjs.map +1 -1
  9. package/dist/index.d.ts +0 -3
  10. package/dist/index.js +178 -97
  11. package/dist/index.js.map +1 -1
  12. package/docs/.vitepress/config.ts +38 -33
  13. package/docs/.vitepress/sidebar-generator.ts +89 -38
  14. package/docs/architecture.md +186 -0
  15. package/docs/cli.md +23 -23
  16. package/docs/code-of-conduct.md +7 -1
  17. package/docs/configuration.md +12 -11
  18. package/docs/contributing.md +6 -2
  19. package/docs/deployment.md +10 -5
  20. package/docs/development.md +8 -5
  21. package/docs/getting-started.md +13 -13
  22. package/docs/index.md +1 -1
  23. package/docs/public/android-chrome-192x192.png +0 -0
  24. package/docs/public/android-chrome-512x512.png +0 -0
  25. package/docs/public/apple-touch-icon.png +0 -0
  26. package/docs/public/favicon-16x16.png +0 -0
  27. package/docs/public/favicon-32x32.png +0 -0
  28. package/docs/public/favicon.ico +0 -0
  29. package/docs/roadmap.md +233 -0
  30. package/docs/site.webmanifest +1 -0
  31. package/docs/troubleshooting.md +12 -1
  32. package/examples/main.ts +5 -30
  33. package/examples/sample-project/script.js +1 -1
  34. package/jest.config.ts +8 -13
  35. package/nodemon.json +5 -10
  36. package/package.json +2 -5
  37. package/src/cli/cli-entry.ts +2 -2
  38. package/src/cli/cli.ts +21 -16
  39. package/src/cli/options.ts +127 -113
  40. package/src/core/bundler.ts +253 -222
  41. package/src/core/extractor.ts +632 -565
  42. package/src/core/minifier.ts +173 -162
  43. package/src/core/packer.ts +141 -137
  44. package/src/core/parser.ts +74 -73
  45. package/src/core/web-fetcher.ts +270 -258
  46. package/src/index.ts +18 -17
  47. package/src/types.ts +9 -11
  48. package/src/utils/font.ts +12 -6
  49. package/src/utils/logger.ts +110 -105
  50. package/src/utils/meta.ts +75 -76
  51. package/src/utils/mime.ts +50 -50
  52. package/src/utils/slugify.ts +33 -34
  53. package/tests/unit/cli/cli-entry.test.ts +72 -70
  54. package/tests/unit/cli/cli.test.ts +314 -278
  55. package/tests/unit/cli/options.test.ts +294 -301
  56. package/tests/unit/core/bundler.test.ts +426 -329
  57. package/tests/unit/core/extractor.test.ts +793 -549
  58. package/tests/unit/core/minifier.test.ts +374 -274
  59. package/tests/unit/core/packer.test.ts +298 -264
  60. package/tests/unit/core/parser.test.ts +538 -150
  61. package/tests/unit/core/web-fetcher.test.ts +389 -359
  62. package/tests/unit/index.test.ts +238 -197
  63. package/tests/unit/utils/font.test.ts +26 -21
  64. package/tests/unit/utils/logger.test.ts +267 -260
  65. package/tests/unit/utils/meta.test.ts +29 -28
  66. package/tests/unit/utils/mime.test.ts +73 -74
  67. package/tests/unit/utils/slugify.test.ts +14 -12
  68. package/tsconfig.build.json +9 -10
  69. package/tsconfig.jest.json +1 -1
  70. package/tsconfig.json +2 -2
  71. package/tsup.config.ts +8 -9
  72. package/typedoc.json +5 -9
  73. /package/docs/{portapack-transparent.png → public/portapack-transparent.png} +0 -0
  74. /package/docs/{portapack.jpg → public/portapack.jpg} +0 -0
package/src/types.ts CHANGED
@@ -18,7 +18,7 @@
18
18
  */
19
19
  export interface Asset {
20
20
  type: 'css' | 'js' | 'image' | 'font' | 'video' | 'audio' | 'other'; // Add video and audio
21
-
21
+
22
22
  /** The resolved or original URL of the asset */
23
23
  url: string;
24
24
 
@@ -94,17 +94,16 @@ export interface BundleOptions {
94
94
  // --- LogLevel Enum ---
95
95
  // Defines available log levels as a numeric enum for comparisons.
96
96
  export enum LogLevel {
97
- NONE = 0, // No logging (equivalent to 'silent')
98
- ERROR = 1, // Only errors
99
- WARN = 2, // Errors and warnings
100
- INFO = 3, // Errors, warnings, and info (Default)
101
- DEBUG = 4 // All messages (Verbose)
97
+ NONE = 0, // No logging (equivalent to 'silent')
98
+ ERROR = 1, // Only errors
99
+ WARN = 2, // Errors and warnings
100
+ INFO = 3, // Errors, warnings, and info (Default)
101
+ DEBUG = 4, // All messages (Verbose)
102
102
  }
103
103
 
104
104
  // --- String Literal Type for LogLevel Names (Optional, useful for CLI parsing) ---
105
105
  export type LogLevelName = 'debug' | 'info' | 'warn' | 'error' | 'silent' | 'none';
106
106
 
107
-
108
107
  /**
109
108
  * Summary statistics and metadata returned after the packing/bundling process completes.
110
109
  */
@@ -138,14 +137,13 @@ export interface BuildResult {
138
137
  metadata: BundleMetadata;
139
138
  }
140
139
 
141
-
142
140
  /** CLI-specific options extending BundleOptions. */
143
141
  export interface CLIOptions extends BundleOptions {
144
142
  /** Input file or URL (positional). */
145
143
  input?: string;
146
144
  /** Max depth for recursive crawling (numeric alias for recursive). */
147
- maxDepth?: number; // Used by commander, then merged into 'recursive'
148
- minify?: boolean; // Minify assets (defaults to true)
145
+ maxDepth?: number; // Used by commander, then merged into 'recursive'
146
+ minify?: boolean; // Minify assets (defaults to true)
149
147
  }
150
148
 
151
149
  /**
@@ -160,4 +158,4 @@ export interface CLIResult {
160
158
 
161
159
  /** Final exit code intended for the process (0 for success, non-zero for errors) */
162
160
  exitCode: number;
163
- }
161
+ }
package/src/utils/font.ts CHANGED
@@ -16,12 +16,18 @@ export function getFontMimeType(fontUrl: string): string {
16
16
  const ext = path.extname(fontUrl).toLowerCase().replace('.', '');
17
17
 
18
18
  switch (ext) {
19
- case 'woff': return 'font/woff';
20
- case 'woff2': return 'font/woff2';
21
- case 'ttf': return 'font/ttf';
22
- case 'otf': return 'font/otf';
23
- case 'eot': return 'application/vnd.ms-fontobject';
24
- default: return 'application/octet-stream';
19
+ case 'woff':
20
+ return 'font/woff';
21
+ case 'woff2':
22
+ return 'font/woff2';
23
+ case 'ttf':
24
+ return 'font/ttf';
25
+ case 'otf':
26
+ return 'font/otf';
27
+ case 'eot':
28
+ return 'application/vnd.ms-fontobject';
29
+ default:
30
+ return 'application/octet-stream';
25
31
  }
26
32
  }
27
33
 
@@ -4,7 +4,6 @@
4
4
  * to control output verbosity throughout the application (core, API, CLI).
5
5
  */
6
6
 
7
- // FIX: Use a regular import for the enum, not 'import type'
8
7
  import { LogLevel } from '../types';
9
8
  // Assuming LogLevel enum is defined and exported in '../types' like:
10
9
  // export enum LogLevel { NONE = 0, ERROR = 1, WARN = 2, INFO = 3, DEBUG = 4 }
@@ -14,7 +13,7 @@ import { LogLevel } from '../types';
14
13
  * (Note: Currently constructor only accepts LogLevel directly)
15
14
  */
16
15
  export interface LoggerOptions {
17
- level?: LogLevel;
16
+ level?: LogLevel;
18
17
  }
19
18
 
20
19
  /**
@@ -22,118 +21,124 @@ export interface LoggerOptions {
22
21
  * Uses standard console methods (debug, info, warn, error) for output.
23
22
  */
24
23
  export class Logger {
25
- /** The current minimum log level required for a message to be output. */
26
- public level: LogLevel;
24
+ /** The current minimum log level required for a message to be output. */
25
+ public level: LogLevel;
27
26
 
28
- /**
29
- * Creates a new Logger instance.
30
- * Defaults to LogLevel.INFO if no level is provided.
31
- *
32
- * @param {LogLevel} [level=LogLevel.INFO] - The initial log level for this logger instance.
33
- * Must be one of the values from the LogLevel enum.
34
- */
35
- constructor(level: LogLevel = LogLevel.INFO) { // Defaulting to INFO level using the enum value
36
- // Ensure a valid LogLevel enum member is provided or default correctly
37
- this.level = (level !== undefined && LogLevel[level] !== undefined)
38
- ? level
39
- : LogLevel.INFO; // Use the enum value for default
40
- }
27
+ /**
28
+ * Creates a new Logger instance.
29
+ * Defaults to LogLevel.INFO if no level is provided.
30
+ *
31
+ * @param {LogLevel} [level=LogLevel.INFO] - The initial log level for this logger instance.
32
+ * Must be one of the values from the LogLevel enum.
33
+ */
34
+ constructor(level: LogLevel = LogLevel.INFO) {
35
+ // Defaulting to INFO level using the enum value
36
+ // Ensure a valid LogLevel enum member is provided or default correctly
37
+ this.level = level !== undefined && LogLevel[level] !== undefined ? level : LogLevel.INFO; // Use the enum value for default
38
+ }
41
39
 
42
- /**
43
- * Updates the logger's current level. Messages below this level will be suppressed.
44
- *
45
- * @param {LogLevel} level - The new log level to set. Must be a LogLevel enum member.
46
- */
47
- setLevel(level: LogLevel): void {
48
- this.level = level;
49
- }
40
+ /**
41
+ * Updates the logger's current level. Messages below this level will be suppressed.
42
+ *
43
+ * @param {LogLevel} level - The new log level to set. Must be a LogLevel enum member.
44
+ */
45
+ setLevel(level: LogLevel): void {
46
+ this.level = level;
47
+ }
50
48
 
51
- /**
52
- * Logs a debug message if the current log level is DEBUG or higher.
53
- *
54
- * @param {string} message - The debug message string.
55
- */
56
- debug(message: string): void {
57
- // Use enum member for comparison
58
- if (this.level >= LogLevel.DEBUG) {
59
- console.debug(`[DEBUG] ${message}`);
60
- }
49
+ /**
50
+ * Logs a debug message if the current log level is DEBUG or higher.
51
+ *
52
+ * @param {string} message - The debug message string.
53
+ */
54
+ debug(message: string): void {
55
+ // Use enum member for comparison
56
+ if (this.level >= LogLevel.DEBUG) {
57
+ console.debug(`[DEBUG] ${message}`);
61
58
  }
59
+ }
62
60
 
63
- /**
64
- * Logs an informational message if the current log level is INFO or higher.
65
- *
66
- * @param {string} message - The informational message string.
67
- */
68
- info(message: string): void {
69
- // Use enum member for comparison
70
- if (this.level >= LogLevel.INFO) {
71
- console.info(`[INFO] ${message}`);
72
- }
61
+ /**
62
+ * Logs an informational message if the current log level is INFO or higher.
63
+ *
64
+ * @param {string} message - The informational message string.
65
+ */
66
+ info(message: string): void {
67
+ // Use enum member for comparison
68
+ if (this.level >= LogLevel.INFO) {
69
+ console.info(`[INFO] ${message}`);
73
70
  }
71
+ }
74
72
 
75
- /**
76
- * Logs a warning message if the current log level is WARN or higher.
77
- *
78
- * @param {string} message - The warning message string.
79
- */
80
- warn(message: string): void {
81
- // Use enum member for comparison
82
- if (this.level >= LogLevel.WARN) {
83
- console.warn(`[WARN] ${message}`);
84
- }
73
+ /**
74
+ * Logs a warning message if the current log level is WARN or higher.
75
+ *
76
+ * @param {string} message - The warning message string.
77
+ */
78
+ warn(message: string): void {
79
+ // Use enum member for comparison
80
+ if (this.level >= LogLevel.WARN) {
81
+ console.warn(`[WARN] ${message}`);
85
82
  }
83
+ }
86
84
 
87
- /**
88
- * Logs an error message if the current log level is ERROR or higher.
89
- *
90
- * @param {string} message - The error message string.
91
- */
92
- error(message: string): void {
93
- // Use enum member for comparison
94
- if (this.level >= LogLevel.ERROR) {
95
- console.error(`[ERROR] ${message}`);
96
- }
85
+ /**
86
+ * Logs an error message if the current log level is ERROR or higher.
87
+ *
88
+ * @param {string} message - The error message string.
89
+ */
90
+ error(message: string): void {
91
+ // Use enum member for comparison
92
+ if (this.level >= LogLevel.ERROR) {
93
+ console.error(`[ERROR] ${message}`);
97
94
  }
95
+ }
98
96
 
99
- /**
100
- * Static factory method to create a Logger instance based on a simple boolean `verbose` flag.
101
- *
102
- * @static
103
- * @param {{ verbose?: boolean }} [options={}] - An object potentially containing a `verbose` flag.
104
- * @returns {Logger} A new Logger instance set to LogLevel.DEBUG if options.verbose is true,
105
- * otherwise set to LogLevel.INFO.
106
- */
107
- static fromVerboseFlag(options: { verbose?: boolean } = {}): Logger {
108
- // Use enum members for assignment
109
- return new Logger(options.verbose ? LogLevel.DEBUG : LogLevel.INFO);
110
- }
97
+ /**
98
+ * Static factory method to create a Logger instance based on a simple boolean `verbose` flag.
99
+ *
100
+ * @static
101
+ * @param {{ verbose?: boolean }} [options={}] - An object potentially containing a `verbose` flag.
102
+ * @returns {Logger} A new Logger instance set to LogLevel.DEBUG if options.verbose is true,
103
+ * otherwise set to LogLevel.INFO.
104
+ */
105
+ static fromVerboseFlag(options: { verbose?: boolean } = {}): Logger {
106
+ // Use enum members for assignment
107
+ return new Logger(options.verbose ? LogLevel.DEBUG : LogLevel.INFO);
108
+ }
111
109
 
112
- /**
113
- * Static factory method to create a Logger instance based on a LogLevel string name.
114
- * Useful for creating a logger from config files or environments variables.
115
- *
116
- * @static
117
- * @param {string | undefined} levelName - The name of the log level (e.g., 'debug', 'info', 'warn', 'error', 'silent'/'none'). Case-insensitive.
118
- * @param {LogLevel} [defaultLevel=LogLevel.INFO] - The level to use if levelName is invalid or undefined.
119
- * @returns {Logger} A new Logger instance set to the corresponding LogLevel.
120
- */
121
- static fromLevelName(levelName?: string, defaultLevel: LogLevel = LogLevel.INFO): Logger {
122
- if (!levelName) {
123
- return new Logger(defaultLevel);
124
- }
125
- switch (levelName.toLowerCase()) {
126
- // Return enum members
127
- case 'debug': return new Logger(LogLevel.DEBUG);
128
- case 'info': return new Logger(LogLevel.INFO);
129
- case 'warn': return new Logger(LogLevel.WARN);
130
- case 'error': return new Logger(LogLevel.ERROR);
131
- case 'silent':
132
- case 'none': return new Logger(LogLevel.NONE);
133
- default:
134
- // Use console.warn directly here as logger might not be ready
135
- console.warn(`[Logger] Invalid log level name "${levelName}". Defaulting to ${LogLevel[defaultLevel]}.`);
136
- return new Logger(defaultLevel);
137
- }
138
- }
139
- }
110
+ /**
111
+ * Static factory method to create a Logger instance based on a LogLevel string name.
112
+ * Useful for creating a logger from config files or environments variables.
113
+ *
114
+ * @static
115
+ * @param {string | undefined} levelName - The name of the log level (e.g., 'debug', 'info', 'warn', 'error', 'silent'/'none'). Case-insensitive.
116
+ * @param {LogLevel} [defaultLevel=LogLevel.INFO] - The level to use if levelName is invalid or undefined.
117
+ * @returns {Logger} A new Logger instance set to the corresponding LogLevel.
118
+ */
119
+ static fromLevelName(levelName?: string, defaultLevel: LogLevel = LogLevel.INFO): Logger {
120
+ if (!levelName) {
121
+ return new Logger(defaultLevel);
122
+ }
123
+ switch (levelName.toLowerCase()) {
124
+ // Return enum members
125
+ case 'debug':
126
+ return new Logger(LogLevel.DEBUG);
127
+ case 'info':
128
+ return new Logger(LogLevel.INFO);
129
+ case 'warn':
130
+ return new Logger(LogLevel.WARN);
131
+ case 'error':
132
+ return new Logger(LogLevel.ERROR);
133
+ case 'silent':
134
+ case 'none':
135
+ return new Logger(LogLevel.NONE);
136
+ default:
137
+ // Use console.warn directly here as logger might not be ready
138
+ console.warn(
139
+ `[Logger] Invalid log level name "${levelName}". Defaulting to ${LogLevel[defaultLevel]}.`
140
+ );
141
+ return new Logger(defaultLevel);
142
+ }
143
+ }
144
+ }
package/src/utils/meta.ts CHANGED
@@ -12,89 +12,88 @@ import type { BundleMetadata } from '../types'; // Assuming types are in ../type
12
12
  * (asset counts, page counts, errors) during the HTML bundling process.
13
13
  */
14
14
  export class BuildTimer {
15
- private startTime: number;
16
- private input: string;
17
- private pagesBundled?: number; // Tracks pages for recursive bundles
18
- private assetCount: number = 0; // Tracks discovered/processed assets
19
- private errors: string[] = []; // Collects warnings/errors
15
+ private startTime: number;
16
+ private input: string;
17
+ private pagesBundled?: number; // Tracks pages for recursive bundles
18
+ private assetCount: number = 0; // Tracks discovered/processed assets
19
+ private errors: string[] = []; // Collects warnings/errors
20
20
 
21
- /**
22
- * Creates and starts a build timer session for a given input.
23
- *
24
- * @param {string} input - The source file path or URL being processed.
25
- */
26
- constructor(input: string) {
27
- this.startTime = Date.now();
28
- this.input = input;
29
- }
21
+ /**
22
+ * Creates and starts a build timer session for a given input.
23
+ *
24
+ * @param {string} input - The source file path or URL being processed.
25
+ */
26
+ constructor(input: string) {
27
+ this.startTime = Date.now();
28
+ this.input = input;
29
+ }
30
30
 
31
- /**
32
- * Explicitly sets the number of assets discovered or processed.
33
- * This might be called after asset extraction/minification.
34
- *
35
- * @param {number} count - The total number of assets.
36
- */
37
- setAssetCount(count: number): void {
38
- this.assetCount = count;
39
- }
31
+ /**
32
+ * Explicitly sets the number of assets discovered or processed.
33
+ * This might be called after asset extraction/minification.
34
+ *
35
+ * @param {number} count - The total number of assets.
36
+ */
37
+ setAssetCount(count: number): void {
38
+ this.assetCount = count;
39
+ }
40
40
 
41
- /**
42
- * Records a warning or error message encountered during the build.
43
- * These are added to the final metadata.
44
- *
45
- * @param {string} message - The warning or error description.
46
- */
47
- addError(message: string): void {
48
- this.errors.push(message);
49
- }
41
+ /**
42
+ * Records a warning or error message encountered during the build.
43
+ * These are added to the final metadata.
44
+ *
45
+ * @param {string} message - The warning or error description.
46
+ */
47
+ addError(message: string): void {
48
+ this.errors.push(message);
49
+ }
50
50
 
51
- /**
52
- * Sets the number of pages bundled, typically used in multi-page
53
- * or recursive bundling scenarios.
54
- *
55
- * @param {number} count - The number of HTML pages included in the bundle.
56
- */
57
- setPageCount(count: number): void {
58
- this.pagesBundled = count;
59
- }
51
+ /**
52
+ * Sets the number of pages bundled, typically used in multi-page
53
+ * or recursive bundling scenarios.
54
+ *
55
+ * @param {number} count - The number of HTML pages included in the bundle.
56
+ */
57
+ setPageCount(count: number): void {
58
+ this.pagesBundled = count;
59
+ }
60
60
 
61
- /**
62
- * Stops the timer, calculates final metrics, and returns the complete
63
- * BundleMetadata object. Merges any explicitly provided metadata
64
- * (like assetCount calculated elsewhere) with the timer's tracked data.
65
- *
66
- * @param {string} finalHtml - The final generated HTML string, used to calculate output size.
67
- * @param {Partial<BundleMetadata>} [extra] - Optional object containing metadata fields
68
- * (like assetCount or pre-calculated errors) that should override the timer's internal values.
69
- * @returns {BundleMetadata} The finalized metadata object for the build process.
70
- */
71
- finish(html: string, extra?: Partial<BundleMetadata>): BundleMetadata {
72
- const buildTimeMs = Date.now() - this.startTime;
73
- const outputSize = Buffer.byteLength(html || '', 'utf-8');
61
+ /**
62
+ * Stops the timer, calculates final metrics, and returns the complete
63
+ * BundleMetadata object. Merges any explicitly provided metadata
64
+ * (like assetCount calculated elsewhere) with the timer's tracked data.
65
+ *
66
+ * @param {string} finalHtml - The final generated HTML string, used to calculate output size.
67
+ * @param {Partial<BundleMetadata>} [extra] - Optional object containing metadata fields
68
+ * (like assetCount or pre-calculated errors) that should override the timer's internal values.
69
+ * @returns {BundleMetadata} The finalized metadata object for the build process.
70
+ */
71
+ finish(html: string, extra?: Partial<BundleMetadata>): BundleMetadata {
72
+ const buildTimeMs = Date.now() - this.startTime;
73
+ const outputSize = Buffer.byteLength(html || '', 'utf-8');
74
74
 
75
- // Combine internal errors with any errors passed in 'extra', avoiding duplicates
76
- // FIX: Ensure extra.errors is treated as an empty array if undefined/null
77
- const combinedErrors = Array.from(new Set([...this.errors, ...(extra?.errors ?? [])]));
75
+ // Combine internal errors with any errors passed in 'extra', avoiding duplicates
76
+ const combinedErrors = Array.from(new Set([...this.errors, ...(extra?.errors ?? [])]));
78
77
 
79
- const finalMetadata: BundleMetadata = {
80
- input: this.input,
81
- outputSize,
82
- buildTimeMs,
83
- assetCount: extra?.assetCount ?? this.assetCount,
84
- pagesBundled: extra?.pagesBundled ?? this.pagesBundled,
85
- // Assign the combined errors array
86
- errors: combinedErrors,
87
- };
78
+ const finalMetadata: BundleMetadata = {
79
+ input: this.input,
80
+ outputSize,
81
+ buildTimeMs,
82
+ assetCount: extra?.assetCount ?? this.assetCount,
83
+ pagesBundled: extra?.pagesBundled ?? this.pagesBundled,
84
+ // Assign the combined errors array
85
+ errors: combinedErrors,
86
+ };
88
87
 
89
- // Clean up optional fields if they weren't set/provided or are empty
90
- if (finalMetadata.pagesBundled === undefined) {
91
- delete finalMetadata.pagesBundled;
92
- }
93
- // Delete errors only if the *combined* array is empty
94
- if (finalMetadata.errors?.length === 0) {
95
- delete finalMetadata.errors;
96
- }
88
+ // Clean up optional fields if they weren't set/provided or are empty
89
+ if (finalMetadata.pagesBundled === undefined) {
90
+ delete finalMetadata.pagesBundled;
91
+ }
92
+ // Delete errors only if the *combined* array is empty
93
+ if (finalMetadata.errors?.length === 0) {
94
+ delete finalMetadata.errors;
95
+ }
97
96
 
98
- return finalMetadata;
97
+ return finalMetadata;
99
98
  }
100
- }
99
+ }
package/src/utils/mime.ts CHANGED
@@ -10,46 +10,46 @@ import type { Asset } from '../types'; // Assuming types are in ../types
10
10
  * Maps common file extensions to their corresponding MIME types and general Asset types.
11
11
  */
12
12
  const MIME_MAP: Record<string, { mime: string; assetType: Asset['type'] }> = {
13
- // CSS
14
- '.css': { mime: 'text/css', assetType: 'css' },
15
- // JavaScript
16
- '.js': { mime: 'application/javascript', assetType: 'js' },
17
- '.mjs': { mime: 'application/javascript', assetType: 'js' },
18
- // Images
19
- '.png': { mime: 'image/png', assetType: 'image' },
20
- '.jpg': { mime: 'image/jpeg', assetType: 'image' },
21
- '.jpeg': { mime: 'image/jpeg', assetType: 'image' },
22
- '.gif': { mime: 'image/gif', assetType: 'image' },
23
- '.svg': { mime: 'image/svg+xml', assetType: 'image' },
24
- '.webp': { mime: 'image/webp', assetType: 'image' },
25
- '.ico': { mime: 'image/x-icon', assetType: 'image' },
26
- '.avif': { mime: 'image/avif', assetType: 'image' },
27
- // Fonts
28
- '.woff': { mime: 'font/woff', assetType: 'font' },
29
- '.woff2': { mime: 'font/woff2', assetType: 'font' },
30
- '.ttf': { mime: 'font/ttf', assetType: 'font' },
31
- '.otf': { mime: 'font/otf', assetType: 'font' },
32
- '.eot': { mime: 'application/vnd.ms-fontobject', assetType: 'font' },
33
- // Audio/Video (add more as needed)
34
- '.mp3': { mime: 'audio/mpeg', assetType: 'other' },
35
- '.ogg': { mime: 'audio/ogg', assetType: 'other' },
36
- '.wav': { mime: 'audio/wav', assetType: 'other' },
37
- '.mp4': { mime: 'video/mp4', assetType: 'other' },
38
- '.webm': { mime: 'video/webm', assetType: 'other' },
39
- // Other common web types
40
- '.json': { mime: 'application/json', assetType: 'other' },
41
- '.webmanifest': { mime: 'application/manifest+json', assetType: 'other' },
42
- '.xml': { mime: 'application/xml', assetType: 'other' },
43
- '.html': { mime: 'text/html', assetType: 'other' }, // Usually not needed as asset, but for completeness
44
- '.txt': { mime: 'text/plain', assetType: 'other' },
13
+ // CSS
14
+ '.css': { mime: 'text/css', assetType: 'css' },
15
+ // JavaScript
16
+ '.js': { mime: 'application/javascript', assetType: 'js' },
17
+ '.mjs': { mime: 'application/javascript', assetType: 'js' },
18
+ // Images
19
+ '.png': { mime: 'image/png', assetType: 'image' },
20
+ '.jpg': { mime: 'image/jpeg', assetType: 'image' },
21
+ '.jpeg': { mime: 'image/jpeg', assetType: 'image' },
22
+ '.gif': { mime: 'image/gif', assetType: 'image' },
23
+ '.svg': { mime: 'image/svg+xml', assetType: 'image' },
24
+ '.webp': { mime: 'image/webp', assetType: 'image' },
25
+ '.ico': { mime: 'image/x-icon', assetType: 'image' },
26
+ '.avif': { mime: 'image/avif', assetType: 'image' },
27
+ // Fonts
28
+ '.woff': { mime: 'font/woff', assetType: 'font' },
29
+ '.woff2': { mime: 'font/woff2', assetType: 'font' },
30
+ '.ttf': { mime: 'font/ttf', assetType: 'font' },
31
+ '.otf': { mime: 'font/otf', assetType: 'font' },
32
+ '.eot': { mime: 'application/vnd.ms-fontobject', assetType: 'font' },
33
+ // Audio/Video (add more as needed)
34
+ '.mp3': { mime: 'audio/mpeg', assetType: 'other' },
35
+ '.ogg': { mime: 'audio/ogg', assetType: 'other' },
36
+ '.wav': { mime: 'audio/wav', assetType: 'other' },
37
+ '.mp4': { mime: 'video/mp4', assetType: 'other' },
38
+ '.webm': { mime: 'video/webm', assetType: 'other' },
39
+ // Other common web types
40
+ '.json': { mime: 'application/json', assetType: 'other' },
41
+ '.webmanifest': { mime: 'application/manifest+json', assetType: 'other' },
42
+ '.xml': { mime: 'application/xml', assetType: 'other' },
43
+ '.html': { mime: 'text/html', assetType: 'other' }, // Usually not needed as asset, but for completeness
44
+ '.txt': { mime: 'text/plain', assetType: 'other' },
45
45
  };
46
46
 
47
47
  /**
48
48
  * Default MIME type and Asset type for unknown file extensions.
49
49
  */
50
50
  const DEFAULT_MIME_TYPE = {
51
- mime: 'application/octet-stream',
52
- assetType: 'other' as Asset['type'] // Explicit cast needed
51
+ mime: 'application/octet-stream',
52
+ assetType: 'other' as Asset['type'], // Explicit cast needed
53
53
  };
54
54
 
55
55
  /**
@@ -61,21 +61,21 @@ const DEFAULT_MIME_TYPE = {
61
61
  * if the extension is unknown.
62
62
  */
63
63
  export function guessMimeType(urlOrPath: string): { mime: string; assetType: Asset['type'] } {
64
- if (!urlOrPath) {
65
- return DEFAULT_MIME_TYPE;
66
- }
67
- // Extract the extension, handling potential query parameters or fragments
68
- let ext = '';
69
- try {
70
- // Use URL parsing first to handle URLs correctly
71
- const parsedUrl = new URL(urlOrPath);
72
- ext = path.extname(parsedUrl.pathname).toLowerCase();
73
- } catch {
74
- // If it's not a valid URL, treat it as a path
75
- ext = path.extname(urlOrPath).toLowerCase();
76
- }
64
+ if (!urlOrPath) {
65
+ return DEFAULT_MIME_TYPE;
66
+ }
67
+ // Extract the extension, handling potential query parameters or fragments
68
+ let ext = '';
69
+ try {
70
+ // Use URL parsing first to handle URLs correctly
71
+ const parsedUrl = new URL(urlOrPath);
72
+ ext = path.extname(parsedUrl.pathname).toLowerCase();
73
+ } catch {
74
+ // If it's not a valid URL, treat it as a path
75
+ ext = path.extname(urlOrPath).toLowerCase();
76
+ }
77
77
 
78
- return MIME_MAP[ext] || DEFAULT_MIME_TYPE;
78
+ return MIME_MAP[ext] || DEFAULT_MIME_TYPE;
79
79
  }
80
80
 
81
81
  /**
@@ -86,5 +86,5 @@ export function guessMimeType(urlOrPath: string): { mime: string; assetType: Ass
86
86
  * @returns {string} The corresponding font MIME type or a default.
87
87
  */
88
88
  export function getFontMimeType(fontUrl: string): string {
89
- return guessMimeType(fontUrl).mime; // Delegate to the main function
90
- }
89
+ return guessMimeType(fontUrl).mime; // Delegate to the main function
90
+ }