Skip to content

Commit

Permalink
Merge pull request #90 from chriskrycho/escape-code-in-tables
Browse files Browse the repository at this point in the history
Escape code in tables
  • Loading branch information
Byron authored Nov 22, 2024
2 parents f6fba5f + a85fe39 commit daef56b
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 464 deletions.
22 changes: 21 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub enum CodeBlockKind {
/// This does not only allow introspection, but enables the user
/// to halt the serialization at any time, and resume it later.
#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct State<'a> {
/// The amount of newlines to insert after `Event::Start(...)`
pub newlines_before_start: usize,
Expand Down Expand Up @@ -79,6 +80,8 @@ pub struct State<'a> {
pub image_stack: Vec<ImageLink<'a>>,
/// Keeps track of the last seen heading's id, classes, and attributes
pub current_heading: Option<Heading<'a>>,
/// True whenever between `Start(TableCell)` and `End(TableCell)`
pub in_table_cell: bool,

/// Keeps track of the last seen shortcut/link
pub current_shortcut_text: Option<String>,
Expand Down Expand Up @@ -305,10 +308,25 @@ where
text_for_header.push_str(text);
text_for_header.push('`');
}

// (re)-escape `|` when it appears as part of inline code in the
// body of a table.
//
// NOTE: This does not do *general* escaped-character handling
// because the only character which *requires* this handling in this
// spot in earlier versions of `pulldown-cmark` is a pipe character
// in inline code in a table. Other escaping is handled when `Text`
// events are emitted.
let text = if state.in_table_cell {
Cow::Owned(text.replace('|', "\\|"))
} else {
Cow::Borrowed(text.as_ref())
};

if text.chars().all(|ch| ch == ' ') {
write!(formatter, "`{text}`")
} else {
let backticks = "`".repeat(count_consecutive(text, '`') + 1);
let backticks = "`".repeat(count_consecutive(&text, '`') + 1);
let space = match text.as_bytes() {
&[b'`', ..] | &[.., b'`'] => " ", // Space needed to separate backtick.
&[b' ', .., b' '] => " ", // Space needed to escape inner space.
Expand Down Expand Up @@ -355,6 +373,7 @@ where
TableRow => Ok(()),
TableCell => {
state.text_for_header = Some(String::new());
state.in_table_cell = true;
formatter.write_char('|')
}
Link {
Expand Down Expand Up @@ -689,6 +708,7 @@ where
state
.table_headers
.push(state.text_for_header.take().unwrap_or_default());
state.in_table_cell = false;
Ok(())
}
t @ (TagEnd::TableRow | TagEnd::TableHead) => {
Expand Down
6 changes: 6 additions & 0 deletions tests/cat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,9 @@ title "stupicat"
WITH_SNAPSHOT="$snapshot/stupicat-toml-frontmatter-output" \
expect_run_sh $SUCCESSFULLY "${exe[*]} $fixture/toml-frontmatter.md 2>/dev/null"
)

(with "table with escaped characters in cells"
it "succeeds in reproducing the escapes" && \
WITH_SNAPSHOT="$snapshot/stupicat-table-with-escapes-output" \
expect_run_sh $SUCCESSFULLY "${exe[*]} $fixture/table-with-escapes.md 2>/dev/null"
)
6 changes: 6 additions & 0 deletions tests/fixtures/snapshots/stupicat-table-with-escapes-output
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
|First|Second|Third|Fourth|
|-----|------|-----|------|
|`\|`|`\\`|`a\[b\]`|`>>`|

Normal inline code with pipes `|` should not be re-escaped, because it does not
cause a problem!
6 changes: 6 additions & 0 deletions tests/fixtures/table-with-escapes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
| First | Second | Third | Fourth |
| ----- | ------ | -------- | ------ |
| `\|` | `\\` | `a\[b\]` | `>>` |

Normal inline code with pipes `|` should not be re-escaped, because it does not
cause a problem!
Loading

0 comments on commit daef56b

Please sign in to comment.