secretumvault/.github/scripts/check-malformed-fences.nu
2026-01-11 23:12:38 +00:00

75 lines
2.1 KiB
Plaintext
Executable File

#!/usr/bin/env nu
# Check for malformed closing code fences in markdown files
# CommonMark spec violation: Closing fences should be ``` without language specifiers
def main [] {
# Find all markdown files (excluding ignored directories)
let md_files = (
glob **/*.md
| where {|f| not ($f | str contains ".git") }
| where {|f| not ($f | str contains "target") }
| where {|f| not ($f | str contains "node_modules") }
| where {|f| not ($f | str contains ".coder") }
| where {|f| not ($f | str contains ".claude") }
| where {|f| not ($f | str contains ".wrks") }
)
mut total_issues = 0
mut files_with_issues = []
for file in $md_files {
let issues = (check_file $file)
if ($issues | length) > 0 {
$total_issues = $total_issues + ($issues | length)
$files_with_issues = ($files_with_issues | append {file: $file, issues: $issues})
}
}
if $total_issues > 0 {
print $"❌ Found ($total_issues) malformed closing fence\(s\) in ($files_with_issues | length) file\(s\):\n"
for item in $files_with_issues {
print $" ($item.file):"
for issue in $item.issues {
print $" Line ($issue.line): ($issue.content)"
}
}
print "\nFix: Remove language specifiers from closing fences (should be just ```)"
exit 1
} else {
print "✅ No malformed closing fences found"
exit 0
}
}
def check_file [file: string] {
mut issues = []
mut in_code_block = false
mut line_num = 0
for line in (open $file | lines) {
$line_num = $line_num + 1
# Check if line is a code fence
let fence_match = ($line | parse --regex '^```(?P<lang>\w+)?\s*$')
if ($fence_match | length) > 0 {
if not $in_code_block {
# Opening fence
$in_code_block = true
} else {
# Closing fence
let lang = ($fence_match | get 0.lang? | default "")
if ($lang | str length) > 0 {
# Malformed: has language on closing fence
$issues = ($issues | append {line: $line_num, content: $line})
}
$in_code_block = false
}
}
}
$issues
}