Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(#199): Auto-tag react fragments #202

Merged
merged 6 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
62 changes: 62 additions & 0 deletions lua/nvim-ts-autotag/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,68 @@ 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

roycrippen4 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading