From 9135a66249bb75d113f8e1df171092f1332c5775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Ara=C3=BAjo?= Date: Mon, 9 Nov 2026 01:52:50 -0300 Subject: [PATCH] fix: let a hard line break keep a nested list separate A hard line break renders as
, which has no end tag. Nothing removed it from the tag history, so Vale read it as an open inline element. A nested list after it joined the list item above, and an enclosing could not pop its own tag. A void tag now leaves the history as soon as it enters. Closes #1225. Assisted-by: Claude Code --- internal/lint/ast.go | 7 +++++++ testdata/e2e/scopes.yaml | 42 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/internal/lint/ast.go b/internal/lint/ast.go index ae0ddd33..6f368ce4 100644 --- a/internal/lint/ast.go +++ b/internal/lint/ast.go @@ -205,6 +205,13 @@ func (l *Linter) lintHTMLTokens(f *core.File, raw []byte, offset int) error { // open = append(open, inlineCapture{tag: txt, scope: scope, masked: skip, begin: buf.Len()}) } walker.addTag(txt, class, getAttribute(tok, markAttr)) + // A void element has no end tag, so it leaves the history at once. + // Left there, a hard line break, `
`, reads as an open inline + // element. A nested list after it then joins the list item above, + // and an enclosing `` cannot pop its own tag (#1225). + if core.StringInSlice(txt, voidTags) { + walker.popTag(txt) + } } else if tokt == html.EndTagToken && isInline { walker.popTag(txt) walker.activeTag = "" diff --git a/testdata/e2e/scopes.yaml b/testdata/e2e/scopes.yaml index b33b6a98..dd3d46a1 100644 --- a/testdata/e2e/scopes.yaml +++ b/testdata/e2e/scopes.yaml @@ -400,6 +400,48 @@ cases: test.md:1:22:T.Text:text: after test.md:3:27:T.Text:text: after + - name: list-item-with-hard-break + about: "#1225 -- a hard line break, `
`, has no end tag. It stayed in the + tag history and joined the nested list to the item above, also inside + emphasis" + files: + .vale.ini: | + StylesPath = styles + MinAlertLevel = suggestion + + [*.md] + BasedOnStyles = T + styles/T/Item.yml: | + extends: metric + message: "item: %s words" + level: error + scope: list + formula: words + condition: "> 3" + break.md: | + - Lead line.\ + Second line. + - One two three four five six seven. + - One two three four five six seven. + - One two three four five six seven. + emphasis.md: | + - *Lead line.\ + second* line. + - One two three four five six seven. + - One two three four five six seven. + - One two three four five six seven. + args: break.md emphasis.md + exit: 1 + want: | + break.md:2:1:T.Item:item: 4.00 words + break.md:3:1:T.Item:item: 7.00 words + break.md:4:1:T.Item:item: 7.00 words + break.md:5:1:T.Item:item: 7.00 words + emphasis.md:2:1:T.Item:item: 4.00 words + emphasis.md:3:1:T.Item:item: 7.00 words + emphasis.md:4:1:T.Item:item: 7.00 words + emphasis.md:5:1:T.Item:item: 7.00 words + - name: table args: . requires: asciidoctor, rst2html