@staticbolt/core 1.0.0-beta.11 → 1.0.0-beta.13

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.
@@ -1,13 +1,15 @@
1
- import { _ as CUSTOM_ATTRIBUTES, t as Log } from "./logger-BfIn1ytK.mjs";
2
- import { NodeType } from "@staticbolt/node-html-parser";
1
+ import { c as isAbsolute, f as normalize, g as replaceExtension, n as CUSTOM_ATTRIBUTES, o as dirname, r as Log, s as extname, u as join } from "./common-Bkh8-tjA.mjs";
2
+ import { existsSync, readFileSync, statSync } from "node:fs";
3
+ import { ResolverFactory } from "oxc-resolver";
3
4
  import c from "chalk";
5
+ import json5 from "json5";
6
+ import { readFile } from "node:fs/promises";
7
+ import { NodeType } from "@staticbolt/node-html-parser";
4
8
  import { Node as Node$1 } from "postcss";
5
9
  import _generator from "@babel/generator";
6
10
  import _traverse from "@babel/traverse";
7
11
  import boxen from "boxen";
8
12
  import { common, createEmphasize } from "emphasize";
9
- import { readFileSync } from "node:fs";
10
- import { readFile } from "node:fs/promises";
11
13
  import { createHash } from "node:crypto";
12
14
 
13
15
  //#region src/helpers/dependency-tracker.ts
@@ -51,6 +53,304 @@ var DependencyTracker = class {
51
53
  }
52
54
  };
53
55
 
56
+ //#endregion
57
+ //#region src/utilities/html-links.ts
58
+ /**
59
+ * Checks if the link is an HTML link (not a file link)
60
+ *
61
+ * @param source - The link
62
+ * @returns
63
+ */
64
+ function isHtmlLink(source) {
65
+ return /^(?:#|https?|mailto:|tel:|url\(|ftp:|data:|javascript:)/i.test(source);
66
+ }
67
+ function isValidRelativePath(source) {
68
+ if (!source) return false;
69
+ if (isAbsolute(source)) return false;
70
+ if (isHtmlLink(source)) return false;
71
+ return true;
72
+ }
73
+ function splitHtmlLink(url) {
74
+ const qIndex = url.indexOf("?");
75
+ const hIndex = url.indexOf("#");
76
+ let delimIndex = -1;
77
+ if (qIndex !== -1 && hIndex !== -1) delimIndex = Math.min(qIndex, hIndex);
78
+ else if (qIndex !== -1) delimIndex = qIndex;
79
+ else if (hIndex !== -1) delimIndex = hIndex;
80
+ if (delimIndex !== -1) {
81
+ const pathEnd = url[delimIndex - 1] === "/" ? delimIndex - 1 : delimIndex;
82
+ return [url.slice(0, pathEnd), url.slice(pathEnd)];
83
+ }
84
+ if (url.endsWith("/")) {
85
+ if (url === "/" || url === "./") return [url, ""];
86
+ return [url.slice(0, -1), "/"];
87
+ }
88
+ return [url, ""];
89
+ }
90
+
91
+ //#endregion
92
+ //#region src/utilities/value-or-error.ts
93
+ function errorsWrapper(function_) {
94
+ return (...arguments_) => {
95
+ try {
96
+ const promiseOrValue = function_(...arguments_);
97
+ if (isPromise(promiseOrValue)) return new Promise((resolve) => {
98
+ promiseOrValue.then((value) => {
99
+ resolve([value, null]);
100
+ }).catch((error) => {
101
+ resolve(handleError(error, function_.name));
102
+ });
103
+ });
104
+ return [promiseOrValue, null];
105
+ } catch (error) {
106
+ return handleError(error, function_.name);
107
+ }
108
+ };
109
+ }
110
+ function isPromise(value) {
111
+ return value && typeof value === "object" && "then" in value && typeof value.then === "function" && "catch" in value && typeof value.catch === "function";
112
+ }
113
+ function handleError(error, functionName = "") {
114
+ if (!error) return [null, /* @__PURE__ */ new Error(`[${functionName}] Unexpected error`)];
115
+ if (typeof error === "string") return [null, new Error(error)];
116
+ if (error instanceof Error) return [null, error];
117
+ if (typeof error === "object" && "message" in error && typeof error.message === "string") return [null, new Error(error.message)];
118
+ return [null, /* @__PURE__ */ new Error(`[${functionName}] Unexpected error`)];
119
+ }
120
+ const valueOrError = errorsWrapper;
121
+
122
+ //#endregion
123
+ //#region src/utilities/read-file.ts
124
+ async function safeReadFile(path, options) {
125
+ try {
126
+ return [await readFile(path, options), null];
127
+ } catch (error) {
128
+ return handleError(error, "readFile");
129
+ }
130
+ }
131
+ function safeReadFileSync(path, options) {
132
+ try {
133
+ return [readFileSync(path, options), null];
134
+ } catch (error) {
135
+ return handleError(error, "readFileSync");
136
+ }
137
+ }
138
+
139
+ //#endregion
140
+ //#region src/utilities/read-json-file.ts
141
+ /** Read a file and parse it as JSON safely. */
142
+ function readJsonFile(path, code) {
143
+ if (!code) {
144
+ const [fileString, readError] = safeReadFileSync(path, "utf8");
145
+ if (readError) return [null, readError];
146
+ code = fileString;
147
+ }
148
+ const [parsed, parseError] = valueOrError(json5.parse)(code);
149
+ if (parseError !== null) return [null, parseError];
150
+ return [parsed, null];
151
+ }
152
+
153
+ //#endregion
154
+ //#region src/resolver/get-aliases.ts
155
+ /** Gets path aliases from `tsconfig.json` */
156
+ function getPathAliases(root) {
157
+ const [tsconfig, tsconfigParseError] = readTsconfig(root);
158
+ if (tsconfigParseError !== null) return [null, tsconfigParseError];
159
+ const paths = tsconfig.paths ?? {};
160
+ const alias = {};
161
+ for (const key in paths) {
162
+ const aliasName = key.replace(/\*$/, "");
163
+ alias[aliasName] = paths[key][0].replace(/\*$/, "");
164
+ }
165
+ return [alias, null];
166
+ }
167
+ function readTsconfig(root) {
168
+ const [tsconfig, tsconfigParseError] = readJsonFile(join(root, "tsconfig.json"));
169
+ if (tsconfigParseError !== null) return [null, tsconfigParseError];
170
+ if (!tsconfig.compilerOptions) return [null, /* @__PURE__ */ new Error("[readTsconfig] No compilerOptions found in tsconfig.json")];
171
+ return [tsconfig.compilerOptions, null];
172
+ }
173
+
174
+ //#endregion
175
+ //#region src/resolver/resolver.ts
176
+ const nodeModulesResolver = new ResolverFactory({
177
+ conditionNames: [
178
+ "browser",
179
+ "import",
180
+ "default"
181
+ ],
182
+ extensions: [
183
+ ".js",
184
+ ".json",
185
+ ".node",
186
+ ".css"
187
+ ],
188
+ symlinks: false
189
+ });
190
+ var Resolver = class Resolver {
191
+ root;
192
+ aliases = {};
193
+ notFound = /* @__PURE__ */ new Set();
194
+ files = /* @__PURE__ */ new Set();
195
+ directories = /* @__PURE__ */ new Set();
196
+ static JS_EXTENSIONS = new Set([
197
+ ".js",
198
+ ".mjs",
199
+ ".cjs",
200
+ ".jsx",
201
+ ".ts",
202
+ ".mts",
203
+ ".cts",
204
+ ".tsx"
205
+ ]);
206
+ static HTML_EXTENSIONS = new Set([".html", ".md"]);
207
+ constructor(root) {
208
+ this.root = root;
209
+ const [aliases] = getPathAliases(root);
210
+ if (aliases) this.aliases = aliases;
211
+ }
212
+ resolve(sourceOrLink, filePath) {
213
+ if (!isValidRelativePath(sourceOrLink)) return;
214
+ const absFilePath = isAbsolute(filePath) ? filePath : join(this.root, filePath);
215
+ const [source, suffix] = splitHtmlLink(sourceOrLink);
216
+ if (isAbsolute(source)) return;
217
+ const checkDirectory = suffix === "/";
218
+ const absSource = join(dirname(absFilePath), source);
219
+ const foundFile = this.findFile(absSource, checkDirectory);
220
+ if (foundFile) return {
221
+ path: foundFile,
222
+ exists: true,
223
+ suffix
224
+ };
225
+ const sourceForAlias = suffix === "/" ? source + "/" : source;
226
+ const resolvedPathAlias = Resolver.resolvePathAlias(sourceForAlias, this.aliases);
227
+ if (resolvedPathAlias) {
228
+ const absSource = join(this.root, resolvedPathAlias);
229
+ const foundFile = this.findFile(absSource, checkDirectory);
230
+ const isFileAlias = sourceForAlias in this.aliases && !sourceForAlias.endsWith("/");
231
+ if (!foundFile && !this.notFound.has(absSource.replace(/\/$/, ""))) {
232
+ this.notFound.add(absSource.replace(/\/$/, ""));
233
+ Log.warn(`[resolver] Source "${sourceOrLink}" found in "${filePath}" was resolved to "${resolvedPathAlias}", but the file is missing.`);
234
+ }
235
+ return {
236
+ path: foundFile ?? absSource,
237
+ exists: !!foundFile,
238
+ suffix,
239
+ isFileAlias,
240
+ isDirAlias: !isFileAlias
241
+ };
242
+ }
243
+ if (!source.startsWith(".")) {
244
+ const resolverResult = nodeModulesResolver.sync(this.root, source);
245
+ if (resolverResult.path) return {
246
+ path: resolverResult.path,
247
+ suffix,
248
+ exists: true,
249
+ isPackage: true
250
+ };
251
+ }
252
+ if (source.startsWith("./") || source.startsWith("../")) {
253
+ if (!this.notFound.has(absSource)) {
254
+ this.notFound.add(absSource);
255
+ Log.warn(`[resolver] Source "${sourceOrLink}" found in "${filePath}" points to a non-existent file.`);
256
+ }
257
+ return {
258
+ path: absSource,
259
+ suffix,
260
+ exists: false
261
+ };
262
+ }
263
+ }
264
+ resolveAlias(source) {
265
+ return Resolver.resolvePathAlias(source, this.aliases);
266
+ }
267
+ normalize(filePath) {
268
+ return normalize(filePath);
269
+ }
270
+ static isFile(filePath) {
271
+ try {
272
+ return statSync(filePath).isFile();
273
+ } catch (error) {
274
+ const code = error.code;
275
+ if (code === "ENOENT" || code === "ENOTDIR") return false;
276
+ throw error;
277
+ }
278
+ }
279
+ /** Aliased path to path */
280
+ static resolvePathAlias(filePath, aliases) {
281
+ for (const [key, value] of Object.entries(aliases)) {
282
+ if (key.endsWith("/")) {
283
+ if (!filePath.startsWith(key)) continue;
284
+ return filePath.replace(key, value);
285
+ }
286
+ if (filePath === key) return value;
287
+ }
288
+ }
289
+ /** Path to aliased path */
290
+ static resolveAliasPath(filePath, aliases) {
291
+ let shortest;
292
+ for (const [key, value] of Object.entries(aliases)) {
293
+ if (key.endsWith("/")) {
294
+ if (!filePath.startsWith(value)) continue;
295
+ const aliased = filePath.replace(value, key);
296
+ if (!shortest || aliased.length < shortest.length) shortest = aliased;
297
+ continue;
298
+ }
299
+ if (filePath === value && (!shortest || key.length < shortest.length)) shortest = key;
300
+ }
301
+ return shortest ?? filePath;
302
+ }
303
+ /** Path to aliased path */
304
+ aliasPath(filePath) {
305
+ return Resolver.resolveAliasPath(filePath, this.aliases);
306
+ }
307
+ findFile(filePath, checkDirectory = false) {
308
+ if (this.files.has(filePath)) return filePath;
309
+ if (Resolver.isFile(filePath)) {
310
+ this.files.add(filePath);
311
+ return filePath;
312
+ }
313
+ const extension = extname(filePath);
314
+ if (!extension) {
315
+ for (const candidateExtension of [...Resolver.JS_EXTENSIONS, ...Resolver.HTML_EXTENSIONS]) {
316
+ const candidate = replaceExtension(filePath, candidateExtension);
317
+ if (this.files.has(candidate)) return candidate;
318
+ if (Resolver.isFile(candidate)) {
319
+ this.files.add(candidate);
320
+ return candidate;
321
+ }
322
+ }
323
+ const withIndex = join(filePath, "index");
324
+ for (const candidateExtension of Resolver.HTML_EXTENSIONS) {
325
+ const candidate = replaceExtension(withIndex, candidateExtension);
326
+ if (this.files.has(candidate)) return candidate;
327
+ if (Resolver.isFile(candidate)) {
328
+ this.files.add(candidate);
329
+ return candidate;
330
+ }
331
+ }
332
+ if (checkDirectory) {
333
+ if (this.directories.has(filePath)) return filePath;
334
+ if (existsSync(filePath)) {
335
+ this.directories.add(filePath);
336
+ return filePath;
337
+ }
338
+ }
339
+ return;
340
+ }
341
+ if (Resolver.JS_EXTENSIONS.has(extension)) {
342
+ for (const jsExtension of Resolver.JS_EXTENSIONS) {
343
+ const candidate = replaceExtension(filePath, jsExtension);
344
+ if (Resolver.isFile(candidate)) {
345
+ this.files.add(candidate);
346
+ return candidate;
347
+ }
348
+ }
349
+ return;
350
+ }
351
+ }
352
+ };
353
+
54
354
  //#endregion
55
355
  //#region src/types/metadata.ts
56
356
  const METADATA_TYPES = Object.freeze({
@@ -275,54 +575,6 @@ function nodeToString(node) {
275
575
  };
276
576
  }
277
577
 
278
- //#endregion
279
- //#region src/utilities/value-or-error.ts
280
- function errorsWrapper(function_) {
281
- return (...arguments_) => {
282
- try {
283
- const promiseOrValue = function_(...arguments_);
284
- if (isPromise(promiseOrValue)) return new Promise((resolve) => {
285
- promiseOrValue.then((value) => {
286
- resolve([value, null]);
287
- }).catch((error) => {
288
- resolve(handleError(error, function_.name));
289
- });
290
- });
291
- return [promiseOrValue, null];
292
- } catch (error) {
293
- return handleError(error, function_.name);
294
- }
295
- };
296
- }
297
- function isPromise(value) {
298
- return value && typeof value === "object" && "then" in value && typeof value.then === "function" && "catch" in value && typeof value.catch === "function";
299
- }
300
- function handleError(error, functionName = "") {
301
- if (!error) return [null, /* @__PURE__ */ new Error(`[${functionName}] Unexpected error`)];
302
- if (typeof error === "string") return [null, new Error(error)];
303
- if (error instanceof Error) return [null, error];
304
- if (typeof error === "object" && "message" in error && typeof error.message === "string") return [null, new Error(error.message)];
305
- return [null, /* @__PURE__ */ new Error(`[${functionName}] Unexpected error`)];
306
- }
307
- const valueOrError = errorsWrapper;
308
-
309
- //#endregion
310
- //#region src/utilities/read-file.ts
311
- async function safeReadFile(path, options) {
312
- try {
313
- return [await readFile(path, options), null];
314
- } catch (error) {
315
- return handleError(error, "readFile");
316
- }
317
- }
318
- function safeReadFileSync(path, options) {
319
- try {
320
- return [readFileSync(path, options), null];
321
- } catch (error) {
322
- return handleError(error, "readFileSync");
323
- }
324
- }
325
-
326
578
  //#endregion
327
579
  //#region src/utilities/utilities.ts
328
580
  /** `process.stdout.write` */
@@ -481,5 +733,5 @@ function escapeHtml(input) {
481
733
  }
482
734
 
483
735
  //#endregion
484
- export { isHtmlMetadata as A, DependencyTracker as B, PrintFormattedError as C, filterScriptMetadata as D, traverse as E, isSvgMetadata as F, isTextAssetMetadata as I, isWebManifestMetadata as L, isPackageMetadata as M, isScriptMetadata as N, filterStyleMetadata as O, isStyleMetadata as P, isScriptType as R, valueOrError as S, generator as T, mergeMaps as _, clamp as a, safeReadFileSync as b, downloadContent as c, hashContent as d, humanReadableBytes as f, kebabToCamelCase as g, isURL as h, capitalize as i, isMarkdownMetadata as j, isBinaryAssetMetadata as k, escapeHtml as l, isObject as m, bytesToKB as n, clearLn as o, isDefined as p, camelCaseToKebabCase as r, cloneObject as s, assign as t, getLineColumn as u, print as v, printFmtError as w, handleError as x, safeReadFile as y, METADATA_TYPES as z };
485
- //# sourceMappingURL=utilities-CZmLMi93.mjs.map
736
+ export { isStyleMetadata as A, handleError as B, filterScriptMetadata as C, isMarkdownMetadata as D, isHtmlMetadata as E, METADATA_TYPES as F, isValidRelativePath as H, Resolver as I, readJsonFile as L, isTextAssetMetadata as M, isWebManifestMetadata as N, isPackageMetadata as O, isScriptType as P, safeReadFile as R, traverse as S, isBinaryAssetMetadata as T, splitHtmlLink as U, valueOrError as V, DependencyTracker as W, mergeMaps as _, clamp as a, printFmtError as b, downloadContent as c, hashContent as d, humanReadableBytes as f, kebabToCamelCase as g, isURL as h, capitalize as i, isSvgMetadata as j, isScriptMetadata as k, escapeHtml as l, isObject as m, bytesToKB as n, clearLn as o, isDefined as p, camelCaseToKebabCase as r, cloneObject as s, assign as t, getLineColumn as u, print as v, filterStyleMetadata as w, generator as x, PrintFormattedError as y, safeReadFileSync as z };
737
+ //# sourceMappingURL=utilities-Bu5rdDC9.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utilities-Bu5rdDC9.mjs","names":["#sourcesToImporters","#importerToSources","chalk","PostcssNode"],"sources":["../src/helpers/dependency-tracker.ts","../src/utilities/html-links.ts","../src/utilities/value-or-error.ts","../src/utilities/read-file.ts","../src/utilities/read-json-file.ts","../src/resolver/get-aliases.ts","../src/resolver/resolver.ts","../src/types/metadata.ts","../src/helpers/is-script-type.ts","../src/utilities/metadata-utilities.ts","../src/helpers/babel-fixed-imports.ts","../src/utilities/highlight-code.ts","../src/utilities/print-formatted-error.ts","../src/utilities/utilities.ts"],"sourcesContent":["/**\n * Tracks bidirectional dependencies between importers and their sources.\\\n * Handles reconciliation when dependencies change, so stale entries are automatically removed when an importer stops referencing\n * a source.\n */\nexport class DependencyTracker {\n /** Source → Set of importers that depend on it */\n readonly #sourcesToImporters = new Map<string, Set<string>>();\n\n /** Importer → Set of sources it depends on */\n readonly #importerToSources = new Map<string, Set<string>>();\n\n /** Updates the full set of sources for a given importer, reconciling any stale entries from previous calls. */\n update(importer: string, sources: Iterable<string>): void {\n const nextSources = new Set(sources);\n const previousSources = this.#importerToSources.get(importer) ?? new Set();\n\n // Remove importer from sources it no longer uses\n for (const source of previousSources) {\n if (!nextSources.has(source)) {\n this.#sourcesToImporters.get(source)?.delete(importer);\n }\n }\n\n // Add importer to newly referenced sources\n for (const source of nextSources) {\n if (!this.#sourcesToImporters.has(source)) {\n this.#sourcesToImporters.set(source, new Set());\n }\n\n this.#sourcesToImporters.get(source)!.add(importer);\n }\n\n this.#importerToSources.set(importer, nextSources);\n }\n\n /** Deletes all dependency data for a given id, whether it's acting as an importer, a source, or both (e.g. on file unlink). */\n delete(id: string): void {\n // id was a source — drop it entirely\n this.#sourcesToImporters.delete(id);\n\n // id was an importer — remove it from all sources it referenced\n const sources = this.#importerToSources.get(id);\n if (sources) {\n for (const source of sources) {\n this.#sourcesToImporters.get(source)?.delete(id);\n }\n\n this.#importerToSources.delete(id);\n }\n }\n\n /** Returns all importers that depend on a given source, or an empty set. */\n getImporters(source: string): ReadonlySet<string> {\n return this.#sourcesToImporters.get(source) ?? new Set();\n }\n\n /** Returns all sources that a given importer depends on, or an empty set. */\n getSources(importer: string): ReadonlySet<string> {\n return this.#importerToSources.get(importer) ?? new Set();\n }\n}\n","import { isAbsolute } from \"./path.ts\";\n\n/**\n * Checks if the link is an HTML link (not a file link)\n *\n * @param source - The link\n * @returns\n */\nexport function isHtmlLink(source: string): boolean {\n return /^(?:#|https?|mailto:|tel:|url\\(|ftp:|data:|javascript:)/i.test(source);\n}\n\nexport function isValidRelativePath(source: string): boolean {\n if (!source) return false;\n // if (source.includes(\" \")) return false;\n if (isAbsolute(source)) return false;\n if (isHtmlLink(source)) return false;\n return true;\n}\n\nexport function splitHtmlLink(url: string): [string, string] {\n const qIndex = url.indexOf(\"?\");\n const hIndex = url.indexOf(\"#\");\n\n // Find the earliest query/hash delimiter\n let delimIndex = -1;\n\n if (qIndex !== -1 && hIndex !== -1) {\n delimIndex = Math.min(qIndex, hIndex);\n }\n //\n else if (qIndex !== -1) {\n delimIndex = qIndex;\n }\n //\n else if (hIndex !== -1) {\n delimIndex = hIndex;\n }\n\n if (delimIndex !== -1) {\n // If a '/' immediately precedes the delimiter, include it in the suffix\n const pathEnd = url[delimIndex - 1] === \"/\" ? delimIndex - 1 : delimIndex;\n return [url.slice(0, pathEnd), url.slice(pathEnd)];\n }\n\n // No query or hash — handle trailing slash\n if (url.endsWith(\"/\")) {\n // Bare \"/\" or \"./\" are kept whole\n if (url === \"/\" || url === \"./\") {\n return [url, \"\"];\n }\n\n return [url.slice(0, -1), \"/\"];\n }\n\n return [url, \"\"];\n}\n","export type ValueOrError<T> = [T, null] | [null, Error];\n\nfunction errorsWrapper<T, A extends unknown[]>(function_: (...arguments_: A) => T | Promise<T>) {\n return (...arguments_: A) => {\n try {\n const promiseOrValue = function_(...arguments_);\n if (isPromise<T>(promiseOrValue)) {\n return new Promise(resolve => {\n promiseOrValue\n .then(value => {\n resolve([value, null]);\n })\n .catch((error: unknown) => {\n resolve(handleError(error, function_.name));\n });\n });\n }\n return [promiseOrValue, null];\n } catch (error) {\n return handleError(error, function_.name);\n }\n };\n}\n\nfunction isPromise<T>(value: T | Promise<T>): value is Promise<T> {\n return (\n value &&\n typeof value === \"object\" &&\n \"then\" in value &&\n typeof value.then === \"function\" &&\n \"catch\" in value &&\n typeof value.catch === \"function\"\n );\n}\n\nexport function handleError<T>(error: unknown, functionName = \"\"): ValueOrError<T> {\n if (!error) {\n return [null, new Error(`[${functionName}] Unexpected error`)];\n }\n\n if (typeof error === \"string\") {\n return [null, new Error(error)];\n }\n\n if (error instanceof Error) {\n return [null, error];\n }\n\n // in some cases the error is not an instance of Error but an object\n if (typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\") {\n return [null, new Error(error.message)];\n }\n\n return [null, new Error(`[${functionName}] Unexpected error`)];\n}\n\ninterface goErrorsI {\n <T, A extends unknown[]>(function_: (...arguments_: A) => Promise<T>): (...arguments_: A) => Promise<ValueOrError<T>>;\n <T, A extends unknown[]>(function_: (...arguments_: A) => T): (...arguments_: A) => ValueOrError<T>;\n}\n\nexport const valueOrError = errorsWrapper as unknown as goErrorsI;\n","import type { Abortable } from \"node:events\";\nimport { readFileSync } from \"node:fs\";\nimport type { ObjectEncodingOptions, OpenMode, PathLike, PathOrFileDescriptor } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport type { FileHandle } from \"node:fs/promises\";\n\nimport { handleError } from \"./value-or-error.ts\";\n\nimport type { ValueOrError } from \"./value-or-error.ts\";\n\nexport async function safeReadFile(\n path: PathLike | FileHandle,\n options?:\n | ({\n encoding?: null | undefined;\n flag?: OpenMode | undefined;\n } & Abortable)\n | null\n): Promise<ValueOrError<Buffer>>;\n\nexport async function safeReadFile(\n path: PathLike | FileHandle,\n options:\n | ({\n encoding: BufferEncoding;\n flag?: OpenMode | undefined;\n } & Abortable)\n | BufferEncoding\n): Promise<ValueOrError<string>>;\n\nexport async function safeReadFile(\n path: PathLike | FileHandle,\n options?:\n | (ObjectEncodingOptions &\n Abortable & {\n flag?: OpenMode | undefined;\n })\n | BufferEncoding\n | null\n): Promise<ValueOrError<string | Buffer>>;\n\nexport async function safeReadFile(\n path: PathLike | FileHandle,\n options?:\n | (ObjectEncodingOptions &\n Abortable & {\n flag?: OpenMode | undefined;\n })\n | BufferEncoding\n | null\n): Promise<ValueOrError<string | Buffer>> {\n try {\n const string_ = await readFile(path, options);\n return [string_, null];\n } catch (error) {\n return handleError(error, \"readFile\");\n }\n}\n\nexport function safeReadFileSync(\n path: PathOrFileDescriptor,\n options?: {\n encoding?: null | undefined;\n flag?: string | undefined;\n } | null\n): ValueOrError<NonSharedBuffer>;\n\nexport function safeReadFileSync(\n path: PathOrFileDescriptor,\n options:\n | {\n encoding: BufferEncoding;\n flag?: string | undefined;\n }\n | BufferEncoding\n): ValueOrError<string>;\n\nexport function safeReadFileSync(\n path: PathOrFileDescriptor,\n options?:\n | (ObjectEncodingOptions & {\n flag?: string | undefined;\n })\n | BufferEncoding\n | null\n): ValueOrError<string | NonSharedBuffer>;\n\nexport function safeReadFileSync(\n path: PathOrFileDescriptor,\n options?:\n | (ObjectEncodingOptions & {\n flag?: string | undefined;\n })\n | BufferEncoding\n | null\n): ValueOrError<string | NonSharedBuffer> {\n try {\n const string_ = readFileSync(path, options);\n return [string_, null];\n } catch (error) {\n return handleError(error, \"readFileSync\");\n }\n}\n","import json5 from \"json5\";\n\nimport { safeReadFileSync } from \"./read-file.ts\";\nimport { valueOrError } from \"./value-or-error.ts\";\n\nimport type { ValueOrError } from \"./value-or-error.ts\";\n\n/** Read a file and parse it as JSON safely. */\nexport function readJsonFile<T>(path: string, code?: string): ValueOrError<T> {\n if (!code) {\n const [fileString, readError] = safeReadFileSync(path, \"utf8\");\n if (readError) {\n return [null, readError];\n }\n\n code = fileString;\n }\n\n const [parsed, parseError] = valueOrError(json5.parse<T>)(code);\n if (parseError !== null) {\n return [null, parseError];\n }\n\n return [parsed, null];\n}\n","import { join } from \"../utilities/path.ts\";\nimport { readJsonFile } from \"../utilities/read-json-file.ts\";\n\nimport type { ValueOrError } from \"../utilities/value-or-error.ts\";\nimport type { CompilerOptions } from \"typescript\";\n\n/** Gets path aliases from `tsconfig.json` */\nexport function getPathAliases(root: string): ValueOrError<Record<string, string>> {\n const [tsconfig, tsconfigParseError] = readTsconfig(root);\n if (tsconfigParseError !== null) {\n return [null, tsconfigParseError];\n }\n\n const paths = tsconfig.paths ?? {};\n const alias: Record<string, string> = {};\n\n for (const key in paths) {\n const aliasName = key.replace(/\\*$/, \"\");\n const aliasPath = paths[key][0].replace(/\\*$/, \"\");\n alias[aliasName] = aliasPath;\n }\n\n return [alias, null];\n}\n\nfunction readTsconfig(root: string): ValueOrError<CompilerOptions> {\n const tsconfigPath = join(root, \"tsconfig.json\");\n\n const [tsconfig, tsconfigParseError] = readJsonFile<{ compilerOptions: CompilerOptions }>(tsconfigPath);\n if (tsconfigParseError !== null) {\n return [null, tsconfigParseError];\n }\n\n if (!tsconfig.compilerOptions) {\n return [null, new Error(\"[readTsconfig] No compilerOptions found in tsconfig.json\")];\n }\n\n return [tsconfig.compilerOptions, null];\n}\n","import { existsSync, statSync } from \"node:fs\";\nimport { ResolverFactory } from \"oxc-resolver\";\n\nimport { isValidRelativePath, splitHtmlLink } from \"../utilities/html-links.ts\";\nimport { Log } from \"../utilities/logger.ts\";\nimport { dirname, extname, isAbsolute, join, normalize, replaceExtension } from \"../utilities/path.ts\";\nimport { getPathAliases } from \"./get-aliases.ts\";\n\nconst nodeModulesResolver = new ResolverFactory({\n conditionNames: [\"browser\", \"import\", \"default\"],\n extensions: [\".js\", \".json\", \".node\", \".css\"],\n symlinks: false,\n});\n\ntype ResolveResult = {\n path: string;\n suffix: string;\n isDirAlias?: boolean;\n isFileAlias?: boolean;\n isPackage?: boolean;\n exists: boolean;\n};\n\nexport class Resolver {\n root: string;\n aliases: Record<string, string> = {};\n notFound: Set<string> = new Set();\n files: Set<string> = new Set();\n directories: Set<string> = new Set();\n\n static JS_EXTENSIONS = new Set([\".js\", \".mjs\", \".cjs\", \".jsx\", \".ts\", \".mts\", \".cts\", \".tsx\"]);\n static HTML_EXTENSIONS = new Set([\".html\", \".md\"]);\n\n constructor(root: string) {\n this.root = root;\n\n const [aliases] = getPathAliases(root);\n if (aliases) {\n this.aliases = aliases;\n }\n }\n\n resolve(sourceOrLink: string, filePath: string): ResolveResult | undefined {\n if (!isValidRelativePath(sourceOrLink)) return;\n\n const absFilePath = isAbsolute(filePath) ? filePath : join(this.root, filePath);\n const [source, suffix] = splitHtmlLink(sourceOrLink);\n\n // HTML links can be absolute E.g. /index.html\n if (isAbsolute(source)) {\n return;\n }\n\n const checkDirectory = suffix === \"/\";\n\n // file or directory\n const absSource = join(dirname(absFilePath), source);\n const foundFile = this.findFile(absSource, checkDirectory);\n if (foundFile) {\n return { path: foundFile, exists: true, suffix };\n }\n\n // path alias — restore the stripped trailing slash so \"~/\" aliases match\n const sourceForAlias = suffix === \"/\" ? source + \"/\" : source;\n const resolvedPathAlias = Resolver.resolvePathAlias(sourceForAlias, this.aliases);\n if (resolvedPathAlias) {\n const absSource = join(this.root, resolvedPathAlias);\n const foundFile = this.findFile(absSource, checkDirectory);\n\n const isFileAlias = sourceForAlias in this.aliases && !sourceForAlias.endsWith(\"/\");\n\n // Warn once when a resolved source cannot be found on disk.\n if (!foundFile && !this.notFound.has(absSource.replace(/\\/$/, \"\"))) {\n this.notFound.add(absSource.replace(/\\/$/, \"\"));\n Log.warn(\n `[resolver] Source \"${sourceOrLink}\" found in \"${filePath}\" was resolved to \"${resolvedPathAlias}\", but the file is missing.`\n );\n }\n\n return { path: foundFile ?? absSource, exists: !!foundFile, suffix, isFileAlias, isDirAlias: !isFileAlias };\n }\n\n // node module package\n if (!source.startsWith(\".\")) {\n const resolverResult = nodeModulesResolver.sync(this.root, source);\n if (resolverResult.path) {\n return { path: resolverResult.path, suffix, exists: true, isPackage: true };\n }\n }\n\n // Not found, but its already a file path\n if (source.startsWith(\"./\") || source.startsWith(\"../\")) {\n // Warn once per missing source: it was resolved previously but the file cannot be found anymore.\n if (!this.notFound.has(absSource)) {\n this.notFound.add(absSource);\n Log.warn(`[resolver] Source \"${sourceOrLink}\" found in \"${filePath}\" points to a non-existent file.`);\n }\n\n return { path: absSource, suffix, exists: false };\n }\n }\n\n resolveAlias(source: string): string | undefined {\n return Resolver.resolvePathAlias(source, this.aliases);\n }\n\n normalize(filePath: string): string {\n return normalize(filePath);\n }\n\n static isFile(filePath: string): boolean {\n try {\n return statSync(filePath).isFile();\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return false;\n }\n\n throw error;\n }\n }\n\n /** Aliased path to path */\n static resolvePathAlias(filePath: string, aliases: Record<string, string>): string | undefined {\n for (const [key, value] of Object.entries(aliases)) {\n // directory path alias\n if (key.endsWith(\"/\")) {\n if (!filePath.startsWith(key)) {\n continue;\n }\n\n return filePath.replace(key, value);\n }\n\n // file path alias\n if (filePath === key) {\n return value;\n }\n }\n }\n\n /** Path to aliased path */\n static resolveAliasPath(filePath: string, aliases: Record<string, string>): string {\n let shortest: string | undefined;\n\n for (const [key, value] of Object.entries(aliases)) {\n // directory path alias\n if (key.endsWith(\"/\")) {\n if (!filePath.startsWith(value)) {\n continue;\n }\n\n const aliased = filePath.replace(value, key);\n if (!shortest || aliased.length < shortest.length) {\n shortest = aliased;\n }\n continue;\n }\n\n // file path alias\n if (filePath === value && (!shortest || key.length < shortest.length)) {\n shortest = key;\n }\n }\n\n return shortest ?? filePath;\n }\n\n /** Path to aliased path */\n aliasPath(filePath: string): string {\n return Resolver.resolveAliasPath(filePath, this.aliases);\n }\n\n findFile(filePath: string, checkDirectory = false): string | undefined {\n // From cache\n if (this.files.has(filePath)) {\n return filePath;\n }\n\n // Exact match\n if (Resolver.isFile(filePath)) {\n this.files.add(filePath);\n return filePath;\n }\n\n const extension = extname(filePath);\n\n // No extension\n if (!extension) {\n // it might be a js file, html file, markdown file or just a directory\n for (const candidateExtension of [...Resolver.JS_EXTENSIONS, ...Resolver.HTML_EXTENSIONS]) {\n const candidate = replaceExtension(filePath, candidateExtension);\n\n if (this.files.has(candidate)) {\n return candidate;\n }\n\n if (Resolver.isFile(candidate)) {\n this.files.add(candidate);\n return candidate;\n }\n }\n\n // it might be index.html or index.md\n const withIndex = join(filePath, \"index\");\n\n for (const candidateExtension of Resolver.HTML_EXTENSIONS) {\n const candidate = replaceExtension(withIndex, candidateExtension);\n\n if (this.files.has(candidate)) {\n return candidate;\n }\n\n if (Resolver.isFile(candidate)) {\n this.files.add(candidate);\n return candidate;\n }\n }\n\n // directory\n if (checkDirectory) {\n if (this.directories.has(filePath)) {\n return filePath;\n }\n\n if (existsSync(filePath)) {\n this.directories.add(filePath);\n return filePath;\n }\n }\n\n return;\n }\n\n // main.js does not exist but main{.jsx, .ts, .tsx} may exist\n if (Resolver.JS_EXTENSIONS.has(extension)) {\n for (const jsExtension of Resolver.JS_EXTENSIONS) {\n const candidate = replaceExtension(filePath, jsExtension);\n\n if (Resolver.isFile(candidate)) {\n this.files.add(candidate);\n return candidate;\n }\n }\n\n return;\n }\n }\n}\n","import type { BabelAst, PostcssAst, Document, MarkdownAst } from \"@staticbolt/core\";\nimport type { WebAppManifest } from \"web-app-manifest\";\n\nexport const METADATA_TYPES = Object.freeze({\n Script: \"Script\",\n HTML: \"Html\",\n Markdown: \"Markdown\",\n CSS: \"Style\",\n SVG: \"Svg\",\n Package: \"Package\",\n TextAsset: \"TextAsset\",\n BinaryAsset: \"BinaryAsset\",\n WebAppManifest: \"WebAppManifest\",\n});\n\nexport type MetadataTypes = (typeof METADATA_TYPES)[keyof typeof METADATA_TYPES];\n\nexport interface MetadataBase {\n readonly type: `${Capitalize<string>}${string}`;\n\n /**\n * Relative path of the source file.\n *\n * Initially identical to `originalSource` when the metadata is created. During the build process, this value may change (e.g.,\n * if the file is moved to a different location and its links are rebased).\n */\n filePath: string;\n\n /**\n * Original relative path of the source file.\n *\n * Set when the metadata is created and never modified.\n */\n readonly id: string;\n\n readonly directDependencies: Set<string>;\n}\n\nexport interface ScriptMetadata extends MetadataBase {\n readonly type: (typeof METADATA_TYPES)[\"Script\"];\n\n /**\n * The Babel AST for the script.\n *\n * Mutated during the build process and always represents the file's current transformed state.\n */\n ast: BabelAst;\n\n /** Whether the script is a module or global */\n module: boolean;\n}\n\nexport interface StyleMetadata extends MetadataBase {\n readonly type: (typeof METADATA_TYPES)[\"CSS\"];\n\n /**\n * The PostCSS root after transformation\n *\n * Mutated during the build process and always represents the file's current transformed state.\n */\n ast: PostcssAst;\n}\n\nexport interface HtmlMetadata extends MetadataBase {\n type: (typeof METADATA_TYPES)[\"HTML\"];\n\n /**\n * The HTML AST (root element).\n *\n * Mutated during the build process and always represents the file's current transformed state\n */\n ast: Document;\n\n /** The transformed ASTs from script tags. The key is the UUID */\n scriptsMetadataList: Map<string, ScriptMetadata>;\n\n /** The transformed ASTs from script tags. The key is the UUID */\n stylesMetadataList: Map<string, StyleMetadata>;\n}\n\nexport interface SvgMetadata extends MetadataBase {\n type: (typeof METADATA_TYPES)[\"SVG\"];\n\n /**\n * The HTML AST (root element).\n *\n * Mutated during the build process and always represents the file's current transformed state\n */\n ast: Document;\n\n /** The transformed ASTs from script tags. The key is the UUID */\n stylesMetadataList: Map<string, StyleMetadata>;\n}\n\nexport interface MarkdownMetadata extends MetadataBase {\n type: (typeof METADATA_TYPES)[\"Markdown\"];\n\n /**\n * Markdown tokens and frontmatter.\n *\n * Mutated during the build process and always represents the file's current transformed state\n */\n ast: MarkdownAst;\n}\n\nexport interface WebManifestMetadata extends MetadataBase {\n type: (typeof METADATA_TYPES)[\"WebAppManifest\"];\n ast: WebAppManifest;\n}\n\nexport interface PackageMetadata extends MetadataBase {\n type: (typeof METADATA_TYPES)[\"Package\"];\n\n /** Metadata code */\n code: string;\n\n packageName: string;\n}\n\nexport interface TextAssetMetadata extends MetadataBase {\n type: (typeof METADATA_TYPES)[\"TextAsset\"];\n\n /** Metadata code */\n code: string;\n}\n\nexport interface BinaryAssetMetadata extends MetadataBase {\n type: (typeof METADATA_TYPES)[\"BinaryAsset\"];\n\n /** Raw binary content — images, fonts, wasm, etc. */\n data?: Uint8Array;\n}\n","const allowedTypes = new Set([\n \"module\",\n \"text/javascript\",\n \"application/javascript\",\n \"text/ecmascript\",\n \"application/ecmascript\",\n \"application/x-javascript\",\n]);\n\nexport function isScriptType(type: string | null) {\n return !type || allowedTypes.has(type.toLowerCase());\n}\n","import { isScriptType } from \"../helpers/is-script-type.ts\";\nimport { CUSTOM_ATTRIBUTES } from \"../types/common.ts\";\nimport { METADATA_TYPES } from \"../types/metadata.ts\";\n\nimport type {\n TextAssetMetadata,\n HtmlMetadata,\n MarkdownMetadata,\n MetadataBase,\n ScriptMetadata,\n StyleMetadata,\n SvgMetadata,\n WebManifestMetadata,\n BinaryAssetMetadata,\n PackageMetadata,\n HTMLElement,\n} from \"@staticbolt/core\";\n\nexport function isScriptMetadata(metadata: MetadataBase | undefined): metadata is ScriptMetadata {\n return metadata?.type === METADATA_TYPES.Script;\n}\n\nexport function isPackageMetadata(metadata: MetadataBase | undefined): metadata is PackageMetadata {\n return metadata?.type === METADATA_TYPES.Package;\n}\n\nexport function isHtmlMetadata(metadata: MetadataBase | undefined): metadata is HtmlMetadata {\n return metadata?.type === METADATA_TYPES.HTML;\n}\n\nexport function isStyleMetadata(metadata: MetadataBase | undefined): metadata is StyleMetadata {\n return metadata?.type === METADATA_TYPES.CSS;\n}\n\nexport function isSvgMetadata(metadata: MetadataBase | undefined): metadata is SvgMetadata {\n return metadata?.type === METADATA_TYPES.SVG;\n}\n\nexport function isMarkdownMetadata(metadata: MetadataBase | undefined): metadata is MarkdownMetadata {\n return metadata?.type === METADATA_TYPES.Markdown;\n}\n\nexport function isTextAssetMetadata(metadata: MetadataBase | undefined): metadata is TextAssetMetadata {\n return metadata?.type === METADATA_TYPES.TextAsset;\n}\n\nexport function isBinaryAssetMetadata(metadata: MetadataBase | undefined): metadata is BinaryAssetMetadata {\n return metadata?.type === METADATA_TYPES.BinaryAsset;\n}\n\nexport function isWebManifestMetadata(metadata: MetadataBase): metadata is WebManifestMetadata {\n return metadata.type === METADATA_TYPES.WebAppManifest;\n}\n\n/**\n * Returns script-related metadata entries.\n *\n * - If the input is ScriptMetadata, it returns it directly.\n * - If the input is HtmlMetadata, it scans <script> tags in the AST and resolves their associated ScriptMetadata using the metadata\n * ID attribute.\n */\nexport function filterScriptMetadata(metadata: MetadataBase) {\n const result: { metadata: ScriptMetadata; tag?: HTMLElement; htmlMetadata?: HtmlMetadata }[] = [];\n\n if (isScriptMetadata(metadata)) {\n result.push({ metadata });\n return result;\n }\n\n if (isHtmlMetadata(metadata)) {\n const scriptTags = metadata.ast.querySelectorAll(\"script\");\n\n for (const scriptTag of scriptTags) {\n const scriptId = scriptTag.getAttribute(CUSTOM_ATTRIBUTES.MetadataID);\n if (!scriptId) continue;\n\n const scriptType = scriptTag.getAttribute(\"type\");\n if (!isScriptType(scriptType)) {\n continue;\n }\n\n const scriptMetadata = metadata.scriptsMetadataList.get(scriptId);\n if (!scriptMetadata) continue;\n\n result.push({ metadata: scriptMetadata, htmlMetadata: metadata, tag: scriptTag });\n }\n }\n\n return result;\n}\n\n/**\n * Returns style-related metadata entries.\n *\n * - If the input is StyleMetadata, it returns it directly.\n * - If the input is HtmlMetadata, it scans <style> tags in the AST and resolves their associated StyleMetadata using the metadata\n * ID attribute.\n */\nexport function filterStyleMetadata(metadata: MetadataBase) {\n const result: { metadata: StyleMetadata; tag?: HTMLElement; htmlMetadata?: HtmlMetadata }[] = [];\n\n if (isStyleMetadata(metadata)) {\n result.push({ metadata });\n return result;\n }\n\n if (isHtmlMetadata(metadata)) {\n const styleTags = metadata.ast.querySelectorAll(\"style\");\n\n for (const styleTag of styleTags) {\n const styleId = styleTag.getAttribute(CUSTOM_ATTRIBUTES.MetadataID) || \"\";\n const styleMetadata = metadata.stylesMetadataList.get(styleId);\n if (!styleMetadata) continue;\n\n result.push({\n metadata: styleMetadata,\n htmlMetadata: metadata,\n tag: styleTag,\n });\n }\n }\n\n return result;\n}\n","import _generator from \"@babel/generator\";\nimport _traverse from \"@babel/traverse\";\n\nconst generator = typeof _generator === \"function\" ? _generator : _generator.default;\n\nconst traverse = typeof _traverse === \"function\" ? _traverse : _traverse.default;\n\nexport { generator, traverse };\n","import boxen from \"boxen\";\nimport chalk from \"chalk\";\nimport { common, createEmphasize } from \"emphasize\";\n\n/** - Highlight code string for terminal */\nexport function highlightCode(code: string, { lang = \"ts\", maxCodeLength = 170, maxLineLength = 110, boxed = true } = {}) {\n // Limit code length\n const isTruncated = code.length > maxCodeLength;\n if (isTruncated) code = code.slice(0, Math.max(0, maxCodeLength));\n\n // Limit line length and break on words\n const lines = code.split(\"\\n\");\n let withNewLines = \"\";\n for (const line of lines) {\n if (line.length <= maxLineLength) {\n withNewLines += line + \"\\n\";\n continue;\n }\n\n const words = line.split(\" \");\n let currentLine = \"\";\n for (const word of words) {\n if (currentLine.length + word.length <= maxLineLength) {\n currentLine += word + \" \";\n continue;\n }\n withNewLines += currentLine + \"\\n\";\n currentLine = word + \" \";\n }\n withNewLines += currentLine + \"\\n\";\n }\n\n // Highlight\n let highlighted = createEmphasize(common).highlight(lang, withNewLines.trim()).value;\n if (isTruncated) highlighted += \"\\n\" + chalk.inverse(\" ... \");\n\n if (!boxed) return highlighted;\n\n return boxen(highlighted, {\n padding: 0.5,\n borderStyle: \"round\",\n borderColor: \"white\",\n dimBorder: true,\n });\n}\n","import { NodeType } from \"@staticbolt/node-html-parser\";\nimport c from \"chalk\";\nimport { Node as PostcssNode } from \"postcss\";\n\nimport { generator } from \"../helpers/babel-fixed-imports.ts\";\nimport { CUSTOM_ATTRIBUTES } from \"../types/common.ts\";\nimport { highlightCode } from \"./highlight-code.ts\";\nimport { Log } from \"./logger.ts\";\n\nimport type { Node as BabelNode } from \"@babel/types\";\nimport type { HTMLElement, Node as HtmlNode } from \"@staticbolt/node-html-parser\";\n\ntype Node = BabelNode | PostcssNode | HtmlNode;\n\ninterface FormatErrorOptions {\n /** AST node (e.g., from Babel, PostCSS, or HTML) to convert and highlight */\n node?: Node;\n\n /** Source code to highlight (use instead of `node`) */\n code?: string;\n\n /** Language of the provided source code (required if `code` is set) */\n lang?: string;\n\n /** Path of the file where the error occurred */\n filePath?: string;\n\n /** Name of the function where the error originated */\n functionName?: string;\n\n level?: \"error\" | \"warning\";\n\n /** Function reference used to extract the function name */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function?: (...arguments_: any[]) => any;\n}\n\ntype MessageAndError = (string | Error)[];\n\nexport class PrintFormattedError {\n options: FormatErrorOptions = {};\n\n constructor(options: FormatErrorOptions = {}) {\n Object.assign(this.options, options);\n }\n\n static create(options: FormatErrorOptions = {}) {\n return new PrintFormattedError(options).print;\n }\n\n print = (...messageAndErrorWithOptions: [...MessageAndError] | [...MessageAndError, FormatErrorOptions]) => {\n const options: FormatErrorOptions = { ...this.options };\n\n const messagesArray: string[] = [];\n for (const item of messageAndErrorWithOptions) {\n // Msg\n if (typeof item === \"string\") {\n messagesArray.push(item);\n continue;\n }\n\n // Error\n if (item instanceof Error) {\n messagesArray.push(`\\n${item.message}`);\n continue;\n }\n\n // Options\n Object.assign(options, item);\n }\n\n let message = \"\";\n\n // First file path in one line without anything else to enable vscode link parsing\n if (options.filePath) {\n message += c.italic(options.filePath) + \"\\n\";\n }\n\n // Then the function name before the messages\n const functionName = options.function?.name ?? options.functionName;\n if (functionName) {\n message += c.dim(`[${functionName}] `);\n }\n\n // Then the messages (spaced)\n message += messagesArray.join(\" \");\n\n // Now the code\n const codeFromNode = options.node && nodeToString(options.node);\n const code = options.code ?? codeFromNode?.code;\n const lang = options.lang ?? codeFromNode?.lang;\n const codeBox = code && lang ? highlightCode(code, { lang }) : \"\";\n if (codeBox) {\n message += \"\\n\" + codeBox;\n }\n\n if (options.level === \"warning\") {\n Log.warn(message);\n return;\n }\n\n Log.error(message);\n };\n}\n\nexport const printFmtError = PrintFormattedError.create();\n\nfunction isHtmlNode(node: Node): node is HtmlNode {\n return \"nodeType\" in node && typeof node.nodeType === \"number\";\n}\n\nfunction isPostcssNode(node: Node): node is PostcssNode {\n return node instanceof PostcssNode;\n}\n\nfunction nodeToString(node: Node): { code: string; lang: string } {\n if (isHtmlNode(node)) {\n const clone = node.clone();\n if (clone.nodeType === NodeType.ELEMENT_NODE) {\n (clone as HTMLElement).removeAttribute(CUSTOM_ATTRIBUTES.MetadataID);\n }\n\n return { code: clone.toString(), lang: \"html\" };\n }\n\n if (isPostcssNode(node)) {\n return { code: node.toString(), lang: \"css\" };\n }\n\n return { code: generator(node, { jsescOption: { minimal: true } }).code, lang: \"js\" };\n}\n","import { createHash } from \"node:crypto\";\n\nimport { Log } from \"./logger.ts\";\n\nimport type { ValueOrError } from \"./value-or-error.ts\";\n\n/** `process.stdout.write` */\nexport function print(...input: string[]) {\n process.stdout.write(input.join(\" \"));\n}\n\n/** - Clear the line in the terminal */\nexport function clearLn() {\n if (\"clearLine\" in process.stdout && typeof process.stdout.clearLine === \"function\") {\n process.stdout.clearLine(0);\n process.stdout.cursorTo(0);\n }\n}\n\n/** Used to assign a computed value to a variable */\nexport function assign<T>(function_: () => T): T {\n return function_();\n}\n\n/** Check if the value is an object */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && !Array.isArray(value) && value !== null;\n}\n\nexport function kebabToCamelCase(string_: string): string {\n return string_.replace(/-([a-z])/g, (_, char) => (char as string).toUpperCase());\n}\n\nexport function camelCaseToKebabCase(string_: string): string {\n return string_.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\nexport function capitalize(string_: string): string {\n return string_.charAt(0).toUpperCase() + string_.slice(1);\n}\n\n/**\n * - Get line and column number from first match index\n *\n * @param code - Code string\n * @param matchIndex - Matching index\n * @returns - `[line, column]`\n */\nexport function getLineColumn(code: string, matchIndex: number): [number, number] {\n let lineNumber = 1;\n let columnNumber = 1;\n\n for (let index = 0; index < matchIndex; index++) {\n if (code[index] === \"\\n\") {\n lineNumber++;\n columnNumber = 1; // Reset column at each new line\n continue;\n }\n\n columnNumber++;\n }\n\n return [lineNumber, columnNumber];\n}\n\n/** - Human readable bytes, E.g: `1024 => 1KB` */\nexport function humanReadableBytes(bytes: number): string {\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n let unitIndex = 0;\n while (bytes >= 1024 && unitIndex < units.length - 1) {\n bytes /= 1024;\n unitIndex++;\n }\n return `${bytes.toFixed(2)} ${units[unitIndex]}`;\n}\n\nexport function bytesToKB(bytes: number): number {\n return bytes / 1024;\n}\n\n/** - Clamp a numeric value between min and max values. */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nexport function isDefined<T>(value: T | undefined): value is T {\n return value !== undefined;\n}\n\n/**\n * Merges all entries from `source` into `target`, mutating `target` in place.\n *\n * - Existing keys in `target` are overwritten by `source` values.\n * - Values are **not** cloned — object references are shared between both maps after the merge.\n *\n * @param target - The map to be mutated with new/updated entries.\n * @param source - The map whose entries are read and applied to `target`.\n * @returns The mutated `target` map.\n */\nexport function mergeMaps<K, V>(target: Map<K, V>, source: Map<K, V>): Map<K, V> {\n for (const [key, value] of source) {\n target.set(key, value);\n }\n return target;\n}\n\nconst cached = new Map<string, string>();\n\n/** - Download from CDN */\nexport async function downloadContent(url: string): Promise<ValueOrError<string>> {\n if (cached.has(url)) {\n return [cached.get(url)!, null];\n }\n\n const headers = {\n \"User-Agent\":\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\",\n Accept: \"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\",\n Referer: url,\n };\n\n try {\n Log.info(`Downloading content from \"${url}\"`);\n const response = await fetch(url, { headers });\n const text = await response.text();\n cached.set(url, text);\n return [text, null];\n } catch {\n return [null, new Error(\"Error downloading q: \" + url)];\n }\n}\n\nexport function isURL(url: string): boolean {\n return url.startsWith(\"http://\") || url.startsWith(\"https://\");\n}\n\n/** Creates a shallow clone of an object while preserving its prototype and property descriptors. */\nexport function cloneObject<T extends object>(object: T): T {\n return Object.create(Object.getPrototypeOf(object) as T, Object.getOwnPropertyDescriptors(object)) as T;\n}\n\nexport function hashContent(content: string) {\n return createHash(\"sha1\").update(content).digest(\"hex\"); // full 40 chars\n}\n\nconst matchHtmlRegExp = /[\"'&<>]/;\n\nexport function escapeHtml(input: string) {\n const string = \"\" + input;\n const match = matchHtmlRegExp.exec(string);\n\n if (!match) {\n return string;\n }\n\n let escape;\n let html = \"\";\n // eslint-disable-next-line no-useless-assignment\n let index = 0;\n let lastIndex = 0;\n\n for (index = match.index; index < string.length; index++) {\n switch (string.codePointAt(index)) {\n case 34: // \"\n escape = \"&quot;\";\n break;\n case 38: // &\n escape = \"&amp;\";\n break;\n case 39: // '\n escape = \"&#39;\";\n break;\n case 60: // <\n escape = \"&lt;\";\n break;\n case 62: // >\n escape = \"&gt;\";\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += string.slice(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex === index ? html : html + string.slice(lastIndex, index);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@staticbolt/core",
3
3
  "description": "Static website builder",
4
- "version": "1.0.0-beta.11",
4
+ "version": "1.0.0-beta.13",
5
5
  "author": "Ahmed ALABSI",
6
6
  "bin": {
7
7
  "staticbolt": "lib/cli/index.mjs"
@@ -75,7 +75,8 @@
75
75
  "@types/postcss-import": "^14.0.3",
76
76
  "@types/unist": "^3.0.3",
77
77
  "@types/ws": "^8.18.1",
78
- "baseline-browser-mapping": "^2.10.29"
78
+ "baseline-browser-mapping": "^2.10.29",
79
+ "vscode-html-languageservice": "^5.6.2"
79
80
  },
80
81
  "exports": {
81
82
  ".": {
@@ -97,8 +98,8 @@
97
98
  ],
98
99
  "license": "MIT",
99
100
  "peerDependencies": {
100
- "@staticbolt/args-parser": "1.0.0-beta.11",
101
- "@staticbolt/node-html-parser": "1.0.0-beta.11"
101
+ "@staticbolt/args-parser": "1.0.0-beta.13",
102
+ "@staticbolt/node-html-parser": "1.0.0-beta.13"
102
103
  },
103
104
  "private": false,
104
105
  "scripts": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger-BfIn1ytK.mjs","names":["chalk"],"sources":["../src/types/common.ts","../src/utilities/path.ts","../src/utilities/logger.ts"],"sourcesContent":["import type { ParseResult } from \"@babel/parser\";\nimport type { NodePath as NodePathT } from \"@babel/traverse\";\nimport type * as t from \"@babel/types\";\nimport type { Plugin } from \"@staticbolt/core\";\nimport type { Root } from \"mdast\";\nimport type postcss from \"postcss\";\n\nexport type NodePath<T = t.Node | null | undefined> = NodePathT<T>;\n\nexport type BabelAst = ParseResult;\nexport type PostcssAst = postcss.Root;\nexport type { HTMLElement, Document } from \"@staticbolt/node-html-parser\";\n\nexport interface MarkdownAst {\n root: Root;\n frontmatter: Record<string, string>;\n render(): Promise<string>;\n}\n\nexport const CUSTOM_ATTRIBUTES = Object.freeze({\n /** For script and style tags to grab the metadata */\n MetadataID: \"data-metadata-id\",\n});\n\nexport const CONFIG_FILE_NAME = \".staticbolt.ts\";\n\nexport interface AppConfig {\n root?: string;\n plugins?: (Plugin[] | Plugin)[];\n outdir?: string;\n production?: boolean;\n browserslist?: string[];\n}\n","import nodePath from \"node:path\";\nimport micromatch from \"micromatch\";\n\nexport { basename, extname, isAbsolute, parse, resolve } from \"node:path\";\n\n// For ESM and CSS compatibility:\n// - Always use unix separators (except `resolve`, which returns an absolute path)\n// - Relative paths should always start with `./`\n\nconst separatorRe = /\\\\/g;\n\n/** Normalizes a path result to unix separators and ensures relative paths start with `./` */\nfunction unixify(path: string): string {\n const unix = path.replace(separatorRe, \"/\");\n\n // Example: dirname(\"index.html\") => \".\"\n if (unix === \".\") {\n return \"./\";\n }\n\n if (unix === \"/\" || nodePath.isAbsolute(unix)) {\n return unix;\n }\n\n if (unix.startsWith(\"./\") || unix.startsWith(\"../\")) {\n return unix;\n }\n\n return `./${unix}`;\n}\n\nexport const join = (...arguments_: string[]) => unixify(nodePath.join(...arguments_));\n\nexport const relative = (from: string, to: string) => unixify(nodePath.relative(from, to));\n\nexport const dirname = (path: string) => unixify(nodePath.dirname(path));\n\nexport const normalize = (path: string) => unixify(nodePath.normalize(path));\n\n/**\n * Recalculates the relative path for a resource after a file has been moved.\n *\n * @param source - The source found in the `oldPath` file.\n * @param oldPath - Absolute or relative original path of the file.\n * @param newPath - Absolute or relative new path of the file.\n * @returns The updated relative path from the new file's directory to the same resource.\n */\nexport function rebaseRelativePath(source: string, oldPath: string, newPath: string): string {\n return relative(dirname(newPath), join(dirname(oldPath), source));\n}\n\n/**\n * Checks if a path (child) is a subpath of another (parent).\n *\n * Note: both paths must be of the same type — either both absolute or both relative. Mixing them will produce incorrect results.\n *\n * @param parentDirectory - The parent directory.\n * @param childPath - The child path (file or directory).\n */\nexport function isSubpath(parentDirectory: string, childPath: string): boolean {\n if (childPath === \"./\") return false;\n const relativePath = relative(normalize(parentDirectory), normalize(childPath));\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !nodePath.isAbsolute(relativePath));\n}\n\ninterface SourceRelativeToRootOptions {\n /** The root directory (absolute or resolvable) */\n root: string;\n /** The file path that contains the source path */\n filePath: string;\n /** The source path */\n sourcePath: string;\n}\n\n/** Calculates the relative path of a source path to the root. */\nexport function sourceRelativeToRoot({ root, filePath, sourcePath }: SourceRelativeToRootOptions): string {\n const absRoot = nodePath.resolve(root);\n return relative(absRoot, nodePath.join(absRoot, dirname(filePath), sourcePath));\n}\n\n/** Replaces the extension of a given path. */\nexport function replaceExtension(filePath: string, extension: string): string {\n const { dir, name } = nodePath.parse(filePath);\n return normalize(nodePath.format({ dir, name, ext: extension }));\n}\n\n/** Appends a forward slash to the end of a path if it doesn't already end with one. */\nexport const appendForwardSlash = (path: string) => (path.endsWith(\"/\") ? path : `${path}/`);\n\n/** Removes the leading `./` from a path. */\nexport const trimDotPrefix = (path: string) => (path.startsWith(\"./\") ? path.slice(2) : path);\n\n/** Returns the first segment of a path. */\nexport function firstPart(path: string): string {\n const cleaned = normalize(path).replace(/\\/$/, \"\");\n return cleaned.split(\"/\")[0] ?? \"\";\n}\n\ninterface MatchPathOptions {\n include: string | string[];\n ignore?: string | string[];\n root: string;\n}\n\n/** Checks if a file path matches a set of patterns. */\nexport function matchPath(filePath: string, { include, ignore, root }: MatchPathOptions): boolean {\n // Case: outside the root directory\n if (filePath.startsWith(\"..\")) {\n const match = micromatch.isMatch(join(root, filePath), include, { ignore });\n return match;\n }\n\n // Case: inside the root dir\n const withoutDotPrefix = filePath.replace(/^\\.\\//, \"\");\n const match = micromatch.isMatch(withoutDotPrefix, include, { cwd: root, ignore });\n\n return match;\n}\n","import chalk from \"chalk\";\n\ntype ChalkInstance = typeof chalk;\n\nconst logConfig = {\n verboseEnabled: false,\n verboseFilter: null as null | RegExp,\n titleWidth: 10,\n spacer: \" \",\n style: {\n success: chalk.green,\n error: chalk.red,\n fatal: chalk.red,\n warning: chalk.yellow,\n verbose: chalk.dim,\n info: chalk.blueBright,\n tip: chalk.magenta,\n log: chalk.white,\n spacer: chalk.dim,\n },\n};\n\nexport function createLog(...defaultMessages: string[]) {\n function Log(...messages: unknown[]) {\n console.log(formatLogTitle(\"LOG\", logConfig.style.log), ...defaultMessages, ...messages);\n }\n\n Log.warn = (...messages: string[]) => {\n logFormatter(\"WARNING\", logConfig.style.warning, ...defaultMessages, ...messages);\n };\n\n Log.success = (...messages: string[]) => {\n logFormatter(\"SUCCESS\", logConfig.style.success, ...defaultMessages, ...messages);\n };\n\n Log.error = (...messages: string[]) => {\n logFormatter(\"ERROR\", logConfig.style.error, ...defaultMessages, ...messages);\n };\n\n Log.fatal = (...messages: string[]) => {\n logFormatter(\"FATAL\", logConfig.style.fatal, ...defaultMessages, ...messages);\n\n // eslint-disable-next-line unicorn/no-process-exit\n process.exit(1);\n };\n\n Log.info = (...messages: string[]) => {\n logFormatter(\"INFO\", logConfig.style.info, ...defaultMessages, ...messages);\n };\n\n Log.tip = (...messages: string[]) => {\n logFormatter(\"TIP\", logConfig.style.tip, ...defaultMessages, ...messages);\n };\n\n Log.debug = (...messages: string[]) => {\n if (!logConfig.verboseEnabled) return;\n\n const joined = defaultMessages.concat(messages).join(\" \");\n if (logConfig.verboseFilter && !logConfig.verboseFilter.test(joined)) return;\n\n logFormatter(\"DEBUG\", logConfig.style.verbose, joined);\n };\n\n Log.enableVerbose = (enabled: boolean) => {\n logConfig.verboseEnabled = enabled;\n };\n\n Log.setVerboseFilter = (filter: RegExp) => {\n logConfig.verboseFilter = filter;\n };\n\n return Log;\n}\n\n/**\n * - Prints a styled message to the console.\n *\n * @example\n * Log(\"Hello World!\"); // Prints: | LOG | Hello World! |\n * Log.success(\"Hello World!\"); // Prints: | SUCCESS | Hello World! |\n * Log.info(\"Hello World!\"); // Prints: | INFO | Hello World! |\n * Log.error(\"Hello World!\"); // Prints: | ERROR | Hello World! |\n * Log.fatal(\"Hello World!\"); // Prints: | FATAL | Hello World! |\n * Log.warn(\"Hello World!\"); // Prints: | WARNING | Hello World! |\n */\nexport const Log = createLog();\n\nfunction formatLogTitle(title: string, style: ChalkInstance) {\n const width = logConfig.titleWidth;\n const paddingLength = title.length >= width ? 0 : (width - title.length) / 2;\n const paddingStart = \" \".repeat(paddingLength);\n const paddingEnd = \" \".repeat(paddingLength);\n\n title = paddingStart + title + paddingEnd;\n\n // Ensure that the final string has width length\n title = title.padEnd(width, \" \");\n\n // apply style\n title = style(title + \"|\");\n\n return title;\n}\n\nfunction logFormatter(title: string, style: ChalkInstance, ...messages: string[]) {\n const { prefixNewlines, content, suffixNewlines } = splitOnNewline(messages);\n const formattedTitle = formatLogTitle(title, style);\n\n const splitByNewLines = content.split(\"\\n\");\n\n let message = \"\";\n for (const [index, splitByNewLine] of splitByNewLines.entries()) {\n if (index > 0) {\n const width = logConfig.titleWidth / logConfig.spacer.length;\n const spacer = logConfig.spacer.repeat(width).padEnd(logConfig.titleWidth);\n message += \"\\n\" + style.dim(spacer + \"↪ \");\n }\n\n message += splitByNewLine;\n }\n\n console.log(prefixNewlines + formattedTitle, message, suffixNewlines);\n}\n\nfunction splitOnNewline(input: string[]) {\n const message = input.join(\" \");\n\n // Check for leading newlines\n let newlineStart = 0;\n while (newlineStart < message.length && message[newlineStart] == \"\\n\") {\n newlineStart++;\n }\n\n // Check for trailing newlines\n let newlineEnd = message.length;\n while (newlineEnd > newlineStart && message[newlineEnd - 1] == \"\\n\") {\n newlineEnd--;\n }\n\n const results = {\n prefixNewlines: message.slice(0, Math.max(0, newlineStart)),\n content: message.slice(newlineStart, newlineEnd),\n suffixNewlines: message.slice(Math.max(0, newlineEnd)),\n };\n\n return results;\n}\n"],"mappings":"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"}