this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix markdown generator to combine type definitions into unified code blocks

Instead of rendering each constructor as a separate code block with
interleaved prose documentation, combine them into a single code block
with inline doc comments ((** ... *)). This produces much more coherent
output for LLM consumption.

Cherry-picked from jonludlam/odoc@6ed5e8ea9

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+89 -16
+89 -16
src/markdown2/generator.ml
··· 305 305 match header with Some header -> Some header | None -> None 306 306 in 307 307 let inline_source = source inline_text_only code in 308 - let code = [ String.concat ~sep:"" inline_source ] in 309 - let block = Renderer.Block.Code_block { info_string; code } in 310 - [ block ] @ to_markdown rest 308 + let initial_code = String.concat ~sep:"" inline_source in 309 + 310 + (* Check if the rest starts with Documented/Nested items - if so, combine them *) 311 + (match rest with 312 + | (Documented _ | Nested _) :: _ -> 313 + let l, _, remaining_rest = take_descr rest in 314 + (* Combine the initial code with the documented items *) 315 + let combine_code_with_docs initial_code items = 316 + let rec collect_lines acc = function 317 + | [] -> List.rev acc 318 + | { attrs = _; anchor = _; code; doc; markers = _ } :: rest -> 319 + let code_line = match code with 320 + | `D code -> 321 + let inline_source = inline ~config ~resolve code in 322 + let code_text = String.concat ~sep:"" (List.concat_map (function 323 + | Renderer.Inline.Text s -> [s] 324 + | _ -> []) inline_source) in 325 + String.trim code_text 326 + | `N n -> 327 + (* For nested items, recursively process them *) 328 + let nested_blocks = to_markdown n in 329 + String.concat ~sep:"\n" (List.concat_map (function 330 + | Renderer.Block.Code_block { code; _ } -> code 331 + | _ -> []) nested_blocks) 332 + in 333 + let doc_comment = match doc with 334 + | [] -> "" 335 + | doc_blocks -> 336 + let doc_text = String.concat ~sep:"" (block_text_only doc_blocks) in 337 + let cleaned_text = String.trim doc_text in 338 + if cleaned_text = "" then "" 339 + else " (** " ^ cleaned_text ^ " *)" 340 + in 341 + let combined_line = code_line ^ doc_comment in 342 + collect_lines (combined_line :: acc) rest 343 + in 344 + let constructor_lines = collect_lines [] items in 345 + String.trim initial_code :: constructor_lines 346 + in 347 + let combined_lines = combine_code_with_docs initial_code l in 348 + if combined_lines <> [] then 349 + let combined_code = String.concat ~sep:"\n" combined_lines in 350 + let code_block = Renderer.Block.Code_block { info_string; code = [combined_code] } in 351 + [code_block] @ to_markdown remaining_rest 352 + else 353 + let code = [ initial_code ] in 354 + let block = Renderer.Block.Code_block { info_string; code } in 355 + [ block ] @ to_markdown rest 356 + | _ -> 357 + let code = [ initial_code ] in 358 + let block = Renderer.Block.Code_block { info_string; code } in 359 + [ block ] @ to_markdown rest) 311 360 | Subpage subp :: _ -> subpage ~config ~resolve subp 312 361 | (Documented _ | Nested _) :: _ -> 313 362 let l, _, rest = take_descr t in 314 - let one { attrs = _; anchor = _; code; doc; markers = _ } = 315 - let content = 316 - match code with 317 - | `D code -> 318 - let inline_source = inline ~config ~resolve code in 319 - let inlines = Renderer.Inline.Inlines inline_source in 320 - let block = Renderer.Block.Paragraph inlines in 321 - [ block ] 322 - | `N n -> to_markdown n 363 + (* Combine code and documentation into a single code block with inline comments *) 364 + let combine_code_with_docs items = 365 + let rec collect_lines acc = function 366 + | [] -> List.rev acc 367 + | { attrs = _; anchor = _; code; doc; markers = _ } :: rest -> 368 + let code_line = match code with 369 + | `D code -> 370 + let inline_source = inline ~config ~resolve code in 371 + let code_text = String.concat ~sep:"" (List.concat_map (function 372 + | Renderer.Inline.Text s -> [s] 373 + | _ -> []) inline_source) in 374 + String.trim code_text 375 + | `N n -> 376 + (* For nested items, recursively process them *) 377 + let nested_blocks = to_markdown n in 378 + String.concat ~sep:"\n" (List.concat_map (function 379 + | Renderer.Block.Code_block { code; _ } -> code 380 + | _ -> []) nested_blocks) 381 + in 382 + let doc_comment = match doc with 383 + | [] -> "" 384 + | doc_blocks -> 385 + let doc_text = String.concat ~sep:"" (block_text_only doc_blocks) in 386 + let cleaned_text = String.trim doc_text in 387 + if cleaned_text = "" then "" 388 + else " (** " ^ cleaned_text ^ " *)" 389 + in 390 + let combined_line = code_line ^ doc_comment in 391 + collect_lines (combined_line :: acc) rest 323 392 in 324 - let block_doc = block ~config ~resolve doc in 325 - List.append content block_doc 393 + collect_lines [] items 326 394 in 327 - let all_blocks = List.concat_map one l in 328 - all_blocks @ to_markdown rest 395 + let combined_lines = combine_code_with_docs l in 396 + if combined_lines <> [] then 397 + let combined_code = String.concat ~sep:"\n" combined_lines in 398 + let code_block = Renderer.Block.Code_block { info_string = None; code = [combined_code] } in 399 + [code_block] @ to_markdown rest 400 + else 401 + to_markdown rest 329 402 in 330 403 to_markdown t 331 404