Skip to content

Commit

Permalink
fix(renderer): Made headings use decorations around the text instead …
Browse files Browse the repository at this point in the history
…of replacing the main text

Headings can now contain things like italic, bold text, inline codes,
html entities and any other inline elements without appearing as raw
text.
  • Loading branch information
OXY2DEV committed Aug 4, 2024
1 parent e102b06 commit 41d57ab
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 62 deletions.
10 changes: 8 additions & 2 deletions lua/markview.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1198,9 +1198,15 @@ markview.configuration = {
},

config = {
p = { conceal = true, hl = "Normal" },
b = { conceal = true, hl = "Bold" },
strong = { conceal = true, hl = "Bold" },

u = { conceal = true, hl = "Underlined" },
i = { conceal = true, hl = "Italic" }

i = { conceal = true, hl = "Italic" },
emphasize = { conceal = true, hl = "Italic" },

marked = { conceal = true, hl = "Special" },
}
},

Expand Down
35 changes: 26 additions & 9 deletions lua/markview/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@ parser.parsed_content = {};
---@param buffer number
---@param TStree any
parser.md = function (buffer, TStree, from, to)
if not parser.cached_conf or not parser.cached_conf.on_injected or parser.cached_conf.on_injected == false then
local root = TStree:root();
local root_r_start, _, root_r_end, _ = root:range();
local buf_lines = vim.api.nvim_buf_line_count(buffer);

if root_r_start ~= 0 or root_r_end ~= buf_lines then
return;
end
end

local scanned_queies = vim.treesitter.query.parse("markdown", [[
((setext_heading) @setext_heading)
Expand Down Expand Up @@ -154,23 +164,21 @@ parser.md = function (buffer, TStree, from, to)
col_end = col_end
})
elseif capture_name == "heading" then
local parent = capture_node:parent();

local heading_txt = capture_node:next_sibling();
local title = heading_txt ~= nil and vim.treesitter.get_node_text(heading_txt, buffer) or "";
local title = heading_txt ~= nil and vim.treesitter.get_node_text(heading_txt, buffer) or nil;
local h_txt_r_start, h_txt_c_start, h_txt_r_end, h_txt_c_end;

if heading_txt ~= nil then
h_txt_r_start, h_txt_c_start, h_txt_r_end, h_txt_c_end = heading_txt:range();
end

table.insert(parser.parsed_content, {
node = capture_node,
type = "heading",

level = vim.fn.strchars(capture_text),

line = vim.treesitter.get_node_text(parent, buffer),
marker = capture_text,
title = title,
title_pos = { h_txt_r_start, h_txt_c_start, h_txt_r_end, h_txt_c_end },

row_start = row_start,
row_end = row_end,
Expand Down Expand Up @@ -534,6 +542,17 @@ parser.md_inline = function (buffer, TStree, from, to)
end

parser.html = function (buffer, TStree, from, to)
if not parser.cached_conf or not parser.cached_conf.on_injected or parser.cached_conf.on_injected == false then
local root = TStree:root();
local root_r_start, _, _, _ = root:range();

local start_line = vim.api.nvim_buf_get_lines(buffer, root_r_start - 1, root_r_start, false)[1] or "";

if start_line:match("```") then
return;
end
end

local scanned_queies = vim.treesitter.query.parse("html", [[
((element) @elem)
]]);
Expand Down Expand Up @@ -591,7 +610,6 @@ parser.init = function (buffer, config_table)

-- Clear the previous contents
parser.parsed_content = {};
local main_tree_parsed = false;

root_parser:for_each_tree(function (TStree, language_tree)
local tree_language = language_tree:lang();
Expand All @@ -618,13 +636,12 @@ parser.parse_range = function (buffer, config_table, from, to)

-- Clear the previous contents
parser.parsed_content = {};
local main_tree_parsed = false;

root_parser:for_each_tree(function (TStree, language_tree)
local tree_language = language_tree:lang();

if tree_language == "markdown" then
parser.md(buffer, TStree, from, to)
parser.md(buffer, TStree, from, to);
elseif tree_language == "markdown_inline" then
parser.md_inline(buffer, TStree, from, to);
elseif tree_language == "html" then
Expand Down
89 changes: 38 additions & 51 deletions lua/markview/renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ local display_width = function (text, config)
local tag_conf = html_conf.tags;
local conf = tag_conf.default or {};

if tag_conf.config and tag_conf.config[filtered_tag] then
conf = tag_conf.config[filtered_tag]
if tag_conf.config and tag_conf.config[string.lower(filtered_tag)] then
conf = tag_conf.config[string.lower(filtered_tag)]
end

local internal_text = tmp_string:match("<" .. start_tag .. ">(.-)</" .. end_tag .. ">") or "";
Expand All @@ -252,7 +252,7 @@ local display_width = function (text, config)
::invalid::
end

for entity_name, semicolon in final_string:gmatch("&(%a+)(;?)") do
for entity_name, semicolon in final_string:gmatch("&([%a%d]+)(;?)") do
if not html_conf or html_conf.enable == false then
break;
elseif not html_conf.entites or html_conf.entites.enable == false then
Expand Down Expand Up @@ -553,7 +553,7 @@ local table_footer = function (buffer, content, config_table)

table.insert(virt_txt, { tbl_conf.text[9], set_hl(tbl_conf.hl[9]) })
curr_col = curr_col + 1
elseif index == #content.rows[1] then
elseif index == #content.rows[#content.rows] then
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, row_end - 1, col_start + curr_col, {
virt_text_pos = "inline",
virt_text = {
Expand Down Expand Up @@ -767,74 +767,61 @@ renderer.render_headings = function (buffer, content, config)
hl_mode = "combine"
});
elseif conf.style == "label" then
-- FIX: Make headings editable
local add_spaces = vim.fn.strchars(table.concat({
string.rep(conf.shift_char or " ", shift * (content.level - 1)),
conf.corner_left or "",
conf.padding_left or "",
conf.icon or "",
}));

-- Adds icons, separators, paddings etc
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, 0, {
virt_text_pos = "overlay",
local conceal_start = string.match(content.line, "^[#]+(%s*)");
local line_length = vim.fn.strchars(content.line);

-- Heading rules
-- 1. Must start at the first column
-- 2. Must have 1 space between the marker and the title
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, content.col_start, {
virt_text_pos = "inline",
virt_text = {
{ string.rep(conf.shift_char or " ", shift * (content.level - 1)), conf.shift_hl },

{ conf.corner_left or "", set_hl(conf.corner_left_hl) or set_hl(conf.hl) },
{ conf.padding_left or "", set_hl(conf.padding_left_hl) or set_hl(conf.hl) },
{ conf.icon or "", set_hl(conf.icon_hl) or set_hl(conf.hl) },
{ content.title or "", set_hl(conf.text_hl) or set_hl(conf.hl) },
{ conf.padding_right or "", set_hl(conf.padding_right_hl) or set_hl(conf.hl) },
{ conf.corner_right or "", set_hl(conf.corner_right_hl) or set_hl(conf.hl) },
{ conf.icon or "", set_hl(conf.icon_hl) or set_hl(conf.hl) }
},

sign_text = conf.sign, sign_hl_group = set_hl(conf.sign_hl) or set_hl(conf.hl),

sign_text = conf.sign, sign_hl_group = set_hl(conf.sign_hl),
hl_mode = "combine",
})

-- Add extra spaces to match the virtual text
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, 0, {
end_col = content.level + vim.fn.strchars(conceal_start),
conceal = ""
});

vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, line_length, {
virt_text_pos = "inline",
virt_text = { { string.rep(" ", add_spaces) } },
virt_text = {
{ conf.padding_right or "", set_hl(conf.padding_right_hl) or set_hl(conf.hl) },
{ conf.corner_right or "", set_hl(conf.corner_right_hl) or set_hl(conf.hl) }
},

end_col = content.title_pos[2] or content.col_end,
conceal = ""
hl_mode = "combine"
});

vim.api.nvim_buf_add_highlight(buffer, renderer.namespace, set_hl(conf.hl), content.row_start, 0, line_length);
elseif conf.style == "icon" then
-- FIX: Make headings editable
local add_spaces = vim.fn.strchars(table.concat({
string.rep(conf.shift_char or " ", shift * (content.level - 1)),
conf.icon or ""
}));

-- Adds simple icons with paddings
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, 0, {
virt_text_pos = "overlay",
local conceal_start = string.match(content.line, "^[#]+(%s*)");

-- Heading rules
-- 1. Must start at the first column
-- 2. Must have 1 space between the marker and the title
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, content.col_start, {
virt_text_pos = "inline",
virt_text = {
{ string.rep(conf.shift_char or " ", shift * (content.level - 1)), set_hl(conf.shift_hl) },

{ conf.icon or "", set_hl(conf.icon_hl) or set_hl(conf.hl) },
{ content.title or "", set_hl(conf.text_hl) or set_hl(conf.hl) },
},

sign_text = conf.sign, sign_hl_group = set_hl(conf.sign_hl),
line_hl_group = set_hl(conf.hl),
hl_mode = "combine",
})

-- Add extra spaces to match the virtual text
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, 0, {
virt_text_pos = "inline",
virt_text = { { string.rep(" ", add_spaces) } },

end_col = content.title_pos[2] or content.col_end,
end_col = content.level + vim.fn.strchars(conceal_start),
conceal = ""
});

vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, 0, {
line_hl_group = set_hl(conf.hl),
sign_text = conf.sign, sign_hl_group = set_hl(conf.sign_hl),
});
end
end

Expand Down Expand Up @@ -1437,8 +1424,8 @@ renderer.render_html_inline = function (buffer, content, user_config)

local html_conf = user_config.tags.default or {};

if user_config.tags.config[content.tag] then
html_conf = user_config.tags.config[content.tag];
if user_config.tags.config[string.lower(content.tag)] then
html_conf = user_config.tags.config[string.lower(content.tag)];
end

if html_conf.conceal ~= false then
Expand Down

0 comments on commit 41d57ab

Please sign in to comment.