Merge pull request #202 from roycrippen4/fix-#199

feat: support react fragments
This commit is contained in:
Price Hiller 2024-07-14 16:39:29 -05:00 committed by GitHub
commit 987cfa5e0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 130 additions and 27 deletions

View File

@ -252,6 +252,9 @@ 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 utils.is_react_file() and utils.is_react_fragment() then
vim.api.nvim_put({ "</>" }, "", true, false)
vim.cmd([[normal! F>]])
end
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

@ -130,25 +130,7 @@ local data = {
after = [[{(card.data >| 0) && <div></div>}]],
},
{
name = "15 vue auto close tag",
filepath = "./sample/index.vue",
filetype = "vue",
linenr = 4,
key = [[>]],
before = [[<Img| ]],
after = [[<Img>|</Img>]],
},
{
name = "16 vue not close on script",
filepath = "./sample/index.vue",
filetype = "vue",
linenr = 12,
key = [[>]],
before = [[const data:Array<string| ]],
after = [[const data:Array<string>| ]],
},
{
name = "17 typescriptreact nested indentifer ",
name = "15 typescriptreact nested indentifer ",
filepath = "./sample/index.tsx",
filetype = "typescriptreact",
linenr = 12,
@ -157,7 +139,43 @@ local data = {
after = [[<Opt.Input>|</Opt.Input> ]],
},
{
name = "18 php div ",
name = "16 typescriptreact autoclose fragment",
filepath = "./sample/index.tsx",
filetype = "typescriptreact",
linenr = 12,
key = [[>]],
before = [[<|<div></div>]],
after = [[<>|</><div></div>]],
},
{
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,
key = [[>]],
before = [[<Img| ]],
after = [[<Img>|</Img>]],
},
{
name = "19 vue not close on script",
filepath = "./sample/index.vue",
filetype = "vue",
linenr = 12,
key = [[>]],
before = [[const data:Array<string| ]],
after = [[const data:Array<string>| ]],
},
{
name = "20 php div ",
filepath = "./sample/index.php",
filetype = "php",
linenr = 25,
@ -175,7 +193,7 @@ local data = {
-- after = [[<div>|</div> ]],
-- },
{
name = "19 lit template div",
name = "21 lit template div",
filepath = "./sample/index.ts",
filetype = "typescript",
linenr = 3,
@ -184,7 +202,7 @@ local data = {
after = [[<div>|</div> ]],
},
{
name = "20 eruby template div",
name = "22 eruby template div",
filepath = "./sample/index.html.erb",
filetype = "eruby",
linenr = 10,
@ -193,7 +211,7 @@ local data = {
after = [[<div>|</div> ]],
},
{
name = "20 eruby template ruby string",
name = "23 eruby template ruby string",
filepath = "./sample/index.html.erb",
filetype = "eruby",
linenr = 10,
@ -202,7 +220,7 @@ local data = {
after = [[<%= <div>| %> ]],
},
{
name = "21 templ close tag",
name = "24 templ close tag",
filepath = "./sample/index.templ",
filetype = "templ",
linenr = 10,
@ -211,7 +229,7 @@ local data = {
after = [[<div>|</div>]],
},
{
name = "22 templ close tag",
name = "25 templ close tag",
filepath = "./sample/index.templ",
filetype = "templ",
linenr = 10,
@ -220,7 +238,7 @@ local data = {
after = [[<div clas="laa">|</div>]],
},
{
name = "23 templ not close tag on close tag",
name = "26 templ not close tag on close tag",
filepath = "./sample/index.templ",
filetype = "templ",
linenr = 10,
@ -229,7 +247,7 @@ local data = {
after = [[<div>aa</div>|]],
},
{
name = "24 templ not close on input tag",
name = "27 templ not close on input tag",
filepath = "./sample/index.templ",
filetype = "templ",
linenr = 10,