markdown-it / markdown-it-container

Fenced container plugin for markdown-it markdown parser
MIT License
496 stars 74 forks source link

Why elements inside are paragraphed? #7

Closed felixsanz closed 8 years ago

felixsanz commented 8 years ago

This is my custom container:

md.use(MarkdownItContainer, '', {
  render(tokens, idx) {
    return (tokens[idx].nesting === 1) ? '<pre><samp>\n' : '</samp></pre>\n'
  },
  marker: '´',
})

I know the name is empty, it's intended. Because i'm using a custom and unique marker, it won't collide with other containers and i think i don't need a name. If i'm wrong please tell me.

With this code:

´´´
[Parsed_cropdetect_0 @ 000000000268d400] x1:0 x2:719 y1:74 y2:501 w:720 h:416 x:0 y:80 pts:1814400 t:20.160000 crop=720:416:0:80

[Parsed_cropdetect_0 @ 000000000268d400] x1:0 x2:719 y1:74 y2:501 w:720 h:416 x:0 y:80 pts:1814400 t:20.160000 crop=720:416:0:80
´´´

It kinda works, but i'm getting this result:

<pre><samp>
<p>[Parsed_cropdetect_0 @ 000000000268d400] x1:0 x2:719 y1:74 y2:501 w:720 h:416 x:0 y:80 pts:1814400 t:20.160000 crop=720:416:0:80</p>
<p>[Parsed_cropdetect_0 @ 000000000268d400] x1:0 x2:719 y1:74 y2:501 w:720 h:416 x:0 y:80 pts:1814400 t:20.160000 crop=720:416:0:80</p>
</samp></pre>

Why the

wrapping ?

felixsanz commented 8 years ago

Also, this is an idea for a markdown-it-samp plugin. I would do it myself, but i can't even configure the container plugin so... :) feel free to do it!

puzrin commented 8 years ago

This plugin is for markdown content inside. There is nothing strange in paragraphs.

If you need "content as is" inside, why don't you customize fenced block renderer instead?

felixsanz commented 8 years ago

Because as far as i know, fenced code blocks are code blocks. Not sample ones. And if i need both, that's a problem, isn't it?

puzrin commented 8 years ago

You can diverge rendering output by block name, or clone fenced block implementation under your own name with your own markers.

Problem is that you use wrong plugin for your needs. This one should be used when you need markdown inside.

felixsanz commented 8 years ago

How i do clone fenced block? I mean, how i do make use of the cloned one or set my own markers? Do i need to create a plugin for that? If you can provide a plugin example or something would be great.

And also i have a doubt here, default_rules.code_block and default_rules.fence aren't the same? One does highlighting but the rule is not the same?

felixsanz commented 8 years ago

My question is not clear enough. I think i know how to create the logic, and i think it goes inside Renderer#rules -> Object, because those extend the default_rules. But where do i say which open/close tags target this rule?

puzrin commented 8 years ago

See https://github.com/markdown-it/markdown-it/blob/master/lib/parser_block.js#L17. Your one will be injected via something like md.block.ruler.before('fence', 'your_blk_name', fn, { alt: [ 'paragraph', 'reference', 'blockquote', 'list' ] ]})

Parcer rule generate tokens. Then, if no renderer defined - default one will be used. If renderer with token name exists - it will be prefered.

code is for indented blocks (see CM spec). I think fenced block as base will be better for you.

felixsanz commented 8 years ago

But using that ruler i must use fenced backticks to access my renderer?

Note that fenced use backticks ``` and i want to use the inverse ones ´´´

puzrin commented 8 years ago

As i said, you can:

felixsanz commented 8 years ago

Thanks, i was confused about that. If i want to make a plugin, this is not neccesary right? I tried to check other plugins to take them as example but they lack of comments and are so hard to understand. Do you know which one should i copy/modify for this use case?

puzrin commented 8 years ago

No ideas. That's an example how parser can be extended:

const md = require('markdown-it')();

md.block.ruler.before('fence', 'your_blk_name', your_parser_fn, { alt: [ 'paragraph', 'reference', 'blockquote', 'list' ] ]});
md.renderer.rules.your_blk_name = your_renderer_fn;
felixsanz commented 8 years ago

I got it working finally. But in my journey i got 2 quick question that would be great if you can help!

Here appears this: token = state.push('fence', 'code', 0); .

fence is the rule name, right? But what are the others two? "code" and "0" ?

The other question is, in the ruler.before, what is this options object? alt: [ 'paragraph', 'reference', 'blockquote', 'list' ]. What this does?

I tried to answer both questions with the API docs but couldn't find anything :(

Thanks so much for helping

puzrin commented 8 years ago

https://github.com/markdown-it/markdown-it/blob/master/lib/rules_block/state_block.js#L92 second param (tag) is for default renderer. "Nesting level" needed to simplify scans when you need to match open/close tokens.

alt says that fenced block can terminate paragraph, reference, blockquote & list without empty line. That's a very simple explanation, but it can't be better without deep knowledge of parser internals.

felixsanz commented 8 years ago

Thanks. All clear. I published the package in case someone want to use/improve it. https://www.npmjs.com/package/markdown-it-samp

I'll try to improve it after understanding the internals a bit better. Also i would release the npm package name if someone wants to upload a better implementation :)

geekplux commented 7 years ago

this issue is so awesome that cleared my confusion.

geekplux commented 7 years ago

I published a package to implement this.

https://github.com/geekplux/markdown-it-fence https://www.npmjs.com/package/markdown-it-fence

geocine commented 6 years ago

I was trying to do the same , I had to search fenced block to get to this issue, very helpful 👍

douglasg14b commented 4 years ago

The paragraph wrapping really throws off the rendering of many use-cases.... It's pretty annoying that it's forced in.

chrisgo commented 1 year ago

Was able to do a hack-y fix

Using https://getbootstrap.com/docs/5.2/components/alerts/

...
.use(window.markdownitContainer, 'alert', {
    validate: function(params) {
        return params.trim().match(/^(primary|secondary|success|danger|warning|info|light|dark)*$/);
    },
    render: function (tokens, idx) {
        var m = tokens[idx].info.trim().match(/^(primary|secondary|success|danger|warning|info|light|dark)*$/);
        if (tokens[idx].nesting === 1) {
            return '<div class="p-inline alert alert-' + m[0] + '">' + '\n';
        } else {
            return '</div>\n';
        }
    }
});

Then just use css to clean up the line break

<style>
.p-inline p {
    display: inline;
}
<style>