Skip to content

Commit 59d8caa

Browse files
committed
Merge branch 'yasu/mrkdwn-escape-slash'
* yasu/mrkdwn-escape-slash: mrkdwn: use correct escape function tests: promote with escaping cases mrkdwn: document commonmark escaping behavior mrkdwn: escape backslash in code elements
2 parents e589230 + 2efbb8f commit 59d8caa

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

lib/mrkdwn.ml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,26 @@ let escape_mrkdwn =
1111
| '&' -> "&"
1212
| c -> String.make 1 c)
1313

14-
let unescape_omd =
15-
Staged.unstage @@ String.Escaping.unescape_gen_exn ~escapeworthy_map:[ '(', '('; ')', ')' ] ~escape_char:'\\'
14+
(** Unescape markdown characters escaped because "any ASCII punctuation
15+
character may be backslash-escaped"
16+
https://spec.commonmark.org/0.30/#backslash-escapes
17+
18+
This pertains to '\\', '[', ']', '(', ')', '`', '*' unconditionally,
19+
and '.', '-', '+', '!', '<', '>', '#' depending on chars before/after.
20+
Argument escapeworthy_map can be left blank because escaped chars are
21+
unescaped to themselves. *)
22+
let unescape_omd = Staged.unstage @@ String.Escaping.unescape_gen_exn ~escapeworthy_map:[] ~escape_char:'\\'
23+
24+
(** Escape the `escape_char` '\\' for use with `unescape_omd` later *)
25+
let escape_omd = Staged.unstage @@ String.Escaping.escape_gen_exn ~escapeworthy_map:[] ~escape_char:'\\'
1626

1727
let transform_text = escape_mrkdwn
1828

29+
(** `Omd.to_markdown` escapes backslash (and other applicable chars) in
30+
`Text` elements but not `Code` elements, so do the same for the latter so
31+
that `unescape_omd` can apply uniformly to the whole mrkdwn string later *)
32+
let transform_code s = escape_omd @@ escape_mrkdwn s
33+
1934
let rec transform_list = List.map ~f:transform
2035

2136
and transform_flatten = List.map ~f:transform_list
@@ -43,9 +58,9 @@ and transform = function
4358
| Html_block _ as e -> Code_block ("", to_markdown [ e ])
4459
| Blockquote t -> Blockquote (transform_list t)
4560
| Img (alt, src, title) -> transform @@ Url (src, [ Text alt ], title)
46-
| Code_block (_, str) -> Code_block ("", str)
61+
| Code_block (_, str) -> Code_block ("", transform_code str)
62+
| Code (_, str) -> Code ("", transform_code str)
4763
| Text s -> Text (transform_text s)
48-
| (Code _ | Br | Hr | NL | Ref _ | Img_ref _ | Raw _ | Raw_block _ | X _) as e -> e
64+
| (Br | Hr | NL | Ref _ | Img_ref _ | Raw _ | Raw_block _ | X _) as e -> e
4965

50-
(* unescaping here is a workaround of to_markdown escaping parentheses in text (bug?) *)
5166
let mrkdwn_of_markdown str = unescape_omd @@ to_markdown @@ transform_list @@ of_string str

mock_payloads/commit_comment.mrkdwn_comment.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"created_at": "2020-06-07T15:11:50Z",
3333
"updated_at": "2020-06-07T15:11:50Z",
3434
"author_association": "OWNER",
35-
"body": "**bold**, *italic*\n> blockquote\n\n* list-element 1\n* list-element 2\n * list-element2.1\n * [list-element2.2](www.google.com)\n\n<div>html block</div>\n```ocaml\nStdio.printf \"hello ocaml\"\n```"
35+
"body": "**bold**, *italic*\n> blockquote\n\n* list-element 1\n* list-element 2\n * list-element2.1\n * [list-element2.2](www.google.com)\n\n<div>html block</div>\n```ocaml\nStdio.printf \"hello ocaml\"\n```\nescaped chars \\\\\\(\\)\\[\\]\\`\\*\n`keep \\`\n```\nkeep \\\n```"
3636
},
3737
"repository": {
3838
"id": 265741348,

test/slack_payloads.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ will notify #all-push-events
7676
"pretext":
7777
"<https://github.com/xinyuluo/pr_test|[xinyuluo/pr_test]> *xinyuluo* commented on `<https://github.com/xinyuluo/pr_test/commit/cd5b85afa306840e0790b62e349ee1f828b2a3c2#commitcomment-39729580|cd5b85af>` add new line at EOF",
7878
"text":
79-
"this can be written shorter:\n`\n| Some serpDomain -> Domain.is_subdomain serpDomain domain\n| None -> false`",
79+
"this can be written shorter:\n`\n| Some serpDomain -&gt; Domain.is_subdomain serpDomain domain\n| None -&gt; false`",
8080
"footer":
8181
"New comment by xinyuluo in <https://github.com/xinyuluo/pr_test/commit/cd5b85afa306840e0790b62e349ee1f828b2a3c2#commitcomment-39729580|runner/chat.ml>"
8282
}
@@ -95,7 +95,7 @@ will notify #all-push-events
9595
"pretext":
9696
"<https://github.com/xinyuluo/pr_test|[xinyuluo/pr_test]> *xinyuluo* commented on `<https://github.com/xinyuluo/pr_test/commit/cd5b85afa306840e0790b62e349ee1f828b2a3c2#commitcomment-39729580|cd5b85af>` add new line at EOF",
9797
"text":
98-
"*bold*, _italic_\n\n> blockquote\n\n\n- list-element 1\n- list-element 2\n - list-element2.1\n - <www.google.com|list-element2.2>\n\n\n```\n<div>html block</div>\n```\n```\nStdio.printf \"hello ocaml\"\n```",
98+
"*bold*, _italic_\n\n> blockquote\n\n\n- list-element 1\n- list-element 2\n - list-element2.1\n - <www.google.com|list-element2.2>\n\n\n```\n<div>html block</div>\n```\n```\nStdio.printf \"hello ocaml\"\n```\nescaped chars \\()[]`*\n`keep \\`\n\n```\nkeep \\\n```",
9999
"footer":
100100
"New comment by xinyuluo in <https://github.com/xinyuluo/pr_test/commit/cd5b85afa306840e0790b62e349ee1f828b2a3c2#commitcomment-39729580|runner/chat.ml>"
101101
}

0 commit comments

Comments
 (0)