( diff: ApiDiff, annotations: ReadonlyMap<string, MigrationAnnotation>, importMapSections: string )
| 270 | } |
| 271 | |
| 272 | export const renderMigrationDocument = ( |
| 273 | diff: ApiDiff, |
| 274 | annotations: ReadonlyMap<string, MigrationAnnotation>, |
| 275 | importMapSections: string |
| 276 | ): string => { |
| 277 | const entries = migrationEntries(diff, annotations, importMapSections) |
| 278 | const replacements = importMapReplacements(importMapSections) |
| 279 | const modulesRemoved = removedModules(diff) |
| 280 | const modules = new Map<string, Array<MigrationEntry>>() |
| 281 | for (const entry of entries) { |
| 282 | const group = modules.get(entry.module) |
| 283 | if (group === undefined) { |
| 284 | modules.set(entry.module, [entry]) |
| 285 | } else { |
| 286 | group.push(entry) |
| 287 | } |
| 288 | } |
| 289 | const lines = [ |
| 290 | "<!-- dprint-ignore-file -->", |
| 291 | "", |
| 292 | "# v3 to v4 Migration Reference", |
| 293 | "", |
| 294 | `Base: \`${diff.base.ref}\` (\`${diff.base.sha}\`)`, |
| 295 | "", |
| 296 | `Head: \`${diff.head.ref}\` (\`${diff.head.sha}\`)`, |
| 297 | "", |
| 298 | "This file is generated from the API diff and `migration/annotations/*.yaml`.", |
| 299 | "", |
| 300 | importMapSections.trim(), |
| 301 | "", |
| 302 | "## Removed Modules", |
| 303 | "" |
| 304 | ] |
| 305 | for (const module of modulesRemoved) { |
| 306 | const annotation = annotations.get(module) |
| 307 | const targets = replacements.get(module) |
| 308 | if (annotation !== undefined) { |
| 309 | lines.push( |
| 310 | `- ${codeSpan(module)} -> ${codeSpan(annotation.replacement)}: ${escapeAnnotationText(annotation.note)}` |
| 311 | ) |
| 312 | } else if (targets !== undefined) { |
| 313 | lines.push(`- ${codeSpan(module)} -> ${targets.map(codeSpan).join(", ")}`) |
| 314 | } else if ([...annotations.keys()].some((id) => id.startsWith(`${module}#`))) { |
| 315 | lines.push(`- ${codeSpan(module)}: No single module replacement; follow the curated per-API guidance below.`) |
| 316 | } else { |
| 317 | lines.push(`- ${codeSpan(module)}: TODO: needs module guidance`) |
| 318 | } |
| 319 | } |
| 320 | if (modulesRemoved.length === 0) { |
| 321 | lines.push("No modules were removed.") |
| 322 | } |
| 323 | lines.push( |
| 324 | "", |
| 325 | "## API Reference", |
| 326 | "" |
| 327 | ) |
| 328 | for (const [module, moduleEntries] of modules) { |
| 329 | lines.push(`### ${codeSpan(module)}`, "") |
no test coverage detected