-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: codemirror extension to automatically insert self closing tag o…
…nce closed e.g. `<Button /` would result in `<Button />`
- Loading branch information
1 parent
66350be
commit 36696d2
Showing
4 changed files
with
60 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { KeyBinding } from "@uiw/react-codemirror"; | ||
import selfClosingTag from "./self-closing-tag"; | ||
|
||
export default [{ key: "/", run: selfClosingTag }] satisfies KeyBinding[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { EditorSelection, EditorView } from "@uiw/react-codemirror"; | ||
import { | ||
getEditorStateInfo, | ||
parseTagFromLineText, | ||
} from "../utils/extensions-utils"; | ||
|
||
function insertSelfClosingTagCommand(view: EditorView): boolean { | ||
const { state, dispatch } = view; | ||
const { cursorPos, lineTextUpToCursor, lineTextAfterCursor } = | ||
getEditorStateInfo(state); | ||
|
||
const tagName = parseTagFromLineText(lineTextUpToCursor); | ||
|
||
if (!tagName) { | ||
return false; | ||
} | ||
|
||
if (!isInsideOpenTag(lineTextUpToCursor)) { | ||
return false; | ||
} | ||
|
||
if (isFollowedByCloseTag(lineTextAfterCursor)) { | ||
return false; | ||
} | ||
|
||
// +2 to move in after the inserted self-closing bracket | ||
const newCursorPos = EditorSelection.cursor(cursorPos + 2); | ||
|
||
// insert self-closing tag syntax ('/>') and adjust the cursor position | ||
dispatch( | ||
state.update({ | ||
changes: { from: cursorPos, insert: "/>" }, | ||
selection: newCursorPos, | ||
}) | ||
); | ||
|
||
return true; | ||
} | ||
|
||
function isInsideOpenTag(lineTextUpToCursor: string): boolean { | ||
// Checks if the cursor is within an open tag (e.g., after "<Button" or "<Button prop"). | ||
return /<\w+[^>]*$/.test(lineTextUpToCursor); | ||
} | ||
|
||
function isFollowedByCloseTag(lineTextAfterCursor: string): boolean { | ||
// Checks if the cursor's position in the document is followed by a closing part of a tag or self-closing syntax. | ||
return ( | ||
/<\/?\w+>/.test(lineTextAfterCursor) || /\/>/.test(lineTextAfterCursor) | ||
); | ||
} | ||
|
||
export default insertSelfClosingTagCommand; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters