UNPKG

shahnevis-core

Version:

**Shahnevis Core** is a lightweight and flexible library for building custom code editors. It provides essential features like syntax highlighting, a minimap, multi-cursor support, line numbering, and plugin management. This library is framework-agnostic,

165 lines (147 loc) 8.24 kB
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* This file is part of Shahnevis Core. Copyright (C) 2024 shahrooz saneidarani (github.com/shahroozD) Shahnevis Core is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Shahnevis Core is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ import { handleCopyOrCut, handlePaste } from "../utils/handleClipboard.js"; import { handleMoveLine } from "../utils/handleLine.js"; import { updateIndentationGuides } from "../utils/lineNumbers.js"; import { extractDefinedVarsAndObjects, handleSuggestions } from "../utils/suggestions.js"; // import { handleMultiCursor } from "../utils/multiCursors.js"; import { updateSyntaxHighlighting } from "./highlighting"; import { createHistoryManager } from "../utils/historyManager.js"; import { handleCodeChange } from "../utils/codeChange.js"; import { createFoldingManager } from "../utils/foldingManager.js"; import { updateMinimapContent } from "./minimap.js"; import { globalState } from "../utils/global.js"; var tabSpaces = ' '; // Number of spaces per tab (use '\t' for an actual tab character) // Function to handle normal Tab (Indent) function handleIndentation(editor, start, end) { editor.setRangeText(tabSpaces, start, start, 'end'); editor.selectionStart = editor.selectionEnd = start + tabSpaces.length; } // Function to handle Shift+Tab (Outdent) function handleOutdentation(editor, start, end) { var lines = editor.value.split('\n'); var cursorLine = lines.findIndex(function (line) { return editor.value.indexOf(line) <= start && editor.value.indexOf(line) + line.length >= end; }); if (lines[cursorLine].startsWith(tabSpaces)) { lines[cursorLine] = lines[cursorLine].replace(tabSpaces, ''); editor.value = lines.join('\n'); editor.selectionStart = editor.selectionEnd = start - tabSpaces.length; } } // Function to handle Tab and Shift+Tab function handleTabs(event, editor) { var start = editor.selectionStart; var end = editor.selectionEnd; if (event.key === 'Tab') { event.preventDefault(); if (event.shiftKey) { handleOutdentation(editor, start, end); } else { handleIndentation(editor, start, end); } // updateLineNumbers(); // const highlight = null; // updateSyntaxHighlighting(editor, highlight); } } // Function to handle auto-closing characters and wrapping selected text function autoCloseOrWrap(event, editor, highlighter) { var _char = event.key; var start = editor.selectionStart; var end = editor.selectionEnd; var selectedText = editor.value.substring(start, end); var closingChar = { '(': ')', '{': '}', '"': '"', "'": "'", "`": "`" }; if (_char === '(' || _char === '{' || _char === '"' || _char === "'" || _char === "`") { event.preventDefault(); if (selectedText.length > 0) { var wrappedText = _char + selectedText + closingChar[_char]; editor.setRangeText(wrappedText, start, end, 'end'); } else { var insertText = _char + closingChar[_char]; editor.setRangeText(insertText, start, start, 'end'); editor.selectionStart = editor.selectionEnd = start + 1; } } else if (_char === ')' || _char === '}' || _char === '"' || _char === "'" || _char === "`") { var cursorPosition = editor.selectionStart; if (editor.value[cursorPosition] === _char) { event.preventDefault(); editor.setSelectionRange(cursorPosition + 1, cursorPosition + 1); } } // updateLineNumbers(); updateSyntaxHighlighting(editor, highlighter); } // Main feature handler export default function featureHandler(editor, minimapContent, suggestionDropdown, lineNumbers, foldingUtils, languageSelector, highlighter, setEditorState, editorState) { // Create a fresh history manager for this editor instance var foldingManager = createFoldingManager(editorState); var history = createHistoryManager(setEditorState, editorState, 150); foldingManager.onChange(function (newState) { setEditorState(_objectSpread({}, newState)); }); // init // Initialize the Features if (editorState.undoStack.length == 0) history.saveState(editor, foldingManager); // Save initial state updateSyntaxHighlighting(editor, highlighter, languageSelector); updateIndentationGuides(editor, minimapContent, lineNumbers, foldingManager); updateMinimapContent(minimapContent, highlighter); var onKeydown = function onKeydown(event) { handleTabs(event, editor); handleMoveLine(event, editor, foldingManager); //= handleCopyOrCut(event, editor, foldingUtils) // handleMultiCursor(event, editor); // Uncomment if needed autoCloseOrWrap(event, editor, highlighter); handleCodeChange(event, editor, minimapContent, lineNumbers, foldingManager); // updateIndentationGuides(editor, minimapContent, lineNumbers, foldingManager); // Ensure indentation guides are updated properly // stack manager history.handleUndoRedo(event, editor, foldingManager); }; var onInput = function onInput(event) { handleSuggestions(editor, suggestionDropdown, languageSelector, highlighter); extractDefinedVarsAndObjects(editor.value); // updateIndentationGuides(editor, minimapContent, lineNumbers, foldingManager); // Ensure indentation guides are updated properly // updateSyntaxHighlighting(editor, languageSelector); updateSyntaxHighlighting(editor, highlighter, languageSelector); updateIndentationGuides(editor, minimapContent, lineNumbers, foldingManager); updateMinimapContent(minimapContent, highlighter); history.debounceSaveState(editor, foldingManager); }; var onPaste = function onPaste(event) { handlePaste(event, editor, minimapContent, lineNumbers, foldingManager); }; // Add event listeners (only once) editor.addEventListener('keydown', onKeydown); editor.addEventListener('input', onInput); editor.addEventListener("paste", onPaste); // Cleanup function to remove event listeners if needed (for React or other environments) return function () { editor.removeEventListener('keydown', onKeydown); editor.removeEventListener('input', onInput); editor.removeEventListener("paste", onPaste); }; }