fix(lua): recognize spaceless headings (==Heading==) in client helpers
CI / editor tests (push) Successful in 44s

The shared heading_level helper still required spaces around the title, so
the client-side regex paths — fold fallback, text objects (ah/ih), and
heading navigation (]] etc.) — skipped spaceless headings, even though the
server (and HTML export) accept them since the #7 fix. Rewrite to match the
lexer: balanced leading/trailing `=` runs (cap 6) around a non-empty title,
spaced or spaceless. Marker-only (`======`), unbalanced (`==a==b`, `==> x`)
and 7+ runs still return 0.

Verified against an 18-case battery + full editor harness (10/10).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-28 12:28:37 +00:00
parent ac1db1af1d
commit a9208db2e4
+15 -3
View File
@@ -6,9 +6,14 @@ local M = {}
-- Heading level of `line` (1-6), or 0 when it isn't a heading. Mirrors the -- Heading level of `line` (1-6), or 0 when it isn't a heading. Mirrors the
-- server lexer: balanced leading/trailing runs of `=` around non-empty text, -- server lexer: balanced leading/trailing runs of `=` around non-empty text,
-- capped at level 6 (a 7+ `=` run is not a heading). `nil`-safe. -- capped at level 6 (a 7+ `=` run is not a heading). Both the spaced
-- (`== H ==`) and spaceless (`==H==`) forms are accepted, matching vimwiki.
-- `nil`-safe.
function M.heading_level(line) function M.heading_level(line)
local lead = line and line:match('^%s*(=+)%s') if not line then
return 0
end
local lead = line:match('^%s*(=+)')
if not lead then if not lead then
return 0 return 0
end end
@@ -16,10 +21,17 @@ function M.heading_level(line)
if lvl > 6 then if lvl > 6 then
return 0 return 0
end end
local trail = line:match('%s(=+)%s*$') -- Same-length trailing run of `=` at end of line (after optional trailing ws).
local trail = line:match('(=+)%s*$')
if not trail or #trail ~= lvl then if not trail or #trail ~= lvl then
return 0 return 0
end end
-- Non-empty title between the two runs (rules out marker-only lines like
-- `======`). `(.-)` is lazy, so the leading/trailing `=+` keep their runs.
local body = line:match('^%s*=+(.-)=+%s*$')
if not body or body:match('^%s*$') then
return 0
end
return lvl return lvl
end end