Skip to content
New issue

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

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

Already on GitHub? Sign in 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)

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

No branches or pull requests

2 participants