Skip to content

Commit

Permalink
Merge pull request #202 from roycrippen4/fix-#199
Browse files Browse the repository at this point in the history
feat: support react fragments
  • Loading branch information
PriceHiller authored Jul 14, 2024
2 parents 323a3e1 + 33a38a5 commit 987cfa5
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 19 deletions.
3 changes: 3 additions & 0 deletions lua/nvim-ts-autotag/internal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
59 changes: 59 additions & 0 deletions lua/nvim-ts-autotag/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
23 changes: 23 additions & 0 deletions sample/index.js
Original file line number Diff line number Diff line change
@@ -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
56 changes: 37 additions & 19 deletions tests/specs/closetag_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,34 @@ local data = {
after = [[{(card.data >| 0) && <div></div>}]],
},
{
name = "15 vue auto close tag",
name = "15 typescriptreact nested indentifer ",
filepath = "./sample/index.tsx",
filetype = "typescriptreact",
linenr = 12,
key = [[>]],
before = [[<Opt.Input| ]],
after = [[<Opt.Input>|</Opt.Input> ]],
},
{
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,
Expand All @@ -139,7 +166,7 @@ local data = {
after = [[<Img>|</Img>]],
},
{
name = "16 vue not close on script",
name = "19 vue not close on script",
filepath = "./sample/index.vue",
filetype = "vue",
linenr = 12,
Expand All @@ -148,16 +175,7 @@ local data = {
after = [[const data:Array<string>| ]],
},
{
name = "17 typescriptreact nested indentifer ",
filepath = "./sample/index.tsx",
filetype = "typescriptreact",
linenr = 12,
key = [[>]],
before = [[<Opt.Input| ]],
after = [[<Opt.Input>|</Opt.Input> ]],
},
{
name = "18 php div ",
name = "20 php div ",
filepath = "./sample/index.php",
filetype = "php",
linenr = 25,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down

0 comments on commit 987cfa5

Please sign in to comment.