package quill
Interactive notebook for OCaml data science
Install
Dune Dependency
Authors
Maintainers
Sources
raven-1.0.0.alpha0.tbz
sha256=a9a8a9787f8250337187bb7b21cb317c41bfd2ecf08bcfe0ab407c7b6660764d
sha512=fe13cf257c487e41efe2967be147d80fa94bac8996d3aab2b8fd16f0bbbd108c15e0e58c025ec9bf294d4a0d220ca2ba00c3b1b42fa2143f758c5f0ee4c15782
doc/src/quill.editor/model_dom.ml.html
Source file model_dom.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
open Quill_markdown open Brr_ext let log fmt = Printf.ksprintf (fun s -> Brr.Console.(log [ Jstr.v ("[model_dom] " ^ s) ])) fmt let parse_dom (root : El.t) : Quill_markdown.block list = match El.find_first_by_selector (Jstr.v "#editor") ~root with | None -> log "Could not find editor element"; [] | Some editor_div -> Quill_markdown.reset_ids (); let content = Jstr.to_string (El.text_content editor_div) in log "Parsing content: %s" content; Quill_markdown.document_of_md (String.trim content) let rec text_length_inline inline : int = match inline.inline_content with | Run s -> String.length s | Code_span s -> 2 + String.length s | Emph inner -> 2 + text_length_inline inner | Strong inner -> 4 + text_length_inline inner | Seq items -> List.fold_left (fun acc i -> acc + text_length_inline i) 0 items | Break _ -> 1 | Image { alt; src } -> 2 + text_length_inline alt + 3 + String.length src + 1 | Link { text; href } -> 1 + text_length_inline text + 3 + String.length href + 1 | Raw_html html -> String.length html and text_length_block block : int = match block.content with | Paragraph inline -> text_length_inline inline + 1 (* inline + "\n" *) | Heading (level, inline) -> level + 1 + text_length_inline inline + 1 (* "# " + inline + "\n" *) | Codeblock { code; _ } -> 4 + String.length code + 4 + 1 (* "```\n" + code + "\n```" + "\n" *) | Blank_line () -> 1 (* "\n" *) | Blocks bs -> List.fold_left (fun acc b -> acc + text_length_block b) 0 bs | Thematic_break -> 4 (* "---\n" *) | Block_quote blocks -> List.fold_left (fun acc b -> acc + 2 + text_length_block b) 0 blocks | List (_, _, items) -> List.fold_left (fun acc item -> acc + List.fold_left (fun acc b -> acc + 2 + text_length_block b) 0 item) 0 items | Html_block html -> String.length html + 1 | Link_reference_definition _ -> 0 (* These are typically not visible in rendered output *) let rec find_in_blocks (blocks : block list) (offset : int) : (string * int) option = let rec loop blocks cumulative = match blocks with | [] -> None | b :: rest -> let len = text_length_block b in if offset < cumulative + len then find_in_block b (offset - cumulative) else loop rest (cumulative + len) in loop blocks 0 and find_in_block (block : block) (offset : int) : (string * int) option = match block.content with | Paragraph inline -> find_in_inline inline offset | Heading (level, inline) -> let syntax_len = level + 1 in (* "# " *) if offset < syntax_len then None else find_in_inline inline (offset - syntax_len) | Codeblock { code; _ } -> let syntax_start_len = 4 in (* "```\n" *) let code_len = String.length code in if offset >= syntax_start_len && offset <= syntax_start_len + code_len then Some ("block", block.id) else None | Blank_line () -> if offset = 0 then Some ("block", block.id) else None | Blocks bs -> find_in_blocks bs offset | Thematic_break -> if offset <= 3 then Some ("block", block.id) else None | Block_quote blocks -> find_in_blocks blocks offset | List (_, _, items) -> let rec find_in_items items offset = match items with | [] -> None | item :: rest -> ( match find_in_blocks item offset with | Some result -> Some result | None -> let item_len = List.fold_left (fun acc b -> acc + text_length_block b) 0 item in find_in_items rest (offset - item_len)) in find_in_items items offset | Html_block _ -> Some ("block", block.id) | Link_reference_definition _ -> None and find_in_inline (inline : inline) (offset : int) : (string * int) option = match inline.inline_content with | Run s -> if offset <= String.length s then Some ("inline", inline.id) else None | Code_span s -> let syntax_len = 1 in (* "`" *) let content_len = String.length s in if offset >= syntax_len && offset <= syntax_len + content_len then Some ("inline", inline.id) else None | Emph inner -> let syntax_len = 1 in (* "*" *) let inner_len = text_length_inline inner in if offset >= syntax_len && offset <= syntax_len + inner_len then find_in_inline inner (offset - syntax_len) else None | Strong inner -> let syntax_len = 2 in (* "**" *) let inner_len = text_length_inline inner in if offset >= syntax_len && offset <= syntax_len + inner_len then find_in_inline inner (offset - syntax_len) else None | Seq items -> let rec loop items cumulative = match items with | [] -> None | i :: rest -> let len = text_length_inline i in if offset <= cumulative + len then find_in_inline i (offset - cumulative) else loop rest (cumulative + len) in loop items 0 | Break _ -> if offset = 0 then Some ("inline", inline.id) else None | Image { alt; _ } -> find_in_inline alt offset | Link { text; _ } -> find_in_inline text offset | Raw_html html -> if offset <= String.length html then Some ("inline", inline.id) else None
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>