Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

An extension is created, but the output is not as expected #2740

Closed
hechuanhua opened this issue Feb 21, 2023 · 1 comment
Closed

An extension is created, but the output is not as expected #2740

hechuanhua opened this issue Feb 21, 2023 · 1 comment
Labels

Comments

@hechuanhua
Copy link

Marked version: 4.2.3

Describe the bug
I want to create a blue block that can contain other labels, but I have been unsuccessful

To Reproduce

const blueBlock = {
    name: 'blueBlock',
    level: 'block',
    start(src) {
        if (src.match(/:/)) {
            return src.match(/:::/).index
        }
        return undefined
    },
    tokenizer(src, tokens) {
        const rule = /^:::\n([\s\S]*?)\n:::/
        const match = rule.exec(src)
        if (match) {
            const token = {
                type: 'blueBlock',
                raw: match[0],
                text: match[0].trim(),
                tokens: [],
            }
            console.log(token.tokens, 666)
            this.lexer.inline(token.text, token.tokens)
            return token
        }
    },
    renderer(token) {
        console.log(token, 777)
        return `<blueBlock>${this.parser.parseInline(token.tokens)}</blueBlock>`
    },
}
marked.use({ extensions: [blueBlock] })
const a = marked.parse(`
:::
# sadfsdf
- aaa
- bbb
:::
`)
console.log(a)

output:

<blueBlock>:::
# sadfsdf
- aaa
- bbb
:::</blueBlock>

Expected behavior

<blueBlock>
<h1 id="sadfsdf">sadfsdf</h1>
<ul>
<li>aaa</li>
<li>bbb</li>
</ul
</blueBlock>
@UziTech
Copy link
Member

UziTech commented Feb 22, 2023

You are almost there!

A couple things to change:

  • this.lexer.inline parses the string as inline tokens. You want to parse the text inside ::: as block tokens. You can do that with this.lexer.blockTokens.
  • You are including the ::: in your inner tokens. You only want the text between them match[1].
  • You need to parse the inner tokens as block tokens with this.parser.parse instead of this.parser.parseInline.
const blueBlock = {
  name: 'blueBlock',
  level: 'block',
  start(src) {
      if (src.match(/:/)) {
          return src.match(/:::/).index
      }
      return undefined
  },
  tokenizer(src, tokens) {
      const rule = /^:::\n([\s\S]*?)\n:::/
      const match = rule.exec(src)
      if (match) {
          return {
              type: 'blueBlock',
              raw: match[0],
              text: match[0].trim(),
              tokens: this.lexer.blockTokens(match[1]),
          }
      }
  },
  renderer(token) {
      console.log(token, 777)
      return `<blueBlock>${this.parser.parse(token.tokens)}</blueBlock>`
  },
}
marked.use({ extensions: [blueBlock] })
const a = marked.parse(`
:::
# sadfsdf
- aaa
- bbb
:::
`)
console.log(a)

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants