vuejs / vitepress

Vite & Vue powered static site generator.
https://vitepress.dev
MIT License
11.33k stars 1.83k forks source link

不支持行内这种**`XXX`**高亮加加粗 #3762

Closed zhangyuantao closed 3 weeks ago

zhangyuantao commented 3 weeks ago

Describe the bug

不支持行内这种XXX高亮加加粗

Reproduction

不支持:aaaXXXbbb 支持:aaa XXX bbb (**和其他文本之间需要加空格)

Expected behavior

null

System Info

null

Additional context

No response

Validations

brc-dd commented 3 weeks ago

It's as per commonmark standard. Even GitHub doesn't render that as bold without spaces.

zhangyuantao commented 3 weeks ago

It's as per commonmark standard. Even GitHub doesn't render that as bold without spaces.

Okay, thank you for your reply. I understand now. The Typora I am using is supported. I'm still puzzled why adding spaces is necessary when using this combination. I'll close the issue

brc-dd commented 3 weeks ago

I'm still puzzled why adding spaces is necessary when using this combination.

It's based on the concept of left/right flanking delimiter runs - https://spec.commonmark.org/0.31.2/#left-flanking-delimiter-run -- that in turn is adapted from some older tool. This example shows what you're experiencing - https://spec.commonmark.org/0.31.2/#example-380 -- (` is treated as a punctuation).

If you want to deviate from the standard, you can do so by modifying markdown-it parser like this:

// .vitepress/config.ts

import { isWhiteSpace } from 'markdown-it/lib/common/utils.mjs'
import { defineConfig } from 'vitepress'

export default defineConfig({
  markdown: {
    config(md) {
      // https://github.com/markdown-it/markdown-it/blob/a367c44154d6c906c8652ed779af6a21f7eaed2e/lib/rules_inline/state_inline.mjs#L88
      // modified to ignore punctuation characters
      md.inline.State.prototype.scanDelims = function (start, canSplitWord) {
        const max = this.posMax
        const marker = this.src.charCodeAt(start)

        // treat beginning of the line as a whitespace
        const lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20

        let pos = start
        while (pos < max && this.src.charCodeAt(pos) === marker) {
          pos++
        }
        const count = pos - start

        // treat end of the line as a whitespace
        const nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20

        const isLastPunctChar = false // MODIFIED
        const isNextPunctChar = false // MODIFIED

        const isLastWhiteSpace = isWhiteSpace(lastChar)
        const isNextWhiteSpace = isWhiteSpace(nextChar)

        const left_flanking =
          !isNextWhiteSpace &&
          (!isNextPunctChar || isLastWhiteSpace || isLastPunctChar)
        const right_flanking =
          !isLastWhiteSpace &&
          (!isLastPunctChar || isNextWhiteSpace || isNextPunctChar)

        const can_open =
          left_flanking && (canSplitWord || !right_flanking || isLastPunctChar)
        const can_close =
          right_flanking && (canSplitWord || !left_flanking || isNextPunctChar)

        return { can_open, can_close, length: count }
      }
    }
  }
})

(You'll need to install markdown-it and @types/markdown-it)