Skip to content

Commit

Permalink
headings: add more special cases for code blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
hsjobeki committed Apr 25, 2024
1 parent 7ed386f commit 742ed5d
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 15 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## Version 3.0.5

Fixes: incompatibility with nixpkgs in 3.0.3 and 3.0.4

by @hsjobeki;

in https://github.com/nix-community/nixdoc/pull/121.

## Version 3.0.4

Fixes: issue with headings ids introduced with 3.0.3
Expand Down
61 changes: 48 additions & 13 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,30 +65,61 @@ pub fn handle_indentation(raw: &str) -> Option<String> {
pub fn shift_headings(raw: &str, levels: usize) -> String {
let mut result = String::new();

let mut curr_fence: Option<String> = None;
for line in raw.split_inclusive('\n') {
let mut curr_fence: Option<(usize, char)> = None;
for raw_line in raw.split_inclusive('\n') {
// Code blocks can only start with backticks or tildes
if line.starts_with("```") | line.starts_with("~~~") {
let fence_line = &trim_leading_whitespace(raw_line, 3);
if fence_line.starts_with("```") | fence_line.starts_with("~~~") {
let fence_info = get_fence(fence_line, true);
if curr_fence.is_none() {
// Start of code block
curr_fence = get_fence(line);
} else if curr_fence.as_deref() == Some(line.trim_end()) {
// End of code block (same fence as start)
curr_fence = None;
curr_fence = fence_info;
} else {
// Possible end of code block. Ending fences cannot have info strings
match (curr_fence, get_fence(fence_line, false)) {
// End of code block must have the same fence type as the start (~~~ or ```)
// Code blocks must be ended with at least the same number of backticks or tildes as the start fence
(Some((start_count, start_char)), Some((end_count, end_char))) => {
if start_count <= end_count && start_char == end_char {
// End of code block (same fence as start)
curr_fence = None;
}
}
_ => {}
};
}
}

if curr_fence.is_none() && line.starts_with('#') {
let heading = handle_heading(line, levels);
if curr_fence.is_none() && raw_line.starts_with('#') {
let heading = handle_heading(raw_line, levels);
result.push_str(&heading);
} else {
result.push_str(line);
result.push_str(raw_line);
}
}
result
}

pub fn get_fence(line: &str) -> Option<String> {
/// Removes leading whitespaces from code fences
/// However maximum of [max] whitespaces are removed.
/// This is useful for code fences may have leading whitespaces (0-3).
fn trim_leading_whitespace(input: &str, max: usize) -> String {
let mut count = 0;
input
.trim_start_matches(|c: char| {
if c.is_whitespace() && count < max {
count += 1;
true
} else {
false
}
})
.to_string()
}
/// A function that returns the count of a code fence line.
/// Param [allow_info] allows to keep info strings in code fences.
/// Ending fences cannot have info strings
pub fn get_fence(line: &str, allow_info: bool) -> Option<(usize, char)> {
let mut chars = line.chars();
if let Some(first_char) = chars.next() {
if first_char == '`' || first_char == '~' {
Expand All @@ -98,10 +129,14 @@ pub fn get_fence(line: &str) -> Option<String> {
// count the number of repeated code fence characters
count += 1;
} else {
break;
if !allow_info && ch != '\n' {
// info string is not allowed this is not a code fence
return None;
}
return Some((count, first_char));
}
}
return Some(std::iter::repeat(first_char).take(count).collect());
return Some((count, first_char));
}
}
None
Expand Down
22 changes: 21 additions & 1 deletion src/snapshots/nixdoc__test__headings.snap
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,27 @@ expression: output
map a from b -> 1
```

##### indented (0-3) fences

``` lang info
# Some pseudocode
map a from b -> 1
```

##### indented (0-3) fences asymmetric

```
# Some pseudocode
map a from b -> 1
```

##### More closing fences than opening

````
# Some pseudocode
map a from b -> 1
```````
##### Some heading
````nix
Expand Down Expand Up @@ -54,7 +75,6 @@ Nested tilde fences
foo
~~~~~

###### h5-heading
Mixed fences
Expand Down
22 changes: 21 additions & 1 deletion test/headings.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@
map a from b -> 1
```

### indented (0-3) fences

``` lang info
# Some pseudocode
map a from b -> 1
```

### indented (0-3) fences asymmetric

```
# Some pseudocode
map a from b -> 1
```

### More closing fences than opening

````
# Some pseudocode
map a from b -> 1
```````
### Some heading
````nix
Expand Down Expand Up @@ -50,7 +71,6 @@ Nested tilde fences
foo
~~~~~


##### h5-heading

Mixed fences
Expand Down

0 comments on commit 742ed5d

Please sign in to comment.