Skip to content

Commit

Permalink
fix(parser): Added support for labels in links
Browse files Browse the repository at this point in the history
Fixes #78.
  • Loading branch information
OXY2DEV committed Aug 6, 2024
1 parent 7e0ad40 commit 1fc5d90
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 65 deletions.
47 changes: 38 additions & 9 deletions lua/markview/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -447,10 +447,12 @@ parser.md_inline = function (buffer, TStree, from, to)
((shortcut_link) @callout)
([
(image)
(inline_link)
(email_autolink)
] @link)
(full_reference_link)
] @link)
((email_autolink) @email)
((image) @image)
((code_span) @code)
Expand Down Expand Up @@ -508,27 +510,54 @@ parser.md_inline = function (buffer, TStree, from, to)
end
end
elseif capture_name == "link" then
local link_type = capture_node:type();
local link_text = string.match(capture_text, "%[(.-)%]");
local link_address = string.match(capture_text, "%((.-)%)")
local link_text = "";
local link_address;

if capture_node:named_child(0) and capture_node:named_child(0):type() == "link_text" then
link_text = vim.treesitter.get_node_text(capture_node:named_child(0), buffer);
end

if capture_node:named_child(1) and (capture_node:named_child(q):type() == "link_destination" or capture_node:named_child(q):type() == "link_label") then
link_address = vim.treesitter.get_node_text(capture_node:named_child(1), buffer);
end

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

text = link_text,
address = link_address,

row_start = row_start,
row_end = row_end,

col_start = col_start,
col_end = col_end,
})
elseif capture_name == "email" then
table.insert(parser.parsed_content, {
node = capture_node,
type = "email",

text = capture_text,

row_start = row_start,
row_end = row_end,

col_start = col_start,
col_end = col_end,
})
elseif capture_name == "image" then
local link_text = string.match(capture_text, "%[(.-)%]");
local link_address = string.match(capture_text, "%((.-)%)")
local desc = capture_node:named_child(0);
local sibl = capture_node:named_child(1);

local link_text = vim.treesitter.get_node_text(desc, buffer);
local link_address = ""

-- vim.print(sibl == nil)
if sibl then
link_address = vim.treesitter.get_node_text(sibl, buffer);
end

table.insert(parser.parsed_content, {
node = capture_node,
Expand Down
239 changes: 183 additions & 56 deletions lua/markview/renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -96,52 +96,107 @@ local display_width = function (text, config)
end

local lnk_conf = config.links ~= nil and config.links.hyperlinks or nil;
---@type markview.render_config.links.link?
local img_conf = config.links ~= nil and config.links.images or nil;
local email_conf = config.links ~= nil and config.links.emails or nil;

for img_identifier, link, address in final_string:gmatch("(!?)%[([^%]]+)%]%(([^%)]+)%)") do
if img_identifier ~= "" then
d_width = d_width - vim.fn.strchars("![" .. "](" .. address .. ")");

if img_conf ~= nil and img_conf.enable ~= false then
d_width = d_width + vim.fn.strchars(table.concat({
img_conf.corner_left or "",
img_conf.padding_left or "",
img_conf.icon or "",
img_conf.padding_right or "",
img_conf.corner_right or ""
}));

final_string = final_string:gsub("!%[" .. link .. "%]%(" .. address .. "%)", table.concat({
img_conf.corner_left or "",
img_conf.padding_left or "",
img_conf.icon or "",
link,
img_conf.padding_right or "",
img_conf.corner_right or ""
}));
end
else
d_width = d_width - vim.fn.strchars("[" .. "](" .. address .. ")");

if lnk_conf ~= nil and lnk_conf.enable ~= false then
d_width = d_width + vim.fn.strchars(table.concat({
lnk_conf.corner_left or "",
lnk_conf.padding_left or "",
lnk_conf.icon or "",
lnk_conf.padding_right or "",
lnk_conf.corner_right or ""
}));

final_string = final_string:gsub("%[" .. link .. "%]%(" .. address .. "%)", table.concat({
lnk_conf.corner_left or "",
lnk_conf.padding_left or "",
lnk_conf.icon or "",
link,
lnk_conf.padding_right or "",
lnk_conf.corner_right or ""
}));
end
--- Image link(normal)
for link, address in final_string:gmatch("!%[([^%]]+)%]%(([^%)]+)%)") do
if not img_conf then
break;
end

d_width = d_width - vim.fn.strchars("![" .. "](" .. address .. ")");

d_width = d_width + vim.fn.strchars(table.concat({
img_conf.corner_left or "",
img_conf.padding_left or "",
img_conf.icon or "",
img_conf.padding_right or "",
img_conf.corner_right or ""
}));

final_string = final_string:gsub("!%[" .. link .. "%]%(" .. address .. "%)", table.concat({
img_conf.corner_left or "",
img_conf.padding_left or "",
img_conf.icon or "",
link,
img_conf.padding_right or "",
img_conf.corner_right or ""
}));
end

-- Image link: labels
for link, address in final_string:gmatch("!%[([^%]]+)%]%[([^%)]+)%]") do
if not img_conf then
break;
end

d_width = d_width - vim.fn.strchars("![" .. "][" .. address .. "]");

d_width = d_width + vim.fn.strchars(table.concat({
img_conf.corner_left or "",
img_conf.padding_left or "",
img_conf.icon or "",
img_conf.padding_right or "",
img_conf.corner_right or ""
}));

final_string = final_string:gsub("!%[" .. link .. "%]%[" .. address .. "%]", table.concat({
img_conf.corner_left or "",
img_conf.padding_left or "",
img_conf.icon or "",
link,
img_conf.padding_right or "",
img_conf.corner_right or ""
}));
end

-- Hyperlinks: normal
for link, address in final_string:gmatch("%[([^%]]+)%]%(([^%)]+)%)") do
d_width = d_width - vim.fn.strchars("[" .. "](" .. address .. ")");

if lnk_conf ~= nil and lnk_conf.enable ~= false then
d_width = d_width + vim.fn.strchars(table.concat({
lnk_conf.corner_left or "",
lnk_conf.padding_left or "",
lnk_conf.icon or "",
lnk_conf.padding_right or "",
lnk_conf.corner_right or ""
}));

final_string = final_string:gsub("%[" .. link .. "%]%(" .. address .. "%)", table.concat({
lnk_conf.corner_left or "",
lnk_conf.padding_left or "",
lnk_conf.icon or "",
link,
lnk_conf.padding_right or "",
lnk_conf.corner_right or ""
}));
end
end

-- Hyperlink: full_reference_link
for link, address in final_string:gmatch("[^!]%[([^%]]+)%]%[([^%]]+)%]") do
d_width = d_width - vim.fn.strchars("[" .. "][" .. address .. "]");

if lnk_conf ~= nil and lnk_conf.enable ~= false then
d_width = d_width + vim.fn.strchars(table.concat({
lnk_conf.corner_left or "",
lnk_conf.padding_left or "",
lnk_conf.icon or "",
lnk_conf.padding_right or "",
lnk_conf.corner_right or ""
}));

final_string = final_string:gsub("%[" .. link .. "%]%[" .. address .. "%]", table.concat({
lnk_conf.corner_left or "",
lnk_conf.padding_left or "",
lnk_conf.icon or "",
link,
lnk_conf.padding_right or "",
lnk_conf.corner_right or ""
}));
end
end

Expand Down Expand Up @@ -1239,41 +1294,109 @@ renderer.render_links = function (buffer, content, config_table)
return;
end

if content.link_type == "inline_link" then
lnk_conf = config_table.hyperlinks;
elseif content.link_type == "image" then
lnk_conf = config_table.images;
elseif content.link_type == "email_autolink" then
lnk_conf = config_table.emails;
end
lnk_conf = config_table.hyperlinks;

-- Do not render links with no config
if not lnk_conf then
return;
end

vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, content.link_type == "email_autolink" and content.col_start or content.col_start + 1, {
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, content.col_start + 1, {
virt_text_pos = "inline",
virt_text = {
{ lnk_conf.corner_left or "", set_hl(lnk_conf.corner_left_hl) or set_hl(lnk_conf.hl) },
{ lnk_conf.padding_left or "", set_hl(lnk_conf.padding_left_hl) or set_hl(lnk_conf.hl) },
{ lnk_conf.icon or "", set_hl(lnk_conf.icon_hl) or set_hl(lnk_conf.hl) },
},

end_col = content.link_type == "email_autolink" and content.col_start + 1 or content.col_start,
end_col = content.col_start,
conceal = ""
});

vim.api.nvim_buf_add_highlight(buffer, renderer.namespace, set_hl(lnk_conf.hl) or "", content.row_start, content.col_start, content.col_end);

vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_end, content.link_type == "email_autolink" and content.col_end - 1 or content.col_end, {
vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_end, content.col_end, {
virt_text_pos = "inline",
virt_text = {
{ lnk_conf.padding_right or "", set_hl(lnk_conf.padding_right_hl) or set_hl(lnk_conf.hl) },
{ lnk_conf.corner_right or "", set_hl(lnk_conf.corner_right_hl) or set_hl(lnk_conf.hl) },
},

end_col = content.link_type == "email_autolink" and content.col_end or content.col_start,
end_col = content.col_start,
conceal = ""
});
end

renderer.render_email_links = function (buffer, content, config_table)
if not config_table or config_table.enable == false then
return;
end

local email_conf = config_table.emails;

if not email_conf then
return;
end

vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, content.col_start, {
virt_text_pos = "inline",
virt_text = {
{ email_conf.corner_left or "", set_hl(email_conf.corner_left_hl) or set_hl(email_conf.hl) },
{ email_conf.padding_left or "", set_hl(email_conf.padding_left_hl) or set_hl(email_conf.hl) },
{ email_conf.icon or "", set_hl(email_conf.icon_hl) or set_hl(email_conf.hl) },
},

end_col = content.col_start + 1,
conceal = ""
});

vim.api.nvim_buf_add_highlight(buffer, renderer.namespace, set_hl(email_conf.hl) or "", content.row_start, content.col_start, content.col_end);

vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_end, content.col_end - 1, {
virt_text_pos = "inline",
virt_text = {
{ email_conf.padding_right or "", set_hl(email_conf.padding_right_hl) or set_hl(email_conf.hl) },
{ email_conf.corner_right or "", set_hl(email_conf.corner_right_hl) or set_hl(email_conf.hl) },
},

end_col = content.col_end,
conceal = ""
});
end

renderer.render_img_links = function (buffer, content, config_table)
if not config_table or config_table.enable == false then
return;
end

local img_conf = config_table.images;

if not img_conf then
return;
end

vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_start, content.col_start + 1, {
virt_text_pos = "inline",
virt_text = {
{ img_conf.corner_left or "", set_hl(img_conf.corner_left_hl) or set_hl(img_conf.hl) },
{ img_conf.padding_left or "", set_hl(img_conf.padding_left_hl) or set_hl(img_conf.hl) },
{ img_conf.icon or "", set_hl(img_conf.icon_hl) or set_hl(img_conf.hl) },
},

end_col = content.col_start,
conceal = ""
});

vim.api.nvim_buf_add_highlight(buffer, renderer.namespace, set_hl(img_conf.hl) or "", content.row_start, content.col_start, content.col_end);

vim.api.nvim_buf_set_extmark(buffer, renderer.namespace, content.row_end, content.col_end - vim.fn.strchars(content.address), {
virt_text_pos = "inline",
virt_text = {
{ img_conf.padding_right or "", set_hl(img_conf.padding_right_hl) or set_hl(img_conf.hl) },
{ img_conf.corner_right or "", set_hl(img_conf.corner_right_hl) or set_hl(img_conf.hl) },
},

end_col = content.col_end,
conceal = ""
});
end
Expand Down Expand Up @@ -1521,8 +1644,10 @@ renderer.render_in_range = function (buffer, partial_contents, config_table)
pcall(renderer.render_horizontal_rules, buffer, content, config_table.horizontal_rules);
elseif type == "link" then
pcall(renderer.render_links, buffer, content, config_table.links);
elseif type == "email" then
pcall(renderer.render_email_links, buffer, content, config_table.links);
elseif type == "image" then
pcall(renderer.render_links, buffer, content, config_table.images);
pcall(renderer.render_img_links, buffer, content, config_table.links);
elseif type == "inline_code" then
pcall(renderer.render_inline_codes, buffer, content, config_table.inline_codes)
elseif type == "list_item" then
Expand Down Expand Up @@ -1581,8 +1706,10 @@ renderer.render = function (buffer, parsed_content, config_table, conceal_start,
pcall(renderer.render_horizontal_rules, buffer, content, config_table.horizontal_rules);
elseif type == "link" then
pcall(renderer.render_links, buffer, content, config_table.links);
elseif type == "email" then
pcall(renderer.render_email_links, buffer, content, config_table.links);
elseif type == "image" then
pcall(renderer.render_links, buffer, content, config_table.images);
pcall(renderer.render_img_links, buffer, content, config_table.links);
elseif type == "inline_code" then
pcall(renderer.render_inline_codes, buffer, content, config_table.inline_codes)
elseif type == "list_item" then
Expand Down

0 comments on commit 1fc5d90

Please sign in to comment.