Skip to content

fix: distinguish unclosed YAML front matter from missing front matter (new YamlFrontMatterUnclosed rule)#1

Open
accesswatch wants to merge 1 commit into
jamalmazrui:mainfrom
accesswatch:feat/yaml-front-matter-unclosed
Open

fix: distinguish unclosed YAML front matter from missing front matter (new YamlFrontMatterUnclosed rule)#1
accesswatch wants to merge 1 commit into
jamalmazrui:mainfrom
accesswatch:feat/yaml-front-matter-unclosed

Conversation

@accesswatch
Copy link
Copy Markdown

Summary

This PR fixes a logic bug in mdModule.metadata() and adds a new rule to distinguish between two distinct document problems that currently both fire NoYamlFrontMatter.

The bug

When a Markdown file starts with --- but has no closing --- or ... delimiter, parseYaml() sets iYamlEndLine = 0 (same as when no front matter exists at all). metadata() then fires NoYamlFrontMatter even though the author clearly intended to write front matter — they just forgot the closing fence. The remediation message "Add a YAML front matter block" is confusing because the block already exists.

Example that currently misfires

---
title: My Document
lang: en

This is the document body with no closing --- above.

Changes

Location Change
mdModule fields Add static bool bYamlOpened;
parseYaml() Set bYamlOpened = false at entry; set bYamlOpened = true after the opening --- is confirmed
metadata() Replace if (iYamlEndLine == 0) with two-stage check: if (!bYamlOpened)NoYamlFrontMatter; else if (iYamlEndLine == 0) → new YamlFrontMatterUnclosed
writeRulesCsv() Add YamlFrontMatterUnclosed row after NoYamlFrontMatter row

New rule

Field Value
RuleId YamlFrontMatterUnclosed
Source MSAC
Category Missing document properties
WCAG 2.4.2
Severity Error
AppliesTo MD
Message The YAML front matter block starting with --- on line 1 has no closing --- or ... delimiter. Pandoc will not process it as front matter.
Remediation Add a closing --- or ... line immediately after the last YAML field, before the document body begins.

Origin

This issue was discovered while implementing the same rule (MD-YAML-UNCLOSED-FENCE) in the GLOW Accessibility Toolkit, an open-source VS Code agent toolkit for auditing Office documents and Markdown files for accessibility compliance. We wanted to contribute the fix back to extCheck as thanks for the inspiration.


Tested by manual inspection of the state machine changes. No new dependencies introduced.

Add a new YamlFrontMatterUnclosed rule that fires when a file starts
with a --- YAML delimiter but has no matching closing --- or ... line.
Previously, the existing NoYamlFrontMatter rule would fire in both
cases -- true absence of front matter AND unclosed front matter --
because both result in iYamlEndLine == 0.

Changes:
- Add static bool bYamlOpened field in mdModule
- In parseYaml(): set bYamlOpened=false at entry, true after the
  opening --- is confirmed
- In metadata(): change iYamlEndLine==0 gate to two-stage:
    if (!bYamlOpened) -> NoYamlFrontMatter (no opening --- at all)
    else if (iYamlEndLine==0) -> YamlFrontMatterUnclosed (new rule)
- Add YamlFrontMatterUnclosed to writeRulesCsv() rule registry

This distinction matters for accurate remediation guidance:
  - NoYamlFrontMatter: 'add a front matter block'
  - YamlFrontMatterUnclosed: 'add the missing closing --- delimiter'

Discovered during implementation of the same rule in the GLOW
Accessibility Toolkit (github.com/jeffbish/glow) where it is tracked
as MD-YAML-UNCLOSED-FENCE.
Copilot AI review requested due to automatic review settings April 28, 2026 21:05
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Markdown (mdModule) YAML front matter detection so the checker can distinguish between (a) missing YAML front matter and (b) YAML front matter that was started but never closed, introducing a new YamlFrontMatterUnclosed rule to avoid confusing remediation guidance.

Changes:

  • Add YamlFrontMatterUnclosed to the rule registry output (writeRulesCsv()).
  • Track whether a YAML front matter opening fence was seen (bYamlOpened) during parseYaml().
  • Update metadata() to emit NoYamlFrontMatter vs YamlFrontMatterUnclosed based on bYamlOpened and iYamlEndLine.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread extCheck.cs

static void parseYaml() {
bYamlOpened = false;
if (aLines.Length < 2 || aLines[0].Trim() != "---") {
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseYaml() returns early when aLines.Length < 2 even if line 1 is ---, leaving bYamlOpened false. For a file that contains only the opening fence (or ends immediately after it), this will still report NoYamlFrontMatter instead of the new YamlFrontMatterUnclosed. Consider removing the length check (or moving it after confirming the opening fence) so bYamlOpened is set true whenever the first line is ---, and the loop can simply no-op when there are no subsequent lines.

Suggested change
if (aLines.Length < 2 || aLines[0].Trim() != "---") {
if (aLines.Length == 0 || aLines[0].Trim() != "---") {

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants