diff --git a/lib/export/html.ml b/lib/export/html.ml
index 91ac493..e0da332 100644
--- a/lib/export/html.ml
+++ b/lib/export/html.ml
@@ -101,6 +101,7 @@ and inline config t =
| Plain s
| Spaces s ->
[ Xml.data s ]
+ | Escaped s -> [ Xml.data ("\\" ^ s) ]
| Superscript l -> [ Xml.block "sup" (map_inline config l) ]
| Subscript l -> [ Xml.block "sub" (map_inline config l) ]
| Emphasis (kind, data) ->
diff --git a/lib/export/markdown.ml b/lib/export/markdown.ml
index c43e50e..afad14c 100644
--- a/lib/export/markdown.ml
+++ b/lib/export/markdown.ml
@@ -103,6 +103,12 @@ let rec inline state config (t : Inline.t) : t list =
map_raw_text [ String.ltrim s ]
) else
map_raw_text [ s ]
+ | Escaped s ->
+ if state.last_newline then (
+ state.last_newline <- false;
+ map_raw_text [ "\\"; s ]
+ ) else
+ map_raw_text [ "\\"; s ]
| Link l -> inline_link l
| Nested_link l -> inline_nested_link l
| Target s -> map_raw_text [ "<<"; s; ">>" ]
diff --git a/lib/mldoc_parser.ml b/lib/mldoc_parser.ml
index 81d25d7..7ddca28 100644
--- a/lib/mldoc_parser.ml
+++ b/lib/mldoc_parser.ml
@@ -47,12 +47,7 @@ let parsers config =
let parse config input =
match parse_string ~consume:All (parsers config) input with
- | Ok result ->
- let ast = Paragraph.concat_paragraph_lines config result in
- if Conf.is_markdown config then
- List.map (fun (t, pos) -> (Type_op.md_unescaped t, pos)) ast
- else
- ast
+ | Ok result -> Paragraph.concat_paragraph_lines config result
| Error err -> failwith err
let load_file f =
diff --git a/lib/syntax/inline.ml b/lib/syntax/inline.ml
index 800944c..36819b9 100644
--- a/lib/syntax/inline.ml
+++ b/lib/syntax/inline.ml
@@ -121,6 +121,7 @@ and t =
| Email of Email_address.t
| Inline_Hiccup of string
| Inline_Html of string
+ | Escaped of string
[@@deriving yojson]
and t_with_pos = t * pos_meta option
@@ -208,6 +209,13 @@ let in_plain_delims config c =
let whitespaces = ws >>| fun spaces -> Plain spaces
+let md_escaped_char set_last_char =
+ char '\\' >>= fun _ ->
+ satisfy is_md_escape_char >>| fun c ->
+ let s = String.make 1 c in
+ set_last_char s;
+ Escaped s
+
let plain ?state config =
let set_last_char s =
Option.(
@@ -223,10 +231,7 @@ let plain ?state config =
<|> ( ws >>| fun s ->
set_last_char s;
Plain s )
- <|> ( char '\\' *> satisfy is_md_escape_char >>| fun c ->
- let s = String.make 1 c in
- set_last_char s;
- Plain ("\\" ^ s) )
+ <|> md_escaped_char set_last_char
<|> ( any_char >>= fun c ->
if in_plain_delims config c then (
let s = String.make 1 c in
@@ -487,7 +492,7 @@ let entity =
try
let entity = Entity.find s in
Entity entity
- with Not_found -> Plain s
+ with Not_found -> Plain ("\\" ^ s)
(* FIXME: nested emphasis not working *)
(* foo_bar, foo_{bar}, foo^bar, foo^{bar} *)
@@ -919,6 +924,7 @@ let nested_link_or_link config =
let nested_emphasis ?state config =
let rec aux_nested_emphasis = function
| Plain s -> Plain s
+ | Escaped s -> Escaped s
| Emphasis (`Italic, [ Emphasis (`Bold, _) ]) as e -> e
| Emphasis (typ, l) ->
let parser =
diff --git a/lib/syntax/type_op.ml b/lib/syntax/type_op.ml
index ce4c442..e037b7f 100644
--- a/lib/syntax/type_op.ml
+++ b/lib/syntax/type_op.ml
@@ -52,116 +52,3 @@ let rec type_move_forawrd t forward_pos =
| Footnote_Definition (s, l) ->
Footnote_Definition (s, inline_list_move_forward l forward_pos)
| _ -> t
-
-let unescaped_md_string s =
- let open Bytes in
- let b = of_string s in
- let n = ref 0 in
- let i = ref 0 in
- let lenb = length b in
- while !i < lenb do
- n :=
- !n
- +
- match get b !i with
- | '\\' when !i + 1 < lenb && Parsers.is_md_escape_char (get b (!i + 1)) ->
- i := !i + 2;
- 1
- | _ ->
- incr i;
- 1
- done;
- if !n = length b then
- s
- else
- let b' = create !n in
- n := 0;
- let i = ref 0 in
- let len_1 = length b - 1 in
- while !i <= len_1 do
- (match get b !i with
- | '\\' when !i < len_1 ->
- let c = get b (!i + 1) in
- if Parsers.is_md_escape_char c then
- set b' !n c
- else (
- set b' !n '\\';
- incr n;
- set b' !n c
- );
- incr i
- | c -> set b' !n c);
- incr n;
- incr i
- done;
- to_string b'
-
-let map_escaped_string t f =
- let rec inline_aux (t : Inline.t) =
- match t with
- | Inline.Emphasis (em_type, tl) ->
- Inline.Emphasis (em_type, List.map inline_aux tl)
- | Inline.Tag tl -> Inline.Tag (List.map inline_aux tl)
- | Inline.Plain s -> Inline.Plain (f s)
- | Inline.Link link ->
- let label = List.map inline_aux link.label in
- let url =
- match link.url with
- | Inline.File s -> Inline.File (f s)
- | Inline.Search s -> Inline.Search (f s)
- | Inline.Page_ref s -> Inline.Page_ref (f s)
- | Inline.Complex complex ->
- Inline.Complex { complex with link = f complex.link }
- | Inline.Block_ref _ -> link.url
- | Inline.Embed_data _ -> link.url
- in
- Inline.Link { link with label; url }
- | Inline.Subscript tl -> Inline.Subscript (List.map inline_aux tl)
- | Inline.Superscript tl -> Inline.Superscript (List.map inline_aux tl)
- | Inline.Footnote_Reference fr ->
- Inline.Footnote_Reference
- { fr with definition = Option.map (List.map inline_aux) fr.definition }
- | _ -> t
- in
- let rec block_list_aux list_item =
- let content' = List.map block_aux list_item.content in
- let items = List.map block_list_aux list_item.items in
- let name =
- List.map (fun (t', pos) -> (inline_aux t', pos)) list_item.name
- in
- { list_item with content = content'; items; name }
- and block_aux (t : Type.t) =
- match t with
- | Paragraph l ->
- Paragraph (List.map (fun (t', pos) -> (inline_aux t', pos)) l)
- | Heading heading ->
- let title' =
- List.map (fun (t', pos) -> (inline_aux t', pos)) heading.title
- in
- Heading { heading with title = title' }
- | List l -> List (List.map block_list_aux l)
- | Quote tl -> Quote (List.map block_aux tl)
- | Custom (name, opts, data, s) ->
- let data' = List.map block_aux data in
- Custom (name, opts, data', s)
- | Footnote_Definition (name, content) ->
- let content' = List.map (fun (t', pos) -> (inline_aux t', pos)) content in
- Footnote_Definition (name, content')
- | Table table ->
- let header = Option.map (List.map (List.map inline_aux)) table.header in
- let groups =
- List.map (List.map (List.map (List.map inline_aux))) table.groups
- in
- Table { table with header; groups }
- | _ -> t
- in
- block_aux t
-
-(** unescape string in Type.Plain:
- e.g. \* -> *
- see also Parsers.md_escape_chars
- text in code fence should preserve '\' *)
-let md_unescaped t = map_escaped_string t unescaped_md_string
-
-(** TODO *)
-let md_escaped _t = failwith "not impl yet"
diff --git a/test/test_export_markdown.ml b/test/test_export_markdown.ml
index d52f0ca..86451a6 100644
--- a/test/test_export_markdown.ml
+++ b/test/test_export_markdown.ml
@@ -119,8 +119,8 @@ let export_md =
\t\t [[line6]]\n\
\t\t\t-\n\
\t\t\t ```\n\
- \t\t\t dwdw\n\
- \t\t\t jdiejdie\n\
+ \t\t\t \t dwdw\n\
+ \t\t\t \t jdiejdie\n\
\t\t\t ```" )
; ( "(5)"
, `Quick
@@ -173,6 +173,14 @@ let export_md =
, `Quick
, check_aux "- {{cloze (content1,content2)}}" "- (content1,content2)"
)
+ ; ("escaped", `Quick, check_aux "- a\\`b" "- a\\`b")
+ ; ( "escaped"
+ , `Quick
+ , check_aux "- a\\^b \\*non-italic*" "- a\\^b \\*non-italic*" )
+ ; ( "escaped"
+ , `Quick
+ , check_aux "- example postgres cmd: \\dt"
+ "- example postgres cmd: \\dt" )
] )
]
diff --git a/test/test_markdown.ml b/test/test_markdown.ml
index a067f2f..94ec4e7 100644
--- a/test/test_markdown.ml
+++ b/test/test_markdown.ml
@@ -696,13 +696,22 @@ let inline =
[ ( "emphasis(1)"
, `Quick
, check_aux "*a\\*b*"
- (paragraph [ Inline.Emphasis (`Italic, [ Inline.Plain "a*b" ]) ])
- )
+ (paragraph
+ [ Inline.Emphasis
+ (`Italic, [ I.Plain "a"; I.Escaped "*"; I.Plain "b" ])
+ ]) )
; ( "emphasis(2)"
, `Quick
, check_aux "*a\\\\\\*b*"
(paragraph
- [ Inline.Emphasis (`Italic, [ Inline.Plain "a\\*b" ]) ]) )
+ [ Inline.Emphasis
+ ( `Italic
+ , [ I.Plain "a"
+ ; I.Escaped "\\"
+ ; I.Escaped "*"
+ ; I.Plain "b"
+ ] )
+ ]) )
; ( "code"
, `Quick
, check_aux "`a\\``"
@@ -710,14 +719,16 @@ let inline =
; ( "nested emphasis"
, `Quick
, check_aux "_a*b\\*_"
- (paragraph [ Inline.Emphasis (`Italic, [ Inline.Plain "a*b*" ]) ])
- )
+ (paragraph
+ [ Inline.Emphasis
+ (`Italic, [ Inline.Plain "a*b"; I.Escaped "*" ])
+ ]) )
; ( "link (1)"
, `Quick
, check_aux "[[\\]]]"
(paragraph
[ Inline.Link
- { url = Inline.Page_ref "]"
+ { url = Inline.Page_ref "\\]"
; label = [ Inline.Plain "" ]
; full_text = "[[\\]]]"
; metadata = ""
@@ -730,7 +741,7 @@ let inline =
(paragraph
[ Inline.Link
{ url = Inline.Search "xxx"
- ; label = [ Inline.Plain "label](x)" ]
+ ; label = [ Inline.Plain "label\\](x)" ]
; full_text = "[label\\](x)](xxx)"
; metadata = ""
; title = None
@@ -741,7 +752,7 @@ let inline =
, check_aux "[label](ur\\)l)"
(paragraph
[ Inline.Link
- { url = Inline.Search "ur)l"
+ { url = Inline.Search "ur\\)l"
; label = [ Inline.Plain "label" ]
; full_text = "[label](ur\\)l)"
; metadata = ""