From e5ace2360c4db3c9a22d9fa44dfdcd6d6c07d1d9 Mon Sep 17 00:00:00 2001 From: "Kelve T. Henrique" Date: Wed, 20 May 2026 17:24:56 +0200 Subject: [PATCH 1/2] feat: add AsciiDoc integration for diagram rendering --- README.md | 45 +++++++++++- lua/diagram/hover.lua | 6 ++ lua/diagram/init.lua | 1 + lua/diagram/integrations/asciidoc.lua | 100 ++++++++++++++++++++++++++ lua/diagram/integrations/init.lua | 2 + 5 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 lua/diagram/integrations/asciidoc.lua diff --git a/README.md b/README.md index 6f435c0..768c569 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Integrations read buffers, extract diagram code, and dispatch work to the render | Integration | Supported renderers | | ----------- | ------------------------------------------- | +| `asciidoc` | `mermaid`, `plantuml`, `d2`, `gnuplot` | | `markdown` | `mermaid`, `plantuml`, `d2`, `gnuplot` | | `neorg` | `mermaid`, `plantuml`, `d2`, `gnuplot` | @@ -73,6 +74,45 @@ With **lazy.nvim**: }, ``` +If you want AsciiDoc support, install the parser from +[`cathaysia/tree-sitter-asciidoc`](https://github.com/cathaysia/tree-sitter-asciidoc): + +```lua +local parsers = require("nvim-treesitter.parsers") + +parsers.asciidoc = { + install_info = { + url = "https://github.com/cathaysia/tree-sitter-asciidoc", + files = { "tree-sitter-asciidoc/src/parser.c", "tree-sitter-asciidoc/src/scanner.c" }, + branch = "master", + location = "tree-sitter-asciidoc", + queries = "queries/asciidoc", + requires = { "asciidoc_inline" }, + }, +} + +parsers.asciidoc_inline = { + install_info = { + url = "https://github.com/cathaysia/tree-sitter-asciidoc", + files = { "tree-sitter-asciidoc_inline/src/parser.c" }, + branch = "master", + location = "tree-sitter-asciidoc_inline", + queries = "queries/asciidoc_inline", + }, +} + +``` + +Then AsciiDoc diagram blocks like this are supported: + +```adoc +[source,mermaid] +---- +graph TD +A-->B +---- +``` + ### Custom CLI Arguments You can pass custom command-line arguments to any renderer using the `cli_args` option. @@ -106,6 +146,7 @@ To use the plugin, you need to set up the integrations and renderers in your Neo ```lua require("diagram").setup({ integrations = { + require("diagram.integrations.asciidoc"), require("diagram.integrations.markdown"), require("diagram.integrations.neorg"), }, @@ -167,7 +208,7 @@ You can add a keymap to view diagrams in a dedicated tab. Place your cursor insi require("diagram").show_diagram_hover() end, mode = "n", - ft = { "markdown", "norg" }, -- Only in these filetypes + ft = { "asciidoc", "adoc", "markdown", "norg" }, -- Only in these filetypes desc = "Show diagram in new tab", }, }, @@ -176,7 +217,7 @@ You can add a keymap to view diagrams in a dedicated tab. Place your cursor insi **Key Configuration Details:** - `"K"` - The key to press (can be changed to any key like `"d"`, `"gd"`, etc.) -- `ft = { "markdown", "norg" }` - Only activates in markdown and neorg files +- `ft = { "asciidoc", "adoc", "markdown", "norg" }` - Only activates in supported document filetypes - The function calls `require("diagram").show_diagram_hover()` to display the diagram **Features:** diff --git a/lua/diagram/hover.lua b/lua/diagram/hover.lua index bc08410..6925936 100644 --- a/lua/diagram/hover.lua +++ b/lua/diagram/hover.lua @@ -20,6 +20,12 @@ local get_extended_range = function(bufnr, diagram) local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) local start_row = diagram.range.start_row local end_row = diagram.range.end_row + local filetype = vim.bo[bufnr].filetype + + if (filetype == "asciidoc" or filetype == "adoc") and start_row > 0 then + local previous_line = lines[start_row] + if previous_line and previous_line:match("^%s*%[.*%]%s*$") then start_row = start_row - 1 end + end -- Look backwards from start_row to find the opening ``` for i = start_row, 0, -1 do diff --git a/lua/diagram/init.lua b/lua/diagram/init.lua index de5e8f3..c75a0f2 100644 --- a/lua/diagram/init.lua +++ b/lua/diagram/init.lua @@ -37,6 +37,7 @@ local state = { }, }, integrations = { + integrations.asciidoc, integrations.markdown, integrations.neorg, }, diff --git a/lua/diagram/integrations/asciidoc.lua b/lua/diagram/integrations/asciidoc.lua new file mode 100644 index 0000000..1bb3e54 --- /dev/null +++ b/lua/diagram/integrations/asciidoc.lua @@ -0,0 +1,100 @@ +local renderers = require("diagram/renderers") +local ts_query = require("vim.treesitter.query") + +---@type vim.treesitter.Query +local query = nil + +local supported_renderers = { + mermaid = true, + plantuml = true, + d2 = true, + gnuplot = true, +} + +local function get_renderer_id(value) + if not value then return nil end + + for token in value:gmatch("[^,%s]+") do + if supported_renderers[token] then return token end + end + + return nil +end + +---@class Integration +local M = { + id = "asciidoc", + filetypes = { "asciidoc", "adoc" }, + renderers = { + renderers.mermaid, + renderers.plantuml, + renderers.d2, + renderers.gnuplot, + }, +} + +M.query_buffer_diagrams = function(bufnr) + if not query then + query = ts_query.parse( + "asciidoc", + [[ + (section_block + (element_attr + (element_attr_marker) + (attr_value) @attr + (element_attr_marker)) + (listing_block + (listing_block_start_marker) @start + (listing_block_body) @code + (listing_block_end_marker) @end)) @diagram + + (section_block + (element_attr + (element_attr_marker) + (attr_value) @attr + (element_attr_marker)) + (literal_block + (literal_block_marker) @start + (literal_block_body) @code + (literal_block_marker) @end)) @diagram + ]] + ) + end + + local buf = bufnr or vim.api.nvim_get_current_buf() + local parser = vim.treesitter.get_parser(buf, "asciidoc") + local root = parser:parse(true)[1]:root() + + ---@type Diagram[] + local diagrams = {} + + for _, match in query:iter_matches(root, buf) do + local attr = match[1] and match[1][1] + local start_marker = match[2] and match[2][1] + local code = match[3] and match[3][1] + local end_marker = match[4] and match[4][1] + + if attr and start_marker and code and end_marker then + local renderer_id = get_renderer_id(vim.treesitter.get_node_text(attr, buf)) + if renderer_id then + local start_row, start_col, _, _ = start_marker:range() + local _, _, end_row, end_col = end_marker:range() + table.insert(diagrams, { + bufnr = buf, + renderer_id = renderer_id, + source = vim.treesitter.get_node_text(code, buf), + range = { + start_row = start_row, + start_col = start_col, + end_row = end_row, + end_col = end_col, + }, + }) + end + end + end + + return diagrams +end + +return M diff --git a/lua/diagram/integrations/init.lua b/lua/diagram/integrations/init.lua index 7a4ee2e..6e4cb52 100644 --- a/lua/diagram/integrations/init.lua +++ b/lua/diagram/integrations/init.lua @@ -1,7 +1,9 @@ +local asciidoc = require("diagram/integrations/asciidoc") local markdown = require("diagram/integrations/markdown") local neorg = require("diagram/integrations/neorg") return { + asciidoc = asciidoc, markdown = markdown, neorg = neorg, } From 5d04dec60569c025c831d6fde50639bfc507ac13 Mon Sep 17 00:00:00 2001 From: "Kelve T. Henrique" Date: Wed, 20 May 2026 18:57:05 +0200 Subject: [PATCH 2/2] Avoid error when asciidoc ts is not installed --- lua/diagram/integrations/asciidoc.lua | 52 ++++++++++++++------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/lua/diagram/integrations/asciidoc.lua b/lua/diagram/integrations/asciidoc.lua index 1bb3e54..4b6dae2 100644 --- a/lua/diagram/integrations/asciidoc.lua +++ b/lua/diagram/integrations/asciidoc.lua @@ -35,34 +35,38 @@ local M = { M.query_buffer_diagrams = function(bufnr) if not query then - query = ts_query.parse( - "asciidoc", - [[ - (section_block - (element_attr - (element_attr_marker) - (attr_value) @attr - (element_attr_marker)) - (listing_block - (listing_block_start_marker) @start - (listing_block_body) @code - (listing_block_end_marker) @end)) @diagram + local ok = pcall(function() + query = ts_query.parse( + "asciidoc", + [[ + (section_block + (element_attr + (element_attr_marker) + (attr_value) @attr + (element_attr_marker)) + (listing_block + (listing_block_start_marker) @start + (listing_block_body) @code + (listing_block_end_marker) @end)) @diagram - (section_block - (element_attr - (element_attr_marker) - (attr_value) @attr - (element_attr_marker)) - (literal_block - (literal_block_marker) @start - (literal_block_body) @code - (literal_block_marker) @end)) @diagram - ]] - ) + (section_block + (element_attr + (element_attr_marker) + (attr_value) @attr + (element_attr_marker)) + (literal_block + (literal_block_marker) @start + (literal_block_body) @code + (literal_block_marker) @end)) @diagram + ]] + ) + end) + if not ok then return {} end end local buf = bufnr or vim.api.nvim_get_current_buf() - local parser = vim.treesitter.get_parser(buf, "asciidoc") + local ok, parser = pcall(vim.treesitter.get_parser, buf, "asciidoc") + if not ok then return {} end local root = parser:parse(true)[1]:root() ---@type Diagram[]