From e37404f7fecc5f57e4f3df4cf5ba0adec67bfbb3 Mon Sep 17 00:00:00 2001 From: yayoyuyu <112897090+yayoyuyu@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:29:27 +0900 Subject: [PATCH] fix(tohtml): enclose font-family names in quotation marks Font-family names must be enclosed in quotation marks to ensure that fonts are applied correctly when there are spaces in the name. Fix an issue where multiple fonts specified in `vim.o.guifont` are inserted as a single element, treating them as a single font. Support for escaping commas with backslash and ignoring spaces after a comma. ref `:help 'guifont'` --- runtime/lua/tohtml.lua | 18 +++++- test/functional/plugin/tohtml_spec.lua | 85 ++++++++++++++++---------- 2 files changed, 70 insertions(+), 33 deletions(-) diff --git a/runtime/lua/tohtml.lua b/runtime/lua/tohtml.lua index 6a5bd6de9d..ed42b28725 100644 --- a/runtime/lua/tohtml.lua +++ b/runtime/lua/tohtml.lua @@ -1293,9 +1293,25 @@ local function opt_to_global_state(opt, title) local fonts = {} if opt.font then fonts = type(opt.font) == 'string' and { opt.font } or opt.font --[[@as (string[])]] + for i, v in pairs(fonts) do + fonts[i] = ('"%s"'):format(v) + end elseif vim.o.guifont:match('^[^:]+') then - table.insert(fonts, vim.o.guifont:match('^[^:]+')) + -- Example: + -- Input: "Font,Escape\,comma, Ignore space after comma" + -- Output: { "Font","Escape,comma","Ignore space after comma" } + local prev = '' + for name in vim.gsplit(vim.o.guifont:match('^[^:]+'), ',', { trimempty = true }) do + if vim.endswith(name, '\\') then + prev = prev .. vim.trim(name:sub(1, -2) .. ',') + elseif vim.trim(name) ~= '' then + table.insert(fonts, ('"%s%s"'):format(prev, vim.trim(name))) + prev = '' + end + end end + -- Generic family names (monospace here) must not be quoted + -- because the browser recognizes them as font families. table.insert(fonts, 'monospace') --- @type vim.tohtml.state.global local state = { diff --git a/test/functional/plugin/tohtml_spec.lua b/test/functional/plugin/tohtml_spec.lua index dbf385c0c3..8cb7105660 100644 --- a/test/functional/plugin/tohtml_spec.lua +++ b/test/functional/plugin/tohtml_spec.lua @@ -136,6 +136,53 @@ local function run_tohtml_and_assert(screen, func) screen:expect({ grid = expected.grid, attr_ids = expected.attr_ids }) end +---@param guifont boolean +local function test_generates_html(guifont) + insert([[line]]) + exec('set termguicolors') + local bg = fn.synIDattr(fn.hlID('Normal'), 'bg#', 'gui') + local fg = fn.synIDattr(fn.hlID('Normal'), 'fg#', 'gui') + if guifont then + exec_lua [[ + vim.o.guifont="Font,Escape\\,comma, Ignore space after comma" + local outfile = vim.fn.tempname() .. '.html' + local html = require('tohtml').tohtml(0,{title="title"}) + vim.fn.writefile(html, outfile) + vim.cmd.split(outfile) + ]] + else + exec_lua [[ + local outfile = vim.fn.tempname() .. '.html' + local html = require('tohtml').tohtml(0,{title="title",font={ "dumyfont","anotherfont" }}) + vim.fn.writefile(html, outfile) + vim.cmd.split(outfile) + ]] + end + local out_file = api.nvim_buf_get_name(api.nvim_get_current_buf()) + eq({ + '', + '', + '', + '', + 'title', + (''):format(api.nvim_get_var('colors_name')), + '', + '', + '', + '
',
+    'line',
+    '',
+    '
', + '', + '', + }, fn.readfile(out_file)) +end + describe(':TOhtml', function() --- @type test.functional.ui.screen local screen @@ -146,38 +193,12 @@ describe(':TOhtml', function() 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({ - '', - '', - '', - '', - 'title', - (''):format(api.nvim_get_var('colors_name')), - '', - '', - '', - '
',
-      'line',
-      '',
-      '
', - '', - '', - }, fn.readfile(out_file)) + it('generates html', function() + test_generates_html(false) + end) + + it("generates html, respects 'guifont'", function() + test_generates_html(true) end) it('expected internal html generated from range', function()