Compare commits

..

4 Commits

Author SHA1 Message Date
roy.crippen4
33a38a53b1 chore: formatting and clarification comment 2024-07-14 17:36:32 -04:00
roycrippen4
2553ac5520
Update lua/nvim-ts-autotag/utils.lua
Co-authored-by: Price Hiller <price@orion-technologies.io>
2024-07-14 17:35:03 -04:00
roy.crippen4
cbe184f12d fix/refactor: Auto-close react fragments
Refactor: Moved detection functions into `utils.lua`
Fix: Improved react detection logic in `.js` files
2024-07-14 16:49:42 -04:00
roy.crippen4
4ab5a1fd9f test(react): Testing for auto-close react fragments in js and tsx files 2024-07-14 16:48:35 -04:00
4 changed files with 104 additions and 49 deletions

View File

@ -242,42 +242,6 @@ local function check_close_tag(close_slash_tag)
return false
end
local function is_react_file()
local ft = vim.bo.ft
-- check filetypes first.
if ft == "javascriptreact" or "typescriptreact" then
return true
elseif ft ~= "javascript" then
return false
end
local ok, buf_parser = pcall(vim.treesitter.get_parser)
if not ok then
return false
end
local tree = buf_parser:parse(true)
if not tree then
return false
end
local root = tree[1]:root()
-- parse the tree for jsx nodes
local query = vim.treesitter.query.parse("javascript", [[
(jsx_element)
(jsx_self_closing_element)
]])
-- iterate over nodes to find jsx nodes
for _, node in query:iter_captures(root, 0, 0, -1) do
if node then
return true
end
end
return false
end
M.close_tag = function()
local ok, buf_parser = pcall(vim.treesitter.get_parser)
if not ok then
@ -288,7 +252,7 @@ M.close_tag = function()
if result == true and tag_name ~= nil then
vim.api.nvim_put({ string.format("</%s>", tag_name) }, "", true, false)
vim.cmd([[normal! F>]])
elseif is_react_file() then
elseif utils.is_react_file() and utils.is_react_fragment() then
vim.api.nvim_put({ "</>" }, "", true, false)
vim.cmd([[normal! F>]])
end

View File

@ -2,6 +2,65 @@ local log = require("nvim-ts-autotag._log")
local get_node_text = vim.treesitter.get_node_text
local M = {}
---@return boolean
function M.is_react_file()
local ft = vim.bo.ft
-- check filetypes first.
if ft == "javascriptreact" or ft == "typescriptreact" then
return true
elseif ft ~= "javascript" then
return false
end
-- If we are in a `javascript` file, then check the content to see if the
-- current file counts as a react file
local ok, buf_parser = pcall(vim.treesitter.get_parser)
if not ok then
return false
end
local tree = buf_parser:parse(true)
if not tree then
return false
end
local root = tree[1]:root()
local queries = { "jsx_element", "jsx_self_closing_element" }
for _, query in ipairs(queries) do
if M.node_exists(root, query) then
return true
end
end
return false
end
---@return boolean
function M.is_react_fragment()
local line = vim.fn.getline(".")
local col = vim.fn.col(".") - 2
local strpart = vim.fn.strpart(line, col)
local char_at_cursor = vim.fn.strcharpart(strpart, 0, 1) ---@type string
return char_at_cursor == "<"
end
---@param node TSNode
---@param query string
---@return boolean
function M.node_exists(node, query)
if node:type() == query then
return true
end
for child in node:iter_children() do
if M.node_exists(child, query) then
return true
end
end
return false
end
M.get_node_text = function(node)
local _, txt = pcall(get_node_text, node, vim.api.nvim_get_current_buf())
return vim.split(txt, "\n") or {}

23
sample/index.js Normal file
View File

@ -0,0 +1,23 @@
import React, { useCallback, useEffect } from 'react'
const SamplePage = () => {
const [state, setstate] = useState(initialState)
return (
<div className="h-full">
</div>
)
}
export default SamplePage

View File

@ -144,11 +144,20 @@ local data = {
filetype = "typescriptreact",
linenr = 12,
key = [[>]],
before = [[<]],
after = [[<>|</>]]
before = [[<|<div></div>]],
after = [[<>|</><div></div>]],
},
{
name = "17 vue auto close tag",
name = "17 javascript autoclose fragment",
filepath = "./sample/index.js",
filetype = "javascript",
linenr = 12,
key = [[>]],
before = [[<|<div></div>]],
after = [[<>|</><div></div>]],
},
{
name = "18 vue auto close tag",
filepath = "./sample/index.vue",
filetype = "vue",
linenr = 4,
@ -157,7 +166,7 @@ local data = {
after = [[<Img>|</Img>]],
},
{
name = "18 vue not close on script",
name = "19 vue not close on script",
filepath = "./sample/index.vue",
filetype = "vue",
linenr = 12,
@ -166,7 +175,7 @@ local data = {
after = [[const data:Array<string>| ]],
},
{
name = "19 php div ",
name = "20 php div ",
filepath = "./sample/index.php",
filetype = "php",
linenr = 25,
@ -184,7 +193,7 @@ local data = {
-- after = [[<div>|</div> ]],
-- },
{
name = "20 lit template div",
name = "21 lit template div",
filepath = "./sample/index.ts",
filetype = "typescript",
linenr = 3,
@ -193,7 +202,7 @@ local data = {
after = [[<div>|</div> ]],
},
{
name = "21 eruby template div",
name = "22 eruby template div",
filepath = "./sample/index.html.erb",
filetype = "eruby",
linenr = 10,
@ -202,7 +211,7 @@ local data = {
after = [[<div>|</div> ]],
},
{
name = "22 eruby template ruby string",
name = "23 eruby template ruby string",
filepath = "./sample/index.html.erb",
filetype = "eruby",
linenr = 10,
@ -211,7 +220,7 @@ local data = {
after = [[<%= <div>| %> ]],
},
{
name = "23 templ close tag",
name = "24 templ close tag",
filepath = "./sample/index.templ",
filetype = "templ",
linenr = 10,
@ -220,7 +229,7 @@ local data = {
after = [[<div>|</div>]],
},
{
name = "24 templ close tag",
name = "25 templ close tag",
filepath = "./sample/index.templ",
filetype = "templ",
linenr = 10,
@ -229,7 +238,7 @@ local data = {
after = [[<div clas="laa">|</div>]],
},
{
name = "25 templ not close tag on close tag",
name = "26 templ not close tag on close tag",
filepath = "./sample/index.templ",
filetype = "templ",
linenr = 10,
@ -238,7 +247,7 @@ local data = {
after = [[<div>aa</div>|]],
},
{
name = "26 templ not close on input tag",
name = "27 templ not close on input tag",
filepath = "./sample/index.templ",
filetype = "templ",
linenr = 10,