Markdown/CommonMark linting and style checking for Visual Studio Code
Intro
The Markdown markup language is designed to be easy to read, write, and understand. It succeeds - and its flexibility is both a benefit and a drawback. Many styles are possible, so formatting can be inconsistent. Some constructs don't work well in all parsers and should be avoided. For example, here are some common/troublesome Markdown constructs.
markdownlint is a Visual Studio Code extension that includes a library of rules to encourage standards and consistency for Markdown files. It is powered by markdownlint for Node.js which is based on markdownlint for Ruby.
Install
Open a Markdown file. Open the split preview window (Cmd + K, V on Mac, or the split view icon in the upper right-hand corner of the window, or open the command palette (menu View → Command Palette or Shift + Cmd + P on Mac) and run Markdown: open Preview to the side.Open the command palette and run Developer: Open WEBVIEW developer tools.; That will open a browser-like inspector, and you. Markdown is simple to write and simple to read. It is commonly used for Github repositories to create ReadMe.md files that provide visitors with insight int.
- Open Visual Studio Code
- Press
Ctrl+P
to open the Quick Open dialog - Type
ext install markdownlint
to find the extension - Click the
Install
button, then theEnable
button
OR
- Press
Ctrl+Shift+X
to open the Extensions tab - Type
markdownlint
to find the extension - Click the
Install
button, then theEnable
button
OR
- Open a command-line prompt
- Run
code --install-extension DavidAnson.vscode-markdownlint
Use
When editing a Markdown file in Code with markdownlint installed, any lines that violate one of markdownlint's rules (see below) will trigger a Warning in the editor. Warnings are indicated by a wavy green underline and can also be seen by pressing Ctrl+Shift+M
to open the Errors and Warnings dialog. Hover the mouse pointer over a green line to see the warning or press F8
and Shift+F8
to cycle through all the warnings (markdownlint warnings all begin with MD###
). For more information about a markdownlint warning, place the cursor on a line and click the light bulb icon or press Ctrl+.
to open the code action dialog. Clicking one of the warnings in the dialog will display that rule's help entry in the default web browser.
For a tutorial, please see Build an Amazing Markdown Editor Using Visual Studio Code and Pandoc by Dave Johnson.
Rules
- MD001heading-increment/header-increment - Heading levels should only increment by one level at a time
- ~~MD002first-heading-h1/first-header-h1 - First heading should be a top level heading~~
- MD003heading-style/header-style - Heading style
- MD004ul-style - Unordered list style
- MD005list-indent - Inconsistent indentation for list items at the same level
- ~~MD006ul-start-left - Consider starting bulleted lists at the beginning of the line~~
- MD007ul-indent - Unordered list indentation
- MD009no-trailing-spaces - Trailing spaces
- MD010no-hard-tabs - Hard tabs
- MD011no-reversed-links - Reversed link syntax
- MD012no-multiple-blanks - Multiple consecutive blank lines
- MD013line-length - Line length
- MD014commands-show-output - Dollar signs used before commands without showing output
- MD018no-missing-space-atx - No space after hash on atx style heading
- MD019no-multiple-space-atx - Multiple spaces after hash on atx style heading
- MD020no-missing-space-closed-atx - No space inside hashes on closed atx style heading
- MD021no-multiple-space-closed-atx - Multiple spaces inside hashes on closed atx style heading
- MD022blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines
- MD023heading-start-left/header-start-left - Headings must start at the beginning of the line
- MD024no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
- MD025single-title/single-h1 - Multiple top level headings in the same document
- MD026no-trailing-punctuation - Trailing punctuation in heading
- MD027no-multiple-space-blockquote - Multiple spaces after blockquote symbol
- MD028no-blanks-blockquote - Blank line inside blockquote
- MD029ol-prefix - Ordered list item prefix
- MD030list-marker-space - Spaces after list markers
- MD031blanks-around-fences - Fenced code blocks should be surrounded by blank lines
- MD032blanks-around-lists - Lists should be surrounded by blank lines
- MD033no-inline-html - Inline HTML
- MD034no-bare-urls - Bare URL used
- MD035hr-style - Horizontal rule style
- MD036no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading
- MD037no-space-in-emphasis - Spaces inside emphasis markers
- MD038no-space-in-code - Spaces inside code span elements
- MD039no-space-in-links - Spaces inside link text
- MD040fenced-code-language - Fenced code blocks should have a language specified
- MD041first-line-heading/first-line-h1 - First line in file should be a top level heading
- MD042no-empty-links - No empty links
- MD043required-headings/required-headers - Required heading structure
- MD044proper-names - Proper names should have the correct capitalization
- MD045no-alt-text - Images should have alternate text (alt text)
- MD046code-block-style - Code block style
- MD047single-trailing-newline - Files should end with a single newline character
- MD048code-fence-style - Code fence style
See markdownlint's Rules.md file for more details.
The following rules can be automatically fixed by moving the cursor to a rule violation (wavy underlined text) and typing Ctrl+.
or clicking the light bulb icon.
- MD004 ul-style
- MD005 list-indent
- MD006 ul-start-left
- MD007 ul-indent
- MD009 no-trailing-spaces
- MD010 no-hard-tabs
- MD011 no-reversed-links
- MD012 no-multiple-blanks
- MD014 commands-show-output
- MD018 no-missing-space-atx
- MD019 no-multiple-space-atx
- MD020 no-missing-space-closed-atx
- MD021 no-multiple-space-closed-atx
- MD022 blanks-around-headings
- MD023 heading-start-left
- MD026 no-trailing-punctuation
- MD027 no-multiple-space-blockquote
- MD030 list-marker-space
- MD031 blanks-around-fences
- MD032 blanks-around-lists
- MD034 no-bare-urls
- MD037 no-space-in-emphasis
- MD038 no-space-in-code
- MD039 no-space-in-links
- MD044 proper-names
- MD047 single-trailing-newline
All violations of the above rules in the current document can be fixed at once by running the markdownlint.fixAll
command, either from the Command Palette (via View|Command Palette...
or Ctrl+Shift+P
then search for 'markdownlint') or by binding the command to a keyboard shortcut.
To automatically fix these violations when saving a Markdown document, configure Visual Studio Code's editor.codeActionsOnSave
setting like so:
Automatically-applied fixes can be reverted by Edit|Undo
or Ctrl+Z
.
To temporarily disable linting of Markdown documents, run the markdownlint.toggleLinting
command (from the Command Palette or by binding it to a keyboard shortcut). To re-enable linting, run the markdownlint.toggleLinting
command again.
Note: The effects of the markdownlint.toggleLinting
command are reset when a new workspace is opened; linting defaults to enabled.
Configure
markdownlint.config
The default rule configuration disables MD013
/line-length
because many files include lines longer than the conventional 80 character limit:
Note: MD002
/first-heading-h1
is disabled by default because it has been deprecated in the markdownlint
library.
Rules can be enabled, disabled, and customized by creating a JSON file named .markdownlint.jsonc
/.markdownlint.json
/.markdownlintrc
or a YAML file named .markdownlint.yaml
/.markdownlint.yml
in any directory of a project. The rules defined by .markdownlint{.jsonc,.json,.yaml,.yml,rc}
apply to Markdown files in the same directory and any sub-directories without their own .markdownlint{.jsonc,.json,.yaml,.yml,rc}
.
Note: .markdownlint{.jsonc,.json,.yaml,.yml,rc}
is used only if a project has been opened. When no folder is open or a file is not part of the current project, normal user and workspace settings apply (see below). If multiple of these files are present in the same directory, .markdownlint.jsonc
will be used instead of .markdownlint.json
will be used instead of .markdownlint.yaml
will be used instead of .markdownlint.yml
will be used instead of .markdownlintrc
.
A custom configuration is often defined by a .markdownlint.json
file in the root of the project:
To extend another configuration file, any configuration file can use the extends
property to provide a relative path:
Files referenced via extends
do not need to be part of the current project (but usually are).
Rules can also be configured using Code's support for user and workspace settings.
The earlier configuration might look like the following in Code's user settings:
File paths referenced by extends
from user settings are resolved relative to the user's home directory (ex: %USERPROFILE%
on Windows or $HOME
on macOS/Linux). File paths referenced by extends
from workspace settings are resolved relative to the workspace folder.
Configuration locations have the following precedence (in decreasing order):
.markdownlint{.jsonc,.json,.yaml,.yml,rc}
file in the same directory.markdownlint{.jsonc,.json,.yaml,.yml,rc}
file in a parent directory.markdownlint{.jsonc,.json,.yaml,.yml,rc}
file in the root of the project- Visual Studio Code user/workspace settings
- Default configuration (see above)
Once a configuration is found, lower-precedence locations are ignored. Changes saved to any location take effect immediately. Files referenced via extends
are not monitored for changes. Only the last two locations apply to files outside a project.
See markdownlint's options.config section for more information about rule configuration. See .markdownlint.jsonc
and .markdownlint.yaml
for example configurations with all properties set to the default value.
When a workspace is active, running the markdownlint.openConfigFile
command (from the Command Palette or by binding it to a keyboard shortcut) will open an editor for the .markdownlint{.jsonc,.json,.yaml,.yml,rc}
configuration file in the root of the workspace. If none of those files exist, .markdownlint.json
will be created in the 'pending save' state and opened in the editor.
markdownlint.ignore
If a workspace contains generated content or other Markdown files that trigger warnings but cannot be fixed, it may be helpful to ignore (skip) those files when linting. This can be done by creating a file named .markdownlintignore
in the root of the project or by updating the user/workspace configuration with a glob expression matching the relevant file names.
When using a .markdownlintignore
file, the content of the file follows the rules for gitignore and may look something like:
An example of using Code's workspace configuration to ignore files might be:
The globbing library used for matching markdownlint.ignore
configuration values is minimatch with the dot
and nocomment
options enabled. Matching is case-sensitive and paths are resolved relative to the root of the workspace. The directory separator is /
, even on Windows.
markdownlint.run
By default, linting is performed as you type or edit a document. Linting is fast and efficient and should not interfere with typical workflows.
If you find this distracting, linting can be configured to run only when the document is saved. This looks like the following in Code's user settings:
Note: When configured to run onSave
, the list of reported issues will become outdated while the document is edited and will update when the document is saved.
markdownlint.customRules
Custom rules can be specified in Code's user/workspace configuration to apply additional linting beyond the default set of rules. Custom rules are specified by the path to a JavaScript file or the path to an npm package exporting one rule or an array of rules.
Paths are normally relative to the root of the current workspace (or the Code install directory when no folder is open). Paths can also be absolute. When adding custom rules to a workspace, consider committing those rules under the .vscode
directory where they will be separate from other workspace content and available to everyone who clones the repository.
Paths of the form {extension}/path
are relative to the base directory of the Code extension named extension
(which must already be installed). This syntax allows custom rules to be included within another extension's package and shared across multiple workspaces.
An example of Code's workspace settings for custom rules might look like the following:
To troubleshoot issues loading or running custom rules, please refer to diagnostic messages from the extension in Code's Output window.
For information about authoring custom rules, see markdownlint/CustomRules.
Markdown View In Vscode
markdownlint.customRulesAlwaysAllow
A list of workspace paths for which the user's response to the custom rule prompt was 'Always allow'. This setting is updated automatically by the extension, but can be modified to reset the prompt for a workspace.
Note: This setting is only valid as a user setting, not as a workspace setting (where it could be set by a malicious workspace).
Suppress
Individual warnings can be suppressed with inline comments:
The following snippets are available to help (press Ctrl+Space
for IntelliSense suggestions):
markdownlint-disable
markdownlint-enable
markdownlint-disable-next-line
markdownlint-capture
markdownlint-restore
markdownlint-disable-file
markdownlint-enable-file
markdownlint-configure-file
See markdownlint's configuration section for more details.
History
See CHANGELOG.md.
Markdown is a formatting language used when the resulting document will be rendered or converted into html documents for web-viewable material. The format is commonly used to generate documents like readme’s in GitHub or blog posts and even this website. Markdown documents are written in plain text, and thus are often simpler to create, edit and manage using text editors intended for writing code. This page includes a how-to discussion of using VSCode, a software package (and associated customizing plugins) intended for writing code that lends itself well to markdowns as well.
Markdown References
There are multiple “flavors” of markdown, for example, this site is rendered using GitHub-flavored markdown. More detailed instructions for the various types of formatting possible using GitHub flavored markdown can be found here. A handy Markdown Cheatsheet is also available here, and can serve as a useful refresher for the formatting required in your markdown in order to use automatic formatting features such as headings, table of contents, tables, links, image embedding and comments.
VSCode is freely available here and is supported on all major operating systems (Windows, macOS & Linux). Download the correct version for your platform and install it. Note, on a Mac you may need to drag the application icon from wherever you unpacked the zip to your Applications folder. This editor has a variety of features that are useful for editing markdowns including an option to toggle a preview pane to view the rendered markdown as you edit. There are also user-developed plugins that can be installed when needed to tailor the editor to your specific needs.
Vscode View Markdown Preview
Creating and Editing Markdown documents
To get started creating or editing markdown files, you should already have a folder set up where you will be working with your markdown files (e.g., a cloned GitHub repo like the one this site is generated from, a folder containing your documentation) on your workstation. From the VSCode “File” menu, select “Open Folder” or “Open” (on macOS) and navigate to the folder containing the files you wish to edit, or to the empty folder you will be creating new documents in. The image below shows and open folder with some markdown files to edit. If you open a folder then all available documents in the folder will show up in the left sidebar, allowing you to switch between documents by simply selecting the files.
Select an existing file or create a new file (File –> New File) and save it with the .md
extension. When you click on the file name it will open a tab and display the contents of the file.
To see a live side-by-side preview of the rendered markdown document to check the formatting and see any images, you can click on the split window with magnifying glass icon in the upper right of the open files
tab. After clicking on this tab, a new pane will appear on the right and display the rendered markdown.
Note: While it’s possible to edit markdown files from random locations in your file system in a one-off manner without opening the folder in VSCode, opening the folder is required for the features of some plugins and linters to work correctly.
Git Integration
VSCode has built-in support for Git repositories (you still need Git installed on your workstation if it’s not already present).
If the folder you have open to edit files is a Git repo, any changes made to files that you’ve saved, the “Git” icon (1) in the left toolbar will have a blue circle indicating how many un-staged/un-committed files there are. To stage (git add) a file that you wish to commit, click on the Git icon, then the file that you want to stage. Click on the “+” icon (2) to stage the file. To commit the changes, enter a commit message in the message box (3) and then click the check mark icon (4).
To push your changes to a remote repository, pull in any new changes from the remote repository or other git functions, click on the “…” icon (5) to reveal the full Git menu.
Installing Plugins
After you have VSCode installed, you can start creating and editing markdown files right away, but there are a few VSCode plugins that will be very helpful. These plugins will allow you to easily paste images into your documents and check the spelling and find formatting errors.
To install a plugin, in VSCode, click on the square extensions icon in the upper left tool bar (1), then in the search box (2) type the name of the plugin you wish to install, find the plugin you are looking for in the results, click on it and then click on the green “Install” button. After it’s installed you’ll need to reload VSCode to use it.
Below are the recommended plugins for authoring Markdown:
Plugin: Paste Image
The “Paste Image” plugin is a huge time saver if your documentation will contain lots of images. Install the Paste Image plugin from “mushan”.
By default, Paste Image will create (if it doesn’t already exist) a single “images” folder at the root of your open directory structure for all images pasted. If you would like to keep your images folder at the same level of the directory structure as your markdown document (to keep them together), you can make the following configuration change. Go to “File” –> “Preferences” –> “Settings” (or “Code” –> “Preferences” –> “Settings” on macOS) and in the “User Settings” configuration section, add the following pasteImage
entries between the curly braces like the following, then close the user settings tab and click save json
.
In this example the sub-folder that will be created in the assets folder named after your file name (this just lets us avoid a single huge assets folder in the long run). Note: if you are editing markdown that is destined for the Fred Hutch Wiki, you must use the above configuration. It is set in the workspace settings for vscode at /.vscode/settings.json which will override the user settings. However in other contexts, you may need to use another folder name like images
in order for certain processes to function.
After the Paste Image
plugin is installed and configured, you can simply copy your prepared image or screenshot, insert the cursor where you want to insert the image in the document and use Ctr+Alt+V on Windows or Linux and Command+Alt+V on macOS. This will automatically create the assets (or whatever you’ve named it) folder if doesn’t already exist and place your image there naming it with a date/timestamp. The inserted text in the editor will look like the following:
Between the empty square brackets, you can place “alt-text”, or a string/name describing the image (it won’t be displayed in your browser or the preview). Without this “alt-text” the Markdown linter (plugin) will provide a warning, but it’s O.K. to leave it empty if you like for most downstream rendering processes.
More information about this plugin is available here
NOTE: To get the Paste Image working on Linux, it may be required to install the “xclip” package (sudo apt install xclip).
Plugin: Spellchecker
VSCode doesn’t include a built-in spell checker. To add a spell checker to VSCode, install the “Code Spell Checker” plugin from “Street Side Software.” After the plugin is installed (and VSCode reloaded) it should automatically start finding typos. There will be a green squiggly line under the suspect word. If the word is misspelled you can click on the word and a yellow light bulb icon will appear. Click on the light bulb icon and a menu should appear offering you suggestions. If the suspected work is in fact spelled correctly you can use the same context menu to add it to your local dictionary.
More information about this plugin is available here.
Plugin: MarkdownLint
A markdown “linter,” a program that tests for formatting problems in a structured plain text file (there are also yaml linters, json linters, etc), may also be useful to help you write correctly formatted markdown. Install the “markdownlint” plugin from “David Anson.” It works exactly like the Spellchecker plugin. Hovering your cursor over the green squiggly underline will reveal the warning from the linter; clicking on the light bulb will reveal a click you can click to learn more about what you are doing wrong.
Visual Studio Code View Markdown
More information about this plugin is available here.