mirror of
https://github.com/neovim/neovim.git
synced 2026-05-05 13:35:02 +00:00
feat!: rewrite TOhtml in lua
Co-authored-by: wookayin <wookayin@gmail.com> Co-authored-by: clason <c.clason@uni-graz.at> Co-authored-by: Lewis Russell <me@lewisr.dev>
This commit is contained in:
370
test/functional/plugin/tohtml_spec.lua
Normal file
370
test/functional/plugin/tohtml_spec.lua
Normal file
@@ -0,0 +1,370 @@
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local clear = helpers.clear
|
||||
local exec = helpers.exec
|
||||
local exec_lua = helpers.exec_lua
|
||||
local eq = helpers.eq
|
||||
local fn = helpers.fn
|
||||
local api = helpers.api
|
||||
local insert = helpers.insert
|
||||
|
||||
local function html_syntax_match()
|
||||
local styles =
|
||||
vim.split(api.nvim_exec2([[/<style>/+,/<\/style>/-p]], { output = true }).output, '\n')
|
||||
local attrnames = {
|
||||
['font%-weight: bold'] = 'bold',
|
||||
['text%-decoration%-line: [^;]*underline'] = 'underline',
|
||||
['font%-style: italic'] = 'italic',
|
||||
['text%-decoration%-line: [^;]*line%-through'] = 'strikethrough',
|
||||
}
|
||||
local hls = {}
|
||||
for _, style in ipairs(styles) do
|
||||
local attr = {}
|
||||
for match, attrname in pairs(attrnames) do
|
||||
if style:find(match) then
|
||||
---@type boolean
|
||||
attr[attrname] = true
|
||||
end
|
||||
end
|
||||
if style:find('text%-decoration%-style: wavy') and attr.underline then
|
||||
---@type boolean
|
||||
attr.underline = nil
|
||||
attr.undercurl = true
|
||||
end
|
||||
attr.bg = style:match('background%-color: #(%x+)')
|
||||
if attr.bg then
|
||||
attr.bg = tonumber(attr.bg, 16)
|
||||
end
|
||||
attr.fg = style:match('[^%-]color: #(%x+)')
|
||||
if attr.fg then
|
||||
attr.fg = tonumber(attr.fg, 16)
|
||||
end
|
||||
if style:match('^%.(%w+)') then
|
||||
---@type table
|
||||
hls[style:match('^%.(%w+)')] = attr
|
||||
end
|
||||
end
|
||||
local whitelist = {
|
||||
'fg',
|
||||
'bg',
|
||||
--'sp',
|
||||
--'blend',
|
||||
'bold',
|
||||
--'standout',
|
||||
'underline',
|
||||
'undercurl',
|
||||
--'underdouble',
|
||||
--'underdotted',
|
||||
--'underdashed',
|
||||
'strikethrough',
|
||||
'italic',
|
||||
--'reverse',
|
||||
--'nocombine',
|
||||
}
|
||||
for name, attrs_old in
|
||||
pairs(api.nvim_get_hl(0, { link = true }) --[[@as table<string,table>]])
|
||||
do
|
||||
---@type table
|
||||
local other = hls[name:gsub('%.', '-'):gsub('@', '-')]
|
||||
if other then
|
||||
local attrs = {}
|
||||
for _, attrname in ipairs(whitelist) do
|
||||
---@type table
|
||||
attrs[attrname] = attrs_old[attrname]
|
||||
end
|
||||
eq(attrs, other)
|
||||
end
|
||||
end
|
||||
return hls
|
||||
end
|
||||
|
||||
local function html_to_extmarks()
|
||||
local buf = api.nvim_get_current_buf()
|
||||
local ns = api.nvim_create_namespace 'test-namespace'
|
||||
api.nvim_buf_clear_namespace(buf, ns, 0, -1)
|
||||
exec 'silent! norm! ggd/^<pre>$\rddG3dk'
|
||||
local stack = {}
|
||||
exec [[set filetype=]]
|
||||
exec [[silent! %s/</¤/g]]
|
||||
exec [[silent! %s/"/"/g]]
|
||||
exec [[silent! %s/&/\&/g]]
|
||||
exec [[silent! %s/>/>/g]]
|
||||
exec [[silent! %s/</</g]]
|
||||
for _, match in
|
||||
ipairs(
|
||||
fn.matchbufline(buf, [[¤span class="\([^"]\+\)">\|¤/span>]], 1, '$', { submatches = true }) --[[@as (table[])]]
|
||||
)
|
||||
do
|
||||
if match.text == '¤/span>' then
|
||||
local val = table.remove(stack)
|
||||
api.nvim_buf_set_extmark(buf, ns, val.lnum - 1, val.byteidx, {
|
||||
hl_group = val.submatches[1],
|
||||
end_row = match.lnum - 1,
|
||||
end_col = match.byteidx,
|
||||
})
|
||||
else
|
||||
table.insert(stack, match)
|
||||
end
|
||||
end
|
||||
exec [[silent! %s/¤\/span>//g]]
|
||||
exec [[silent! %s/¤span[^>]*>//g]]
|
||||
end
|
||||
|
||||
---@param screen test.functional.ui.screen
|
||||
---@param func function?
|
||||
local function run_tohtml_and_assert(screen, func)
|
||||
exec('norm! ggO-;')
|
||||
exec('norm! gg0f;:\r')
|
||||
screen:sleep(10)
|
||||
local snapshot = { grid = screen:get_snapshot().grid, attr_ids = screen:get_snapshot().attr_ids }
|
||||
do
|
||||
(func or exec)('TOhtml')
|
||||
end
|
||||
exec('only')
|
||||
html_syntax_match()
|
||||
html_to_extmarks()
|
||||
exec('norm! gg0f;:\r')
|
||||
screen:sleep(10)
|
||||
eq(snapshot, { grid = screen:get_snapshot().grid, attr_ids = screen:get_snapshot().attr_ids })
|
||||
end
|
||||
|
||||
describe(':TOhtml', function()
|
||||
--- @type test.functional.ui.screen
|
||||
local screen
|
||||
before_each(function()
|
||||
clear({ args = { '--clean' } })
|
||||
screen = Screen.new(80, 80)
|
||||
screen:attach({ term_name = 'xterm' })
|
||||
exec('colorscheme default')
|
||||
end)
|
||||
|
||||
it('expected internal html generated', function()
|
||||
insert([[line]])
|
||||
exec('set termguicolors')
|
||||
local bg = fn.synIDattr(fn.hlID('Normal'), 'bg#', 'gui')
|
||||
local fg = fn.synIDattr(fn.hlID('Normal'), 'fg#', 'gui')
|
||||
exec_lua [[
|
||||
local outfile = vim.fn.tempname() .. '.html'
|
||||
local html = require('tohtml').tohtml(0,{title="title",font="dumyfont"})
|
||||
vim.fn.writefile(html, outfile)
|
||||
vim.cmd.split(outfile)
|
||||
]]
|
||||
local out_file = api.nvim_buf_get_name(api.nvim_get_current_buf())
|
||||
eq({
|
||||
'<!DOCTYPE html>',
|
||||
'<html>',
|
||||
'<head>',
|
||||
'<meta charset="UTF-8">',
|
||||
'<title>title</title>',
|
||||
('<meta name="colorscheme" content="%s"></meta>'):format(api.nvim_get_var('colors_name')),
|
||||
'<style>',
|
||||
'* {font-family: dumyfont,monospace}',
|
||||
('body {background-color: %s; color: %s}'):format(bg, fg),
|
||||
'</style>',
|
||||
'</head>',
|
||||
'<body style="display: flex">',
|
||||
'<pre>',
|
||||
'line',
|
||||
'',
|
||||
'</pre>',
|
||||
'</body>',
|
||||
'</html>',
|
||||
}, fn.readfile(out_file))
|
||||
end)
|
||||
|
||||
it('highlight attributes generated', function()
|
||||
--Make sure to uncomment the attribute in `html_syntax_match()`
|
||||
exec('hi LINE gui=' .. table.concat({
|
||||
'bold',
|
||||
'underline',
|
||||
'italic',
|
||||
'strikethrough',
|
||||
}, ','))
|
||||
exec('hi UNDERCURL gui=undercurl')
|
||||
exec('syn keyword LINE line')
|
||||
exec('syn keyword UNDERCURL undercurl')
|
||||
insert('line\nundercurl')
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
|
||||
it('syntax', function()
|
||||
insert [[
|
||||
function main()
|
||||
print("hello world")
|
||||
end
|
||||
]]
|
||||
exec('set termguicolors')
|
||||
exec('syntax enable')
|
||||
exec('setf lua')
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
|
||||
it('diff', function()
|
||||
exec('set diffopt=')
|
||||
insert [[
|
||||
diffadd
|
||||
nochage
|
||||
diffchange1
|
||||
]]
|
||||
exec('new')
|
||||
insert [[
|
||||
nochage
|
||||
diffchange2
|
||||
diffremove
|
||||
]]
|
||||
exec('set diff')
|
||||
exec('close')
|
||||
exec('set diff')
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
|
||||
it('treesitter', function()
|
||||
insert [[
|
||||
function main()
|
||||
print("hello world")
|
||||
end
|
||||
]]
|
||||
exec('setf lua')
|
||||
exec_lua('vim.treesitter.start()')
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
|
||||
it('matchadd', function()
|
||||
insert [[
|
||||
line
|
||||
]]
|
||||
fn.matchadd('Visual', 'line')
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
|
||||
describe('conceallevel', function()
|
||||
local function run(level)
|
||||
insert([[
|
||||
line0
|
||||
line1
|
||||
line2
|
||||
line3
|
||||
]])
|
||||
local ns = api.nvim_create_namespace ''
|
||||
fn.matchadd('Conceal', 'line1', 3, 5, { conceal = 'a' })
|
||||
api.nvim_buf_set_extmark(0, ns, 2, 0, { conceal = 'a', end_col = 5 })
|
||||
exec(':syntax match Conceal "line3" conceal cchar=a')
|
||||
exec('set conceallevel=' .. level)
|
||||
run_tohtml_and_assert(screen)
|
||||
end
|
||||
it('conceallevel=0', function()
|
||||
run(0)
|
||||
end)
|
||||
it('conceallevel=1', function()
|
||||
run(1)
|
||||
end)
|
||||
it('conceallevel=2', function()
|
||||
run(2)
|
||||
end)
|
||||
it('conceallevel=3', function()
|
||||
run(3)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('extmarks', function()
|
||||
it('virt_text', function()
|
||||
insert [[
|
||||
line1
|
||||
line2
|
||||
line3
|
||||
line4
|
||||
]]
|
||||
local ns = api.nvim_create_namespace ''
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'foo' } } })
|
||||
api.nvim_buf_set_extmark(
|
||||
0,
|
||||
ns,
|
||||
1,
|
||||
0,
|
||||
{ virt_text = { { 'foo' } }, virt_text_pos = 'overlay' }
|
||||
)
|
||||
api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = { { 'foo' } }, virt_text_pos = 'inline' })
|
||||
--api.nvim_buf_set_extmark(0,ns,3,0,{virt_text={{'foo'}},virt_text_pos='right_align'})
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
it('highlgith', function()
|
||||
insert [[
|
||||
line1
|
||||
]]
|
||||
local ns = api.nvim_create_namespace ''
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 2, hl_group = 'Visual' })
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
it('virt_line', function()
|
||||
insert [[
|
||||
line1
|
||||
line2
|
||||
]]
|
||||
local ns = api.nvim_create_namespace ''
|
||||
api.nvim_buf_set_extmark(0, ns, 1, 0, { end_col = 2, virt_lines = { { { 'foo' } } } })
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
end)
|
||||
|
||||
it('listchars', function()
|
||||
exec('setlocal list')
|
||||
exec(
|
||||
'setlocal listchars=eol:$,tab:<->,space:-,multispace:++,lead:_,leadmultispace:##,trail:&,nbsp:%'
|
||||
)
|
||||
fn.setline(1, '\tfoo\t')
|
||||
fn.setline(2, ' foo foo ')
|
||||
fn.setline(3, ' foo foo ')
|
||||
fn.setline(4, 'foo\x2cfoo')
|
||||
run_tohtml_and_assert(screen)
|
||||
exec('new|only')
|
||||
fn.setline(1, '\tfoo\t')
|
||||
exec('setlocal list')
|
||||
exec('setlocal listchars=tab:a-')
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
|
||||
it('folds', function()
|
||||
insert([[
|
||||
line1
|
||||
line2
|
||||
]])
|
||||
exec('set foldtext=foldtext()')
|
||||
exec('%fo')
|
||||
run_tohtml_and_assert(screen)
|
||||
end)
|
||||
|
||||
it('statuscol', function()
|
||||
local function run()
|
||||
local buf = api.nvim_get_current_buf()
|
||||
run_tohtml_and_assert(screen, function()
|
||||
exec_lua [[
|
||||
local outfile = vim.fn.tempname() .. '.html'
|
||||
local html = require('tohtml').tohtml(0,{number_lines=true})
|
||||
vim.fn.writefile(html, outfile)
|
||||
vim.cmd.split(outfile)
|
||||
]]
|
||||
end)
|
||||
api.nvim_set_current_buf(buf)
|
||||
end
|
||||
insert([[
|
||||
line1
|
||||
line2
|
||||
]])
|
||||
exec('setlocal relativenumber')
|
||||
run()
|
||||
exec('setlocal norelativenumber')
|
||||
exec('setlocal number')
|
||||
run()
|
||||
exec('setlocal relativenumber')
|
||||
run()
|
||||
exec('setlocal signcolumn=yes:2')
|
||||
run()
|
||||
exec('setlocal foldcolumn=2')
|
||||
run()
|
||||
exec('setlocal norelativenumber')
|
||||
run()
|
||||
exec('setlocal signcolumn=no')
|
||||
run()
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user