From 703a711c7aee06b1f5440f8324b941abaa21fab4 Mon Sep 17 00:00:00 2001 From: Lukasz Stafiniak Date: Tue, 23 Jan 2024 17:23:24 +0100 Subject: [PATCH] Fix: escaping characters `<`, `>` --- src/printbox-md/PrintBox_md.ml | 22 +++++++++++++++++----- src/printbox-md/playground.md | 2 ++ test/test_md.expected | 26 +++++++++++++++++++++----- test/test_md.expected.md | 26 +++++++++++++++++++++----- test/test_md.ml | 4 +++- 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/printbox-md/PrintBox_md.ml b/src/printbox-md/PrintBox_md.ml index 106d2ee..ff10d16 100644 --- a/src/printbox-md/PrintBox_md.ml +++ b/src/printbox-md/PrintBox_md.ml @@ -92,12 +92,23 @@ let break_lines l = else Some s) lines -let pp_string_nbsp ~tab_width ~code_block ~code_quote ~infix out s = +let pp_string_nbsp ~tab_width ~code_block ~code_quote ~html ~infix out s = + (* TODO: benchmark if writing to a buffer first would be more efficient. *) let open Format in if code_block then pp_print_string out s else let print_sp nbsp = pp_print_string out (if nbsp then " " else " ") in + let print_char = + if html then + fun c -> + pp_print_string out @@ + match c with '<' -> "<" | '>' -> ">" | '&' -> "&" | c -> String.make 1 c + else + fun c -> + pp_print_string out @@ + (* TODO: consider extending this list, but maybe we shouldn't be too eager? *) + match c with '<' -> "\\<" | '>' -> "\\>" | '*' -> "\\*" | c -> String.make 1 c in let len = String.length s in let check i = i < len && (s.[i] = ' ' || s.[i] = '\t') in let i = ref 0 in @@ -113,10 +124,11 @@ let pp_string_nbsp ~tab_width ~code_block ~code_quote ~infix out s = k := !i; if code_quote then ( i := len; + (* TODO: escape the backtick `. *) pp_print_string out @@ String.sub s !k (len - !k);) else ( - while !i < len && (not @@ check !i) do incr i done; - if !k < len then pp_print_string out @@ String.sub s !k (!i - !k); + while !i < len && (not @@ check !i) do print_char s.[!i]; incr i done; + (* if !k < len then pp_print_string out @@ String.sub s !k (!i - !k); *) ) done @@ -134,7 +146,6 @@ let rec multiline_heuristic b = Array.length children > 0 || multiline_heuristic header | B.Link {inner; _} -> multiline_heuristic inner - let pp c out b = let open Format in (* We cannot use Format for indentation, because we need to insert ">" at the right places. *) @@ -146,7 +157,8 @@ let pp c out b = let multiline = List.length l > 1 in let sty_pre, sty_post, code_block, code_quote, inline = style_format c ~in_span ~multiline style in - let preformat = pp_string_nbsp ~tab_width:c.Config.tab_width ~code_block ~code_quote in + let preformat = + pp_string_nbsp ~tab_width:c.Config.tab_width ~code_block ~code_quote ~html:in_span in pp_print_string out sty_pre; if not inline && String.length sty_pre > 0 then fprintf out "@,%s" prefix; if code_block then fprintf out "```@,%s" prefix; diff --git a/src/printbox-md/playground.md b/src/printbox-md/playground.md index 73536bf..f1f1b48 100644 --- a/src/printbox-md/playground.md +++ b/src/printbox-md/playground.md @@ -177,3 +177,5 @@ Trying this
one-line code
is not inline. multiline
  code line 1
  code line 2 + +What happens with say & also `` html-ish syntax? < and > -- hmm & only if it's &something; recognized? \ No newline at end of file diff --git a/test/test_md.expected b/test/test_md.expected index 15fec64..230cff4 100644 --- a/test/test_md.expected +++ b/test/test_md.expected @@ -10,7 +10,9 @@ Test default: > - > subchild 3 - - > header 4 - - subchild 4 + - \ + - `` + - & \*subchild\* 4 - > `header 5` > - ``` > subchild 5 @@ -54,7 +56,9 @@ Test uniform unfolded: - - header 4 - - subchild 4 + - \ + - \ + - & \*subchild\* 4 -
header 5 @@ -130,7 +134,11 @@ Test foldable: -
header 4 - - subchild 4 + -
<returns> + + - `` +
+ - & \*subchild\* 4
- >
header 5 @@ -185,7 +193,11 @@ Test uniform tab=2, text tables: -
header 4 - - subchild 4 + -
<returns> + + - \ +
+ - & \*subchild\* 4
-
@@ -247,7 +259,11 @@ Test single quote tab=2, text tables: -
header 4 - - subchild 4 + -
<returns> + + - \ +
+ - & \*subchild\* 4
-
diff --git a/test/test_md.expected.md b/test/test_md.expected.md index 15fec64..230cff4 100644 --- a/test/test_md.expected.md +++ b/test/test_md.expected.md @@ -10,7 +10,9 @@ Test default: > - > subchild 3 - - > header 4 - - subchild 4 + - \ + - `` + - & \*subchild\* 4 - > `header 5` > - ``` > subchild 5 @@ -54,7 +56,9 @@ Test uniform unfolded:
- - header 4 - - subchild 4 + - \ + - \ + - & \*subchild\* 4 -
header 5 @@ -130,7 +134,11 @@ Test foldable: -
header 4 - - subchild 4 + -
<returns> + + - `` +
+ - & \*subchild\* 4
- >
header 5 @@ -185,7 +193,11 @@ Test uniform tab=2, text tables: -
header 4 - - subchild 4 + -
<returns> + + - \ +
+ - & \*subchild\* 4
-
@@ -247,7 +259,11 @@ Test single quote tab=2, text tables: -
header 4 - - subchild 4 + -
<returns> + + - \ +
+ - & \*subchild\* 4
-
diff --git a/test/test_md.ml b/test/test_md.ml index 1775e7e..6857016 100644 --- a/test/test_md.ml +++ b/test/test_md.ml @@ -15,7 +15,9 @@ let b = tree (frame @@ text "header 3") [frame @@ text "subchild 3"] ]; tree empty [ - tree (frame @@ text "header 4") [text "subchild 4"] + tree (frame @@ text "header 4") [ + tree (text "") [text_with_style Style.preformatted ""]; + text "& *subchild* 4"] ]; frame @@ tree (text_with_style Style.preformatted "header 5") [lines_with_style Style.preformatted