fix(11.1-07): check go fences, README src= and shell fences from the AST

- goLang follows the highlighter's chroma lookup, so golang and main.go need src=
- a src= fence in a module README is refused and never captioned
- shell fences inside callouts and lists are command-checked
- a fence with four or more leading spaces is an indented code block
This commit is contained in:
Jakub Zych
2026-10-01 08:30:19 +02:00
parent 5b7e37fb69
commit 73c72af244
8 changed files with 88 additions and 49 deletions

View File

@@ -452,6 +452,11 @@ type drift struct {
// its container marker, so the fence is refused instead of extracted.
const nestedSrcMessage = "src= code block must be a top-level block of the page, not inside a callout, blockquote or list item"
// readmeSrcMessage is the problem for a src= fence in a module README.
// Those fences are rendered as written and never compared, so a src=
// there would claim a check that does not run.
const readmeSrcMessage = "module README code blocks are rendered as written; src= is verified only in docs/ pages"
// checkFences verifies every src= fence in fences. lines are the body
// lines the fences index into. lineBase is the 1-based file line of
// lines[0]; file is the display path for problems.
@@ -513,19 +518,30 @@ func unindent(l string, n int) string {
return l[i:]
}
// checkSnippets verifies the src= fences of every docs page. Module
// READMEs are skipped here; a later check refuses src= on those pages
// because their fences are rendered as written.
// checkSnippets verifies the src= fences of every page. A docs/ page is
// compared with its source. A module README is rendered as written, so
// any src= fence there is refused instead of checked.
func (s *site) checkSnippets(docs []parsedDoc) ([]Problem, error) {
var problems []Problem
for _, d := range docs {
if d.page == nil || d.page.Module != "" {
if d.page == nil {
continue
}
fences, err := collectFences(d.doc, d.body)
if err != nil {
return nil, err
}
if d.page.Module != "" {
for _, f := range fences {
ref, ok := ParseSrc(f.info)
if !ok {
continue
}
problems = append(problems, Problem{File: d.file, Line: d.line + f.line, Rule: "snippet",
Message: ref.String() + ": " + readmeSrcMessage})
}
continue
}
_, ps, err := checkFences(s.opts.Root, d.file, strings.Split(string(d.body), "\n"), d.line, fences)
if err != nil {
return nil, err