12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273(*---------------------------------------------------------------------------
Copyright (c) 2026 The Raven authors. All rights reserved.
SPDX-License-Identifier: ISC
---------------------------------------------------------------------------*)typespan={first:int;last:int}typeblock_kind=|Paragraph|Headingofint|Block_quote|List|Thematic_break|Table|Blanktypeblock={span:span;kind:block_kind}typet={source:string;blocks:blocklist}letclassify_block=function|Cmarkit.Block.Paragraph_->Paragraph|Cmarkit.Block.Heading(h,_)->Heading(Cmarkit.Block.Heading.levelh)|Cmarkit.Block.Code_block_->Paragraph|Cmarkit.Block.Block_quote_->Block_quote|Cmarkit.Block.List_->List|Cmarkit.Block.Thematic_break_->Thematic_break|Cmarkit.Block.Html_block_->Paragraph|Cmarkit.Block.Blank_line_->Blank|Cmarkit.Block.Link_reference_definition_->Blank|Cmarkit.Block.Ext_table_->Table|Cmarkit.Block.Ext_math_block_->Paragraph|Cmarkit.Block.Ext_footnote_definition_->Blank|Cmarkit.Block.Blocks_->Paragraph|_->Paragraphletparsesource=letdoc=Cmarkit.Doc.of_string~locs:true~strict:falsesourceinlettop_blocks=matchCmarkit.Doc.blockdocwith|Cmarkit.Block.Blocks(bs,_)->bs|b->[b]inletblocks=List.filter_map(funb->letloc=Cmarkit.Meta.textloc(Cmarkit.Block.metab)inifCmarkit.Textloc.is_nonelocthenNoneelseletfirst=Cmarkit.Textloc.first_bytelocinletlast=Cmarkit.Textloc.last_bytelocinletkind=classify_blockbinSome{span={first;last};kind})top_blocksin{source;blocks}letsourcet=t.sourceletblockst=t.blocksletactive_blockt~cursor=List.find_opt(funb->cursor>=b.span.first&&cursor<=b.span.last)t.blocksletblock_sourcetblock=letlen=block.span.last-block.span.first+1inString.subt.sourceblock.span.firstlenletto_htmlsource=letdoc=Cmarkit.Doc.of_string~heading_auto_ids:true~strict:falsesourceinCmarkit_html.of_doc~safe:truedocletblock_to_htmltblock=to_html(block_sourcetblock)