@@ -324,7 +324,290 @@ module JsonOutput = struct
324324 ]
325325end
326326
327- module MdOutput = struct end
327+ module MdOutput = struct
328+ let stringifyDocstrings docstrings =
329+ match docstrings with
330+ | [] -> " "
331+ | docstrings ->
332+ docstrings |> List. map String. trim
333+ |> List. filter (fun s -> s <> " " )
334+ |> String. concat " \n\n "
335+
336+ let stringifyFieldDoc (fieldDoc : fieldDoc ) =
337+ let buffer = Buffer. create 256 in
338+ Buffer. add_string buffer
339+ (Printf. sprintf " - **FIELD:** `%s`\n " fieldDoc.fieldName);
340+ Buffer. add_string buffer
341+ (Printf. sprintf " - **TYPE:** `%s`\n " fieldDoc.signature);
342+ Buffer. add_string buffer
343+ (Printf. sprintf " - **OPTIONAL:** %s\n "
344+ (string_of_bool fieldDoc.optional));
345+ (match fieldDoc.deprecated with
346+ | Some d ->
347+ Buffer. add_string buffer (Printf. sprintf " - **DEPRECATED:** %s\n " d)
348+ | None -> () );
349+ (match stringifyDocstrings fieldDoc.docstrings with
350+ | "" -> ()
351+ | docs ->
352+ Buffer. add_string buffer (Printf. sprintf " - **DESCRIPTION:** %s\n " docs));
353+ Buffer. contents buffer
354+
355+ let stringifyConstructorDoc (constructorDoc : constructorDoc ) =
356+ let buffer = Buffer. create 256 in
357+ Buffer. add_string buffer
358+ (Printf. sprintf " - **CONSTRUCTOR:** `%s`\n " constructorDoc.constructorName);
359+ Buffer. add_string buffer
360+ (Printf. sprintf " - **SIGNATURE:** `%s`\n " constructorDoc.signature);
361+ (match constructorDoc.deprecated with
362+ | Some d ->
363+ Buffer. add_string buffer (Printf. sprintf " - **DEPRECATED:** %s\n " d)
364+ | None -> () );
365+ (match stringifyDocstrings constructorDoc.docstrings with
366+ | "" -> ()
367+ | docs ->
368+ Buffer. add_string buffer (Printf. sprintf " - **DESCRIPTION:** %s\n " docs));
369+ (match constructorDoc.items with
370+ | None -> ()
371+ | Some (InlineRecord {fieldDocs} ) ->
372+ Buffer. add_string buffer " - **INLINE_RECORD_FIELDS:**\n " ;
373+ fieldDocs
374+ |> List. iter (fun field ->
375+ let field_lines =
376+ stringifyFieldDoc field |> String. split_on_char '\n'
377+ in
378+ field_lines
379+ |> List. iter (fun line ->
380+ if String. trim line <> " " then
381+ Buffer. add_string buffer (" " ^ line ^ " \n " ))));
382+ Buffer. contents buffer
383+
384+ let stringifyDetail (detail : docItemDetail ) =
385+ match detail with
386+ | Record {fieldDocs} ->
387+ let buffer = Buffer. create 512 in
388+ Buffer. add_string buffer " \n **RECORD_FIELDS:**\n " ;
389+ fieldDocs
390+ |> List. iter (fun field ->
391+ Buffer. add_string buffer (stringifyFieldDoc field ^ " \n " ));
392+ Buffer. contents buffer
393+ | Variant {constructorDocs} ->
394+ let buffer = Buffer. create 512 in
395+ Buffer. add_string buffer " \n **VARIANT_CONSTRUCTORS:**\n " ;
396+ constructorDocs
397+ |> List. iter (fun constructor ->
398+ Buffer. add_string buffer
399+ (stringifyConstructorDoc constructor ^ " \n " ));
400+ Buffer. contents buffer
401+ | Signature {parameters = _ ; returnType = _ } ->
402+ (* For function signatures, we could add parameter details, but for now keep it simple *)
403+ " "
404+
405+ let stringifySource (source : source ) =
406+ Printf. sprintf " **SOURCE:** %s:%d:%d" source.filepath source.line source.col
407+
408+ let rec stringifyDocItem ?(depth = 2 ) (item : docItem ) =
409+ let heading = String. make depth '#' ^ " " in
410+
411+ match item with
412+ | Value {name; docstring; signature; deprecated; detail; source} ->
413+ let buffer = Buffer. create 1024 in
414+ Buffer. add_string buffer (Printf. sprintf " %s%s\n\n " heading name);
415+ Buffer. add_string buffer " **KIND:** VALUE\n\n " ;
416+ Buffer. add_string buffer
417+ (Printf. sprintf " **SIGNATURE:** `%s`\n\n " signature);
418+ Buffer. add_string buffer
419+ (Printf. sprintf " %s\n\n " (stringifySource source));
420+ (match deprecated with
421+ | Some d ->
422+ Buffer. add_string buffer (Printf. sprintf " **DEPRECATED:** %s\n\n " d)
423+ | None -> () );
424+ (match stringifyDocstrings docstring with
425+ | "" -> ()
426+ | docs ->
427+ Buffer. add_string buffer
428+ (Printf. sprintf " **DESCRIPTION:**\n %s\n\n " docs));
429+ (match detail with
430+ | None -> ()
431+ | Some d -> Buffer. add_string buffer (stringifyDetail d ^ " \n " ));
432+ Buffer. contents buffer
433+ | Type {name; docstring; signature; deprecated; detail; source} ->
434+ let buffer = Buffer. create 1024 in
435+ Buffer. add_string buffer (Printf. sprintf " %s%s\n\n " heading name);
436+ Buffer. add_string buffer " **KIND:** TYPE\n\n " ;
437+ Buffer. add_string buffer
438+ (Printf. sprintf " **SIGNATURE:** `%s`\n\n " signature);
439+ Buffer. add_string buffer
440+ (Printf. sprintf " %s\n\n " (stringifySource source));
441+ (match deprecated with
442+ | Some d ->
443+ Buffer. add_string buffer (Printf. sprintf " **DEPRECATED:** %s\n\n " d)
444+ | None -> () );
445+ (match stringifyDocstrings docstring with
446+ | "" -> ()
447+ | docs ->
448+ Buffer. add_string buffer
449+ (Printf. sprintf " **DESCRIPTION:**\n %s\n\n " docs));
450+ (match detail with
451+ | None -> ()
452+ | Some d -> Buffer. add_string buffer (stringifyDetail d ^ " \n " ));
453+ Buffer. contents buffer
454+ | Module m ->
455+ let buffer = Buffer. create 1024 in
456+ Buffer. add_string buffer (Printf. sprintf " %s%s\n\n " heading m.name);
457+ Buffer. add_string buffer " **KIND:** MODULE\n\n " ;
458+ Buffer. add_string buffer
459+ (Printf. sprintf " %s\n\n " (stringifySource m.source));
460+ (match m.moduletypeid with
461+ | Some id ->
462+ Buffer. add_string buffer
463+ (Printf. sprintf " **MODULE_TYPE_ID:** %s\n\n " id)
464+ | None -> () );
465+ (match m.deprecated with
466+ | Some d ->
467+ Buffer. add_string buffer (Printf. sprintf " **DEPRECATED:** %s\n\n " d)
468+ | None -> () );
469+ (match stringifyDocstrings m.docstring with
470+ | "" -> ()
471+ | docs ->
472+ Buffer. add_string buffer
473+ (Printf. sprintf " **DESCRIPTION:**\n %s\n\n " docs));
474+ (match m.items with
475+ | [] -> ()
476+ | items ->
477+ Buffer. add_string buffer " **MODULE_CONTENTS:**\n\n " ;
478+ items
479+ |> List. iter (fun item ->
480+ Buffer. add_string buffer
481+ (stringifyDocItem ~depth: (depth + 1 ) item ^ " \n " )));
482+ Buffer. contents buffer
483+ | ModuleType m ->
484+ let buffer = Buffer. create 1024 in
485+ Buffer. add_string buffer (Printf. sprintf " %s%s\n\n " heading m.name);
486+ Buffer. add_string buffer " **KIND:** MODULE_TYPE\n\n " ;
487+ Buffer. add_string buffer
488+ (Printf. sprintf " %s\n\n " (stringifySource m.source));
489+ (match m.deprecated with
490+ | Some d ->
491+ Buffer. add_string buffer (Printf. sprintf " **DEPRECATED:** %s\n\n " d)
492+ | None -> () );
493+ (match stringifyDocstrings m.docstring with
494+ | "" -> ()
495+ | docs ->
496+ Buffer. add_string buffer
497+ (Printf. sprintf " **DESCRIPTION:**\n %s\n\n " docs));
498+ (match m.items with
499+ | [] -> ()
500+ | items ->
501+ Buffer. add_string buffer " **MODULE_TYPE_CONTENTS:**\n\n " ;
502+ items
503+ |> List. iter (fun item ->
504+ Buffer. add_string buffer
505+ (stringifyDocItem ~depth: (depth + 1 ) item ^ " \n " )));
506+ Buffer. contents buffer
507+ | ModuleAlias m ->
508+ let buffer = Buffer. create 1024 in
509+ Buffer. add_string buffer (Printf. sprintf " %s%s\n\n " heading m.name);
510+ Buffer. add_string buffer " **KIND:** MODULE_ALIAS\n\n " ;
511+ Buffer. add_string buffer
512+ (Printf. sprintf " %s\n\n " (stringifySource m.source));
513+ (match stringifyDocstrings m.docstring with
514+ | "" -> ()
515+ | docs ->
516+ Buffer. add_string buffer
517+ (Printf. sprintf " **DESCRIPTION:**\n %s\n\n " docs));
518+ (match m.items with
519+ | [] -> ()
520+ | items ->
521+ Buffer. add_string buffer " **ALIASED_MODULE_CONTENTS:**\n\n " ;
522+ items
523+ |> List. iter (fun item ->
524+ Buffer. add_string buffer
525+ (stringifyDocItem ~depth: (depth + 1 ) item ^ " \n " )));
526+ Buffer. contents buffer
527+
528+ let stringifyDocsForModule (docs : docsForModule ) =
529+ let buffer = Buffer. create 4096 in
530+
531+ (* Header with metadata *)
532+ Buffer. add_string buffer (Printf. sprintf " # %s\n\n " docs.name);
533+ Buffer. add_string buffer " **KIND:** MODULE\n\n " ;
534+ Buffer. add_string buffer
535+ (Printf. sprintf " %s\n\n " (stringifySource docs.source));
536+
537+ (match docs.deprecated with
538+ | Some d ->
539+ Buffer. add_string buffer (Printf. sprintf " **DEPRECATED:** %s\n\n " d)
540+ | None -> () );
541+
542+ (match stringifyDocstrings docs.docstring with
543+ | "" -> ()
544+ | docs_str ->
545+ Buffer. add_string buffer
546+ (Printf. sprintf " **DESCRIPTION:**\n %s\n\n " docs_str));
547+
548+ (* Group items by type for better organization *)
549+ let values, types, modules, module_types, module_aliases =
550+ docs.items
551+ |> List. fold_left
552+ (fun (vals , typs , mods , mod_typs , mod_aliases ) item ->
553+ match item with
554+ | Value _ -> (item :: vals, typs, mods, mod_typs, mod_aliases)
555+ | Type _ -> (vals, item :: typs, mods, mod_typs, mod_aliases)
556+ | Module _ -> (vals, typs, item :: mods, mod_typs, mod_aliases)
557+ | ModuleType _ -> (vals, typs, mods, item :: mod_typs, mod_aliases)
558+ | ModuleAlias _ -> (vals, typs, mods, mod_typs, item :: mod_aliases))
559+ ([] , [] , [] , [] , [] )
560+ in
561+
562+ let values = List. rev values in
563+ let types = List. rev types in
564+ let modules = List. rev modules in
565+ let module_types = List. rev module_types in
566+ let module_aliases = List. rev module_aliases in
567+
568+ (* Content sections with clear headers *)
569+ (match values with
570+ | [] -> ()
571+ | _ ->
572+ Buffer. add_string buffer " ## VALUES\n\n " ;
573+ values
574+ |> List. iter (fun item ->
575+ Buffer. add_string buffer (stringifyDocItem ~depth: 3 item ^ " \n " )));
576+
577+ (match types with
578+ | [] -> ()
579+ | _ ->
580+ Buffer. add_string buffer " ## TYPES\n\n " ;
581+ types
582+ |> List. iter (fun item ->
583+ Buffer. add_string buffer (stringifyDocItem ~depth: 3 item ^ " \n " )));
584+
585+ (match modules with
586+ | [] -> ()
587+ | _ ->
588+ Buffer. add_string buffer " ## MODULES\n\n " ;
589+ modules
590+ |> List. iter (fun item ->
591+ Buffer. add_string buffer (stringifyDocItem ~depth: 3 item ^ " \n " )));
592+
593+ (match module_types with
594+ | [] -> ()
595+ | _ ->
596+ Buffer. add_string buffer " ## MODULE_TYPES\n\n " ;
597+ module_types
598+ |> List. iter (fun item ->
599+ Buffer. add_string buffer (stringifyDocItem ~depth: 3 item ^ " \n " )));
600+
601+ (match module_aliases with
602+ | [] -> ()
603+ | _ ->
604+ Buffer. add_string buffer " ## MODULE_ALIASES\n\n " ;
605+ module_aliases
606+ |> List. iter (fun item ->
607+ Buffer. add_string buffer (stringifyDocItem ~depth: 3 item ^ " \n " )));
608+
609+ Buffer. contents buffer
610+ end
328611
329612let fieldToFieldDoc (field : SharedTypes.field ) : fieldDoc =
330613 {
@@ -655,5 +938,5 @@ let extractDocsToJson ~entryPointFile ~debug =
655938
656939let extractDocsToMd ~entryPointFile ~debug =
657940 match extractDocs ~entry PointFile ~debug with
658- | Ok (_docs , _env ) -> Ok " wip "
941+ | Ok (docs , _env ) -> Ok ( MdOutput. stringifyDocsForModule docs)
659942 | Error e -> Error e
0 commit comments