Markdown Linting Setup

This document provides how linting and formatting is setup in this project

This comprehensive guide demonstrates how to set up markdown linting and formatting in VS Code for Hugo projects. Learn to configure essential tools like Markdownlint, YAML Front Matter Lint, and Prettier to ensure consistent, professional documentation. The tutorial covers global settings configuration, extension setup, and practical workflows that work out-of-the-box without project-specific configuration.


Overview

The term linting refers to the process of analyzing code for potential errors, stylistic issues, and other concerns. In the context of this project, we focus primarily on linting Markdown files to ensure they adhere to best practices and maintain a consistent style throughout the documentation.

Most web content is written in Markdown format using various Static Site Generators (SSGs). This project utilizes Hugo as its SSG and YAML frontmatter in Markdown files. To ensure that Markdown files are well-formatted and free of common issues, we employ a carefully curated combination of tools and extensions.

Essential Tools and Extensions

The following tools and extensions form the foundation of our linting and formatting workflow:

  1. Markdownlint: A popular VS Code extension that provides comprehensive linting for Markdown files. It identifies common issues and enforces consistent styling across all documentation.

  2. YAML Front Matter Lint: This specialized extension provides linting specifically for YAML frontmatter in Markdown files, ensuring metadata is correctly formatted and adheres to Hugo’s requirements. Find out more about this setting on the yaml-fm-lint GitHub repository

  3. Prettier - Code formatter: An opinionated code formatter supporting multiple languages, including Markdown and YAML. It maintains consistent formatting and style across all project files.

  4. Markdownlint-cli2: A command-line tool for linting Markdown files, providing automation capabilities and integration with CI/CD pipelines.

VS Code Configuration Strategy

VS Code utilizes a hierarchical settings system combining global (user settings) and project-specific configurations. When working with multiple projects, it is strongly recommended to use project-specific settings to ensure each project adheres to its own linting and formatting standards. Additionally, folder-level settings are supported in multi-root workspaces for granular control.

For this tutorial, we maintain global settings in the ~/.config/Code/User/settings.json file on Unix-based systems to provide consistent baseline configurations across all projects. Here are the essential settings currently configured:

 1{
 2  "files.autoSave": "onFocusChange",
 3  "editor.formatOnSave": true,
 4  "editor.formatOnSaveMode": "modificationsIfAvailable",
 5  "editor.pasteAs.preferences": ["text.plain"],
 6
 7  // Markdown Configuration
 8  "[markdown]": {
 9    "editor.defaultFormatter": "esbenp.prettier-vscode"
10  },
11
12  // =========================================================================
13  // PRETTIER CONFIGURATION
14  // =========================================================================
15  "prettier.endOfLine": "lf",
16  "prettier.singleQuote": true,
17  "prettier.arrowParens": "always",
18  "prettier.proseWrap": "preserve"
19}

There are number of settings shown above, we only pay attention to the following settings at present:

  1. "files.autoSave": "onFocusChange": This setting enables automatic saving of files when the editor focus changes, ensuring that changes are not lost.
  2. "editor.formatOnSave": true: This setting enables automatic formatting of files upon saving, ensuring consistent code style.
  3. "editor.defaultFormatter": "esbenp.prettier-vscode": This setting is defined in language specific scope that is for Markdown content this formatter is used.
  4. "editor.formatOnSaveMode": "modificationsIfAvailable": This setting increases efficiency by formatting only the modified sections of a file when saving, rather than reformatting the entire document. This is particularly useful for large files or when making frequent edits, as it reduces the time taken for formatting operations and minimizes disruptions to the editing workflow.

Therefore if you make your project a git repository and commit the initial files. Change this seetting as shown below in your project .vscode/settings.json file to format the entire file on save.

1{
2  "editor.formatOnSaveMode": "file"
3}

Practical Implementation and Testing

Initial Project Setup

When beginning work on a new project, follow this recommended approach:

  1. Start with no project-specific settings.
  2. Keep the .vscode/settings.json file empty initially.
  3. Verify that global/user settings are applied correctly.
  4. Add project-specific configurations only when necessary.
  5. Install the necessary extensions: Markdownlint, YAML Front Matter Lint, and Prettier - Code formatter.

Testing the Configuration

Let’s verify our setup by creating a test file with intentional formatting issues. Create a file named broken-frontmatter.md and observe the visual indicators for linting issues, status bar statistics, messages in the problem pane and automatic formatting behavior on focus change or save events.

Example test content with formatting issues:

 1--
 2title:            Test Post
 3date: 2024-01-01
 4draft:  true
 5tags: [tag1, tag2, tag3]
 6
 7categories: [category1, category2]
 8author: "Author Name"
 9summary: 'This is a test post to check frontmatter formatting issues.'
10slug: 
11    - test-post
12---
13
14##          Content
15
16This has frontmatter        formatting issues.
Visual demonstration of markdown linting with YAML frontmatter issues highlighted

Markdown content displaying YAML frontmatter linting issues in VS Code

Verifying Auto-Save and Formatting

To confirm that both auto-save and formatting features work as expected:

  1. Make changes to your test file
  2. Switch focus to another file and return to the Markdown file
  3. Observe the automatic formatting applied

The file should be automatically formatted as shown below:

 1---
 2title: Test Post
 3date: 2024-01-01
 4draft: true
 5tags: [tag1, tag2, tag3]
 6
 7categories: [category1, category2]
 8author: 'Author Name'
 9summary: 'This is a test post to check frontmatter formatting issues.'
10slug:
11  - test-post
12---
13
14## Content
15
16This has formatting issues.

Linting Markers

For a linting extension to show the markers or lint the code, it has to parse the code first. If the code has syntax errors, the extension may not be able to parse it correctly, leading to no linting markers being displayed. For example, markdownlint extension expects frontmatter to be a valid yaml and the code must be syntactically correct. The following mistake maks the front matter invalid hence will not be piced up by markdownlint extension.

1---
2
3title: Test Pass
4draft true
5
6---

Markdownlint treats the content between --- delimiters as YAML and attempts to parse it. The linting behavior depends on whether the YAML is syntactically valid:

When YAML is invalid, If there’s a syntax error in the YAML (like a missing colon), markdownlint:

  • Fails to parse the YAML block
  • Stops processing or treats the entire front matter as problematic
  • May not lint the markdown content properly

Therefore, to pick up the errors in the front matter, ensure you have a mechanism laid out correctly and for this reason we are using YAML-Fm-Lint extension which is specifically designed to lint YAML front matter in markdown files.

In the above scenario, the YAML-Fm-Lint extension would help identify and fix the front matter issues.

Visual demonstration of markdown linting with YAML frontmatter issues highlighted

Markdown content displaying YAML frontmatter linting issues in VS Code


Conclusion

Our linting and formatting setup demonstrates three critical advantages:

  1. Zero-Configuration Functionality Linting operates immediately without any project-specific configuration, working seamlessly for both frontmatter and Markdown content.

  2. Integrated Global Settings Global settings such as onFocusChange auto-save and formatOnSave function reliably across all projects.

  3. Out-of-the-Box Experience The entire workflow functions without requiring any project-level configuration, making it ideal for rapid development and consistent team collaboration.


FAQs