fix(client): colour-span conceal must skip unallocatable colours
CI / cargo fmt --check (push) Successful in 34s
CI / cargo clippy (push) Successful in 42s
CI / cargo test (push) Successful in 35s
CI / editor keymaps (push) Successful in 1m36s

A literal `<span style="color:…">` in prose (the sample wiki's own colorize
instructions used one, with a `…` ellipsis as the colour) was matched by the
scanner and fed to `highlight guifg=…`, which raised E254 on the un-silenced
guifg line. That aborted the whole nuwiki#colors#refresh(), so on the Vim
clients NO spans got concealed (start-vim) and follow-link crashed mid
FileType autocmd (start-vim-coc). Neovim happened to dodge it depending on
which buffer was scanned.

s:define() now:
- validates the colour (only #hex or an alphabetic name) and skips anything
  else — rgb()/hsl() functions and prose examples no longer create bogus
  conceal regions or errors;
- runs both `highlight` calls under `silent!`, so a valid-format but unknown
  name can't abort the refresh either (tags still conceal, text just isn't
  recoloured).

Also reworded the sample wiki's colorize note so it no longer embeds a
literal span tag.

Test: colorize.skips_unallocatable_colour (vim) — an rgb() span before a real
one: refresh doesn't error, the rgb span isn't concealed, the real span still
is. nvim 269, vim 260+18, all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 16:09:15 +00:00
parent 15ba774a28
commit 9de8543385
3 changed files with 32 additions and 6 deletions
+18
View File
@@ -545,6 +545,24 @@ call s:record(
\ 'concealed=' . synconcealed(1, 1)[0]
\ . ' grp=' . synIDattr(synID(1, stridx(s:cz_l2, 'target') + 1, 1), 'name'))
" A span whose colour Vim can't allocate (rgb()/prose) must be skipped — not
" abort refresh, not conceal — while a real span afterwards still conceals.
call s:set_buf(['plain', 'x <span style="color:rgb(1,2,3)">y</span> z', '<span style="color:red">word</span> z'])
call cursor(1, 1)
let s:cz_e = ''
try
call nuwiki#colors#refresh()
catch
let s:cz_e = v:exception
endtry
call s:record(
\ s:cz_e ==# ''
\ && synconcealed(3, 1)[0] == 1
\ && synconcealed(2, stridx(getline(2), '<span') + 1)[0] == 0 ? 1 : 0,
\ 'colorize.skips_unallocatable_colour',
\ 'err=' . s:cz_e . ' real=' . synconcealed(3, 1)[0]
\ . ' rgb=' . synconcealed(2, stridx(getline(2), '<span') + 1)[0])
" ===== Follow-link resolves + opens in the current window (regression) =====
" follow_link_or_create() must resolve the definition itself and `:edit` the
" target in the CURRENT window — including a page that does not exist yet