@bfra.me/doc-sync 0.1.0 → 0.1.2

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.
@@ -0,0 +1,327 @@
1
+ // src/watcher/change-detector.ts
2
+ import { createChangeDetector as createBaseDetector } from "@bfra.me/es/watcher";
3
+
4
+ // src/watcher/file-watcher.ts
5
+ import path from "path";
6
+ import process from "process";
7
+ import { createFileWatcher as createBaseWatcher } from "@bfra.me/es/watcher";
8
+ var DEFAULT_WATCH_PATTERNS = [
9
+ "packages/*/README.md",
10
+ "packages/*/readme.md",
11
+ "packages/*/package.json",
12
+ "packages/*/src/**/*.ts",
13
+ "packages/*/src/**/*.tsx"
14
+ ];
15
+ var DEFAULT_IGNORE_PATTERNS = [
16
+ "**/node_modules/**",
17
+ "**/lib/**",
18
+ "**/dist/**",
19
+ "**/.git/**",
20
+ "**/coverage/**",
21
+ "**/*.test.ts",
22
+ "**/*.spec.ts",
23
+ "**/__tests__/**",
24
+ "**/__mocks__/**"
25
+ ];
26
+ function extractPackageName(filePath, root) {
27
+ const relativePath = path.relative(root, filePath);
28
+ const parts = relativePath.split(path.sep);
29
+ if (parts[0] === "packages" && parts.length > 1) {
30
+ return parts[1];
31
+ }
32
+ return void 0;
33
+ }
34
+ function createDocWatcher(options = {}) {
35
+ const {
36
+ rootDir = process.cwd(),
37
+ debounceMs = 300,
38
+ additionalIgnore = [],
39
+ usePolling = false
40
+ } = options;
41
+ const watchPaths = DEFAULT_WATCH_PATTERNS.map((pattern) => path.join(rootDir, pattern));
42
+ const ignoredPatterns = [...DEFAULT_IGNORE_PATTERNS, ...additionalIgnore];
43
+ const watcherOptions = {
44
+ debounceMs,
45
+ ignored: ignoredPatterns,
46
+ usePolling
47
+ };
48
+ const baseWatcher = createBaseWatcher(watchPaths, watcherOptions);
49
+ const handlers = /* @__PURE__ */ new Set();
50
+ function transformToDocEvents(changes) {
51
+ return changes.map((change) => ({
52
+ type: change.type,
53
+ path: change.path,
54
+ packageName: extractPackageName(change.path, rootDir),
55
+ timestamp: new Date(change.timestamp)
56
+ }));
57
+ }
58
+ return {
59
+ async start() {
60
+ baseWatcher.on("change", (event) => {
61
+ const docEvents = transformToDocEvents(event.changes);
62
+ for (const handler of handlers) {
63
+ Promise.resolve(handler(docEvents)).catch((error) => {
64
+ console.error("[doc-sync] Error in change handler:", error);
65
+ });
66
+ }
67
+ });
68
+ await baseWatcher.start();
69
+ },
70
+ async close() {
71
+ await baseWatcher.close();
72
+ handlers.clear();
73
+ },
74
+ onChanges(handler) {
75
+ handlers.add(handler);
76
+ return () => {
77
+ handlers.delete(handler);
78
+ };
79
+ },
80
+ getWatchedPaths() {
81
+ return watchPaths;
82
+ }
83
+ };
84
+ }
85
+ function categorizeFile(filePath) {
86
+ const basename = path.basename(filePath).toLowerCase();
87
+ if (basename === "readme.md" || basename === "readme") {
88
+ return "readme";
89
+ }
90
+ if (basename === "package.json") {
91
+ return "package-json";
92
+ }
93
+ const ext = path.extname(filePath).toLowerCase();
94
+ if (ext === ".ts" || ext === ".tsx") {
95
+ return "source";
96
+ }
97
+ return "unknown";
98
+ }
99
+ function groupChangesByPackage(events) {
100
+ const grouped = /* @__PURE__ */ new Map();
101
+ for (const event of events) {
102
+ const pkg = event.packageName ?? "__unknown__";
103
+ const existing = grouped.get(pkg);
104
+ if (existing === void 0) {
105
+ grouped.set(pkg, [event]);
106
+ } else {
107
+ existing.push(event);
108
+ }
109
+ }
110
+ return grouped;
111
+ }
112
+ function filterDocumentationChanges(events) {
113
+ return events.filter((event) => {
114
+ const category = categorizeFile(event.path);
115
+ return category !== "unknown";
116
+ });
117
+ }
118
+
119
+ // src/watcher/change-detector.ts
120
+ function createDocChangeDetector(options = {}) {
121
+ const baseDetector = createBaseDetector({ algorithm: options.algorithm });
122
+ const packageFiles = /* @__PURE__ */ new Map();
123
+ return {
124
+ async hasChanged(filePath) {
125
+ return baseDetector.hasChanged(filePath);
126
+ },
127
+ async record(filePath) {
128
+ await baseDetector.record(filePath);
129
+ },
130
+ async recordPackage(pkg, files) {
131
+ const fileSet = new Set(files);
132
+ packageFiles.set(pkg.name, fileSet);
133
+ await Promise.all(files.map(async (file) => baseDetector.record(file)));
134
+ },
135
+ clear(filePath) {
136
+ baseDetector.clear(filePath);
137
+ for (const fileSet of packageFiles.values()) {
138
+ fileSet.delete(filePath);
139
+ }
140
+ },
141
+ clearAll() {
142
+ baseDetector.clearAll();
143
+ packageFiles.clear();
144
+ },
145
+ async analyzeChanges(events) {
146
+ const packageChanges = /* @__PURE__ */ new Map();
147
+ for (const event of events) {
148
+ const packageName = event.packageName ?? "__unknown__";
149
+ const category = categorizeFile(event.path);
150
+ let analysis = packageChanges.get(packageName);
151
+ if (analysis === void 0) {
152
+ analysis = { categories: /* @__PURE__ */ new Set(), files: [] };
153
+ packageChanges.set(packageName, analysis);
154
+ }
155
+ if (category !== "unknown") {
156
+ analysis.categories.add(category);
157
+ }
158
+ analysis.files.push(event.path);
159
+ }
160
+ const results = [];
161
+ for (const [packageName, analysis] of packageChanges) {
162
+ const changedCategories = [...analysis.categories];
163
+ const needsRegeneration = changedCategories.includes("readme") || changedCategories.includes("package-json") || changedCategories.includes("source");
164
+ results.push({
165
+ packageName,
166
+ needsRegeneration,
167
+ changedCategories,
168
+ changedFiles: analysis.files
169
+ });
170
+ }
171
+ return results;
172
+ }
173
+ };
174
+ }
175
+ function determineRegenerationScope(changedCategories) {
176
+ const hasReadme = changedCategories.includes("readme");
177
+ const hasSource = changedCategories.includes("source");
178
+ const hasPackageJson = changedCategories.includes("package-json");
179
+ if (hasReadme && hasSource) {
180
+ return "full";
181
+ }
182
+ if (hasSource) {
183
+ return "api-only";
184
+ }
185
+ if (hasReadme) {
186
+ return "readme-only";
187
+ }
188
+ if (hasPackageJson) {
189
+ return "metadata-only";
190
+ }
191
+ return "none";
192
+ }
193
+ async function hasAnyFileChanged(detector, files) {
194
+ const results = await Promise.all(files.map(async (file) => detector.hasChanged(file)));
195
+ return results.some((changed) => changed);
196
+ }
197
+
198
+ // src/watcher/debouncer.ts
199
+ import { createDebouncer as createBaseDebouncer } from "@bfra.me/es/watcher";
200
+ function createDocDebouncer(handler, options = {}) {
201
+ const { debounceMs = 300, maxWaitMs = 5e3 } = options;
202
+ let pendingEvents = [];
203
+ let maxWaitTimeout;
204
+ function processEvents(events) {
205
+ if (maxWaitTimeout !== void 0) {
206
+ clearTimeout(maxWaitTimeout);
207
+ maxWaitTimeout = void 0;
208
+ }
209
+ const deduplicated = deduplicateEvents(events);
210
+ if (deduplicated.length > 0) {
211
+ Promise.resolve(handler(deduplicated)).catch((error) => {
212
+ console.error("[doc-sync] Error in batch handler:", error);
213
+ });
214
+ }
215
+ }
216
+ const baseDebouncer = createBaseDebouncer((events) => {
217
+ processEvents(events);
218
+ pendingEvents = [];
219
+ }, debounceMs);
220
+ function startMaxWaitTimer() {
221
+ if (maxWaitTimeout === void 0) {
222
+ maxWaitTimeout = setTimeout(() => {
223
+ baseDebouncer.flush();
224
+ }, maxWaitMs);
225
+ }
226
+ }
227
+ return {
228
+ add(event) {
229
+ pendingEvents.push(event);
230
+ startMaxWaitTimer();
231
+ baseDebouncer.add(event);
232
+ },
233
+ addAll(events) {
234
+ for (const event of events) {
235
+ pendingEvents.push(event);
236
+ baseDebouncer.add(event);
237
+ }
238
+ if (events.length > 0) {
239
+ startMaxWaitTimer();
240
+ }
241
+ },
242
+ flush() {
243
+ if (maxWaitTimeout !== void 0) {
244
+ clearTimeout(maxWaitTimeout);
245
+ maxWaitTimeout = void 0;
246
+ }
247
+ baseDebouncer.flush();
248
+ },
249
+ cancel() {
250
+ if (maxWaitTimeout !== void 0) {
251
+ clearTimeout(maxWaitTimeout);
252
+ maxWaitTimeout = void 0;
253
+ }
254
+ pendingEvents = [];
255
+ baseDebouncer.cancel();
256
+ },
257
+ getPendingCount() {
258
+ return pendingEvents.length;
259
+ }
260
+ };
261
+ }
262
+ function deduplicateEvents(events) {
263
+ const latestByPath = /* @__PURE__ */ new Map();
264
+ for (const event of events) {
265
+ const existing = latestByPath.get(event.path);
266
+ if (existing === void 0 || event.timestamp > existing.timestamp) {
267
+ latestByPath.set(event.path, event);
268
+ }
269
+ }
270
+ return [...latestByPath.values()];
271
+ }
272
+ function consolidateEvents(events) {
273
+ const byPath = /* @__PURE__ */ new Map();
274
+ for (const event of events) {
275
+ const existing = byPath.get(event.path);
276
+ if (existing === void 0) {
277
+ byPath.set(event.path, [event]);
278
+ } else {
279
+ existing.push(event);
280
+ }
281
+ }
282
+ const consolidated = [];
283
+ for (const [, pathEvents] of byPath) {
284
+ const firstEvent = pathEvents[0];
285
+ if (firstEvent === void 0) {
286
+ continue;
287
+ }
288
+ if (pathEvents.length === 1) {
289
+ consolidated.push(firstEvent);
290
+ continue;
291
+ }
292
+ pathEvents.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
293
+ const first = pathEvents[0];
294
+ const last = pathEvents.at(-1);
295
+ if (first === void 0 || last === void 0) {
296
+ continue;
297
+ }
298
+ if (first.type === "add" && last.type === "unlink") {
299
+ continue;
300
+ }
301
+ if (first.type === "unlink" && last.type === "add") {
302
+ consolidated.push({
303
+ type: "change",
304
+ path: last.path,
305
+ packageName: last.packageName,
306
+ timestamp: last.timestamp
307
+ });
308
+ continue;
309
+ }
310
+ consolidated.push(last);
311
+ }
312
+ return consolidated;
313
+ }
314
+
315
+ export {
316
+ createDocWatcher,
317
+ categorizeFile,
318
+ groupChangesByPackage,
319
+ filterDocumentationChanges,
320
+ createDocChangeDetector,
321
+ determineRegenerationScope,
322
+ hasAnyFileChanged,
323
+ createDocDebouncer,
324
+ deduplicateEvents,
325
+ consolidateEvents
326
+ };
327
+ //# sourceMappingURL=chunk-45NROJIG.js.map
@@ -1,6 +1,13 @@
1
1
  import {
2
2
  SENTINEL_MARKERS
3
3
  } from "./chunk-ROLA7SBB.js";
4
+ import {
5
+ extractCodeBlocks,
6
+ parseJSXTags,
7
+ sanitizeAttribute,
8
+ sanitizeForMDX,
9
+ sanitizeJSXTag
10
+ } from "./chunk-GZ2MP3VN.js";
4
11
 
5
12
  // src/generators/api-reference-generator.ts
6
13
  function generateAPIReference(api) {
@@ -435,80 +442,6 @@ function formatGroupedExamples(api, options = {}) {
435
442
  return sections.join("\n").trim();
436
443
  }
437
444
 
438
- // src/utils/sanitization.ts
439
- import { sanitizeInput } from "@bfra.me/es/validation";
440
- import escapeHtml from "escape-html";
441
- function sanitizeForMDX(content) {
442
- const escaped = sanitizeInput(content, { trim: false });
443
- return escaped.replaceAll("{", "{").replaceAll("}", "}");
444
- }
445
- function sanitizeAttribute(value) {
446
- return escapeHtml(value);
447
- }
448
- function parseJSXAttributes(tag) {
449
- const attrs = [];
450
- const spaceIndex = tag.indexOf(" ");
451
- if (spaceIndex === -1) return attrs;
452
- const closeIndex = tag.lastIndexOf(">");
453
- if (closeIndex === -1) return attrs;
454
- const attrRegion = tag.slice(spaceIndex + 1, closeIndex).trim();
455
- let i = 0;
456
- while (i < attrRegion.length) {
457
- while (i < attrRegion.length && /\s/.test(attrRegion.charAt(i))) i++;
458
- if (i >= attrRegion.length) break;
459
- let name = "";
460
- while (i < attrRegion.length && /[\w-]/.test(attrRegion.charAt(i))) {
461
- name += attrRegion[i];
462
- i++;
463
- }
464
- if (!name) break;
465
- while (i < attrRegion.length && /\s/.test(attrRegion.charAt(i))) i++;
466
- if (i >= attrRegion.length || attrRegion[i] !== "=") {
467
- attrs.push({ name, value: null });
468
- continue;
469
- }
470
- i++;
471
- while (i < attrRegion.length && /\s/.test(attrRegion.charAt(i))) i++;
472
- if (i >= attrRegion.length) {
473
- attrs.push({ name, value: "" });
474
- break;
475
- }
476
- let value = "";
477
- const quote = attrRegion[i];
478
- if (quote === '"' || quote === "'") {
479
- i++;
480
- while (i < attrRegion.length && attrRegion[i] !== quote) {
481
- value += attrRegion[i];
482
- i++;
483
- }
484
- if (i < attrRegion.length) i++;
485
- } else {
486
- while (i < attrRegion.length && !/[\s/>]/.test(attrRegion.charAt(i))) {
487
- value += attrRegion[i];
488
- i++;
489
- }
490
- }
491
- attrs.push({ name, value });
492
- }
493
- return attrs;
494
- }
495
- function sanitizeJSXTag(tag) {
496
- const tagMatch = tag.match(/^<([A-Z][a-zA-Z0-9]*)/);
497
- if (!tagMatch || typeof tagMatch[1] !== "string" || tagMatch[1].length === 0) {
498
- return escapeHtml(tag);
499
- }
500
- const tagName = tagMatch[1];
501
- const selfClosing = tag.endsWith("/>");
502
- const attributes = parseJSXAttributes(tag);
503
- const sanitizedAttrs = attributes.map(({ name, value }) => {
504
- if (value === null) return name;
505
- const escaped = escapeHtml(value);
506
- return `${name}="${escaped}"`;
507
- });
508
- const attrString = sanitizedAttrs.length > 0 ? ` ${sanitizedAttrs.join(" ")}` : "";
509
- return `<${tagName}${attrString}${selfClosing ? " />" : ">"}`;
510
- }
511
-
512
445
  // src/generators/component-mapper.ts
513
446
  var DEFAULT_CONFIG = {
514
447
  featureSections: ["features", "highlights", "key features"],
@@ -564,6 +497,9 @@ function isFeatureSection(heading, featureSections) {
564
497
  function isInstallationSection(heading, tabSections) {
565
498
  return tabSections.some((tab) => heading.includes(tab.toLowerCase()));
566
499
  }
500
+ function escapeAngleBrackets(text) {
501
+ return text.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
502
+ }
567
503
  function mapFeatureSection(section) {
568
504
  const lines = [];
569
505
  lines.push(`## ${section.heading}`);
@@ -574,7 +510,7 @@ function mapFeatureSection(section) {
574
510
  for (const feature of features) {
575
511
  const icon = inferFeatureIcon(feature.title, feature.emoji);
576
512
  lines.push(` <Card title="${sanitizeAttribute(feature.title)}" icon="${icon}">`);
577
- lines.push(` ${feature.description}`);
513
+ lines.push(` ${escapeAngleBrackets(feature.description)}`);
578
514
  lines.push(" </Card>");
579
515
  }
580
516
  lines.push("</CardGrid>");
@@ -1167,179 +1103,6 @@ function stripQuotes(value) {
1167
1103
 
1168
1104
  // src/generators/mdx-generator.ts
1169
1105
  import { err as err2, ok as ok2 } from "@bfra.me/es/result";
1170
-
1171
- // src/utils/safe-patterns.ts
1172
- import remarkParse from "remark-parse";
1173
- import { unified } from "unified";
1174
- function createHeadingPattern(level) {
1175
- if (level < 1 || level > 6) {
1176
- throw new Error("Heading level must be between 1 and 6");
1177
- }
1178
- const hashes = "#".repeat(level);
1179
- return new RegExp(`^${hashes} ([^\r
1180
- ]+)$`, "gm");
1181
- }
1182
- function hasComponent(content, componentName) {
1183
- const escaped = componentName.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
1184
- const pattern = new RegExp(String.raw`<${escaped}(?:\s[^>]*)?(?:>|\/>)`);
1185
- return pattern.test(content);
1186
- }
1187
- function extractCodeBlocks(content) {
1188
- const processor = unified().use(remarkParse);
1189
- let tree;
1190
- try {
1191
- tree = processor.parse(content);
1192
- } catch {
1193
- return [];
1194
- }
1195
- const blocks = [];
1196
- function visit(node) {
1197
- if (node.type === "code") {
1198
- const lang = node.lang ?? "";
1199
- const value = node.value ?? "";
1200
- blocks.push(`\`\`\`${lang}
1201
- ${value}
1202
- \`\`\``);
1203
- }
1204
- if (Array.isArray(node.children)) {
1205
- for (const child of node.children) {
1206
- visit(child);
1207
- }
1208
- }
1209
- }
1210
- visit(tree);
1211
- return blocks;
1212
- }
1213
- function parseJSXTags(content) {
1214
- const results = [];
1215
- let i = 0;
1216
- while (i < content.length) {
1217
- if (content[i] !== "<") {
1218
- i++;
1219
- continue;
1220
- }
1221
- const startIndex = i;
1222
- i++;
1223
- if (i >= content.length) break;
1224
- const isClosing = content[i] === "/";
1225
- if (isClosing) {
1226
- i++;
1227
- if (i >= content.length) break;
1228
- }
1229
- if (!/^[A-Z]/.test(content[i] ?? "")) {
1230
- continue;
1231
- }
1232
- let tagName = "";
1233
- while (i < content.length && /^[a-z0-9]/i.test(content[i] ?? "")) {
1234
- tagName += content[i];
1235
- i++;
1236
- }
1237
- if (tagName.length === 0) {
1238
- continue;
1239
- }
1240
- if (isClosing) {
1241
- if (i < content.length && content[i] === ">") {
1242
- results.push({
1243
- tag: `</${tagName}>`,
1244
- index: startIndex,
1245
- isClosing: true,
1246
- isSelfClosing: false
1247
- });
1248
- i++;
1249
- }
1250
- continue;
1251
- }
1252
- let depth = 0;
1253
- let foundEnd = false;
1254
- let isSelfClosing = false;
1255
- while (i < content.length && !foundEnd) {
1256
- const char = content[i];
1257
- if ((char === '"' || char === "'") && depth === 0) {
1258
- const quote = char;
1259
- i++;
1260
- while (i < content.length && content[i] !== quote) {
1261
- if (content[i] === "\\" && i + 1 < content.length) {
1262
- i += 2;
1263
- } else {
1264
- i++;
1265
- }
1266
- }
1267
- if (i < content.length) i++;
1268
- continue;
1269
- }
1270
- if (char === "{") {
1271
- depth++;
1272
- i++;
1273
- continue;
1274
- }
1275
- if (char === "}") {
1276
- depth = Math.max(0, depth - 1);
1277
- i++;
1278
- continue;
1279
- }
1280
- if (depth === 0) {
1281
- if (char === "/" && i + 1 < content.length && content[i + 1] === ">") {
1282
- isSelfClosing = true;
1283
- foundEnd = true;
1284
- i += 2;
1285
- continue;
1286
- }
1287
- if (char === ">") {
1288
- foundEnd = true;
1289
- i++;
1290
- continue;
1291
- }
1292
- }
1293
- i++;
1294
- }
1295
- if (foundEnd) {
1296
- const fullTag = content.slice(startIndex, i);
1297
- results.push({ tag: fullTag, index: startIndex, isClosing: false, isSelfClosing });
1298
- }
1299
- }
1300
- return results;
1301
- }
1302
- function findEmptyMarkdownLinks(content) {
1303
- const positions = [];
1304
- let pos = 0;
1305
- while (pos < content.length) {
1306
- const openBracket = content.indexOf("[", pos);
1307
- if (openBracket === -1) break;
1308
- let bracketDepth = 1;
1309
- let closeBracket = openBracket + 1;
1310
- while (closeBracket < content.length && bracketDepth > 0) {
1311
- if (content[closeBracket] === "[") {
1312
- bracketDepth++;
1313
- } else if (content[closeBracket] === "]") {
1314
- bracketDepth--;
1315
- }
1316
- closeBracket++;
1317
- }
1318
- if (bracketDepth !== 0) {
1319
- pos = openBracket + 1;
1320
- continue;
1321
- }
1322
- closeBracket--;
1323
- if (closeBracket + 1 < content.length && content[closeBracket + 1] === "(") {
1324
- let parenPos = closeBracket + 2;
1325
- let isEmptyOrWhitespace = true;
1326
- while (parenPos < content.length && content[parenPos] !== ")") {
1327
- if (!/^\s/.test(content[parenPos] ?? "")) {
1328
- isEmptyOrWhitespace = false;
1329
- break;
1330
- }
1331
- parenPos++;
1332
- }
1333
- if (isEmptyOrWhitespace && parenPos < content.length && content[parenPos] === ")") {
1334
- positions.push(openBracket);
1335
- }
1336
- }
1337
- pos = closeBracket + 1;
1338
- }
1339
- return positions;
1340
- }
1341
-
1342
- // src/generators/mdx-generator.ts
1343
1106
  var DEFAULT_OPTIONS2 = {
1344
1107
  includeAPI: true,
1345
1108
  includeExamples: true,
@@ -1442,11 +1205,7 @@ function sanitizeTextContent(content) {
1442
1205
  if (index > lastIndex) {
1443
1206
  parts.push(sanitizeContent(content.slice(lastIndex, index)));
1444
1207
  }
1445
- if (isClosing) {
1446
- parts.push(tag);
1447
- } else {
1448
- parts.push(sanitizeJSXTag(tag));
1449
- }
1208
+ parts.push(isClosing ? tag : sanitizeJSXTag(tag));
1450
1209
  lastIndex = index + tag.length;
1451
1210
  }
1452
1211
  if (lastIndex < content.length) {
@@ -1471,17 +1230,23 @@ function validateMDXSyntax(mdx) {
1471
1230
  }
1472
1231
  return ok2(true);
1473
1232
  }
1233
+ function isTypeScriptGeneric(tag) {
1234
+ const tagNameMatch = tag.match(/<\/?([A-Z][a-zA-Z0-9]*)/);
1235
+ const tagName = tagNameMatch?.[1];
1236
+ return tagName !== void 0 && tagName.length === 1;
1237
+ }
1474
1238
  function checkForUnclosedTags(mdx) {
1475
1239
  const unclosed = [];
1476
1240
  const tagStack = [];
1477
1241
  const codeBlocks = extractCodeBlocks(mdx);
1478
- let contentWithoutCodeBlocks = mdx;
1242
+ let contentWithoutCode = mdx;
1479
1243
  for (const block of codeBlocks) {
1480
1244
  const lineCount = block.split("\n").length;
1481
1245
  const placeholder = "\n".repeat(lineCount);
1482
- contentWithoutCodeBlocks = contentWithoutCodeBlocks.replace(block, placeholder);
1246
+ contentWithoutCode = contentWithoutCode.replace(block, placeholder);
1483
1247
  }
1484
- const jsxTags = parseJSXTags(contentWithoutCodeBlocks);
1248
+ const allJSXTags = parseJSXTags(contentWithoutCode);
1249
+ const jsxTags = allJSXTags.filter(({ tag }) => !isTypeScriptGeneric(tag));
1485
1250
  for (const { tag, isClosing, isSelfClosing } of jsxTags) {
1486
1251
  const tagNameMatch = isClosing ? tag.match(/^<\/([A-Z][a-zA-Z0-9]*)>$/) : tag.match(/^<([A-Z][a-zA-Z0-9]*)/);
1487
1252
  const tagName = tagNameMatch?.[1];
@@ -1548,13 +1313,9 @@ export {
1548
1313
  generateFrontmatter,
1549
1314
  stringifyFrontmatter,
1550
1315
  parseFrontmatter,
1551
- createHeadingPattern,
1552
- hasComponent,
1553
- extractCodeBlocks,
1554
- findEmptyMarkdownLinks,
1555
1316
  generateMDXDocument,
1556
1317
  sanitizeContent,
1557
1318
  sanitizeTextContent,
1558
1319
  validateMDXSyntax
1559
1320
  };
1560
- //# sourceMappingURL=chunk-G5KKGJYO.js.map
1321
+ //# sourceMappingURL=chunk-CUBMCGAY.js.map
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-DRBRT57F.js.map