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
Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
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

5D59
// 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