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
JavaScript
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);
};
}