@nshipster/sosumi 1.0.4 → 1.0.5

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nshipster/sosumi",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Making Apple docs AI-readable",
5
5
  "license": "MIT",
6
6
  "author": "NSHipster",
@@ -5,6 +5,7 @@
5
5
  import type {
6
6
  AppleDocJSON,
7
7
  ContentItem,
8
+ Declaration,
8
9
  IndexContentItem,
9
10
  PossibleValueItem,
10
11
  PropertyItem,
@@ -227,10 +228,25 @@ function generateBreadcrumbs(sourceUrl: string, externalOrigin?: string): string
227
228
  return `${breadcrumbs}\n\n`
228
229
  }
229
230
 
231
+ /**
232
+ * Map a DocC language code to a Markdown code-fence identifier. DocC uses
233
+ * `occ` for Objective-C internally, but Markdown highlighters expect `objc`.
234
+ */
235
+ function normalizeFenceLanguage(syntax: string): string {
236
+ return syntax === "occ" ? "objc" : syntax
237
+ }
238
+
239
+ /**
240
+ * Tab titles DocC uses for language-variant code examples. Used to detect
241
+ * whether a `tabNavigator` is a language switch (so we can default to Swift)
242
+ * versus some other tabbed content we should leave alone.
243
+ */
244
+ const LANGUAGE_TAB_TITLES = new Set(["Swift", "Objective-C"])
245
+
230
246
  /**
231
247
  * Render declaration sections
232
248
  */
233
- function renderDeclarations(declarations: Array<{ tokens?: Array<{ text?: string }> }>): string {
249
+ function renderDeclarations(declarations: Declaration[]): string {
234
250
  let markdown = ""
235
251
 
236
252
  for (const decl of declarations) {
@@ -242,7 +258,8 @@ function renderDeclarations(declarations: Array<{ tokens?: Array<{ text?: string
242
258
  .join("")
243
259
  .trim()
244
260
 
245
- markdown += `\`\`\`swift\n${code}\n\`\`\`\n\n`
261
+ const fence = decl.languages?.includes("occ") ? "objc" : "swift"
262
+ markdown += `\`\`\`${fence}\n${code}\n\`\`\`\n\n`
246
263
  }
247
264
  }
248
265
 
@@ -399,7 +416,7 @@ function renderContentArray(
399
416
  } else {
400
417
  code = String(item.code || "")
401
418
  }
402
- const syntax = item.syntax || "swift"
419
+ const syntax = normalizeFenceLanguage(item.syntax || "swift")
403
420
 
404
421
  markdown += `\`\`\`${syntax}\n${code}\n\`\`\`\n\n`
405
422
  } else if (item.type === "unorderedList") {
@@ -439,10 +456,24 @@ function renderContentArray(
439
456
  } else if (item.type === "table") {
440
457
  markdown += renderTable(item, references, depth, externalOrigin)
441
458
  } else if (item.type === "tabNavigator" && item.tabs?.length) {
442
- for (const tab of item.tabs) {
443
- const label = tab.title?.trim()
444
- if (label) {
445
- markdown += `**${label}**\n\n`
459
+ // Only filter when every tab is a known language tab — otherwise
460
+ // `tabNavigator` may carry non-language content (e.g. platform or
461
+ // theme variants) that we shouldn't drop.
462
+ const allLanguageTabs = item.tabs.every(
463
+ (tab) => tab.title != null && LANGUAGE_TAB_TITLES.has(tab.title.trim()),
464
+ )
465
+ let tabsToRender = item.tabs
466
+ if (allLanguageTabs) {
467
+ const swiftTabs = item.tabs.filter((tab) => tab.title?.trim() === "Swift")
468
+ tabsToRender = swiftTabs.length > 0 ? swiftTabs : item.tabs
469
+ }
470
+ const showLabel = tabsToRender.length > 1
471
+ for (const tab of tabsToRender) {
472
+ if (showLabel) {
473
+ const label = tab.title?.trim()
474
+ if (label) {
475
+ markdown += `**${label}**\n\n`
476
+ }
446
477
  }
447
478
  if (tab.content?.length) {
448
479
  markdown += renderContentArray(tab.content, references, depth + 1, externalOrigin)
package/src/lib/types.ts CHANGED
@@ -86,6 +86,7 @@ export interface ContentItem {
86
86
  */
87
87
  export interface Declaration {
88
88
  tokens?: Token[]
89
+ languages?: string[]
89
90
  }
90
91
 
91
92
  /**