@mui/internal-docs-infra 0.2.0-alpha.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/esm/CodeHighlighter/CodeHighlighter.js +54 -39
  2. package/esm/CodeHighlighter/CodeHighlighterClient.js +77 -33
  3. package/esm/CodeHighlighter/errors.js +1 -1
  4. package/esm/CodeHighlighter/loadFallbackCode.js +6 -2
  5. package/esm/CodeHighlighter/loadVariant.js +64 -22
  6. package/esm/CodeHighlighter/maybeInitialData.d.ts +2 -2
  7. package/esm/CodeHighlighter/maybeInitialData.js +2 -2
  8. package/esm/CodeHighlighter/transformSource.js +57 -17
  9. package/esm/CodeHighlighter/types.d.ts +20 -3
  10. package/esm/abstractCreateDemo/abstractCreateDemo.d.ts +4 -2
  11. package/esm/abstractCreateDemo/abstractCreateDemo.js +2 -1
  12. package/esm/pipeline/hastUtils/hastUtils.d.ts +6 -0
  13. package/esm/pipeline/hastUtils/hastUtils.js +20 -0
  14. package/esm/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.d.ts +3 -1
  15. package/esm/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.js +2 -1
  16. package/esm/pipeline/loadPrecomputedCodeHighlighter/parseCreateFactoryCall.d.ts +6 -4
  17. package/esm/pipeline/loadPrecomputedCodeHighlighter/parseCreateFactoryCall.js +443 -258
  18. package/esm/pipeline/loadServerSource/loadServerSource.js +59 -19
  19. package/esm/pipeline/loaderUtils/index.d.ts +1 -1
  20. package/esm/pipeline/loaderUtils/index.js +1 -1
  21. package/esm/pipeline/loaderUtils/parseImportsAndComments.d.ts +91 -0
  22. package/esm/pipeline/loaderUtils/parseImportsAndComments.js +1329 -0
  23. package/esm/pipeline/loaderUtils/processRelativeImports.d.ts +8 -3
  24. package/esm/pipeline/loaderUtils/processRelativeImports.js +237 -118
  25. package/esm/pipeline/loaderUtils/resolveModulePath.d.ts +7 -3
  26. package/esm/pipeline/loaderUtils/resolveModulePath.js +3 -3
  27. package/esm/pipeline/loaderUtils/resolveModulePathWithFs.d.ts +4 -0
  28. package/esm/pipeline/loaderUtils/rewriteImports.d.ts +12 -5
  29. package/esm/pipeline/loaderUtils/rewriteImports.js +56 -26
  30. package/esm/pipeline/transformHtmlCodePrecomputed/index.d.ts +2 -0
  31. package/esm/pipeline/transformHtmlCodePrecomputed/index.js +4 -0
  32. package/esm/pipeline/transformHtmlCodePrecomputed/transformHtmlCodePrecomputed.d.ts +13 -0
  33. package/esm/pipeline/transformHtmlCodePrecomputed/transformHtmlCodePrecomputed.js +415 -0
  34. package/esm/pipeline/transformMarkdownCode/transformMarkdownCode.js +304 -47
  35. package/esm/useCode/Pre.js +5 -0
  36. package/esm/useCode/useFileNavigation.js +4 -0
  37. package/esm/withDocsInfra/withDocsInfra.d.ts +12 -1
  38. package/esm/withDocsInfra/withDocsInfra.js +34 -6
  39. package/package.json +6 -4
  40. package/esm/pipeline/loaderUtils/parseImports.d.ts +0 -19
  41. package/esm/pipeline/loaderUtils/parseImports.js +0 -306
  42. package/esm/pipeline/transformHtmlCode/index.d.ts +0 -2
  43. package/esm/pipeline/transformHtmlCode/index.js +0 -4
  44. package/esm/pipeline/transformHtmlCode/transformHtmlCode.d.ts +0 -13
  45. package/esm/pipeline/transformHtmlCode/transformHtmlCode.js +0 -300
@@ -0,0 +1,1329 @@
1
+ import _regenerator from "@babel/runtime/helpers/esm/regenerator";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
3
+ import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
4
+ import _extends from "@babel/runtime/helpers/esm/extends";
5
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
6
+ // webpack does not like node: imports
7
+ // eslint-disable-next-line n/prefer-node-protocol
8
+ import path from 'path';
9
+
10
+ /**
11
+ * Represents a single import name with its properties.
12
+ */
13
+
14
+ /**
15
+ * Represents the position of an import path in the source code.
16
+ */
17
+
18
+ /**
19
+ * Represents an import from a relative path (starts with ./ or ../).
20
+ */
21
+
22
+ /**
23
+ * Represents an import from an external package (node_modules).
24
+ */
25
+
26
+ /**
27
+ * The result of parsing import statements from source code.
28
+ */
29
+
30
+ /**
31
+ * Checks if a character starts a string literal.
32
+ * @param ch - The character to check
33
+ * @param withinMdx - Whether we're parsing within an MDX file (affects quote handling)
34
+ * @returns True if the character starts a string literal
35
+ */
36
+ function isStringStart(ch, withinMdx) {
37
+ if (withinMdx) {
38
+ // quotes in MDX don't create strings
39
+ return ch === '`';
40
+ }
41
+ return ch === '"' || ch === "'" || ch === '`';
42
+ }
43
+
44
+ /**
45
+ * Checks if a comment matches any of the specified prefixes for removal.
46
+ * @param commentText - The full comment text including comment markers
47
+ * @param removeCommentsWithPrefix - Array of prefixes to match against
48
+ * @returns True if the comment starts with any of the specified prefixes
49
+ */
50
+ function matchesCommentPrefix(commentText, removeCommentsWithPrefix) {
51
+ return removeCommentsWithPrefix.some(function (prefix) {
52
+ // For single-line comments, check after the //
53
+ if (commentText.startsWith('//')) {
54
+ var content = commentText.slice(2).trim();
55
+ return content.startsWith(prefix);
56
+ }
57
+ // For multi-line comments, check after the /*
58
+ if (commentText.startsWith('/*')) {
59
+ var _content = commentText.slice(2, -2).trim();
60
+ return _content.startsWith(prefix);
61
+ }
62
+ return false;
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Removes comment markers from comment text and returns the content as an array of lines.
68
+ * @param commentText - The full comment text including markers
69
+ * @returns Array of comment content lines with markers removed and whitespace trimmed
70
+ */
71
+ function stripCommentMarkers(commentText) {
72
+ // For single-line comments, remove // and trim, return as single-item array
73
+ if (commentText.startsWith('//')) {
74
+ return [commentText.slice(2).trim()];
75
+ }
76
+ // For multi-line comments, remove /* and */, split by lines, and trim each line
77
+ if (commentText.startsWith('/*') && commentText.endsWith('*/')) {
78
+ var content = commentText.slice(2, -2);
79
+ return content.split('\n').map(function (line) {
80
+ return line.trim();
81
+ }).filter(function (line) {
82
+ return line !== '';
83
+ });
84
+ }
85
+ // Fallback: return as single-item array if format is unexpected
86
+ return [commentText];
87
+ }
88
+
89
+ /**
90
+ * Counts consecutive backticks starting at a given position (used for MDX code blocks).
91
+ * @param sourceText - The source text to scan
92
+ * @param startPos - The position to start counting from
93
+ * @returns The number of consecutive backticks found
94
+ */
95
+ function countBackticks(sourceText, startPos) {
96
+ var count = 0;
97
+ var pos = startPos;
98
+ while (pos < sourceText.length && sourceText[pos] === '`') {
99
+ count += 1;
100
+ pos += 1;
101
+ }
102
+ return count;
103
+ }
104
+
105
+ /**
106
+ * Generic function to scan source code character-by-character, finding import statements
107
+ * while correctly handling strings, comments, and template literals. Optionally processes
108
+ * comments for removal and collection.
109
+ *
110
+ * @param sourceCode - The source code to scan
111
+ * @param importDetector - Function that detects import statements at a given position
112
+ * @param isMdxFile - Whether this is an MDX file (affects string and code block handling)
113
+ * @param removeCommentsWithPrefix - Optional array of prefixes for comments to remove
114
+ * @param notableCommentsPrefix - Optional array of prefixes for comments to collect
115
+ * @returns Object containing found import statements and optionally processed code/comments
116
+ */
117
+ function scanForImports(sourceCode, importDetector, isMdxFile, removeCommentsWithPrefix, notableCommentsPrefix) {
118
+ var statements = [];
119
+ var comments = {};
120
+ var shouldProcessComments = !!(removeCommentsWithPrefix || notableCommentsPrefix);
121
+ var result = shouldProcessComments ? '' : sourceCode;
122
+
123
+ // Position mapping from original source to processed source (after comment removal)
124
+ var positionMapping = new Map();
125
+ var processedPos = 0;
126
+
127
+ // Helper to check if a comment matches notable prefix
128
+ var matchesNotablePrefix = function matchesNotablePrefix(commentText) {
129
+ if (!notableCommentsPrefix || notableCommentsPrefix.length === 0) {
130
+ return false; // If no notable prefix specified, don't match any comments as notable
131
+ }
132
+ return notableCommentsPrefix.some(function (prefix) {
133
+ if (commentText.startsWith('//')) {
134
+ var content = commentText.slice(2).trim();
135
+ return content.startsWith(prefix);
136
+ }
137
+ if (commentText.startsWith('/*')) {
138
+ var _content2 = commentText.slice(2, -2).trim();
139
+ return _content2.startsWith(prefix);
140
+ }
141
+ return false;
142
+ });
143
+ };
144
+ var i = 0;
145
+ var outputLine = 0; // Line number in output code after comment removal
146
+ var len = sourceCode.length;
147
+ var state = 'code';
148
+ var stringQuote = null;
149
+ var codeblockBacktickCount = 0; // Track how many backticks opened the current code block
150
+ // Comment stripping variables
151
+ var commentStart = 0;
152
+ var commentStartOutputLine = 0;
153
+ var lineStartPos = 0;
154
+ var preCommentContent = '';
155
+ while (i < len) {
156
+ var ch = sourceCode[i];
157
+ var next = sourceCode[i + 1];
158
+ if (state === 'code') {
159
+ // Track line numbers for newlines in code
160
+ if (ch === '\n') {
161
+ if (shouldProcessComments) {
162
+ result += ch;
163
+ processedPos += 1;
164
+ }
165
+ outputLine += 1;
166
+ lineStartPos = i + 1;
167
+ i += 1;
168
+ continue;
169
+ }
170
+
171
+ // Check for backtick sequences (3 or more backticks start code blocks in MDX)
172
+ if (isMdxFile && ch === '`') {
173
+ // Count consecutive backticks
174
+ var backtickCount = countBackticks(sourceCode, i);
175
+ if (backtickCount >= 3) {
176
+ state = 'codeblock';
177
+ codeblockBacktickCount = backtickCount;
178
+ if (shouldProcessComments) {
179
+ result += sourceCode.slice(i, i + backtickCount);
180
+ }
181
+ i += backtickCount;
182
+ continue;
183
+ }
184
+ }
185
+ // Start of single-line comment
186
+ if (ch === '/' && next === '/') {
187
+ if (shouldProcessComments) {
188
+ commentStart = i;
189
+ commentStartOutputLine = outputLine;
190
+ // Remove content that was already added to result for this line
191
+ var contentSinceLineStart = sourceCode.slice(lineStartPos, commentStart);
192
+ result = result.slice(0, result.length - contentSinceLineStart.length);
193
+ preCommentContent = contentSinceLineStart;
194
+ }
195
+ state = 'singleline-comment';
196
+ i += 2;
197
+ continue;
198
+ }
199
+ // Start of multi-line comment
200
+ if (ch === '/' && next === '*') {
201
+ if (shouldProcessComments) {
202
+ commentStart = i;
203
+ commentStartOutputLine = outputLine;
204
+ // Remove content that was already added to result for this line
205
+ var _contentSinceLineStart = sourceCode.slice(lineStartPos, commentStart);
206
+ result = result.slice(0, result.length - _contentSinceLineStart.length);
207
+ preCommentContent = _contentSinceLineStart;
208
+ }
209
+ state = 'multiline-comment';
210
+ i += 2;
211
+ continue;
212
+ }
213
+ // Start of string
214
+ if (isStringStart(ch, isMdxFile)) {
215
+ state = ch === '`' ? 'template' : 'string';
216
+ stringQuote = ch;
217
+ if (shouldProcessComments) {
218
+ result += ch;
219
+ }
220
+ i += 1;
221
+ continue;
222
+ }
223
+
224
+ // Update position mapping for current position
225
+ if (shouldProcessComments) {
226
+ positionMapping.set(i, processedPos);
227
+ }
228
+
229
+ // Create position mapper function
230
+ var positionMapper = function positionMapper(originalPos) {
231
+ if (!shouldProcessComments) {
232
+ return originalPos; // No comment processing, positions are unchanged
233
+ }
234
+ // Find the closest mapped position
235
+ var closest = 0;
236
+ positionMapping.forEach(function (procPos, origPos) {
237
+ if (origPos <= originalPos && origPos > closest) {
238
+ closest = origPos;
239
+ }
240
+ });
241
+ var offset = originalPos - closest;
242
+ return (positionMapping.get(closest) || 0) + offset;
243
+ };
244
+
245
+ // Use the provided import detector on the original source code
246
+ var detection = importDetector(sourceCode, i, positionMapper);
247
+ if (detection.found) {
248
+ if (detection.statement) {
249
+ statements.push(detection.statement);
250
+ }
251
+ // Copy the detected import to result if we're building one
252
+ if (shouldProcessComments) {
253
+ var importText = sourceCode.slice(i, detection.nextPos);
254
+ result += importText;
255
+ processedPos += importText.length;
256
+ }
257
+ i = detection.nextPos;
258
+ continue;
259
+ }
260
+ if (shouldProcessComments) {
261
+ result += ch;
262
+ processedPos += 1;
263
+ }
264
+ i += 1;
265
+ continue;
266
+ }
267
+ if (state === 'singleline-comment') {
268
+ if (ch === '\n') {
269
+ if (shouldProcessComments) {
270
+ // End of single-line comment
271
+ var commentText = sourceCode.slice(commentStart, i);
272
+ var shouldStrip = removeCommentsWithPrefix && matchesCommentPrefix(commentText, removeCommentsWithPrefix);
273
+ var isNotable = matchesNotablePrefix(commentText);
274
+
275
+ // Collect comments if they're notable (all stripped comments when no prefix specified, or notable comments when prefix specified)
276
+ var shouldCollect = shouldStrip && !notableCommentsPrefix || isNotable;
277
+ if (shouldCollect) {
278
+ var _comments$commentStar;
279
+ if (!comments[commentStartOutputLine]) {
280
+ comments[commentStartOutputLine] = [];
281
+ }
282
+ (_comments$commentStar = comments[commentStartOutputLine]).push.apply(_comments$commentStar, _toConsumableArray(stripCommentMarkers(commentText)));
283
+ }
284
+ if (shouldStrip) {
285
+ // Check if comment is the only thing on its line (ignoring whitespace)
286
+ var isCommentOnlyLine = preCommentContent.trim() === '';
287
+ if (isCommentOnlyLine) {
288
+ // Don't add the pre-comment content or newline for comment-only lines
289
+ // Skip the newline entirely
290
+ } else {
291
+ // Comment is inline, keep the pre-comment content and newline
292
+ result += preCommentContent;
293
+ result += '\n';
294
+ outputLine += 1;
295
+ }
296
+ } else {
297
+ // Keep the comment and newline
298
+ result += preCommentContent;
299
+ result += commentText;
300
+ result += '\n';
301
+ outputLine += 1;
302
+ }
303
+ preCommentContent = '';
304
+ lineStartPos = i + 1;
305
+ }
306
+ state = 'code';
307
+ }
308
+ i += 1;
309
+ continue;
310
+ }
311
+ if (state === 'multiline-comment') {
312
+ if (ch === '*' && next === '/') {
313
+ if (shouldProcessComments) {
314
+ // End of multi-line comment
315
+ var _commentText = sourceCode.slice(commentStart, i + 2);
316
+ var _shouldStrip = removeCommentsWithPrefix && matchesCommentPrefix(_commentText, removeCommentsWithPrefix);
317
+ var _isNotable = matchesNotablePrefix(_commentText);
318
+
319
+ // Collect comments if they're notable (all stripped comments when no prefix specified, or notable comments when prefix specified)
320
+ var _shouldCollect = _shouldStrip && !notableCommentsPrefix || _isNotable;
321
+ if (_shouldCollect) {
322
+ var _comments$commentStar2;
323
+ if (!comments[commentStartOutputLine]) {
324
+ comments[commentStartOutputLine] = [];
325
+ }
326
+ (_comments$commentStar2 = comments[commentStartOutputLine]).push.apply(_comments$commentStar2, _toConsumableArray(stripCommentMarkers(_commentText)));
327
+ }
328
+ if (_shouldStrip) {
329
+ // Find the end of the comment and check what's after
330
+ var afterCommentPos = i + 2;
331
+ var afterCommentContent = '';
332
+ var nextNewlinePos = sourceCode.indexOf('\n', afterCommentPos);
333
+ if (nextNewlinePos === -1) {
334
+ nextNewlinePos = sourceCode.length;
335
+ }
336
+ afterCommentContent = sourceCode.slice(afterCommentPos, nextNewlinePos).trim();
337
+ var isCommentOnlyLines = preCommentContent.trim() === '' && afterCommentContent === '';
338
+ if (isCommentOnlyLines) {
339
+ // Skip the entire comment and everything up to and including the next newline
340
+ i = nextNewlinePos;
341
+ if (i < len && sourceCode[i] === '\n') {
342
+ // Skip the newline entirely - advance to the character after it
343
+ i += 1;
344
+ lineStartPos = i;
345
+ } else {
346
+ lineStartPos = i;
347
+ }
348
+ state = 'code';
349
+ preCommentContent = '';
350
+ continue;
351
+ } else {
352
+ // Comment is inline or mixed with code, add pre-comment content
353
+ result += preCommentContent;
354
+ i += 2;
355
+ }
356
+ } else {
357
+ // Keep the comment - add pre-comment content and comment
358
+ result += preCommentContent;
359
+ result += _commentText;
360
+ // Count newlines in the kept comment to update output line
361
+ var newlineCount = (_commentText.match(/\n/g) || []).length;
362
+ outputLine += newlineCount;
363
+ i += 2;
364
+ }
365
+ preCommentContent = '';
366
+ } else {
367
+ i += 2;
368
+ }
369
+ state = 'code';
370
+ continue;
371
+ }
372
+ i += 1;
373
+ continue;
374
+ }
375
+ if (state === 'string') {
376
+ if (ch === '\n') {
377
+ outputLine += 1;
378
+ lineStartPos = i + 1;
379
+ }
380
+ if (ch === '\\\\') {
381
+ if (shouldProcessComments) {
382
+ result += sourceCode.slice(i, i + 2);
383
+ }
384
+ i += 2;
385
+ continue;
386
+ }
387
+ if (ch === stringQuote) {
388
+ state = 'code';
389
+ stringQuote = null;
390
+ }
391
+ if (shouldProcessComments) {
392
+ result += ch;
393
+ }
394
+ i += 1;
395
+ continue;
396
+ }
397
+ if (state === 'template') {
398
+ if (ch === '\n') {
399
+ outputLine += 1;
400
+ lineStartPos = i + 1;
401
+ }
402
+ if (ch === '`') {
403
+ state = 'code';
404
+ stringQuote = null;
405
+ if (shouldProcessComments) {
406
+ result += ch;
407
+ }
408
+ i += 1;
409
+ continue;
410
+ }
411
+ if (ch === '\\\\') {
412
+ if (shouldProcessComments) {
413
+ result += sourceCode.slice(i, i + 2);
414
+ }
415
+ i += 2;
416
+ continue;
417
+ }
418
+ if (shouldProcessComments) {
419
+ result += ch;
420
+ }
421
+ i += 1;
422
+ continue;
423
+ }
424
+ if (state === 'codeblock') {
425
+ if (ch === '\n') {
426
+ outputLine += 1;
427
+ lineStartPos = i + 1;
428
+ }
429
+ // Look for closing backticks that match or exceed the opening count
430
+ if (ch === '`') {
431
+ var closingBacktickCount = countBackticks(sourceCode, i);
432
+ if (closingBacktickCount >= codeblockBacktickCount) {
433
+ state = 'code';
434
+ codeblockBacktickCount = 0;
435
+ if (shouldProcessComments) {
436
+ result += sourceCode.slice(i, i + closingBacktickCount);
437
+ }
438
+ i += closingBacktickCount;
439
+ continue;
440
+ }
441
+ }
442
+ if (shouldProcessComments) {
443
+ result += ch;
444
+ }
445
+ i += 1;
446
+ continue;
447
+ }
448
+ if (shouldProcessComments) {
449
+ result += ch;
450
+ }
451
+ i += 1;
452
+ }
453
+
454
+ // Handle case where file ends with a comment
455
+ if (shouldProcessComments && (state === 'singleline-comment' || state === 'multiline-comment')) {
456
+ var _commentText2 = sourceCode.slice(commentStart);
457
+ var _shouldStrip2 = removeCommentsWithPrefix && matchesCommentPrefix(_commentText2, removeCommentsWithPrefix);
458
+ var _isNotable2 = matchesNotablePrefix(_commentText2);
459
+
460
+ // Collect comments if they're notable (all stripped comments when no prefix specified, or notable comments when prefix specified)
461
+ var _shouldCollect2 = _shouldStrip2 && !notableCommentsPrefix || _isNotable2;
462
+ if (_shouldCollect2) {
463
+ var _comments$commentStar3;
464
+ if (!comments[commentStartOutputLine]) {
465
+ comments[commentStartOutputLine] = [];
466
+ }
467
+ (_comments$commentStar3 = comments[commentStartOutputLine]).push.apply(_comments$commentStar3, _toConsumableArray(stripCommentMarkers(_commentText2)));
468
+ }
469
+ if (!_shouldStrip2) {
470
+ result += _commentText2;
471
+ }
472
+ }
473
+
474
+ // Create the final position mapper for return
475
+ var finalPositionMapper = function finalPositionMapper(originalPos) {
476
+ if (!shouldProcessComments) {
477
+ return originalPos; // No comment processing, positions are unchanged
478
+ }
479
+ // Find the closest mapped position
480
+ var closest = 0;
481
+ positionMapping.forEach(function (procPos, origPos) {
482
+ if (origPos <= originalPos && origPos > closest) {
483
+ closest = origPos;
484
+ }
485
+ });
486
+ var offset = originalPos - closest;
487
+ return (positionMapping.get(closest) || 0) + offset;
488
+ };
489
+ return _extends({
490
+ statements: statements
491
+ }, shouldProcessComments && {
492
+ code: result,
493
+ comments: comments,
494
+ positionMapper: finalPositionMapper
495
+ });
496
+ }
497
+
498
+ /**
499
+ * Adds an import name to the target array if it doesn't already exist.
500
+ * @param target - The array of import names to add to
501
+ * @param name - The name of the import
502
+ * @param type - The type of import (default, named, or namespace)
503
+ * @param alias - Optional alias for the import
504
+ * @param isType - Whether this is a TypeScript type-only import
505
+ */
506
+ function addImportName(target, name, type, alias, isType) {
507
+ var existing = target.find(function (n) {
508
+ return n.name === name && n.type === type && n.alias === alias;
509
+ });
510
+ if (!existing) {
511
+ target.push(_extends(_extends({
512
+ name: name
513
+ }, alias && {
514
+ alias: alias
515
+ }), {}, {
516
+ type: type
517
+ }, isType && {
518
+ isType: true
519
+ }));
520
+ }
521
+ }
522
+
523
+ /**
524
+ * Checks if a character is a valid JavaScript identifier character.
525
+ * @param ch - The character to check
526
+ * @returns True if the character can be part of a JavaScript identifier
527
+ */
528
+ function isIdentifierChar(ch) {
529
+ return /[a-zA-Z0-9_$]/.test(ch);
530
+ }
531
+
532
+ /**
533
+ * Checks if a character is whitespace.
534
+ * @param ch - The character to check
535
+ * @returns True if the character is whitespace
536
+ */
537
+ function isWhitespace(ch) {
538
+ return /\s/.test(ch);
539
+ }
540
+
541
+ /**
542
+ * Skips whitespace characters and returns the next non-whitespace position.
543
+ * @param text - The text to scan
544
+ * @param start - The starting position
545
+ * @returns The position of the next non-whitespace character
546
+ */
547
+ function skipWhitespace(text, start) {
548
+ var pos = start;
549
+ while (pos < text.length && isWhitespace(text[pos])) {
550
+ pos += 1;
551
+ }
552
+ return pos;
553
+ }
554
+
555
+ /**
556
+ * Reads a JavaScript identifier starting at the given position.
557
+ * @param text - The text to read from
558
+ * @param start - The starting position
559
+ * @returns Object containing the identifier name and the next position
560
+ */
561
+ function readIdentifier(text, start) {
562
+ var pos = start;
563
+ var name = '';
564
+
565
+ // First character must be letter, underscore, or dollar sign
566
+ if (pos < text.length && /[a-zA-Z_$]/.test(text[pos])) {
567
+ name += text[pos];
568
+ pos += 1;
569
+
570
+ // Subsequent characters can be letters, digits, underscore, or dollar sign
571
+ while (pos < text.length && isIdentifierChar(text[pos])) {
572
+ name += text[pos];
573
+ pos += 1;
574
+ }
575
+ }
576
+ return {
577
+ name: name,
578
+ nextPos: pos
579
+ };
580
+ }
581
+
582
+ // Helper function to read a quoted string starting at position
583
+ function readQuotedString(text, start) {
584
+ var quote = text[start];
585
+ var pos = start + 1;
586
+ var value = '';
587
+ var pathStart = start; // Start at the opening quote
588
+
589
+ while (pos < text.length) {
590
+ var ch = text[pos];
591
+ if (ch === '\\' && pos + 1 < text.length) {
592
+ // Skip escaped character
593
+ pos += 2;
594
+ continue;
595
+ }
596
+ if (ch === quote) {
597
+ var pathEnd = pos + 1; // End after the closing quote
598
+ pos += 1;
599
+ return {
600
+ value: value,
601
+ nextPos: pos,
602
+ pathStart: pathStart,
603
+ pathEnd: pathEnd
604
+ };
605
+ }
606
+ value += ch;
607
+ pos += 1;
608
+ }
609
+
610
+ // If we reach here, no closing quote was found - fallback
611
+ return {
612
+ value: value,
613
+ nextPos: pos,
614
+ pathStart: pathStart,
615
+ pathEnd: pos
616
+ };
617
+ }
618
+
619
+ // Helper function to parse named imports from a brace-enclosed section
620
+ function parseNamedImports(text, start, end) {
621
+ var imports = [];
622
+ var pos = start;
623
+ while (pos < end) {
624
+ pos = skipWhitespace(text, pos);
625
+ if (pos >= end) {
626
+ break;
627
+ }
628
+
629
+ // Handle comments within named imports
630
+ if (pos + 1 < end && text[pos] === '/' && text[pos + 1] === '/') {
631
+ // Skip single-line comment
632
+ while (pos < end && text[pos] !== '\n') {
633
+ pos += 1;
634
+ }
635
+ continue;
636
+ }
637
+ if (pos + 1 < end && text[pos] === '/' && text[pos + 1] === '*') {
638
+ // Skip multi-line comment
639
+ pos += 2;
640
+ while (pos + 1 < end) {
641
+ if (text[pos] === '*' && text[pos + 1] === '/') {
642
+ pos += 2;
643
+ break;
644
+ }
645
+ pos += 1;
646
+ }
647
+ continue;
648
+ }
649
+
650
+ // Skip comma if we encounter it
651
+ if (text[pos] === ',') {
652
+ pos += 1;
653
+ continue;
654
+ }
655
+
656
+ // Check for 'type' keyword
657
+ var isTypeImport = false;
658
+ if (text.slice(pos, pos + 4) === 'type' && !isIdentifierChar(text[pos + 4] || '')) {
659
+ isTypeImport = true;
660
+ pos += 4;
661
+ pos = skipWhitespace(text, pos);
662
+ }
663
+
664
+ // Read the import name
665
+ var _readIdentifier = readIdentifier(text, pos),
666
+ name = _readIdentifier.name,
667
+ nextPos = _readIdentifier.nextPos;
668
+ if (!name) {
669
+ pos += 1;
670
+ continue;
671
+ }
672
+ pos = nextPos;
673
+ pos = skipWhitespace(text, pos);
674
+
675
+ // Check for 'as' keyword (alias)
676
+ var alias = void 0;
677
+ if (text.slice(pos, pos + 2) === 'as' && !isIdentifierChar(text[pos + 2] || '')) {
678
+ pos += 2;
679
+ pos = skipWhitespace(text, pos);
680
+ var aliasResult = readIdentifier(text, pos);
681
+ alias = aliasResult.name;
682
+ pos = aliasResult.nextPos;
683
+ pos = skipWhitespace(text, pos);
684
+ }
685
+ imports.push(_extends(_extends({
686
+ name: name
687
+ }, alias && {
688
+ alias: alias
689
+ }), isTypeImport && {
690
+ isType: true
691
+ }));
692
+
693
+ // Skip comma if present
694
+ if (text[pos] === ',') {
695
+ pos += 1;
696
+ }
697
+ }
698
+ return imports;
699
+ }
700
+
701
+ // Function to parse a single CSS @import statement
702
+ function parseCssImportStatement(cssCode, start) {
703
+ var pos = start + 7; // Skip '@import'
704
+ var len = cssCode.length;
705
+
706
+ // Skip whitespace
707
+ while (pos < len && /\s/.test(cssCode[pos])) {
708
+ pos += 1;
709
+ }
710
+ var modulePath = null;
711
+ var pathStart;
712
+ var pathEnd;
713
+
714
+ // Check for url() syntax
715
+ if (cssCode.slice(pos, pos + 4) === 'url(') {
716
+ pos += 4;
717
+ // Skip whitespace
718
+ while (pos < len && /\s/.test(cssCode[pos])) {
719
+ pos += 1;
720
+ }
721
+
722
+ // Read the URL (quoted or unquoted)
723
+ if (pos < len && (cssCode[pos] === '"' || cssCode[pos] === "'")) {
724
+ var quote = cssCode[pos];
725
+ pathStart = pos; // Start at the opening quote
726
+ pos += 1;
727
+ var url = '';
728
+ while (pos < len && cssCode[pos] !== quote) {
729
+ // Only stop at newlines - parentheses and semicolons are valid in URLs
730
+ if (cssCode[pos] === '\n') {
731
+ break;
732
+ }
733
+ if (cssCode[pos] === '\\') {
734
+ pos += 2;
735
+ continue;
736
+ }
737
+ url += cssCode[pos];
738
+ pos += 1;
739
+ }
740
+ if (pos < len && cssCode[pos] === quote) {
741
+ pathEnd = pos + 1; // End after the closing quote
742
+ pos += 1;
743
+ modulePath = url;
744
+ }
745
+ // If we didn't find the closing quote, don't set modulePath (malformed)
746
+ } else {
747
+ // Unquoted URL
748
+ pathStart = pos;
749
+ var _url = '';
750
+ while (pos < len && cssCode[pos] !== ')' && !/\s/.test(cssCode[pos])) {
751
+ _url += cssCode[pos];
752
+ pos += 1;
753
+ }
754
+ pathEnd = pos;
755
+ modulePath = _url;
756
+ }
757
+
758
+ // Skip to closing parenthesis - if we don't find it, the url() is malformed
759
+ while (pos < len && cssCode[pos] !== ')' && cssCode[pos] !== ';' && cssCode[pos] !== '\n') {
760
+ pos += 1;
761
+ }
762
+ if (pos < len && cssCode[pos] === ')') {
763
+ pos += 1;
764
+ // Only consider this a valid URL if we found the closing parenthesis
765
+ } else {
766
+ // Malformed url() - don't set modulePath
767
+ modulePath = null;
768
+ pathStart = undefined;
769
+ pathEnd = undefined;
770
+ }
771
+ } else if (pos < len && (cssCode[pos] === '"' || cssCode[pos] === "'")) {
772
+ // Direct quoted import
773
+ var _quote = cssCode[pos];
774
+ pathStart = pos; // Start at the opening quote
775
+ pos += 1;
776
+ var _url2 = '';
777
+ while (pos < len && cssCode[pos] !== _quote) {
778
+ // Stop if we hit a newline (likely malformed), but semicolons are valid in URLs
779
+ if (cssCode[pos] === '\n') {
780
+ break;
781
+ }
782
+ if (cssCode[pos] === '\\') {
783
+ pos += 2;
784
+ continue;
785
+ }
786
+ _url2 += cssCode[pos];
787
+ pos += 1;
788
+ }
789
+ if (pos < len && cssCode[pos] === _quote) {
790
+ pathEnd = pos + 1; // End after the closing quote
791
+ pos += 1;
792
+ modulePath = _url2;
793
+ }
794
+ // If we didn't find the closing quote, don't set modulePath (malformed import)
795
+ }
796
+
797
+ // Skip to semicolon or end of statement
798
+ while (pos < len && cssCode[pos] !== ';' && cssCode[pos] !== '\n') {
799
+ pos += 1;
800
+ }
801
+ if (pos < len && cssCode[pos] === ';') {
802
+ pos += 1;
803
+ }
804
+ return {
805
+ modulePath: modulePath,
806
+ nextPos: pos,
807
+ pathStart: pathStart,
808
+ pathEnd: pathEnd
809
+ };
810
+ }
811
+
812
+ // CSS import detector function
813
+ function detectCssImport(sourceText, pos, cssResult, cssExternals, cssFilePath, positionMapper) {
814
+ var ch = sourceText[pos];
815
+
816
+ // Look for '@import' keyword
817
+ if (ch === '@' && sourceText.slice(pos, pos + 7) === '@import' && /\s/.test(sourceText[pos + 7] || '')) {
818
+ // Parse the @import statement
819
+ var importResult = parseCssImportStatement(sourceText, pos);
820
+ if (importResult.modulePath && importResult.pathStart !== undefined && importResult.pathEnd !== undefined) {
821
+ // In CSS, imports are relative unless they have a protocol/hostname
822
+ // Examples of external: "http://...", "https://...", "//example.com/style.css"
823
+ // Examples of relative: "print.css", "./local.css", "../parent.css"
824
+ var hasProtocol = /^https?:\/\//.test(importResult.modulePath);
825
+ var hasHostname = /^\/\//.test(importResult.modulePath);
826
+ var isExternal = hasProtocol || hasHostname;
827
+ var position = {
828
+ start: positionMapper(importResult.pathStart),
829
+ end: positionMapper(importResult.pathEnd)
830
+ };
831
+ if (isExternal) {
832
+ if (!cssExternals[importResult.modulePath]) {
833
+ cssExternals[importResult.modulePath] = {
834
+ names: [],
835
+ positions: []
836
+ };
837
+ }
838
+ cssExternals[importResult.modulePath].positions.push(position);
839
+ } else {
840
+ // Treat as relative import - normalize the path if it doesn't start with ./ or ../
841
+ var normalizedPath = importResult.modulePath;
842
+ if (!normalizedPath.startsWith('./') && !normalizedPath.startsWith('../')) {
843
+ normalizedPath = "./".concat(normalizedPath);
844
+ }
845
+ var resolvedPath = path.resolve(path.dirname(cssFilePath), normalizedPath);
846
+ if (!cssResult[importResult.modulePath]) {
847
+ cssResult[importResult.modulePath] = {
848
+ path: resolvedPath,
849
+ names: [],
850
+ positions: []
851
+ };
852
+ }
853
+ cssResult[importResult.modulePath].positions.push(position);
854
+ }
855
+ }
856
+ return {
857
+ found: true,
858
+ nextPos: importResult.nextPos
859
+ };
860
+ }
861
+ return {
862
+ found: false,
863
+ nextPos: pos
864
+ };
865
+ }
866
+
867
+ /**
868
+ * Parses CSS @import statements from CSS source code.
869
+ * @param cssCode - The CSS source code to parse
870
+ * @param cssFilePath - The CSS file path for resolving relative imports
871
+ * @param cssResult - Object to store relative CSS import results
872
+ * @param cssExternals - Object to store external CSS import results
873
+ * @param removeCommentsWithPrefix - Optional prefixes for comments to remove
874
+ * @param notableCommentsPrefix - Optional prefixes for comments to collect
875
+ * @returns The parsed CSS import results with optional processed code and comments
876
+ */
877
+ function parseCssImports(cssCode, cssFilePath, cssResult, cssExternals, removeCommentsWithPrefix, notableCommentsPrefix) {
878
+ // Use the generic scanner with a bound detector function
879
+ var scanResult = scanForImports(cssCode, function (sourceText, pos, positionMapper) {
880
+ return detectCssImport(sourceText, pos, cssResult, cssExternals, cssFilePath, positionMapper);
881
+ }, false, removeCommentsWithPrefix, notableCommentsPrefix);
882
+ return _extends(_extends({
883
+ relative: cssResult,
884
+ externals: cssExternals
885
+ }, scanResult.code && {
886
+ code: scanResult.code
887
+ }), scanResult.comments && {
888
+ comments: scanResult.comments
889
+ });
890
+ }
891
+
892
+ /**
893
+ * Parses JavaScript/TypeScript import statements from source code.
894
+ * @param code - The source code to parse
895
+ * @param filePath - The file path for resolving relative imports
896
+ * @param result - Object to store relative import results
897
+ * @param externals - Object to store external import results
898
+ * @param isMdxFile - Whether this is an MDX file
899
+ * @param removeCommentsWithPrefix - Optional prefixes for comments to remove
900
+ * @param notableCommentsPrefix - Optional prefixes for comments to collect
901
+ * @returns The parsed import results with optional processed code and comments
902
+ */
903
+ function parseJSImports(code, filePath, result, externals, isMdxFile, removeCommentsWithPrefix, notableCommentsPrefix) {
904
+ // Scan code for JavaScript import statements
905
+ var scanResult = scanForImports(code, detectJavaScriptImport, isMdxFile, removeCommentsWithPrefix, notableCommentsPrefix);
906
+
907
+ // Now, parse each import statement using character-by-character parsing
908
+ var _iterator = _createForOfIteratorHelper(scanResult.statements),
909
+ _step;
910
+ try {
911
+ var _loop = function _loop() {
912
+ var _step$value = _step.value,
913
+ start = _step$value.start,
914
+ text = _step$value.text;
915
+ var pos = 0;
916
+ var textLen = text.length;
917
+
918
+ // Skip 'import'
919
+ pos = 6; // We know it starts with 'import'
920
+ pos = skipWhitespace(text, pos);
921
+
922
+ // Check for 'type' keyword
923
+ var isTypeImport = false;
924
+ if (text.slice(pos, pos + 4) === 'type' && !isIdentifierChar(text[pos + 4] || '')) {
925
+ isTypeImport = true;
926
+ pos += 4;
927
+ pos = skipWhitespace(text, pos);
928
+ }
929
+
930
+ // Check if this is a side-effect import (starts with quote)
931
+ if (pos < textLen && (text[pos] === '"' || text[pos] === "'")) {
932
+ var _readQuotedString = readQuotedString(text, pos),
933
+ _modulePath = _readQuotedString.value,
934
+ _pathStart = _readQuotedString.pathStart,
935
+ _pathEnd = _readQuotedString.pathEnd;
936
+ if (_modulePath) {
937
+ // Calculate the position in the original source code
938
+ var _originalPathStart = start + _pathStart;
939
+ var _originalPathEnd = start + _pathEnd;
940
+
941
+ // Apply position mapping if available (for comment-stripped positions)
942
+ var _mappedStart = _originalPathStart;
943
+ var _mappedEnd = _originalPathEnd;
944
+ if (scanResult.positionMapper) {
945
+ _mappedStart = scanResult.positionMapper(_originalPathStart);
946
+ _mappedEnd = scanResult.positionMapper(_originalPathEnd);
947
+ }
948
+ var _position = {
949
+ start: _mappedStart,
950
+ end: _mappedEnd
951
+ };
952
+ var _isRelative = _modulePath.startsWith('./') || _modulePath.startsWith('../');
953
+ if (_isRelative) {
954
+ var resolvedPath = path.resolve(path.dirname(filePath), _modulePath);
955
+ if (!result[_modulePath]) {
956
+ result[_modulePath] = {
957
+ path: resolvedPath,
958
+ names: [],
959
+ positions: []
960
+ };
961
+ }
962
+ result[_modulePath].positions.push(_position);
963
+ } else {
964
+ if (!externals[_modulePath]) {
965
+ externals[_modulePath] = {
966
+ names: [],
967
+ positions: []
968
+ };
969
+ }
970
+ externals[_modulePath].positions.push(_position);
971
+ }
972
+ }
973
+ return 0; // continue
974
+ }
975
+
976
+ // Parse import specifiers
977
+ var defaultImport;
978
+ var namespaceImport;
979
+ var namedImports = [];
980
+
981
+ // Check for default import (identifier not followed by 'from')
982
+ if (pos < textLen && /[a-zA-Z_$]/.test(text[pos])) {
983
+ var _readIdentifier2 = readIdentifier(text, pos),
984
+ name = _readIdentifier2.name,
985
+ nextPos = _readIdentifier2.nextPos;
986
+ var afterName = skipWhitespace(text, nextPos);
987
+
988
+ // If next non-whitespace is comma or 'from', this is a default import
989
+ if (afterName >= textLen || text[afterName] === ',' || text.slice(afterName, afterName + 4) === 'from') {
990
+ defaultImport = name;
991
+ pos = afterName;
992
+
993
+ // Skip comma if present
994
+ if (pos < textLen && text[pos] === ',') {
995
+ pos += 1;
996
+ pos = skipWhitespace(text, pos);
997
+ }
998
+ }
999
+ }
1000
+
1001
+ // Check for namespace import (* as Name)
1002
+ if (pos < textLen && text[pos] === '*') {
1003
+ pos += 1;
1004
+ pos = skipWhitespace(text, pos);
1005
+
1006
+ // Expect 'as'
1007
+ if (text.slice(pos, pos + 2) === 'as') {
1008
+ pos += 2;
1009
+ pos = skipWhitespace(text, pos);
1010
+ var _readIdentifier3 = readIdentifier(text, pos),
1011
+ _name = _readIdentifier3.name;
1012
+ if (_name) {
1013
+ namespaceImport = _name;
1014
+ pos = readIdentifier(text, pos).nextPos;
1015
+ pos = skipWhitespace(text, pos);
1016
+ }
1017
+ }
1018
+ }
1019
+
1020
+ // Check for named imports ({ ... })
1021
+ if (pos < textLen && text[pos] === '{') {
1022
+ pos += 1;
1023
+ var braceStart = pos;
1024
+
1025
+ // Find the closing brace
1026
+ var braceDepth = 1;
1027
+ while (pos < textLen && braceDepth > 0) {
1028
+ if (text[pos] === '{') {
1029
+ braceDepth += 1;
1030
+ } else if (text[pos] === '}') {
1031
+ braceDepth -= 1;
1032
+ }
1033
+ pos += 1;
1034
+ }
1035
+ if (braceDepth === 0) {
1036
+ var braceEnd = pos - 1;
1037
+ namedImports = parseNamedImports(text, braceStart, braceEnd);
1038
+ }
1039
+ }
1040
+
1041
+ // Skip to 'from' keyword
1042
+ pos = skipWhitespace(text, pos);
1043
+ while (pos < textLen && text.slice(pos, pos + 4) !== 'from') {
1044
+ pos += 1;
1045
+ }
1046
+ if (pos >= textLen || text.slice(pos, pos + 4) !== 'from') {
1047
+ return 0; // continue
1048
+ // No 'from' found, skip this import
1049
+ }
1050
+ pos += 4;
1051
+ pos = skipWhitespace(text, pos);
1052
+
1053
+ // Read module path
1054
+ if (pos >= textLen || !(text[pos] === '"' || text[pos] === "'")) {
1055
+ return 0; // continue
1056
+ // No quoted module path found
1057
+ }
1058
+ var _readQuotedString2 = readQuotedString(text, pos),
1059
+ modulePath = _readQuotedString2.value,
1060
+ pathStart = _readQuotedString2.pathStart,
1061
+ pathEnd = _readQuotedString2.pathEnd;
1062
+ if (!modulePath) {
1063
+ return 0; // continue
1064
+ }
1065
+
1066
+ // Calculate the position in the original source code
1067
+ var originalPathStart = start + pathStart;
1068
+ var originalPathEnd = start + pathEnd;
1069
+ var isRelative = modulePath.startsWith('./') || modulePath.startsWith('../');
1070
+
1071
+ // Apply position mapping if available (for comment-stripped positions)
1072
+ var mappedStart = originalPathStart;
1073
+ var mappedEnd = originalPathEnd;
1074
+ if (scanResult.positionMapper) {
1075
+ mappedStart = scanResult.positionMapper(originalPathStart);
1076
+ mappedEnd = scanResult.positionMapper(originalPathEnd);
1077
+ }
1078
+ var position = {
1079
+ start: mappedStart,
1080
+ end: mappedEnd
1081
+ };
1082
+ if (isRelative) {
1083
+ var _resolvedPath = path.resolve(path.dirname(filePath), modulePath);
1084
+ if (!result[modulePath]) {
1085
+ result[modulePath] = _extends({
1086
+ path: _resolvedPath,
1087
+ names: [],
1088
+ positions: []
1089
+ }, isTypeImport && {
1090
+ includeTypeDefs: true
1091
+ });
1092
+ } else if (isTypeImport && !result[modulePath].includeTypeDefs) {
1093
+ result[modulePath].includeTypeDefs = true;
1094
+ }
1095
+
1096
+ // Add position information
1097
+ result[modulePath].positions.push(position);
1098
+ if (defaultImport) {
1099
+ addImportName(result[modulePath].names, defaultImport, 'default', undefined, isTypeImport);
1100
+ }
1101
+ if (namespaceImport) {
1102
+ addImportName(result[modulePath].names, namespaceImport, 'namespace', undefined, isTypeImport);
1103
+ }
1104
+ namedImports.forEach(function (_ref) {
1105
+ var name = _ref.name,
1106
+ alias = _ref.alias,
1107
+ isType = _ref.isType;
1108
+ addImportName(result[modulePath].names, name, 'named', alias, isTypeImport || isType);
1109
+ });
1110
+ } else {
1111
+ if (!externals[modulePath]) {
1112
+ externals[modulePath] = {
1113
+ names: [],
1114
+ positions: []
1115
+ };
1116
+ }
1117
+
1118
+ // Add position information
1119
+ externals[modulePath].positions.push(position);
1120
+ if (defaultImport) {
1121
+ addImportName(externals[modulePath].names, defaultImport, 'default', undefined, isTypeImport);
1122
+ }
1123
+ if (namespaceImport) {
1124
+ addImportName(externals[modulePath].names, namespaceImport, 'namespace', undefined, isTypeImport);
1125
+ }
1126
+ namedImports.forEach(function (_ref2) {
1127
+ var name = _ref2.name,
1128
+ alias = _ref2.alias,
1129
+ isType = _ref2.isType;
1130
+ addImportName(externals[modulePath].names, name, 'named', alias, isTypeImport || isType);
1131
+ });
1132
+ }
1133
+ },
1134
+ _ret;
1135
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1136
+ _ret = _loop();
1137
+ if (_ret === 0) continue;
1138
+ }
1139
+ } catch (err) {
1140
+ _iterator.e(err);
1141
+ } finally {
1142
+ _iterator.f();
1143
+ }
1144
+ return _extends(_extends({
1145
+ relative: result,
1146
+ externals: externals
1147
+ }, scanResult.code && {
1148
+ code: scanResult.code
1149
+ }), scanResult.comments && {
1150
+ comments: scanResult.comments
1151
+ });
1152
+ }
1153
+
1154
+ /**
1155
+ * Detects JavaScript import statements at a given position in source code.
1156
+ * @param sourceText - The source text to scan
1157
+ * @param pos - The current position in the text
1158
+ * @param positionMapper - Function to map original positions to processed positions
1159
+ * @returns Object indicating if an import was found, the next position, and statement details
1160
+ */
1161
+ function detectJavaScriptImport(sourceText, pos, _positionMapper) {
1162
+ var ch = sourceText[pos];
1163
+
1164
+ // Look for 'import' keyword (not part of an identifier, and not preceded by @)
1165
+ if (ch === 'i' && sourceText.slice(pos, pos + 6) === 'import' && (pos === 0 || /[^a-zA-Z0-9_$@]/.test(sourceText[pos - 1])) && /[^a-zA-Z0-9_$]/.test(sourceText[pos + 6] || '')) {
1166
+ // Mark start of import statement
1167
+ var importStart = pos;
1168
+ var len = sourceText.length;
1169
+
1170
+ // Now, scan forward to find the end of the statement (semicolon or proper end for side-effect imports)
1171
+ var j = pos + 6;
1172
+ var importState = 'code';
1173
+ var importQuote = null;
1174
+ var braceDepth = 0;
1175
+ var foundFrom = false;
1176
+ var foundModulePath = false;
1177
+ while (j < len) {
1178
+ var cj = sourceText[j];
1179
+ if (importState === 'code') {
1180
+ if (cj === ';') {
1181
+ j += 1;
1182
+ break;
1183
+ }
1184
+ // Check if we're at a bare import statement (no 'from')
1185
+ if (cj === '\n' && !foundFrom && !foundModulePath && braceDepth === 0) {
1186
+ // This might be a side-effect import or end of statement
1187
+ // Look ahead to see if there's content that could be part of the import
1188
+ var k = j + 1;
1189
+ while (k < len && /\s/.test(sourceText[k])) {
1190
+ k += 1;
1191
+ }
1192
+ if (k >= len || sourceText.slice(k, k + 4) === 'from' || isStringStart(sourceText[k])) {
1193
+ // Continue, this newline is within the import
1194
+ } else {
1195
+ // This looks like the end of a side-effect import
1196
+ j += 1;
1197
+ break;
1198
+ }
1199
+ }
1200
+ if (isStringStart(cj)) {
1201
+ importState = cj === '`' ? 'template' : 'string';
1202
+ importQuote = cj;
1203
+ if (foundFrom) {
1204
+ foundModulePath = true;
1205
+ }
1206
+ j += 1;
1207
+ continue;
1208
+ }
1209
+ if (cj === '{') {
1210
+ braceDepth += 1;
1211
+ }
1212
+ if (cj === '}') {
1213
+ braceDepth -= 1;
1214
+ }
1215
+ if (sourceText.slice(j, j + 4) === 'from' && /\s/.test(sourceText[j + 4] || '')) {
1216
+ foundFrom = true;
1217
+ }
1218
+ // If we found a module path and we're back to normal code, we might be done
1219
+ if (foundModulePath && braceDepth === 0 && /\s/.test(cj)) {
1220
+ // Look ahead for semicolon or end of statement
1221
+ var _k = j;
1222
+ while (_k < len && /\s/.test(sourceText[_k])) {
1223
+ _k += 1;
1224
+ }
1225
+ if (_k >= len || sourceText[_k] === ';' || sourceText[_k] === '\n') {
1226
+ if (sourceText[_k] === ';') {
1227
+ j = _k + 1;
1228
+ } else {
1229
+ j = _k;
1230
+ }
1231
+ break;
1232
+ }
1233
+ }
1234
+ } else if (importState === 'string') {
1235
+ if (cj === '\\') {
1236
+ j += 2;
1237
+ continue;
1238
+ }
1239
+ if (cj === importQuote) {
1240
+ importState = 'code';
1241
+ importQuote = null;
1242
+ }
1243
+ j += 1;
1244
+ continue;
1245
+ } else if (importState === 'template') {
1246
+ if (cj === '`') {
1247
+ importState = 'code';
1248
+ importQuote = null;
1249
+ } else if (cj === '\\') {
1250
+ j += 2;
1251
+ continue;
1252
+ }
1253
+ j += 1;
1254
+ continue;
1255
+ }
1256
+ j += 1;
1257
+ }
1258
+ var importText = sourceText.slice(importStart, j);
1259
+ return {
1260
+ found: true,
1261
+ nextPos: j,
1262
+ statement: {
1263
+ start: importStart,
1264
+ end: j,
1265
+ text: importText
1266
+ }
1267
+ };
1268
+ }
1269
+ return {
1270
+ found: false,
1271
+ nextPos: pos
1272
+ };
1273
+ }
1274
+
1275
+ /**
1276
+ * Parse import statements from JavaScript/TypeScript/CSS code.
1277
+ *
1278
+ * This function analyzes source code to extract all import statements, categorizing them
1279
+ * as either relative imports (local files) or external imports (packages). It supports
1280
+ * JavaScript, TypeScript, CSS, and MDX files.
1281
+ *
1282
+ * Comment processing (stripping/collecting) is performed during import parsing
1283
+ * for efficiency. Since we must already parse the entire file character-by-character
1284
+ * to correctly identify imports while avoiding false positives in strings, comments,
1285
+ * and template literals, it's most efficient to handle comment processing in this
1286
+ * same pass rather than requiring separate parsing steps.
1287
+ *
1288
+ * @param code - The source code to parse
1289
+ * @param filePath - The file path, used to determine file type and resolve relative imports
1290
+ * @param options - Optional configuration for comment processing
1291
+ * @param options.removeCommentsWithPrefix - Array of prefixes; comments starting with these will be stripped from output
1292
+ * @param options.notableCommentsPrefix - Array of prefixes; comments starting with these will be collected regardless of stripping
1293
+ * @returns Promise resolving to parsed import data, optionally including processed code and collected comments
1294
+ *
1295
+ * @example
1296
+ * ```typescript
1297
+ * const result = await parseImportsAndComments(
1298
+ * 'import React from "react";\nimport { Button } from "./Button";',
1299
+ * '/src/App.tsx'
1300
+ * );
1301
+ * // result.externals['react'] contains the React import
1302
+ * // result.relative['./Button'] contains the Button import
1303
+ * ```
1304
+ */
1305
+ export function parseImportsAndComments(_x, _x2, _x3) {
1306
+ return _parseImportsAndComments.apply(this, arguments);
1307
+ }
1308
+ function _parseImportsAndComments() {
1309
+ _parseImportsAndComments = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(code, filePath, options) {
1310
+ var result, externals, isCssFile, isMdxFile;
1311
+ return _regenerator().w(function (_context) {
1312
+ while (1) switch (_context.n) {
1313
+ case 0:
1314
+ result = {};
1315
+ externals = {}; // Check if this is a CSS file
1316
+ isCssFile = filePath.toLowerCase().endsWith('.css'); // Check if this is an MDX file (which can contain code blocks with triple backticks)
1317
+ isMdxFile = filePath.toLowerCase().endsWith('.mdx'); // If this is a CSS file, parse CSS @import statements instead
1318
+ if (!isCssFile) {
1319
+ _context.n = 1;
1320
+ break;
1321
+ }
1322
+ return _context.a(2, parseCssImports(code, filePath, result, externals, options == null ? void 0 : options.removeCommentsWithPrefix, options == null ? void 0 : options.notableCommentsPrefix));
1323
+ case 1:
1324
+ return _context.a(2, parseJSImports(code, filePath, result, externals, isMdxFile, options == null ? void 0 : options.removeCommentsWithPrefix, options == null ? void 0 : options.notableCommentsPrefix));
1325
+ }
1326
+ }, _callee);
1327
+ }));
1328
+ return _parseImportsAndComments.apply(this, arguments);
1329
+ }