mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	fix(lsp): markdown code fence should allow space before info string #24364
Problem:
Bash language server returns "hover" markdown content that starts with
a code fence and info string of `man` preceded by whitespace, which Nvim
does not render properly.
See 0ee73c53ce/server/src/server.ts (L821C15-L821C15)
```typescript
function getMarkdownContent(documentation: string, language?: string): LSP.MarkupContent {
  return {
    value: language
      ? // eslint-disable-next-line prefer-template
        ['``` ' + language, documentation, '```'].join('\n')
      : documentation,
    kind: LSP.MarkupKind.Markdown,
  }
}
```
For example,
```
    ``` man
    NAME
       git - the stupid content tracker
    ```
```
If I remove the white space, then it is properly formatted. 
```    
    ```man instead of ``` man
```
Per CommonMark Spec https://spec.commonmark.org/0.30/#info-string
whitespace is allowed before and after the `info string` which
identifies the language in a codeblock.
> The line with the opening code fence may optionally contain some text
> following the code fence; this is trimmed of leading and trailing
> spaces or tabs and called the [info
> string](https://spec.commonmark.org/0.30/#info-string). If the [info
> string](https://spec.commonmark.org/0.30/#info-string) comes after
> a backtick fence, it may not contain any backtick characters. (The
> reason for this restriction is that otherwise some inline code would
> be incorrectly interpreted as the beginning of a fenced code block.)
 Solution:
 Adjust stylize_markdown() to allow whitespace before codeblock info.
			
			
This commit is contained in:
		| @@ -1347,7 +1347,7 @@ function M.stylize_markdown(bufnr, contents, opts) | |||||||
|   -- table of fence types to {ft, begin, end} |   -- table of fence types to {ft, begin, end} | ||||||
|   -- when ft is nil, we get the ft from the regex match |   -- when ft is nil, we get the ft from the regex match | ||||||
|   local matchers = { |   local matchers = { | ||||||
|     block = { nil, '```+([a-zA-Z0-9_]*)', '```+' }, |     block = { nil, '```+%s*([a-zA-Z0-9_]*)', '```+' }, | ||||||
|     pre = { nil, '<pre>([a-z0-9]*)', '</pre>' }, |     pre = { nil, '<pre>([a-z0-9]*)', '</pre>' }, | ||||||
|     code = { '', '<code>', '</code>' }, |     code = { '', '<code>', '</code>' }, | ||||||
|     text = { 'text', '<text>', '</text>' }, |     text = { 'text', '<text>', '</text>' }, | ||||||
|   | |||||||
| @@ -34,6 +34,19 @@ describe('vim.lsp.util', function() | |||||||
|       eq(expected, stylize_markdown(lines, opts)) |       eq(expected, stylize_markdown(lines, opts)) | ||||||
|     end) |     end) | ||||||
|  |  | ||||||
|  |     it('code fences with whitespace surrounded info string', function() | ||||||
|  |       local lines = { | ||||||
|  |         "```   lua   ", | ||||||
|  |         "local hello = 'world'", | ||||||
|  |         "```", | ||||||
|  |       } | ||||||
|  |       local expected = { | ||||||
|  |         "local hello = 'world'", | ||||||
|  |       } | ||||||
|  |       local opts = {} | ||||||
|  |       eq(expected, stylize_markdown(lines, opts)) | ||||||
|  |     end) | ||||||
|  |  | ||||||
|     it('adds separator after code block', function() |     it('adds separator after code block', function() | ||||||
|       local lines = { |       local lines = { | ||||||
|         "```lua", |         "```lua", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Mike
					Mike