8000 NodeCodeBlock should have a property indicating whether it's closed · Issue #552 · kivikakk/comrak · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
NodeCodeBlock should have a property indicating whether it's closed #552
Open
@tvanderstad

Description

@tvanderstad

Similar to #422, it'd be nice if NodeCodeBlock provided an indication of whether a fenced code block has a closing fence:

```rust
fn this_has_a_closing_fence() {}
```

vs

```rust
fn this_does_not() {}

Motivation
I'm working on a markdown editor for a note taking app that lets you edit the rendered markdown similar to Bear or Obsidian. When the user clicks the code block and starts editing, I use sourcepos information to figure out what part of the file needs to change, but I need the sourcepos information for the editable part of the code block (i.e. the code itself) rather than the whole thing. That means I have to read the last line in the reported source position and check if it's a closing fence to know if it's editable or not:

let info_line_idx = sourcepos.start.line;
let mut code_line_idx = info_line_idx + 1;

// "If the end of the containing block (or document) is reached and
// no closing code fence has been found, the code block contains all
// of the lines after the opening code fence until the end of the
// containing block (or document)."
// https://github.github.com/gfm/#fenced-code-blocks
let last_line_idx = sourcepos.end.line;
let last_line_range = self.bounds.source_lines[last_line_idx];
let last_line = &self.buffer[last_line_range];
let last_line_indentation_spaces = last_line.chars().take_while(|&c| c == ' ').count();
let code_block_closed = is_closing_fence(last_line, fence_char, fence_length);
let last_code_line_idx =
    if code_block_closed { last_line_idx - 1 } else { last_line_idx };

while code_line_idx <= last_code_line_idx {
    let code_line_range = self.bounds.source_lines[code_line_idx];
    let code_line_text = &self.buffer[code_line_range];

    /* code for drawing the code line omitted */

    code_line_idx += 1;
}

Here's how I do that:

// "The closing code fence may be indented up to three spaces, and may be
// followed only by spaces, which are ignored."
// https://github.github.com/gfm/#fenced-code-blocks
fn is_closing_fence(line: &str, fence_char: &u8, fence_length: usize) -> bool {
    let ch = *fence_char as char;
    let s = line.trim_end(); // Remove trailing spaces

    let mut chars = s.chars();

    // Skip up to 3 leading spaces
    for _ in 0..3 {
        if chars.clone().next() == Some(' ') {
            chars.next();
        } else {
            break;
        }
    }

    // Count matching fence characters
    let mut count = 0;
    for c in chars {
        if c == ch {
            count += 1;
            if count >= fence_length {
                return true;
            }
        } else {
            break;
        }
    }

    false
}

I understand comrak doesn't aim to provide a CST, and I wouldn't mind having this kind of code around my codebase except that I'm not sure it's correct. If there's a situation where comrak considers a line to be a closing code fence and my implementation doesn't or vice versa, my app will probably crash.

I'm open to contributing if this is a change you'll accept. Is this a good first issue?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0