Files
my-rook-config/tests/scripts/markdownlint-tab-spacing.js
T
Blaine Gardner c9d99e01a0 ci: use markdownlint to enforce mkdocs compatibility
mkdocs uses a markdown renderer that is hardcoded to 4 spaces per tab
for detecting indentation levels, including ordered- and
unordered-lists. Since we cannot easily change the renderer, begin using
a markdown linter in CI that will fail if official docs do not adhere to
the spacing rules.

As a starting point, the markdownlint config does not begin with the
default set of checks, which might overwhelm attempts to fix them.
Instead, focus on list-tab-spacing rules and a few other highly useful
checks.

markdownlint also has some gaps in its abilities that allow common Rook
doc issues to pass acceptance. However, it allows creating custom
linting plugins. Create 2 such linting plugins to check 2 things:

- all doc lines (except code blocks) must be aligned to a 4-space
  boundary, without exception. This ensures that markdown will render
  correctly with mkdocs. This unfortunately makes it possible to create
  lists that are internally aligned strangely.
- admonitions must all follow the same format of
  ```
  !!! header
      body
  ```

For the strange lists, this is allowed and renders correctly, but it
looks strange:

```md
- first bullet
- second bullet
    still second bullet
- third bullet

    has a paragraph
    of text inside

- last bullet

Signed-off-by: Blaine Gardner <blaine.gardner@ibm.com>
2024-04-29 17:25:11 -06:00

78 lines
3.3 KiB
JavaScript

// enforce that lines must be indented to a strict number of tab-spaces
// this lint rule is largely non-contextual and requires nearly all lines to adhere to the rule
// this is even true for ordered/unordered lists in which mkdocs **usually** allows spacing to match
// that of the parent line. but this rule is quick and dirty, and it does not harm to enforce
// indenting to 4-space boundaries to be entirely certain that mkdocs will render as intended.
const expected_tab_spaces = 4
// it's hard to know exactly what spacing the user intended, but we can make an educated guess
// considering 2 things:
// 1. most code editors are likely to indent to 2 spaces by default. therefore, suggest
// that anything indented 2 spaces or more should be indented all the way
// 2. some users put a single space in front of bullets/numbers when starting a list.
// therefore, suggest that anything indented only a single space should be non-indented
const suggested_spacing_indent_cutoff = 2
module.exports = {
"names": [ "strict-tab-spacing" ],
"description": "Enforce strict tab spacing",
"tags": [ "test" ],
"parser": "none",
"function": function rule(params, onError) {
const { lines } = params;
const countTabSpaces = (line) => {
start_spaces = /^\s*/;
return line.match(start_spaces)[0].length
};
const generateTabSpaces = (count) => {
return ''.padStart(count, ' ')
}
const isCodeBlockEnd = (line) => {
trimmed = line.trim()
return ( trimmed === "```" )
}
const isCodeBlockStart = (line) => {
if ( isCodeBlockEnd(line) ) return false;
trimmed = line.trim()
return ( trimmed.startsWith("```") )
}
let code_block_depth = 0
lines.forEach((line, i) => {
// don't strictly enforce tab spacing inside code blocks
if ( isCodeBlockStart(line) ) {
code_block_depth++
// code block start lines must be indented to a tab-space boundary
} else if ( isCodeBlockEnd(line) ) {
code_block_depth--
// code block end lines must also be indented to a tab-space boundary
} else if ( code_block_depth > 0 ) {
// if inside of a code block, but not a start/end line, don't warn about spacing
return
}
const thisLineNumber = i+1 // "lineNumber" field is ones-based
got_tab_spaces = countTabSpaces(line)
const floor = got_tab_spaces / expected_tab_spaces
const remainder = got_tab_spaces % expected_tab_spaces
if ( remainder != 0 ) {
// begin with the assumption that the line should be non-indented
suggested_spacing = generateTabSpaces(floor)
if ( remainder >= suggested_spacing_indent_cutoff ) {
suggested_spacing = generateTabSpaces(floor + expected_tab_spaces)
}
onError({
"lineNumber": thisLineNumber,
"detail": "lines must be indented to a strict boundary of " + expected_tab_spaces + " spaces",
"context": line,
"fixInfo": {
"lineNumber": thisLineNumber,
"deleteCount": got_tab_spaces,
"insertText": suggested_spacing, // insert at beginning of lineNumber
},
});
}
});
}
};