Skip to content
This repository was archived by the owner on May 23, 2025. It is now read-only.

Commit fbb916c

Browse files
author
Cristhian Melo
committed
feat(*): Initial commit
0 parents  commit fbb916c

File tree

3 files changed

+201
-0
lines changed

3 files changed

+201
-0
lines changed

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Cristhian Fernando Melo Montilla
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+

README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# 😸 template-string.nvim
2+
3+
`template-string.nvim` is a simple Neovim plugin for handling template strings in JavaScript and TypeScript files. It provides functionality to wrap template literals with `{``}` when inside JSX/TSX components and revert them back to their original form when necessary.
4+
5+
## Features
6+
7+
- Wrap template literals with `{``}` when inside JSX/TSX components.
8+
- Revert template literals to their original form when necessary.
9+
- Configurable options to enable/disable wrapping with `{``}`.
10+
11+
## Supported Languages
12+
13+
- JavaScript
14+
- TypeScript
15+
- JSX
16+
- TSX
17+
18+
## Installation
19+
20+
Install using your favorite package manager for Neovim. For example, using [lazy.nvim](https://github.com/folke/lazy.nvim):
21+
22+
```lua
23+
{
24+
"rxtsel/template-string.nvim",
25+
event = "BufReadPost",
26+
dependencies = {
27+
"nvim-lua/plenary.nvim",
28+
},
29+
config = function()
30+
require("template-string").setup()
31+
end,
32+
}
33+
```
34+
35+
## Usage
36+
37+
Once installed, the plugin automatically wraps template literals with **``** when editing JavaScript or TypeScript files. To use template literals, simply enclose your JavaScript or TypeScript expressions in `${}`. For example:
38+
39+
```javascript
40+
// Javascript/TypeScript
41+
const name = "World";
42+
const greeting = `Hello, ${name}!`;
43+
console.log(greeting);
44+
```
45+
46+
On JSX/TSX components, the plugin will wrap template literals with `{``}`. For example:
47+
48+
```jsx
49+
const props = {
50+
name: "World",
51+
};
52+
53+
<Test greeting={`Hello, ${props.name}!`} />;
54+
```
55+
56+
## Configuration
57+
58+
The `setup` function accepts an optional configuration object with the following options:
59+
60+
- **jsx_brackets** `boolean | nil`: Enable/disable wrapping template literals with `{``}` inside JSX/TSX components. Defaults to `true` if not provided.
61+
62+
```lua
63+
-- Default configuration
64+
require('template-string').setup({
65+
jsx_brackets = true, -- Wrap template literals with {``} inside JSX/TSX components
66+
})
67+
```
68+
69+
## License
70+
71+
This plugin is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

lua/template-string.lua

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---@class TemplateStringConfig
2+
---@field jsx_brackets boolean | nil
3+
4+
local M = {}
5+
6+
local allowed_filetypes = {
7+
javascript = true,
8+
typescript = true,
9+
javascriptreact = true,
10+
typescriptreact = true,
11+
}
12+
13+
local function is_allowed_filetype()
14+
local filetype = vim.bo.filetype
15+
return allowed_filetypes[filetype] or false
16+
end
17+
18+
-- Function to wrap with {``} if inside a JSX/TSX component
19+
local function wrap_with_brackets_if_necessary(content)
20+
if content:find("%${") then
21+
return "={`" .. content .. "`}"
22+
else
23+
return '="' .. content .. '"'
24+
end
25+
end
26+
27+
-- Function to replace quotes in the current line
28+
local function replace_quotes_in_line()
29+
if not is_allowed_filetype() then
30+
return
31+
end
32+
33+
local row = vim.api.nvim_win_get_cursor(0)[1]
34+
local line = vim.api.nvim_buf_get_lines(0, row - 1, row, false)[1]
35+
36+
if not line then
37+
return
38+
end
39+
40+
local new_line = line
41+
42+
-- Replace quotes with backticks when ${ is found
43+
new_line = new_line:gsub("(['\"])(.-)%${(.-)}(.-)%1", function(quote, before, inside, after)
44+
return "`" .. before .. "${" .. inside .. "}" .. after .. "`"
45+
end)
46+
47+
if M.jsx_brackets then
48+
-- Wrap with {``} if inside a JSX/TSX component
49+
new_line = new_line:gsub("=%s*`([^`]*)`", wrap_with_brackets_if_necessary)
50+
51+
-- Revert backticks to original quotes if ${ is not found
52+
new_line = new_line:gsub("={[`{]+([^`]*)[`}]+}", function(content)
53+
if not content:find("%${") then
54+
-- Determine the original type of quotes, double or single
55+
local original_quote = line:match("=[\"']") and '"' or line:match("=['\"]") and "'" or '"'
56+
return "=" .. original_quote .. content .. original_quote
57+
end
58+
return "={" .. "`" .. content .. "`" .. "}"
59+
end)
60+
end
61+
62+
-- Also handle reverting solitary backticks on normal lines
63+
new_line = new_line:gsub("`([^`]*)`", function(content)
64+
if not content:find("%${") then
65+
-- Determine the original type of quotes, double or single
66+
local original_quote = line:match("[\"']") or '"'
67+
return original_quote .. content .. original_quote
68+
end
69+
return "`" .. content .. "`"
70+
end)
71+
72+
if new_line ~= line then
73+
vim.api.nvim_buf_set_lines(0, row - 1, row, false, { new_line })
74+
end
75+
end
76+
77+
-- Function to execute update with debounce
78+
local function debounce(fn, ms)
79+
local timer = vim.loop.new_timer()
80+
return function(...)
81+
timer:stop()
82+
local argv = { ... }
83+
timer:start(
84+
ms,
85+
0,
86+
vim.schedule_wrap(function()
87+
fn(unpack(argv))
88+
end)
89+
)
90+
end
91+
end
92+
93+
--- Configures the plugin behavior.
94+
---@param opts TemplateStringConfig | nil Optional plugin configuration.
95+
function M.setup(opts)
96+
opts = opts or {}
97+
-- Enable brackets for JSX/TSX
98+
local jsx_brackets = opts.jsx_brackets == nil or opts.jsx_brackets
99+
M.jsx_brackets = jsx_brackets
100+
101+
-- Enable debounce
102+
local debounced_replace = debounce(replace_quotes_in_line, 100)
103+
vim.api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, {
104+
callback = debounced_replace,
105+
})
106+
end
107+
108+
return M

0 commit comments

Comments
 (0)