Repository: kivikakk/comrak (Rust)

Issue:
incorrect `sourcepos` for escaped character spans
_First off, shoutout to @kivikakk for the recent inline sourcepos fixes! I ran into a bug with source positions recently and just thought - **oh, no** - until I updated from 0.29 to 0.38 and not only was my issue resolved but I also got subscripts and alerts. Nice!_

This is another one of #448, #502, #507. When using `options.render.escaped_char_spans = true;`, the sourcepos info for the text child node in the escaped tag node contains the backslash that escaped it. This is in contrast to, say, the text child node of an emph node, where the emph includes the syntax that made it emph but the text inside doesn't.

So, in this example doc...
```md
\`code\`
```
...my program's ascii-art debug output is...
```
■ Document 1:1-1:8 +1■
  └>■ Paragraph 1:1-1:8 +3=
    ├>= Escaped 1:1-1:2 +1■
    │ └>= Text("`") 1:1-1:2
    ├>= Text("code") 1:3-1:6
    └>= Escaped 1:7-1:8 +1■
      └>= Text("`") 1:7-1:8
```
...but I expect it to be...
```
■ Document 1:1-1:8 +1■
  └>■ Paragraph 1:1-1:8 +3=
    ├>= Escaped 1:1-1:2 +1■
    │ └>= Text("`") 1:2-1:2
    ├>= Text("code") 1:3-1:6
    └>= Escaped 1:7-1:8 +1■
      └>= Text("`") 1:8-1:8
```
...with the start and end LineColumn's of each text range being equal, consistent with them having length 1, and with those text ranges being strict subsets of the text ranges for their parent 'escaped' nodes.


Discussion:
This issue isn't that big of a deal to me. The only experience it's powering in my app is for the escape sequence's backslash to be rendered in a different color than the escaped character.
PR welcome! This is probably a relatively simple fix to adjust the text node's sourcepos when inserting the `Escaped` node.



Patch:
diff --git a/src/parser/inlines.rs b/src/parser/inlines.rs
index 82e1c24b..61aa36ca 100644
--- a/src/parser/inlines.rs
+++ b/src/parser/inlines.rs
@@ -392,7 +392,7 @@ impl<'a, 'r, 'o, 'd, 'c, 'p> Subject<'a, 'r, 'o, 'd, 'c, 'p> {
 
             let inline_text = self.make_inline(
                 NodeValue::Text(self.input[self.pos - 1..self.pos].to_string().into()),
-                self.pos - 2,
+                self.pos - 1,
                 self.pos - 1,
             );
 


Test patch:
diff --git a/src/tests/escaped_char_spans.rs b/src/tests/escaped_char_spans.rs
index 5b8bbf33..2c80d8d5 100644
--- a/src/tests/escaped_char_spans.rs
+++ b/src/tests/escaped_char_spans.rs
@@ -12,3 +12,24 @@ fn escaped_char_spans(markdown: &str, html: &str) {
 fn disabled_escaped_char_spans(markdown: &str, expected: &str) {
     html(markdown, expected);
 }
+
+#[test]
+fn escaped_char_span_sourcepos() {
+    assert_ast_match!(
+        [render.escaped_char_spans],
+        "Test \\`hello world\\` here.",
+        (document (1:1-1:26) [
+            (paragraph (1:1-1:26) [
+                (text (1:1-1:5) "Test ")
+                (escaped (1:6-1:7) [
+                    (text (1:7-1:7) "`")
+                ])
+                (text (1:8-1:18) "hello world")
+                (escaped (1:19-1:20) [
+                    (text (1:20-1:20) "`")
+                ])
+                (text (1:21-1:26) " here.")
+            ])
+        ])
+    );
+}
diff --git a/src/tests/sourcepos.rs b/src/tests/sourcepos.rs
index 499c5faf..074fd226 100644
--- a/src/tests/sourcepos.rs
+++ b/src/tests/sourcepos.rs
@@ -246,7 +246,12 @@ const TEXT: TestCase = (
         sourcepos!((11:3-11:8)),
         sourcepos!((12:3-12:9)),
         sourcepos!((12:12-12:15)),
-        sourcepos!((14:7-14:14)),
+        sourcepos!((14:1-14:5)),
+        sourcepos!((14:7-14:7)),
+        sourcepos!((14:8-14:18)),
+        sourcepos!((14:20-14:20)),
+        sourcepos!((14:21-14:26)),
+        sourcepos!((16:7-16:14)),
     ],
     r#"stuff before
 
@@ -261,6 +266,8 @@ hello world
 - item 1[^1]
 - item 2 **bold**
 
+Test \`hello world\` here.
+
 [^1]: The end.
 "#,
 );