@staticbolt/core 1.0.0-beta.3 → 1.0.0-beta.31

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,32 +1,101 @@
1
- import { i as CUSTOM_ATTRIBUTES, t as Log } from "./logger-BuxMGhij.mjs";
1
+ import { _ as replaceExtension, c as isAbsolute, d as join, f as normalize, n as CUSTOM_ATTRIBUTES, o as dirname, r as Log, s as extname } from "./common-D1QTZ8ra.mjs";
2
+ import { existsSync, readFileSync, statSync } from "node:fs";
3
+ import { ResolverFactory } from "oxc-resolver";
4
+ import chalk from "chalk";
5
+ import json5 from "json5";
6
+ import { readFile } from "node:fs/promises";
7
+ import _generator from "@babel/generator";
2
8
  import { NodeType } from "@staticbolt/node-html-parser";
3
- import c from "chalk";
4
9
  import { Node as Node$1 } from "postcss";
5
- import _generator from "@babel/generator";
6
- import _traverse from "@babel/traverse";
7
10
  import boxen from "boxen";
8
11
  import { common, createEmphasize } from "emphasize";
9
- import { readFileSync } from "node:fs";
10
- import { readFile } from "node:fs/promises";
11
12
  import { createHash } from "node:crypto";
12
13
 
13
- //#region src/types/metadata.ts
14
- const METADATA_TYPES = Object.freeze({
15
- Script: "Script",
16
- HTML: "Html",
17
- Markdown: "Markdown",
18
- CSS: "Style",
19
- SVG: "Svg",
20
- Package: "Package",
21
- TextAsset: "TextAsset",
22
- BinaryAsset: "BinaryAsset",
23
- WebAppManifest: "WebAppManifest"
24
- });
14
+ //#region src/helpers/dependency-tracker.ts
15
+ /**
16
+ * Tracks bidirectional dependencies between importers and their sources.\
17
+ * Handles reconciliation when dependencies change, so stale entries are automatically removed when an importer stops referencing
18
+ * a source.
19
+ */
20
+ var DependencyTracker = class {
21
+ /** Source → Set of importers that depend on it */
22
+ #sourcesToImporters = /* @__PURE__ */ new Map();
23
+ /** Importer → Set of sources it depends on */
24
+ #importerToSources = /* @__PURE__ */ new Map();
25
+ /** Updates the full set of sources for a given importer, reconciling any stale entries from previous calls. */
26
+ update(importer, sources) {
27
+ const nextSources = new Set(sources);
28
+ const previousSources = this.#importerToSources.get(importer) ?? /* @__PURE__ */ new Set();
29
+ for (const source of previousSources) if (!nextSources.has(source)) this.#sourcesToImporters.get(source)?.delete(importer);
30
+ for (const source of nextSources) {
31
+ if (!this.#sourcesToImporters.has(source)) this.#sourcesToImporters.set(source, /* @__PURE__ */ new Set());
32
+ this.#sourcesToImporters.get(source).add(importer);
33
+ }
34
+ this.#importerToSources.set(importer, nextSources);
35
+ }
36
+ /** Deletes all dependency data for a given id, whether it's acting as an importer, a source, or both (e.g. on file unlink). */
37
+ delete(id) {
38
+ this.#sourcesToImporters.delete(id);
39
+ const sources = this.#importerToSources.get(id);
40
+ if (sources) {
41
+ for (const source of sources) this.#sourcesToImporters.get(source)?.delete(id);
42
+ this.#importerToSources.delete(id);
43
+ }
44
+ }
45
+ /** Returns all importers that depend on a given source, or an empty set. */
46
+ getImporters(source) {
47
+ return this.#sourcesToImporters.get(source) ?? /* @__PURE__ */ new Set();
48
+ }
49
+ /** Returns all sources that a given importer depends on, or an empty set. */
50
+ getSources(importer) {
51
+ return this.#importerToSources.get(importer) ?? /* @__PURE__ */ new Set();
52
+ }
53
+ };
54
+
55
+ //#endregion
56
+ //#region src/utilities/html-links.ts
57
+ /**
58
+ * Checks if the link is an HTML link (not a file link)
59
+ *
60
+ * @param source - The link
61
+ * @returns
62
+ */
63
+ function isHtmlLink(source) {
64
+ return /^(?:#|https?|mailto:|tel:|url\(|ftp:|data:|javascript:)/i.test(source);
65
+ }
66
+ function isValidRelativePath(source) {
67
+ if (!source) return false;
68
+ if (isAbsolute(source)) return false;
69
+ return !isHtmlLink(source);
70
+ }
71
+ function splitHtmlLink(url) {
72
+ const qIndex = url.indexOf("?");
73
+ const hIndex = url.indexOf("#");
74
+ let delimIndex = -1;
75
+ if (qIndex !== -1 && hIndex !== -1) delimIndex = Math.min(qIndex, hIndex);
76
+ else if (qIndex !== -1) delimIndex = qIndex;
77
+ else if (hIndex !== -1) delimIndex = hIndex;
78
+ if (delimIndex !== -1) {
79
+ const pathEnd = url[delimIndex - 1] === "/" ? delimIndex - 1 : delimIndex;
80
+ return [url.slice(0, pathEnd), url.slice(pathEnd)];
81
+ }
82
+ if (url.endsWith("/")) {
83
+ if (url === "/" || url === "./") return [url, ""];
84
+ return [url.slice(0, -1), "/"];
85
+ }
86
+ return [url, ""];
87
+ }
25
88
 
26
89
  //#endregion
27
90
  //#region src/helpers/is-script-type.ts
28
- const allowedTypes = new Set([
91
+ /**
92
+ * The `type` that marks a script as TypeScript for the editor: Prettier formats it as such, the editor's own script support
93
+ * leaves it alone, and the build drops it from the output.
94
+ */
95
+ const TYPESCRIPT_TYPE = "application/x-typescript";
96
+ const allowedTypes = /* @__PURE__ */ new Set([
29
97
  "module",
98
+ TYPESCRIPT_TYPE,
30
99
  "text/javascript",
31
100
  "application/javascript",
32
101
  "text/ecmascript",
@@ -37,6 +106,350 @@ function isScriptType(type) {
37
106
  return !type || allowedTypes.has(type.toLowerCase());
38
107
  }
39
108
 
109
+ //#endregion
110
+ //#region src/helpers/lsp-checks.ts
111
+ /** The placeholder syntaxes a plugin or a runtime may fill in: `{{ }}`, `[[ ]]`, `${ }`, `<% %>`, `{% %}` and `%name%`. */
112
+ const PLACEHOLDER = /\{\{[\s\S]*?\}\}|\[\[[\s\S]*?\]\]|\$\{[\s\S]*?\}|<%[\s\S]*?%>|\{%[\s\S]*?%\}|%[\w.-]+%/;
113
+ /** Whether an attribute value is only known later: it holds a placeholder something else fills in. */
114
+ function isDynamic(value) {
115
+ return PLACEHOLDER.test(value);
116
+ }
117
+ /**
118
+ * Reports an attribute whose value is a path to a file that is not there. A URL, an absolute link or a value with a placeholder
119
+ * is left alone.
120
+ */
121
+ function checkFileExists(attribute, document, report) {
122
+ if (!attribute.value) return;
123
+ if (isDynamic(attribute.value)) return;
124
+ if (!isValidRelativePath(attribute.value)) return;
125
+ if (document.resolve(attribute.value)?.exists) return;
126
+ report.error(attribute, `"${attribute.value}" does not exist`);
127
+ }
128
+ /** Reports an attribute whose value is not the JSON of an object. A value with a placeholder is left alone. */
129
+ function checkJsonObject(attribute, report) {
130
+ if (!attribute.value) return;
131
+ if (isDynamic(attribute.value)) return;
132
+ if (isJsonObject(attribute.value)) return;
133
+ report.error(attribute, `"${attribute.name}" must be a JSON object`);
134
+ }
135
+ /** Whether a string is the JSON of an object. */
136
+ function isJsonObject(text) {
137
+ try {
138
+ const parsed = JSON.parse(text);
139
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed);
140
+ } catch {
141
+ return false;
142
+ }
143
+ }
144
+ /** Whether a script element holds JavaScript, going by its `type`: the build leaves any other kind of script alone. */
145
+ function isJavaScript(script) {
146
+ return isScriptType(script.attribute("type")?.value ?? null);
147
+ }
148
+ /** Whether a `<script>` is marked as TypeScript for the editor, which also keeps the editor's own script support out. */
149
+ function isTypeScriptScript(script) {
150
+ return script.attribute("type")?.value?.toLowerCase() === TYPESCRIPT_TYPE;
151
+ }
152
+ /** Whether an element has nothing but whitespace between its tags. */
153
+ function isEmptyElement(element, document) {
154
+ if (!element.contentRange) return true;
155
+ return document.textOf(element.contentRange).trim() === "";
156
+ }
157
+
158
+ //#endregion
159
+ //#region src/utilities/value-or-error.ts
160
+ function errorsWrapper(function_) {
161
+ return (...arguments_) => {
162
+ try {
163
+ const promiseOrValue = function_(...arguments_);
164
+ if (isPromise(promiseOrValue)) return new Promise((resolve) => {
165
+ promiseOrValue.then((value) => {
166
+ resolve([value, null]);
167
+ }).catch((error) => {
168
+ resolve(handleError(error, function_.name));
169
+ });
170
+ });
171
+ return [promiseOrValue, null];
172
+ } catch (error) {
173
+ return handleError(error, function_.name);
174
+ }
175
+ };
176
+ }
177
+ function isPromise(value) {
178
+ return value && typeof value === "object" && "then" in value && typeof value.then === "function" && "catch" in value && typeof value.catch === "function";
179
+ }
180
+ function handleError(error, functionName = "") {
181
+ if (!error) return [null, /* @__PURE__ */ new Error(`[${functionName}] Unexpected error`)];
182
+ if (typeof error === "string") return [null, new Error(error)];
183
+ if (error instanceof Error) return [null, error];
184
+ if (typeof error === "object" && "message" in error && typeof error.message === "string") return [null, new Error(error.message)];
185
+ return [null, /* @__PURE__ */ new Error(`[${functionName}] Unexpected error`)];
186
+ }
187
+ const valueOrError = errorsWrapper;
188
+
189
+ //#endregion
190
+ //#region src/utilities/read-file.ts
191
+ async function safeReadFile(path, options) {
192
+ try {
193
+ return [await readFile(path, options), null];
194
+ } catch (error) {
195
+ return handleError(error, "readFile");
196
+ }
197
+ }
198
+ function safeReadFileSync(path, options) {
199
+ try {
200
+ return [readFileSync(path, options), null];
201
+ } catch (error) {
202
+ return handleError(error, "readFileSync");
203
+ }
204
+ }
205
+
206
+ //#endregion
207
+ //#region src/utilities/read-json-file.ts
208
+ /** Read a file and parse it as JSON safely. */
209
+ function readJsonFile(path, code) {
210
+ if (!code) {
211
+ const [fileString, readError] = safeReadFileSync(path, "utf8");
212
+ if (readError) return [null, readError];
213
+ code = fileString;
214
+ }
215
+ const [parsed, parseError] = valueOrError(json5.parse)(code);
216
+ if (parseError !== null) return [null, parseError];
217
+ return [parsed, null];
218
+ }
219
+
220
+ //#endregion
221
+ //#region src/resolver/get-aliases.ts
222
+ /** Gets path aliases from `tsconfig.json` */
223
+ function getPathAliases(root) {
224
+ const [tsconfig, tsconfigParseError] = readTsconfig(root);
225
+ if (tsconfigParseError !== null) return [null, tsconfigParseError];
226
+ const paths = tsconfig.paths ?? {};
227
+ const alias = {};
228
+ for (const key in paths) {
229
+ const aliasName = key.replace(/\*$/, "");
230
+ alias[aliasName] = paths[key][0].replace(/\*$/, "");
231
+ }
232
+ return [alias, null];
233
+ }
234
+ function readTsconfig(root) {
235
+ const tsconfigPath = join(root, "tsconfig.json");
236
+ const [tsconfig, tsconfigParseError] = readJsonFile(tsconfigPath);
237
+ if (tsconfigParseError !== null) return [null, tsconfigParseError];
238
+ if (!tsconfig.compilerOptions) return [null, /* @__PURE__ */ new Error("[readTsconfig] No compilerOptions found in tsconfig.json")];
239
+ return [tsconfig.compilerOptions, null];
240
+ }
241
+
242
+ //#endregion
243
+ //#region src/resolver/resolver.ts
244
+ const nodeModulesResolver = new ResolverFactory({
245
+ conditionNames: [
246
+ "browser",
247
+ "import",
248
+ "default"
249
+ ],
250
+ extensions: [
251
+ ".js",
252
+ ".json",
253
+ ".node",
254
+ ".css"
255
+ ],
256
+ symlinks: false
257
+ });
258
+ var Resolver = class Resolver {
259
+ root;
260
+ isProduction;
261
+ aliases = {};
262
+ notFound = /* @__PURE__ */ new Set();
263
+ files = /* @__PURE__ */ new Set();
264
+ directories = /* @__PURE__ */ new Set();
265
+ misses = /* @__PURE__ */ new Set();
266
+ /** Whether a source that resolves to a missing file is logged, once. The result says so either way. */
267
+ shouldWarnOnMissing;
268
+ static JS_EXTENSIONS = /* @__PURE__ */ new Set([
269
+ ".js",
270
+ ".mjs",
271
+ ".cjs",
272
+ ".jsx",
273
+ ".ts",
274
+ ".mts",
275
+ ".cts",
276
+ ".tsx"
277
+ ]);
278
+ static HTML_EXTENSIONS = /* @__PURE__ */ new Set([".html", ".md"]);
279
+ constructor(root, isProduction = false, configAliases = {}, shouldWarnOnMissing = true) {
280
+ this.root = root;
281
+ this.isProduction = isProduction;
282
+ this.shouldWarnOnMissing = shouldWarnOnMissing;
283
+ const [aliases] = getPathAliases(root);
284
+ this.aliases = {
285
+ ...aliases,
286
+ ...configAliases
287
+ };
288
+ }
289
+ resolve(sourceOrLink, filePath) {
290
+ if (!isValidRelativePath(sourceOrLink)) return;
291
+ const absFilePath = isAbsolute(filePath) ? filePath : join(this.root, filePath);
292
+ const [source, suffix] = splitHtmlLink(sourceOrLink);
293
+ if (isAbsolute(source)) return;
294
+ const isDirectory = suffix === "/";
295
+ const absSource = join(dirname(absFilePath), source);
296
+ const foundFile = this.findFile(absSource, isDirectory);
297
+ if (foundFile) return {
298
+ path: foundFile,
299
+ exists: true,
300
+ suffix
301
+ };
302
+ const sourceForAlias = suffix === "/" ? source + "/" : source;
303
+ const resolvedPathAlias = Resolver.resolvePathAlias(sourceForAlias, this.aliases);
304
+ if (resolvedPathAlias) {
305
+ const absSource = join(this.root, resolvedPathAlias);
306
+ const foundFile = this.findFile(absSource, isDirectory);
307
+ const isFileAlias = Object.hasOwn(this.aliases, sourceForAlias) && !sourceForAlias.endsWith("/");
308
+ if (!foundFile) this.#warnMissing(absSource.replace(/\/$/, ""), `[resolver] Source "${sourceOrLink}" found in "${filePath}" was resolved to "${resolvedPathAlias}", but the file is missing.`);
309
+ return {
310
+ path: foundFile ?? absSource,
311
+ exists: !!foundFile,
312
+ suffix,
313
+ isFileAlias,
314
+ isDirAlias: !isFileAlias
315
+ };
316
+ }
317
+ if (!source.startsWith(".")) {
318
+ const resolverResult = nodeModulesResolver.sync(this.root, source);
319
+ if (resolverResult.path) return {
320
+ path: resolverResult.path,
321
+ suffix,
322
+ exists: true,
323
+ isPackage: true
324
+ };
325
+ }
326
+ if (source.startsWith("./") || source.startsWith("../")) {
327
+ this.#warnMissing(absSource, `[resolver] Source "${sourceOrLink}" found in "${filePath}" points to a non-existent file.`);
328
+ return {
329
+ path: absSource,
330
+ suffix,
331
+ exists: false
332
+ };
333
+ }
334
+ }
335
+ /** Logs a missing file the first time it is resolved to, when the resolver is set to. */
336
+ #warnMissing(absSource, message) {
337
+ if (!this.shouldWarnOnMissing) return;
338
+ if (this.notFound.has(absSource)) return;
339
+ this.notFound.add(absSource);
340
+ Log.warn(message);
341
+ }
342
+ resolveAlias(source) {
343
+ return Resolver.resolvePathAlias(source, this.aliases);
344
+ }
345
+ normalize(filePath) {
346
+ return normalize(filePath);
347
+ }
348
+ static isFile(filePath) {
349
+ try {
350
+ return statSync(filePath).isFile();
351
+ } catch (error) {
352
+ const code = error.code;
353
+ if (code === "ENOENT" || code === "ENOTDIR") return false;
354
+ throw error;
355
+ }
356
+ }
357
+ /** Aliased path to path */
358
+ static resolvePathAlias(filePath, aliases) {
359
+ for (const [key, value] of Object.entries(aliases)) {
360
+ if (key.endsWith("/")) {
361
+ if (!filePath.startsWith(key)) continue;
362
+ return filePath.replace(key, () => value);
363
+ }
364
+ if (filePath === key) return value;
365
+ }
366
+ }
367
+ /** Path to aliased path */
368
+ static resolveAliasPath(filePath, aliases) {
369
+ let shortest;
370
+ for (const [key, value] of Object.entries(aliases)) {
371
+ if (key.endsWith("/")) {
372
+ if (!filePath.startsWith(value)) continue;
373
+ const aliased = filePath.replace(value, () => key);
374
+ if (!shortest || aliased.length < shortest.length) shortest = aliased;
375
+ continue;
376
+ }
377
+ if (filePath === value && (!shortest || key.length < shortest.length)) shortest = key;
378
+ }
379
+ return shortest ?? filePath;
380
+ }
381
+ /** Path to aliased path */
382
+ aliasPath(filePath) {
383
+ return Resolver.resolveAliasPath(filePath, this.aliases);
384
+ }
385
+ findFile(filePath, shouldCheckDirectory = false) {
386
+ const missKey = (shouldCheckDirectory ? "d:" : "f:") + filePath;
387
+ if (this.isProduction && this.misses.has(missKey)) return;
388
+ const found = this.#findFileUncached(filePath, shouldCheckDirectory);
389
+ if (found === void 0 && this.isProduction) this.misses.add(missKey);
390
+ return found;
391
+ }
392
+ #findFileUncached(filePath, shouldCheckDirectory) {
393
+ if (this.files.has(filePath)) return filePath;
394
+ if (Resolver.isFile(filePath)) {
395
+ this.files.add(filePath);
396
+ return filePath;
397
+ }
398
+ const extension = extname(filePath);
399
+ if (!extension) {
400
+ for (const candidateExtension of [...Resolver.JS_EXTENSIONS, ...Resolver.HTML_EXTENSIONS]) {
401
+ const candidate = replaceExtension(filePath, candidateExtension);
402
+ if (this.files.has(candidate)) return candidate;
403
+ if (Resolver.isFile(candidate)) {
404
+ this.files.add(candidate);
405
+ return candidate;
406
+ }
407
+ }
408
+ const withIndex = join(filePath, "index");
409
+ for (const candidateExtension of Resolver.HTML_EXTENSIONS) {
410
+ const candidate = replaceExtension(withIndex, candidateExtension);
411
+ if (this.files.has(candidate)) return candidate;
412
+ if (Resolver.isFile(candidate)) {
413
+ this.files.add(candidate);
414
+ return candidate;
415
+ }
416
+ }
417
+ if (shouldCheckDirectory) {
418
+ if (this.directories.has(filePath)) return filePath;
419
+ if (existsSync(filePath)) {
420
+ this.directories.add(filePath);
421
+ return filePath;
422
+ }
423
+ }
424
+ return;
425
+ }
426
+ if (Resolver.JS_EXTENSIONS.has(extension)) {
427
+ for (const jsExtension of Resolver.JS_EXTENSIONS) {
428
+ const candidate = replaceExtension(filePath, jsExtension);
429
+ if (Resolver.isFile(candidate)) {
430
+ this.files.add(candidate);
431
+ return candidate;
432
+ }
433
+ }
434
+ return;
435
+ }
436
+ }
437
+ };
438
+
439
+ //#endregion
440
+ //#region src/types/metadata.ts
441
+ const METADATA_TYPES = Object.freeze({
442
+ Script: "Script",
443
+ HTML: "Html",
444
+ Markdown: "Markdown",
445
+ CSS: "Style",
446
+ SVG: "Svg",
447
+ Package: "Package",
448
+ TextAsset: "TextAsset",
449
+ BinaryAsset: "BinaryAsset",
450
+ WebAppManifest: "WebAppManifest"
451
+ });
452
+
40
453
  //#endregion
41
454
  //#region src/utilities/metadata-utilities.ts
42
455
  function isScriptMetadata(metadata) {
@@ -84,7 +497,8 @@ function filterScriptMetadata(metadata) {
84
497
  for (const scriptTag of scriptTags) {
85
498
  const scriptId = scriptTag.getAttribute(CUSTOM_ATTRIBUTES.MetadataID);
86
499
  if (!scriptId) continue;
87
- if (!isScriptType(scriptTag.getAttribute("type"))) continue;
500
+ const scriptType = scriptTag.getAttribute("type");
501
+ if (!isScriptType(scriptType)) continue;
88
502
  const scriptMetadata = metadata.scriptsMetadataList.get(scriptId);
89
503
  if (!scriptMetadata) continue;
90
504
  result.push({
@@ -125,11 +539,6 @@ function filterStyleMetadata(metadata) {
125
539
  return result;
126
540
  }
127
541
 
128
- //#endregion
129
- //#region src/helpers/babel-fixed-imports.ts
130
- const generator = typeof _generator === "function" ? _generator : _generator.default;
131
- const traverse = typeof _traverse === "function" ? _traverse : _traverse.default;
132
-
133
542
  //#endregion
134
543
  //#region src/utilities/highlight-code.ts
135
544
  /** - Highlight code string for terminal */
@@ -156,7 +565,7 @@ function highlightCode(code, { lang = "ts", maxCodeLength = 170, maxLineLength =
156
565
  withNewLines += currentLine + "\n";
157
566
  }
158
567
  let highlighted = createEmphasize(common).highlight(lang, withNewLines.trim()).value;
159
- if (isTruncated) highlighted += "\n" + c.inverse(" ... ");
568
+ if (isTruncated) highlighted += "\n" + chalk.inverse(" ... ");
160
569
  if (!boxed) return highlighted;
161
570
  return boxen(highlighted, {
162
571
  padding: .5,
@@ -168,6 +577,7 @@ function highlightCode(code, { lang = "ts", maxCodeLength = 170, maxLineLength =
168
577
 
169
578
  //#endregion
170
579
  //#region src/utilities/print-formatted-error.ts
580
+ const generator = typeof _generator === "function" ? _generator : _generator.default;
171
581
  var PrintFormattedError = class PrintFormattedError {
172
582
  options = {};
173
583
  constructor(options = {}) {
@@ -191,9 +601,9 @@ var PrintFormattedError = class PrintFormattedError {
191
601
  Object.assign(options, item);
192
602
  }
193
603
  let message = "";
194
- if (options.filePath) message += c.italic(options.filePath) + "\n";
604
+ if (options.filePath) message += chalk.italic(options.filePath) + "\n";
195
605
  const functionName = options.function?.name ?? options.functionName;
196
- if (functionName) message += c.dim(`[${functionName}] `);
606
+ if (functionName) message += chalk.dim(`[${functionName}] `);
197
607
  message += messagesArray.join(" ");
198
608
  const codeFromNode = options.node && nodeToString(options.node);
199
609
  const code = options.code ?? codeFromNode?.code;
@@ -233,54 +643,6 @@ function nodeToString(node) {
233
643
  };
234
644
  }
235
645
 
236
- //#endregion
237
- //#region src/utilities/value-or-error.ts
238
- function errorsWrapper(function_) {
239
- return (...arguments_) => {
240
- try {
241
- const promiseOrValue = function_(...arguments_);
242
- if (isPromise(promiseOrValue)) return new Promise((resolve) => {
243
- promiseOrValue.then((value) => {
244
- resolve([value, null]);
245
- }).catch((error) => {
246
- resolve(handleError(error, function_.name));
247
- });
248
- });
249
- return [promiseOrValue, null];
250
- } catch (error) {
251
- return handleError(error, function_.name);
252
- }
253
- };
254
- }
255
- function isPromise(value) {
256
- return value && typeof value === "object" && "then" in value && typeof value.then === "function" && "catch" in value && typeof value.catch === "function";
257
- }
258
- function handleError(error, functionName = "") {
259
- if (!error) return [null, /* @__PURE__ */ new Error(`[${functionName}] Unexpected error`)];
260
- if (typeof error === "string") return [null, new Error(error)];
261
- if (error instanceof Error) return [null, error];
262
- if (typeof error === "object" && "message" in error && typeof error.message === "string") return [null, new Error(error.message)];
263
- return [null, /* @__PURE__ */ new Error(`[${functionName}] Unexpected error`)];
264
- }
265
- const valueOrError = errorsWrapper;
266
-
267
- //#endregion
268
- //#region src/utilities/read-file.ts
269
- async function safeReadFile(path, options) {
270
- try {
271
- return [await readFile(path, options), null];
272
- } catch (error) {
273
- return handleError(error, "readFile");
274
- }
275
- }
276
- function safeReadFileSync(path, options) {
277
- try {
278
- return [readFileSync(path, options), null];
279
- } catch (error) {
280
- return handleError(error, "readFileSync");
281
- }
282
- }
283
-
284
646
  //#endregion
285
647
  //#region src/utilities/utilities.ts
286
648
  /** `process.stdout.write` */
@@ -289,10 +651,9 @@ function print(...input) {
289
651
  }
290
652
  /** - Clear the line in the terminal */
291
653
  function clearLn() {
292
- if ("clearLine" in process.stdout && typeof process.stdout.clearLine === "function") {
293
- process.stdout.clearLine(0);
294
- process.stdout.cursorTo(0);
295
- }
654
+ if (!("clearLine" in process.stdout && typeof process.stdout.clearLine === "function")) return;
655
+ process.stdout.clearLine(0);
656
+ process.stdout.cursorTo(0);
296
657
  }
297
658
  /** Used to assign a computed value to a variable */
298
659
  function assign(function_) {
@@ -405,7 +766,7 @@ function hashContent(content) {
405
766
  }
406
767
  const matchHtmlRegExp = /["'&<>]/;
407
768
  function escapeHtml(input) {
408
- const string = "" + input;
769
+ const string = input;
409
770
  const match = matchHtmlRegExp.exec(string);
410
771
  if (!match) return string;
411
772
  let escape;
@@ -439,47 +800,5 @@ function escapeHtml(input) {
439
800
  }
440
801
 
441
802
  //#endregion
442
- //#region src/helpers/dependency-tracker.ts
443
- /**
444
- * Tracks bidirectional dependencies between importers and their sources.\
445
- * Handles reconciliation when dependencies change, so stale entries are automatically removed when an importer stops referencing
446
- * a source.
447
- */
448
- var DependencyTracker = class {
449
- /** Source → Set of importers that depend on it */
450
- #sourcesToImporters = /* @__PURE__ */ new Map();
451
- /** Importer → Set of sources it depends on */
452
- #importerToSources = /* @__PURE__ */ new Map();
453
- /** Updates the full set of sources for a given importer, reconciling any stale entries from previous calls. */
454
- update(importer, sources) {
455
- const nextSources = new Set(sources);
456
- const previousSources = this.#importerToSources.get(importer) ?? /* @__PURE__ */ new Set();
457
- for (const source of previousSources) if (!nextSources.has(source)) this.#sourcesToImporters.get(source)?.delete(importer);
458
- for (const source of nextSources) {
459
- if (!this.#sourcesToImporters.has(source)) this.#sourcesToImporters.set(source, /* @__PURE__ */ new Set());
460
- this.#sourcesToImporters.get(source).add(importer);
461
- }
462
- this.#importerToSources.set(importer, nextSources);
463
- }
464
- /** Deletes all dependency data for a given id, whether it's acting as an importer, a source, or both (e.g. on file unlink). */
465
- delete(id) {
466
- this.#sourcesToImporters.delete(id);
467
- const sources = this.#importerToSources.get(id);
468
- if (sources) {
469
- for (const source of sources) this.#sourcesToImporters.get(source)?.delete(id);
470
- this.#importerToSources.delete(id);
471
- }
472
- }
473
- /** Returns all importers that depend on a given source, or an empty set. */
474
- getImporters(source) {
475
- return this.#sourcesToImporters.get(source) ?? /* @__PURE__ */ new Set();
476
- }
477
- /** Returns all sources that a given importer depends on, or an empty set. */
478
- getSources(importer) {
479
- return this.#importerToSources.get(importer) ?? /* @__PURE__ */ new Set();
480
- }
481
- };
482
-
483
- //#endregion
484
- export { isHtmlMetadata as A, 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, kebabToCamelCase as _, capitalize as a, safeReadFile as b, cloneObject as c, getLineColumn as d, hashContent as f, isURL as g, isObject as h, camelCaseToKebabCase as i, isMarkdownMetadata as j, isBinaryAssetMetadata as k, downloadContent as l, isDefined as m, assign as n, clamp as o, humanReadableBytes as p, bytesToKB as r, clearLn as s, DependencyTracker as t, escapeHtml as u, mergeMaps as v, printFmtError as w, safeReadFileSync as x, print as y, METADATA_TYPES as z };
485
- //# sourceMappingURL=dependency-tracker-BuZfopIj.mjs.map
803
+ export { isTextAssetMetadata as A, checkJsonObject as B, isBinaryAssetMetadata as C, isScriptMetadata as D, isPackageMetadata as E, safeReadFile as F, isTypeScriptScript as G, isEmptyElement as H, safeReadFileSync as I, isHtmlLink as J, TYPESCRIPT_TYPE as K, handleError as L, METADATA_TYPES as M, Resolver as N, isStyleMetadata as O, readJsonFile as P, valueOrError as R, filterStyleMetadata as S, isMarkdownMetadata as T, isJavaScript as U, isDynamic as V, isJsonObject as W, splitHtmlLink as X, isValidRelativePath as Y, DependencyTracker as Z, 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, isWebManifestMetadata as j, isSvgMetadata as k, escapeHtml as l, isObject as m, bytesToKB as n, clearLn as o, isDefined as p, isScriptType as q, camelCaseToKebabCase as r, cloneObject as s, assign as t, getLineColumn as u, print as v, isHtmlMetadata as w, filterScriptMetadata as x, PrintFormattedError as y, checkFileExists as z };
804
+ //# sourceMappingURL=utilities-jK4uUZBV.mjs.map