@bfra.me/doc-sync 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -497,6 +497,9 @@ function isFeatureSection(heading, featureSections) {
497
497
  function isInstallationSection(heading, tabSections) {
498
498
  return tabSections.some((tab) => heading.includes(tab.toLowerCase()));
499
499
  }
500
+ function escapeAngleBrackets(text) {
501
+ return text.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
502
+ }
500
503
  function mapFeatureSection(section) {
501
504
  const lines = [];
502
505
  lines.push(`## ${section.heading}`);
@@ -507,7 +510,7 @@ function mapFeatureSection(section) {
507
510
  for (const feature of features) {
508
511
  const icon = inferFeatureIcon(feature.title, feature.emoji);
509
512
  lines.push(` <Card title="${sanitizeAttribute(feature.title)}" icon="${icon}">`);
510
- lines.push(` ${feature.description}`);
513
+ lines.push(` ${escapeAngleBrackets(feature.description)}`);
511
514
  lines.push(" </Card>");
512
515
  }
513
516
  lines.push("</CardGrid>");
@@ -1315,4 +1318,4 @@ export {
1315
1318
  sanitizeTextContent,
1316
1319
  validateMDXSyntax
1317
1320
  };
1318
- //# sourceMappingURL=chunk-LOB73H77.js.map
1321
+ //# sourceMappingURL=chunk-CUBMCGAY.js.map
@@ -2,12 +2,12 @@ import {
2
2
  generateMDXDocument,
3
3
  mergeContent,
4
4
  validateMDXSyntax
5
- } from "./chunk-LOB73H77.js";
5
+ } from "./chunk-CUBMCGAY.js";
6
6
  import {
7
7
  analyzePublicAPI,
8
8
  parsePackageComplete,
9
9
  parseReadmeFile
10
- } from "./chunk-6NKAJT2M.js";
10
+ } from "./chunk-VHUUC45J.js";
11
11
  import {
12
12
  createHeadingPattern,
13
13
  extractCodeBlocks,
@@ -710,4 +710,4 @@ export {
710
710
  createSyncOrchestrator,
711
711
  isValidFilePath
712
712
  };
713
- //# sourceMappingURL=chunk-NC7YTZAL.js.map
713
+ //# sourceMappingURL=chunk-DTXB5PMR.js.map
@@ -1074,11 +1074,11 @@ function extractTextFromNode(node) {
1074
1074
  }
1075
1075
  function serializeNode(node) {
1076
1076
  if (node.type === "paragraph") {
1077
- return extractTextFromNode(node);
1077
+ return serializeInlineContent(node);
1078
1078
  }
1079
1079
  if (node.type === "heading") {
1080
1080
  const prefix = "#".repeat(node.depth);
1081
- return `${prefix} ${extractTextFromNode(node)}`;
1081
+ return `${prefix} ${serializeInlineContent(node)}`;
1082
1082
  }
1083
1083
  if (node.type === "code") {
1084
1084
  return `\`\`\`${node.lang ?? ""}
@@ -1108,6 +1108,38 @@ ${node.value}
1108
1108
  }
1109
1109
  return extractTextFromNode(node);
1110
1110
  }
1111
+ function serializeInlineContent(node) {
1112
+ if ("value" in node && typeof node.value === "string") {
1113
+ return node.value;
1114
+ }
1115
+ if (!("children" in node) || !Array.isArray(node.children)) {
1116
+ return "";
1117
+ }
1118
+ return node.children.map((child) => {
1119
+ if (child.type === "strong") {
1120
+ return `**${serializeInlineContent(child)}**`;
1121
+ }
1122
+ if (child.type === "emphasis") {
1123
+ return `*${serializeInlineContent(child)}*`;
1124
+ }
1125
+ if (child.type === "inlineCode") {
1126
+ return `\`${"value" in child ? child.value : ""}\``;
1127
+ }
1128
+ if (child.type === "link") {
1129
+ const text = serializeInlineContent(child);
1130
+ return `[${text}](${"url" in child ? child.url : ""})`;
1131
+ }
1132
+ if (child.type === "image") {
1133
+ const alt = "alt" in child ? child.alt : "";
1134
+ const url = "url" in child ? child.url : "";
1135
+ return `![${alt}](${url})`;
1136
+ }
1137
+ if ("value" in child && typeof child.value === "string") {
1138
+ return child.value;
1139
+ }
1140
+ return serializeInlineContent(child);
1141
+ }).join("");
1142
+ }
1111
1143
  function serializeTable(node) {
1112
1144
  if (node.type !== "table" || !("children" in node)) {
1113
1145
  return "";
@@ -1230,4 +1262,4 @@ export {
1230
1262
  flattenSections,
1231
1263
  getTableOfContents
1232
1264
  };
1233
- //# sourceMappingURL=chunk-6NKAJT2M.js.map
1265
+ //# sourceMappingURL=chunk-VHUUC45J.js.map
package/lib/cli/index.js CHANGED
@@ -3,15 +3,15 @@ import {
3
3
  createPackageScanner,
4
4
  createSyncOrchestrator,
5
5
  createValidationPipeline
6
- } from "../chunk-NC7YTZAL.js";
6
+ } from "../chunk-DTXB5PMR.js";
7
7
  import {
8
8
  generateMDXDocument,
9
9
  mergeContent
10
- } from "../chunk-LOB73H77.js";
10
+ } from "../chunk-CUBMCGAY.js";
11
11
  import "../chunk-ROLA7SBB.js";
12
12
  import {
13
13
  getUnscopedName
14
- } from "../chunk-6NKAJT2M.js";
14
+ } from "../chunk-VHUUC45J.js";
15
15
  import "../chunk-GZ2MP3VN.js";
16
16
  import "../chunk-45NROJIG.js";
17
17
 
@@ -34,7 +34,7 @@ import {
34
34
  validateMarkerPairing,
35
35
  wrapAutoSection,
36
36
  wrapManualSection
37
- } from "../chunk-LOB73H77.js";
37
+ } from "../chunk-CUBMCGAY.js";
38
38
  import "../chunk-ROLA7SBB.js";
39
39
  import "../chunk-GZ2MP3VN.js";
40
40
  export {
package/lib/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  isValidFilePath,
9
9
  validateContentString,
10
10
  validateDocument
11
- } from "./chunk-NC7YTZAL.js";
11
+ } from "./chunk-DTXB5PMR.js";
12
12
  import {
13
13
  cleanCodeExample,
14
14
  createBadge,
@@ -45,7 +45,7 @@ import {
45
45
  validateMarkerPairing,
46
46
  wrapAutoSection,
47
47
  wrapManualSection
48
- } from "./chunk-LOB73H77.js";
48
+ } from "./chunk-CUBMCGAY.js";
49
49
  import {
50
50
  SENTINEL_MARKERS
51
51
  } from "./chunk-ROLA7SBB.js";
@@ -104,7 +104,7 @@ import {
104
104
  parseReadmeFile,
105
105
  parseSourceContent,
106
106
  parseSourceFile
107
- } from "./chunk-6NKAJT2M.js";
107
+ } from "./chunk-VHUUC45J.js";
108
108
  import "./chunk-DRBRT57F.js";
109
109
  import {
110
110
  createHeadingPattern,
@@ -8,10 +8,10 @@ import {
8
8
  isValidFilePath,
9
9
  validateContentString,
10
10
  validateDocument
11
- } from "../chunk-NC7YTZAL.js";
12
- import "../chunk-LOB73H77.js";
11
+ } from "../chunk-DTXB5PMR.js";
12
+ import "../chunk-CUBMCGAY.js";
13
13
  import "../chunk-ROLA7SBB.js";
14
- import "../chunk-6NKAJT2M.js";
14
+ import "../chunk-VHUUC45J.js";
15
15
  import "../chunk-GZ2MP3VN.js";
16
16
  import "../chunk-45NROJIG.js";
17
17
  export {
@@ -53,7 +53,7 @@ import {
53
53
  parseReadmeFile,
54
54
  parseSourceContent,
55
55
  parseSourceFile
56
- } from "../chunk-6NKAJT2M.js";
56
+ } from "../chunk-VHUUC45J.js";
57
57
  export {
58
58
  analyzePublicAPI,
59
59
  analyzeTypeScriptContent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bfra.me/doc-sync",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Intelligent documentation synchronization engine for automatic Astro Starlight site updates",
5
5
  "keywords": [
6
6
  "astro",
@@ -82,7 +82,7 @@
82
82
  "remark-parse": "11.0.0",
83
83
  "ts-morph": "27.0.2",
84
84
  "unified": "11.0.5",
85
- "zod": "4.1.13",
85
+ "zod": "4.2.1",
86
86
  "@bfra.me/es": "0.1.0"
87
87
  },
88
88
  "devDependencies": {
@@ -111,6 +111,16 @@ function isInstallationSection(heading: string, tabSections: readonly string[]):
111
111
  return tabSections.some(tab => heading.includes(tab.toLowerCase()))
112
112
  }
113
113
 
114
+ /**
115
+ * Escape angle brackets in text to prevent MDX JSX tag misinterpretation
116
+ * This is applied to section content to prevent TypeScript generics like Result<T, E>
117
+ * from being interpreted as unclosed JSX tags
118
+ */
119
+ function escapeAngleBrackets(text: string): string {
120
+ // Escape all < and > to HTML entities
121
+ return text.replaceAll('<', '&lt;').replaceAll('>', '&gt;')
122
+ }
123
+
114
124
  function mapFeatureSection(section: ReadmeSection): string {
115
125
  const lines: string[] = []
116
126
 
@@ -124,7 +134,7 @@ function mapFeatureSection(section: ReadmeSection): string {
124
134
  for (const feature of features) {
125
135
  const icon = inferFeatureIcon(feature.title, feature.emoji)
126
136
  lines.push(` <Card title="${sanitizeAttribute(feature.title)}" icon="${icon}">`)
127
- lines.push(` ${feature.description}`)
137
+ lines.push(` ${escapeAngleBrackets(feature.description)}`)
128
138
  lines.push(' </Card>')
129
139
  }
130
140
  lines.push('</CardGrid>')
@@ -183,12 +183,12 @@ function extractTextFromNode(node: RootContent): string {
183
183
 
184
184
  function serializeNode(node: RootContent): string {
185
185
  if (node.type === 'paragraph') {
186
- return extractTextFromNode(node)
186
+ return serializeInlineContent(node)
187
187
  }
188
188
 
189
189
  if (node.type === 'heading') {
190
190
  const prefix = '#'.repeat(node.depth)
191
- return `${prefix} ${extractTextFromNode(node)}`
191
+ return `${prefix} ${serializeInlineContent(node)}`
192
192
  }
193
193
 
194
194
  if (node.type === 'code') {
@@ -227,6 +227,59 @@ function serializeNode(node: RootContent): string {
227
227
  return extractTextFromNode(node)
228
228
  }
229
229
 
230
+ /**
231
+ * Serialize inline content preserving markdown formatting like **bold**, *italic*, `code`, etc.
232
+ */
233
+ function serializeInlineContent(node: RootContent): string {
234
+ if ('value' in node && typeof node.value === 'string') {
235
+ return node.value
236
+ }
237
+
238
+ if (!('children' in node) || !Array.isArray(node.children)) {
239
+ return ''
240
+ }
241
+
242
+ return (node.children as RootContent[])
243
+ .map(child => {
244
+ // Handle strong (bold) text
245
+ if (child.type === 'strong') {
246
+ return `**${serializeInlineContent(child)}**`
247
+ }
248
+
249
+ // Handle emphasis (italic) text
250
+ if (child.type === 'emphasis') {
251
+ return `*${serializeInlineContent(child)}*`
252
+ }
253
+
254
+ // Handle inline code
255
+ if (child.type === 'inlineCode') {
256
+ return `\`${'value' in child ? child.value : ''}\``
257
+ }
258
+
259
+ // Handle links
260
+ if (child.type === 'link') {
261
+ const text = serializeInlineContent(child)
262
+ return `[${text}](${'url' in child ? child.url : ''})`
263
+ }
264
+
265
+ // Handle images
266
+ if (child.type === 'image') {
267
+ const alt = 'alt' in child ? child.alt : ''
268
+ const url = 'url' in child ? child.url : ''
269
+ return `![${alt}](${url})`
270
+ }
271
+
272
+ // Handle plain text
273
+ if ('value' in child && typeof child.value === 'string') {
274
+ return child.value
275
+ }
276
+
277
+ // Recursively handle other inline elements
278
+ return serializeInlineContent(child)
279
+ })
280
+ .join('')
281
+ }
282
+
230
283
  function serializeTable(node: RootContent): string {
231
284
  if (node.type !== 'table' || !('children' in node)) {
232
285
  return ''