Skip to content

Commit

Permalink
Add Markdown diff linter
Browse files Browse the repository at this point in the history
Add Makefile target, and scripts to lint only the modified Markdown
files, failing only if the violation is within the changed lines.

Signed-off-by: Ivan Valdes <[email protected]>
  • Loading branch information
ivanvc committed Aug 7, 2024
1 parent 5d9e9fe commit 2d222a1
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
config:
line-length: false # Allow lines longer than 80 characters.
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,10 @@ ifndef LATEST_VERSION
else
./scripts/update_release_version.sh "$(LATEST_VERSION)"
endif

.PHONY: markdown-diff-lint
markdown-diff-lint:
ifndef CHANGED_FILES
@echo "Warning: CHANGED_FILES is not specified, or empty"
endif
./scripts/markdown_diff_lint.sh "$(CHANGED_FILES)"
98 changes: 98 additions & 0 deletions scripts/markdown_diff_lint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env bash
# This script runs markdownlint-cli2 on changed files.
# Usage: ./markdown_lint.sh

set -eo pipefail

if ! command markdownlint-cli2 dummy.md &>/dev/null; then
echo "markdownlint-cli2 needs to be installed."
echo "Install it by running npm install -g markdownlint-cli2"
exit 1
fi

COLOR_RED='\033[0;31m'
COLOR_BOLD='\033[1m'
COLOR_ORANGE='\033[0;33m'
COLOR_NONE='\033[0m' # No Color

function log_error {
echo -n -e "${COLOR_BOLD}${COLOR_RED}$*${COLOR_NONE}\n"
}

function log_warning {
echo -n -e "${COLOR_ORANGE}$*${COLOR_NONE}\n"
}

if [ -z "${PULL_BASE_SHA}" ]; then
echo "Empty base reference (\$PULL_BASE_SHA), assuming: main"
PULL_BASE_SHA=main
fi

if [ -z "${PULL_PULL_SHA}" ]; then
PULL_PULL_SHA="$(git rev-parse HEAD)"
echo "Empty pull reference (\$PULL_PULL_SHA), assuming: ${PULL_PULL_SHA}"
fi

MD_LINT_URL_PREFIX="https://github.com/DavidAnson/markdownlint/blob/main/doc/"

mapfile -t changed_files < <(git diff "${PULL_BASE_SHA}" --name-only)
declare -A files_with_failures start_ranges end_ranges

for file in "${changed_files[@]}"; do
if ! [[ "$file" =~ .md$ ]]; then
continue
fi

# Find start and end ranges from changed files.
start_ranges=()
end_ranges=()
# From https://github.com/paleite/eslint-plugin-diff/blob/46c5bcf296e9928db19333288457bf2805aad3b9/src/git.ts#L8-L27
ranges=$(git diff "${PULL_BASE_SHA}" \
--diff-algorithm=histogram \
--diff-filter=ACM \
--find-renames=100% \
--no-ext-diff \
--relative \
--unified=0 -- "${file}" | \
awk 'match($0, /^@@\s-[0-9,]+\s\+([0-9]+)(,([0-9]+))?/, m) { \
print m[1] ":" m[1] + ((m[3] == "") ? "0" : m[3]) }')
i=0
for range in ${ranges}; do
start_ranges["${i}"]=$(echo "${range}" | awk -F: '{print $1}')
end_ranges["${i}"]=$(echo "${range}" | awk -F: '{print $2}')
i=$((1 + i))
done
if [ -z "${ranges}" ]; then
start_ranges[0]=0
end_ranges[0]=0
fi

i=0
markdownlint-cli2 "${file}" 2>/dev/null || true
while IFS= read -r line; do
line_number=$(echo "${line}" | awk -F: '{print $2}' | awk '{print $1}')
while [ "${i}" -lt "${#end_ranges[@]}" ] && [ "${line_number}" -gt "${end_ranges["${i}"]}" ]; do
i=$((1 + i))
done
rule=$(echo "${line}" | awk 'match($2, /([^\/]+)/, m) {print tolower(m[1])}')
lint_error="${line} (${MD_LINT_URL_PREFIX}${rule}.md)"

if [ "${i}" -lt "${#start_ranges[@]}" ] && [ "${line_number}" -ge "${start_ranges["${i}"]}" ] && [ "${line_number}" -le "${end_ranges["${i}"]}" ]; then
# Inside range with changes, raise an error.
log_error "${lint_error}"
files_with_failures["${file}"]=1
else
# Outside of range, raise a warning.
log_warning "${lint_error}"
fi
done < <(markdownlint-cli2 "${file}" 2>&1 >/dev/null || true)
done

echo "Finished linting"

for file in "${!files_with_failures[@]}"; do
log_error "${file} has linting issues"
done
if [ "${#files_with_failures[@]}" -gt "0" ]; then
exit 1
fi

0 comments on commit 2d222a1

Please sign in to comment.