From b5e91792e1cf59e5c04418c64d6faedc3ccb9551 Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Mon, 7 Oct 2024 21:03:49 +0300 Subject: [PATCH 1/9] feat: superscript for footnotes --- src/ast_inline.ml | 1 + src/html.ml | 7 +++++++ src/parser.ml | 33 ++++++++++++++++++++++++--------- src/sexp.ml | 1 + src/toc.ml | 1 + tests/attributes.md | 10 ++++++++++ 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/ast_inline.ml b/src/ast_inline.ml index a74c8de9..1d68084c 100644 --- a/src/ast_inline.ml +++ b/src/ast_inline.ml @@ -16,6 +16,7 @@ type 'attr inline = | Link of 'attr * 'attr link | Image of 'attr * 'attr link | Html of 'attr * string + | Sup of 'attr * 'attr inline and 'attr link = { label : 'attr inline diff --git a/src/html.ml b/src/html.ml index dd817d34..219924d3 100644 --- a/src/html.ml +++ b/src/html.ml @@ -169,6 +169,7 @@ let to_plain_text t = go i | Hard_break _ | Soft_break _ -> Buffer.add_char buf ' ' | Html _ -> () + | Sup (_, i) -> go i in go t; Buffer.contents buf @@ -191,6 +192,9 @@ and img label destination title attrs = in elt Inline "img" attrs None +and sup attrs child = + elt Inline "sup" attrs (Some child) + and inline = function | Ast.Impl.Concat (_, l) -> concat_map inline l | Text (_, t) -> text t @@ -204,6 +208,9 @@ and inline = function url label destination title attr | Image (attr, { label; destination; title }) -> img label destination title attr + | Sup (attrs, il) -> + sup attrs (inline il) + (* TODO: handle sup tag *) let alignment_attributes = function | Default -> [] diff --git a/src/parser.ml b/src/parser.ml index 0723c7a7..a41af6b8 100644 --- a/src/parser.ml +++ b/src/parser.ml @@ -1088,7 +1088,13 @@ let link_label allow_balanced_brackets st = Buffer.add_char buf c; loop n true in - loop 0 false + let is_footnote = begin + match peek_exn st with + | '^' -> true + | _ -> false + end in + let label = loop 0 false in + label, is_footnote type add_uchar_result = { start : bool @@ -1676,7 +1682,7 @@ let rec inline defs st = let rec reference_link kind acc st = let off0 = pos st in match protect (link_label true) st with - | lab -> ( + | label, is_footnote -> ( let reflink lab = let s = normalize lab in match @@ -1692,6 +1698,10 @@ let rec inline defs st = | Pre.Img -> Image (attr, def) | Url -> Link (attr, def) in + let r = match is_footnote with + | true -> Sup ([], r) + | false -> r + in loop (Pre.R r :: text acc) st | None -> if kind = Img then Buffer.add_char buf '!'; @@ -1705,22 +1715,22 @@ let rec inline defs st = if peek_after '\000' st = ']' then ( junk st; junk st; - reflink lab) + reflink label) else match protect (link_label false) st with | _ -> set_pos st off0; junk st; loop (Left_bracket kind :: text acc) st - | exception Fail -> reflink lab) + | exception Fail -> reflink label) | Some '(' -> ( match protect inline_link st with | _ -> set_pos st off0; junk st; loop (Left_bracket kind :: text acc) st - | exception Fail -> reflink lab) - | Some _ | None -> reflink lab) + | exception Fail -> reflink label) + | Some _ | None -> reflink label) | exception Fail -> junk st; loop (Left_bracket kind :: text acc) st @@ -1815,11 +1825,12 @@ let rec inline defs st = Buffer.add_char buf ']'; loop ~seen_link acc st) | Some '[' -> ( + (* FIXME: there is a logic duplicate with reference_link *) let label = Pre.parse_emph xs in let off1 = pos st in match link_label false st with - | lab -> ( - let s = normalize lab in + | label_text, is_footnote -> ( + let s = normalize label_text in match List.find_opt (fun ({ label; _ } : attributes link_def) -> @@ -1835,6 +1846,10 @@ let rec inline defs st = | Img -> Image (attr, def) | Url -> Link (attr, def) in + let r = match is_footnote with + | true -> Sup ([], r) + | false -> r + in loop ~seen_link (Pre.R r :: acc') st | None -> if k = Img then Buffer.add_char buf '!'; @@ -1923,7 +1938,7 @@ let link_reference_definition st : attributes link_def = match next st with w when is_whitespace w -> ws st | _ -> raise Fail in ignore (sp3 st); - let label = link_label false st in + let label, _ = link_label false st in if next st <> ':' then raise Fail; ws st; let destination = link_destination st in diff --git a/src/sexp.ml b/src/sexp.ml index f84a3300..4bbc5444 100644 --- a/src/sexp.ml +++ b/src/sexp.ml @@ -21,6 +21,7 @@ and inline = function | Link (_, def) -> List [ Atom "url"; link def ] | Html (_, s) -> List [ Atom "html"; Atom s ] | Image _ -> Atom "img" + | Sup _ -> Atom "sup" let table_header (header, alignment) = List diff --git a/src/toc.ml b/src/toc.ml index 3aac8446..a66b51a6 100644 --- a/src/toc.ml +++ b/src/toc.ml @@ -9,6 +9,7 @@ let rec remove_links inline = | Image (attr, link) -> Image (attr, { link with label = remove_links link.label }) | Hard_break _ | Soft_break _ | Html _ | Code _ | Text _ -> inline + | Sup (_, child) -> remove_links child let headers = let remove_links_f = remove_links in diff --git a/tests/attributes.md b/tests/attributes.md index 615a9c8d..470a748c 100644 --- a/tests/attributes.md +++ b/tests/attributes.md @@ -287,3 +287,13 @@ Ref id attributes testing

Ref 3

Ref 4

```````````````````````````````` + +Footnotes: + +```````````````````````````````` example +[^footnote] + +[^footnote]: link +. +

footnote<\sup>

+```````````````````````````````` \ No newline at end of file From 30e6b15ee3fb337021e9e74738333ad8da8468cf Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Tue, 8 Oct 2024 10:46:51 +0300 Subject: [PATCH 2/9] fix: remove '^' from the footnote labels --- src/parser.ml | 5 +++++ tests/attributes.md | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/parser.ml b/src/parser.ml index a41af6b8..00fc1574 100644 --- a/src/parser.ml +++ b/src/parser.ml @@ -1691,6 +1691,11 @@ let rec inline defs st = defs with | Some { label = _; destination; title; attributes = attr } -> + (* If reference is footnote, we should remove '^' prefix from the text to display *) + let lab = match is_footnote with + | true -> String.sub lab 1 (String.length lab - 1) + | false -> lab + in let lab1 = inline defs (of_string lab) in let r = let def = { label = lab1; destination; title } in diff --git a/tests/attributes.md b/tests/attributes.md index 470a748c..480ddd15 100644 --- a/tests/attributes.md +++ b/tests/attributes.md @@ -295,5 +295,5 @@ Footnotes: [^footnote]: link . -

footnote<\sup>

-```````````````````````````````` \ No newline at end of file +

footnote

+```````````````````````````````` From 1466847efad988db9ed757fc7819108e70bf57a6 Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Tue, 8 Oct 2024 10:49:38 +0300 Subject: [PATCH 3/9] chore: remove unnecessary changes --- src/parser.ml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/parser.ml b/src/parser.ml index 00fc1574..5545ef19 100644 --- a/src/parser.ml +++ b/src/parser.ml @@ -1834,7 +1834,7 @@ let rec inline defs st = let label = Pre.parse_emph xs in let off1 = pos st in match link_label false st with - | label_text, is_footnote -> ( + | label_text, _ -> ( let s = normalize label_text in match List.find_opt @@ -1851,10 +1851,6 @@ let rec inline defs st = | Img -> Image (attr, def) | Url -> Link (attr, def) in - let r = match is_footnote with - | true -> Sup ([], r) - | false -> r - in loop ~seen_link (Pre.R r :: acc') st | None -> if k = Img then Buffer.add_char buf '!'; From 1e61ae835d5ac4be3d7e82985ec6fe537fd25fb8 Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Tue, 8 Oct 2024 16:59:12 +0300 Subject: [PATCH 4/9] feat: footnotes --- src/ast_block.ml | 7 +++++++ src/html.ml | 20 ++++++++++++++++++-- src/omd.ml | 22 +++++++++++++++++++++- src/parser.ml | 41 ++++++++++++++++++++++++++++++++--------- src/sexp.ml | 1 + src/toc.ml | 3 ++- tests/attributes.md | 6 +++++- tests/dune.inc | 9 +++++++++ 8 files changed, 95 insertions(+), 14 deletions(-) diff --git a/src/ast_block.ml b/src/ast_block.ml index 3ca545d9..8b988968 100644 --- a/src/ast_block.ml +++ b/src/ast_block.ml @@ -37,6 +37,8 @@ module Make (C : BlockContent) = struct ; defs : 'attr C.t list } + type 'attr footnote = { id: string; label: string; content: 'attr C.t } + (* A value of type 'attr is present in all variants of this type. We use it to associate extra information to each node in the AST. Cn the common case, the attributes type defined above is used. We might eventually have an alternative function to parse blocks while keeping @@ -51,6 +53,7 @@ module Make (C : BlockContent) = struct | Html_block of 'attr * string | Definition_list of 'attr * 'attr def_elt list | Table of 'attr * ('attr C.t * cell_alignment) list * 'attr C.t list list + | Footnote_list of 'attr footnote list (** A table is represented by a header row, which is a list of pairs of header cells and alignments, and a list of rows *) end @@ -79,6 +82,10 @@ module MakeMapper (Src : BlockContent) (Dst : BlockContent) = struct ( attr , List.map (fun (header, alignment) -> (f header, alignment)) headers , List.map (List.map f) rows ) + | Footnote_list footnotes -> + Footnote_list + (List.map (fun { SrcBlock.id; content; label } -> { DstBlock.id = id; content = f content; label }) + footnotes) end module Mapper = MakeMapper (StringContent) (InlineContent) diff --git a/src/html.ml b/src/html.ml index 219924d3..db7964c7 100644 --- a/src/html.ml +++ b/src/html.ml @@ -113,7 +113,7 @@ module Identifiers : sig val empty : t val touch : string -> t -> int * t - (** Bump the frequency count for the given string. + (** Bump the frequency count for the given string. It returns the previous count (before bumping) *) end = struct module SMap = Map.Make (String) @@ -210,7 +210,6 @@ and inline = function img label destination title attr | Sup (attrs, il) -> sup attrs (inline il) - (* TODO: handle sup tag *) let alignment_attributes = function | Default -> [] @@ -317,6 +316,23 @@ let rec block ~auto_identifiers = function "table" attr (Some (concat (table_header headers) (table_body headers rows))) + | Footnote_list footnotes -> + let footnote_block content = + elt Block "div" [("class", "footnotes")] (Some content) + and footnote_list footnotes = + let footnote_p footnote = + (elt + Block "p" [] + (Some + (concat + (inline footnote.content) + (elt Block "a" [("href", "#fnref:" ^ footnote.label)] (Some (text "↩")))))) + in + elt Block "ol" [] + (Some (concat_map + (fun footnote -> elt Block "li" [("id", footnote.id)] (Some (footnote_p footnote))) footnotes)) + in + footnote_block (footnote_list footnotes) let of_doc ?(auto_identifiers = true) doc = let identifiers = Identifiers.empty in diff --git a/src/omd.ml b/src/omd.ml index d00f26bf..0d27e053 100644 --- a/src/omd.ml +++ b/src/omd.ml @@ -22,7 +22,27 @@ let parse_inlines (md, defs) : doc = in List.map f defs in - List.map (Ast_block.Mapper.map (parse_inline defs)) md + (* List.iter + (fun def -> Printf.printf + "def: %s, kind=%s\n" + def.Parser.label + (match def.Parser.kind with + | Parser.Footnote -> "Footnote" + | Parser.Reference -> "Reference")) + defs;*) + let footnotes = List.filter_map + (fun def -> match def.Parser.kind with + | Footnote { id; label; } -> Some ({ id; label; Ast_block.Raw.content = def.destination; }) + | _ -> None) + defs + in + let footnote_block : _ Ast_block.Raw.block = Footnote_list footnotes + in + let md = match List.is_empty footnotes with + | true -> md + | false -> md @ [footnote_block] + in + (List.map (Ast_block.Mapper.map (parse_inline defs)) md) let escape_html_entities = Html.htmlentities let of_channel ic : doc = parse_inlines (Block_parser.Pre.of_channel ic) diff --git a/src/parser.ml b/src/parser.ml index 5545ef19..ef5341ce 100644 --- a/src/parser.ml +++ b/src/parser.ml @@ -1,10 +1,15 @@ open Ast.Impl +type link_kind = + | Reference + | Footnote of { id: string; label: string } + type 'attr link_def = { label : string ; destination : string ; title : string option ; attributes : 'attr + ; kind : link_kind } let is_whitespace = function @@ -1690,11 +1695,20 @@ let rec inline defs st = (fun ({ label; _ } : attributes link_def) -> label = s) defs with - | Some { label = _; destination; title; attributes = attr } -> + | Some { destination; title; attributes = attr; kind = link_kind; _ } -> (* If reference is footnote, we should remove '^' prefix from the text to display *) - let lab = match is_footnote with - | true -> String.sub lab 1 (String.length lab - 1) - | false -> lab + let lab = match link_kind with + | Footnote { label; _ } -> label + | Reference -> lab + in + (* Printf.sprintf "#fn:%s" reference*) + let attr = match link_kind with + | Footnote { label; _ } -> ("id", "fnref:" ^ label) :: attr + | Reference -> attr + in + let destination = match link_kind with + | Footnote { id; _ } -> "#" ^ id + | Reference -> destination in let lab1 = inline defs (of_string lab) in let r = @@ -1843,7 +1857,7 @@ let rec inline defs st = defs with | Some - { label = _; destination; title; attributes = attr } + { destination; title; attributes = attr; _ } -> let def = { label; destination; title } in let r = @@ -1939,16 +1953,25 @@ let link_reference_definition st : attributes link_def = match next st with w when is_whitespace w -> ws st | _ -> raise Fail in ignore (sp3 st); - let label, _ = link_label false st in + (* TODO: return kind directly *) + let label, is_footnote = link_label false st in + (* Printf.printf "label:%s, is_footnote:%s\n" label (Bool.to_string is_footnote);*) if next st <> ':' then raise Fail; ws st; let destination = link_destination st in let attributes = inline_attribute_string st in + let kind = match is_footnote with + | true -> + let label = (String.sub label 1 (String.length label - 1)) in + Footnote { id = Printf.sprintf "fn:%s" label; label; } + | false -> Reference + in match protect (ws1 >>> link_title <<< sp <<< eol) st with - | title -> { label; destination; title = Some title; attributes } + | title -> + { label; destination; title = Some title; attributes; kind } | exception Fail -> - (sp >>> eol) st; - { label; destination; title = None; attributes } + (sp >>> eol) st; + { label; destination; title = None; attributes; kind; } let link_reference_definitions st = let rec loop acc = diff --git a/src/sexp.ml b/src/sexp.ml index 4bbc5444..778904b7 100644 --- a/src/sexp.ml +++ b/src/sexp.ml @@ -61,6 +61,7 @@ let rec block = function ; List (List.map table_header headers) ; List (List.map (fun row -> List (List.map inline row)) rows) ] + | Footnote_list _footnotes -> List [] let create ast = List (List.map block ast) diff --git a/src/toc.ml b/src/toc.ml index a66b51a6..373c8a42 100644 --- a/src/toc.ml +++ b/src/toc.ml @@ -27,7 +27,8 @@ let headers = | List (_, _, _, block_lists) -> List.iter loop block_lists | Paragraph _ | Thematic_break _ | Html_block _ | Definition_list _ | Code_block _ | Table _ -> - ()) + () + | Footnote_list _ -> ()) blocks in loop doc; diff --git a/tests/attributes.md b/tests/attributes.md index 480ddd15..ee05d88b 100644 --- a/tests/attributes.md +++ b/tests/attributes.md @@ -295,5 +295,9 @@ Footnotes: [^footnote]: link . -

footnote

+

footnote

+
  1. link +

  2. +
+
```````````````````````````````` diff --git a/tests/dune.inc b/tests/dune.inc index 5996df97..85905d73 100644 --- a/tests/dune.inc +++ b/tests/dune.inc @@ -688,6 +688,7 @@ attributes-013.md attributes-013.html attributes-014.md attributes-014.html attributes-015.md attributes-015.html + attributes-016.md attributes-016.html def_list-001.md def_list-001.html) (action (run ./extract_tests.exe -generate-test-files %{deps}))) (rule @@ -4847,6 +4848,13 @@ (rule (alias attributes-015) (action (diff attributes-015.html attributes-015.html.new))) +(rule + (action + (with-stdout-to attributes-016.html.new + (run ./omd.exe %{dep:attributes-016.md})))) +(rule + (alias attributes-016) + (action (diff attributes-016.html attributes-016.html.new))) (rule (action (with-stdout-to def_list-001.html.new @@ -5544,4 +5552,5 @@ (alias attributes-013) (alias attributes-014) (alias attributes-015) + (alias attributes-016) (alias def_list-001))) From b3ed34d29b7be2a788da47e62ad8a3a29de46f99 Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Tue, 8 Oct 2024 17:05:39 +0300 Subject: [PATCH 5/9] feat: horizontal separator for footnotes --- src/html.ml | 9 +++++++-- tests/attributes.md | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/html.ml b/src/html.ml index db7964c7..ca2a2209 100644 --- a/src/html.ml +++ b/src/html.ml @@ -318,15 +318,20 @@ let rec block ~auto_identifiers = function (Some (concat (table_header headers) (table_body headers rows))) | Footnote_list footnotes -> let footnote_block content = - elt Block "div" [("class", "footnotes")] (Some content) + elt Block "div" [("class", "footnotes")] + (Some (concat + (elt Inline "hr" [] None) + content)) and footnote_list footnotes = + let footnote_backlink label = + (elt Block "a" [("href", "#fnref:" ^ label)] (Some (text "↩"))) in let footnote_p footnote = (elt Block "p" [] (Some (concat (inline footnote.content) - (elt Block "a" [("href", "#fnref:" ^ footnote.label)] (Some (text "↩")))))) + (footnote_backlink footnote.label)))) in elt Block "ol" [] (Some (concat_map diff --git a/tests/attributes.md b/tests/attributes.md index ee05d88b..08351ad7 100644 --- a/tests/attributes.md +++ b/tests/attributes.md @@ -296,7 +296,7 @@ Footnotes: [^footnote]: link .

footnote

-
  1. link +


    1. link

    From a3fe339e4322c2df0b2118353a3f9e941c27c7b4 Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Tue, 8 Oct 2024 17:13:37 +0300 Subject: [PATCH 6/9] chore: refactor html.ml --- src/html.ml | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/html.ml b/src/html.ml index ca2a2209..d07ad14f 100644 --- a/src/html.ml +++ b/src/html.ml @@ -255,6 +255,28 @@ let table_body headers rows = row))) rows)) +let footnote_block content = + elt Block "div" [("class", "footnotes")] + (Some (concat + (elt Inline "hr" [] None) + content)) + +let footnote_list footnotes = + let backlink label = + (elt Block "a" [("href", "#fnref:" ^ label)] (Some (text "↩"))) in + let p footnote = + (elt + Block "p" [] + (Some + (concat + (inline footnote.content) + (backlink footnote.label)))) + in + elt Block "ol" [] + (Some (concat_map + (fun footnote -> elt Block "li" [("id", footnote.id)] (Some (p footnote))) + footnotes)) + let rec block ~auto_identifiers = function | Blockquote (attr, q) -> elt @@ -316,28 +338,7 @@ let rec block ~auto_identifiers = function "table" attr (Some (concat (table_header headers) (table_body headers rows))) - | Footnote_list footnotes -> - let footnote_block content = - elt Block "div" [("class", "footnotes")] - (Some (concat - (elt Inline "hr" [] None) - content)) - and footnote_list footnotes = - let footnote_backlink label = - (elt Block "a" [("href", "#fnref:" ^ label)] (Some (text "↩"))) in - let footnote_p footnote = - (elt - Block "p" [] - (Some - (concat - (inline footnote.content) - (footnote_backlink footnote.label)))) - in - elt Block "ol" [] - (Some (concat_map - (fun footnote -> elt Block "li" [("id", footnote.id)] (Some (footnote_p footnote))) footnotes)) - in - footnote_block (footnote_list footnotes) + | Footnote_list footnotes -> footnote_block (footnote_list footnotes) let of_doc ?(auto_identifiers = true) doc = let identifiers = Identifiers.empty in From 3c16ee7827cc33a63cc5eb6292ee3d89155504ef Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Tue, 8 Oct 2024 18:31:10 +0300 Subject: [PATCH 7/9] chore: cleanup+refactor --- src/omd.ml | 8 -------- src/parser.ml | 26 +++++++++----------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/omd.ml b/src/omd.ml index 0d27e053..31e8a921 100644 --- a/src/omd.ml +++ b/src/omd.ml @@ -22,14 +22,6 @@ let parse_inlines (md, defs) : doc = in List.map f defs in - (* List.iter - (fun def -> Printf.printf - "def: %s, kind=%s\n" - def.Parser.label - (match def.Parser.kind with - | Parser.Footnote -> "Footnote" - | Parser.Reference -> "Reference")) - defs;*) let footnotes = List.filter_map (fun def -> match def.Parser.kind with | Footnote { id; label; } -> Some ({ id; label; Ast_block.Raw.content = def.destination; }) diff --git a/src/parser.ml b/src/parser.ml index ef5341ce..fcfbd59b 100644 --- a/src/parser.ml +++ b/src/parser.ml @@ -1093,13 +1093,7 @@ let link_label allow_balanced_brackets st = Buffer.add_char buf c; loop n true in - let is_footnote = begin - match peek_exn st with - | '^' -> true - | _ -> false - end in - let label = loop 0 false in - label, is_footnote + loop 0 false type add_uchar_result = { start : bool @@ -1687,7 +1681,7 @@ let rec inline defs st = let rec reference_link kind acc st = let off0 = pos st in match protect (link_label true) st with - | label, is_footnote -> ( + | label -> ( let reflink lab = let s = normalize lab in match @@ -1717,9 +1711,9 @@ let rec inline defs st = | Pre.Img -> Image (attr, def) | Url -> Link (attr, def) in - let r = match is_footnote with - | true -> Sup ([], r) - | false -> r + let r = match link_kind with + | Footnote { label = _; _ } -> Sup ([], r) + | Reference -> r in loop (Pre.R r :: text acc) st | None -> @@ -1844,11 +1838,10 @@ let rec inline defs st = Buffer.add_char buf ']'; loop ~seen_link acc st) | Some '[' -> ( - (* FIXME: there is a logic duplicate with reference_link *) let label = Pre.parse_emph xs in let off1 = pos st in match link_label false st with - | label_text, _ -> ( + | label_text -> ( let s = normalize label_text in match List.find_opt @@ -1953,14 +1946,13 @@ let link_reference_definition st : attributes link_def = match next st with w when is_whitespace w -> ws st | _ -> raise Fail in ignore (sp3 st); - (* TODO: return kind directly *) - let label, is_footnote = link_label false st in - (* Printf.printf "label:%s, is_footnote:%s\n" label (Bool.to_string is_footnote);*) + let is_footnote label = (String.get label 0) = '^' in + let label = link_label false st in if next st <> ':' then raise Fail; ws st; let destination = link_destination st in let attributes = inline_attribute_string st in - let kind = match is_footnote with + let kind = match is_footnote label with | true -> let label = (String.sub label 1 (String.length label - 1)) in Footnote { id = Printf.sprintf "fn:%s" label; label; } From a16df33a4d02729f729e02500c740a9a18f082a9 Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Tue, 8 Oct 2024 18:39:19 +0300 Subject: [PATCH 8/9] refactor: move empty footnote check to html module --- src/html.ml | 6 +++++- src/omd.ml | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/html.ml b/src/html.ml index d07ad14f..4ca76d4d 100644 --- a/src/html.ml +++ b/src/html.ml @@ -338,7 +338,11 @@ let rec block ~auto_identifiers = function "table" attr (Some (concat (table_header headers) (table_body headers rows))) - | Footnote_list footnotes -> footnote_block (footnote_list footnotes) + | Footnote_list footnotes -> begin + match List.is_empty footnotes with + | false -> footnote_block (footnote_list footnotes) + | true -> Null + end let of_doc ?(auto_identifiers = true) doc = let identifiers = Identifiers.empty in diff --git a/src/omd.ml b/src/omd.ml index 31e8a921..a1a0dca6 100644 --- a/src/omd.ml +++ b/src/omd.ml @@ -15,26 +15,26 @@ let toc = Toc.toc let parse_inline defs s = Parser.inline defs (Parser.P.of_string s) -let parse_inlines (md, defs) : doc = - let defs = - let f (def : attributes Parser.link_def) = - { def with label = Parser.normalize def.label } - in - List.map f defs - in - let footnotes = List.filter_map +let footnotes defs = + let footnote_defs = List.filter_map (fun def -> match def.Parser.kind with | Footnote { id; label; } -> Some ({ id; label; Ast_block.Raw.content = def.destination; }) | _ -> None) defs in - let footnote_block : _ Ast_block.Raw.block = Footnote_list footnotes + let footnote_block : _ Ast_block.Raw.block = Footnote_list footnote_defs in - let md = match List.is_empty footnotes with - | true -> md - | false -> md @ [footnote_block] + footnote_block + +let parse_inlines (md, defs) : doc = + let defs = + let f (def : attributes Parser.link_def) = + { def with label = Parser.normalize def.label } + in + List.map f defs in - (List.map (Ast_block.Mapper.map (parse_inline defs)) md) + let blocks = md @ [ (footnotes defs) ] in + (List.map (Ast_block.Mapper.map (parse_inline defs)) blocks) let escape_html_entities = Html.htmlentities let of_channel ic : doc = parse_inlines (Block_parser.Pre.of_channel ic) From a2d6ae00460be5b7ec85b52dc872f60360a3597c Mon Sep 17 00:00:00 2001 From: Onur Sahin Date: Tue, 8 Oct 2024 18:51:59 +0300 Subject: [PATCH 9/9] feat: use url --- src/html.ml | 2 +- tests/attributes.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/html.ml b/src/html.ml index 4ca76d4d..81ac9a1d 100644 --- a/src/html.ml +++ b/src/html.ml @@ -263,7 +263,7 @@ let footnote_block content = let footnote_list footnotes = let backlink label = - (elt Block "a" [("href", "#fnref:" ^ label)] (Some (text "↩"))) in + url (Text ([], "↩")) ("#fnref:" ^ label) None [] in let p footnote = (elt Block "p" [] diff --git a/tests/attributes.md b/tests/attributes.md index 08351ad7..f67331e6 100644 --- a/tests/attributes.md +++ b/tests/attributes.md @@ -296,8 +296,7 @@ Footnotes: [^footnote]: link .

    footnote

    -

    1. link -

    2. +

      1. link

      ````````````````````````````````