markdown-it-rust / markdown-it

markdown-it js library rewritten in rust
Other
79 stars 9 forks source link

Parsing content in a fenced block (for a new plugin) #15

Open digitalmoksha opened 1 year ago

digitalmoksha commented 1 year ago

Hi, I'm writing a plugin that adds syntax for multiline block quotes, such as

>>>
material to be block quoted
>>>

In general I have it working by creating a version of FenceScanner (as MultilineBlockquoteScanner) and CodeFence (as MultilineBlockquote). Of course, the code fencing doesn't parse the content inside the fence, which needs to happen for a blockquote.

I've replaced the fmt.text(&self.content); with fmt.contents(&node.children); when rendering the new MultilineBlockquote node.

However I'm having trouble figuring out how to actually get the contents parsed and added as children.

Any suggestions?

digitalmoksha commented 1 year ago

I added

        node.children.push(Node::new(InlineRoot::new(content, mapping)));

and that gets the first line of the block parsed, but not the rest of it.

Looking at https://github.com/rlidwka/markdown-it.rs/blob/master/src/parser/block/builtin/block_parser.rs, I don't see an analogous BlockRoot available.

Or would I need to run the block parser directly?

The code is in https://gitlab.com/digitalmoksha/glfm_multiline_blockquote.rs/-/blob/master/src/lib.rs

digitalmoksha commented 1 year ago

Ideally a Rust port of https://github.com/markdown-it/markdown-it-container would solve it

marcuswhybrow commented 1 year ago

I've got things working like this.

use markdown_it::{NodeValue};
use markdown_it::parser::block::{BlockRule, BlockState};
use markdown_it::common::sourcemap::SourcePos;

struct MyBlockType;

impl NodeValue for MyBlockType {...}

struct MyBlockTypeScanner;

impl BlockRule for MyBlockTypeScanner {
    fn run(state: &mut BlockState) -> Option<(Node, usize)> {
        let start_line = state.line;
        let end_line = start_line + 10; // for example

        let (content, _mapping) = state.get_lines(start_line, end_line);

        let mut node = state.md.parse(content);
        node.replace(MyBlockType);
        node.srcmap = Some(SourcePos::new(start_line, end_line));
        Some((node, end_line - start_line));
    }
}

P.S. I'm just guessing with the source map stuff. Not sure how to test it.

marcuswhybrow commented 1 year ago

Actually, I think this is the way to do it...

https://github.com/rlidwka/markdown-it.rs/blob/eb5459039685d19cefd0361859422118d08d35d4/src/plugins/cmark/block/blockquote.rs#L149-L156