diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..56f3b6b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b5a0ba3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,19 @@ +* text=auto eol=lf + +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf + +*.ico binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.webp binary +*.woff binary +*.woff2 binary +*.ttf binary +*.pyd binary +*.dll binary +*.exe binary +*.zip binary diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..f32b851 --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,42 @@ +name: Code Quality + +on: + pull_request: + push: + branches: + - main + - master + +concurrency: + group: quality-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + biome: + name: Biome + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Check pull request changes + if: github.event_name == 'pull_request' + run: npm run check -- --changed --since=${{ github.event.pull_request.base.sha }} --no-errors-on-unmatched --reporter=github + + - name: Check repository + if: github.event_name == 'push' + run: npm run check -- --reporter=github diff --git a/README.md b/README.md index f847698..a568ce2 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,13 @@ git clone https://github.com/cdmtn-dev/codemotion-ide.git cd codemotion-ide # Install dependencies -npm install +npm ci + +# Check formatting and linting +npm run check + +# Apply safe automatic fixes +npm run check:fix # Start the development server npm start @@ -77,6 +83,8 @@ We love contributions! Whether it's bug reports, feature requests, or pull reque #### Contributing Guidelines - Fork the repository - Create your feature branch ```git checkout -b feature/AmazingFeature``` +- Install exact dependencies with ```npm ci``` +- Run ```npm run check:fix``` before committing; ```npm run check``` is required in pull requests and reports legacy lint findings without blocking formatting checks - Commit your changes ```git commit -m 'Add some AmazingFeature'``` - Push to the branch ```git push origin feature/AmazingFeature``` - Open a Pull Request diff --git a/app/auth.js b/app/auth.js index fb6f481..0a0b24b 100644 --- a/app/auth.js +++ b/app/auth.js @@ -1,46 +1,46 @@ -const { ipcMain, app } = require('electron'); -const fs = require('fs'); -const path = require('path'); -const { LOCAL_FILE_PATH } = require("./main/helpers/paths.js") +const { ipcMain, app } = require("electron"); +const fs = require("fs"); +const path = require("path"); +const { LOCAL_FILE_PATH } = require("./main/helpers/paths.js"); -const tokenFile = LOCAL_FILE_PATH +const tokenFile = LOCAL_FILE_PATH; const { API } = require("./main/helpers/paths.js"); async function register(username, email, password, passwordConfirm) { try { const response = await fetch(`${API}/auth/register`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json' + "Content-Type": "application/json", }, body: JSON.stringify({ username, password, email, - passwordConfirm - }) + passwordConfirm, + }), }); const result = await response.json(); - - console.log(`POST ${API}/auth/register.php:`) - console.log(`>`, result) + + console.log(`POST ${API}/auth/register.php:`); + console.log(">", result); if (!response.ok) { return { success: false, - result: result.result || 'Registration failed' + result: result.result || "Registration failed", }; } return { success: true, - result: result.result + result: result.result, }; } catch (error) { return { success: false, - result: error.message + result: error.message, }; } } @@ -48,14 +48,14 @@ async function register(username, email, password, passwordConfirm) { async function login(email, password) { try { const response = await fetch(`${API}/auth/checkLogin`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json' + "Content-Type": "application/json", }, body: JSON.stringify({ email, - password - }) + password, + }), }); const result = await response.json(); @@ -63,18 +63,18 @@ async function login(email, password) { if (!response.ok) { return { success: false, - result: result.result || 'Login failed' + result: result.result || "Login failed", }; } return { success: true, - result: result.result + result: result.result, }; } catch (error) { return { success: false, - result: error.message + result: error.message, }; } } @@ -82,14 +82,14 @@ async function login(email, password) { async function loginById(id, password) { try { const response = await fetch(`${API}/auth/checkLogin`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json' + "Content-Type": "application/json", }, body: JSON.stringify({ id, - password - }) + password, + }), }); const result = await response.json(); @@ -97,18 +97,18 @@ async function loginById(id, password) { if (!response.ok) { return { success: false, - result: result.result || 'Login failed' + result: result.result || "Login failed", }; } return { success: true, - result: result.result + result: result.result, }; } catch (error) { return { success: false, - result: error.message + result: error.message, }; } } @@ -116,23 +116,23 @@ async function loginById(id, password) { async function verifyToken(token) { try { const response = await fetch(`${API}/verifyToken`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${token}` - } + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, }); const result = await response.json(); return { success: response.ok, - result: result.result + result: result.result, }; } catch (error) { return { success: false, - result: error.message + result: error.message, }; } } @@ -142,7 +142,7 @@ function saveToken(tokenData) { fs.writeFileSync(tokenFile, JSON.stringify(tokenData, null, 2)); return true; } catch (error) { - console.error('Error saving token:', error); + console.error("Error saving token:", error); return false; } } @@ -150,12 +150,12 @@ function saveToken(tokenData) { function loadToken() { try { if (fs.existsSync(tokenFile)) { - const data = fs.readFileSync(tokenFile, 'utf-8'); + const data = fs.readFileSync(tokenFile, "utf-8"); return JSON.parse(data); } return null; } catch (error) { - console.error('Error loading token:', error); + console.error("Error loading token:", error); return null; } } @@ -167,19 +167,17 @@ function deleteToken() { } return true; } catch (error) { - console.error('Error deleting token:', error); + console.error("Error deleting token:", error); return false; } } -function decodeJWT(token) { +function decodeJwt(token) { try { - const parts = token.split('.'); + const parts = token.split("."); if (parts.length !== 3) return null; - const payload = JSON.parse( - Buffer.from(parts[1], 'base64').toString('utf-8') - ); + const payload = JSON.parse(Buffer.from(parts[1], "base64").toString("utf-8")); if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) { return null; @@ -187,7 +185,7 @@ function decodeJWT(token) { return payload; } catch (error) { - console.error('Error decoding JWT:', error); + console.error("Error decoding JWT:", error); return null; } } @@ -195,76 +193,75 @@ function decodeJWT(token) { async function recoveryCode(email) { try { const response = await fetch(`${API}/auth/requestRecovery`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json' + "Content-Type": "application/json", }, - body: JSON.stringify({ email }) + body: JSON.stringify({ email }), }); - const data = await response.json() + const data = await response.json(); if (data.success) { - return { success: true, result: data.result } - } else { - return { success: false, result: data.result } + return { success: true, result: data.result }; } + return { success: false, result: data.result }; } catch (error) { - return { success: false, result: error } + return { success: false, result: error }; } } async function verifyRecoveryCode(email, code) { try { const response = await fetch(`${API}/auth/verifyRecoveryCode`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json' + "Content-Type": "application/json", }, - body: JSON.stringify({ email, code }) + body: JSON.stringify({ email, code }), }); - const data = await response.json() + const data = await response.json(); - console.log("VRC:", data) + console.log("VRC:", data); if (data.success) { - return { success: true, result: data.result } - } else { - return { success: false, result: data.result } + return { success: true, result: data.result }; } + return { success: false, result: data.result }; } catch (error) { - return { success: false, result: error } + return { success: false, result: error }; } } async function resetPassword(recoveryToken, newPassword) { try { const response = await fetch(`${API}/auth/resetPassword`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json' + "Content-Type": "application/json", }, - body: JSON.stringify({ recovery_token: recoveryToken, new_password: newPassword }) + body: JSON.stringify({ recovery_token: recoveryToken, new_password: newPassword }), }); - const data = await response.json() + const data = await response.json(); if (data.success) { - return { success: true, result: data.result } - } else { - return { success: false, result: data.result } + return { success: true, result: data.result }; } + return { success: false, result: data.result }; } catch (error) { - return { success: false, result: error } + return { success: false, result: error }; } } -ipcMain.handle('register', async (_e, username, email, password, passwordConfirm) => { - return await register(username, email, password, passwordConfirm); -}); +ipcMain.handle( + "register", + async (_e, username, email, password, passwordConfirm) => + await register(username, email, password, passwordConfirm), +); -ipcMain.handle('login', async (_e, email, password) => { +ipcMain.handle("login", async (_e, email, password) => { const result = await login(email, password); if (result.success && result.result.token) { @@ -272,26 +269,26 @@ ipcMain.handle('login', async (_e, email, password) => { token: result.result.token, user: result.result.user, expiresIn: result.result.expiresIn, - savedAt: new Date().toISOString() + savedAt: new Date().toISOString(), }); } return result; }); -ipcMain.handle('request-recovery-code', async (_, email) => { - return await recoveryCode(email) -}) +ipcMain.handle("request-recovery-code", async (_, email) => await recoveryCode(email)); -ipcMain.handle('verify-recovery-code', async (_, email, code) => { - return await verifyRecoveryCode(email, code) -}) +ipcMain.handle( + "verify-recovery-code", + async (_, email, code) => await verifyRecoveryCode(email, code), +); -ipcMain.handle('reset-password', async (_, recoveryToken, newPassword) => { - return await resetPassword(recoveryToken, newPassword) -}) +ipcMain.handle( + "reset-password", + async (_, recoveryToken, newPassword) => await resetPassword(recoveryToken, newPassword), +); -ipcMain.handle('login-by-id', async (_e, id, password) => { +ipcMain.handle("login-by-id", async (_e, id, password) => { const result = await loginById(id, password); if (result.success && result.result.token) { @@ -299,55 +296,55 @@ ipcMain.handle('login-by-id', async (_e, id, password) => { token: result.result.token, user: result.result.user, expiresIn: result.result.expiresIn, - savedAt: new Date().toISOString() + savedAt: new Date().toISOString(), }); } return result; }); -ipcMain.handle('logout', async () => { +ipcMain.handle("logout", async () => { deleteToken(); return { success: true, - result: 'Logged out successfully' + result: "Logged out successfully", }; }); -ipcMain.handle('get-token', async () => { +ipcMain.handle("get-token", async () => { const tokenData = loadToken(); if (!tokenData) { return { success: false, - result: null + result: null, }; } - const decoded = decodeJWT(tokenData.token); + const decoded = decodeJwt(tokenData.token); if (!decoded) { deleteToken(); return { success: false, - result: null + result: null, }; } return { success: true, - result: tokenData + result: tokenData, }; }); -ipcMain.handle('is-logged-in', async () => { +ipcMain.handle("is-logged-in", async () => { const tokenData = loadToken(); if (!tokenData) { return false; } - const decoded = decodeJWT(tokenData.token); + const decoded = decodeJwt(tokenData.token); if (!decoded) { deleteToken(); @@ -358,25 +355,25 @@ ipcMain.handle('is-logged-in', async () => { }); ipcMain.handle("set-non-account-mode", async (_, value = true) => { - let data = {} + let data = {}; try { if (fs.existsSync(LOCAL_FILE_PATH)) { - const raw = fs.readFileSync(LOCAL_FILE_PATH, "utf-8") - data = JSON.parse(raw || "{}") + const raw = fs.readFileSync(LOCAL_FILE_PATH, "utf-8"); + data = JSON.parse(raw || "{}"); } } catch (e) { - data = {} + data = {}; } - data.nonAccountMode = value + data.nonAccountMode = value; try { - fs.writeFileSync(LOCAL_FILE_PATH, JSON.stringify(data, null, 4), "utf-8") - return { ok: true } + fs.writeFileSync(LOCAL_FILE_PATH, JSON.stringify(data, null, 4), "utf-8"); + return { ok: true }; } catch (e) { - return { ok: false } + return { ok: false }; } -}) +}); -module.exports = { API, login, verifyToken } \ No newline at end of file +module.exports = { API, login, verifyToken }; diff --git a/app/electron/live-server.js b/app/electron/live-server.js index 45461d0..b0619a1 100644 --- a/app/electron/live-server.js +++ b/app/electron/live-server.js @@ -1,26 +1,26 @@ -const { ipcMain, shell } = require("electron") -const fs = require("fs") -const path = require("path") -const http = require("http") -const WebSocket = require("ws") -const chokidar = require("chokidar") +const { ipcMain, shell } = require("electron"); +const fs = require("fs"); +const path = require("path"); +const http = require("http"); +const WebSocket = require("ws"); +const chokidar = require("chokidar"); -let liveServer = null -let wss = null -let watcher = null +let liveServer = null; +let wss = null; +let watcher = null; ipcMain.handle("start-live-server", async (event, htmlPath) => { if (!fs.existsSync(htmlPath)) { - return { error: "HTML file not found" } + return { error: "HTML file not found" }; } if (liveServer) { - return { error: "Live server already running" } + return { error: "Live server already running" }; } - const root = path.dirname(htmlPath) - const port = 3000 - const wsPort = 3001 + const root = path.dirname(htmlPath); + const port = 3000; + const wsPort = 3001; function inject(html) { const script = ` @@ -28,81 +28,75 @@ ipcMain.handle("start-live-server", async (event, htmlPath) => { const ws = new WebSocket("ws://localhost:${wsPort}") ws.onmessage = () => location.reload() - ` - return html.replace("", script + "") + `; + return html.replace("", script + ""); } liveServer = http.createServer((req, res) => { - - let filePath = path.join(root, req.url === "/" ? path.basename(htmlPath) : req.url) + const filePath = path.join(root, req.url === "/" ? path.basename(htmlPath) : req.url); fs.readFile(filePath, (err, data) => { - if (err) { - res.writeHead(404) - return res.end("Not found") + res.writeHead(404); + return res.end("Not found"); } if (filePath.endsWith(".html")) { - data = inject(data.toString()) + data = inject(data.toString()); } - res.writeHead(200) - res.end(data) - - }) - }) + res.writeHead(200); + res.end(data); + }); + }); - liveServer.listen(port) + liveServer.listen(port); - wss = new WebSocket.Server({ port: wsPort }) + wss = new WebSocket.Server({ port: wsPort }); watcher = chokidar.watch(root).on("change", () => { - wss.clients.forEach(client => { + wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { - client.send("reload") + client.send("reload"); } - }) + }); + }); - }) + const url = `http://localhost:${port}`; - const url = `http://localhost:${port}` - - shell.openExternal(url) + shell.openExternal(url); return { success: true, - url - } -}) + url, + }; +}); ipcMain.handle("stop-live-server", async () => { if (!liveServer) { - return { error: "Live server not running" } + return { error: "Live server not running" }; } try { - if (watcher) { - await watcher.close() - watcher = null + await watcher.close(); + watcher = null; } if (wss) { - wss.close() - wss = null + wss.close(); + wss = null; } - liveServer.close() - liveServer = null + liveServer.close(); + liveServer = null; return { - success: true - } - + success: true, + }; } catch (err) { return { - error: err.message - } + error: err.message, + }; } -}) \ No newline at end of file +}); diff --git a/app/main/helpers/os.js b/app/main/helpers/os.js index f7911e5..eeb547d 100644 --- a/app/main/helpers/os.js +++ b/app/main/helpers/os.js @@ -1,7 +1,7 @@ -const { dialog } = require("electron") -const fsPromise = require('fs/promises'); -const path = require("path") -const { loadGitignore, isIgnored } = require("./gitignore") +const { dialog } = require("electron"); +const fsPromise = require("fs/promises"); +const path = require("path"); +const { loadGitignore, isIgnored } = require("./gitignore"); function selectFile(win) { const result = dialog.showOpenDialogSync(win, { @@ -17,7 +17,7 @@ function selectFile(win) { function selectFolder(win) { const result = dialog.showOpenDialogSync(win, { title: "Choose directory", - properties: ["openDirectory"] + properties: ["openDirectory"], }); if (!result || !result.length) return null; @@ -26,7 +26,7 @@ function selectFolder(win) { async function saveFile(fullPath, content) { try { - await fsPromise.writeFile(fullPath, content, 'utf8'); + await fsPromise.writeFile(fullPath, content, "utf8"); return { success: true }; } catch (err) { return { success: false, error: err.message }; @@ -48,21 +48,25 @@ async function readDirTree(rootPath, options = {}) { for (const d of dirents) { const full = path.join(dir, d.name); const isDirectory = d.isDirectory(); - const item = { name: d.name, path: full, ignored: isIgnored(full, ignoreRoot, ignoreRules, isDirectory) }; + const item = { + name: d.name, + path: full, + ignored: isIgnored(full, ignoreRoot, ignoreRules, isDirectory), + }; if (isDirectory) { if (item.ignored && ignoreRules.canPrune) { - entries.push({ ...item, type: 'dir', loaded: false }); + entries.push({ ...item, type: "dir", loaded: false }); } else if (depth < maxDepth) { const children = await walk(full, depth + 1); - entries.push({ ...item, type: 'dir', children, loaded: true }); + entries.push({ ...item, type: "dir", children, loaded: true }); } else { - entries.push({ ...item, type: 'dir', loaded: false }); + entries.push({ ...item, type: "dir", loaded: false }); } } else if (d.isSymbolicLink()) { - entries.push({ ...item, type: 'symlink' }); + entries.push({ ...item, type: "symlink" }); } else { - entries.push({ ...item, type: 'file' }); + entries.push({ ...item, type: "file" }); } } @@ -70,16 +74,15 @@ async function readDirTree(rootPath, options = {}) { if (a.type === b.type) { return a.name.localeCompare(b.name); } - if (a.type === 'dir') return -1; - if (b.type === 'dir') return 1; + if (a.type === "dir") return -1; + if (b.type === "dir") return 1; return 0; }); - } catch (err) { entries.push({ name: path.basename(dir), path: dir, - type: 'dir', + type: "dir", error: String(err), }); } @@ -91,12 +94,12 @@ async function readDirTree(rootPath, options = {}) { const st = await fsPromise.lstat(absRoot); if (st.isFile()) { - return [{ name: path.basename(absRoot), path: absRoot, type: 'file' }]; + return [{ name: path.basename(absRoot), path: absRoot, type: "file" }]; } } catch (e) { throw new Error(`Path not found: ${absRoot}`); } - + return walk(absRoot); } @@ -104,5 +107,5 @@ module.exports = { selectFile, selectFolder, saveFile, - readDirTree -} + readDirTree, +}; diff --git a/app/main/helpers/paths.js b/app/main/helpers/paths.js index 91918e9..ef9bcab 100644 --- a/app/main/helpers/paths.js +++ b/app/main/helpers/paths.js @@ -1,36 +1,36 @@ -const { app } = require("electron") -const path = require("path") +const { app } = require("electron"); +const path = require("path"); -const appPath = app.getAppPath() +const appPath = app.getAppPath(); -const USER_DATA_PATH = app.getPath("userData") +const USER_DATA_PATH = app.getPath("userData"); -const HTML_PATH = path.join(appPath, "html") -const ASSETS_PATH = path.join(appPath, "assets") -const APP_PATH = path.join(appPath, "app") -const LANGUAGES_PATH = path.join(appPath, "languages") +const HTML_PATH = path.join(appPath, "html"); +const ASSETS_PATH = path.join(appPath, "assets"); +const APP_PATH = path.join(appPath, "app"); +const LANGUAGES_PATH = path.join(appPath, "languages"); -const JSON_PATH = USER_DATA_PATH +const JSON_PATH = USER_DATA_PATH; const SETTINGS_PATH = path.join(JSON_PATH, "settings.json"); const LOCAL_BUGS_PATH = path.join(JSON_PATH, "bugs.json"); const LOCAL_FILE_PATH = path.join(JSON_PATH, "local.json"); const PACKAGE_FILE_PATH = path.join(appPath, "package.json"); -const SPLASH_HTML_PATH = path.join(HTML_PATH, "splash.html") -const INDEX_HTML_PATH = path.join(HTML_PATH, "index.html") -const LOGIN_HTML_PATH = path.join(HTML_PATH, "login.html") -const REGISTER_HTML_PATH = path.join(HTML_PATH, "register.html") +const SPLASH_HTML_PATH = path.join(HTML_PATH, "splash.html"); +const INDEX_HTML_PATH = path.join(HTML_PATH, "index.html"); +const LOGIN_HTML_PATH = path.join(HTML_PATH, "login.html"); +const REGISTER_HTML_PATH = path.join(HTML_PATH, "register.html"); -const PRELOAD_PATH = path.join(APP_PATH, "dist", "preload.js") -const RENDERER_PATH = path.join(APP_PATH, "renderer.js") +const PRELOAD_PATH = path.join(APP_PATH, "dist", "preload.js"); +const RENDERER_PATH = path.join(APP_PATH, "renderer.js"); -const DEFAULT_ICON = path.join(ASSETS_PATH, "media", "codemotion_icon.png") +const DEFAULT_ICON = path.join(ASSETS_PATH, "media", "codemotion_icon.png"); // const API = "https://dev.yurba.one/api/pcode" -const API = "https://codemotion.yurba.one/api" +const API = "https://codemotion.yurba.one/api"; -module.exports = { +module.exports = { APP_PATH, SETTINGS_PATH, LOCAL_BUGS_PATH, @@ -48,5 +48,5 @@ module.exports = { RENDERER_PATH, LANGUAGES_PATH, API, - USER_DATA_PATH -} \ No newline at end of file + USER_DATA_PATH, +}; diff --git a/app/main/helpers/requests.js b/app/main/helpers/requests.js index e85b403..084afba 100644 --- a/app/main/helpers/requests.js +++ b/app/main/helpers/requests.js @@ -1,8 +1,8 @@ -const { app } = require("electron") -const fs = require("fs") -const path = require("path") -const fsPromise = require('fs/promises'); -const https = require("https") +const { app } = require("electron"); +const fs = require("fs"); +const path = require("path"); +const fsPromise = require("fs/promises"); +const https = require("https"); const { SETTINGS_PATH, LOCAL_BUGS_PATH, @@ -11,8 +11,8 @@ const { DEFAULT_ICON, ASSETS_PATH, LANGUAGES_PATH, - API -} = require("./paths.js") + API, +} = require("./paths.js"); function deepMerge(target, source) { if (!source || typeof source !== "object") return target; @@ -54,9 +54,9 @@ function readSettings() { } function writeLocalBugs(data) { try { - fs.writeFileSync(LOCAL_BUGS_PATH, JSON.stringify(data, null, 4), "utf-8") + fs.writeFileSync(LOCAL_BUGS_PATH, JSON.stringify(data, null, 4), "utf-8"); } catch (e) { - console.error("Write error:", e) + console.error("Write error:", e); } } @@ -91,7 +91,7 @@ function ensureLocalJson() { if (!fs.existsSync(LOCAL_FILE_PATH)) { const defaultData = { user: false, - password: false + password: false, }; fs.writeFileSync(LOCAL_FILE_PATH, JSON.stringify(defaultData, null, 4), "utf-8"); } @@ -99,20 +99,20 @@ function ensureLocalJson() { function ensureSettingsJson() { if (!fs.existsSync(SETTINGS_PATH)) { const defaultData = { - "app": { - "icon": "default", - "workSeconds": 0, - "workSecondsSession": 0, - "devMode": false, - "splashScreen": true, - "uiScale": 1, - "language": "en", - "restoreFolder": true + app: { + icon: "default", + workSeconds: 0, + workSecondsSession: 0, + devMode: false, + splashScreen: true, + uiScale: 1, + language: "en", + restoreFolder: true, }, - "editor": { - "smoothScroll": true - } - } + editor: { + smoothScroll: true, + }, + }; fs.writeFileSync(SETTINGS_PATH, JSON.stringify(defaultData, null, 4), "utf-8"); } @@ -159,51 +159,51 @@ function getPackageData() { } } async function getAppIcon() { - const settings = await readSettings() + const settings = await readSettings(); if ("app" in settings) { if ("icon" in settings.app) { - const appIcon = settings.app.icon == "default" - ? DEFAULT_ICON - : path.join(ASSETS_PATH, "media", "app-icons", `codemotion-icon-${settings.app.icon}.png`) - - return appIcon - } - else { - return DEFAULT_ICON + const appIcon = + settings.app.icon == "default" + ? DEFAULT_ICON + : path.join( + ASSETS_PATH, + "media", + "app-icons", + `codemotion-icon-${settings.app.icon}.png`, + ); + + return appIcon; } + return DEFAULT_ICON; } - else { - return DEFAULT_ICON - } + return DEFAULT_ICON; } function readFilesInFolder(folderPath) { - const base = path.isAbsolute(folderPath) - ? folderPath - : path.join(app.getAppPath(), folderPath); + const base = path.isAbsolute(folderPath) ? folderPath : path.join(app.getAppPath(), folderPath); if (!fs.existsSync(base)) { return []; } - return fs.readdirSync(base).map(file => { + return fs.readdirSync(base).map((file) => { const fullPath = path.join(base, file); const isDir = fs.statSync(fullPath).isDirectory(); return { name: file, path: fullPath, - type: isDir ? "folder" : "file" + type: isDir ? "folder" : "file", }; }); } -async function readFileContent(filePath, encoding = 'utf8') { - const base = path.isAbsolute(filePath) - ? filePath - : path.join(app.getAppPath(), filePath); +async function readFileContent(filePath, encoding = "utf8") { + const base = path.isAbsolute(filePath) ? filePath : path.join(app.getAppPath(), filePath); const abs = path.resolve(base, filePath); - const data = await fsPromise.readFile(abs, { encoding: encoding === null ? undefined : encoding }); + const data = await fsPromise.readFile(abs, { + encoding: encoding === null ? undefined : encoding, + }); return data; } function updateLocalAppData(newData) { @@ -223,17 +223,17 @@ function updateLocalAppData(newData) { try { fs.writeFileSync(filePath, JSON.stringify(updatedData, null, 4), "utf-8"); - console.log("local.json updated") + console.log("local.json updated"); } catch (e) { console.error("Error while updating local.json:", e); } } async function checkStatus({ updateSplash }) { - function checkURL(url, stepName) { + function checkUrl(url, stepName) { return new Promise((resolve, reject) => { const req = https.get(url, (res) => { if (res.statusCode >= 200 && res.statusCode < 400) { - updateSplash(`${stepName}: OK (${res.statusCode})`) + updateSplash(`${stepName}: OK (${res.statusCode})`); res.resume(); resolve(true); } else { @@ -252,234 +252,229 @@ async function checkStatus({ updateSplash }) { }); } - updateSplash("Internet check...") + updateSplash("Internet check..."); try { - await checkURL("https://www.gstatic.com/generate_204", "Internet"); + await checkUrl("https://www.gstatic.com/generate_204", "Internet"); } catch (err) { - updateSplash(`Error: ${err.message}`, true) + updateSplash(`Error: ${err.message}`, true); throw new Error("Error: " + err.message); } - const hosts = [ - { name: "API Server", url: API } - ]; + const hosts = [{ name: "API Server", url: API }]; for (let i = 0; i < hosts.length; i++) { const { name, url } = hosts[i]; - updateSplash(`Requesting ${url}...`) + updateSplash(`Requesting ${url}...`); try { - await checkURL(url, name); + await checkUrl(url, name); } catch (err) { throw new Error(`${name} not aviable: ${err.message}`); } } - updateSplash("Everything is okey. Starting the program...") + updateSplash("Everything is okey. Starting the program..."); return true; } async function getAllLanguages() { - if(fs.existsSync(LANGUAGES_PATH)) { + if (fs.existsSync(LANGUAGES_PATH)) { try { - const files = await fs.promises.readdir(LANGUAGES_PATH) - const result = [] + const files = await fs.promises.readdir(LANGUAGES_PATH); + const result = []; for (const file of files) { - const fullPath = path.join(LANGUAGES_PATH, file) - const stat = await fs.promises.stat(fullPath) + const fullPath = path.join(LANGUAGES_PATH, file); + const stat = await fs.promises.stat(fullPath); if (stat.isFile()) { - const name = file.split(".")[0].trim() - result.push(name) + const name = file.split(".")[0].trim(); + result.push(name); } } - return result + return result; } catch (err) { - console.error("getAllLanguages error:", err) - return {} + console.error("getAllLanguages error:", err); + return {}; } - } - else { - return {} + } else { + return {}; } } -async function getAllLanguagesJSON() { - const languages = await getAllLanguages() - let result = {} +async function getAllLanguagesJson() { + const languages = await getAllLanguages(); + const result = {}; - if(languages.length > 0) { - languages.forEach(language => { + if (languages.length > 0) { + languages.forEach((language) => { try { - const data = fs.readFileSync(path.join(LANGUAGES_PATH, language + ".json"), 'utf8'); - result[language] = JSON.parse(data) + const data = fs.readFileSync(path.join(LANGUAGES_PATH, language + ".json"), "utf8"); + result[language] = JSON.parse(data); } catch (error) {} - }) + }); } - return result + return result; } async function getUserToken() { - if(fs.existsSync(LOCAL_FILE_PATH)) { + if (fs.existsSync(LOCAL_FILE_PATH)) { try { - let data = fs.readFileSync(LOCAL_FILE_PATH, 'utf8'); - data = JSON.parse(data) + let data = fs.readFileSync(LOCAL_FILE_PATH, "utf8"); + data = JSON.parse(data); - if("token" in data) { - return data.token + if ("token" in data) { + return data.token; } - else { - return false - } - } - catch { - return false + return false; + } catch { + return false; } } } -async function requestAddBug({ title = "Unnamed", description = "No description provided", priority = 0, isPrivate = 0, assignTo = 0 }) { - const userToken = await getUserToken() +async function requestAddBug({ + title = "Unnamed", + description = "No description provided", + priority = 0, + isPrivate = 0, + assignTo = 0, +}) { + const userToken = await getUserToken(); const formData = new FormData(); - formData.append('name', title); - formData.append('description', description); - formData.append('priority', priority); - formData.append('private', isPrivate); - - if(assignTo != 0) { - formData.append('touserid', assignTo); + formData.append("name", title); + formData.append("description", description); + formData.append("priority", priority); + formData.append("private", isPrivate); + + if (assignTo != 0) { + formData.append("touserid", assignTo); } - console.log(`Request bug creation. assign to: ${assignTo} (allowed: ${assignTo != 0})`) + console.log(`Request bug creation. assign to: ${assignTo} (allowed: ${assignTo != 0})`); try { const response = await fetch(`${API}/bug/add`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, - body: formData + body: formData, }); const data = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } } async function requestMakeVerifyBug({ bugid }) { - const userToken = await getUserToken() + const userToken = await getUserToken(); const formData = new FormData(); - formData.append('bugid', bugid); + formData.append("bugid", bugid); try { const response = await fetch(`${API}/bug/makeVerify`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, - body: formData + body: formData, }); const data = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } } async function requestGetYourOrgColleagues() { - const userToken = await getUserToken() + const userToken = await getUserToken(); try { const response = await fetch(`${API}/org/getYourColleagues`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, - body: {} + body: {}, }); const data = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } } async function requestCreateOrganization({ name, description, website }) { - const userToken = await getUserToken() + const userToken = await getUserToken(); const formData = new FormData(); - formData.append('name', name); - formData.append('description', description); - formData.append('website', website); + formData.append("name", name); + formData.append("description", description); + formData.append("website", website); try { const response = await fetch(`${API}/org/create`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, - body: formData + body: formData, }); - const data = await response.json() + const data = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } } async function requestExploreOrganizations() { - const userToken = await getUserToken() + const userToken = await getUserToken(); try { const response = await fetch(`${API}/org/explore`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, - body: {} + body: {}, }); - const data = await response.json() + const data = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } } @@ -487,89 +482,55 @@ async function getUsedLanguagesByPath(targetPath) { const languages = { js: { name: "JavaScript", - extensions: [ - ".js", - ".mjs", - ".cjs", - ".jsx", - ".es6" - ], - color: "#FFCC33" + extensions: [".js", ".mjs", ".cjs", ".jsx", ".es6"], + color: "#FFCC33", }, ts: { name: "TypeScript", - extensions: [ - ".ts", - ".mts", - ".cts", - ".tsx" - ], - color: "#3178c6" + extensions: [".ts", ".mts", ".cts", ".tsx"], + color: "#3178c6", }, html: { name: "HTML", - extensions: [ - ".html", - ".htm", - ".xhtml" - ], - color: "#FF6933" + extensions: [".html", ".htm", ".xhtml"], + color: "#FF6933", }, css: { name: "CSS", - extensions: [ - ".css", - ".scss", - ".sass", - ".less" - ], - color: "#3388FF" + extensions: [".css", ".scss", ".sass", ".less"], + color: "#3388FF", }, json: { name: "JSON", - extensions: [ - ".json", - ".jsonc", - ".json5" - ], - color: "#FF8B33" + extensions: [".json", ".jsonc", ".json5"], + color: "#FF8B33", }, php: { name: "PHP", - extensions: [ - ".php", - ".phtml", - ".php3", - ".php4", - ".php5", - ".phps", - ".inc" - ], - color: "#8692ff" + extensions: [".php", ".phtml", ".php3", ".php4", ".php5", ".phps", ".inc"], + color: "#8692ff", }, go: { name: "Go", - extensions: [ - ".go" - ], - color: "#62daff" - } - } + extensions: [".go"], + color: "#62daff", + }, + }; const extensionMap = Object.entries(languages).reduce((acc, [key, lang]) => { for (const ext of lang.extensions) { - acc[ext] = key + acc[ext] = key; } - return acc - }, {}) + return acc; + }, {}); - const IGNORED_DIRS = new Set([ + const IgnoredDirs = new Set([ "node_modules", ".git", "dist", @@ -580,84 +541,80 @@ async function getUsedLanguagesByPath(targetPath) { "package-lock.json", "LICENSE", ".gitignore", - "README.md" - ]) + "README.md", + ]); if (!path.isAbsolute(targetPath)) { - throw new Error("Path must be absolute") + throw new Error("Path must be absolute"); } - const counts = {} - let knownFiles = 0 - let unknownFiles = 0 + const counts = {}; + let knownFiles = 0; + let unknownFiles = 0; async function scan(dir) { - let entries + let entries; try { - entries = await fsPromise.readdir(dir, { withFileTypes: true }) + entries = await fsPromise.readdir(dir, { withFileTypes: true }); } catch { - return + return; } - const tasks = [] + const tasks = []; for (const entry of entries) { - const fullPath = path.join(dir, entry.name) + const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { - if (!IGNORED_DIRS.has(entry.name)) { - tasks.push(scan(fullPath)) + if (!IgnoredDirs.has(entry.name)) { + tasks.push(scan(fullPath)); } - continue + continue; } - if (!entry.isFile()) continue + if (!entry.isFile()) continue; - const ext = path.extname(entry.name).toLowerCase() - const langKey = extensionMap[ext] + const ext = path.extname(entry.name).toLowerCase(); + const langKey = extensionMap[ext]; if (langKey) { - counts[langKey] = (counts[langKey] || 0) + 1 - knownFiles++ + counts[langKey] = (counts[langKey] || 0) + 1; + knownFiles++; } else { - unknownFiles++ + unknownFiles++; } } - await Promise.all(tasks) + await Promise.all(tasks); } - await scan(targetPath) + await scan(targetPath); - const totalFiles = knownFiles + unknownFiles + const totalFiles = knownFiles + unknownFiles; const result = Object.entries(languages).map(([key, lang]) => { - const files = counts[key] || 0 + const files = counts[key] || 0; return { key, name: lang.name, color: lang.color, files, - percentage: totalFiles - ? Math.round((files / totalFiles) * 100) - : 0 - } - }) + percentage: totalFiles ? Math.round((files / totalFiles) * 100) : 0, + }; + }); - const unknownPercentage = totalFiles - ? Math.round((unknownFiles / totalFiles) * 100) - : 0 + const unknownPercentage = totalFiles ? Math.round((unknownFiles / totalFiles) * 100) : 0; return { languages: result, unknown: { files: unknownFiles, - percentage: unknownPercentage + percentage: unknownPercentage, }, - totalFiles - } + totalFiles, + }; } module.exports = { @@ -679,12 +636,12 @@ module.exports = { updateLocalAppData, checkStatus, getAllLanguages, - getAllLanguagesJSON, + getAllLanguagesJSON: getAllLanguagesJson, getUserToken, requestAddBug, requestMakeVerifyBug, requestGetYourOrgColleagues, getUsedLanguagesByPath, requestCreateOrganization, - requestExploreOrganizations -} \ No newline at end of file + requestExploreOrganizations, +}; diff --git a/app/main/helpers/terminal.js b/app/main/helpers/terminal.js index 21e00c6..65fc18e 100644 --- a/app/main/helpers/terminal.js +++ b/app/main/helpers/terminal.js @@ -1,7 +1,7 @@ -const { spawn, spawnSync } = require('child_process'); -const { ipcMain } = require('electron'); -const fs = require('fs'); -const os = require('os'); +const { spawn, spawnSync } = require("child_process"); +const { ipcMain } = require("electron"); +const fs = require("fs"); +const os = require("os"); class TerminalManager { constructor() { @@ -14,9 +14,9 @@ class TerminalManager { // configure fish, bash, or other shells. Hardcoding /bin/bash // breaks terminal for non-bash users. We read $SHELL and // validate the binary exists before using it. - - if (process.platform === 'win32') { - return 'cmd.exe'; + + if (process.platform === "win32") { + return "cmd.exe"; } const userShell = process.env.SHELL; @@ -25,25 +25,25 @@ class TerminalManager { return userShell; } - for (const shell of ['/bin/zsh', '/bin/bash', '/bin/sh']) { + for (const shell of ["/bin/zsh", "/bin/bash", "/bin/sh"]) { if (fs.existsSync(shell)) { return shell; } } - return '/bin/sh'; + return "/bin/sh"; } validateWorkDir(cwd) { - if (!cwd || !fs.existsSync(cwd)) { + if (!(cwd && fs.existsSync(cwd))) { console.log("[Terminal] Path does not exist, using default: " + process.cwd()); return process.cwd(); } const stat = fs.statSync(cwd); - + if (stat.isFile()) { - const path = require('path'); + const path = require("path"); const dirname = path.dirname(cwd); console.log(`[Terminal] Path is a file, using directory: ${dirname}`); return dirname; @@ -53,20 +53,22 @@ class TerminalManager { return cwd; } - console.log("[Terminal] Path is neither file nor directory, using default: " + process.cwd()); + console.log( + "[Terminal] Path is neither file nor directory, using default: " + process.cwd(), + ); return process.cwd(); } handleOutput(data, type, event) { const output = data.toString(); - const prefix = type === 'stderr' ? '[ERR] ' : ''; - + const prefix = type === "stderr" ? "[ERR] " : ""; + console.log(`[Terminal ${type}] ${output}`); - + event.sender.send("terminal-result", { - type: type === 'stderr' ? 'error' : 'output', + type: type === "stderr" ? "error" : "output", data: prefix + output, - timestamp: Date.now() + timestamp: Date.now(), }); } @@ -89,16 +91,16 @@ class TerminalManager { const pid = this.activeProcess.pid; try { - if (process.platform === 'win32') { - const args = ['/pid', String(pid), '/T']; - if (force) args.push('/F'); + if (process.platform === "win32") { + const args = ["/pid", String(pid), "/T"]; + if (force) args.push("/F"); - spawnSync('taskkill.exe', args, { + spawnSync("taskkill.exe", args, { windowsHide: true, - stdio: 'ignore' + stdio: "ignore", }); } else { - this.activeProcess.kill(force ? 'SIGKILL' : 'SIGTERM'); + this.activeProcess.kill(force ? "SIGKILL" : "SIGTERM"); } } catch (err) { console.error(`[Terminal] Error killing process tree: ${err.message}`); @@ -110,8 +112,8 @@ class TerminalManager { if (this.activeProcess) { event.sender.send("terminal-result", { - type: 'warning', - data: 'Another process is already running. Kill it first.\r\n' + type: "warning", + data: "Another process is already running. Kill it first.\r\n", }); return; } @@ -123,22 +125,22 @@ class TerminalManager { console.log(`[Terminal] Using shell: ${shell}`); try { - const isWindows = process.platform === 'win32'; - const spawnArgs = isWindows ? ['/c', cmd] : ['-c', cmd]; - const spawnShell = isWindows ? 'cmd.exe' : shell; + const isWindows = process.platform === "win32"; + const spawnArgs = isWindows ? ["/c", cmd] : ["-c", cmd]; + const spawnShell = isWindows ? "cmd.exe" : shell; this.activeProcess = spawn(spawnShell, spawnArgs, { cwd: workDir, shell: false, - stdio: ['pipe', 'pipe', 'pipe'], + stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - TERM: 'xterm-256color' - } + TERM: "xterm-256color", + }, }); - if (!this.activeProcess || !this.activeProcess.pid) { - const errorMsg = 'Failed to spawn process - check shell path and arguments'; + if (!(this.activeProcess && this.activeProcess.pid)) { + const errorMsg = "Failed to spawn process - check shell path and arguments"; console.error(`[Terminal] ${errorMsg}`); throw new Error(errorMsg); } @@ -146,20 +148,20 @@ class TerminalManager { console.log(`[Terminal] Process spawned with PID: ${this.activeProcess.pid}`); this.activeProcess.stdout.on("data", (data) => { - this.handleOutput(data, 'stdout', event); + this.handleOutput(data, "stdout", event); }); this.activeProcess.stderr.on("data", (data) => { - this.handleOutput(data, 'stderr', event); + this.handleOutput(data, "stderr", event); }); this.activeProcess.on("close", (code) => { console.log(`[Terminal] Process exited with code ${code}`); - + event.sender.send("terminal-result", { - type: 'exit', + type: "exit", data: `\r\nProcess exited with code ${code}\r\n`, - exitCode: code + exitCode: code, }); this.activeProcess = null; @@ -168,10 +170,10 @@ class TerminalManager { this.activeProcess.on("error", (err) => { console.error(`[Terminal] Error: ${err.message}`); - + event.sender.send("terminal-result", { - type: 'error', - data: `Error: ${err.message}\r\n` + type: "error", + data: `Error: ${err.message}\r\n`, }); this.activeProcess = null; @@ -183,27 +185,26 @@ class TerminalManager { this.inputHandler = (e, input) => { if (this.activeProcess && !this.activeProcess.killed) { try { - const inputWithNewline = input.endsWith('\n') ? input : input + '\n'; + const inputWithNewline = input.endsWith("\n") ? input : input + "\n"; this.activeProcess.stdin.write(inputWithNewline); console.log(`[Terminal] Sent input: ${input}`); } catch (err) { console.error("Error writing to stdin:", err.message); event.sender.send("terminal-result", { - type: 'error', - data: `Error writing to stdin: ${err.message}\r\n` + type: "error", + data: `Error writing to stdin: ${err.message}\r\n`, }); } } }; ipcMain.on("terminal-input", this.inputHandler); - } catch (err) { console.error(`[Terminal] Catch error: ${err.message}`); - + event.sender.send("terminal-result", { - type: 'error', - data: `Failed to execute command: ${err.message}\r\n` + type: "error", + data: `Failed to execute command: ${err.message}\r\n`, }); this.activeProcess = null; @@ -228,20 +229,19 @@ class TerminalManager { const forceKillTimeout = setTimeout(() => { if (this.activeProcess && !this.activeProcess.killed) { - console.log(`[Terminal] Force killing process`); + console.log("[Terminal] Force killing process"); this.killProcessTree(true); } }, 2000); - this.activeProcess.on('exit', () => { + this.activeProcess.on("exit", () => { clearTimeout(forceKillTimeout); }); - } catch (err) { console.error(`[Terminal] Error killing process: ${err.message}`); event.sender.send("terminal-result", { - type: 'error', - data: `Error killing process: ${err.message}\r\n` + type: "error", + data: `Error killing process: ${err.message}\r\n`, }); } } diff --git a/app/main/ipc/api.ts b/app/main/ipc/api.ts index c77daed..8f9457a 100644 --- a/app/main/ipc/api.ts +++ b/app/main/ipc/api.ts @@ -1,60 +1,59 @@ -import { ipcMain, IpcMainInvokeEvent } from "electron"; -import { getUserToken, readFileContent } from "../helpers/requests"; +import { type IpcMainInvokeEvent, ipcMain } from "electron"; import { API, LOCAL_FILE_PATH } from "../helpers/paths"; +import { getUserToken, readFileContent } from "../helpers/requests"; -ipcMain.handle('get-user-data-from-api', async () => { - let localData: any = await readFileContent(LOCAL_FILE_PATH) - localData = JSON.parse(localData) +ipcMain.handle("get-user-data-from-api", async () => { + let localData: any = await readFileContent(LOCAL_FILE_PATH); + localData = JSON.parse(localData); - let api = `${API}/getMe` + const api = `${API}/getMe`; try { const response = await fetch(api, { method: "GET", headers: { - "Authorization": `Bearer ${localData.token}` - } + Authorization: `Bearer ${localData.token}`, + }, }); const result = await response.json(); if (!response.ok) { return { success: false, - result: result - } + result, + }; } - + return { success: true, - result: result - } + result, + }; } catch (error: unknown) { return { success: false, result: String(error), - } + }; } -}) +}); -ipcMain.handle('get-user', async (_: IpcMainInvokeEvent, userid: number) => { - const userToken = await getUserToken() +ipcMain.handle("get-user", async (_: IpcMainInvokeEvent, userid: number) => { + const userToken = await getUserToken(); try { const response = await fetch(`${API}/user/get?id=${userid}`, { - method: 'GET', + method: "GET", headers: { - 'Authorization': `Bearer ${userToken}` - } + Authorization: `Bearer ${userToken}`, + }, }); - const data: any = await response.json() + const data: any = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } -}) \ No newline at end of file +}); diff --git a/app/main/ipc/bugs.ts b/app/main/ipc/bugs.ts index 40a2d26..1c6f484 100644 --- a/app/main/ipc/bugs.ts +++ b/app/main/ipc/bugs.ts @@ -1,9 +1,11 @@ -import { ipcMain, IpcMainInvokeEvent } from "electron" -import { requestAddBug, requestMakeVerifyBug } from "../helpers/requests" +import { type IpcMainInvokeEvent, ipcMain } from "electron"; +import { requestAddBug, requestMakeVerifyBug } from "../helpers/requests"; -ipcMain.handle("request-add-bug", async (_: IpcMainInvokeEvent, params: object) => { - return await requestAddBug(params) -}) -ipcMain.handle("request-make-verify-bug", async (_: IpcMainInvokeEvent, params = {}) => { - return await requestMakeVerifyBug(params) -}) \ No newline at end of file +ipcMain.handle( + "request-add-bug", + async (_: IpcMainInvokeEvent, params: object) => await requestAddBug(params), +); +ipcMain.handle( + "request-make-verify-bug", + async (_: IpcMainInvokeEvent, params = {}) => await requestMakeVerifyBug(params), +); diff --git a/app/main/ipc/editor.ts b/app/main/ipc/editor.ts index 1dc0a9e..78baabc 100644 --- a/app/main/ipc/editor.ts +++ b/app/main/ipc/editor.ts @@ -34,4 +34,4 @@ export function setEditorChangedCallback(cb: EditorChangedCallback): void { export function setEditorClickedCallback(cb: EditorClickedCallback): void { editorClickedCallback = cb; -} \ No newline at end of file +} diff --git a/app/main/ipc/filesWork.ts b/app/main/ipc/filesWork.ts index d008af9..4aeaa56 100644 --- a/app/main/ipc/filesWork.ts +++ b/app/main/ipc/filesWork.ts @@ -1,39 +1,39 @@ -import { dialog, ipcMain, IpcMainInvokeEvent, shell } from "electron" -import path from "node:path" -import fs from "fs" - -import { readDirTree, saveFile } from "../helpers/os" -import { readFileContent } from "../helpers/requests" -import { SaveContentPayload } from "../payloads" -import { APP_PATH } from "../helpers/paths" +import path from "node:path"; +import process from "node:process"; +import { dialog, type IpcMainInvokeEvent, ipcMain, shell } from "electron"; +import fs from "fs"; +import { readDirTree, saveFile } from "../helpers/os"; +import { APP_PATH } from "../helpers/paths"; +import { readFileContent } from "../helpers/requests"; +import type { SaveContentPayload } from "../payloads"; ipcMain.handle("create-file", async (_: IpcMainInvokeEvent, targetPath: string) => { try { - const resolvedPath = path.resolve(targetPath) - const handle = await fs.promises.open(resolvedPath, "wx") - await handle.close() - return { success: true, path: resolvedPath } + const resolvedPath = path.resolve(targetPath); + const handle = await fs.promises.open(resolvedPath, "wx"); + await handle.close(); + return { success: true, path: resolvedPath }; } catch (err: unknown) { - return { success: false, error: String(err) } + return { success: false, error: String(err) }; } -}) +}); ipcMain.handle("create-folder", async (_: IpcMainInvokeEvent, targetPath: string) => { try { - const resolvedPath = path.resolve(targetPath) - await fs.promises.mkdir(resolvedPath) - return { success: true, path: resolvedPath } + const resolvedPath = path.resolve(targetPath); + await fs.promises.mkdir(resolvedPath); + return { success: true, path: resolvedPath }; } catch (err: unknown) { - return { success: false, error: String(err) } + return { success: false, error: String(err) }; } -}) +}); ipcMain.handle("reveal-in-file-explorer", async (_: IpcMainInvokeEvent, targetPath: string) => { if (!targetPath || typeof targetPath !== "string") { - return { success: false, error: "Invalid path" } + return { success: false, error: "Invalid path" }; } - shell.showItemInFolder(path.resolve(targetPath)) - return { success: true } -}) + shell.showItemInFolder(path.resolve(targetPath)); + return { success: true }; +}); ipcMain.handle("rename-path", async (_: IpcMainInvokeEvent, oldPath: string, newPath: string) => { async function copyRecursive(src: string, dest: string) { const stat = await fs.promises.stat(src); @@ -55,106 +55,113 @@ ipcMain.handle("rename-path", async (_: IpcMainInvokeEvent, oldPath: string, new await fs.promises.rename(resolvedOldPath, resolvedNewPath); return { success: true, path: resolvedNewPath }; } catch (err: unknown) { - const error = err as NodeJS.ErrnoException + const error = err as NodeJS.ErrnoException; if ((error.code === "EPERM" || error.code === "EACCES") && process.platform === "win32") { try { - await copyRecursive(resolvedOldPath, resolvedNewPath) - await fs.promises.rm(resolvedOldPath, { recursive: true, force: true }) + await copyRecursive(resolvedOldPath, resolvedNewPath); + await fs.promises.rm(resolvedOldPath, { recursive: true, force: true }); - return { success: true, path: resolvedNewPath } + return { success: true, path: resolvedNewPath }; } catch (fallbackErr: unknown) { - const e = fallbackErr as Error - return { success: false, error: e.message } + const e = fallbackErr as Error; + return { success: false, error: e.message }; } } - const e = err as Error - return { success: false, error: e.message } + const e = err as Error; + return { success: false, error: e.message }; } -}) -ipcMain.handle('save-file', async (_: IpcMainInvokeEvent, fullPath: string, content: string) => { - return await saveFile(fullPath, content); -}); -ipcMain.handle('readFileContent', async (_: IpcMainInvokeEvent, filePath: string, encoding = 'utf8') => { - return readFileContent(filePath, encoding); -}); -ipcMain.handle('readDirTree', async (_: IpcMainInvokeEvent, rootPath: string, options = {}) => { - return readDirTree(rootPath, options); }); +ipcMain.handle( + "save-file", + async (_: IpcMainInvokeEvent, fullPath: string, content: string) => + await saveFile(fullPath, content), +); +ipcMain.handle( + "readFileContent", + async (_: IpcMainInvokeEvent, filePath: string, encoding = "utf8") => + readFileContent(filePath, encoding), +); +ipcMain.handle("readDirTree", async (_: IpcMainInvokeEvent, rootPath: string, options = {}) => + readDirTree(rootPath, options), +); ipcMain.handle("remove-by-path", async (_: IpcMainInvokeEvent, targetPath: string) => { try { if (!targetPath || typeof targetPath !== "string") { - throw new Error("Invalid path") + throw new Error("Invalid path"); } - const resolvedPath = path.resolve(targetPath) + const resolvedPath = path.resolve(targetPath); if (!fs.existsSync(resolvedPath)) { - return { success: false, error: "Path does not exist" } + return { success: false, error: "Path does not exist" }; } - const stat = fs.lstatSync(resolvedPath) + const stat = fs.lstatSync(resolvedPath); if (stat.isDirectory()) { - fs.rmSync(resolvedPath, { recursive: true, force: true }) + fs.rmSync(resolvedPath, { recursive: true, force: true }); } else { - fs.unlinkSync(resolvedPath) + fs.unlinkSync(resolvedPath); } - return { success: true } + return { success: true }; } catch (err: unknown) { - return { success: false, error: String(err) } + return { success: false, error: String(err) }; } -}) -ipcMain.handle('ask-to-save-content', async (_: IpcMainInvokeEvent, payload: SaveContentPayload) => { - try { - const result: any = await dialog.showSaveDialog({ - title: 'Save a new file', - defaultPath: payload.filename, - buttonLabel: 'Save', - properties: ['createDirectory'] - }); - - if (result.canceled || !result.filePath) { - return { success: false, canceled: true }; - } - - await fs.promises.writeFile(result.filePath, payload.content, 'utf-8'); - - return { - success: true, - path: result.filePath - }; +}); +ipcMain.handle( + "ask-to-save-content", + async (_: IpcMainInvokeEvent, payload: SaveContentPayload) => { + try { + const result: any = await dialog.showSaveDialog({ + title: "Save a new file", + defaultPath: payload.filename, + buttonLabel: "Save", + properties: ["createDirectory"], + }); + + if (result.canceled || !result.filePath) { + return { success: false, canceled: true }; + } - } catch (err: unknown) { - console.error('Save error:', err); + await fs.promises.writeFile(result.filePath, payload.content, "utf-8"); - return { - success: false, - error: String(err) - }; - } -}); + return { + success: true, + path: result.filePath, + }; + } catch (err: unknown) { + console.error("Save error:", err); -ipcMain.handle("read-file", async (event: IpcMainInvokeEvent, filePath: string, parentPath: string): Promise<{ success: boolean; result: string | Error }> => { - try { - const data = await fs.promises.readFile( - path.join(parentPath, filePath), - "utf-8" - ) - - return { - success: true, - result: data + return { + success: false, + error: String(err), + }; } - } catch (error) { - return { - success: false, - result: error instanceof Error - ? error - : new Error(String(error)) + }, +); + +ipcMain.handle( + "read-file", + async ( + event: IpcMainInvokeEvent, + filePath: string, + parentPath: string, + ): Promise<{ success: boolean; result: string | Error }> => { + try { + const data = await fs.promises.readFile(path.join(parentPath, filePath), "utf-8"); + + return { + success: true, + result: data, + }; + } catch (error) { + return { + success: false, + result: error instanceof Error ? error : new Error(String(error)), + }; } - } -} -) \ No newline at end of file + }, +); diff --git a/app/main/ipc/getters.ts b/app/main/ipc/getters.ts index 6c08eec..80a5b68 100644 --- a/app/main/ipc/getters.ts +++ b/app/main/ipc/getters.ts @@ -1,5 +1,9 @@ -import { ipcMain, IpcMainInvokeEvent } from "electron"; -import os from "node:os" +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import process from "node:process"; +import { type IpcMainInvokeEvent, ipcMain } from "electron"; +import { ASSETS_PATH } from "../helpers/paths"; import { getAllLanguages, getAllLanguagesJSON, @@ -10,37 +14,28 @@ import { getUsedLanguagesByPath, getUserToken, readFilesInFolder, - readSettings + readSettings, } from "../helpers/requests"; -import path from "node:path"; -import fs from "node:fs" -import { ASSETS_PATH } from "../helpers/paths"; -ipcMain.handle('get-package-data', async () => { - return getPackageData() -}); -ipcMain.handle('get-local-bugs-data', async () => { - return getLocalBugsData() -}); -ipcMain.handle("get-user-pc-info", async () => { - return { - platform: process.platform, - arch: process.arch, - cpus: os.cpus().length, - totalMemory: os.totalmem(), - freeMemory: os.freemem(), - hostname: os.hostname(), - homedir: os.homedir() - }; -}); -ipcMain.handle('get-all-app-icons', () => { +ipcMain.handle("get-package-data", async () => getPackageData()); +ipcMain.handle("get-local-bugs-data", async () => getLocalBugsData()); +ipcMain.handle("get-user-pc-info", async () => ({ + platform: process.platform, + arch: process.arch, + cpus: os.cpus().length, + totalMemory: os.totalmem(), + freeMemory: os.freemem(), + hostname: os.hostname(), + homedir: os.homedir(), +})); +ipcMain.handle("get-all-app-icons", () => { try { return readFilesInFolder("assets/media/icons/symbols/files"); } catch (e) { return []; } }); -ipcMain.handle('get-all-filenames-app-icons', () => { +ipcMain.handle("get-all-filenames-app-icons", () => { try { return readFilesInFolder("assets/media/icons/symbols/files"); } catch (e) { @@ -49,49 +44,34 @@ ipcMain.handle('get-all-filenames-app-icons', () => { }); ipcMain.handle("get-app-icons", async () => { try { - const dir = path.join(ASSETS_PATH, "media", "app-icons") - const files = await fs.promises.readdir(dir) - const result = [] + const dir = path.join(ASSETS_PATH, "media", "app-icons"); + const files = await fs.promises.readdir(dir); + const result = []; for (const file of files) { - const fullPath = path.join(dir, file) - const stat = await fs.promises.stat(fullPath) + const fullPath = path.join(dir, file); + const stat = await fs.promises.stat(fullPath); if (stat.isFile()) { - result.push(file) + result.push(file); } } - return result + return result; } catch (err) { - console.error("get-app-icons error:", err) - return [] + console.error("get-app-icons error:", err); + return []; } -}) -ipcMain.handle("get-app-local", async () => { - return await getLocalAppData() -}) -ipcMain.handle("get-all-languages", async () => { - return await getAllLanguages() -}) -ipcMain.handle("get-all-languages-json", async () => { - return await getAllLanguagesJSON() -}) -ipcMain.handle("get-app-icon", async () => { - return await getAppIcon() -}) -ipcMain.handle("get-dirname", async () => { - return __dirname -}) -ipcMain.handle("get-platform", () => { - return process.platform -}) -ipcMain.handle("get-user-token", async () => { - return await getUserToken() -}) -ipcMain.handle("get-used-languages-by-path", async (_: IpcMainInvokeEvent, targetPath: string) => { - return await getUsedLanguagesByPath(targetPath) -}) -ipcMain.handle("read-settings", () => { - return readSettings(); -}); \ No newline at end of file +}); +ipcMain.handle("get-app-local", async () => await getLocalAppData()); +ipcMain.handle("get-all-languages", async () => await getAllLanguages()); +ipcMain.handle("get-all-languages-json", async () => await getAllLanguagesJSON()); +ipcMain.handle("get-app-icon", async () => await getAppIcon()); +ipcMain.handle("get-dirname", async () => __dirname); +ipcMain.handle("get-platform", () => process.platform); +ipcMain.handle("get-user-token", async () => await getUserToken()); +ipcMain.handle( + "get-used-languages-by-path", + async (_: IpcMainInvokeEvent, targetPath: string) => await getUsedLanguagesByPath(targetPath), +); +ipcMain.handle("read-settings", () => readSettings()); diff --git a/app/main/ipc/misc.ts b/app/main/ipc/misc.ts index fd272fa..df68611 100644 --- a/app/main/ipc/misc.ts +++ b/app/main/ipc/misc.ts @@ -1,5 +1,5 @@ -import { ipcMain, IpcMainInvokeEvent, shell } from "electron"; +import { type IpcMainInvokeEvent, ipcMain, shell } from "electron"; ipcMain.handle("open-in-browser", (_: IpcMainInvokeEvent, url: string) => { shell.openExternal(url); -}); \ No newline at end of file +}); diff --git a/app/main/ipc/organizations.ts b/app/main/ipc/organizations.ts index 14649f8..f7ac012 100644 --- a/app/main/ipc/organizations.ts +++ b/app/main/ipc/organizations.ts @@ -1,118 +1,119 @@ -import { dialog, ipcMain, IpcMainInvokeEvent } from "electron" -import { getUserToken, requestCreateOrganization, requestExploreOrganizations, requestGetYourOrgColleagues } from "../helpers/requests" -import { API } from "../helpers/paths" -import { readFile } from "fs/promises"; -import fs from "node:fs" +import fs from "node:fs"; import path from "node:path"; - -ipcMain.handle("create-organization", async (_: IpcMainInvokeEvent, params: any) => { - return await requestCreateOrganization(params) -}) -ipcMain.handle("request-get-your-org-colleagues", async (_: IpcMainInvokeEvent) => { - return await requestGetYourOrgColleagues() -}) -ipcMain.handle("get-explore-organizations", async () => { - return await requestExploreOrganizations() -}) -ipcMain.handle('get-org-data-from-api', async (_: IpcMainInvokeEvent, orgID: number) => { - const userToken = await getUserToken() +import { dialog, type IpcMainInvokeEvent, ipcMain } from "electron"; +import { readFile } from "fs/promises"; +import { API } from "../helpers/paths"; +import { + getUserToken, + requestCreateOrganization, + requestExploreOrganizations, + requestGetYourOrgColleagues, +} from "../helpers/requests"; + +ipcMain.handle( + "create-organization", + async (_: IpcMainInvokeEvent, params: any) => await requestCreateOrganization(params), +); +ipcMain.handle( + "request-get-your-org-colleagues", + async (_: IpcMainInvokeEvent) => await requestGetYourOrgColleagues(), +); +ipcMain.handle("get-explore-organizations", async () => await requestExploreOrganizations()); +ipcMain.handle("get-org-data-from-api", async (_: IpcMainInvokeEvent, orgId: number) => { + const userToken = await getUserToken(); try { - const response = await fetch(`${API}/org/get?id=${orgID}`, { - method: 'GET', + const response = await fetch(`${API}/org/get?id=${orgId}`, { + method: "GET", headers: { - 'Authorization': `Bearer ${userToken}` - } + Authorization: `Bearer ${userToken}`, + }, }); - const data: any = await response.json() + const data: any = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } -}) -ipcMain.handle('remove-org', async (_: IpcMainInvokeEvent, orgID: number) => { - const userToken = await getUserToken() +}); +ipcMain.handle("remove-org", async (_: IpcMainInvokeEvent, orgId: number) => { + const userToken = await getUserToken(); const formData = new FormData(); - formData.append('id', orgID); + formData.append("id", orgId); try { const response = await fetch(`${API}/org/remove`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, - body: formData + body: formData, }); - const data: any = await response.json() + const data: any = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } -}) -ipcMain.handle('join-org', async (_: IpcMainInvokeEvent, inviteCode: string) => { - const userToken = await getUserToken() +}); +ipcMain.handle("join-org", async (_: IpcMainInvokeEvent, inviteCode: string) => { + const userToken = await getUserToken(); const formData = new FormData(); - formData.append('invite_code', inviteCode); + formData.append("invite_code", inviteCode); try { const response = await fetch(`${API}/org/join`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, body: JSON.stringify({ - "invite_code": inviteCode - }) + invite_code: inviteCode, + }), }); - const data: any = await response.json() + const data: any = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } -}) -ipcMain.handle('reset-org-invite-code', async (_: IpcMainInvokeEvent, orgid: number) => { - const userToken = await getUserToken() +}); +ipcMain.handle("reset-org-invite-code", async (_: IpcMainInvokeEvent, orgid: number) => { + const userToken = await getUserToken(); const formData = new FormData(); - formData.append('org_id', orgid); + formData.append("org_id", orgid); try { const response = await fetch(`${API}/org/resetInviteCode`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, - body: formData + body: formData, }); - const data: any = await response.json() + const data: any = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } -}) +}); ipcMain.handle("upload-org-avatar", async (_: IpcMainInvokeEvent, orgid: number) => { const userToken = await getUserToken(); @@ -122,18 +123,18 @@ ipcMain.handle("upload-org-avatar", async (_: IpcMainInvokeEvent, orgid: number) filters: [ { name: "Images", - extensions: ["png", "jpg", "jpeg", "webp"] - } - ] + extensions: ["png", "jpg", "jpeg", "webp"], + }, + ], }); const canceled = (result as any).canceled ?? false; - const filePaths: string[] = Array.isArray(result) ? result : (result as any).filePaths ?? []; + const filePaths: string[] = Array.isArray(result) ? result : ((result as any).filePaths ?? []); if (canceled || filePaths.length === 0) { return { success: false, - msg: "Selection cancelled" + msg: "Selection cancelled", }; } @@ -145,7 +146,7 @@ ipcMain.handle("upload-org-avatar", async (_: IpcMainInvokeEvent, orgid: number) const body = JSON.stringify({ orgid, - image + image, }); try { @@ -153,69 +154,67 @@ ipcMain.handle("upload-org-avatar", async (_: IpcMainInvokeEvent, orgid: number) method: "POST", headers: { Authorization: `Bearer ${userToken}`, - "Content-Type": "application/json" + "Content-Type": "application/json", }, - body + body, }); const data: any = await response.json(); return { success: data.success, - msg: data.result + msg: data.result, }; } catch (error: any) { return { success: false, - msg: error.message + msg: error.message, }; } }); -ipcMain.handle('set-github-repos', async (_: IpcMainInvokeEvent, orgid: number, repos: object) => { - const userToken = await getUserToken() +ipcMain.handle("set-github-repos", async (_: IpcMainInvokeEvent, orgid: number, repos: object) => { + const userToken = await getUserToken(); try { const response = await fetch(`${API}/org/setGithubRepos`, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${userToken}` + Authorization: `Bearer ${userToken}`, }, body: JSON.stringify({ - orgid: orgid, - repos: repos - }) + orgid, + repos, + }), }); - const data: any = await response.json() + const data: any = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } -}) -ipcMain.handle('search-orgs', async (_: IpcMainInvokeEvent, query: string) => { - const userToken = await getUserToken() +}); +ipcMain.handle("search-orgs", async (_: IpcMainInvokeEvent, query: string) => { + const userToken = await getUserToken(); try { const response = await fetch(`${API}/org/search?q=${encodeURIComponent(query)}`, { - method: 'GET', + method: "GET", headers: { - 'Authorization': `Bearer ${userToken}` - } + Authorization: `Bearer ${userToken}`, + }, }); - const data: any = await response.json() + const data: any = await response.json(); if (data.success) { - return { success: true, msg: data.result } - } else { - return { success: false, msg: data.result } + return { success: true, msg: data.result }; } + return { success: false, msg: data.result }; } catch (error) { - return { success: false, msg: error } + return { success: false, msg: error }; } -}) \ No newline at end of file +}); diff --git a/app/main/ipc/setters.ts b/app/main/ipc/setters.ts index e601d8e..a8e9ac9 100644 --- a/app/main/ipc/setters.ts +++ b/app/main/ipc/setters.ts @@ -1,17 +1,17 @@ -import { ipcMain, IpcMainInvokeEvent } from "electron" -import { getLocalAppData, readSettings, writeSettings, writeLocal } from "../helpers/requests" +import { type IpcMainInvokeEvent, ipcMain } from "electron"; +import { getLocalAppData, readSettings, writeLocal, writeSettings } from "../helpers/requests"; ipcMain.handle("set-settings", (_: IpcMainInvokeEvent, data: unknown) => { if (!data || typeof data !== "object" || Array.isArray(data)) { - return readSettings() + return readSettings(); } - return writeSettings(data as object) -}) + return writeSettings(data as object); +}); ipcMain.handle("set-local", (_: IpcMainInvokeEvent, data: unknown) => { if (!data || typeof data !== "object" || Array.isArray(data)) { - return getLocalAppData() + return getLocalAppData(); } - return writeLocal(data as object) -}) \ No newline at end of file + return writeLocal(data as object); +}); diff --git a/app/main/ipc/updaters.ts b/app/main/ipc/updaters.ts index d79ff10..088e7af 100644 --- a/app/main/ipc/updaters.ts +++ b/app/main/ipc/updaters.ts @@ -1,6 +1,6 @@ -import { ipcMain, IpcMainInvokeEvent } from "electron"; +import { type IpcMainInvokeEvent, ipcMain } from "electron"; import { updateLocalAppData } from "../helpers/requests"; -ipcMain.on('update-local-app-data', async (_: IpcMainInvokeEvent, data: object) => { - updateLocalAppData(data) -}); \ No newline at end of file +ipcMain.on("update-local-app-data", async (_: IpcMainInvokeEvent, data: object) => { + updateLocalAppData(data); +}); diff --git a/app/main/main.ts b/app/main/main.ts index 17a2798..25fb517 100644 --- a/app/main/main.ts +++ b/app/main/main.ts @@ -1,54 +1,54 @@ -import type { IpcMainEvent } from "electron" - -import { app, BrowserWindow, screen, ipcMain, shell } from "electron" -import path from "node:path" -import fs from "node:fs" +import fs from "node:fs"; +import path from "node:path"; +import process from "node:process"; +import type { IpcMainEvent } from "electron"; +import { app, BrowserWindow, ipcMain, screen, shell } from "electron"; import { GlobalKeyboardListener } from "node-global-key-listener"; const v = new GlobalKeyboardListener(); -const bus = require("../../helpers/eventBus") - -const { verifyToken } = require("../auth") - -const { HTML_PATH, JSON_PATH } = require("../main/helpers/paths.js") - -let mainWindow: any -let workSeconds: number = 0 - -require("../sandbox/sandbox") -require("../../helpers/getPython") -require("../auth") -require("../electron/live-server") -require("./runtime/runtimeHandler") -require("./tools/diagnostics") -require("./tools/js-ts/ast") -require("./tools/go/ast") - -require("./ipc/filesWork") -require("./ipc/api") -require("./ipc/getters") -require("./ipc/setters") -require("./ipc/updaters") -require("./ipc/misc") -require("./ipc/organizations") -require("./ipc/bugs") -require("./ipc/suggest") +const bus = require("../../helpers/eventBus"); + +const { verifyToken } = require("../auth"); + +const { HTML_PATH, JSON_PATH } = require("../main/helpers/paths.js"); + +let mainWindow: any; +let workSeconds = 0; + +require("../sandbox/sandbox"); +require("../../helpers/getPython"); +require("../auth"); +require("../electron/live-server"); +require("./runtime/runtimeHandler"); +require("./tools/diagnostics"); +require("./tools/js-ts/ast"); +require("./tools/go/ast"); + +require("./ipc/filesWork"); +require("./ipc/api"); +require("./ipc/getters"); +require("./ipc/setters"); +require("./ipc/updaters"); +require("./ipc/misc"); +require("./ipc/organizations"); +require("./ipc/bugs"); +require("./ipc/suggest"); // ext -require("../sandbox/regs/language") -require("../sandbox/regs/docs") -require("../sandbox/regs/filenames") -require("../sandbox/regs/fileExtensions") -require("../sandbox/regs/templates") +require("../sandbox/regs/language"); +require("../sandbox/regs/docs"); +require("../sandbox/regs/filenames"); +require("../sandbox/regs/fileExtensions"); +require("../sandbox/regs/templates"); console.log("APP PATH:", app.getAppPath()); -const { terminalManager } = require("../main/helpers/terminal.js") +const { terminalManager } = require("../main/helpers/terminal.js"); const { createDebuggerWindow } = require("../../helpers/debuggerWindow/debuggerWindow.js"); -const { createSplashWindow, updateSplash } = require('../splash/splash.js'); -const { - readSettings, +const { createSplashWindow, updateSplash } = require("../splash/splash.js"); +const { + readSettings, writeSettings, ensureLocalJson, ensureSettingsJson, @@ -57,43 +57,40 @@ const { getSettingsData, getAppIcon, checkStatus, -} = require("../main/helpers/requests.js") +} = require("../main/helpers/requests.js"); -const { spawnNotification, notifications } = require("../notifications/notifications.js") +const { spawnNotification, notifications } = require("../notifications/notifications.js"); -const { - selectFile, - selectFolder, -} = require("../main/helpers/os.js"); +const { selectFile, selectFolder } = require("../main/helpers/os.js"); -const { APP_PATH } = require('../main/helpers/paths.js'); +const { APP_PATH } = require("../main/helpers/paths.js"); -console.log(`App started on ${process.arch} system`) +console.log(`App started on ${process.arch} system`); async function createWindow() { if (!fs.existsSync(JSON_PATH)) { fs.mkdirSync(JSON_PATH, { recursive: true }); } - + ensureLocalJson(); ensureLocalBugs(); ensureSettingsJson(); const localData = getLocalAppData(); - const settingsData = getSettingsData() + const settingsData = getSettingsData(); const appIcon = await getAppIcon(); const isPackaged = app.isPackaged; const primaryDisplay = screen.getPrimaryDisplay(); const { width, height } = primaryDisplay.workAreaSize; - let dev = false - let splash: InstanceType | null = null + let dev = false; + let splash: InstanceType | null = null; - if("app" in settingsData && settingsData.app.splashScreen) { - splash = await createSplashWindow() + if ("app" in settingsData && settingsData.app.splashScreen) { + splash = await createSplashWindow(); } - if(process.argv.includes('--d')) dev = true + if (process.argv.includes("--d")) dev = true; mainWindow = new BrowserWindow({ width, @@ -103,75 +100,80 @@ async function createWindow() { backgroundColor: "#0a0a0a", webPreferences: { preload: path.join(APP_PATH, "dist", "preload.js"), - contextIsolation: true + contextIsolation: true, }, - icon: appIcon + icon: appIcon, }); mainWindow.webContents.setWindowOpenHandler(({ url }: { url: string }) => { shell.openExternal(url); - return { action: 'deny' }; + return { action: "deny" }; }); - mainWindow.webContents.on('did-finish-load', () => { - if(splash) splash.destroy(); - mainWindow.maximize() + mainWindow.webContents.on("did-finish-load", () => { + if (splash) splash.destroy(); + mainWindow.maximize(); mainWindow.show(); - }) + }); mainWindow.on("closed", () => { for (const win of notifications) { - if (win && !win.isDestroyed()) win.close() + if (win && !win.isDestroyed()) win.close(); } - }) + }); - if(splash) updateSplash("Waiting for connect...") + if (splash) updateSplash("Waiting for connect..."); // if offline mode (w/o account) then dont check status if (localData.nonAccountMode) { await mainWindow.loadFile(path.join(HTML_PATH, "index.html")); - } - else { - checkStatus({ updateSplash: updateSplash }) + } else { + checkStatus({ updateSplash }) .then(async () => { - if (!localData.token) { - await mainWindow.loadFile(path.join(HTML_PATH, "login.html")); - } - else { - let userCheckLogin = await verifyToken(localData.token); + if (localData.token) { + const userCheckLogin = await verifyToken(localData.token); if (userCheckLogin.success) { await mainWindow.loadFile(path.join(HTML_PATH, "index.html")); - } - else { + } else { await mainWindow.loadFile(path.join(HTML_PATH, "login.html")); - mainWindow.webContents.send("auth-msg", { type: "error", content: userCheckLogin.result }) + mainWindow.webContents.send("auth-msg", { + type: "error", + content: userCheckLogin.result, + }); } + } else { + await mainWindow.loadFile(path.join(HTML_PATH, "login.html")); } - v.addListener(function (e: any, down: any) { - if (mainWindow && mainWindow.isFocused() && e.state == "DOWN" && e.name == "S" && down["LEFT CTRL"]) { + v.addListener((e: any, down: any) => { + if ( + mainWindow && + mainWindow.isFocused() && + e.state == "DOWN" && + e.name == "S" && + down["LEFT CTRL"] + ) { mainWindow.webContents.send("keyboard_action", { - type: "saved" + type: "saved", }); } }); }) .catch((err: TypeError) => { - updateSplash(`Error: ${err.message}. Please report this error to the developer and try again later`, true) + updateSplash( + `Error: ${err.message}. Please report this error to the developer and try again later`, + true, + ); }); } - ipcMain.handle("request-file-open", () => { - return selectFile(mainWindow) - }) - ipcMain.handle("request-folder-open", () => { - return selectFolder(mainWindow) - }) + ipcMain.handle("request-file-open", () => selectFile(mainWindow)); + ipcMain.handle("request-folder-open", () => selectFolder(mainWindow)); ipcMain.on("main-ready", (event: IpcMainEvent) => { bus.emit("main-ready", event.sender); - }) + }); ipcMain.on("custom-language-registration-ready", () => { - mainWindow.webContents.send("custom-language-registered") - }) + mainWindow.webContents.send("custom-language-registered"); + }); ipcMain.on("close", () => { terminalManager.killProcessTree(true); @@ -191,11 +193,10 @@ async function createWindow() { ipcMain.on("set-app-title", (_, title) => { if (mainWindow) { - if(title != undefined) { - mainWindow.setTitle(`${title} - CodeMotion IDE`) - } - else { - mainWindow.setTitle(`CodeMotion IDE`) + if (title == undefined) { + mainWindow.setTitle("CodeMotion IDE"); + } else { + mainWindow.setTitle(`${title} - CodeMotion IDE`); } } }); @@ -204,51 +205,51 @@ async function createWindow() { terminalManager.killProcessTree(true); terminalManager.cleanupInputHandler(); app.relaunch(); - app.quit(); + app.quit(); }); ipcMain.handle("create-debugger-window", async () => { - createDebuggerWindow(mainWindow) - return true - }) + createDebuggerWindow(mainWindow); + return true; + }); // send app close. Example: close all notification windows - app.on('window-all-closed', () => { + app.on("window-all-closed", () => { bus.emit("main-closed", mainWindow); - }) + }); return { mainWindow, splash }; } ipcMain.on("spawn-notification", (_: IpcMainEvent, data: any) => { - spawnNotification(data) -}) + spawnNotification(data); +}); app.whenReady().then(createWindow); -app.on('before-quit', () => { +app.on("before-quit", () => { terminalManager.killProcessTree(true); terminalManager.cleanupInputHandler(); }); setInterval(() => { - workSeconds += 0.1 -}, 100) + workSeconds += 0.1; +}, 100); -app.on('window-all-closed', () => { +app.on("window-all-closed", () => { terminalManager.killProcessTree(true); terminalManager.cleanupInputHandler(); - if (process.platform !== 'darwin') app.quit(); + if (process.platform !== "darwin") app.quit(); - const settings = readSettings() + const settings = readSettings(); - if("app" in settings) { - if("workSeconds" in settings.app) { - let seconds = settings.app.workSeconds - writeSettings({ app: { workSeconds: Math.round((workSeconds + seconds) * 10) / 10 }}) + if ("app" in settings) { + if ("workSeconds" in settings.app) { + const seconds = settings.app.workSeconds; + writeSettings({ app: { workSeconds: Math.round((workSeconds + seconds) * 10) / 10 } }); } - if("workSecondsSession" in settings.app) { - writeSettings({ app: { workSecondsSession: Math.round(workSeconds * 10) / 10 }}) + if ("workSecondsSession" in settings.app) { + writeSettings({ app: { workSecondsSession: Math.round(workSeconds * 10) / 10 } }); } } }); diff --git a/app/main/payloads.ts b/app/main/payloads.ts index ef5a0ff..38d340a 100644 --- a/app/main/payloads.ts +++ b/app/main/payloads.ts @@ -1,9 +1,9 @@ export type SaveContentPayload = { - filename: string - content: string -} + filename: string; + content: string; +}; export type RunPythonPayload = { - code: string, - filePath: string, - useEmbed: boolean -} \ No newline at end of file + code: string; + filePath: string; + useEmbed: boolean; +}; diff --git a/app/main/preload.ts b/app/main/preload.ts index e6e3422..4ce038c 100644 --- a/app/main/preload.ts +++ b/app/main/preload.ts @@ -1,12 +1,14 @@ -import { RunPythonPayload, SaveContentPayload } from "./payloads"; +import type { RunPythonPayload, SaveContentPayload } from "./payloads"; -const { contextBridge, ipcRenderer } = require('electron'); +const { contextBridge, ipcRenderer } = require("electron"); let isRegisteredCustomLanguageRegistration = false; -contextBridge.exposeInMainWorld('electron', { - readDirTree: (rootPath: any, options = {}) => ipcRenderer.invoke('readDirTree', rootPath, options), - readFileContent: (filePath: any, encoding = 'utf8') => ipcRenderer.invoke('readFileContent', filePath, encoding), +contextBridge.exposeInMainWorld("electron", { + readDirTree: (rootPath: any, options = {}) => + ipcRenderer.invoke("readDirTree", rootPath, options), + readFileContent: (filePath: any, encoding = "utf8") => + ipcRenderer.invoke("readFileContent", filePath, encoding), getUserPcInfo: () => ipcRenderer.invoke("get-user-pc-info"), getPackageData: () => ipcRenderer.invoke("get-package-data"), getLocalBugsData: () => ipcRenderer.invoke("get-local-bugs-data"), @@ -24,8 +26,10 @@ contextBridge.exposeInMainWorld('electron', { createOrganization: (params: any) => ipcRenderer.invoke("create-organization", params), requestExploreOrganizations: () => ipcRenderer.invoke("get-explore-organizations"), requestRecoveryCode: (email: string) => ipcRenderer.invoke("request-recovery-code", email), - verifyRecoveryCode: (email: string, code: string) => ipcRenderer.invoke("verify-recovery-code", email, code), - resetPassword: (recoveryToken: string, newPassword: string) => ipcRenderer.invoke("reset-password", recoveryToken, newPassword), + verifyRecoveryCode: (email: string, code: string) => + ipcRenderer.invoke("verify-recovery-code", email, code), + resetPassword: (recoveryToken: string, newPassword: string) => + ipcRenderer.invoke("reset-password", recoveryToken, newPassword), createNotification: (data: any) => ipcRenderer.send("spawn-notification", data), @@ -34,9 +38,11 @@ contextBridge.exposeInMainWorld('electron', { setNonAccountMode: (value: boolean) => ipcRenderer.invoke("set-non-account-mode", value), setAppTitle: (title: string) => ipcRenderer.send("set-app-title", title), - askToSaveNewFile: (properties: SaveContentPayload) => ipcRenderer.invoke("ask-to-save-content", properties), + askToSaveNewFile: (properties: SaveContentPayload) => + ipcRenderer.invoke("ask-to-save-content", properties), - keyboardAction: (callback: any) => ipcRenderer.on("keyboard_action", (_: any, data: any) => callback(data)), + keyboardAction: (callback: any) => + ipcRenderer.on("keyboard_action", (_: any, data: any) => callback(data)), getCurrentUserDataFromAPI: () => ipcRenderer.invoke("get-user-data-from-api"), getUser: (userid: number) => ipcRenderer.invoke("get-user", userid), @@ -45,7 +51,8 @@ contextBridge.exposeInMainWorld('electron', { joinOrg: (inviteCode: string) => ipcRenderer.invoke("join-org", inviteCode), resetOrgInviteCode: (orgid: number) => ipcRenderer.invoke("reset-org-invite-code", orgid), uploadOrgAvatar: (orgid: number) => ipcRenderer.invoke("upload-org-avatar", orgid), - setOrgGithubRepos: (orgid: number, repos: object) => ipcRenderer.invoke("set-github-repos", orgid, repos), + setOrgGithubRepos: (orgid: number, repos: object) => + ipcRenderer.invoke("set-github-repos", orgid, repos), searchOrg: (query: string) => ipcRenderer.invoke("search-orgs", query), close: () => ipcRenderer.send("close"), @@ -55,7 +62,8 @@ contextBridge.exposeInMainWorld('electron', { getAllFilenamesIcons: () => ipcRenderer.invoke("get-all-filenames-app-icons"), login: (email: string, password: string) => ipcRenderer.invoke("login", email, password), - register: (username: string, email: string, password: string, passwordConfirm: string) => ipcRenderer.invoke("register", username, email, password, passwordConfirm), + register: (username: string, email: string, password: string, passwordConfirm: string) => + ipcRenderer.invoke("register", username, email, password, passwordConfirm), isLoggedIn: () => ipcRenderer.invoke("is-logged-in"), logout: () => ipcRenderer.invoke("logout"), @@ -67,7 +75,8 @@ contextBridge.exposeInMainWorld('electron', { revealInFileExplorer: (path: string) => ipcRenderer.invoke("reveal-in-file-explorer", path), createFile: (path: string) => ipcRenderer.invoke("create-file", path), createFolder: (path: string) => ipcRenderer.invoke("create-folder", path), - renamePath: (oldPath: string, newPath: string) => ipcRenderer.invoke("rename-path", oldPath, newPath), + renamePath: (oldPath: string, newPath: string) => + ipcRenderer.invoke("rename-path", oldPath, newPath), setLocal: (data: any) => ipcRenderer.invoke("set-local", data), getLocal: () => ipcRenderer.invoke("get-app-local"), @@ -90,41 +99,46 @@ contextBridge.exposeInMainWorld('electron', { killProcess: () => ipcRenderer.send("terminal-kill"), cleanupTerminal: () => ipcRenderer.send("terminal-cleanup"), onCommandResult: (callback: any) => { - const listener = (event: any, result: any) => callback(result) - ipcRenderer.on("terminal-result", listener) - return () => ipcRenderer.removeListener("terminal-result", listener) + const listener = (event: any, result: any) => callback(result); + ipcRenderer.on("terminal-result", listener); + return () => ipcRenderer.removeListener("terminal-result", listener); }, requestExtensions: () => ipcRenderer.invoke("request-extensions"), requestExtension: (name: string) => ipcRenderer.invoke("request-extension", name), createDebuggerWindow: () => ipcRenderer.invoke("create-debugger-window"), - loadExtensionModule: (name: string, version: string) => ipcRenderer.invoke("load-module", name, version), + loadExtensionModule: (name: string, version: string) => + ipcRenderer.invoke("load-module", name, version), - readFile: (path: string, parentPath: string) => ipcRenderer.invoke("read-file", path, parentPath), + readFile: (path: string, parentPath: string) => + ipcRenderer.invoke("read-file", path, parentPath), removeByPath: (path: string) => ipcRenderer.invoke("remove-by-path", path), sendDebuggerData: (data: any) => ipcRenderer.send("debugger-data", data), - onDebuggerReady: () => { - return new Promise((resolve) => { + onDebuggerReady: () => + new Promise((resolve) => { const handler = (_: any, args: any[]) => { - resolve(args) - ipcRenderer.removeListener("debugger-ready", handler) - } + resolve(args); + ipcRenderer.removeListener("debugger-ready", handler); + }; - ipcRenderer.on("debugger-ready", handler) - }) - }, + ipcRenderer.on("debugger-ready", handler); + }), mainReady: () => ipcRenderer.send("main-ready"), getPython: () => ipcRenderer.invoke("get-python-info"), getDirname: () => ipcRenderer.invoke("get-dirname"), getPlatform: () => ipcRenderer.invoke("get-platform"), - typescriptDiagnostic: (code: string, language?: string) => ipcRenderer.invoke("typescript-diagnostic", code, language), - javascriptDiagnostic: (code: string, language?: string) => ipcRenderer.invoke("javascript-diagnostic", code, language), - javascriptAST: (code: string, language?: string) => ipcRenderer.invoke("javascript-ast", code, language), - typescriptAST: (code: string, language?: string) => ipcRenderer.invoke("typescript-ast", code, language), + typescriptDiagnostic: (code: string, language?: string) => + ipcRenderer.invoke("typescript-diagnostic", code, language), + javascriptDiagnostic: (code: string, language?: string) => + ipcRenderer.invoke("javascript-diagnostic", code, language), + javascriptAST: (code: string, language?: string) => + ipcRenderer.invoke("javascript-ast", code, language), + typescriptAST: (code: string, language?: string) => + ipcRenderer.invoke("typescript-ast", code, language), golangAST: (code: string) => ipcRenderer.invoke("golang-ast", code), sendCodeSuggestRequest: (data: any) => ipcRenderer.send("code-suggest-request", data), @@ -139,108 +153,131 @@ contextBridge.exposeInMainWorld('electron', { ext: { ui: { theme: { - onRegister: (callback: any) => - ipcRenderer.on("new-theme-register", (event: string, name: string, data: any) => callback(name, data)), + onRegister: (callback: any) => + ipcRenderer.on("new-theme-register", (event: string, name: string, data: any) => + callback(name, data), + ), }, css: { - onLoad: (callback: any) => - ipcRenderer.on("load-css", (event: any, name: any, content: any) => callback(name, content)), + onLoad: (callback: any) => + ipcRenderer.on("load-css", (event: any, name: any, content: any) => + callback(name, content), + ), }, element: { - onCreate: (callback: any) => - ipcRenderer.on("extension-create-element", (event: any, data: object) => callback(data)), - onMod: (callback: any) => - ipcRenderer.on("extension-mod-element", (event: any, data: object) => callback(data)), - sendTo: (data: object) => - ipcRenderer.send("extension-send-element", data) - } + onCreate: (callback: any) => + ipcRenderer.on("extension-create-element", (event: any, data: object) => + callback(data), + ), + onMod: (callback: any) => + ipcRenderer.on("extension-mod-element", (event: any, data: object) => + callback(data), + ), + sendTo: (data: object) => ipcRenderer.send("extension-send-element", data), + }, }, editor: { language: { - register: (data: any) => - ipcRenderer.send("language-register", data), - onRegister: (callback: any) => - ipcRenderer.on("on-language-register", (event: any, data: any) => callback(data)), - onIconsRegister: (callback: any) => - ipcRenderer.on("new-language-icons-register", (event: any, data: any) => callback(data)), - onChangeHLRules: (callback: any) => - ipcRenderer.on("on-editor-change-new-hl-rules", (event: any, data: any) => callback(data)), + register: (data: any) => ipcRenderer.send("language-register", data), + onRegister: (callback: any) => + ipcRenderer.on("on-language-register", (event: any, data: any) => + callback(data), + ), + onIconsRegister: (callback: any) => + ipcRenderer.on("new-language-icons-register", (event: any, data: any) => + callback(data), + ), + onChangeHLRules: (callback: any) => + ipcRenderer.on("on-editor-change-new-hl-rules", (event: any, data: any) => + callback(data), + ), }, api: { - onReplace: (callback: any) => - ipcRenderer.on("editor-api-replace", (event: any, data: any) => callback(data)), + onReplace: (callback: any) => + ipcRenderer.on("editor-api-replace", (event: any, data: any) => callback(data)), }, dir: { - onIconsRegister: (callback: any) => - ipcRenderer.on("new-dir-icon-register", (event: any, data: any) => callback(data)), + onIconsRegister: (callback: any) => + ipcRenderer.on("new-dir-icon-register", (event: any, data: any) => + callback(data), + ), }, docs: { - register: (data: any) => - ipcRenderer.send("docs-register", data), - onRegister: (callback: any) => - ipcRenderer.on("new-documentation-register", (event: any, data: any) => callback(data)), + register: (data: any) => ipcRenderer.send("docs-register", data), + onRegister: (callback: any) => + ipcRenderer.on("new-documentation-register", (event: any, data: any) => + callback(data), + ), }, filenames: { - register: (data: any) => - ipcRenderer.send("filenames-register", data), + register: (data: any) => ipcRenderer.send("filenames-register", data), onRegister: (callback: any) => - ipcRenderer.on("new-filenames-register", (event: any, data: any) => callback(data)), + ipcRenderer.on("new-filenames-register", (event: any, data: any) => + callback(data), + ), }, fileExtensions: { - register: (data: any) => - ipcRenderer.send("file-extensions-register", data), + register: (data: any) => ipcRenderer.send("file-extensions-register", data), onRegister: (callback: any) => - ipcRenderer.on("new-file-extensions-register", (event: any, data: any) => callback(data)), + ipcRenderer.on("new-file-extensions-register", (event: any, data: any) => + callback(data), + ), }, templates: { - register: (data: any) => - ipcRenderer.send("templates-register", data), + register: (data: any) => ipcRenderer.send("templates-register", data), onRegister: (callback: any) => - ipcRenderer.on("new-templates-register", (event: any, data: any) => callback(data)), - } + ipcRenderer.on("new-templates-register", (event: any, data: any) => + callback(data), + ), + }, }, app: { - onNotification: (callback: any) => - ipcRenderer.on("extension-notification", (event: any, name: any, data: any) => callback(name, data)), - onLog: (callback: any) => + onNotification: (callback: any) => + ipcRenderer.on("extension-notification", (event: any, name: any, data: any) => + callback(name, data), + ), + onLog: (callback: any) => ipcRenderer.on("extension-log", (event: any, data: any) => callback(data)), - onAudioPlay: (callback: any) => + onAudioPlay: (callback: any) => ipcRenderer.on("extension-play-sound", (event: any, data: any) => callback(data)), onLocalizationRegister: (callback: any) => - ipcRenderer.on("extension-localization-register", (event: any, data: any) => callback(data)), - } + ipcRenderer.on("extension-localization-register", (event: any, data: any) => + callback(data), + ), + }, }, - runExtension: (code: string, permissions: object, meta: object) => ipcRenderer.invoke("run-extension", code, permissions, meta), - - onCustomLanguageRegistration: () => { - return new Promise((resolve) => { + runExtension: (code: string, permissions: object, meta: object) => + ipcRenderer.invoke("run-extension", code, permissions, meta), + + onCustomLanguageRegistration: () => + new Promise((resolve) => { if (isRegisteredCustomLanguageRegistration) { - resolve(null) - return + resolve(null); + return; } ipcRenderer.once("custom-language-registered", () => { - isRegisteredCustomLanguageRegistration = true - resolve(null) - }) - }) - }, + isRegisteredCustomLanguageRegistration = true; + resolve(null); + }); + }), sendCustomLanguageRegistrationReady: () => { - ipcRenderer.send("custom-language-registration-ready") + ipcRenderer.send("custom-language-registration-ready"); }, - + triggers: { sendFileOpened: (data: any) => ipcRenderer.send("file-opened-event", data), sendEditorChanged: (data: any) => ipcRenderer.send("editor-changed-event", data), sendEditorClicked: (data: any) => ipcRenderer.send("editor-clicked-event", data), }, - // + // - onAuthMsg: (callback: any) => ipcRenderer.on("auth-msg", (event: any, data: any) => callback(data)), + onAuthMsg: (callback: any) => + ipcRenderer.on("auth-msg", (event: any, data: any) => callback(data)), sendAuthMsg: (data: any) => ipcRenderer.send("auth-msg", data), - + on: (event: any, msg: any) => ipcRenderer.on(event, msg), oncb: (event: any, cb: any) => ipcRenderer.on(event, (_: any, data: any) => cb(data)), }); diff --git a/app/main/runtime/runtimeHandler.ts b/app/main/runtime/runtimeHandler.ts index aa9a3d9..5b8e98a 100644 --- a/app/main/runtime/runtimeHandler.ts +++ b/app/main/runtime/runtimeHandler.ts @@ -1,185 +1,187 @@ -import { ipcMain, IpcMainInvokeEvent, app } from "electron" -import { spawn, ChildProcessWithoutNullStreams } from "node:child_process" -import fs from "fs" -import path from "node:path" -import { RunPythonPayload } from "../payloads" +import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process"; +import path from "node:path"; +import process from "node:process"; +import { app, type IpcMainInvokeEvent, ipcMain } from "electron"; +import fs from "fs"; +import type { RunPythonPayload } from "../payloads"; type RunPythonResult = | { - type: "file_not_found" | "no_input" | "python_not_found" | "timeout" | "spawn_error" | "internal_error" - result: string - } + type: + | "file_not_found" + | "no_input" + | "python_not_found" + | "timeout" + | "spawn_error" + | "internal_error"; + result: string; + } | { - type: "success" - stdout: string - stderr: string - exitCode: number - file: string - interpreter: string - } + type: "success"; + stdout: string; + stderr: string; + exitCode: number; + file: string; + interpreter: string; + } | { - type: "error" - stdout: string - stderr: string - exitCode: number - file: string - interpreter: string - } + type: "error"; + stdout: string; + stderr: string; + exitCode: number; + file: string; + interpreter: string; + }; ipcMain.handle( "run-python-code", - ( - _: IpcMainInvokeEvent, - data: RunPythonPayload - ): Promise => { + (_: IpcMainInvokeEvent, data: RunPythonPayload): Promise => { return new Promise((resolve) => { - let runPath: string - let isTempFile = false - let resolved = false + let runPath: string; + let isTempFile = false; + let resolved = false; - const filePath = data.filePath - const code = data.code - const useEmbed = data.useEmbed + const filePath = data.filePath; + const code = data.code; + const useEmbed = data.useEmbed; - const tempDir = path.join(app.getAppPath(), "temp") + const tempDir = path.join(app.getAppPath(), "temp"); // Caused by: embedded Python runtime ships as .exe // On macOS/Linux this path is invalid and spawn fails silently. // We select the correct binary name per platform, falling back // to system-installed python3 when embedded is unavailable. - const pythonBinary = process.platform === 'win32' ? 'python.exe' : 'python3' + const pythonBinary = process.platform === "win32" ? "python.exe" : "python3"; const embeddedPy = app.isPackaged ? path.join(process.resourcesPath, "runtime", "python", pythonBinary) - : path.join(__dirname, "..", "runtime", "python", pythonBinary) + : path.join(__dirname, "..", "runtime", "python", pythonBinary); const cleanup = (): void => { if (isTempFile && runPath && fs.existsSync(runPath)) { try { - fs.unlinkSync(runPath) + fs.unlinkSync(runPath); } catch {} } - } + }; const finish = (result: RunPythonResult): void => { - if (resolved) return - resolved = true - cleanup() - resolve(result) - } + if (resolved) return; + resolved = true; + cleanup(); + resolve(result); + }; const trySpawn = ( command: string, args: string[], - options: any = {} + options: any = {}, ): ChildProcessWithoutNullStreams | null => { try { - return spawn(command, args, options) + return spawn(command, args, options); } catch { - return null + return null; } - } + }; try { if (filePath) { if (!fs.existsSync(filePath)) { return finish({ type: "file_not_found", - result: `File not found: ${filePath}` - }) + result: `File not found: ${filePath}`, + }); } - runPath = filePath + runPath = filePath; } else if (code) { if (!fs.existsSync(tempDir)) { - fs.mkdirSync(tempDir, { recursive: true }) + fs.mkdirSync(tempDir, { recursive: true }); } - runPath = path.join(tempDir, `temp-${Date.now()}.py`) - fs.writeFileSync(runPath, code, "utf8") - isTempFile = true + runPath = path.join(tempDir, `temp-${Date.now()}.py`); + fs.writeFileSync(runPath, code, "utf8"); + isTempFile = true; } else { return finish({ type: "no_input", - result: "No code or filePath provided" - }) + result: "No code or filePath provided", + }); } - let pyCommand: string - let pyArgs: string[] = [runPath] + let pyCommand: string; + const pyArgs: string[] = [runPath]; if (useEmbed) { if (!fs.existsSync(embeddedPy)) { return finish({ type: "python_not_found", - result: "Embedded Python not found" - }) + result: "Embedded Python not found", + }); } - pyCommand = embeddedPy + pyCommand = embeddedPy; } else { - pyCommand = "python" + pyCommand = "python"; } let py = trySpawn(pyCommand, pyArgs, { - cwd: path.dirname(runPath) - }) + cwd: path.dirname(runPath), + }); - if (!py && !useEmbed) { - pyCommand = process.platform === 'win32' ? 'py' : 'python3' + if (!(py || useEmbed)) { + pyCommand = process.platform === "win32" ? "py" : "python3"; py = trySpawn(pyCommand, pyArgs, { - cwd: path.dirname(runPath) - }) + cwd: path.dirname(runPath), + }); } if (!py) { return finish({ type: "python_not_found", - result: useEmbed - ? "Embedded Python not found" - : "System Python not found" - }) + result: useEmbed ? "Embedded Python not found" : "System Python not found", + }); } - let stdout = "" - let stderr = "" + let stdout = ""; + let stderr = ""; const timeout = setTimeout(() => { - py!.kill() + py!.kill(); finish({ type: "timeout", - result: "Execution timed out" - }) - }, 10000) + result: "Execution timed out", + }); + }, 10_000); py.stdout.on("data", (data: Buffer) => { - stdout += data.toString() - }) + stdout += data.toString(); + }); py.stderr.on("data", (data: Buffer) => { - stderr += data.toString() - }) + stderr += data.toString(); + }); py.on("error", () => { - clearTimeout(timeout) + clearTimeout(timeout); if (!useEmbed && pyCommand === "python") { - const fallback = process.platform === 'win32' ? 'py' : 'python3' + const fallback = process.platform === "win32" ? "py" : "python3"; py = spawn(fallback, pyArgs, { - cwd: path.dirname(runPath) - }) - return + cwd: path.dirname(runPath), + }); + return; } finish({ type: "spawn_error", - result: "Failed to start Python process" - }) - }) + result: "Failed to start Python process", + }); + }); py.on("close", (exitCode: number | null) => { - clearTimeout(timeout) + clearTimeout(timeout); finish({ type: exitCode === 0 ? "success" : "error", @@ -187,19 +189,17 @@ ipcMain.handle( stderr, exitCode: exitCode ?? -1, file: runPath, - interpreter: pyCommand - }) - }) - + interpreter: pyCommand, + }); + }); } catch (err: unknown) { - const message = - err instanceof Error ? err.message : String(err) + const message = err instanceof Error ? err.message : String(err); finish({ type: "internal_error", - result: message - }) + result: message, + }); } - }) - } -) \ No newline at end of file + }); + }, +); diff --git a/app/main/textmate/compile.ts b/app/main/textmate/compile.ts index f5443e7..2f971eb 100644 --- a/app/main/textmate/compile.ts +++ b/app/main/textmate/compile.ts @@ -1,15 +1,15 @@ interface Language { - id: string, - keywords?: string[], - comment?: string, - operators?: string[], - types?: string[] + id: string; + keywords?: string[]; + comment?: string; + operators?: string[]; + types?: string[]; } interface TextMateProperties { - scopeName: string, - patterns: object[], - repository: Record + scopeName: string; + patterns: object[]; + repository: Record; } export function fromJSONToTextMate(language: Language): TextMateProperties { @@ -19,37 +19,43 @@ export function fromJSONToTextMate(language: Language): TextMateProperties { if (language.comment) { repository.comment = { match: language.comment, - name: "comment.line" + name: "comment.line", }; patterns.push({ include: "#comment" }); } if (language.keywords?.length) { repository.keywords = { - patterns: [{ - match: `\\b(${language.keywords.join("|")})\\b`, - name: "keyword.control" - }] + patterns: [ + { + match: `\\b(${language.keywords.join("|")})\\b`, + name: "keyword.control", + }, + ], }; patterns.push({ include: "#keywords" }); } if (language.operators?.length) { repository.operators = { - patterns: [{ - match: `\\b(${language.operators.join("|")})\\b`, - name: "keyword.operator" - }] + patterns: [ + { + match: `\\b(${language.operators.join("|")})\\b`, + name: "keyword.operator", + }, + ], }; patterns.push({ include: "#operators" }); } if (language.types?.length) { repository.types = { - patterns: [{ - match: `\\b(${language.types.join("|")})\\b`, - name: "entity.name.type" - }] + patterns: [ + { + match: `\\b(${language.types.join("|")})\\b`, + name: "entity.name.type", + }, + ], }; patterns.push({ include: "#types" }); } @@ -57,6 +63,6 @@ export function fromJSONToTextMate(language: Language): TextMateProperties { return { scopeName: `source.${language.id}`, patterns, - repository + repository, }; -} \ No newline at end of file +} diff --git a/app/main/tools/diagnostics.ts b/app/main/tools/diagnostics.ts index 413b84f..2f5890e 100644 --- a/app/main/tools/diagnostics.ts +++ b/app/main/tools/diagnostics.ts @@ -1,93 +1,105 @@ -import { ipcMain, IpcMainInvokeEvent } from "electron" -import { Worker } from "worker_threads" -import path from "path" +import { type IpcMainInvokeEvent, ipcMain } from "electron"; +import path from "path"; +import { Worker } from "worker_threads"; -type DiagnosticResult = unknown[] -type DiagnosticLanguage = "js" | "jsx" | "ts" | "tsx" | "dts" +type DiagnosticResult = unknown[]; +type DiagnosticLanguage = "js" | "jsx" | "ts" | "tsx" | "dts"; -type WorkerKey = "js" | "ts" +type WorkerKey = "js" | "ts"; -type WorkerMap = Record -type PendingMap = Record void>> -type WorkerResponse = { id?: number, diagnostics?: DiagnosticResult } +type WorkerMap = Record; +type PendingMap = Record void>>; +type WorkerResponse = { id?: number; diagnostics?: DiagnosticResult }; -let nextRequestId = 0 +let nextRequestId = 0; function normalizeLanguage(language: unknown, fallback: DiagnosticLanguage): DiagnosticLanguage { - const normalized = String(language || "").trim().toLowerCase().replace(/^\./, "") + const normalized = String(language || "") + .trim() + .toLowerCase() + .replace(/^\./, ""); if (["js", "jsx", "ts", "tsx", "dts"].includes(normalized)) { - return normalized as DiagnosticLanguage + return normalized as DiagnosticLanguage; } - if (["mjs", "cjs", "es6"].includes(normalized)) return "js" - if (["mts", "cts"].includes(normalized)) return "ts" - return fallback + if (["mjs", "cjs", "es6"].includes(normalized)) return "js"; + if (["mts", "cts"].includes(normalized)) return "ts"; + return fallback; } function createWorker(): Worker { - return new Worker(path.join(__dirname, "js-ts/diagnosticWorker.js")) + return new Worker(path.join(__dirname, "js-ts/diagnosticWorker.js")); } const workers: WorkerMap = { js: createWorker(), ts: createWorker(), -} +}; const pending: PendingMap = { js: new Map(), ts: new Map(), -} - -function resolvePending(workerKey: WorkerKey, id: number | undefined, diagnostics: DiagnosticResult) { - if (id === undefined) return - const resolve = pending[workerKey].get(id) - if (!resolve) return - - pending[workerKey].delete(id) - resolve(diagnostics) +}; + +function resolvePending( + workerKey: WorkerKey, + id: number | undefined, + diagnostics: DiagnosticResult, +) { + if (id === undefined) return; + const resolve = pending[workerKey].get(id); + if (!resolve) return; + + pending[workerKey].delete(id); + resolve(diagnostics); } function rejectAllPending(workerKey: WorkerKey) { - for (const resolve of pending[workerKey].values()) resolve([]) - pending[workerKey].clear() + for (const resolve of pending[workerKey].values()) resolve([]); + pending[workerKey].clear(); } for (const workerKey of ["js", "ts"] as const) { workers[workerKey].on("message", (response: WorkerResponse) => { - resolvePending(workerKey, response?.id, response?.diagnostics || []) - }) + resolvePending(workerKey, response?.id, response?.diagnostics || []); + }); workers[workerKey].on("error", (error: Error) => { - console.error(`${workerKey.toUpperCase()} diagnostics worker error:`, error) - rejectAllPending(workerKey) - }) + console.error(`${workerKey.toUpperCase()} diagnostics worker error:`, error); + rejectAllPending(workerKey); + }); workers[workerKey].on("exit", (code: number) => { - if (code !== 0) console.error(`${workerKey.toUpperCase()} diagnostics worker exited with code ${code}`) - rejectAllPending(workerKey) - }) + if (code !== 0) + console.error(`${workerKey.toUpperCase()} diagnostics worker exited with code ${code}`); + rejectAllPending(workerKey); + }); } -function requestDiagnostics(workerKey: WorkerKey, code: string, lang: DiagnosticLanguage): Promise { - const id = ++nextRequestId - - return new Promise(resolve => { - pending[workerKey].set(id, resolve) - workers[workerKey].postMessage({ id, code, lang }) - }) +function requestDiagnostics( + workerKey: WorkerKey, + code: string, + lang: DiagnosticLanguage, +): Promise { + const id = ++nextRequestId; + + return new Promise((resolve) => { + pending[workerKey].set(id, resolve); + workers[workerKey].postMessage({ id, code, lang }); + }); } ipcMain.handle( "javascript-diagnostic", (_event: IpcMainInvokeEvent, code: string, language?: unknown): Promise => { - const lang = normalizeLanguage(language, "js") - return requestDiagnostics("js", code, lang) - } -) + const lang = normalizeLanguage(language, "js"); + return requestDiagnostics("js", code, lang); + }, +); ipcMain.handle( "typescript-diagnostic", (_event: IpcMainInvokeEvent, code: string, language?: unknown): Promise => { - const lang = normalizeLanguage(language, "ts") - return requestDiagnostics("ts", code, lang) - } -) + const lang = normalizeLanguage(language, "ts"); + return requestDiagnostics("ts", code, lang); + }, +); diff --git a/app/main/tools/go/ast.js b/app/main/tools/go/ast.js index a5642cf..22141b5 100644 --- a/app/main/tools/go/ast.js +++ b/app/main/tools/go/ast.js @@ -12,7 +12,10 @@ function findClosingBrace(lines, startLine) { let found = false; for (let i = startLine - 1; i < lines.length; i++) { for (const ch of lines[i]) { - if (ch === "{") { depth++; found = true; } + if (ch === "{") { + depth++; + found = true; + } if (ch === "}") { depth--; if (found && depth === 0) return i + 1; @@ -23,24 +26,37 @@ function findClosingBrace(lines, startLine) { } function parseParams(raw) { - if (!raw || !raw.trim()) return []; + if (!(raw && raw.trim())) return []; const params = []; - let depth = 0, current = ""; + let depth = 0, + current = ""; for (const ch of raw) { - if (ch === "(" || ch === "[") { depth++; current += ch; continue; } - if (ch === ")" || ch === "]") { depth--; current += ch; continue; } - if (ch === "," && depth === 0) { params.push(current.trim()); current = ""; continue; } + if (ch === "(" || ch === "[") { + depth++; + current += ch; + continue; + } + if (ch === ")" || ch === "]") { + depth--; + current += ch; + continue; + } + if (ch === "," && depth === 0) { + params.push(current.trim()); + current = ""; + continue; + } current += ch; } if (current.trim()) params.push(current.trim()); - return params.map(p => { + return params.map((p) => { const variadic = p.startsWith("..."); const clean = variadic ? p.slice(3) : p; const parts = clean.trim().split(/\s+/); if (parts.length === 1) return { names: [], paramType: (variadic ? "..." : "") + parts[0] }; const typePart = parts[parts.length - 1]; - const names = parts.slice(0, -1).map(n => n.replace(/,$/, "")); + const names = parts.slice(0, -1).map((n) => n.replace(/,$/, "")); return { names, paramType: (variadic ? "..." : "") + typePart }; }); } @@ -66,7 +82,11 @@ function parseImports(lines, body) { const single = line.match(/^import\s+"([^"]+)"/); if (single) { - body.push({ type: "ImportDeclaration", paths: [{ path: single[1], alias: null }], loc: loc(lineNum, lineNum) }); + body.push({ + type: "ImportDeclaration", + paths: [{ path: single[1], alias: null }], + loc: loc(lineNum, lineNum), + }); continue; } @@ -89,9 +109,12 @@ function parseStructFields(lines, startLine, endLine) { for (let i = startLine; i < endLine - 1; i++) { const line = lines[i].trim(); if (!line || line.startsWith("//") || line === "{" || line === "}") continue; - const m = line.match(/^([\w,\s]+?)\s+([\w\[\]*\.]+(?:\[[\w*\.]+\])?)\s*(`[^`]*`)?\s*$/); + const m = line.match(/^([\w,\s]+?)\s+([\w[\]*.]+(?:\[[\w*.]+\])?)\s*(`[^`]*`)?\s*$/); if (m) { - const names = m[1].split(",").map(s => s.trim()).filter(Boolean); + const names = m[1] + .split(",") + .map((s) => s.trim()) + .filter(Boolean); fields.push({ type: "StructField", names, @@ -122,7 +145,11 @@ function parseInterfaceMethods(lines, startLine, endLine) { } const embed = line.match(/^(\w+)$/); if (embed) { - methods.push({ type: "InterfaceEmbed", id: { name: embed[1] }, loc: loc(i + 1, i + 1) }); + methods.push({ + type: "InterfaceEmbed", + id: { name: embed[1] }, + loc: loc(i + 1, i + 1), + }); } } return methods; @@ -138,10 +165,20 @@ function parseBlock(lines, startLine, endLine) { // short var := const shortVar = line.match(/^([\w,\s]+?)\s*:=\s*(.+)$/); if (shortVar) { - const names = shortVar[1].split(",").map(s => s.trim()).filter(Boolean); + const names = shortVar[1] + .split(",") + .map((s) => s.trim()) + .filter(Boolean); const callMatch = shortVar[2].trim().match(/^([\w.]+)\s*\(/); const values = callMatch - ? [{ type: "CallExpression", calleeName: callMatch[1] + "()", args: [], loc: loc(lineNum, lineNum) }] + ? [ + { + type: "CallExpression", + calleeName: callMatch[1] + "()", + args: [], + loc: loc(lineNum, lineNum), + }, + ] : []; stmts.push({ type: "ShortVarDeclaration", names, values, loc: loc(lineNum, lineNum) }); continue; @@ -162,19 +199,42 @@ function parseBlock(lines, startLine, endLine) { // go / defer const goStmt = line.match(/^go\s+([\w.]+)\s*\(/); if (goStmt) { - stmts.push({ type: "GoStatement", call: { type: "CallExpression", calleeName: goStmt[1] + "()", args: [], loc: loc(lineNum, lineNum) }, loc: loc(lineNum, lineNum) }); + stmts.push({ + type: "GoStatement", + call: { + type: "CallExpression", + calleeName: goStmt[1] + "()", + args: [], + loc: loc(lineNum, lineNum), + }, + loc: loc(lineNum, lineNum), + }); continue; } const deferStmt = line.match(/^defer\s+([\w.]+)\s*\(/); if (deferStmt) { - stmts.push({ type: "DeferStatement", call: { type: "CallExpression", calleeName: deferStmt[1] + "()", args: [], loc: loc(lineNum, lineNum) }, loc: loc(lineNum, lineNum) }); + stmts.push({ + type: "DeferStatement", + call: { + type: "CallExpression", + calleeName: deferStmt[1] + "()", + args: [], + loc: loc(lineNum, lineNum), + }, + loc: loc(lineNum, lineNum), + }); continue; } // call expression const callStmt = line.match(/^([\w.]+)\s*\(/); if (callStmt) { - stmts.push({ type: "CallExpression", calleeName: callStmt[1] + "()", args: [], loc: loc(lineNum, lineNum) }); + stmts.push({ + type: "CallExpression", + calleeName: callStmt[1] + "()", + args: [], + loc: loc(lineNum, lineNum), + }); } } return stmts; @@ -253,7 +313,7 @@ function parse(code) { } // type alias - const typeAliasMatch = line.match(/^type\s+(\w+)\s+(?!=)([\w\[\]*]+(?:\[[\w*]+\])?)\s*$/); + const typeAliasMatch = line.match(/^type\s+(\w+)\s+(?!=)([\w[\]*]+(?:\[[\w*]+\])?)\s*$/); if (typeAliasMatch && !line.includes("struct") && !line.includes("interface")) { body.push({ type: "TypeAlias", @@ -267,7 +327,11 @@ function parse(code) { // var const varMatch = line.match(/^var\s+(.+)/); if (varMatch) { - const names = varMatch[1].split(/\s+/)[0].split(",").map(s => s.trim()).filter(Boolean); + const names = varMatch[1] + .split(/\s+/)[0] + .split(",") + .map((s) => s.trim()) + .filter(Boolean); body.push({ type: "VariableDeclaration", kind: "var", @@ -280,7 +344,10 @@ function parse(code) { // const const constMatch = line.match(/^const\s+(.+)/); if (constMatch) { - const names = constMatch[1].split(",").map(s => s.trim().split(/\s+/)[0]).filter(Boolean); + const names = constMatch[1] + .split(",") + .map((s) => s.trim().split(/\s+/)[0]) + .filter(Boolean); body.push({ type: "ConstDeclaration", declarations: [{ type: "ConstDeclarator", names, loc: loc(lineNum, lineNum) }], @@ -299,4 +366,4 @@ ipcMain.handle("golang-ast", (_, code) => { console.error("Go AST parse error:", e); return { type: "Program", loc: null, body: [] }; } -}); \ No newline at end of file +}); diff --git a/app/main/tools/go/gomod-mode.js b/app/main/tools/go/gomod-mode.js index 7694383..a1116af 100644 --- a/app/main/tools/go/gomod-mode.js +++ b/app/main/tools/go/gomod-mode.js @@ -1,110 +1,125 @@ -ace.define("ace/mode/gomod_highlight_rules", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text_highlight_rules"], function(require, exports, module) { - const oop = require("ace/lib/oop"); - const TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; +ace.define( + "ace/mode/gomod_highlight_rules", + ["require", "exports", "module", "ace/lib/oop", "ace/mode/text_highlight_rules"], + (require, exports, module) => { + const oop = require("ace/lib/oop"); + const TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; - const GoModHighlightRules = function() { - this.$rules = { - start: [ - { - token: "comment.line", - regex: /\/\/.*$/, - }, - { - token: "keyword.control", - regex: /^(?:module|go|require|replace|exclude|retract)\b/, - next: "directive", - }, - { - token: "paren.lparen", - regex: /\(/, - next: "block", - }, - ], + const GoModHighlightRules = function () { + this.$rules = { + start: [ + { + token: "comment.line", + regex: /\/\/.*$/, + }, + { + token: "keyword.control", + regex: /^(?:module|go|require|replace|exclude|retract)\b/, + next: "directive", + }, + { + token: "paren.lparen", + regex: /\(/, + next: "block", + }, + ], - directive: [ - { - token: "constant.numeric", - regex: /\b\d+\.\d+(?:\.\d+)?\b/, - }, - { - token: "string.unquoted", - regex: /[a-zA-Z0-9][\w\-]*(?:\.[a-zA-Z][\w\-]*)+(?:\/[\w\.\-~]+)*/, - }, - { - token: "keyword.operator", - regex: /=>/, - }, - { - token: "string.other", - regex: /\.\.?\/[\w\/\.\-]*/, - }, - { - token: "constant.language", - regex: /v\d+\.\d+\.\d+(?:-[\w\.\+]+)?(?:\+incompatible)?/, - }, - { - token: "text", - regex: /$/, - next: "start", - }, - ], + directive: [ + { + token: "constant.numeric", + regex: /\b\d+\.\d+(?:\.\d+)?\b/, + }, + { + token: "string.unquoted", + regex: /[a-zA-Z0-9][\w-]*(?:\.[a-zA-Z][\w-]*)+(?:\/[\w.\-~]+)*/, + }, + { + token: "keyword.operator", + regex: /[=]>/, + }, + { + token: "string.other", + regex: /\.\.?\/[\w/.-]*/, + }, + { + token: "constant.language", + regex: /v\d+\.\d+\.\d+(?:-[\w.+]+)?(?:\+incompatible)?/, + }, + { + token: "text", + regex: /$/, + next: "start", + }, + ], - block: [ - { - token: "comment.line", - regex: /\/\/.*$/, - }, - { - token: "paren.rparen", - regex: /\)/, - next: "start", - }, - { - token: "string.unquoted", - regex: /[a-zA-Z0-9][\w\-]*(?:\.[a-zA-Z][\w\-]*)+(?:\/[\w\.\-~]+)*/, - }, - { - token: "keyword.operator", - regex: /=>/, - }, - { - token: "string.other", - regex: /\.\.?\/[\w\/\.\-]*/, - }, - { - token: "constant.language", - regex: /v\d+\.\d+\.\d+(?:-[\w\.\+]+)?(?:\+incompatible)?/, - }, - { - token: "comment.line.indirect", - regex: /\/\/\s*indirect\b/, - }, - ], - }; + block: [ + { + token: "comment.line", + regex: /\/\/.*$/, + }, + { + token: "paren.rparen", + regex: /\)/, + next: "start", + }, + { + token: "string.unquoted", + regex: /[a-zA-Z0-9][\w-]*(?:\.[a-zA-Z][\w-]*)+(?:\/[\w.\-~]+)*/, + }, + { + token: "keyword.operator", + regex: /[=]>/, + }, + { + token: "string.other", + regex: /\.\.?\/[\w/.-]*/, + }, + { + token: "constant.language", + regex: /v\d+\.\d+\.\d+(?:-[\w.+]+)?(?:\+incompatible)?/, + }, + { + token: "comment.line.indirect", + regex: /\/\/\s*indirect\b/, + }, + ], + }; - this.normalizeRules(); - }; + this.normalizeRules(); + }; - oop.inherits(GoModHighlightRules, TextHighlightRules); - exports.GoModHighlightRules = GoModHighlightRules; -}); + oop.inherits(GoModHighlightRules, TextHighlightRules); + exports.GoModHighlightRules = GoModHighlightRules; + }, +); -ace.define("ace/mode/gomod", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text", "ace/mode/gomod_highlight_rules"], function(require, exports, module) { - const oop = require("ace/lib/oop"); - const TextMode = require("ace/mode/text").Mode; - const GoModHighlightRules = require("ace/mode/gomod_highlight_rules").GoModHighlightRules; +ace.define( + "ace/mode/gomod", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/mode/text", + "ace/mode/gomod_highlight_rules", + ], + (require, exports, module) => { + const oop = require("ace/lib/oop"); + const TextMode = require("ace/mode/text").Mode; + const GoModHighlightRules = require("ace/mode/gomod_highlight_rules").GoModHighlightRules; - const Mode = function() { - this.HighlightRules = GoModHighlightRules; - this.$behaviour = this.$defaultBehaviour; - }; + const Mode = function () { + this.HighlightRules = GoModHighlightRules; + this.$behaviour = this.$defaultBehaviour; + }; - oop.inherits(Mode, TextMode); + oop.inherits(Mode, TextMode); - (function() { - this.lineCommentStart = "//"; - this.$id = "ace/mode/gomod"; - }).call(Mode.prototype); + (function () { + this.lineCommentStart = "//"; + this.$id = "ace/mode/gomod"; + }).call(Mode.prototype); - exports.Mode = Mode; -}); \ No newline at end of file + exports.Mode = Mode; + }, +); diff --git a/app/main/tools/js-ts/ast.js b/app/main/tools/js-ts/ast.js index 1208937..59cc67e 100644 --- a/app/main/tools/js-ts/ast.js +++ b/app/main/tools/js-ts/ast.js @@ -39,7 +39,7 @@ function offsetToLoc(offset, lineTable) { } function getLoc(node, lineTable) { - if (!node || !Number.isInteger(node.start) || !Number.isInteger(node.end)) { + if (!(node && Number.isInteger(node.start) && Number.isInteger(node.end))) { return null; } @@ -121,14 +121,15 @@ function bindingToString(node) { case "ArrayPattern": return `[${(node.elements || []).map(bindingToString).join(", ")}]`; case "ObjectPattern": - return `{ ${( - node.properties || [] - ).map(property => { - if (property?.type === "RestElement") return bindingToString(property); - const key = keyToString(property?.key); - const value = bindingToString(property?.value); - return property?.shorthand || key === value ? key : `${key}: ${value}`; - }).filter(Boolean).join(", ")} }`; + return `{ ${(node.properties || []) + .map((property) => { + if (property?.type === "RestElement") return bindingToString(property); + const key = keyToString(property?.key); + const value = bindingToString(property?.value); + return property?.shorthand || key === value ? key : `${key}: ${value}`; + }) + .filter(Boolean) + .join(", ")} }`; default: return ""; } @@ -142,7 +143,9 @@ function convertNode(node, lineTable) { return { type: "Program", loc: getLoc(node, lineTable), - body: (node.body || []).map(child => convertNode(child, lineTable)).filter(Boolean), + body: (node.body || []) + .map((child) => convertNode(child, lineTable)) + .filter(Boolean), }; case "ImportDeclaration": @@ -210,11 +213,11 @@ function convertImportDeclaration(node, lineTable) { source: literalToString(node.source), importKind, phase: node.phase || null, - attributes: (node.attributes || []).map(attribute => ({ + attributes: (node.attributes || []).map((attribute) => ({ key: importNameToString(attribute.key), value: literalToString(attribute.value), })), - specifiers: (node.specifiers || []).map(specifier => { + specifiers: (node.specifiers || []).map((specifier) => { const specifierKind = specifier.importKind || importKind; const local = specifier.local?.name || ""; @@ -238,9 +241,10 @@ function convertImportDeclaration(node, lineTable) { function convertImportEqualsDeclaration(node, lineTable) { const reference = node.moduleReference; - const source = reference?.type === "TSExternalModuleReference" - ? literalToString(reference.expression) - : expressionToString(reference); + const source = + reference?.type === "TSExternalModuleReference" + ? literalToString(reference.expression) + : expressionToString(reference); return { type: "TSImportEqualsDeclaration", @@ -255,9 +259,9 @@ function convertVariableDeclaration(node, lineTable) { return { type: "VariableDeclaration", loc: getLoc(node, lineTable), - declarations: (node.declarations || []).map(declaration => - convertVariableDeclarator(declaration, lineTable) - ).filter(Boolean), + declarations: (node.declarations || []) + .map((declaration) => convertVariableDeclarator(declaration, lineTable)) + .filter(Boolean), }; } @@ -294,9 +298,9 @@ function convertVariableDeclarator(node, lineTable) { return { ...base, isObject: true, - properties: (init.properties || []).map(property => - convertProperty(property, lineTable) - ).filter(Boolean), + properties: (init.properties || []) + .map((property) => convertProperty(property, lineTable)) + .filter(Boolean), }; } @@ -334,13 +338,13 @@ function convertClass(node, lineTable) { id: { name: node.id?.name || "anonymous" }, isAbstract: Boolean(node.abstract), extends: node.superClass ? [expressionToString(node.superClass)] : [], - implements: (node.implements || []).map(implementation => - expressionToString(implementation.expression) - ).filter(Boolean), + implements: (node.implements || []) + .map((implementation) => expressionToString(implementation.expression)) + .filter(Boolean), loc: getLoc(node, lineTable), - body: (node.body?.body || []).map(member => - convertClassMember(member, lineTable) - ).filter(Boolean), + body: (node.body?.body || []) + .map((member) => convertClassMember(member, lineTable)) + .filter(Boolean), }; } @@ -397,13 +401,13 @@ function convertInterface(node, lineTable) { return { type: "InterfaceDeclaration", id: { name: node.id?.name || "" }, - extends: (node.extends || []).map(extension => - expressionToString(extension.expression) - ).filter(Boolean), + extends: (node.extends || []) + .map((extension) => expressionToString(extension.expression)) + .filter(Boolean), loc: getLoc(node, lineTable), - body: (node.body?.body || []).map(member => - convertInterfaceMember(member, lineTable) - ).filter(Boolean), + body: (node.body?.body || []) + .map((member) => convertInterfaceMember(member, lineTable)) + .filter(Boolean), }; } @@ -450,7 +454,7 @@ function convertEnum(node, lineTable) { type: "EnumDeclaration", id: { name: node.id?.name || "" }, isConst: Boolean(node.const), - members: (node.members || []).map(member => ({ + members: (node.members || []).map((member) => ({ type: "EnumMember", id: { name: keyToString(member.id) }, loc: getLoc(member, lineTable), @@ -460,14 +464,15 @@ function convertEnum(node, lineTable) { } function convertModuleDeclaration(node, lineTable) { - const body = node.body?.type === "TSModuleBlock" - ? node.body.body - : node.body ? [node.body] : []; + const body = + node.body?.type === "TSModuleBlock" ? node.body.body : node.body ? [node.body] : []; return { type: "TSModuleDeclaration", id: { name: keyToString(node.id) }, loc: getLoc(node, lineTable), - body: Array.isArray(body) ? body.map(child => convertNode(child, lineTable)).filter(Boolean) : [], + body: Array.isArray(body) + ? body.map((child) => convertNode(child, lineTable)).filter(Boolean) + : [], }; } @@ -506,9 +511,9 @@ function convertProperty(node, lineTable) { type: "Property", ...base, isObject: true, - properties: (value.properties || []).map(property => - convertProperty(property, lineTable) - ).filter(Boolean), + properties: (value.properties || []) + .map((property) => convertProperty(property, lineTable)) + .filter(Boolean), }; } @@ -517,10 +522,12 @@ function convertProperty(node, lineTable) { } function convertExpressionStatement(node, lineTable) { - return convertExpressionChild(node.expression, lineTable) || { - type: "ExpressionStatement", - loc: getLoc(node, lineTable), - }; + return ( + convertExpressionChild(node.expression, lineTable) || { + type: "ExpressionStatement", + loc: getLoc(node, lineTable), + } + ); } function convertExpressionChild(node, lineTable) { @@ -549,9 +556,9 @@ function convertExpressionChild(node, lineTable) { return { type: "ObjectExpression", loc: getLoc(node, lineTable), - properties: (node.properties || []).map(property => - convertProperty(property, lineTable) - ).filter(Boolean), + properties: (node.properties || []) + .map((property) => convertProperty(property, lineTable)) + .filter(Boolean), }; case "ClassExpression": return convertClass(node, lineTable); @@ -572,9 +579,9 @@ function convertExpressionChild(node, lineTable) { return { type: "SequenceExpression", loc: getLoc(node, lineTable), - body: (node.expressions || []).map(expression => - convertExpressionChild(expression, lineTable) - ).filter(Boolean), + body: (node.expressions || []) + .map((expression) => convertExpressionChild(expression, lineTable)) + .filter(Boolean), }; default: return null; @@ -586,18 +593,20 @@ function convertCallExpression(node, lineTable) { type: "CallExpression", calleeName: `${node.type === "NewExpression" ? "new " : ""}${expressionToString(node.callee)}()`, loc: getLoc(node, lineTable), - args: (node.arguments || []).map(argument => - convertExpressionChild(argument, lineTable) - ).filter(Boolean), + args: (node.arguments || []) + .map((argument) => convertExpressionChild(argument, lineTable)) + .filter(Boolean), }; } function convertAwaitExpression(node, lineTable) { return { type: "AwaitExpression", - calleeName: node.argument?.type === "CallExpression" || node.argument?.type === "OptionalCallExpression" - ? `${expressionToString(node.argument.callee)}()` - : null, + calleeName: + node.argument?.type === "CallExpression" || + node.argument?.type === "OptionalCallExpression" + ? `${expressionToString(node.argument.callee)}()` + : null, loc: getLoc(node, lineTable), body: [convertExpressionChild(node.argument, lineTable)].filter(Boolean), }; @@ -622,17 +631,17 @@ function convertImportExpression(node, lineTable) { } function convertIfStatement(node, lineTable) { - const toBlock = statement => statement?.type === "BlockStatement" - ? statement - : { body: statement ? [statement] : [] }; + const toBlock = (statement) => + statement?.type === "BlockStatement" ? statement : { body: statement ? [statement] : [] }; return { type: "IfStatement", loc: getLoc(node, lineTable), body: convertBlockBody(toBlock(node.consequent), lineTable), - alternate: node.alternate?.type === "IfStatement" - ? [convertIfStatement(node.alternate, lineTable)] - : convertBlockBody(toBlock(node.alternate), lineTable), + alternate: + node.alternate?.type === "IfStatement" + ? [convertIfStatement(node.alternate, lineTable)] + : convertBlockBody(toBlock(node.alternate), lineTable), }; } @@ -641,16 +650,20 @@ function convertTryStatement(node, lineTable) { type: "TryStatement", loc: getLoc(node, lineTable), body: convertBlockBody(node.block, lineTable), - handler: node.handler ? { - type: "CatchClause", - loc: getLoc(node.handler, lineTable), - body: convertBlockBody(node.handler.body, lineTable), - } : null, - finalizer: node.finalizer ? { - type: "FinallyClause", - loc: getLoc(node.finalizer, lineTable), - body: convertBlockBody(node.finalizer, lineTable), - } : null, + handler: node.handler + ? { + type: "CatchClause", + loc: getLoc(node.handler, lineTable), + body: convertBlockBody(node.handler.body, lineTable), + } + : null, + finalizer: node.finalizer + ? { + type: "FinallyClause", + loc: getLoc(node.finalizer, lineTable), + body: convertBlockBody(node.finalizer, lineTable), + } + : null, }; } @@ -660,8 +673,10 @@ function convertLoopStatement(node, lineTable) { loc: getLoc(node, lineTable), init: convertNode(node.init, lineTable), body: convertBlockBody( - node.body?.type === "BlockStatement" ? node.body : { body: node.body ? [node.body] : [] }, - lineTable + node.body?.type === "BlockStatement" + ? node.body + : { body: node.body ? [node.body] : [] }, + lineTable, ), }; } @@ -670,8 +685,10 @@ function convertSwitchStatement(node, lineTable) { return { type: "SwitchStatement", loc: getLoc(node, lineTable), - body: (node.cases || []).flatMap(switchCase => - (switchCase.consequent || []).map(statement => convertStatement(statement, lineTable)).filter(Boolean) + body: (node.cases || []).flatMap((switchCase) => + (switchCase.consequent || []) + .map((statement) => convertStatement(statement, lineTable)) + .filter(Boolean), ), }; } @@ -686,8 +703,8 @@ function convertExportDeclaration(node, lineTable) { } function convertBlockBody(node, lineTable) { - if (!node?.body || !Array.isArray(node.body)) return []; - return node.body.map(statement => convertStatement(statement, lineTable)).filter(Boolean); + if (!(node?.body && Array.isArray(node.body))) return []; + return node.body.map((statement) => convertStatement(statement, lineTable)).filter(Boolean); } function convertStatement(node, lineTable) { @@ -713,9 +730,9 @@ function convertStatement(node, lineTable) { } function typeParameterNames(typeParameters) { - return (typeParameters?.params || []).map(parameter => { - return parameter.name?.name || parameter.name || ""; - }).filter(Boolean); + return (typeParameters?.params || []) + .map((parameter) => parameter.name?.name || parameter.name || "") + .filter(Boolean); } function serializeTypeAnnotation(node) { @@ -727,58 +744,88 @@ function serializeType(node) { if (!node) return null; switch (node.type) { - case "TSStringKeyword": return "string"; - case "TSNumberKeyword": return "number"; - case "TSBooleanKeyword": return "boolean"; - case "TSAnyKeyword": return "any"; - case "TSUnknownKeyword": return "unknown"; - case "TSNeverKeyword": return "never"; - case "TSVoidKeyword": return "void"; - case "TSNullKeyword": return "null"; - case "TSUndefinedKeyword": return "undefined"; - case "TSObjectKeyword": return "object"; - case "TSSymbolKeyword": return "symbol"; - case "TSBigIntKeyword": return "bigint"; - case "TSIntrinsicKeyword": return "intrinsic"; - case "TSArrayType": return `${serializeType(node.elementType)}[]`; - case "TSUnionType": return (node.types || []).map(serializeType).join(" | "); - case "TSIntersectionType": return (node.types || []).map(serializeType).join(" & "); + case "TSStringKeyword": + return "string"; + case "TSNumberKeyword": + return "number"; + case "TSBooleanKeyword": + return "boolean"; + case "TSAnyKeyword": + return "any"; + case "TSUnknownKeyword": + return "unknown"; + case "TSNeverKeyword": + return "never"; + case "TSVoidKeyword": + return "void"; + case "TSNullKeyword": + return "null"; + case "TSUndefinedKeyword": + return "undefined"; + case "TSObjectKeyword": + return "object"; + case "TSSymbolKeyword": + return "symbol"; + case "TSBigIntKeyword": + return "bigint"; + case "TSIntrinsicKeyword": + return "intrinsic"; + case "TSArrayType": + return `${serializeType(node.elementType)}[]`; + case "TSUnionType": + return (node.types || []).map(serializeType).join(" | "); + case "TSIntersectionType": + return (node.types || []).map(serializeType).join(" & "); case "TSTypeReference": { const parameters = node.typeArguments?.params || node.typeParameters?.params || []; const args = parameters.map(serializeType).join(", "); const name = expressionToString(node.typeName); return args ? `${name}<${args}>` : name; } - case "TSLiteralType": return JSON.stringify(node.literal?.value); - case "TSTupleType": return `[${(node.elementTypes || []).map(serializeType).join(", ")}]`; + case "TSLiteralType": + return JSON.stringify(node.literal?.value); + case "TSTupleType": + return `[${(node.elementTypes || []).map(serializeType).join(", ")}]`; case "TSFunctionType": { - const parameters = (node.params || []).map(parameter => { - const name = bindingToString(parameter); - const type = serializeTypeAnnotation(parameter.typeAnnotation); - return type ? `${name}: ${type}` : name; - }).join(", "); + const parameters = (node.params || []) + .map((parameter) => { + const name = bindingToString(parameter); + const type = serializeTypeAnnotation(parameter.typeAnnotation); + return type ? `${name}: ${type}` : name; + }) + .join(", "); return `(${parameters}) => ${serializeTypeAnnotation(node.returnType)}`; } - case "TSConstructorType": return `new (...) => ${serializeTypeAnnotation(node.returnType)}`; - case "TSParenthesizedType": return `(${serializeType(node.typeAnnotation)})`; - case "TSOptionalType": return `${serializeType(node.typeAnnotation)}?`; - case "TSRestType": return `...${serializeType(node.typeAnnotation)}`; + case "TSConstructorType": + return `new (...) => ${serializeTypeAnnotation(node.returnType)}`; + case "TSParenthesizedType": + return `(${serializeType(node.typeAnnotation)})`; + case "TSOptionalType": + return `${serializeType(node.typeAnnotation)}?`; + case "TSRestType": + return `...${serializeType(node.typeAnnotation)}`; case "TSConditionalType": return `${serializeType(node.checkType)} extends ${serializeType(node.extendsType)} ? ${serializeType(node.trueType)} : ${serializeType(node.falseType)}`; case "TSIndexedAccessType": return `${serializeType(node.objectType)}[${serializeType(node.indexType)}]`; - case "TSTypeOperator": return `${node.operator} ${serializeType(node.typeAnnotation)}`; - case "TSInferType": return `infer ${serializeType(node.typeParameter)}`; + case "TSTypeOperator": + return `${node.operator} ${serializeType(node.typeAnnotation)}`; + case "TSInferType": + return `infer ${serializeType(node.typeParameter)}`; case "TSTypePredicate": return `${expressionToString(node.parameterName)} is ${serializeTypeAnnotation(node.typeAnnotation)}`; - case "TSImportType": return `import(${JSON.stringify(literalToString(node.argument))})`; - case "TSMappedType": return "{ [K in ...]: ... }"; - case "TSNamedTupleMember": return `${keyToString(node.label)}: ${serializeType(node.elementType)}`; - default: return node.type || null; + case "TSImportType": + return `import(${JSON.stringify(literalToString(node.argument))})`; + case "TSMappedType": + return "{ [K in ...]: ... }"; + case "TSNamedTupleMember": + return `${keyToString(node.label)}: ${serializeType(node.elementType)}`; + default: + return node.type || null; } } -function buildAST(code, language = "js") { +function buildAst(code, language = "js") { const lang = normalizeLanguage(language); try { @@ -787,18 +834,24 @@ function buildAST(code, language = "js") { sourceType: "unambiguous", preserveParens: false, }); - return convertNode(result.program, buildLineTable(code)) || { - type: "Program", - loc: null, - body: [], - }; + return ( + convertNode(result.program, buildLineTable(code)) || { + type: "Program", + loc: null, + body: [], + } + ); } catch (error) { console.error("Oxc AST parse error:", error); return { type: "Program", loc: null, body: [] }; } } -ipcMain.handle("javascript-ast", (_, code, language = "js") => buildAST(code, normalizeLanguage(language, "js"))); -ipcMain.handle("typescript-ast", (_, code, language = "ts") => buildAST(code, normalizeLanguage(language, "ts"))); +ipcMain.handle("javascript-ast", (_, code, language = "js") => + buildAst(code, normalizeLanguage(language, "js")), +); +ipcMain.handle("typescript-ast", (_, code, language = "ts") => + buildAst(code, normalizeLanguage(language, "ts")), +); -module.exports = { buildAST, normalizeLanguage }; \ No newline at end of file +module.exports = { buildAST: buildAst, normalizeLanguage }; diff --git a/app/main/tools/js-ts/diagnosticWorker.js b/app/main/tools/js-ts/diagnosticWorker.js index aceb2a8..3220959 100644 --- a/app/main/tools/js-ts/diagnosticWorker.js +++ b/app/main/tools/js-ts/diagnosticWorker.js @@ -4,7 +4,10 @@ const oxc = require("oxc-parser"); const OXC_LANGUAGES = new Set(["js", "jsx", "ts", "tsx", "dts"]); function normalizeLanguage(language, fallback = "js") { - const normalized = String(language || "").trim().toLowerCase().replace(/^\./, ""); + const normalized = String(language || "") + .trim() + .toLowerCase() + .replace(/^\./, ""); if (OXC_LANGUAGES.has(normalized)) return normalized; if (["mjs", "cjs", "es6"].includes(normalized)) return "js"; if (["mts", "cts"].includes(normalized)) return "ts"; @@ -22,7 +25,7 @@ function getDiagnostics(code, language = "js") { showSemanticErrors: true, }); const lineTable = buildLineTable(source); - return (result.errors || []).map(error => formatError(error, source, lineTable)); + return (result.errors || []).map((error) => formatError(error, source, lineTable)); } catch (error) { return [formatThrownError(error, source)]; } @@ -50,8 +53,8 @@ function offsetToLoc(offset, lineTable) { } function formatError(error, code, lineTable) { - const label = (error.labels || []).find(candidate => - Number.isInteger(candidate?.start) && Number.isInteger(candidate?.end) + const label = (error.labels || []).find( + (candidate) => Number.isInteger(candidate?.start) && Number.isInteger(candidate?.end), ); const start = clampOffset(label?.start, code.length); const end = clampOffset(label?.end, code.length); @@ -87,10 +90,13 @@ function clampOffset(offset, length) { function severityToCategory(severity) { switch (severity) { - case "Warning": return "Warning"; - case "Advice": return "Suggestion"; + case "Warning": + return "Warning"; + case "Advice": + return "Suggestion"; case "Error": - default: return "Error"; + default: + return "Error"; } } @@ -99,4 +105,4 @@ parentPort.on("message", ({ id, code, lang, isTS = false } = {}) => { parentPort.postMessage({ id, diagnostics }); }); -module.exports = { getDiagnostics, normalizeLanguage }; \ No newline at end of file +module.exports = { getDiagnostics, normalizeLanguage }; diff --git a/app/main/types/global.d.ts b/app/main/types/global.d.ts index dee210c..b317f47 100644 --- a/app/main/types/global.d.ts +++ b/app/main/types/global.d.ts @@ -1,7 +1,5 @@ -import type { LoginPayload, RegisterPayload, SaveContentPayload } from "../payloads" +import type { LoginPayload, RegisterPayload, SaveContentPayload } from "../payloads"; export interface ElectronAPI { - askToSaveNewFile: ( - properties: SaveContentPayload - ) => Promise -} \ No newline at end of file + askToSaveNewFile: (properties: SaveContentPayload) => Promise; +} diff --git a/app/notifications/notifications.js b/app/notifications/notifications.js index 72a79de..c3e67aa 100644 --- a/app/notifications/notifications.js +++ b/app/notifications/notifications.js @@ -1,48 +1,45 @@ -const { BrowserWindow, screen, ipcMain, app } = require("electron") -const { HTML_PATH, APP_PATH } = require("../main/helpers/paths.js") +const { BrowserWindow, screen, ipcMain, app } = require("electron"); +const { HTML_PATH, APP_PATH } = require("../main/helpers/paths.js"); -const path = require("path") +const path = require("path"); -const notifications = [] +const notifications = []; -const notifyWidth = 400 -const margin = 5 -const minHeight = 50 -const maxHeight = 200 -const maxStack = 5 +const notifyWidth = 400; +const margin = 5; +const minHeight = 50; +const maxHeight = 200; +const maxStack = 5; -const bus = require("../../helpers/eventBus") +const bus = require("../../helpers/eventBus"); function updatePositions() { - const { width, height } = screen.getPrimaryDisplay().workAreaSize + const { width, height } = screen.getPrimaryDisplay().workAreaSize; - let offset = margin + let offset = margin; for (let i = notifications.length - 1; i >= 0; i--) { - const win = notifications[i] + const win = notifications[i]; - if (!win || win.isDestroyed()) continue + if (!win || win.isDestroyed()) continue; - const [w, h] = win.getSize() + const [w, h] = win.getSize(); - win.setPosition( - width - w - margin, - height - h - offset - ) + win.setPosition(width - w - margin, height - h - offset); - offset += h + margin + offset += h + margin; } } function closeNotification(win) { - if (!win || win.isDestroyed()) return - win.close() + if (!win || win.isDestroyed()) return; + win.close(); } function spawnNotification(properties = {}) { - ipcMain.removeAllListeners("notification-close") + ipcMain.removeAllListeners("notification-close"); - const timeout = properties.timeout ?? 4000 + const timeout = properties.timeout ?? 4000; const win = new BrowserWindow({ width: notifyWidth, @@ -55,59 +52,56 @@ function spawnNotification(properties = {}) { webPreferences: { preload: path.join(APP_PATH, "notifications", "preload.js"), contextIsolation: true, - nodeIntegration: false - } - }) + nodeIntegration: false, + }, + }); - win.loadFile(path.join(HTML_PATH, "notification.html")) + win.loadFile(path.join(HTML_PATH, "notification.html")); - notifications.push(win) + notifications.push(win); if (notifications.length > maxStack) { - const old = notifications.shift() - if (old && !old.isDestroyed()) old.close() + const old = notifications.shift(); + if (old && !old.isDestroyed()) old.close(); } win.webContents.once("did-finish-load", async () => { - win.webContents.send("data", properties) + win.webContents.send("data", properties); setTimeout(async () => { const contentHeight = await win.webContents.executeJavaScript( - "document.body.scrollHeight" - ) + "document.body.scrollHeight", + ); - const finalHeight = Math.min( - Math.max(contentHeight, minHeight), - maxHeight - ) + const finalHeight = Math.min(Math.max(contentHeight, minHeight), maxHeight); - win.setSize(notifyWidth, finalHeight) + win.setSize(notifyWidth, finalHeight); - updatePositions() - }, 50) - }) + updatePositions(); + }, 50); + }); win.on("closed", () => { - const i = notifications.indexOf(win) - if (i !== -1) notifications.splice(i, 1) + const i = notifications.indexOf(win); + if (i !== -1) notifications.splice(i, 1); - updatePositions() - }) + updatePositions(); + }); - updatePositions() + updatePositions(); if (timeout > 0) { setTimeout(() => { - closeNotification(win) - }, timeout) + closeNotification(win); + }, timeout); } ipcMain.on("notification-close", (event) => { - const win = BrowserWindow.fromWebContents(event.sender) - if (win && !win.isDestroyed()) win.close() - }) + const win = BrowserWindow.fromWebContents(event.sender); + if (win && !win.isDestroyed()) win.close(); + }); - return win + return win; } -module.exports = { spawnNotification, notifications } \ No newline at end of file +module.exports = { spawnNotification, notifications }; diff --git a/app/notifications/preload.js b/app/notifications/preload.js index 0a59815..65dd294 100644 --- a/app/notifications/preload.js +++ b/app/notifications/preload.js @@ -1,8 +1,8 @@ -const { contextBridge, ipcRenderer } = require("electron") +const { contextBridge, ipcRenderer } = require("electron"); contextBridge.exposeInMainWorld("electron", { - onData: callback => { - ipcRenderer.on("data", (_, data) => callback(data)) + onData: (callback) => { + ipcRenderer.on("data", (_, data) => callback(data)); }, - close: () => ipcRenderer.send("notification-close") -}) \ No newline at end of file + close: () => ipcRenderer.send("notification-close"), +}); diff --git a/app/notifications/renderer.js b/app/notifications/renderer.js index 7a3f65a..648e1f2 100644 --- a/app/notifications/renderer.js +++ b/app/notifications/renderer.js @@ -1,50 +1,46 @@ -import { generateAvatar, truncateString } from "../../assets/js/lib.js" - -window.electron.onData(data => { - const types = ["default", "danger", "success", "warn"] - - const icon = data.icon == undefined ? false : data.icon - const image = data.image == undefined ? false : data.image - const initials = data.initials == undefined ? false : data.initials - const title = data.title == undefined ? "Unnamed" : data.title - const type = data.type == undefined ? "default" : data.type - const description = data.description == undefined ? "No description provided" : data.description - - const notifyWrapper = document.querySelector(".notification-wrapper") - const notifyIcon = document.querySelector(".notification-icon span") - const notifyTitle = document.querySelector(".notification-title") - const notifyDescription = document.querySelector(".notification-description") - const notifyClose = document.querySelector(".notification-close") - - if(!icon) { - if(image) { - const img = document.createElement("img") - img.classList.add("notification-image") - img.src = image - - notifyIcon.parentElement.appendChild(img) - notifyIcon.remove() - } - else if(initials) { - const generatedAvatar = generateAvatar(initials) - - notifyIcon.parentElement.classList.add("initials") - notifyIcon.parentElement.innerHTML = generatedAvatar - } - else { - notifyIcon.parentElement.remove() - } - } - else { - notifyIcon.textContent = icon +import { generateAvatar, truncateString } from "../../assets/js/lib.js"; + +window.electron.onData((data) => { + const types = ["default", "danger", "success", "warn"]; + + const icon = data.icon == undefined ? false : data.icon; + const image = data.image == undefined ? false : data.image; + const initials = data.initials == undefined ? false : data.initials; + const title = data.title == undefined ? "Unnamed" : data.title; + const type = data.type == undefined ? "default" : data.type; + const description = + data.description == undefined ? "No description provided" : data.description; + + const notifyWrapper = document.querySelector(".notification-wrapper"); + const notifyIcon = document.querySelector(".notification-icon span"); + const notifyTitle = document.querySelector(".notification-title"); + const notifyDescription = document.querySelector(".notification-description"); + const notifyClose = document.querySelector(".notification-close"); + + if (icon) { + notifyIcon.textContent = icon; + } else if (image) { + const img = document.createElement("img"); + img.classList.add("notification-image"); + img.src = image; + + notifyIcon.parentElement.appendChild(img); + notifyIcon.remove(); + } else if (initials) { + const generatedAvatar = generateAvatar(initials); + + notifyIcon.parentElement.classList.add("initials"); + notifyIcon.parentElement.innerHTML = generatedAvatar; + } else { + notifyIcon.parentElement.remove(); } - if(types.includes(type)) notifyWrapper.classList.add(type) - + if (types.includes(type)) notifyWrapper.classList.add(type); + notifyClose.addEventListener("click", () => { - window.electron.close() - }) + window.electron.close(); + }); - notifyTitle.textContent = truncateString(title, 80) - notifyDescription.textContent = truncateString(description, 250) -}) \ No newline at end of file + notifyTitle.textContent = truncateString(title, 80); + notifyDescription.textContent = truncateString(description, 250); +}); diff --git a/app/renderer.js b/app/renderer.js index b7faa41..8c58273 100644 --- a/app/renderer.js +++ b/app/renderer.js @@ -14,147 +14,166 @@ import { setTabNameCounter, setTabName, DragDrop, - GLS -} from "../assets/js/lib.js" -import { getCurrentUserDataFromAPI } from "../assets/js/user.js" + GLS, +} from "../assets/js/lib.js"; +import { getCurrentUserDataFromAPI } from "../assets/js/user.js"; -import * as object from "../assets/js/objects.js" +import * as object from "../assets/js/objects.js"; -import { openTab, reopenLastClosed, activateTab, recentlyClosed, tabsByPath, currentPath, updateTabPath, closeFolder } from "../assets/js/explorerTree/tabHandler.js" -import { handlePopovers } from "../assets/js/handlers/handlePopovers.js" -import { initExtensions } from "../assets/js/extensionsHandler/extensionsHandler.js" -import { sendDebugMsg } from "../assets/js/handlers/debuggerSignalHandlers.js" -import { initActions } from "../assets/js/actions.js" - -import { handleHistoryTab } from "../assets/js/explorerTabsHandlers/history.js" -import { handleBugsTab } from "../assets/js/explorerTabsHandlers/bugs.js" -import { electronAPI, getDirname, readSettings } from "../assets/js/global.js" -import { closeAllTabs } from "../assets/js/explorerTree/tabHandler.js" - -import { handleSettings } from "../assets/js/settings.js" -import { SidebarResizeHandler } from "../assets/js/handlers/SidebarResizeHandler.js" - -import { buildTreeHtml, renderNodes } from "../assets/js/explorerTree/render.js" -import { openFolder } from "../assets/js/explorerTree/handlers/openFolderHandler.js" -import { bindFileClicks } from "../assets/js/explorerTree/handlers/bindFileClicksHandler.js" - -import { setupSegmentedControl } from "../assets/js/handlers/segmentedControlHandler.js" - -import { getAddBugModal } from "../assets/js/modals/addBugModal.js" -import { getLogoutModal } from "../assets/js/modals/logoutModal.js" -import { ExplorerSidebar } from "../assets/js/sidebar/ExplorerSidebar.js" - -let isSaveAviable = true +import { + openTab, + reopenLastClosed, + activateTab, + recentlyClosed, + tabsByPath, + currentPath, + updateTabPath, + closeFolder, +} from "../assets/js/explorerTree/tabHandler.js"; +import { handlePopovers } from "../assets/js/handlers/handlePopovers.js"; +import { initExtensions } from "../assets/js/extensionsHandler/extensionsHandler.js"; +import { sendDebugMsg } from "../assets/js/handlers/debuggerSignalHandlers.js"; +import { initActions } from "../assets/js/actions.js"; + +import { handleHistoryTab } from "../assets/js/explorerTabsHandlers/history.js"; +import { handleBugsTab } from "../assets/js/explorerTabsHandlers/bugs.js"; +import { electronAPI, getDirname, readSettings } from "../assets/js/global.js"; +import { closeAllTabs } from "../assets/js/explorerTree/tabHandler.js"; + +import { handleSettings } from "../assets/js/settings.js"; +import { SidebarResizeHandler } from "../assets/js/handlers/SidebarResizeHandler.js"; + +import { buildTreeHtml, renderNodes } from "../assets/js/explorerTree/render.js"; +import { openFolder } from "../assets/js/explorerTree/handlers/openFolderHandler.js"; +import { bindFileClicks } from "../assets/js/explorerTree/handlers/bindFileClicksHandler.js"; + +import { setupSegmentedControl } from "../assets/js/handlers/segmentedControlHandler.js"; + +import { getAddBugModal } from "../assets/js/modals/addBugModal.js"; +import { getLogoutModal } from "../assets/js/modals/logoutModal.js"; +import { ExplorerSidebar } from "../assets/js/sidebar/ExplorerSidebar.js"; + +let isSaveAviable = true; export function disableSave() { - isSaveAviable = false + isSaveAviable = false; } export function enableSave() { - isSaveAviable = true + isSaveAviable = true; } document.addEventListener("DOMContentLoaded", async () => { - const gls = await GLS.init() - - localStorage.setItem("gls.current", gls.currentLang) - localStorage.setItem("gls", JSON.stringify(gls.registry)) + const gls = await GLS.init(); + + localStorage.setItem("gls.current", gls.currentLang); + localStorage.setItem("gls", JSON.stringify(gls.registry)); - document.querySelectorAll("[gls]").forEach(e => { - e.textContent = gls.get(e.getAttribute("gls")) - e.removeAttribute("gls") - }) + document.querySelectorAll("[gls]").forEach((e) => { + e.textContent = gls.get(e.getAttribute("gls")); + e.removeAttribute("gls"); + }); - const addBugModal = await getAddBugModal() - addBugModal.bind(document.querySelector("#add_bug")) + const addBugModal = await getAddBugModal(); + addBugModal.bind(document.querySelector("#add_bug")); - const logoutModal = await getLogoutModal() - logoutModal.bind(document.querySelector("#logout")) + const logoutModal = await getLogoutModal(); + logoutModal.bind(document.querySelector("#logout")); - let __dirname = await getDirname() - const settings = await readSettings() - const appIcon = await window.electron.getAppIcon() - const localData = await window.electron.getLocal() + let __dirname = await getDirname(); + const settings = await readSettings(); + const appIcon = await window.electron.getAppIcon(); + const localData = await window.electron.getLocal(); - await handleSettings(settings) + await handleSettings(settings); if ("app" in settings) { if ("devMode" in settings.app) { if (settings.app.devMode) { - window.electron.createDebuggerWindow() - await window.electron.onDebuggerReady() - - const developerModeTopBar = new TopBarElement("devMode") - developerModeTopBar.content({ icon: "bug_report", text: gls.get("devModeEnabled"), type: "notification" }) + window.electron.createDebuggerWindow(); + await window.electron.onDebuggerReady(); + + const developerModeTopBar = new TopBarElement("devMode"); + developerModeTopBar.content({ + icon: "bug_report", + text: gls.get("devModeEnabled"), + type: "notification", + }); setTimeout(() => { - developerModeTopBar.show() + developerModeTopBar.show(); setTimeout(() => { - developerModeTopBar.hide({ iconVisible: true }) - }, 3000) - }, 1000) + developerModeTopBar.hide({ iconVisible: true }); + }, 3000); + }, 1000); - developerModeTopBar.on("hover", (instance) => { instance.show() }) - developerModeTopBar.on("unhover", (instance) => { instance.hide({ iconVisible: true }) }) + developerModeTopBar.on("hover", (instance) => { + instance.show(); + }); + developerModeTopBar.on("unhover", (instance) => { + instance.hide({ iconVisible: true }); + }); } } } window.electron.mainReady(); - handlePopups() - handlePopovers(gls) - initExtensions() - initActions() + handlePopups(); + handlePopovers(gls); + initExtensions(); + initActions(); // drag n drop files - const fileDragDrop = new DragDrop(document.querySelector(".code-wrapper")) + const fileDragDrop = new DragDrop(document.querySelector(".code-wrapper")); fileDragDrop.onDrop(({ content, name, extension }) => { - openTab(name, content, extension, name, undefined, true, { gls: gls }) - }) + openTab(name, content, extension, name, undefined, true, { gls: gls }); + }); - // + // - sendDebugMsg("App started") + sendDebugMsg("App started"); // update language "Python" and set version in name - const pythonInfo = await window.electron.getPython() + const pythonInfo = await window.electron.getPython(); if (pythonInfo) { Languages.update("py", { name: `Python (${pythonInfo.version})`, icon: "py", iconExt: "svg", - mode: "python" - }) + mode: "python", + }); } - // + // // set text-color to l-rings (loaders) - document.querySelectorAll("l-ring").forEach(loader => { - const textColor = window.getComputedStyle(document.documentElement).getPropertyValue("--text-color") - loader.setAttribute("color", textColor) - }) - // + document.querySelectorAll("l-ring").forEach((loader) => { + const textColor = window + .getComputedStyle(document.documentElement) + .getPropertyValue("--text-color"); + loader.setAttribute("color", textColor); + }); + // - handleOnWheelScrollX() + handleOnWheelScrollX(); - const pathContext = {} - window.__pathContext = pathContext + const pathContext = {}; + window.__pathContext = pathContext; - document.querySelector(".code-start__main-logo").src = appIcon + document.querySelector(".code-start__main-logo").src = appIcon; - setupSegmentedControl() - showIndicator() + setupSegmentedControl(); + showIndicator(); // States const historyObject = {}; const bugsObject = {}; - const priorityClasses = object.priorityClasses + const priorityClasses = object.priorityClasses; - window.historyObject = historyObject - window.bugsObject = bugsObject - window.priorityClasses = priorityClasses + window.historyObject = historyObject; + window.bugsObject = bugsObject; + window.priorityClasses = priorityClasses; const explorerTitle = document.querySelector(".explorer-title__name"); const loader = document.querySelector(".loader"); @@ -163,33 +182,35 @@ document.addEventListener("DOMContentLoaded", async () => { const explorer = document.querySelector(".explorer"); const filesPanel = document.querySelector('.explorer-elements[data-tab="files"]'); - const yourOrganizationsPopupItem = document.querySelector(".popup-content__item#yourOrganizations") - const logoutPopupItem = document.querySelector(".popup-content__item#logout") - const createOrgPopupItem = document.querySelector(".popup-content__item#createOrganization") - const topbarCenterUserData = document.querySelector(".topbar-center#userData") - const topbarCenterBugsData = document.querySelector(".topbar-center#bugsData") + const yourOrganizationsPopupItem = document.querySelector( + ".popup-content__item#yourOrganizations", + ); + const logoutPopupItem = document.querySelector(".popup-content__item#logout"); + const createOrgPopupItem = document.querySelector(".popup-content__item#createOrganization"); + const topbarCenterUserData = document.querySelector(".topbar-center#userData"); + const topbarCenterBugsData = document.querySelector(".topbar-center#bugsData"); // explorer sidebar toggle handler - ExplorerSidebar.init() - ExplorerSidebar.bindEvent("showInSidebarItemClick") + ExplorerSidebar.init(); + ExplorerSidebar.bindEvent("showInSidebarItemClick"); document.querySelector("#sidebar-toggle").addEventListener("click", () => { - ExplorerSidebar.toggleWidth() - }) + ExplorerSidebar.toggleWidth(); + }); // restore last folder on startup if (settings?.app?.restoreFolder !== false && settings?.app?.lastFolder) { - const lastFolder = settings.app.lastFolder + const lastFolder = settings.app.lastFolder; try { - await window.electron.readDirTree(lastFolder, { maxDepth: 0 }) + await window.electron.readDirTree(lastFolder, { maxDepth: 0 }); openFolder({ pathRoot: lastFolder, filesPanel: filesPanel, addToHistory: addToHistory, pathContext: pathContext, - settings: settings - }) + settings: settings, + }); } catch (e) {} } @@ -198,26 +219,25 @@ document.addEventListener("DOMContentLoaded", async () => { if (localData.nonAccountMode) { loader?.classList.add("hidden"); - yourOrganizationsPopupItem.classList.add("disabled") - logoutPopupItem.classList.add("disabled") - createOrgPopupItem.classList.add("disabled") + yourOrganizationsPopupItem.classList.add("disabled"); + logoutPopupItem.classList.add("disabled"); + createOrgPopupItem.classList.add("disabled"); - topbarCenterUserData.querySelector("#username").textContent = gls.get("notAuth") - topbarCenterUserData.querySelector("#current_hours").classList.add("v-hidden") - topbarCenterBugsData.classList.add("v-hidden") + topbarCenterUserData.querySelector("#username").textContent = gls.get("notAuth"); + topbarCenterUserData.querySelector("#current_hours").classList.add("v-hidden"); + topbarCenterBugsData.classList.add("v-hidden"); - const loginPopupItem = document.createElement("div") - loginPopupItem.classList.add("popup-content__item") - loginPopupItem.textContent = gls.get("popups.account.login") + const loginPopupItem = document.createElement("div"); + loginPopupItem.classList.add("popup-content__item"); + loginPopupItem.textContent = gls.get("popups.account.login"); loginPopupItem.addEventListener("click", () => { - window.electron.setNonAccountMode(false) - window.electron.reload() - }) + window.electron.setNonAccountMode(false); + window.electron.reload(); + }); - document.querySelector(`[popup="account"] .popup-content`).prepend(loginPopupItem) - } - else { + document.querySelector(`[popup="account"] .popup-content`).prepend(loginPopupItem); + } else { getCurrentUserDataFromAPI(gls).then((e) => { if (!e.success) { const errEl = loader?.querySelector(".loader-msg"); @@ -233,34 +253,33 @@ document.addEventListener("DOMContentLoaded", async () => { // Explorer tabs - document.querySelectorAll(".sidebar-item").forEach(tab => { + document.querySelectorAll(".sidebar-item").forEach((tab) => { const id = tab.getAttribute("id"); tab.addEventListener("click", async () => { - document.querySelectorAll("[visibleOn]").forEach(el => { - const tabID = tab.id - const visibleID = el.getAttribute("visibleOn") + document.querySelectorAll("[visibleOn]").forEach((el) => { + const tabID = tab.id; + const visibleID = el.getAttribute("visibleOn"); if (visibleID.startsWith("tab:")) { if (tabID == visibleID.split("tab:")[1]) { - el.classList.remove("hidden") - } - else { - el.classList.add("hidden") + el.classList.remove("hidden"); + } else { + el.classList.add("hidden"); } } - }) + }); - if (tab.getAttribute("nondefault") != null) return + if (tab.getAttribute("nondefault") != null) return; - document.querySelectorAll(".sidebar-item").forEach(t => t.classList.remove("active")); + document.querySelectorAll(".sidebar-item").forEach((t) => t.classList.remove("active")); tab.classList.add("active"); if (tabName) { tabName.textContent = id === "files" ? "explorer" : id; } if (document.querySelector(`[data-tab="${id}"]`)) { - document.querySelectorAll(`[data-tab]`).forEach(t => t.classList.add("hidden")); + document.querySelectorAll(`[data-tab]`).forEach((t) => t.classList.add("hidden")); document.querySelector(`[data-tab="${id}"]`).classList.remove("hidden"); } setTabNameCounter(false); @@ -268,17 +287,17 @@ document.addEventListener("DOMContentLoaded", async () => { if (id == "files") { if (Object.keys(pathContext).length > 0) { if ("root" in pathContext) { - setTabName(pathContext.root) + setTabName(pathContext.root); } } } if (id === "history") { - handleHistoryTab(historyObject) + handleHistoryTab(historyObject); } if (id === "bugs") { - await handleBugsTab(bugsObject) + await handleBugsTab(bugsObject); } }); @@ -302,11 +321,10 @@ document.addEventListener("DOMContentLoaded", async () => { const rec = tabsByPath.get(currentPath); if (rec.new) { - const saveNewFileRes = await electronAPI.askToSaveNewFile( - { - filename: currentPath, - content: rec.editor.getValue() - }); + const saveNewFileRes = await electronAPI.askToSaveNewFile({ + filename: currentPath, + content: rec.editor.getValue(), + }); if (saveNewFileRes.success) { const newPath = saveNewFileRes.path; @@ -323,13 +341,11 @@ document.addEventListener("DOMContentLoaded", async () => { if (saveStatus.success) { rec.tabEl.classList.remove("not-saved"); - addToHistory( - { - actionType: "file-saved", - value: currentPath.split(/[\\/]/).pop(), - desc: currentPath - } - ); + addToHistory({ + actionType: "file-saved", + value: currentPath.split(/[\\/]/).pop(), + desc: currentPath, + }); } } @@ -345,20 +361,20 @@ document.addEventListener("DOMContentLoaded", async () => { if (data.type === "saved") { await saveActiveTab(); } - }) + }); window.addEventListener("blur", () => { const modifiers = [ { key: "Control", code: "ControlLeft" }, { key: "Alt", code: "AltLeft" }, { key: "Shift", code: "ShiftLeft" }, - { key: "Meta", code: "MetaLeft" } + { key: "Meta", code: "MetaLeft" }, ]; const targets = [window, document]; if (document.activeElement) { targets.push(document.activeElement); } - targets.forEach(target => { + targets.forEach((target) => { modifiers.forEach(({ key, code }) => { try { const event = new KeyboardEvent("keyup", { @@ -369,7 +385,7 @@ document.addEventListener("DOMContentLoaded", async () => { shiftKey: false, metaKey: false, bubbles: true, - cancelable: true + cancelable: true, }); target.dispatchEvent(event); } catch (e) { @@ -381,16 +397,15 @@ document.addEventListener("DOMContentLoaded", async () => { // File clicks (explorer) - if (filesPanel) bindFileClicks( - { + if (filesPanel) + bindFileClicks({ scopeEl: filesPanel, tabsByPath: tabsByPath, recentlyClosed: recentlyClosed, pathContext: pathContext, settings: settings, - gls: gls - } - ); + gls: gls, + }); if (topbar && mainWrapper) { mainWrapper.style.cssText = `height: calc(100% - ${topbar.offsetHeight}px)`; @@ -401,43 +416,39 @@ document.addEventListener("DOMContentLoaded", async () => { mainWrapper: mainWrapper, settings: settings, onResizeEnd: () => { - tabsByPath.forEach((tab) => tab.editor?.resize?.()) - } - }) + tabsByPath.forEach((tab) => tab.editor?.resize?.()); + }, + }); // open folder btn - document.querySelectorAll("#open_folder").forEach(btn => { + document.querySelectorAll("#open_folder").forEach((btn) => { btn.addEventListener("click", async () => { - const l = new Loader(document.querySelector(".explorer-elements[data-tab='files']"), - { - size: "20px", - stroke: "1px", - pos: "absolute-center", - method: "inner" - } - ) - l.render() + const l = new Loader(document.querySelector(".explorer-elements[data-tab='files']"), { + size: "20px", + stroke: "1px", + pos: "absolute-center", + method: "inner", + }); + l.render(); - let openedFile = await window.electron.requestFolder() + let openedFile = await window.electron.requestFolder(); - l.remove() + l.remove(); - openFolder( - { - pathRoot: openedFile, - filesPanel: filesPanel, - addToHistory: addToHistory, - pathContext: pathContext, - settings: settings - } - ) - }) - }) + openFolder({ + pathRoot: openedFile, + filesPanel: filesPanel, + addToHistory: addToHistory, + pathContext: pathContext, + settings: settings, + }); + }); + }); - document.querySelectorAll("#close_folder").forEach(btn => { + document.querySelectorAll("#close_folder").forEach((btn) => { btn.addEventListener("click", () => { closeFolder(); - }) - }) -}) + }); + }); +}); diff --git a/app/sandbox/permissions/audio/play.js b/app/sandbox/permissions/audio/play.js index 1b75d40..2863134 100644 --- a/app/sandbox/permissions/audio/play.js +++ b/app/sandbox/permissions/audio/play.js @@ -1,54 +1,50 @@ -const { ipcMain } = require("electron") -const { getExt, isFileExists, createSandboxConsole } = require("../../tools") -const path = require("path") +const { ipcMain } = require("electron"); +const { getExt, isFileExists, createSandboxConsole } = require("../../tools"); +const path = require("path"); function callback(data) { - const audioFilePath = data.selfArgs[0] - const audioProperties = data.selfArgs[1] - - const fileExt = getExt(audioFilePath) - const extPath = data.extensionPath - const extName = data.extensionName - const debuggerSender = data.debuggerSender - const mainSender = data.mainSender - const permName = data.permissionName - - const c = createSandboxConsole(extName, debuggerSender) - - const aviableExts = [".mp3", ".wav"] - - if(typeof audioProperties != "object" || Array.isArray(audioProperties)) { - c.error(`[${permName}]: Audio properties must be object`) - return + const audioFilePath = data.selfArgs[0]; + const audioProperties = data.selfArgs[1]; + + const fileExt = getExt(audioFilePath); + const extPath = data.extensionPath; + const extName = data.extensionName; + const debuggerSender = data.debuggerSender; + const mainSender = data.mainSender; + const permName = data.permissionName; + + const c = createSandboxConsole(extName, debuggerSender); + + const aviableExts = [".mp3", ".wav"]; + + if (typeof audioProperties != "object" || Array.isArray(audioProperties)) { + c.error(`[${permName}]: Audio properties must be object`); + return; } - let volume = audioProperties.volume == undefined ? 0.2 : audioProperties.volume - let speed = audioProperties.speed == undefined ? 1 : audioProperties.speed + let volume = audioProperties.volume == undefined ? 0.2 : audioProperties.volume; + let speed = audioProperties.speed == undefined ? 1 : audioProperties.speed; - if (volume > 0.8) volume = 0.2 - if (volume < 0.2) volume = 0.2 + if (volume > 0.8) volume = 0.2; + if (volume < 0.2) volume = 0.2; - if (speed > 4) speed = 1 - if (speed < 0.5) speed = 1 + if (speed > 4) speed = 1; + if (speed < 0.5) speed = 1; - if(aviableExts.includes(fileExt)) { - const fullAudioPath = path.join(extPath, audioFilePath) - const isAudioFound = isFileExists(fullAudioPath) + if (aviableExts.includes(fileExt)) { + const fullAudioPath = path.join(extPath, audioFilePath); + const isAudioFound = isFileExists(fullAudioPath); - if(!isAudioFound) { - c.error(`[${permName}]: File "${fullAudioPath}" not found`) - return - } - else { - mainSender.send("extension-play-sound", - { - path: fullAudioPath, - volume: volume, - speed: speed - } - ) + if (isAudioFound) { + mainSender.send("extension-play-sound", { + path: fullAudioPath, + volume, + speed, + }); + } else { + c.error(`[${permName}]: File "${fullAudioPath}" not found`); } } } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/commands/execCommand.js b/app/sandbox/permissions/commands/execCommand.js index cf4b1df..9af5f82 100644 --- a/app/sandbox/permissions/commands/execCommand.js +++ b/app/sandbox/permissions/commands/execCommand.js @@ -1,15 +1,15 @@ function callback(data) { - const extName = data.extensionName - const commandString = data.selfArgs[0] + const extName = data.extensionName; + const commandString = data.selfArgs[0]; data.debuggerSender.send("debug-event", { data: { type: "execCommand", command: commandString, - from: extName + from: extName, }, - time: Date.now() - }) + time: Date.now(), + }); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/commands/registerCommand.js b/app/sandbox/permissions/commands/registerCommand.js index 78a85bb..71bf3fe 100644 --- a/app/sandbox/permissions/commands/registerCommand.js +++ b/app/sandbox/permissions/commands/registerCommand.js @@ -1,19 +1,23 @@ -const { checkFields } = require("../../tools.js") +const { checkFields } = require("../../tools.js"); function callback(data) { - const input = data.selfArgs[0] - const extName = data.extensionName + const input = data.selfArgs[0]; + const extName = data.extensionName; checkFields("APP.registerCommand", input, { name: "string", - response: "string" - }) + response: "string", + }); if (/\s/g.test(input.name)) { - throw new Error(`The command cannot contain spaces. Use characters such as "-", "_", etc., instead. Example: ${data.name.replaceAll(/\s/g, "-")}`) + throw new Error( + `The command cannot contain spaces. Use characters such as "-", "_", etc., instead. Example: ${data.name.replaceAll(/\s/g, "-")}`, + ); } if (input.name.startsWith("-")) { - throw new Error(`A command name cannot begin with a hyphen (-) when registering a command, because commands that start with this character may be reserved by the program`) + throw new Error( + "A command name cannot begin with a hyphen (-) when registering a command, because commands that start with this character may be reserved by the program", + ); } data.debuggerSender.send("debug-event", { @@ -22,12 +26,12 @@ function callback(data) { command: { name: input.name, arguments: input.arguments, - response: input.response + response: input.response, }, - from: extName + from: extName, }, - time: Date.now() - }) + time: Date.now(), + }); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/config/get.js b/app/sandbox/permissions/config/get.js index 9a37df9..7b7e6f2 100644 --- a/app/sandbox/permissions/config/get.js +++ b/app/sandbox/permissions/config/get.js @@ -1,18 +1,18 @@ -const fs = require("fs") -const path = require("path") +const fs = require("fs"); +const path = require("path"); function callback(data) { - const extensionPath = data.extensionPath - const configPath = path.join(extensionPath, "config.json") + const extensionPath = data.extensionPath; + const configPath = path.join(extensionPath, "config.json"); return () => { try { if (fs.existsSync(configPath)) { - return JSON.parse(fs.readFileSync(configPath, "utf-8")) + return JSON.parse(fs.readFileSync(configPath, "utf-8")); } } catch (e) {} - return {} - } + return {}; + }; } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/config/set.js b/app/sandbox/permissions/config/set.js index 3722f27..b42ef27 100644 --- a/app/sandbox/permissions/config/set.js +++ b/app/sandbox/permissions/config/set.js @@ -1,26 +1,26 @@ -const fs = require("fs") -const path = require("path") +const fs = require("fs"); +const path = require("path"); function callback(data) { - const extensionPath = data.extensionPath - const configPath = path.join(extensionPath, "config.json") + const extensionPath = data.extensionPath; + const configPath = path.join(extensionPath, "config.json"); return (newValues) => { if (!newValues || typeof newValues !== "object" || Array.isArray(newValues)) { - throw new Error("[config.set] Argument must be a plain object") + throw new Error("[config.set] Argument must be a plain object"); } - let current = {} + let current = {}; try { if (fs.existsSync(configPath)) { - current = JSON.parse(fs.readFileSync(configPath, "utf-8")) + current = JSON.parse(fs.readFileSync(configPath, "utf-8")); } } catch (e) {} - const merged = { ...current, ...newValues } - fs.writeFileSync(configPath, JSON.stringify(merged, null, 4), "utf-8") - return merged - } + const merged = { ...current, ...newValues }; + fs.writeFileSync(configPath, JSON.stringify(merged, null, 4), "utf-8"); + return merged; + }; } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/css/load.js b/app/sandbox/permissions/css/load.js index 19f871f..99fa059 100644 --- a/app/sandbox/permissions/css/load.js +++ b/app/sandbox/permissions/css/load.js @@ -1,24 +1,24 @@ -const { saveReadFile } = require("../../tools.js") -const path = require("path") +const { saveReadFile } = require("../../tools.js"); +const path = require("path"); function callback(data) { - const extName = data.extensionName - const extPath = data.extensionPath - const filename = data.selfArgs[0] + ".css" - const CSSContent = saveReadFile(path.join(extPath, filename)) + const extName = data.extensionName; + const extPath = data.extensionPath; + const filename = data.selfArgs[0] + ".css"; + const CssContent = saveReadFile(path.join(extPath, filename)); - if (!CSSContent) throw new Error(`The file "${filename}" was not found or is empty`) + if (!CssContent) throw new Error(`The file "${filename}" was not found or is empty`); data.debuggerSender.send("debug-event", { data: { type: "warn", content: `Loaded local resource: ${filename}`, - from: extName + from: extName, }, - time: Date.now() - }) + time: Date.now(), + }); - data.mainSender.send("load-css", extName, CSSContent) + data.mainSender.send("load-css", extName, CssContent); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/discord/discordRichPresence.js b/app/sandbox/permissions/discord/discordRichPresence.js index 58a1865..1462402 100644 --- a/app/sandbox/permissions/discord/discordRichPresence.js +++ b/app/sandbox/permissions/discord/discordRichPresence.js @@ -1,196 +1,209 @@ -const net = require("net") -const os = require("os") +const net = require("net"); +const os = require("os"); -const clients = new Map() +const clients = new Map(); function callback(data) { - const input = data.selfArgs[0] - const extensionName = data.extensionName - const debuggerSender = data.debuggerSender + const input = data.selfArgs[0]; + const extensionName = data.extensionName; + const debuggerSender = data.debuggerSender; if (input === "clear") { - return getClient(extensionName, {}, debuggerSender).clear() + return getClient(extensionName, {}, debuggerSender).clear(); } if (!input || typeof input !== "object" || Array.isArray(input)) { - throw new Error("[APP.richPresence] First argument must be a presence object or \"clear\"") + throw new Error('[APP.richPresence] First argument must be a presence object or "clear"'); } - const provider = input.provider || "discord" + const provider = input.provider || "discord"; if (provider !== "discord") { - throw new Error(`[APP.richPresence] Unsupported provider "${provider}"`) + throw new Error(`[APP.richPresence] Unsupported provider "${provider}"`); } if (typeof input.clientId !== "string" || input.clientId.trim() === "") { - throw new Error("[APP.richPresence] Discord provider requires a clientId string") + throw new Error("[APP.richPresence] Discord provider requires a clientId string"); } - return getClient(extensionName, input, debuggerSender).setActivity(input) + return getClient(extensionName, input, debuggerSender).setActivity(input); } function getClient(extensionName, options, debuggerSender) { - const key = `${extensionName}:discord` + const key = `${extensionName}:discord`; if (!clients.has(key)) { - clients.set(key, new DiscordPresenceClient({ - extensionName, - clientId: options.clientId, - debuggerSender - })) + clients.set( + key, + new DiscordPresenceClient({ + extensionName, + clientId: options.clientId, + debuggerSender, + }), + ); } - const client = clients.get(key) + const client = clients.get(key); if (options.clientId) { - client.clientId = options.clientId + client.clientId = options.clientId; } - return client + return client; } class DiscordPresenceClient { constructor({ extensionName, clientId, debuggerSender }) { - this.extensionName = extensionName - this.clientId = clientId - this.debuggerSender = debuggerSender - this.socket = null - this.connected = false - this.connecting = false - this.pendingActivity = null + this.extensionName = extensionName; + this.clientId = clientId; + this.debuggerSender = debuggerSender; + this.socket = null; + this.connected = false; + this.connecting = false; + this.pendingActivity = null; } async setActivity(input) { - this.pendingActivity = this.#toDiscordActivity(input) + this.pendingActivity = this.#toDiscordActivity(input); - await this.#connect() + await this.#connect(); - if (!this.connected) return false + if (!this.connected) return false; this.#send(1, { cmd: "SET_ACTIVITY", args: { pid: process.pid, - activity: this.pendingActivity + activity: this.pendingActivity, }, - nonce: this.#nonce() - }) + nonce: this.#nonce(), + }); - return true + return true; } async clear() { - await this.#connect() + await this.#connect(); - if (!this.connected) return false + if (!this.connected) return false; this.#send(1, { cmd: "SET_ACTIVITY", args: { - pid: process.pid + pid: process.pid, }, - nonce: this.#nonce() - }) + nonce: this.#nonce(), + }); - return true + return true; } async #connect() { - if (this.connected || this.connecting) return + if (this.connected || this.connecting) return; - this.connecting = true + this.connecting = true; for (const pipePath of getDiscordPipePaths()) { - const connected = await this.#tryConnect(pipePath) + const connected = await this.#tryConnect(pipePath); if (connected) { - this.connecting = false - this.connected = true - this.#send(0, { v: 1, client_id: this.clientId }) - return + this.connecting = false; + this.connected = true; + this.#send(0, { v: 1, client_id: this.clientId }); + return; } } - this.connecting = false - this.#log("warn", "Discord IPC pipe was not found. Is Discord running?") + this.connecting = false; + this.#log("warn", "Discord IPC pipe was not found. Is Discord running?"); } #tryConnect(pipePath) { return new Promise((resolve) => { - const socket = net.createConnection(pipePath) - let settled = false + const socket = net.createConnection(pipePath); + let settled = false; const done = (success) => { - if (settled) return + if (settled) return; - settled = true - socket.removeAllListeners("connect") - socket.removeAllListeners("error") - resolve(success) - } + settled = true; + socket.removeAllListeners("connect"); + socket.removeAllListeners("error"); + resolve(success); + }; socket.once("connect", () => { - this.socket = socket - socket.on("error", (error) => this.#handleDisconnect(error)) - socket.on("close", () => this.#handleDisconnect()) - done(true) - }) + this.socket = socket; + socket.on("error", (error) => this.#handleDisconnect(error)); + socket.on("close", () => this.#handleDisconnect()); + done(true); + }); - socket.once("error", () => done(false)) - }) + socket.once("error", () => done(false)); + }); } #handleDisconnect(error) { if (error) { - this.#log("warn", `Discord presence disconnected: ${error.message}`) + this.#log("warn", `Discord presence disconnected: ${error.message}`); } - this.connected = false - this.socket = null + this.connected = false; + this.socket = null; } #send(opcode, payload) { - if (!this.socket) return + if (!this.socket) return; - const json = Buffer.from(JSON.stringify(payload)) - const frame = Buffer.alloc(8 + json.length) + const json = Buffer.from(JSON.stringify(payload)); + const frame = Buffer.alloc(8 + json.length); - frame.writeInt32LE(opcode, 0) - frame.writeInt32LE(json.length, 4) - json.copy(frame, 8) + frame.writeInt32LE(opcode, 0); + frame.writeInt32LE(json.length, 4); + json.copy(frame, 8); - this.socket.write(frame) + this.socket.write(frame); } #toDiscordActivity(input) { const activity = { details: input.details || "Editing code", - state: input.state || "In CodeMotion" - } + state: input.state || "In CodeMotion", + }; if (Number.isFinite(Number(input.startTimestamp))) { - activity.timestamps = { start: Number(input.startTimestamp) } + activity.timestamps = { start: Number(input.startTimestamp) }; } - if (input.largeImageKey || input.largeImageText || input.smallImageKey || input.smallImageText) { - activity.assets = {} - - if (input.largeImageKey) activity.assets.large_image = String(input.largeImageKey) - if (input.largeImageText) activity.assets.large_text = String(input.largeImageText) - if (input.smallImageKey) activity.assets.small_image = String(input.smallImageKey) - if (input.smallImageText) activity.assets.small_text = String(input.smallImageText) + if ( + input.largeImageKey || + input.largeImageText || + input.smallImageKey || + input.smallImageText + ) { + activity.assets = {}; + + if (input.largeImageKey) activity.assets.large_image = String(input.largeImageKey); + if (input.largeImageText) activity.assets.large_text = String(input.largeImageText); + if (input.smallImageKey) activity.assets.small_image = String(input.smallImageKey); + if (input.smallImageText) activity.assets.small_text = String(input.smallImageText); } if (Array.isArray(input.buttons) && input.buttons.length > 0) { activity.buttons = input.buttons .slice(0, 2) - .filter(button => button && typeof button.label === "string" && typeof button.url === "string") - .map(button => ({ label: button.label, url: button.url })) + .filter( + (button) => + button && + typeof button.label === "string" && + typeof button.url === "string", + ) + .map((button) => ({ label: button.label, url: button.url })); } - return activity + return activity; } #nonce() { - return `${Date.now()}-${Math.random().toString(16).slice(2)}` + return `${Date.now()}-${Math.random().toString(16).slice(2)}`; } #log(type, content) { @@ -198,28 +211,28 @@ class DiscordPresenceClient { data: { type, content, - from: this.extensionName + from: this.extensionName, }, - time: Date.now() - }) + time: Date.now(), + }); } } function getDiscordPipePaths() { - const paths = [] + const paths = []; for (let index = 0; index < 10; index++) { if (process.platform === "win32") { - paths.push(`\\\\?\\pipe\\discord-ipc-${index}`) + paths.push(`\\\\?\\pipe\\discord-ipc-${index}`); } else { - const runtimeDir = process.env.XDG_RUNTIME_DIR || os.tmpdir() + const runtimeDir = process.env.XDG_RUNTIME_DIR || os.tmpdir(); - paths.push(`${runtimeDir}/discord-ipc-${index}`) - paths.push(`/tmp/discord-ipc-${index}`) + paths.push(`${runtimeDir}/discord-ipc-${index}`); + paths.push(`/tmp/discord-ipc-${index}`); } } - return paths + return paths; } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/editor/__api.js b/app/sandbox/permissions/editor/__api.js index 2c9fa84..fa72159 100644 --- a/app/sandbox/permissions/editor/__api.js +++ b/app/sandbox/permissions/editor/__api.js @@ -8,31 +8,35 @@ function getAceTriggeredData({ data, mainSender }) { mode: data.editorMode, language: { name: data.editorLanguage, - extension: data.editorLanguageExtension + extension: data.editorLanguageExtension, }, errors: data.errors || 0, cursor: data.cursor || { line: 1, - column: 1 + column: 1, }, api: { - replace: (...args) => publicAPI.replace({ editorValue: data.editorValue, mainSender: mainSender }, ...args), - includes: (...args) => publicAPI.includes({ editorValue: data.editorValue }, ...args) - } - } + replace: (...args) => + publicApi.replace({ editorValue: data.editorValue, mainSender }, ...args), + includes: (...args) => publicApi.includes({ editorValue: data.editorValue }, ...args), + }, + }; - return object + return object; } -const publicAPI = { +const publicApi = { replace({ editorValue, mainSender }, findString, replaceString) { - if(typeof editorValue == "string") { - mainSender.send("editor-api-replace", { findString: findString, replaceString: replaceString }) + if (typeof editorValue == "string") { + mainSender.send("editor-api-replace", { + findString, + replaceString, + }); } }, includes({ editorValue }, findString) { - return editorValue.includes(findString) - } -} + return editorValue.includes(findString); + }, +}; -module.exports = { getAceTriggeredData, publicAPI } \ No newline at end of file +module.exports = { getAceTriggeredData, publicAPI: publicApi }; diff --git a/app/sandbox/permissions/editor/dirs/newIconSet.js b/app/sandbox/permissions/editor/dirs/newIconSet.js index dec7c16..63f4b18 100644 --- a/app/sandbox/permissions/editor/dirs/newIconSet.js +++ b/app/sandbox/permissions/editor/dirs/newIconSet.js @@ -1,20 +1,20 @@ -const { saveReadFile } = require("../../../tools.js") -const path = require("path") +const { saveReadFile } = require("../../../tools.js"); +const path = require("path"); function callback(data) { - const extPath = data.extensionPath - const configPath = data.selfArgs[0] + const extPath = data.extensionPath; + const configPath = data.selfArgs[0]; if (configPath) { - let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true) - configContent = JSON.parse(configContent) + let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true); + configContent = JSON.parse(configContent); - Object.keys(configContent).forEach(k => { - configContent[k] = path.join(extPath, configContent[k]) - }) + Object.keys(configContent).forEach((k) => { + configContent[k] = path.join(extPath, configContent[k]); + }); - data.mainSender.send("new-dir-icon-register", configContent) + data.mainSender.send("new-dir-icon-register", configContent); } } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/editor/docs/register.js b/app/sandbox/permissions/editor/docs/register.js index 8155f36..ef7fd17 100644 --- a/app/sandbox/permissions/editor/docs/register.js +++ b/app/sandbox/permissions/editor/docs/register.js @@ -1,31 +1,36 @@ -const { checkFields, saveReadFile } = require("../../../tools") -const path = require("path") +const { checkFields, saveReadFile } = require("../../../tools"); +const path = require("path"); function callback(data) { - const configPath = data.selfArgs[0] - const extPath = data.extensionPath + const configPath = data.selfArgs[0]; + const extPath = data.extensionPath; - let documentationProperties = {} + let documentationProperties = {}; if (configPath) { - let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true) - configContent = JSON.parse(configContent) + let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true); + configContent = JSON.parse(configContent); - const docPropertiesKey = "__$props__" + const docPropertiesKey = "__$props__"; if (Object.keys(configContent).length > 0) { // check $props and fields - if(docPropertiesKey in configContent) { - documentationProperties = configContent[docPropertiesKey] - - checkFields(`${data.permissionName}:config:${docPropertiesKey}`, documentationProperties, { - onMode: "string" - }) - - delete configContent[docPropertiesKey] - } - else { - throw new Error(`${data.permissionName}: key "$props" in documentation config is required`) + if (docPropertiesKey in configContent) { + documentationProperties = configContent[docPropertiesKey]; + + checkFields( + `${data.permissionName}:config:${docPropertiesKey}`, + documentationProperties, + { + onMode: "string", + }, + ); + + delete configContent[docPropertiesKey]; + } else { + throw new Error( + `${data.permissionName}: key "$props" in documentation config is required`, + ); } // check each config item @@ -34,16 +39,16 @@ function callback(data) { type: "string", description: "string", example: "string", - sources: "array" - }) - }) + sources: "array", + }); + }); data.mainSender.send("new-documentation-register", { config: configContent, - props: documentationProperties - }) + props: documentationProperties, + }); } } } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/editor/hl/registerProvider.js b/app/sandbox/permissions/editor/hl/registerProvider.js index 7f848de..47a12cf 100644 --- a/app/sandbox/permissions/editor/hl/registerProvider.js +++ b/app/sandbox/permissions/editor/hl/registerProvider.js @@ -1,5 +1,5 @@ const { setEditorChangedCallback } = require("../../../../dist/ipc/ace.js"); -const { getAceTriggeredData } = require("../__api.js") +const { getAceTriggeredData } = require("../__api.js"); const providers = new Map(); @@ -8,11 +8,11 @@ function registerProvider(id, cb) { } function callback(data) { - const providerID = data.selfArgs[0]; + const providerId = data.selfArgs[0]; const cb = data.selfArgs[1]; const mainSender = data.mainSender; - registerProvider(providerID, cb) + registerProvider(providerId, cb); if (typeof cb !== "function") return; @@ -21,13 +21,13 @@ function callback(data) { const allRules = []; - for (const [providerID, cb] of providers) { + for (const [providerId, cb] of providers) { const data = getAceTriggeredData({ data: editorData, - mainSender: editorData.mainSender + mainSender: editorData.mainSender, }); - delete data["api"] + delete data["api"]; const result = cb(data); @@ -40,25 +40,31 @@ function callback(data) { typeof item.id !== "string" || typeof item.regex !== "string" || typeof item.token !== "string" - ) continue; + ) + continue; allRules.push({ - id: `${providerID}_${item.id}`, + id: `${providerId}_${item.id}`, regex: item.regex, - token: item.token + token: item.token, }); } } - applyRules({ editorData: editorData, fileId: fileId, rules: allRules, mainSender: mainSender }); + applyRules({ + editorData, + fileId, + rules: allRules, + mainSender, + }); }); } function applyRules({ editorData, fileId, rules, mainSender }) { mainSender.send("on-editor-change-new-hl-rules", { - fileId: fileId, - rules: rules + fileId, + rules, }); } -module.exports = { callback }; \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/editor/onChange.js b/app/sandbox/permissions/editor/onChange.js index f977180..949a092 100644 --- a/app/sandbox/permissions/editor/onChange.js +++ b/app/sandbox/permissions/editor/onChange.js @@ -11,10 +11,10 @@ function callback(data) { cb( getAceTriggeredData({ data: rawData, - mainSender - }) + mainSender, + }), ); }); } -module.exports = { callback }; \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/editor/onClick.js b/app/sandbox/permissions/editor/onClick.js index 10098fa..aa488a9 100644 --- a/app/sandbox/permissions/editor/onClick.js +++ b/app/sandbox/permissions/editor/onClick.js @@ -1,5 +1,5 @@ -const { setAceClickedCallback } = require("../../../main/ipc/ace.ts") -const { getAceTriggeredData } = require("./__api.js") +const { setAceClickedCallback } = require("../../../main/ipc/ace.ts"); +const { getAceTriggeredData } = require("./__api.js"); function callback(data) { const cb = data.selfArgs[0]; @@ -8,11 +8,13 @@ function callback(data) { if (typeof cb !== "function") return; setAceClickedCallback((rawData) => { - cb(getAceTriggeredData({ - data: rawData, - mainSender - })); + cb( + getAceTriggeredData({ + data: rawData, + mainSender, + }), + ); }); } -module.exports = { callback }; \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/events/onFileOpened.js b/app/sandbox/permissions/events/onFileOpened.js index 2178c4e..b7a4545 100644 --- a/app/sandbox/permissions/events/onFileOpened.js +++ b/app/sandbox/permissions/events/onFileOpened.js @@ -1,11 +1,11 @@ -const { ipcMain } = require("electron") +const { ipcMain } = require("electron"); function callback(data) { - const cb = data.selfArgs[0] + const cb = data.selfArgs[0]; ipcMain.on("file-opened-event", (_, data) => { - cb(data) - }) + cb(data); + }); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/events/onInit.js b/app/sandbox/permissions/events/onInit.js index 0628109..219c685 100644 --- a/app/sandbox/permissions/events/onInit.js +++ b/app/sandbox/permissions/events/onInit.js @@ -1,9 +1,9 @@ -const { ipcMain } = require("electron") +const { ipcMain } = require("electron"); function callback(data) { - const cb = data.selfArgs[0] + const cb = data.selfArgs[0]; - cb(data) + cb(data); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/http/request.js b/app/sandbox/permissions/http/request.js index aeeb03e..e2b9d24 100644 --- a/app/sandbox/permissions/http/request.js +++ b/app/sandbox/permissions/http/request.js @@ -1,24 +1,20 @@ -function callback(data) { - const properties = data.selfArgs[0] - const url = properties.url +async function callback(data) { + const properties = data.selfArgs[0]; + const url = properties.url; const method = properties.method || "GET"; const headers = properties.headers || {}; - const body = properties.body + const body = properties.body; try { const options = { method, - headers + headers, }; - const hasContentType = Object.keys(headers).some( - k => k.toLowerCase() === "content-type" - ); + const hasContentType = Object.keys(headers).some((k) => k.toLowerCase() === "content-type"); if (body && method !== "GET") { - options.body = typeof body === "string" - ? body - : JSON.stringify(body); + options.body = typeof body === "string" ? body : JSON.stringify(body); if (hasContentType) { options.headers["Content-Type"] = "application/json"; @@ -36,23 +32,18 @@ function callback(data) { data = text; } - return async () => { - return { - status: res.status, - ok: res.ok, - headers: Object.fromEntries(res.headers.entries()), - data - } - }; - + return async () => ({ + status: res.status, + ok: res.ok, + headers: Object.fromEntries(res.headers.entries()), + data, + }); } catch (err) { - return async () => { - return { - ok: false, - error: err.message - } - }; + return async () => ({ + ok: false, + error: err.message, + }); } } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/js/clearInterval.js b/app/sandbox/permissions/js/clearInterval.js index 2e31801..d208594 100644 --- a/app/sandbox/permissions/js/clearInterval.js +++ b/app/sandbox/permissions/js/clearInterval.js @@ -1,5 +1,5 @@ function callback(data) { - clearInterval(data.selfArgs[0]) + clearInterval(data.selfArgs[0]); } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/js/clearTimeout.js b/app/sandbox/permissions/js/clearTimeout.js index 7c2f5ed..d53a3b3 100644 --- a/app/sandbox/permissions/js/clearTimeout.js +++ b/app/sandbox/permissions/js/clearTimeout.js @@ -1,5 +1,5 @@ function callback(data) { - clearTimeout(data.selfArgs[0]) + clearTimeout(data.selfArgs[0]); } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/js/setInterval.js b/app/sandbox/permissions/js/setInterval.js index 1755317..e9b013e 100644 --- a/app/sandbox/permissions/js/setInterval.js +++ b/app/sandbox/permissions/js/setInterval.js @@ -1,12 +1,12 @@ function callback(data) { - const cb = data.selfArgs[0] - const delay = Number(data.selfArgs[1]) + const cb = data.selfArgs[0]; + const delay = Number(data.selfArgs[1]); if (typeof cb !== "function") { - throw new Error("[APP.setInterval] First argument must be a function") + throw new Error("[APP.setInterval] First argument must be a function"); } - return setInterval(cb, Number.isFinite(delay) ? delay : 0) + return setInterval(cb, Number.isFinite(delay) ? delay : 0); } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/js/setTimeout.js b/app/sandbox/permissions/js/setTimeout.js index 9c0de61..1e949c8 100644 --- a/app/sandbox/permissions/js/setTimeout.js +++ b/app/sandbox/permissions/js/setTimeout.js @@ -1,12 +1,12 @@ function callback(data) { - const cb = data.selfArgs[0] - const delay = Number(data.selfArgs[1]) + const cb = data.selfArgs[0]; + const delay = Number(data.selfArgs[1]); if (typeof cb !== "function") { - throw new Error(`[${data.permissionName}] First argument must be a function`) + throw new Error(`[${data.permissionName}] First argument must be a function`); } - return setTimeout(cb, Number.isFinite(delay) ? delay : 0) + return setTimeout(cb, Number.isFinite(delay) ? delay : 0); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/localization/register.js b/app/sandbox/permissions/localization/register.js index fe0e1de..dd8e0ec 100644 --- a/app/sandbox/permissions/localization/register.js +++ b/app/sandbox/permissions/localization/register.js @@ -1,49 +1,52 @@ -const path = require("node:path") -const { saveReadFile, createSandboxConsole, checkFields } = require("../../tools.js") +const path = require("node:path"); +const { saveReadFile, createSandboxConsole, checkFields } = require("../../tools.js"); function callback(data) { - const langName = data.selfArgs[0] - const configPath = data.selfArgs[1] - const extPath = data.extensionPath - const extName = data.extensionName - const permName = data.permissionName - const mainSender = data.mainSender - const debuggerSender = data.debuggerSender - - const c = createSandboxConsole(extName, debuggerSender) - - if(!langName) { - c.error(`[${permName}] Each language must have a unique name-id. For example: en`) - return + const langName = data.selfArgs[0]; + const configPath = data.selfArgs[1]; + const extPath = data.extensionPath; + const extName = data.extensionName; + const permName = data.permissionName; + const mainSender = data.mainSender; + const debuggerSender = data.debuggerSender; + + const c = createSandboxConsole(extName, debuggerSender); + + if (!langName) { + c.error(`[${permName}] Each language must have a unique name-id. For example: en`); + return; } - if(configPath) { - let configContent = saveReadFile(path.join(extPath, configPath + ".json")) - configContent = JSON.parse(configContent) + if (configPath) { + let configContent = saveReadFile(path.join(extPath, configPath + ".json")); + configContent = JSON.parse(configContent); - if(!configContent) { - c.error(`[${permName}] Config "${configPath}.json" is empty or not exists`) - return - } - else { + if (configContent) { try { checkFields(`${permName}:config`, configContent, { - name: "string" - }) - - mainSender.send("extension-localization-register", { langName, configContent, from: extName }) - } - catch(e) { - c.error(String(e)) + name: "string", + }); + + mainSender.send("extension-localization-register", { + langName, + configContent, + from: extName, + }); + } catch (e) { + c.error(String(e)); } + } else { + c.error(`[${permName}] Config "${configPath}.json" is empty or not exists`); + return; } - } - else { - c.error(`[${permName}] The language configuration must be the second argument after the name-id`) - return + } else { + c.error( + `[${permName}] The language configuration must be the second argument after the name-id`, + ); + return; } - return () => {} + return () => {}; } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/notification/send.js b/app/sandbox/permissions/notification/send.js index 006f0ef..9da26f4 100644 --- a/app/sandbox/permissions/notification/send.js +++ b/app/sandbox/permissions/notification/send.js @@ -1,11 +1,11 @@ -const { saveReadFile } = require("../../tools.js") -const path = require("path") +const { saveReadFile } = require("../../tools.js"); +const path = require("path"); function callback(data) { - const extName = data.extensionName - const notificationData = data.selfArgs[0] + const extName = data.extensionName; + const notificationData = data.selfArgs[0]; - data.mainSender.send("extension-notification", extName, notificationData) + data.mainSender.send("extension-notification", extName, notificationData); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/shell/exec.js b/app/sandbox/permissions/shell/exec.js index e7410ab..6c5aa1e 100644 --- a/app/sandbox/permissions/shell/exec.js +++ b/app/sandbox/permissions/shell/exec.js @@ -1,51 +1,51 @@ -const { exec } = require("child_process") +const { exec } = require("child_process"); function callback(data) { return (...args) => { - const command = args[0] - const options = args[1] || {} - const onData = args[2] || null + const command = args[0]; + const options = args[1] || {}; + const onData = args[2] || null; if (typeof command !== "string" || command.length === 0) { - throw new Error("[shell.exec] First argument must be a non-empty command string") + throw new Error("[shell.exec] First argument must be a non-empty command string"); } return new Promise((resolve) => { const proc = exec(command, { encoding: options.encoding || "utf-8", - timeout: options.timeout || 60000, + timeout: options.timeout || 60_000, maxBuffer: options.maxBuffer || 1024 * 1024 * 5, cwd: options.cwd || undefined, env: options.env || process.env, - shell: options.shell || true - }) + shell: true, + }); - let stdout = "" - let stderr = "" + let stdout = ""; + let stderr = ""; proc.stdout.on("data", (chunk) => { - stdout += chunk + stdout += chunk; if (typeof onData === "function") { - onData({ type: "stdout", data: chunk.toString() }) + onData({ type: "stdout", data: chunk.toString() }); } - }) + }); proc.stderr.on("data", (chunk) => { - stderr += chunk + stderr += chunk; if (typeof onData === "function") { - onData({ type: "stderr", data: chunk.toString() }) + onData({ type: "stderr", data: chunk.toString() }); } - }) + }); proc.on("close", (code) => { - resolve({ stdout, stderr, ok: code === 0, code }) - }) + resolve({ stdout, stderr, ok: code === 0, code }); + }); proc.on("error", (err) => { - resolve({ stdout, stderr: err.message, ok: false, code: -1 }) - }) - }) - } + resolve({ stdout, stderr: err.message, ok: false, code: -1 }); + }); + }); + }; } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/shell/info.js b/app/sandbox/permissions/shell/info.js index 37354ae..08b0111 100644 --- a/app/sandbox/permissions/shell/info.js +++ b/app/sandbox/permissions/shell/info.js @@ -1,21 +1,21 @@ -const os = require("os") +const os = require("os"); function callback(data) { return (...args) => { - const platform = os.platform() - const arch = os.arch() + const platform = os.platform(); + const arch = os.arch(); const platformMap = { win32: "windows", darwin: "macos", linux: "linux", - freebsd: "freebsd" - } + freebsd: "freebsd", + }; return { platform: platformMap[platform] || platform, platformRaw: platform, - arch: arch, + arch, release: os.release(), hostname: os.hostname(), cpus: os.cpus().length, @@ -25,10 +25,10 @@ function callback(data) { tmpDir: os.tmpdir(), userInfo: { username: os.userInfo().username, - uid: os.userInfo().uid - } - } - } + uid: os.userInfo().uid, + }, + }; + }; } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/shell/kill.js b/app/sandbox/permissions/shell/kill.js index fe41646..272eb96 100644 --- a/app/sandbox/permissions/shell/kill.js +++ b/app/sandbox/permissions/shell/kill.js @@ -1,59 +1,66 @@ -const { execSync } = require("child_process") -const os = require("os") +const { execSync } = require("child_process"); +const os = require("os"); function callback(data) { return (...args) => { - const target = args[0] - const force = args[1] || false + const target = args[0]; + const force = args[1]; if (target === undefined || target === null) { - throw new Error("[shell.kill] First argument must be a process ID (number) or process/exe name (string)") + throw new Error( + "[shell.kill] First argument must be a process ID (number) or process/exe name (string)", + ); } - const platform = os.platform() + const platform = os.platform(); try { - if (typeof target === "number" || (typeof target === "string" && /^\d+$/.test(target))) { - const pid = Number(target) - if (pid <= 0) throw new Error("[shell.kill] Process ID must be a positive number") + if ( + typeof target === "number" || + (typeof target === "string" && /^\d+$/.test(target)) + ) { + const pid = Number(target); + if (pid <= 0) throw new Error("[shell.kill] Process ID must be a positive number"); if (platform === "win32") { - const cmd = force ? `taskkill /PID ${pid} /F` : `taskkill /PID ${pid}` - execSync(cmd, { encoding: "utf-8", stdio: "pipe" }) + const cmd = force ? `taskkill /PID ${pid} /F` : `taskkill /PID ${pid}`; + execSync(cmd, { encoding: "utf-8", stdio: "pipe" }); } else { - process.kill(pid, force ? "SIGKILL" : "SIGTERM") + process.kill(pid, force ? "SIGKILL" : "SIGTERM"); } - return { ok: true, pid } + return { ok: true, pid }; } - const name = String(target) + const name = String(target); if (platform === "win32") { - const cmd = force - ? `taskkill /IM "${name}" /F` - : `taskkill /IM "${name}"` - execSync(cmd, { encoding: "utf-8", stdio: "pipe" }) - return { ok: true, name } - } else { - const signal = force ? "SIGKILL" : "SIGTERM" - const result = execSync(`pgrep -f "${name}"`, { encoding: "utf-8", stdio: "pipe" }).trim() - const pids = result.split("\n").filter(Boolean).map(Number) - - if (pids.length === 0) { - return { ok: false, error: `No process found matching "${name}"`, name } - } - - pids.forEach(pid => { - try { process.kill(pid, signal) } catch {} - }) + const cmd = force ? `taskkill /IM "${name}" /F` : `taskkill /IM "${name}"`; + execSync(cmd, { encoding: "utf-8", stdio: "pipe" }); + return { ok: true, name }; + } + const signal = force ? "SIGKILL" : "SIGTERM"; + const result = execSync(`pgrep -f "${name}"`, { + encoding: "utf-8", + stdio: "pipe", + }).trim(); + const pids = result.split("\n").filter(Boolean).map(Number); - return { ok: true, name, pids } + if (pids.length === 0) { + return { ok: false, error: `No process found matching "${name}"`, name }; } + + pids.forEach((pid) => { + try { + process.kill(pid, signal); + } catch {} + }); + + return { ok: true, name, pids }; } catch (err) { - return { ok: false, error: err.message, target: String(target) } + return { ok: false, error: err.message, target: String(target) }; } - } + }; } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/shell/run.js b/app/sandbox/permissions/shell/run.js index 457a54e..ccfdb97 100644 --- a/app/sandbox/permissions/shell/run.js +++ b/app/sandbox/permissions/shell/run.js @@ -1,34 +1,34 @@ -const { execSync } = require("child_process") +const { execSync } = require("child_process"); function callback(data) { return (...args) => { - const command = args[0] - const options = args[1] || {} + const command = args[0]; + const options = args[1] || {}; if (typeof command !== "string" || command.length === 0) { - throw new Error("[shell.run] First argument must be a non-empty command string") + throw new Error("[shell.run] First argument must be a non-empty command string"); } try { const result = execSync(command, { encoding: options.encoding || "utf-8", - timeout: options.timeout || 30000, + timeout: options.timeout || 30_000, maxBuffer: options.maxBuffer || 1024 * 1024, cwd: options.cwd || undefined, env: options.env || process.env, - shell: options.shell || true - }) + shell: true, + }); - return { stdout: result, stderr: "", ok: true } + return { stdout: result, stderr: "", ok: true }; } catch (err) { return { stdout: err.stdout || "", stderr: err.stderr || err.message, ok: false, - code: err.status - } + code: err.status, + }; } - } + }; } -module.exports = { callback } +module.exports = { callback }; diff --git a/app/sandbox/permissions/theme/new.js b/app/sandbox/permissions/theme/new.js index d65f9ca..9caf972 100644 --- a/app/sandbox/permissions/theme/new.js +++ b/app/sandbox/permissions/theme/new.js @@ -1,51 +1,50 @@ -const { checkFields } = require("../../tools.js") +const { checkFields } = require("../../tools.js"); function callback(data) { - const themeName = data.selfArgs[0] - const themeData = data.selfArgs[1] - const extName = data.extensionName - const permissionName = data.permissionName + const themeName = data.selfArgs[0]; + const themeData = data.selfArgs[1]; + const extName = data.extensionName; + const permissionName = data.permissionName; - let allCSSVariables = data.allCSSVariables + let allCssVariables = data.allCSSVariables; checkFields(permissionName, themeData, { id: "string", variables: "object", - editorTheme: "string" - }) + editorTheme: "string", + }); - let variables = [] + const variables = []; - Object.keys(themeData.variables).forEach(v => { + Object.keys(themeData.variables).forEach((v) => { variables.push(`${v}: ${themeData.variables[v]}`); - allCSSVariables = allCSSVariables.map(item => { + allCssVariables = allCssVariables.map((item) => { const name = item.split(":")[0].trim(); const value = themeData.variables[name]; if (value) { return `${name}: ${value}`; - } else { - return `${name}: default`; } + return `${name}: default`; }); }); - themeData.variables = variables.join(";") + themeData.variables = variables.join(";"); - data.mainSender.send("new-theme-register", themeName, themeData) + data.mainSender.send("new-theme-register", themeName, themeData); data.debuggerSender.send("debug-event", { data: { type: "newCommand", command: { name: "CSSVariables", - response: `A list of current CSS variables will be displayed below. The format is "name:value":\n${allCSSVariables.join(", \n")}` + response: `A list of current CSS variables will be displayed below. The format is "name:value":\n${allCssVariables.join(", \n")}`, }, - from: extName + from: extName, }, - time: Date.now() - }) + time: Date.now(), + }); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/tools/regex/toString.js b/app/sandbox/permissions/tools/regex/toString.js index b5f027b..44e1d4d 100644 --- a/app/sandbox/permissions/tools/regex/toString.js +++ b/app/sandbox/permissions/tools/regex/toString.js @@ -1,13 +1,13 @@ function callback(data) { - const regex = data.selfArgs[0] + const regex = data.selfArgs[0]; let source = regex instanceof RegExp ? regex.source : String(regex); return () => { - source = source.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - source = source.slice(1) - source = source.slice(0, -1) - return source + source = source.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + source = source.slice(1); + source = source.slice(0, -1); + return source; }; } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/ui/createElement.js b/app/sandbox/permissions/ui/createElement.js index 8e801e0..cdf23ac 100644 --- a/app/sandbox/permissions/ui/createElement.js +++ b/app/sandbox/permissions/ui/createElement.js @@ -5,208 +5,244 @@ const { ExtensionError, createSandboxConsole } = require("../../tools"); function checkForMatch(originalObject, matchObject) { const allowed = new Set(Object.keys(matchObject)); - return Object.keys(originalObject).filter(key => !allowed.has(key)); + return Object.keys(originalObject).filter((key) => !allowed.has(key)); } function callback(data) { - const elType = data.selfArgs[0] - const mainSender = data.mainSender - const debuggerSender = data.debuggerSender - const extName = data.extensionName - const extPath = data.extensionPath + const elType = data.selfArgs[0]; + const mainSender = data.mainSender; + const debuggerSender = data.debuggerSender; + const extName = data.extensionName; + const extPath = data.extensionPath; - const allowedImageFormats = ["gif", "png", "jpg", "jpeg", "svg"] + const allowedImageFormats = ["gif", "png", "jpg", "jpeg", "svg"]; - const c = createSandboxConsole(extName, debuggerSender) + const c = createSandboxConsole(extName, debuggerSender); - const list = {} + const list = {}; function createElement(type) { - const id = crypto.randomUUID() - const events = {} + const id = crypto.randomUUID(); + const events = {}; function genObj(object) { return { - id: id, - extName: extName, - ...object - } + id, + extName, + ...object, + }; } - list[id] = {} + list[id] = {}; - mainSender.send("extension-create-element", genObj({ - type: type - })) + mainSender.send( + "extension-create-element", + genObj({ + type, + }), + ); const properties = { on: (eventName, callback) => { if (typeof eventName != "string") { - c.error(`[${type}:on] Event name must be a string`) + c.error(`[${type}:on] Event name must be a string`); } if (typeof callback != "function") { - c.error(`[${type}:on] Callback must be a function`) + c.error(`[${type}:on] Callback must be a function`); } - mainSender.send("extension-mod-element", genObj({ - type: "onEvent", - value: eventName, - })) + mainSender.send( + "extension-mod-element", + genObj({ + type: "onEvent", + value: eventName, + }), + ); - events[eventName] = callback + events[eventName] = callback; - list[id]["events"] = events + list[id]["events"] = events; }, setSize: (object) => { if (typeof object != "object") { - c.error(`[${type}:setSize] Argument 0 must be an object`) + c.error(`[${type}:setSize] Argument 0 must be an object`); } const sizes = { - "width": "width: {v}px", - "height": "height: {v}px", - } + width: "width: {v}px", + height: "height: {v}px", + }; - const sizesMatch = checkForMatch(object, sizes) + const sizesMatch = checkForMatch(object, sizes); if (sizesMatch.length > 0) { - c.error(`[${type}:setSize] Undefined size name(-s): ${sizesMatch.join(", ")}`) + c.error(`[${type}:setSize] Undefined size name(-s): ${sizesMatch.join(", ")}`); } - mainSender.send("extension-mod-element", genObj({ - type: "setSize", - value: { - availableSizes: sizes, - sizes: object - }, - })) - - list[id]["size"] = object + mainSender.send( + "extension-mod-element", + genObj({ + type: "setSize", + value: { + availableSizes: sizes, + sizes: object, + }, + }), + ); + + list[id]["size"] = object; }, setPosition: (object) => { if (typeof object != "object") { - c.error(`[${type}:on] Argument 0 must be an object`) + c.error(`[${type}:on] Argument 0 must be an object`); } const positions = { - "bottom": "bottom: {v}px", - "right": "right: {v}px", - "left": "left: {v}px", - "top": "top: {v}px" - } + bottom: "bottom: {v}px", + right: "right: {v}px", + left: "left: {v}px", + top: "top: {v}px", + }; - const positionsMatch = checkForMatch(object, positions) + const positionsMatch = checkForMatch(object, positions); if (positionsMatch.length > 0) { - c.error(`[${type}:setPosition] Undefined position name(-s): ${positionsMatch.join(", ")}`) + c.error( + `[${type}:setPosition] Undefined position name(-s): ${positionsMatch.join(", ")}`, + ); } - mainSender.send("extension-mod-element", genObj({ - type: "setPosition", - value: { - availablePositions: positions, - positions: object - } - })) - - list[id]["position"] = object - } - } + mainSender.send( + "extension-mod-element", + genObj({ + type: "setPosition", + value: { + availablePositions: positions, + positions: object, + }, + }), + ); + + list[id]["position"] = object; + }, + }; - if(type == "image") { + if (type == "image") { properties["src"] = (srcPath) => { - const srcBase = srcPath.split("?")[0] - if(!allowedImageFormats.includes(srcBase.split(".").pop())) { - c.error(`[${type}:src] This image format is not supported. Supported formats: ${allowedImageFormats.join(", ")}`) + const srcBase = srcPath.split("?")[0]; + if (!allowedImageFormats.includes(srcBase.split(".").pop())) { + c.error( + `[${type}:src] This image format is not supported. Supported formats: ${allowedImageFormats.join(", ")}`, + ); } - const query = srcPath.includes("?") ? "?" + srcPath.split("?")[1] : "" - const p = path.join(extPath, srcBase) + query + const query = srcPath.includes("?") ? "?" + srcPath.split("?")[1] : ""; + const p = path.join(extPath, srcBase) + query; - mainSender.send("extension-mod-element", genObj({ - type: "setSrc", - value: p, - })) + mainSender.send( + "extension-mod-element", + genObj({ + type: "setSrc", + value: p, + }), + ); - list[id]["src"] = p - } + list[id]["src"] = p; + }; } - if(type == "topbarItem") { + if (type == "topbarItem") { properties["setup"] = (properties = {}) => { - if("image" in properties) { - const imgBase = properties.image.split("?")[0] - const imgQuery = properties.image.includes("?") ? "?" + properties.image.split("?")[1] : "" - if(!allowedImageFormats.includes(imgBase.split(".").pop())) { - c.error(`[${type}:setup:image] This image format is not supported. Supported formats: ${allowedImageFormats.join(", ")}`) + if ("image" in properties) { + const imgBase = properties.image.split("?")[0]; + const imgQuery = properties.image.includes("?") + ? "?" + properties.image.split("?")[1] + : ""; + if (!allowedImageFormats.includes(imgBase.split(".").pop())) { + c.error( + `[${type}:setup:image] This image format is not supported. Supported formats: ${allowedImageFormats.join(", ")}`, + ); } - properties.image = path.join(extPath, imgBase) + imgQuery + properties.image = path.join(extPath, imgBase) + imgQuery; } - mainSender.send("extension-mod-element", genObj({ - type: "setTopbarItemSetup", - value: properties, - })) + mainSender.send( + "extension-mod-element", + genObj({ + type: "setTopbarItemSetup", + value: properties, + }), + ); - list[id]["properties"] = properties - } + list[id]["properties"] = properties; + }; properties["hide"] = () => { - mainSender.send("extension-mod-element", genObj({ - type: "setTopbarItemHide" - })) - } + mainSender.send( + "extension-mod-element", + genObj({ + type: "setTopbarItemHide", + }), + ); + }; properties["hideText"] = () => { - mainSender.send("extension-mod-element", genObj({ - type: "setTopbarItemHideWithIcon" - })) - } + mainSender.send( + "extension-mod-element", + genObj({ + type: "setTopbarItemHideWithIcon", + }), + ); + }; properties["show"] = () => { - mainSender.send("extension-mod-element", genObj({ - type: "setTopbarItemShow" - })) - } + mainSender.send( + "extension-mod-element", + genObj({ + type: "setTopbarItemShow", + }), + ); + }; properties["on"] = (eventName, callback = () => {}) => { - mainSender.send("extension-mod-element", genObj({ - type: "setTopbarItemEvent", - value: eventName - })) - - events[eventName] = callback - - list[id]["events"] = events - } + mainSender.send( + "extension-mod-element", + genObj({ + type: "setTopbarItemEvent", + value: eventName, + }), + ); + + events[eventName] = callback; + + list[id]["events"] = events; + }; } - return properties + return properties; } // listen to external changes ipcMain.on("extension-send-element", (_, object) => { - const type = object.type - const id = object.id - const data = object.data + const type = object.type; + const id = object.id; + const data = object.data; - const current = list[id] + const current = list[id]; - if(type == "onEventTriggered" && current) { - const eventName = data.eventName + if (type == "onEventTriggered" && current) { + const eventName = data.eventName; - if(eventName in current.events) { - current.events[eventName]() + if (eventName in current.events) { + current.events[eventName](); } } - }) + }); const elements = { image: createElement("image"), - topbarItem: createElement("topbarItem") - } + topbarItem: createElement("topbarItem"), + }; - if(elType in elements) { - return () => { - return elements[elType] - } + if (elType in elements) { + return () => elements[elType]; } } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/window/close.js b/app/sandbox/permissions/window/close.js index ef80c73..b527bf0 100644 --- a/app/sandbox/permissions/window/close.js +++ b/app/sandbox/permissions/window/close.js @@ -4,4 +4,4 @@ function callback(data) { app.quit(); } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/permissions/window/create.js b/app/sandbox/permissions/window/create.js index e4e0fe1..7652bdc 100644 --- a/app/sandbox/permissions/window/create.js +++ b/app/sandbox/permissions/window/create.js @@ -1,37 +1,36 @@ -const { createNativeImageFromUrl } = require("../../tools.js") -const { BrowserWindow } = require("electron") +const { createNativeImageFromUrl } = require("../../tools.js"); +const { BrowserWindow } = require("electron"); function callback(data) { return (id, properties = {}) => { if (id == undefined) { - id = Math.floor(Math.random() * 9999) + 1 + id = Math.floor(Math.random() * 9999) + 1; } - const title = properties.title == undefined ? `${data.extensionName} Window` : properties.title - const url = properties.url == undefined ? `google.com` : properties.url + const title = + properties.title == undefined ? `${data.extensionName} Window` : properties.title; + const url = properties.url == undefined ? "google.com" : properties.url; - const win = new BrowserWindow( - { - width: 800, - height: 600, - show: false - } - ) - win.setMenu(null) + const win = new BrowserWindow({ + width: 800, + height: 600, + show: false, + }); + win.setMenu(null); - win.setTitle(title) - win.loadURL(`https://${url}`) + win.setTitle(title); + win.loadURL(`https://${url}`); return { - id: id, + id, open: () => { - win.show() + win.show(); }, close: () => { - win.close() - } - } - } + win.close(); + }, + }; + }; } -module.exports = { callback } \ No newline at end of file +module.exports = { callback }; diff --git a/app/sandbox/regs/docs.js b/app/sandbox/regs/docs.js index f151288..285475b 100644 --- a/app/sandbox/regs/docs.js +++ b/app/sandbox/regs/docs.js @@ -1,11 +1,11 @@ -const { ipcMain } = require("electron") -const { checkFields, saveReadFile } = require("../tools") -const path = require("path") +const { ipcMain } = require("electron"); +const { checkFields, saveReadFile } = require("../tools"); +const path = require("path"); -const bus = require("../../../helpers/eventBus") +const bus = require("../../../helpers/eventBus"); -let debuggerSender = null -let mainSender = null +let debuggerSender = null; +let mainSender = null; bus.on("debugger-ready", (sender) => { debuggerSender = sender; @@ -15,31 +15,30 @@ bus.on("main-ready", (sender) => { }); ipcMain.on("docs-register", async (event, data) => { - const configPath = data.configPath - const extPath = data.extensionPath - const extName = data.extensionName + const configPath = data.configPath; + const extPath = data.extensionPath; + const extName = data.extensionName; - let documentationProperties = {} + let documentationProperties = {}; if (configPath) { - let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true) - configContent = JSON.parse(configContent) + let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true); + configContent = JSON.parse(configContent); - const docPropertiesKey = "__$props__" + const docPropertiesKey = "__$props__"; if (Object.keys(configContent).length > 0) { // check $props and fields - if(docPropertiesKey in configContent) { - documentationProperties = configContent[docPropertiesKey] + if (docPropertiesKey in configContent) { + documentationProperties = configContent[docPropertiesKey]; checkFields(`docs.register:config:${docPropertiesKey}`, documentationProperties, { - onMode: "string" - }) + onMode: "string", + }); - delete configContent[docPropertiesKey] - } - else { - throw new Error(`docs.register: key "$props" in documentation config is required`) + delete configContent[docPropertiesKey]; + } else { + throw new Error(`docs.register: key "$props" in documentation config is required`); } // check each config item @@ -48,14 +47,14 @@ ipcMain.on("docs-register", async (event, data) => { type: "string", description: "string", example: "string", - sources: "array" - }) - }) + sources: "array", + }); + }); mainSender.send("new-documentation-register", { config: configContent, - props: documentationProperties - }) + props: documentationProperties, + }); } } -}) \ No newline at end of file +}); diff --git a/app/sandbox/regs/fileExtensions.js b/app/sandbox/regs/fileExtensions.js index f9c942f..ff285aa 100644 --- a/app/sandbox/regs/fileExtensions.js +++ b/app/sandbox/regs/fileExtensions.js @@ -1,11 +1,11 @@ -const { ipcMain } = require("electron") -const { checkFields, saveReadFile, createSandboxConsole, ExtensionError } = require("../tools") -const path = require("path") +const { ipcMain } = require("electron"); +const { checkFields, saveReadFile, createSandboxConsole, ExtensionError } = require("../tools"); +const path = require("path"); -const bus = require("../../../helpers/eventBus") +const bus = require("../../../helpers/eventBus"); -let debuggerSender = null -let mainSender = null +let debuggerSender = null; +let mainSender = null; bus.on("debugger-ready", (sender) => { debuggerSender = sender; @@ -15,36 +15,35 @@ bus.on("main-ready", (sender) => { }); ipcMain.on("file-extensions-register", async (event, data) => { - const configPath = data.configPath - const extPath = data.extensionPath - const extName = data.extensionName + const configPath = data.configPath; + const extPath = data.extensionPath; + const extName = data.extensionName; - const c = createSandboxConsole(extName, debuggerSender) + const c = createSandboxConsole(extName, debuggerSender); if (configPath) { - let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true) - configContent = JSON.parse(configContent) + let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true); + configContent = JSON.parse(configContent); if (Object.keys(configContent).length > 0) { - Object.keys(configContent).forEach(item => { - const filename = configContent[item] + Object.keys(configContent).forEach((item) => { + const filename = configContent[item]; try { checkFields(`fileExtensions:register:${item}`, filename, { icon: "SVGFile|PNGFile", name: "string", - mode: "string" - }) + mode: "string", + }); + } catch (e) { + c.error(String(e)); } - catch(e) { - c.error(String(e)) - } - }) + }); mainSender.send("new-file-extensions-register", { config: configContent, - extPath: extPath - }) + extPath, + }); } } -}) \ No newline at end of file +}); diff --git a/app/sandbox/regs/filenames.js b/app/sandbox/regs/filenames.js index 178acd6..925b9c3 100644 --- a/app/sandbox/regs/filenames.js +++ b/app/sandbox/regs/filenames.js @@ -1,11 +1,11 @@ -const { ipcMain } = require("electron") -const { checkFields, saveReadFile, createSandboxConsole, ExtensionError } = require("../tools") -const path = require("path") +const { ipcMain } = require("electron"); +const { checkFields, saveReadFile, createSandboxConsole, ExtensionError } = require("../tools"); +const path = require("path"); -const bus = require("../../../helpers/eventBus") +const bus = require("../../../helpers/eventBus"); -let debuggerSender = null -let mainSender = null +let debuggerSender = null; +let mainSender = null; bus.on("debugger-ready", (sender) => { debuggerSender = sender; @@ -15,36 +15,35 @@ bus.on("main-ready", (sender) => { }); ipcMain.on("filenames-register", async (event, data) => { - const configPath = data.configPath - const extPath = data.extensionPath - const extName = data.extensionName + const configPath = data.configPath; + const extPath = data.extensionPath; + const extName = data.extensionName; - const c = createSandboxConsole(extName, debuggerSender) + const c = createSandboxConsole(extName, debuggerSender); if (configPath) { - let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true) - configContent = JSON.parse(configContent) + let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true); + configContent = JSON.parse(configContent); if (Object.keys(configContent).length > 0) { - Object.keys(configContent).forEach(item => { - const filename = configContent[item] + Object.keys(configContent).forEach((item) => { + const filename = configContent[item]; try { checkFields(`filenames:register:${item}`, filename, { icon: "SVGFile|PNGFile", name: "string", - mode: "string" - }) + mode: "string", + }); + } catch (e) { + c.error(String(e)); } - catch(e) { - c.error(String(e)) - } - }) + }); mainSender.send("new-filenames-register", { config: configContent, - extPath: extPath - }) + extPath, + }); } } -}) \ No newline at end of file +}); diff --git a/app/sandbox/regs/language.js b/app/sandbox/regs/language.js index e65ee6e..b3da3c9 100644 --- a/app/sandbox/regs/language.js +++ b/app/sandbox/regs/language.js @@ -1,10 +1,10 @@ -const { app, ipcMain } = require("electron") -const { checkFields, saveReadFile, isFileExists } = require("../tools") -const path = require("path") -const bus = require("../../../helpers/eventBus") +const { app, ipcMain } = require("electron"); +const { checkFields, saveReadFile, isFileExists } = require("../tools"); +const path = require("path"); +const bus = require("../../../helpers/eventBus"); -let debuggerSender = null -let mainSender = null +let debuggerSender = null; +let mainSender = null; bus.on("debugger-ready", (sender) => { debuggerSender = sender; @@ -14,49 +14,54 @@ bus.on("main-ready", (sender) => { }); ipcMain.on("language-register", async (event, data) => { - const configPath = data.configPath - const extPath = data.extensionPath - const extName = data.extensionName + const configPath = data.configPath; + const extPath = data.extensionPath; + const extName = data.extensionName; if (configPath) { - let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true) - configContent = JSON.parse(configContent) + let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true); + configContent = JSON.parse(configContent); - checkFields(`language.register:config`, configContent, { + checkFields("language.register:config", configContent, { name: "string", displayName: "string", extensions: "array", - rules: "string" - }) + rules: "string", + }); - let rulesConfig = saveReadFile(path.join(extPath, configContent.rules + ".json"), true) - rulesConfig = JSON.parse(rulesConfig) + let rulesConfig = saveReadFile(path.join(extPath, configContent.rules + ".json"), true); + rulesConfig = JSON.parse(rulesConfig); - checkFields(`language.register:config:rules`, rulesConfig, { + checkFields("language.register:config:rules", rulesConfig, { syntax: "object", // autocomplete: "object" - }) + }); - let iconPath = false - const defaultIcon = path.join(app.getAppPath(), "assets", "media", "icons", "default.svg") + let iconPath = false; + const defaultIcon = path.join(app.getAppPath(), "assets", "media", "icons", "default.svg"); if ("icon" in configContent) { - checkFields(`language.register:config`, configContent, { - icon: "SVGFile|PNGFile" - }) + checkFields("language.register:config", configContent, { + icon: "SVGFile|PNGFile", + }); - iconPath = path.join(extPath, configContent.icon) - isFileExists(iconPath, true) - } - else { - iconPath = defaultIcon + iconPath = path.join(extPath, configContent.icon); + isFileExists(iconPath, true); + } else { + iconPath = defaultIcon; for (const e of configContent.extensions) { - let extIconPath = path.join(app.getAppPath(), "assets", "media", "icons", `${e}.svg`) + const extIconPath = path.join( + app.getAppPath(), + "assets", + "media", + "icons", + `${e}.svg`, + ); if (isFileExists(extIconPath)) { - iconPath = extIconPath - break + iconPath = extIconPath; + break; } } } @@ -66,35 +71,39 @@ ipcMain.on("language-register", async (event, data) => { languageDisplayName: configContent.displayName, languageExtensions: configContent.extensions, languageRules: rulesConfig, - languageIconPath: iconPath - } + languageIconPath: iconPath, + }; if ("documentation" in configContent) { - let documentationConfig = saveReadFile(path.join(extPath, configContent.documentation + ".json"), true) - documentationConfig = JSON.parse(documentationConfig) + let documentationConfig = saveReadFile( + path.join(extPath, configContent.documentation + ".json"), + true, + ); + documentationConfig = JSON.parse(documentationConfig); - dataToSend["languageDocumentation"] = documentationConfig + dataToSend["languageDocumentation"] = documentationConfig; } - + // send data if (mainSender && !mainSender.isDestroyed()) { - mainSender.send("on-language-register", dataToSend) + mainSender.send("on-language-register", dataToSend); } else { - console.error("[language.register] mainSender is destroyed") + console.error("[language.register] mainSender is destroyed"); } - if(debuggerSender) { + if (debuggerSender) { debuggerSender.send("debug-event", { data: { type: "msg", content: `Added new language: ${configContent.name}`, - from: extName + from: extName, }, - time: Date.now() - }) + time: Date.now(), + }); } + } else { + throw new Error( + "[language.register] You must specify the configuration for language registration", + ); } - else { - throw new Error(`[language.register] You must specify the configuration for language registration`) - } -}) \ No newline at end of file +}); diff --git a/app/sandbox/regs/templates.js b/app/sandbox/regs/templates.js index 376e841..abab058 100644 --- a/app/sandbox/regs/templates.js +++ b/app/sandbox/regs/templates.js @@ -1,11 +1,11 @@ -const { ipcMain } = require("electron") -const { checkFields, saveReadFile, createSandboxConsole, ExtensionError } = require("../tools") -const path = require("path") +const { ipcMain } = require("electron"); +const { checkFields, saveReadFile, createSandboxConsole, ExtensionError } = require("../tools"); +const path = require("path"); -const bus = require("../../../helpers/eventBus") +const bus = require("../../../helpers/eventBus"); -let debuggerSender = null -let mainSender = null +let debuggerSender = null; +let mainSender = null; bus.on("debugger-ready", (sender) => { debuggerSender = sender; @@ -15,39 +15,38 @@ bus.on("main-ready", (sender) => { }); ipcMain.on("templates-register", async (event, data) => { - const configPath = data.configPath - const extPath = data.extensionPath - const extName = data.extensionName + const configPath = data.configPath; + const extPath = data.extensionPath; + const extName = data.extensionName; - const c = createSandboxConsole(extName, debuggerSender) + const c = createSandboxConsole(extName, debuggerSender); if (configPath) { - let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true) - configContent = JSON.parse(configContent) + let configContent = saveReadFile(path.join(extPath, configPath + ".json"), true); + configContent = JSON.parse(configContent); - const keys = Object.keys(configContent) + const keys = Object.keys(configContent); if (keys.length > 0) { - keys.forEach(item => { - const extensionConfig = configContent[item] + keys.forEach((item) => { + const extensionConfig = configContent[item]; - extensionConfig.forEach(cfgItem => { + extensionConfig.forEach((cfgItem) => { try { checkFields(`templates:register:${item}`, cfgItem, { name: "string", - content: "string" - }) + content: "string", + }); + } catch (e) { + c.error(String(e)); } - catch(e) { - c.error(String(e)) - } - }) - }) + }); + }); mainSender.send("new-templates-register", { config: configContent, - extPath: extPath - }) + extPath, + }); } } -}) \ No newline at end of file +}); diff --git a/app/sandbox/sandbox.js b/app/sandbox/sandbox.js index 03ccc59..2f2431d 100644 --- a/app/sandbox/sandbox.js +++ b/app/sandbox/sandbox.js @@ -1,12 +1,12 @@ -const { app, ipcMain, BrowserWindow } = require("electron") -const fs = require("fs") -const path = require("path") -const bus = require("../../helpers/eventBus.js") -const { APP_PATH } = require("../main/helpers/paths.js") -const ErrorStackParser = require("error-stack-parser") - -const { - getType, +const { app, ipcMain, BrowserWindow } = require("electron"); +const fs = require("fs"); +const path = require("path"); +const bus = require("../../helpers/eventBus.js"); +const { APP_PATH } = require("../main/helpers/paths.js"); +const ErrorStackParser = require("error-stack-parser"); + +const { + getType, createNativeImageFromUrl, checkType, ok, @@ -17,27 +17,27 @@ const { isFileExists, checkFields, createSandboxConsole, - getArgumentNames -} = require("../sandbox/tools.js") -const { basicMinifyCSS } = require("../../helpers/minify.js") + getArgumentNames, +} = require("../sandbox/tools.js"); +const { basicMinifyCSS } = require("../../helpers/minify.js"); const vm = require("vm"); -const { config } = require("process") +const { config } = require("process"); const EXTENSIONS_DIR = path.resolve( - app.isPackaged ? process.resourcesPath : app.getAppPath(), - "extensions" -) + app.isPackaged ? process.resourcesPath : app.getAppPath(), + "extensions", +); -console.log("EXTENSIONS PATH:", EXTENSIONS_DIR) +console.log("EXTENSIONS PATH:", EXTENSIONS_DIR); let debuggerSender = null; let mainSender = null; -const rendererBus = require("../../assets/js/bus.js") +const rendererBus = require("../../assets/js/bus.js"); function parsePackageJson(raw) { - return JSON.parse(raw.replace(/^\uFEFF/, "")) + return JSON.parse(raw.replace(/^\uFEFF/, "")); } bus.on("debugger-ready", (sender) => { @@ -49,102 +49,96 @@ bus.on("main-ready", (sender) => { console.log("ExtensionManager: main connected"); }); -ipcMain.handle("get-extensions-dir", () => { - return EXTENSIONS_DIR -}) +ipcMain.handle("get-extensions-dir", () => EXTENSIONS_DIR); ipcMain.handle("request-extensions", async () => { try { if (!fs.existsSync(EXTENSIONS_DIR)) { - return fail("Extensions directory does not exist") + return fail("Extensions directory does not exist"); } - const files = await fs.promises.readdir(EXTENSIONS_DIR, { withFileTypes: true }) + const files = await fs.promises.readdir(EXTENSIONS_DIR, { withFileTypes: true }); - const dirs = files - .filter(f => f.isDirectory()) - .map(f => f.name) - - return ok(dirs) + const dirs = files.filter((f) => f.isDirectory()).map((f) => f.name); + return ok(dirs); } catch (err) { - return fail(err) + return fail(err); } -}) +}); ipcMain.handle("request-extension", async (event, name) => { try { if (!isSafeName(name)) { - return fail("Invalid extension name") + return fail("Invalid extension name"); } - const extPath = path.join(EXTENSIONS_DIR, name) + const extPath = path.join(EXTENSIONS_DIR, name); if (!fs.existsSync(extPath)) { - return fail("Extension not found") + return fail("Extension not found"); } - const stat = await fs.promises.stat(extPath) + const stat = await fs.promises.stat(extPath); if (!stat.isDirectory()) { - return fail("Extension is not a directory") + return fail("Extension is not a directory"); } - const packagePath = path.join(extPath, "package.json") + const packagePath = path.join(extPath, "package.json"); if (!fs.existsSync(packagePath)) { - return fail("package.json not found") + return fail("package.json not found"); } - const raw = await fs.promises.readFile(packagePath, "utf-8") + const raw = await fs.promises.readFile(packagePath, "utf-8"); - let json + let json; try { - json = parsePackageJson(raw) + json = parsePackageJson(raw); } catch { - return fail("Invalid JSON in package.json") + return fail("Invalid JSON in package.json"); } - return ok({ package: json, path: extPath }) - + return ok({ package: json, path: extPath }); } catch (err) { - return fail(err) + return fail(err); } -}) +}); ipcMain.handle("run-extension", async (event, code, permissions, meta) => { - const extensionName = meta.extensionName != undefined ? meta.extensionName : "Unknown" - const extensionVersion = meta.extensionVersion != undefined ? meta.extensionVersion : null - const extensionPath = meta.extensionPath != undefined ? meta.extensionPath : null - const isDev = meta.isDev != undefined ? meta.isDev : false - const activeOn = meta.activeOn - const isPackaged = app.isPackaged - const extensionSettings = meta.extensionSettings || {} - - let allCSSVariables = meta.allCSSVariables != undefined ? meta.allCSSVariables : [] - - function createAPI(permissions) { - const os = require("os") - const platformRaw = os.platform() + const extensionName = meta.extensionName == undefined ? "Unknown" : meta.extensionName; + const extensionVersion = meta.extensionVersion == undefined ? null : meta.extensionVersion; + const extensionPath = meta.extensionPath == undefined ? null : meta.extensionPath; + const isDev = meta.isDev == undefined ? false : meta.isDev; + const activeOn = meta.activeOn; + const isPackaged = app.isPackaged; + const extensionSettings = meta.extensionSettings || {}; + + const allCssVariables = meta.allCSSVariables == undefined ? [] : meta.allCSSVariables; + + function createApi(permissions) { + const os = require("os"); + const platformRaw = os.platform(); const platformMap = { win32: "windows", darwin: "macos", linux: "linux", - freebsd: "freebsd" - } + freebsd: "freebsd", + }; const app = { name: extensionName, - permissions: permissions, + permissions, version: extensionVersion, path: extensionPath, - isDev: isDev, - CSSVariables: allCSSVariables, - isPackaged: isPackaged, + isDev, + CSSVariables: allCssVariables, + isPackaged, settings: extensionSettings, os: { platform: platformMap[platformRaw] || platformRaw, - platformRaw: platformRaw, + platformRaw, arch: os.arch(), release: os.release(), hostname: os.hostname(), @@ -152,38 +146,42 @@ ipcMain.handle("run-extension", async (event, code, permissions, meta) => { totalMemory: os.totalmem(), freeMemory: os.freemem(), homeDir: os.homedir(), - tmpDir: os.tmpdir() - } + tmpDir: os.tmpdir(), + }, }; function setNestedProperty(obj, path, value) { - const parts = path.split(".") + const parts = path.split("."); - let current = obj + let current = obj; - for(let i = 0; i < parts.length - 1; i++) { - const part = parts[i] + for (let i = 0; i < parts.length - 1; i++) { + const part = parts[i]; - if(!current[part]) { - current[part] = {} + if (!current[part]) { + current[part] = {}; } - current = current[part] + current = current[part]; } - current[parts.at(-1)] = value + current[parts.at(-1)] = value; } - permissions.forEach(p => { - const checkRegex = /^[A-Za-z]+(?:\.[A-Za-z]+)+$/gm + permissions.forEach((p) => { + const checkRegex = /^[A-Za-z]+(?:\.[A-Za-z]+)+$/gm; - if(checkRegex.test(p)) { - let appPermissionFile = p.replaceAll(".", "/") + if (checkRegex.test(p)) { + const appPermissionFile = p.replaceAll(".", "/"); - if (fs.existsSync(path.join(APP_PATH, "sandbox", "permissions", appPermissionFile + ".js"))) { - const { callback } = require(`./permissions/${appPermissionFile}.js`) + if ( + fs.existsSync( + path.join(APP_PATH, "sandbox", "permissions", appPermissionFile + ".js"), + ) + ) { + const { callback } = require(`./permissions/${appPermissionFile}.js`); - debuggerSender = debuggerSender ?? mainSender + debuggerSender = debuggerSender ?? mainSender; setNestedProperty(app, p, (...args) => { const factory = callback({ @@ -192,65 +190,67 @@ ipcMain.handle("run-extension", async (event, code, permissions, meta) => { extensionName, extensionPath, permissionName: "app." + p, - allCSSVariables, + allCSSVariables: allCssVariables, selfArgs: args, - activeOn: activeOn - }) + activeOn, + }); if (factory && typeof factory === "function") { return factory(...args); } - }) - } - else { - throw new Error(`Permission "${p}" is not exists`) + }); + } else { + throw new Error(`Permission "${p}" is not exists`); } } - }) + }); return Object.freeze(app); } try { - let app = createAPI(permissions); + const app = createApi(permissions); const sandbox = { console: createSandboxConsole(extensionName, debuggerSender), - Map: Map, - app + Map, + app, }; const context = vm.createContext(sandbox); - await vm.runInContext(` + await vm.runInContext( + ` (async function(){ "use strict"; ${code} })() - `, context); + `, + context, + ); return { success: true }; } catch (err) { - const stack = err?.stack || String(err) - const evalLocation = stack.match(/evalmachine\.:(\d+):(\d+)/) + const stack = err?.stack || String(err); + const evalLocation = stack.match(/evalmachine\.:(\d+):(\d+)/); if (!evalLocation) { return { success: false, - error: `\n${err?.message || stack}` + error: `\n${err?.message || stack}`, }; } - const lineNumber = Number(evalLocation[1]) - const columnNumber = Number(evalLocation[2]) - let message = stack.replaceAll(evalLocation[0], "").split("at")[0].trim() + const lineNumber = Number(evalLocation[1]); + const columnNumber = Number(evalLocation[2]); + let message = stack.replaceAll(evalLocation[0], "").split("at")[0].trim(); - message += `\n\tat line: ${lineNumber - 3}` - message += `\n\tat column: ${columnNumber}` + message += `\n\tat line: ${lineNumber - 3}`; + message += `\n\tat column: ${columnNumber}`; - return { + return { success: false, - error: String(err) + error: String(err), }; } -}); \ No newline at end of file +}); diff --git a/app/sandbox/tools.js b/app/sandbox/tools.js index 27e51d6..2b26d9c 100644 --- a/app/sandbox/tools.js +++ b/app/sandbox/tools.js @@ -1,9 +1,9 @@ -const { net, nativeImage, app } = require("electron") -const fs = require("fs") -const path = require("path") +const { net, nativeImage, app } = require("electron"); +const fs = require("fs"); +const path = require("path"); function log(...args) { - console.log(...args) + console.log(...args); } async function createNativeImageFromUrl(imageUrl) { @@ -14,12 +14,12 @@ async function createNativeImageFromUrl(imageUrl) { const chunks = []; return new Promise((resolve, reject) => { - request.on('response', (response) => { - response.on('data', (chunk) => { + request.on("response", (response) => { + response.on("data", (chunk) => { chunks.push(chunk); }); - response.on('end', () => { + response.on("end", () => { // Concatenate all chunks into a single buffer const imageBuffer = Buffer.concat(chunks); @@ -27,14 +27,18 @@ async function createNativeImageFromUrl(imageUrl) { const image = nativeImage.createFromBuffer(imageBuffer); if (image.isEmpty()) { - reject(new Error('Failed to create NativeImage from buffer. The URL might not be a valid image.')); + reject( + new Error( + "Failed to create NativeImage from buffer. The URL might not be a valid image.", + ), + ); } else { resolve(image); } }); }); - request.on('error', (error) => { + request.on("error", (error) => { reject(error); }); @@ -43,15 +47,20 @@ async function createNativeImageFromUrl(imageUrl) { } function getType(value) { if (typeof value === "number" && !isNaN(value) && isFinite(value)) { - return value % 1 !== 0 ? "float" : "int"; + return value % 1 === 0 ? "int" : "float"; } if (typeof value === "string") { if (value.endsWith(".css")) return "CSSFile"; if (value.endsWith(".js")) return "JSFile"; if (value.endsWith(".svg")) return "SVGFile"; if (value.endsWith(".png")) return "PNGFile"; - if (/^#([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$/i.test(value)) return "HEX" - if (/^rgb[a]?\(\s*(?:\d{1,3}%?,\s*){2}\d{1,3}%?(?:,\s*(?:0?\.\d+|\d+|\d{1,3}%?))?\s*\)$/i.test(value)) return "RGB" + if (/^#([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$/i.test(value)) return "HEX"; + if ( + /^rgb[a]?\(\s*(?:\d{1,3}%?,\s*){2}\d{1,3}%?(?:,\s*(?:0?\.\d+|\d+|\d{1,3}%?))?\s*\)$/i.test( + value, + ) + ) + return "RGB"; return "string"; } @@ -63,19 +72,19 @@ function getType(value) { return "any"; } function checkType(type, value) { - const allowedTypes = type.split("|").map(t => t.trim()) - const valueType = getType(value) + const allowedTypes = type.split("|").map((t) => t.trim()); + const valueType = getType(value); - return allowedTypes.includes(valueType) + return allowedTypes.includes(valueType); } function ok(result) { - return { success: true, result } + return { success: true, result }; } function fail(error) { - return { success: false, result: error instanceof Error ? error.message : String(error) } + return { success: false, result: error instanceof Error ? error.message : String(error) }; } function isSafeName(name) { - return typeof name === "string" && !name.includes("..") && !path.isAbsolute(name) + return typeof name === "string" && !name.includes("..") && !path.isAbsolute(name); } function stringify(v) { try { @@ -83,8 +92,12 @@ function stringify(v) { return JSON.stringify(v); } if (typeof v === "function") { - let args = v.toString().match(/\(([\s\S]*?)\)/)[1].split(',').map(s => s.trim()) - return `<${v.name ? `function ${v.name}` : "function"}:(${args})>` + const args = v + .toString() + .match(/\(([\s\S]*?)\)/)[1] + .split(",") + .map((s) => s.trim()); + return `<${v.name ? `function ${v.name}` : "function"}:(${args})>`; } return String(v); } catch { @@ -93,54 +106,51 @@ function stringify(v) { } function saveReadFile(path, throwError = false) { if (fs.existsSync(path)) { - const data = fs.readFileSync(path, 'utf-8'); + const data = fs.readFileSync(path, "utf-8"); return data; - } else { - if (throwError) { - throw new Error(`The file at the path "${path}" was not found or is empty`) - } - return false; } + if (throwError) { + throw new Error(`The file at the path "${path}" was not found or is empty`); + } + return false; } function isFileExists(path, throwError = false) { if (fs.existsSync(path)) { - return true - } else { - if (throwError) { - throw new Error(`The file at the path "${path}" was not found`) - } - return false; + return true; + } + if (throwError) { + throw new Error(`The file at the path "${path}" was not found`); } + return false; } function checkFields(fieldsParentName = "", object = {}, fields = {}) { - const keys = Object.keys(object) - const fieldsKeys = Object.keys(fields) + const keys = Object.keys(object); + const fieldsKeys = Object.keys(fields); for (const field of fieldsKeys) { if (!keys.includes(field)) { throw new Error( - `[${fieldsParentName}] Missing "${field}" field, expected "${fields[field]}"` - ) + `[${fieldsParentName}] Missing "${field}" field, expected "${fields[field]}"`, + ); } if (!checkType(fields[field], object[field])) { throw new Error( - `[${fieldsParentName}] Field "${field}" has type "${getType(object[field])}", expected "${fields[field].replaceAll("|", " or ")}"` - ) + `[${fieldsParentName}] Field "${field}" has type "${getType(object[field])}", expected "${fields[field].replaceAll("|", " or ")}"`, + ); } } - } function createSandboxConsole(extensionName, debuggerSender) { function send(type, args) { debuggerSender.send("debug-event", { data: { - type: type, - content: args.map(a => stringify(a)).join(", "), - from: extensionName + type, + content: args.map((a) => stringify(a)).join(", "), + from: extensionName, }, - time: Date.now() - }) + time: Date.now(), + }); } return { @@ -152,28 +162,27 @@ function createSandboxConsole(extensionName, debuggerSender) { }, error: (...args) => { send("error", args); - throw new ExtensionError(args.join(", ")) - } + throw new ExtensionError(args.join(", ")); + }, }; } function getArgumentNames(func) { - let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; - let ARGUMENT_NAMES = /([^\s,]+)/g; + const StripComments = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm; + const ArgumentNames = /([^\s,]+)/g; function getParamNames(func) { - var fnStr = func.toString().replace(STRIP_COMMENTS, ''); - var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); - if (result === null) - result = []; + var fnStr = func.toString().replace(StripComments, ""); + var result = fnStr.slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")")).match(ArgumentNames); + if (result === null) result = []; return result; } - return getParamNames(func) + return getParamNames(func); } function getExt(filename) { - const ext = path.extname(filename) - return ext + const ext = path.extname(filename); + return ext; } class ExtensionError extends Error { @@ -183,12 +192,12 @@ class ExtensionError extends Error { } } -module.exports = { - createNativeImageFromUrl, - getType, - checkType, - ok, - fail, +module.exports = { + createNativeImageFromUrl, + getType, + checkType, + ok, + fail, isSafeName, stringify, saveReadFile, @@ -199,5 +208,5 @@ module.exports = { log, getExt, - ExtensionError -} \ No newline at end of file + ExtensionError, +}; diff --git a/app/splash/splash.js b/app/splash/splash.js index 5b2e872..d06d43a 100644 --- a/app/splash/splash.js +++ b/app/splash/splash.js @@ -1,11 +1,11 @@ -const { BrowserWindow, app } = require("electron") -const { PRELOAD_PATH, SPLASH_HTML_PATH } = require("../main/helpers/paths.js") -const { getAppIcon } = require("../main/helpers/requests.js") +const { BrowserWindow, app } = require("electron"); +const { PRELOAD_PATH, SPLASH_HTML_PATH } = require("../main/helpers/paths.js"); +const { getAppIcon } = require("../main/helpers/requests.js"); let splash; async function createSplashWindow() { - const appIcon = await getAppIcon() + const appIcon = await getAppIcon(); splash = new BrowserWindow({ width: 800, @@ -17,20 +17,20 @@ async function createSplashWindow() { center: true, show: true, webPreferences: { - preload: PRELOAD_PATH + preload: PRELOAD_PATH, }, - icon: appIcon + icon: appIcon, }); - splash.loadFile(SPLASH_HTML_PATH) + splash.loadFile(SPLASH_HTML_PATH); - return splash + return splash; } function updateSplash(text, isError = false) { - if(splash) { + if (splash) { splash.webContents.send("status-update", { msg: text, error: isError }); } } -module.exports = { createSplashWindow, updateSplash } \ No newline at end of file +module.exports = { createSplashWindow, updateSplash }; diff --git a/app/splash/splashRenderer.js b/app/splash/splashRenderer.js index 69755a6..4e7d945 100644 --- a/app/splash/splashRenderer.js +++ b/app/splash/splashRenderer.js @@ -1,49 +1,49 @@ -import { GLS } from "../../assets/js/lib.js" +import { GLS } from "../../assets/js/lib.js"; document.addEventListener("DOMContentLoaded", async () => { - const gls = await GLS.init() + const gls = await GLS.init(); - const buttons = document.querySelector(".buttons") - const closeBtn = buttons.querySelector("#close") - const offlineBtn = buttons.querySelector("#offline") + const buttons = document.querySelector(".buttons"); + const closeBtn = buttons.querySelector("#close"); + const offlineBtn = buttons.querySelector("#offline"); - let packageData = await window.electron.getPackageData() - let version = packageData.version - let author = packageData.author - let desc = packageData.description + const packageData = await window.electron.getPackageData(); + const version = packageData.version; + const author = packageData.author; + const desc = packageData.description; - let image = document.querySelector(".image") - let r = Math.floor(Math.random() * 12) + 1; - let randomImage = `../assets/media/splash/splash_${r}.svg` - let splashImage = new Image() - splashImage.src = randomImage - splashImage.decoding = "async" - image.replaceChildren(splashImage) + const image = document.querySelector(".image"); + const r = Math.floor(Math.random() * 12) + 1; + const randomImage = `../assets/media/splash/splash_${r}.svg`; + const splashImage = new Image(); + splashImage.src = randomImage; + splashImage.decoding = "async"; + image.replaceChildren(splashImage); - document.querySelector(".version").innerText = `v${version}` - document.querySelector(".author").innerText = gls.get("splash.createdBy", { name: author }) - document.querySelector(".description").innerText = gls.get("splash.description") + document.querySelector(".version").innerText = `v${version}`; + document.querySelector(".author").innerText = gls.get("splash.createdBy", { name: author }); + document.querySelector(".description").innerText = gls.get("splash.description"); window.electron.onStatusUpdate((_event, data) => { - document.querySelector(".status").innerText = data.msg + document.querySelector(".status").innerText = data.msg; if (data.error) { - document.querySelector(".status").classList.add("text-danger") - document.querySelector(".ring-loader").classList.add("hidden") + document.querySelector(".status").classList.add("text-danger"); + document.querySelector(".ring-loader").classList.add("hidden"); - let buttons = document.querySelector(".buttons") - buttons.classList.remove("hidden") + const buttons = document.querySelector(".buttons"); + buttons.classList.remove("hidden"); } }); - closeBtn.textContent = gls.get("splash.closeBtn") - offlineBtn.textContent = gls.get("splash.offlineBtn") + closeBtn.textContent = gls.get("splash.closeBtn"); + offlineBtn.textContent = gls.get("splash.offlineBtn"); closeBtn.addEventListener("click", () => { - window.electron.close() - }) + window.electron.close(); + }); offlineBtn.addEventListener("click", async () => { - await window.electron.setNonAccountMode(true) - window.electron.reload() - }) -}) \ No newline at end of file + await window.electron.setNonAccountMode(true); + window.electron.reload(); + }); +}); diff --git a/assets/css/ace-custom.css b/assets/css/ace-custom.css index 340a2e2..178d3c9 100644 --- a/assets/css/ace-custom.css +++ b/assets/css/ace-custom.css @@ -16,32 +16,31 @@ .ace_boolean, .ace_constant.ace_boolean { - color: var(--color-boolean)!important; + color: var(--color-boolean) !important; } .ace_numeric, .ace_constant.ace_numeric { - color: var(--color-number)!important; + color: var(--color-number) !important; } .ace_constant { - color: var(--color-const)!important; + color: var(--color-const) !important; } .ace_class { - color: var(--color-class)!important; + color: var(--color-class) !important; } .ace_function { - color: var(--color-function)!important; + color: var(--color-function) !important; } .ace_storage.ace_type.ace_ts { - color: var(--color-class)!important; + color: var(--color-class) !important; } .ace_variable { - color: var(--color-const)!important; + color: var(--color-const) !important; } .ace_keyword { - color: var(--color-keyword)!important; + color: var(--color-keyword) !important; } - .ace_editor .ace_dom.ace_global { color: var(--color-keyword); font-weight: 600; @@ -83,7 +82,7 @@ color: var(--warning); } .ace_completion-meta { - opacity: .2; + opacity: 0.2; font-size: 12px; font-family: var(--main-font); } @@ -91,28 +90,28 @@ padding: 0px 5px; font-size: 14px; cursor: pointer; - transition: .2s; + transition: 0.2s; } .ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line { background: var(--block-divider-border-color); } .ace_autocomplete .ace_text-layer { width: 100%; - margin: 0px!important; + margin: 0px !important; } .ace_line-hover { - border: 0px!important; - background: var(--body-color-solid)!important; + border: 0px !important; + background: var(--body-color-solid) !important; } .ace_invalid.ace_deprecated, .ace_invalid { - background: var(--topbar-menu-item-hover-bg)!important; + background: var(--topbar-menu-item-hover-bg) !important; border-radius: 4px; text-decoration: line-through; } .ace_tooltip { - background: var(--body-color)!important; + background: var(--body-color) !important; border: 1px solid var(--topbar-menu-item-hover-bg); border-radius: 5px; box-shadow: #0000005e 0px 2px 7px 0px; @@ -142,17 +141,16 @@ margin-right: 5px; } - .ace_search { background: var(--body-color-transparent); - border: 1px solid var(--block-divider-border-color)!important; + border: 1px solid var(--block-divider-border-color) !important; backdrop-filter: blur(5px); - border-radius: 10px!important; + border-radius: 10px !important; padding: 5px; } .ace_search.right { top: 10px; - right: 10px!important; + right: 10px !important; } .ace_search_form { display: flex; @@ -176,10 +174,10 @@ background: none; border: 0px; color: var(--text-color); - opacity: .2; + opacity: 0.2; font-family: var(--main-font); - padding: 0px!important; - transition: .2s; + padding: 0px !important; + transition: 0.2s; } .ace_searchbtn:last-child { border: 0px; @@ -212,13 +210,13 @@ font-size: 12px; } .ace_searchbtn_close { - background: url('data:image/svg+xml,%3Csvg%20width%3D%222156%22%20height%3D%222156%22%20viewBox%3D%220%200%202156%202156%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20clip-path%3D%22url(%23a)%22%3E%3Cpath%20d%3D%22m1078%201307.54-803.376%20803.37Q229.536%202156%20159.855%202156q-69.68%200-114.768-45.09C15.03%202080.85%200%202042.6%200%201996.14c0-46.45%2015.03-84.71%2045.087-114.76L848.464%201078%2045.087%20274.624Q0%20229.536%200%20159.855q0-69.68%2045.087-114.768T159.855%200t114.769%2045.087L1078%20848.464l803.38-803.377C1911.43%2015.03%201949.69%200%201996.14%200c46.46%200%2084.71%2015.03%20114.77%2045.087Q2156%2090.175%202156%20159.855t-45.09%20114.769L1307.54%201078l803.37%20803.38c30.06%2030.05%2045.09%2068.31%2045.09%20114.76%200%2046.46-15.03%2084.71-45.09%20114.77S2042.6%202156%201996.14%202156c-46.45%200-84.71-15.03-114.76-45.09z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fg%3E%3Cdefs%3E%3CclipPath%20id%3D%22a%22%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M0%200h2156v2156H0z%22%2F%3E%3C%2FclipPath%3E%3C%2Fdefs%3E%3C%2Fsvg%3E'); + background: url("data:image/svg+xml,%3Csvg%20width%3D%222156%22%20height%3D%222156%22%20viewBox%3D%220%200%202156%202156%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20clip-path%3D%22url(%23a)%22%3E%3Cpath%20d%3D%22m1078%201307.54-803.376%20803.37Q229.536%202156%20159.855%202156q-69.68%200-114.768-45.09C15.03%202080.85%200%202042.6%200%201996.14c0-46.45%2015.03-84.71%2045.087-114.76L848.464%201078%2045.087%20274.624Q0%20229.536%200%20159.855q0-69.68%2045.087-114.768T159.855%200t114.769%2045.087L1078%20848.464l803.38-803.377C1911.43%2015.03%201949.69%200%201996.14%200c46.46%200%2084.71%2015.03%20114.77%2045.087Q2156%2090.175%202156%20159.855t-45.09%20114.769L1307.54%201078l803.37%20803.38c30.06%2030.05%2045.09%2068.31%2045.09%20114.76%200%2046.46-15.03%2084.71-45.09%20114.77S2042.6%202156%201996.14%202156c-46.45%200-84.71-15.03-114.76-45.09z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fg%3E%3Cdefs%3E%3CclipPath%20id%3D%22a%22%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M0%200h2156v2156H0z%22%2F%3E%3C%2FclipPath%3E%3C%2Fdefs%3E%3C%2Fsvg%3E"); background-size: cover; border-radius: 0px; height: 8px; width: 8px; - opacity: .2; - transition: .2s; + opacity: 0.2; + transition: 0.2s; } .ace_searchbtn_close:hover { opacity: 1; @@ -229,20 +227,20 @@ } .ace_comment_danger { - opacity: .5; + opacity: 0.5; color: var(--danger); } .ace_comment_what { - opacity: .5; + opacity: 0.5; color: var(--success); } .ace_comment_todo { - opacity: .5; + opacity: 0.5; color: var(--warning); } .ace_marker-layer .ace_selected-word { - border: none!important; + border: none !important; } .ace-github-dark .ace_indent-guide { @@ -251,15 +249,15 @@ } .ace_no_usage { - opacity: .5; + opacity: 0.5; text-decoration: underline wavy #888; } .ace_operator { - color: var(--color-operator) + color: var(--color-operator); } .ace_punctuation.ace_operator { - color: inherit!important; + color: inherit !important; } .ace_other { @@ -275,24 +273,24 @@ position: absolute; width: 100%; height: 100%; - opacity: .1; + opacity: 0.1; background: white; top: 0; left: 0; z-index: 999999; - transition: .2s; + transition: 0.2s; } .ace-flash.hidden { - display: flex!important; + display: flex !important; opacity: 0; pointer-events: none; } .ace_paren.ace_lparen:not(.ace_func), .ace_paren.ace_rparen:not(.ace_func) { - color: var(--color-template-literal-wrapper) + color: var(--color-template-literal-wrapper); } .ace_character { - color: var(--color-character) -} \ No newline at end of file + color: var(--color-character); +} diff --git a/assets/css/auth.css b/assets/css/auth.css index fcd79f7..cd36a90 100644 --- a/assets/css/auth.css +++ b/assets/css/auth.css @@ -7,7 +7,7 @@ justify-content: center; flex-direction: column; opacity: 0; - transition: .4s; + transition: 0.4s; } .auth-visibility__change { @@ -16,6 +16,6 @@ right: -40px; top: 15px; color: var(--text-color); - opacity: .2; + opacity: 0.2; cursor: pointer; -} \ No newline at end of file +} diff --git a/assets/css/codemirror.css b/assets/css/codemirror.css index b37431a..1bbc8fe 100644 --- a/assets/css/codemirror.css +++ b/assets/css/codemirror.css @@ -29,11 +29,11 @@ } .cm-scroller::-webkit-scrollbar-thumb:hover { - opacity: .5; + opacity: 0.5; } /* data color */ span[data-color] { - outline: 1px solid var(--block-divider-border-color)!important; -} \ No newline at end of file + outline: 1px solid var(--block-divider-border-color) !important; +} diff --git a/assets/css/components/aceDocTooltip.css b/assets/css/components/aceDocTooltip.css index 0f01931..46ab3f0 100644 --- a/assets/css/components/aceDocTooltip.css +++ b/assets/css/components/aceDocTooltip.css @@ -4,7 +4,7 @@ background: var(--body-color); backdrop-filter: blur(5px); color: var(--text-color); - display: flex!important; + display: flex !important; flex-direction: column; gap: 5px; font-size: 14px; @@ -13,10 +13,10 @@ max-width: 300px; border: 1px solid var(--topbar-menu-item-hover-bg); box-shadow: #00000014 0px 2px 5px 0px; - transition: .2s; + transition: 0.2s; } .ace-documentation__tooltip.hidden { - display: flex!important; + display: flex !important; opacity: 0; pointer-events: none; } @@ -51,7 +51,7 @@ font-size: 12px; border-bottom: 1px solid var(--topbar-menu-item-hover-bg); color: var(--text-color-muted); -} +} .ace-documentation__tooltip .ace-documentation__tooltip-description { padding: 10px 15px; padding-bottom: 5px; @@ -66,13 +66,13 @@ font-size: 12px; } .ace-documentation__tooltip .ace-documentation__tooltip-example .ace_editor { - background: transparent!important; + background: transparent !important; height: 50px; font-size: 15px; padding: 0px; } .ace-documentation__tooltip .ace-documentation__tooltip-example .ace_editor .ace_cursor { - display: none!important; + display: none !important; } .ace-documentation__tooltip .ace-documentation__tooltip-example .content { font-family: var(--code-font); @@ -91,4 +91,4 @@ padding-bottom: 5px; color: var(--text-color-muted); font-size: 12px; -} \ No newline at end of file +} diff --git a/assets/css/components/codeWrapper.css b/assets/css/components/codeWrapper.css index 7db1a08..d0f8732 100644 --- a/assets/css/components/codeWrapper.css +++ b/assets/css/components/codeWrapper.css @@ -28,7 +28,7 @@ max-height: 200px; overflow: scroll; display: block; - transition: .2s; + transition: 0.2s; min-height: 160px; position: relative; } @@ -80,8 +80,6 @@ cursor: default; } - - .code-wrapper .bottom-window.console { overflow: hidden; height: 300px; @@ -123,12 +121,12 @@ border-radius: 999px; background: var(--text-color); opacity: 0; - transition: opacity .2s; + transition: opacity 0.2s; } .code-wrapper .bottom-window__resize-handle:hover::after, .code-wrapper .bottom-window.resizing .bottom-window__resize-handle::after { - opacity: .35; + opacity: 0.35; } body.bottom-window-resizing { @@ -139,8 +137,8 @@ body.bottom-window-resizing { .bottom-window__resize-preview { position: fixed; height: 2px; - border-top: 2px solid rgba(255, 255, 255, .9); - box-shadow: 0 0 0 1px rgba(0, 0, 0, .45); + border-top: 2px solid rgba(255, 255, 255, 0.9); + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.45); pointer-events: none; z-index: 9999; } @@ -156,16 +154,16 @@ body.bottom-window-resizing { } .code-wrapper .bottom-window .bottom-window__content .time { - opacity: .5; + opacity: 0.5; position: absolute; right: 0px; } .code-wrapper .bottom-window #bottomWindowClose { font-size: 15px; - opacity: .5; + opacity: 0.5; color: var(--text-color); - transition: .2s; + transition: 0.2s; } .code-wrapper .bottom-window #bottomWindowClose:hover { @@ -186,16 +184,24 @@ body.bottom-window-resizing { align-items: center; gap: 5px; position: relative; - transition: .2s; + transition: 0.2s; } -.code-wrapper .bottom-window .bottom-window__content div.bottom-window__item span[class^="material-symbols"] { +.code-wrapper + .bottom-window + .bottom-window__content + div.bottom-window__item + span[class^="material-symbols"] { font-size: 15px; - opacity: .2; + opacity: 0.2; margin-right: 10px; } -.code-wrapper .bottom-window .bottom-window__content div.bottom-window__item span[class^="material-symbols"].error { +.code-wrapper + .bottom-window + .bottom-window__content + div.bottom-window__item + span[class^="material-symbols"].error { color: #ff4343; opacity: 1; } @@ -205,7 +211,7 @@ body.bottom-window-resizing { width: fit-content; font-size: 12px; color: var(--text-color); - opacity: .5; + opacity: 0.5; font-weight: var(--default-font-weight); } @@ -240,28 +246,47 @@ body.bottom-window-resizing { font-family: inherit; } -.code-wrapper .bottom-window .bottom-window__content div.bottom-window__item[class^="log"].whitespaced { +.code-wrapper + .bottom-window + .bottom-window__content + div.bottom-window__item[class^="log"].whitespaced { white-space: break-spaces; word-wrap: break-word; display: block; } -.code-wrapper .bottom-window .bottom-window__content div.bottom-window__item[class^="log"] .runtime-typeof { +.code-wrapper + .bottom-window + .bottom-window__content + div.bottom-window__item[class^="log"] + .runtime-typeof { background: inherit; padding: 3px 5px; border-radius: 5px; - opacity: .5; + opacity: 0.5; } -.code-wrapper .bottom-window .bottom-window__content div.bottom-window__item[class^="log"] .runtime-typeof.string { +.code-wrapper + .bottom-window + .bottom-window__content + div.bottom-window__item[class^="log"] + .runtime-typeof.string { color: inherit; } -.code-wrapper .bottom-window .bottom-window__content div.bottom-window__item[class^="log"] .runtime-typeof.object { +.code-wrapper + .bottom-window + .bottom-window__content + div.bottom-window__item[class^="log"] + .runtime-typeof.object { color: #42dbff; } -.code-wrapper .bottom-window .bottom-window__content div.bottom-window__item[class^="log"] .runtime-typeof.number { +.code-wrapper + .bottom-window + .bottom-window__content + div.bottom-window__item[class^="log"] + .runtime-typeof.number { color: #fd9e38; } @@ -269,7 +294,10 @@ body.bottom-window-resizing { color: #edbc2a; } -.code-wrapper .bottom-window .bottom-window__content span.log-warning.span[class^="material-symbols"] { +.code-wrapper + .bottom-window + .bottom-window__content + span.log-warning.span[class^="material-symbols"] { color: #edbc2a; opacity: 1; } @@ -278,21 +306,27 @@ body.bottom-window-resizing { color: #ff4141; } -.code-wrapper .bottom-window .bottom-window__content span.log-error.span[class^="material-symbols"] { +.code-wrapper + .bottom-window + .bottom-window__content + span.log-error.span[class^="material-symbols"] { color: #ff4141; opacity: 1; } .code-wrapper .bottom-window .bottom-window__content div.bottom-window__item.prev { filter: grayscale(1); - opacity: .2; + opacity: 0.2; } -.code-wrapper .bottom-window .bottom-window__content div.bottom-window__item.success span[class^="material-symbols"] { +.code-wrapper + .bottom-window + .bottom-window__content + div.bottom-window__item.success + span[class^="material-symbols"] { color: #38db73; } - .code-wrapper .code { width: 100%; height: 100%; @@ -332,4 +366,4 @@ body.bottom-window-resizing { .code-inner__wrapper div.code.active-pane { z-index: 4; -} \ No newline at end of file +} diff --git a/assets/css/components/contextMenu.css b/assets/css/components/contextMenu.css index bf86ce1..ae28bdf 100644 --- a/assets/css/components/contextMenu.css +++ b/assets/css/components/contextMenu.css @@ -32,7 +32,11 @@ backdrop-filter: blur(5px); border: 1px solid var(--context-border); border-radius: 10px; - transition: opacity .15s ease, filter .15s ease, left .1s ease, top .1s ease; + transition: + opacity 0.15s ease, + filter 0.15s ease, + left 0.1s ease, + top 0.1s ease; opacity: 1; filter: blur(0px); pointer-events: all; @@ -55,7 +59,7 @@ display: flex; align-items: center; gap: 5px; - transition: .2s; + transition: 0.2s; justify-content: space-between; border-radius: 5px; padding-right: 8px; @@ -65,7 +69,7 @@ background: var(--context-border); } .context-menu .context-menu__item.disabled { - opacity: .45; + opacity: 0.45; } .context-menu .context-menu__item.disabled:hover { cursor: default; @@ -79,12 +83,12 @@ } .context-menu .context-menu__item .context-menu__item-block .shortcut { font-size: 12px; - opacity: .5; + opacity: 0.5; } .context-menu .context-menu__item span[class^="material-symbols"] { font-size: 15px; - font-variation-settings: 'FILL' 0; + font-variation-settings: "FILL" 0; } .context-menu .context-menu__item .content { width: fit-content; @@ -117,4 +121,4 @@ border-radius: 4px; font: inherit; outline: none; -} \ No newline at end of file +} diff --git a/assets/css/components/loader.css b/assets/css/components/loader.css index 0fb6569..35387a2 100644 --- a/assets/css/components/loader.css +++ b/assets/css/components/loader.css @@ -9,7 +9,7 @@ justify-content: flex-start; height: var(--uib-size); width: var(--uib-size); - transition: .2s; + transition: 0.2s; } .content-loader.container.loader-hidden { @@ -35,7 +35,7 @@ } .line::before { - content: ''; + content: ""; height: 22%; width: 100%; border-radius: calc(var(--uib-stroke) / 2); @@ -134,7 +134,6 @@ } @keyframes pulse { - 0%, 80%, 100% { @@ -146,4 +145,4 @@ transform: scaleY(1); opacity: 1; } -} \ No newline at end of file +} diff --git a/assets/css/components/notificator.css b/assets/css/components/notificator.css index 89b8fd5..212a726 100644 --- a/assets/css/components/notificator.css +++ b/assets/css/components/notificator.css @@ -6,7 +6,7 @@ bottom: 0; z-index: 99; width: 100%; - transition: .4s ease-in-out; + transition: 0.4s ease-in-out; } .notificator-wrapper.hidden { @@ -47,11 +47,11 @@ .notificator-wrapper .notificator span[class^="material-symbols"] { color: var(--text-color); font-size: 20px; - opacity: .5; + opacity: 0.5; } .notificator-wrapper .notificator .notificator-body .notificator-body__value { font-size: 15px; font-weight: 600; text-align: center; -} \ No newline at end of file +} diff --git a/assets/css/components/popup.css b/assets/css/components/popup.css index f3cb6cc..82fe2e0 100644 --- a/assets/css/components/popup.css +++ b/assets/css/components/popup.css @@ -10,10 +10,10 @@ .popup-title { font-size: 14px; font-weight: 500; - opacity: .5; + opacity: 0.5; padding: 2px 7px; user-select: none; - transition: .2s; + transition: 0.2s; } .popup-title.inline { @@ -42,7 +42,7 @@ display: flex; flex-direction: column; z-index: 99; - transition: .2s; + transition: 0.2s; border-radius: 10px; border: 1px solid var(--block-divider-border-color); overflow: hidden; @@ -56,12 +56,12 @@ .popup-content__item { padding: 10px 15px; font-size: 14px; - transition: .2s; + transition: 0.2s; width: 100%; white-space: nowrap; } .popup-content__item.disabled { - opacity: .5; + opacity: 0.5; pointer-events: none; user-select: none; } @@ -84,4 +84,4 @@ .popup-content__divider { border-bottom: 1px solid var(--block-divider-border-color); -} \ No newline at end of file +} diff --git a/assets/css/components/rangeSlider.css b/assets/css/components/rangeSlider.css index a1a0c90..642ec7a 100644 --- a/assets/css/components/rangeSlider.css +++ b/assets/css/components/rangeSlider.css @@ -42,20 +42,24 @@ input[type="range"]::-webkit-slider-thumb { --box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0 100vmax currentColor; width: var(--thumb-width, var(--thumb-height)); - background: linear-gradient(currentColor 0 0) scroll no-repeat left center / 50% calc(var(--track-height) + 1px); + background: + linear-gradient(currentColor 0 0) scroll no-repeat left center / 50% + calc(var(--track-height) + 1px); background-color: currentColor; box-shadow: var(--box-fill); border-radius: var(--thumb-width, var(--thumb-height)); filter: brightness(100%); - clip-path: polygon(100% -1px, - var(--clip-edges) -1px, - 0 var(--clip-top), - -100vmax var(--clip-top), - -100vmax var(--clip-bottom), - 0 var(--clip-bottom), - var(--clip-edges) 100%, - var(--clip-further) var(--clip-further)); + clip-path: polygon( + 100% -1px, + var(--clip-edges) -1px, + 0 var(--clip-top), + -100vmax var(--clip-top), + -100vmax var(--clip-bottom), + 0 var(--clip-bottom), + var(--clip-edges) 100%, + var(--clip-further) var(--clip-further) + ); } input[type="range"]:hover::-webkit-slider-thumb { @@ -69,7 +73,9 @@ input[type="range"]:active::-webkit-slider-thumb { } input[type="range"]::-webkit-slider-runnable-track { - background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center / 100% calc(var(--track-height) + 1px); + background: + linear-gradient(var(--track-color) 0 0) scroll no-repeat center / 100% + calc(var(--track-height) + 1px); } input[type="range"]:disabled::-webkit-slider-thumb { @@ -91,4 +97,4 @@ input[type="range"] { --brightness-down: 80%; --clip-edges: 1px; outline: none; -} \ No newline at end of file +} diff --git a/assets/css/components/roundSwitch.css b/assets/css/components/roundSwitch.css index fc654a8..cbe7a52 100644 --- a/assets/css/components/roundSwitch.css +++ b/assets/css/components/roundSwitch.css @@ -9,11 +9,11 @@ display: none; } -.round-switch input[type=checkbox]:checked+.slider { +.round-switch input[type="checkbox"]:checked + .slider { background-color: var(--switch-checkbox-active); } -.round-switch input[type=checkbox]:checked+.slider:before { +.round-switch input[type="checkbox"]:checked + .slider:before { transform: translateX(17px); } @@ -41,4 +41,4 @@ -webkit-transition: 0.4s; transition: 0.4s; border-radius: 5px; -} \ No newline at end of file +} diff --git a/assets/css/components/select.css b/assets/css/components/select.css index a32dee6..db6f037 100644 --- a/assets/css/components/select.css +++ b/assets/css/components/select.css @@ -13,8 +13,9 @@ display: flex; font-size: 14px; justify-content: space-between; - transition: .2s; -}.options-selector__wrapper .options-selector:hover { + transition: 0.2s; +} +.options-selector__wrapper .options-selector:hover { cursor: pointer; } .options-selector__wrapper .options-selector__items { @@ -30,7 +31,7 @@ overflow-y: auto; z-index: 1; max-height: 200px; - transition: .2s; + transition: 0.2s; } .options-selector__wrapper .options-selector__items.hidden { opacity: 0; @@ -42,7 +43,7 @@ .options-selector__wrapper .options-selector__items .options-selector__item { padding: 8px 10px; font-size: 14px; - transition: .2s; + transition: 0.2s; display: flex; align-items: center; gap: 5px; @@ -56,14 +57,16 @@ } .options-selector__wrapper .options-selector__items .options-selector__item .secondary { - opacity: .5; + opacity: 0.5; } .options-selector__wrapper .options-selector__items .options-selector__item .modal-badge span { background: rgba(50, 100, 168, 0.2); color: rgb(50, 100, 168); font-size: 12px; - font-variation-settings: 'FILL' 1, 'wght' 700 !important; + font-variation-settings: + "FILL" 1, + "wght" 700 !important; margin-top: 1px; padding: 5px; } @@ -73,4 +76,4 @@ .options-selector__wrapper#languageSelect .options-selector__item .secondary { position: absolute; right: 10px; -} \ No newline at end of file +} diff --git a/assets/css/editor/screenshot.css b/assets/css/editor/screenshot.css index 4459b5d..e1d94fc 100644 --- a/assets/css/editor/screenshot.css +++ b/assets/css/editor/screenshot.css @@ -45,4 +45,4 @@ .code-snippet__wrapper #language { position: absolute; right: 10px; -} \ No newline at end of file +} diff --git a/assets/css/global.css b/assets/css/global.css index fa4d1cb..0535bd3 100644 --- a/assets/css/global.css +++ b/assets/css/global.css @@ -9,13 +9,13 @@ @import url("components/aceDocTooltip.css"); @font-face { - font-family: 'Inter'; - src: url('../fonts/Inter.ttf'); + font-family: "Inter"; + src: url("../fonts/Inter.ttf"); } @font-face { - font-family: 'JetBrainsMono'; - src: url('../fonts/JetBrainsMono.ttf'); + font-family: "JetBrainsMono"; + src: url("../fonts/JetBrainsMono.ttf"); } textarea { @@ -35,27 +35,29 @@ textarea { } .icon-fill { - font-variation-settings: 'FILL' 1; + font-variation-settings: "FILL" 1; } .text-loading-effect { --s2u-speed: 1.8s; --s2u-angle: 115deg; --s2u-tint: 0, 0, 0; - --s2u-base-alpha: .5; + --s2u-base-alpha: 0.5; --s2u-shine-alpha: 1; position: relative; display: inline-block; line-height: 1.2; - letter-spacing: .02em; + letter-spacing: 0.02em; color: #00000000; text-shadow: 0 0 0 rgba(var(--s2u-tint), var(--s2u-base-alpha)); - background-image: linear-gradient(var(--s2u-angle), - rgba(var(--s2u-tint), 0) 0%, - rgba(var(--s2u-tint), 0) 40%, - rgba(var(--s2u-tint), var(--s2u-shine-alpha)) 50%, - rgba(var(--s2u-tint), 0) 60%, - rgba(var(--s2u-tint), 0) 100%); + background-image: linear-gradient( + var(--s2u-angle), + rgba(var(--s2u-tint), 0) 0%, + rgba(var(--s2u-tint), 0) 40%, + rgba(var(--s2u-tint), var(--s2u-shine-alpha)) 50%, + rgba(var(--s2u-tint), 0) 60%, + rgba(var(--s2u-tint), 0) 100% + ); background-repeat: no-repeat; background-size: 220% 100%; background-position: 200% 0; @@ -75,7 +77,7 @@ textarea { } .v-hidden { - display: none!important; + display: none !important; } .ace_gutter-cell.ace_warning, @@ -101,7 +103,7 @@ textarea { .ace_icon.ace_info, .ace_gutter-cell.ace_hint, .ace_icon.ace_hint { - background-image: url("../media/markers/info.svg")!important; + background-image: url("../media/markers/info.svg") !important; background-size: contain; background-repeat: no-repeat; } @@ -147,7 +149,7 @@ textarea { margin-top: -2px; border: 0px; vertical-align: middle; - background-image: url('data:image/svg+xml,%3Csvg%20width%3D%222156%22%20height%3D%222156%22%20viewBox%3D%220%200%202156%202156%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M1582.34%201023c30.74%200%2055.66%2024.85%2055.66%2055.5s-24.92%2055.5-55.66%2055.5H572.66c-30.74%200-55.66-24.85-55.66-55.5s24.92-55.5%2055.66-55.5z%22%20fill%3D%22%23fff%22%2F%3E%3Cpath%20d%3D%22M701.67%20825.102c19.093-24.095%2054.112-28.157%2078.218-9.074%2024.106%2019.084%2028.171%2054.086%209.078%2078.18L643.327%201078l145.639%20183.79c19.092%2024.1%2015.028%2059.1-9.078%2078.18-24.106%2019.09-59.125%2015.02-78.218-9.07l-169.637-214.08c-9.064-11.44-12.908-25.34-11.867-38.82-1.041-13.48%202.803-27.38%2011.867-38.82zm754.66%20505.798c-19.09%2024.09-54.11%2028.16-78.22%209.07-24.1-19.08-28.17-54.08-9.08-78.18L1514.67%201078l-145.64-183.792c-19.09-24.094-15.02-59.096%209.08-78.18%2024.11-19.083%2059.13-15.021%2078.22%209.074l169.64%20214.078c9.06%2011.44%2012.9%2025.34%2011.86%2038.82%201.04%2013.48-2.8%2027.38-11.86%2038.82z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fsvg%3E'); + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%222156%22%20height%3D%222156%22%20viewBox%3D%220%200%202156%202156%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M1582.34%201023c30.74%200%2055.66%2024.85%2055.66%2055.5s-24.92%2055.5-55.66%2055.5H572.66c-30.74%200-55.66-24.85-55.66-55.5s24.92-55.5%2055.66-55.5z%22%20fill%3D%22%23fff%22%2F%3E%3Cpath%20d%3D%22M701.67%20825.102c19.093-24.095%2054.112-28.157%2078.218-9.074%2024.106%2019.084%2028.171%2054.086%209.078%2078.18L643.327%201078l145.639%20183.79c19.092%2024.1%2015.028%2059.1-9.078%2078.18-24.106%2019.09-59.125%2015.02-78.218-9.07l-169.637-214.08c-9.064-11.44-12.908-25.34-11.867-38.82-1.041-13.48%202.803-27.38%2011.867-38.82zm754.66%20505.798c-19.09%2024.09-54.11%2028.16-78.22%209.07-24.1-19.08-28.17-54.08-9.08-78.18L1514.67%201078l-145.64-183.792c-19.09-24.094-15.02-59.096%209.08-78.18%2024.11-19.083%2059.13-15.021%2078.22%209.074l169.64%20214.078c9.06%2011.44%2012.9%2025.34%2011.86%2038.82%201.04%2013.48-2.8%2027.38-11.86%2038.82z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fsvg%3E"); background-color: var(--topbar-menu-item-hover-bg); background-repeat: no-repeat, repeat-x; background-position: center; @@ -185,7 +187,6 @@ textarea { } @keyframes bounce { - 0%, 20%, 50%, @@ -211,4 +212,4 @@ textarea { 100% { opacity: 1; } -} \ No newline at end of file +} diff --git a/assets/css/login.css b/assets/css/login.css index 4a48272..2574494 100644 --- a/assets/css/login.css +++ b/assets/css/login.css @@ -62,7 +62,7 @@ justify-content: center; position: relative; cursor: pointer; - transition: .2s; + transition: 0.2s; } .form-submit:hover { background: #4183ff; @@ -70,7 +70,7 @@ .form-submit[disabled] { pointer-events: none; user-select: none; - opacity: .5; + opacity: 0.5; } .form-element.disappearance { transform: translateY(-50px); @@ -88,10 +88,10 @@ color: var(--text-color-muted); position: relative; cursor: pointer; - transition: .2s; + transition: 0.2s; } .user-form__links a::after { - content: ''; + content: ""; background: var(--switch-bg-default); width: 1px; height: 50%; @@ -127,7 +127,7 @@ l-line-spinner.animate-appearance { .user-form__error.hidden { opacity: 0; pointer-events: none; - transition: .4s cubic-bezier(0.68, -0.55, 0.27, 1.55); + transition: 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55); } .user-form__error { border-radius: 10px; @@ -138,5 +138,5 @@ l-line-spinner.animate-appearance { font-weight: 500; position: absolute; bottom: 15%; - transition: .4s cubic-bezier(0.68, -0.55, 0.27, 1.55); -} \ No newline at end of file + transition: 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55); +} diff --git a/assets/css/main.css b/assets/css/main.css index 6ad021c..1ab3579 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -1,4 +1,4 @@ -@import url('modals.css'); +@import url("modals.css"); @import url("./window/topWindowList.css"); @import url("components/codeWrapper.css"); @import url("auth.css"); @@ -63,7 +63,7 @@ --main-font: "Inter", sans-serif; --code-font: "JetBrainsMono", monospace; - --uib-color: var(--text-color)!important; + --uib-color: var(--text-color) !important; --ui-scale: 1; @@ -100,18 +100,18 @@ html { .material-symbols-rounded { font-variation-settings: - 'FILL' 1, - 'wght' 600, - 'GRAD' 0, - 'opsz' 40; + "FILL" 1, + "wght" 600, + "GRAD" 0, + "opsz" 40; user-select: none; } .material-symbols-rounded.outline { font-variation-settings: - 'FILL' 0, - 'wght' 400, - 'GRAD' 0, - 'opsz' 40; + "FILL" 0, + "wght" 400, + "GRAD" 0, + "opsz" 40; } body { margin: 0px; @@ -120,14 +120,18 @@ body { height: 100%; overflow: hidden; overscroll-behavior: none; - zoom: var(--ui-scale) + zoom: var(--ui-scale); } -p, a, input, textarea, button { +p, +a, +input, +textarea, +button { font-family: var(--main-font); } .hidden { - display: none!important; + display: none !important; } .text-in-line { @@ -152,49 +156,49 @@ p, a, input, textarea, button { margin-bottom: 10px; flex-shrink: 0; } -.segmented-picker>input { +.segmented-picker > input { pointer-events: none; position: absolute; visibility: hidden; } -.segmented-picker>input:nth-last-of-type(1):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(1):checked ~ label:last-of-type::before { left: 0; } -.segmented-picker>input:nth-last-of-type(2):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(2):checked ~ label:last-of-type::before { left: -100%; } -.segmented-picker>input:nth-last-of-type(3):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(3):checked ~ label:last-of-type::before { left: -200%; } -.segmented-picker>input:nth-last-of-type(4):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(4):checked ~ label:last-of-type::before { left: -300%; } -.segmented-picker>input:nth-last-of-type(5):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(5):checked ~ label:last-of-type::before { left: -400%; } -.segmented-picker>input:nth-last-of-type(6):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(6):checked ~ label:last-of-type::before { left: -500%; } -.segmented-picker>input:nth-last-of-type(7):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(7):checked ~ label:last-of-type::before { left: -600%; } -.segmented-picker>input:nth-last-of-type(8):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(8):checked ~ label:last-of-type::before { left: -700%; } -.segmented-picker>input:nth-last-of-type(9):checked~label:last-of-type::before { +.segmented-picker > input:nth-last-of-type(9):checked ~ label:last-of-type::before { left: -800%; } -.segmented-picker>label { +.segmented-picker > label { align-items: center; cursor: pointer; display: flex; @@ -204,7 +208,7 @@ p, a, input, textarea, button { position: relative; } -.segmented-picker>label>span { +.segmented-picker > label > span { font-size: 14px; font-weight: var(--default-font-weight); letter-spacing: 0.02em; @@ -212,8 +216,7 @@ p, a, input, textarea, button { z-index: 2; } - -.segmented-picker>label:last-of-type::before { +.segmented-picker > label:last-of-type::before { background-color: var(--segment-label); content: ""; display: block; @@ -239,10 +242,10 @@ p, a, input, textarea, button { .form-element { width: 100%; position: relative; - transition: .4s; + transition: 0.4s; } .form-element[disabled] { - opacity: .5; + opacity: 0.5; } input { @@ -252,7 +255,9 @@ input { font-family: Inter; padding: 20px 15px 5px 10px; background-clip: padding-box; - transition: border-color 0.125s ease, box-shadow 0.125s ease; + transition: + border-color 0.125s ease, + box-shadow 0.125s ease; background: var(--block-divider-border-color); border: none; color: var(--text-color); @@ -261,16 +266,16 @@ input { border-radius: 10px; } -input.focused~.form-label, -input:focus~.form-label, -input:valid[required]~.form-label input[placeholder]~.form-label { +input.focused ~ .form-label, +input:focus ~ .form-label, +input:valid[required] ~ .form-label input[placeholder] ~ .form-label { top: 5px; font-size: 12px; line-height: 1.75; left: 10px; } -input~span { +input ~ span { pointer-events: none; } @@ -335,7 +340,7 @@ input~span { } .topbar-section__item { font-size: 14px; - transition: .2s; + transition: 0.2s; user-select: none; } .topbar-section__item.menu-item { @@ -356,11 +361,11 @@ input~span { min-width: 20px; text-align: center; height: 20px; - display: flex!important; + display: flex !important; align-items: center; gap: 3px; border-radius: 100px; - transition: .4s; + transition: 0.4s; overflow: hidden; white-space: nowrap; user-select: none; @@ -378,13 +383,13 @@ input~span { } .topbar-center.topbar-item__clickable { cursor: pointer; - transition: .4s; + transition: 0.4s; } .topbar-center.topbar-item__clickable:hover { - opacity: .5; + opacity: 0.5; } .topbar-center span { - transition: .4s; + transition: 0.4s; font-weight: var(--default-font-weight); } .topbar-center span[class^="material-symbols"] { @@ -453,14 +458,14 @@ input~span { } .topbar-center .topbar-center__text { - transition: .2s; + transition: 0.2s; } .topbar-center .topbar-center__image-icon { width: 14px; - transition: margin-left .4s; + transition: margin-left 0.4s; } .topbar-center .topbar-center__text.hidden { - display: block!important; + display: block !important; opacity: 0; pointer-events: none; } @@ -470,7 +475,7 @@ input~span { height: 8px; background: #3abf6a; border-radius: 100%; - transition: .4s cubic-bezier(0.4, 0, 0.2, 1); + transition: 0.4s cubic-bezier(0.4, 0, 0.2, 1); position: absolute; right: -5px; } @@ -485,7 +490,7 @@ input~span { font-weight: var(--bold-font-weight); } .translucent { - opacity: .5; + opacity: 0.5; } .uppercase { text-transform: uppercase; @@ -503,18 +508,18 @@ input~span { align-items: center; justify-content: center; font-size: 14px; - transition: .2s; + transition: 0.2s; user-select: none; } .topbar-action:hover { cursor: pointer; - opacity: .5; + opacity: 0.5; } .main-wrapper { display: flex; align-items: flex-start; - height: calc(100% - 44px)!important; + height: calc(100% - 44px) !important; min-height: 0; overflow: hidden; } @@ -529,13 +534,13 @@ input~span { color: var(--text-color); font-weight: var(--default-font-weight); position: relative; - transition: .4s; + transition: 0.4s; border-left: 1px solid var(--block-divider-border-color); border-right: 1px solid var(--block-divider-border-color); overflow: hidden; } .explorer.zero-width { - --explorer-width: 0!important; + --explorer-width: 0 !important; min-width: 0; border-left: none; } @@ -562,11 +567,11 @@ input~span { border-radius: 999px; background: var(--text-color); opacity: 0; - transition: opacity .2s; + transition: opacity 0.2s; } .explorer__resize-handle:hover::after, .explorer.resizing .explorer__resize-handle::after { - opacity: .35; + opacity: 0.35; } body.explorer-resizing { cursor: ew-resize; @@ -575,8 +580,8 @@ body.explorer-resizing { .explorer__resize-preview { position: fixed; width: 2px; - border-left: 2px solid rgba(255, 255, 255, .9); - box-shadow: 0 0 0 1px rgba(0, 0, 0, .45); + border-left: 2px solid rgba(255, 255, 255, 0.9); + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.45); pointer-events: none; z-index: 9999; } @@ -603,7 +608,7 @@ body.explorer-resizing { --squircle-radius-bottom-right: 20px; --squircle-radius-bottom-left: 20px; background: var(--explorer-tabs-bg); - transition: .4s; + transition: 0.4s; } .explorer-tabs::after { content: ""; @@ -621,8 +626,8 @@ body.explorer-resizing { pointer-events: none; } .explorer-tabs .explorer-tab { - opacity: .5; - transition: .4s; + opacity: 0.5; + transition: 0.4s; font-size: 20px; width: -webkit-fill-available; height: -webkit-fill-available; @@ -632,7 +637,7 @@ body.explorer-resizing { } .explorer-tabs .explorer-tab.active { opacity: 1; - cursor: pointer; + cursor: pointer; position: relative; } .explorer-tabs .explorer-tab:hover { @@ -641,7 +646,7 @@ body.explorer-resizing { } .explorer-tabs .explorer-tab ion-icon { --ionicon-stroke-width: 40px; - transition: .4s cubic-bezier(0, 0, 0.2, 1); + transition: 0.4s cubic-bezier(0, 0, 0.2, 1); color: var(--explorer-tabs-color); } .explorer-tabs .explorer-tab.hidden { @@ -656,7 +661,7 @@ body.explorer-resizing { padding: var(--explorer-padding); height: 40px; text-transform: capitalize; - transition: .2s; + transition: 0.2s; align-items: center; position: absolute; width: -webkit-fill-available; @@ -687,13 +692,13 @@ body.explorer-resizing { height: 20px; } .explorer-title__actions span[class^="material-symbols"].disabled { - opacity: .2; + opacity: 0.2; pointer-events: none; user-select: none; } .explorer-title__actions > * { - opacity: .5; - transition: .2s; + opacity: 0.5; + transition: 0.2s; } .explorer-title__actions > *:hover { opacity: 1; @@ -711,7 +716,7 @@ body.explorer-resizing { overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; - transition: .2s; + transition: 0.2s; padding-top: 55px; } .explorer-elements__files-empty { @@ -720,7 +725,7 @@ body.explorer-resizing { top: 50%; left: 50%; transform: translate(-50%, -50%); - opacity: .2; + opacity: 0.2; } .explorer-elements__files-empty span[class^="material-symbols"] { font-size: 14px; @@ -731,7 +736,7 @@ body.explorer-resizing { width: 4px; } .explorer-elements > *:last-child { - margin-bottom: 60px!important; + margin-bottom: 60px !important; } .explorer-elements.hidden { opacity: 0; @@ -779,7 +784,7 @@ body.explorer-resizing { border-radius: 3px; } .code-tab.not-saved::before { - content: ''; + content: ""; width: 10px; height: 10px; background: white; @@ -793,14 +798,20 @@ body.explorer-resizing { cursor: pointer; color: var(--text-color); } -.code-tab.dragging { opacity: 0.4; } -.code-tab.drag-over-left { border-left: 2px solid var(--link-color); } -.code-tab.drag-over-right { border-right: 2px solid var(--link-color); } +.code-tab.dragging { + opacity: 0.4; +} +.code-tab.drag-over-left { + border-left: 2px solid var(--link-color); +} +.code-tab.drag-over-right { + border-right: 2px solid var(--link-color); +} .code-tab.active { border-bottom: 2px solid var(--link-color); } .code-tab.active.no-color { - border-bottom: 2px solid var(--link-color)!important; + border-bottom: 2px solid var(--link-color) !important; } .code-tab.active .file-name { color: var(--text-color); @@ -811,7 +822,7 @@ body.explorer-resizing { margin-top: 2px; color: var(--text-color-muted); border-radius: 100%; - transition: .2s; + transition: 0.2s; padding: 1px; } .code-tab span:hover { @@ -861,13 +872,13 @@ body.explorer-resizing { border: 0px; } .ace_content { - width: 100%!important; + width: 100% !important; } .explorer-elements[data-tab="files"] { gap: 5px; } -.explorer-elements .file { +.explorer-elements .file { display: flex; align-items: center; flex: 0 0 auto; @@ -875,7 +886,7 @@ body.explorer-resizing { font-size: 12px; padding: 4px 5px; border-radius: 5px; - transition: .2s; + transition: 0.2s; width: -webkit-fill-available; user-select: none; font-weight: var(--slim-font-weight); @@ -908,7 +919,7 @@ body.explorer-resizing { overflow: visible; min-height: 28px; height: auto; - transition: .2s; + transition: 0.2s; margin-left: 5px; border-left: 1px solid transparent; } @@ -926,7 +937,7 @@ body.explorer-resizing { background: linear-gradient(45deg, transparent 5%, var(--expanded-line) 80%); } .explorer-elements .dir.expanded.ignored::before { - opacity: .45; + opacity: 0.45; } .explorer-elements .dir.expanded > .dir-title:first-child::before { content: ""; @@ -977,7 +988,7 @@ body.explorer-resizing { .explorer-elements .file.ignored, .explorer-elements .dir.ignored > .dir-title, .explorer-elements .dir.ignored .file { - opacity: .45; + opacity: 0.45; } .explorer-elements .dir-content { margin-left: 5px; @@ -1022,13 +1033,13 @@ body.explorer-resizing { } .path-parent { text-transform: capitalize; - opacity: .5; - font-size: 12px!important; - margin-right: 5px!important; + opacity: 0.5; + font-size: 12px !important; + margin-right: 5px !important; } .path-title { - font-size: 12px!important; - opacity: .5; + font-size: 12px !important; + opacity: 0.5; margin-left: 5px; text-transform: none; width: 100px; @@ -1079,12 +1090,12 @@ body.explorer-resizing { font-size: 100px; } .code-start .code-start__main p { - opacity: .5; + opacity: 0.5; } .column-element { position: relative; - transition: .2s; + transition: 0.2s; } .explorer-elements[data-tab="bugs"] { @@ -1145,7 +1156,7 @@ body.explorer-resizing { .elements .elements-empty__text { margin: 0; - opacity: .5; + opacity: 0.5; font-size: 15px; display: flex; align-items: center; @@ -1153,7 +1164,6 @@ body.explorer-resizing { margin-top: 15px; } - .column-element p { margin: 0px; color: var(--text-color); @@ -1192,7 +1202,10 @@ body.explorer-resizing { .explorer-elements[data-tab="history"] .column-element .column-element__title-element { width: fit-content; } -.explorer-elements[data-tab="history"] .column-element .column-element__title-element .column-element__title-element__name { +.explorer-elements[data-tab="history"] + .column-element + .column-element__title-element + .column-element__title-element__name { padding: 0px; } @@ -1203,14 +1216,16 @@ body.explorer-resizing { font-size: 25px; border-radius: 100%; color: var(--text-color); - opacity: .5; + opacity: 0.5; margin-right: 10px; display: flex; align-items: flex-start; justify-content: center; width: 30px; height: 30px; - font-variation-settings: 'wght' 400, 'FILL' 1; + font-variation-settings: + "wght" 400, + "FILL" 1; } .column-element .column-element__title-element { display: flex; @@ -1228,7 +1243,7 @@ body.explorer-resizing { word-wrap: break-word; } .column-element .column-element__title-element__description { - opacity: .3; + opacity: 0.3; font-weight: var(--default-font-weight); line-height: 20px; padding: 10px; @@ -1253,7 +1268,7 @@ body.explorer-resizing { display: flex; align-items: center; gap: 5px; - opacity: .2; + opacity: 0.2; font-size: 12px; } .column-element .column-element__second-element span[class^="material-symbols"] { @@ -1269,7 +1284,9 @@ body.explorer-resizing { } /* column element tree */ -.column-element .column-element__second-element__tree .column-element__second-element:first-child::before { +.column-element + .column-element__second-element__tree + .column-element__second-element:first-child::before { content: ""; background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTcwIiBoZWlnaHQ9IjE3MCIgdmlld0JveD0iMCAwIDE3MCAxNzAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTAgMTIyLjY3NUMwIDU0LjIxOCA1OC40MTEgMCAxMjguODQ0IDBIMTcwdjI3LjU2OGgtNDEuMTU2Yy01Ni42NTkgMC0xMDEuMjc2IDQzLjI4Ny0xMDEuMjc2IDk1LjEwN1YxNzBIMHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="); background-size: cover; @@ -1277,7 +1294,9 @@ body.explorer-resizing { height: 10px; margin-top: 10px; } -.column-element .column-element__second-element__tree .column-element__second-element:last-child::before { +.column-element + .column-element__second-element__tree + .column-element__second-element:last-child::before { content: ""; background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTcwIiBoZWlnaHQ9IjE3MCIgdmlld0JveD0iMCAwIDE3MCAxNzAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyMi42NzUgMTcwQzU0LjIxOCAxNzAgMCAxMTEuNTg5IDAgNDEuMTU2VjBoMjcuNTY4djQxLjE1NmMwIDU2LjY1OSA0My4yODcgMTAxLjI3NiA5NS4xMDcgMTAxLjI3NkgxNzBWMTcweiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg=="); background-size: cover; @@ -1313,7 +1332,7 @@ body.explorer-resizing { position: absolute; top: 0; right: 10px; - opacity: .4; + opacity: 0.4; } .column-element .column-element__buttons { display: flex; @@ -1391,7 +1410,7 @@ body.explorer-resizing { .column-element-linear-graphic__items-item__perc { font-size: 12px; font-weight: 400; - opacity: .5; + opacity: 0.5; position: absolute; right: 20px; } @@ -1405,7 +1424,7 @@ body.explorer-resizing { height: 30px; font-weight: var(--default-font-weight); font-size: 12px; - transition: .2s; + transition: 0.2s; border-radius: 5px; } @@ -1426,12 +1445,12 @@ body.explorer-resizing { } .btn:hover { - opacity: .5; + opacity: 0.5; cursor: pointer; } .settings-col { - margin: 0px!important; + margin: 0px !important; display: flex; flex-direction: column; gap: 5px; @@ -1459,7 +1478,7 @@ body.explorer-resizing { line-height: 20px; } .settings-col__row li::after { - content: ''; + content: ""; position: absolute; top: 8px; left: 3px; @@ -1515,11 +1534,11 @@ body.explorer-resizing { height: 40px; border-radius: 10px; font-size: 25px; - transition: .2s; + transition: 0.2s; } .settings-buttons__wrapper .settings-button:hover { cursor: pointer; - opacity: .5; + opacity: 0.5; } .loader { @@ -1532,12 +1551,12 @@ body.explorer-resizing { background: #0e0e0ef2; z-index: 99; backdrop-filter: blur(50px); - transition: .4s; + transition: 0.4s; flex-direction: column; } .loader .loader-msg { color: var(--text-color); - transition: .4s; + transition: 0.4s; font-weight: var(--default-font-weight); } .loader .loader-msg.hidden { @@ -1560,32 +1579,32 @@ body.explorer-resizing { /* input switch */ .switch { - position: relative; - display: inline-block; + position: relative; + display: inline-block; } .switch-input { - display: none; + display: none; } .switch-label { - display: block; - width: 48px; - height: 24px; - text-indent: -150%; - clip: rect(0 0 0 0); - color: transparent; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; + display: block; + width: 48px; + height: 24px; + text-indent: -150%; + clip: rect(0 0 0 0); + color: transparent; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } .switch-label:before, .switch-label:after { - content: ""; - display: block; - position: absolute; - cursor: pointer; + content: ""; + display: block; + position: absolute; + cursor: pointer; } .switch-label:before { width: 40px; @@ -1602,11 +1621,36 @@ body.explorer-resizing { border-radius: 50%; background-color: var(--switch-inner-default); box-shadow: 0 0 2px rgba(0, 0, 0, 0.45); - transition: left .4s linear(0 0%, 0 1.8%, 0.01 3.6%, 0.03 6.35%, 0.07 9.1%, 0.13 11.4%, 0.19 13.4%, 0.27 15%, 0.34 16.1%, 0.54 18.35%, 0.66 20.6%, 0.72 22.4%, 0.77 24.6%, 0.81 27.3%, 0.85 30.4%, 0.88 35.1%, 0.92 40.6%, 0.94 47.2%, 0.96 55%, 0.98 64%, 0.99 74.4%, 1 86.4%, 1 100%); + transition: left 0.4s + linear( + 0 0%, + 0 1.8%, + 0.01 3.6%, + 0.03 6.35%, + 0.07 9.1%, + 0.13 11.4%, + 0.19 13.4%, + 0.27 15%, + 0.34 16.1%, + 0.54 18.35%, + 0.66 20.6%, + 0.72 22.4%, + 0.77 24.6%, + 0.81 27.3%, + 0.85 30.4%, + 0.88 35.1%, + 0.92 40.6%, + 0.94 47.2%, + 0.96 55%, + 0.98 64%, + 0.99 74.4%, + 1 86.4%, + 1 100% + ); } .switch-input:checked + .switch-label:before { - background-color: var(--switch-bg-active); + background-color: var(--switch-bg-active); } .switch-input:checked + .switch-label:after { left: 20px; @@ -1637,7 +1681,9 @@ body.explorer-resizing { --squircle-radius-bottom-right: 4px; --squircle-radius-bottom-left: 4px; } -.code-footer, .code-structure, .code-taskprogress { +.code-footer, +.code-structure, +.code-taskprogress { position: absolute; bottom: 0; width: -webkit-fill-available; @@ -1647,7 +1693,7 @@ body.explorer-resizing { color: var(--text-color-muted); font-size: 12px; padding: 5px 8px; - display: flex!important; + display: flex !important; align-items: center; justify-content: space-between; border-top: 1px solid var(--block-divider-border-color); @@ -1666,7 +1712,7 @@ body.explorer-resizing { background-size: 200% 100%; animation: shimmer 4s infinite linear; display: inline-block; - transition: .2s; + transition: 0.2s; padding: 0px 10px; height: 30px; @@ -1687,12 +1733,12 @@ body.explorer-resizing { font-weight: 700; } .code-taskprogress.finished .code-taskprogress_name::before { - font-family: 'Material Symbols Rounded'; - content: '\e19f'; + font-family: "Material Symbols Rounded"; + content: "\e19f"; margin-right: 5px; font-size: 18px; font-weight: 400; - font-variation-settings: 'FILL' 1; + font-variation-settings: "FILL" 1; } .code-taskprogress a { color: inherit; @@ -1709,11 +1755,11 @@ body.explorer-resizing { text-decoration-color: var(--taskprogress-text); } .code-taskprogress a::before { - font-family: 'Material Symbols Rounded'; - content: '\fffb5'; + font-family: "Material Symbols Rounded"; + content: "\fffb5"; margin-right: 5px; font-size: 15px; - font-variation-settings: 'FILL' 1; + font-variation-settings: "FILL" 1; } .code-taskprogress_buttons { display: flex; @@ -1726,7 +1772,7 @@ body.explorer-resizing { border-radius: 5px; font-weight: 400; padding: 5px 10px; - transition: .4s; + transition: 0.4s; } .code-taskprogress_buttons button.primary { background: var(--taskprogress-bg); @@ -1739,7 +1785,7 @@ body.explorer-resizing { border: 1px solid var(--taskprogress-bg); } .code-taskprogress_buttons button:hover { - opacity: .5; + opacity: 0.5; cursor: pointer; } .code-structure { @@ -1805,14 +1851,14 @@ body.explorer-resizing { gap: 12px; } .code-footer .code-footer__section-btn { - transition: .4s; + transition: 0.4s; } .code-footer .code-footer__section-btn:hover { color: var(--text-color); cursor: pointer; } .code-footer .code-footer__section-btn.disabled { - opacity: .5; + opacity: 0.5; pointer-events: none; } .code-footer .code-footer__section-btn.row { @@ -1829,7 +1875,7 @@ body.explorer-resizing { position: relative; } .code-footer .code-footer__section .left-divider::after { - content: ''; + content: ""; width: 1px; height: 10px; position: absolute; @@ -1854,7 +1900,7 @@ body.explorer-resizing { display: flex; flex-direction: column; min-width: 300px; - transition: .2s; + transition: 0.2s; position: relative; border-radius: 15px; border: 1px solid var(--topbar-menu-item-hover-bg); @@ -1920,7 +1966,7 @@ body.explorer-resizing { align-items: center; justify-content: center; opacity: 1; - transition: .2s; + transition: 0.2s; } .notify #close:hover { opacity: 1; @@ -1942,12 +1988,12 @@ body.explorer-resizing { z-index: 79; background: #00000063; backdrop-filter: blur(20px); - transition: .4s; + transition: 0.4s; } .backdrop.hidden { opacity: 0; pointer-events: none; - display: flex!important; + display: flex !important; } /* transparent scrollbar sryle */ @@ -1988,7 +2034,7 @@ body.explorer-resizing { position: relative; } .sidebar .sidebar-item { - opacity: .5; + opacity: 0.5; position: relative; font-weight: var(--default-font-weight); font-size: 25px; @@ -2027,7 +2073,7 @@ body.explorer-resizing { } .sidebar .sidebar-item.bottom.disabled { - opacity: .2; + opacity: 0.2; pointer-events: none; } .sidebar .sidebar-item.bottom.disabled .badge { @@ -2051,7 +2097,7 @@ body.explorer-resizing { align-items: center; justify-content: center; padding: 1px 4px; - transition: .2s; + transition: 0.2s; } .sidebar .sidebar-item .badge.hidden { opacity: 0; diff --git a/assets/css/modals.css b/assets/css/modals.css index 6ae7546..d84c9a5 100644 --- a/assets/css/modals.css +++ b/assets/css/modals.css @@ -22,12 +22,37 @@ display: flex; justify-content: center; align-items: center; - transition: .4s linear(0 0%, 0 1.8%, 0.01 3.6%, 0.03 6.35%, 0.07 9.1%, 0.13 11.4%, 0.19 13.4%, 0.27 15%, 0.34 16.1%, 0.54 18.35%, 0.66 20.6%, 0.72 22.4%, 0.77 24.6%, 0.81 27.3%, 0.85 30.4%, 0.88 35.1%, 0.92 40.6%, 0.94 47.2%, 0.96 55%, 0.98 64%, 0.99 74.4%, 1 86.4%, 1 100%); + transition: 0.4s + linear( + 0 0%, + 0 1.8%, + 0.01 3.6%, + 0.03 6.35%, + 0.07 9.1%, + 0.13 11.4%, + 0.19 13.4%, + 0.27 15%, + 0.34 16.1%, + 0.54 18.35%, + 0.66 20.6%, + 0.72 22.4%, + 0.77 24.6%, + 0.81 27.3%, + 0.85 30.4%, + 0.88 35.1%, + 0.92 40.6%, + 0.94 47.2%, + 0.96 55%, + 0.98 64%, + 0.99 74.4%, + 1 86.4%, + 1 100% + ); } .modal-wrapper.hidden { transform: translateY(100%); pointer-events: none; - display: flex!important; + display: flex !important; } .modal-wrapper .modal, .modal-wrapper .modal.lg { @@ -70,8 +95,8 @@ } .modal.confirm { - width: 400px!important; - height: 200px!important; + width: 400px !important; + height: 200px !important; } .modal.confirm .confirm-title { font-size: 15px; @@ -81,7 +106,7 @@ .modal.confirm .confirm-desc { font-size: 14px; font-weight: 400; - opacity: .5; + opacity: 0.5; } .modal.confirm .confirm-buttons { position: absolute; @@ -95,13 +120,13 @@ color: var(--text-color); padding: 8px 12px; border-radius: 5px; - transition: .2s; + transition: 0.2s; } .modal.confirm .confirm-buttons button.danger { background: var(--danger); } .modal.confirm .confirm-buttons button:hover { - opacity: .5; + opacity: 0.5; cursor: pointer; } @@ -118,8 +143,11 @@ } .modal-note::before { content: "\e000"; - font-family: 'Material Symbols Rounded'; - font-variation-settings: 'FILL' 1, 'wght' 700, 'opzs' 24; + font-family: "Material Symbols Rounded"; + font-variation-settings: + "FILL" 1, + "wght" 700, + "opzs" 24; margin-right: 5px; font-size: 15px; color: var(--warning); @@ -129,4 +157,4 @@ border-top: 1px solid var(--context-border); margin-top: 5px; margin-bottom: 5px; -} \ No newline at end of file +} diff --git a/assets/css/modals/badges.css b/assets/css/modals/badges.css index 63eae17..5c43924 100644 --- a/assets/css/modals/badges.css +++ b/assets/css/modals/badges.css @@ -25,7 +25,9 @@ border-radius: 5px; width: 15px; height: 15px; - clip-path: path("M6.27861 0.626884C7.11057 -0.204959 7.88317 -0.211655 8.71513 0.626884L9.73271 1.63665C9.83834 1.73578 9.93105 1.76945 10.0696 1.76946H11.4964C12.6845 1.7696 13.2259 2.3238 13.2259 3.49895V4.93157C13.2259 5.06366 13.2657 5.16307 13.3645 5.26165L14.3685 6.27825C15.2069 7.11016 15.2137 7.88287 14.3685 8.71478L13.3645 9.73235C13.2659 9.83782 13.2259 9.92995 13.2259 10.0683V11.495C13.2258 12.6831 12.678 13.2244 11.4964 13.2245H10.0696C9.93103 13.2246 9.83835 13.2643 9.73271 13.3632L8.71611 14.374C7.88381 15.2059 7.11063 15.2123 6.27861 14.374L5.26201 13.3632C5.16289 13.2644 5.06399 13.2246 4.93193 13.2245H3.49833C2.31697 13.2244 1.76891 12.6766 1.76884 11.495V10.0683C1.7688 9.93001 1.73555 9.83777 1.63701 9.73235L0.626265 8.71478C-0.205383 7.88278 -0.21212 7.11066 0.626265 6.27923L1.63603 5.26165C1.7352 5.16249 1.76884 5.06368 1.76884 4.93157V3.49895C1.76886 2.3107 2.31739 1.7685 3.49931 1.76849H4.93193C5.06405 1.76848 5.1634 1.73552 5.26201 1.63665L6.27861 0.626884Z"); + clip-path: path( + "M6.27861 0.626884C7.11057 -0.204959 7.88317 -0.211655 8.71513 0.626884L9.73271 1.63665C9.83834 1.73578 9.93105 1.76945 10.0696 1.76946H11.4964C12.6845 1.7696 13.2259 2.3238 13.2259 3.49895V4.93157C13.2259 5.06366 13.2657 5.16307 13.3645 5.26165L14.3685 6.27825C15.2069 7.11016 15.2137 7.88287 14.3685 8.71478L13.3645 9.73235C13.2659 9.83782 13.2259 9.92995 13.2259 10.0683V11.495C13.2258 12.6831 12.678 13.2244 11.4964 13.2245H10.0696C9.93103 13.2246 9.83835 13.2643 9.73271 13.3632L8.71611 14.374C7.88381 15.2059 7.11063 15.2123 6.27861 14.374L5.26201 13.3632C5.16289 13.2644 5.06399 13.2246 4.93193 13.2245H3.49833C2.31697 13.2244 1.76891 12.6766 1.76884 11.495V10.0683C1.7688 9.93001 1.73555 9.83777 1.63701 9.73235L0.626265 8.71478C-0.205383 7.88278 -0.21212 7.11066 0.626265 6.27923L1.63603 5.26165C1.7352 5.16249 1.76884 5.06368 1.76884 4.93157V3.49895C1.76886 2.3107 2.31739 1.7685 3.49931 1.76849H4.93193C5.06405 1.76848 5.1634 1.73552 5.26201 1.63665L6.27861 0.626884Z" + ); justify-content: center; } @@ -44,7 +46,9 @@ } */ .modal-verified__badge span[class^="material-symbols"] { font-size: 10px; - font-variation-settings: 'FILL' 1, 'wght' 700 !important; + font-variation-settings: + "FILL" 1, + "wght" 700 !important; margin-top: 1px; } @@ -59,6 +63,8 @@ } .modal-owner__badge span[class^="material-symbols"] { font-size: 14px; - font-variation-settings: 'FILL' 1, 'wght' 700 !important; + font-variation-settings: + "FILL" 1, + "wght" 700 !important; margin-top: 1px; -} \ No newline at end of file +} diff --git a/assets/css/modals/buttons.css b/assets/css/modals/buttons.css index d63ca5f..c5a8bc6 100644 --- a/assets/css/modals/buttons.css +++ b/assets/css/modals/buttons.css @@ -6,7 +6,7 @@ border-radius: 10px; font-size: 14px; border: 1px solid var(--block-divider-border-color); - transition: .2s; + transition: 0.2s; } .modal-button:hover { background: var(--topbar-menu-item-hover-bg); @@ -18,4 +18,4 @@ color: #ff5b5b; font-weight: 400; border: 1px solid #ff5b5b14; -} \ No newline at end of file +} diff --git a/assets/css/modals/category.css b/assets/css/modals/category.css index 7200213..51be445 100644 --- a/assets/css/modals/category.css +++ b/assets/css/modals/category.css @@ -27,7 +27,7 @@ height: fit-content; } .modal-category__item.disabled { - opacity: .5; + opacity: 0.5; pointer-events: none; user-select: none; } @@ -41,7 +41,7 @@ gap: 5px; } .modal-category__item .modal-category__item-desc { - opacity: .5; + opacity: 0.5; font-size: 14px; font-weight: var(--default-font-weight); } @@ -91,16 +91,16 @@ align-items: center; flex-shrink: 0; gap: 5px; - transition: .2s; + transition: 0.2s; } .modal-category__item .modal-appicons div p { margin: 0; font-size: 12px; } .modal-category__item .modal-appicons div.active { - opacity: .5; + opacity: 0.5; } .modal-category__item .modal-appicons div:hover { - opacity: .5; + opacity: 0.5; cursor: pointer; -} \ No newline at end of file +} diff --git a/assets/css/modals/centered.css b/assets/css/modals/centered.css index 2fd9771..93b748d 100644 --- a/assets/css/modals/centered.css +++ b/assets/css/modals/centered.css @@ -9,5 +9,5 @@ } .modal-centered span { font-size: 100px; - opacity: .1; -} \ No newline at end of file + opacity: 0.1; +} diff --git a/assets/css/modals/container.css b/assets/css/modals/container.css index a77cd08..5dd43ab 100644 --- a/assets/css/modals/container.css +++ b/assets/css/modals/container.css @@ -5,5 +5,5 @@ } .modal-container.disabled { pointer-events: none; - opacity: .5; -} \ No newline at end of file + opacity: 0.5; +} diff --git a/assets/css/modals/extensionItem.css b/assets/css/modals/extensionItem.css index 87421c5..f04b296 100644 --- a/assets/css/modals/extensionItem.css +++ b/assets/css/modals/extensionItem.css @@ -31,7 +31,7 @@ .modal-extension__item .modal-extension__item-subtitle { font-size: 12px; font-weight: var(--slim-font-weight); - opacity: .5; + opacity: 0.5; max-width: 90%; white-space: nowrap; overflow: hidden; @@ -40,7 +40,7 @@ .modal-extension__item .modal-extension__item-desc { font-size: 14px; font-weight: var(--slim-font-weight); - opacity: .5; + opacity: 0.5; } .modal-extension__item .modal-extension__item-tag__wrapper { display: flex; @@ -58,7 +58,9 @@ display: flex; align-items: center; } -.modal-extension__item .modal-extension__item-tag__wrapper .modal-extension__item-tag.module::before { +.modal-extension__item + .modal-extension__item-tag__wrapper + .modal-extension__item-tag.module::before { content: "M"; background: var(--danger); height: 100%; @@ -69,7 +71,9 @@ padding: 3px; font-weight: var(--medium-font-weight); } -.modal-extension__item .modal-extension__item-tag__wrapper .modal-extension__item-tag.permission::before { +.modal-extension__item + .modal-extension__item-tag__wrapper + .modal-extension__item-tag.permission::before { content: "P"; background: var(--warning); height: 100%; @@ -102,10 +106,13 @@ border: 1px solid var(--text-color); color: var(--text-color); border-radius: 100%; - opacity: .2; - transition: .2s; + opacity: 0.2; + transition: 0.2s; } -.modal-extension__item .modal-extension__item-btn__wrapper .modal-extension__item-btn span[class^="material-symbols"] { +.modal-extension__item + .modal-extension__item-btn__wrapper + .modal-extension__item-btn + span[class^="material-symbols"] { font-size: 15px; } .modal-extension__item .modal-extension__item-btn__wrapper .modal-extension__item-btn:hover { @@ -116,8 +123,10 @@ color: var(--danger); border-color: var(--danger); } -.modal-extension__item .modal-extension__item-btn__wrapper .modal-extension__item-btn.text-danger:hover { - opacity: .8; +.modal-extension__item + .modal-extension__item-btn__wrapper + .modal-extension__item-btn.text-danger:hover { + opacity: 0.8; } .modal-extension__toggle { transform: scale(0.8); @@ -135,10 +144,20 @@ } @keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } + from { + opacity: 0; + } + to { + opacity: 1; + } } @keyframes scaleIn { - from { opacity: 0; transform: scale(.95); } - to { opacity: 1; transform: scale(1); } -} \ No newline at end of file + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} diff --git a/assets/css/modals/githubrepos.css b/assets/css/modals/githubrepos.css index 54e16cf..8802353 100644 --- a/assets/css/modals/githubrepos.css +++ b/assets/css/modals/githubrepos.css @@ -15,10 +15,10 @@ color: var(--text-color); text-decoration: none; font-size: 15px; - transition: .4s; + transition: 0.4s; } .modal-githubrepos__item:hover { - opacity: .5; + opacity: 0.5; cursor: pointer; } .modal-githubrepos__icon { @@ -49,9 +49,9 @@ border: 1px solid var(--block-divider-border-color); border-radius: 10px; height: 40px; - transition: .4s; + transition: 0.4s; } .modal-githubrepos .modal-githubrepos__forkbtn:hover { - opacity: .5; + opacity: 0.5; cursor: pointer; -} \ No newline at end of file +} diff --git a/assets/css/modals/header.css b/assets/css/modals/header.css index a2219f3..8bd2a36 100644 --- a/assets/css/modals/header.css +++ b/assets/css/modals/header.css @@ -29,8 +29,8 @@ text-align: left; } .modal-wrapper .modal-header .modal-header__close { - opacity: .2; - transition: .4s; + opacity: 0.2; + transition: 0.4s; display: flex; align-items: center; margin-right: -8px; @@ -45,4 +45,4 @@ } .modal-wrapper .modal-header p { margin: 0px; -} \ No newline at end of file +} diff --git a/assets/css/modals/infoBlocks.css b/assets/css/modals/infoBlocks.css index ff18d81..8b76b56 100644 --- a/assets/css/modals/infoBlocks.css +++ b/assets/css/modals/infoBlocks.css @@ -25,5 +25,5 @@ } .modal-infoblocks .modal-infoblocks__desc { font-size: 14px; - opacity: .5; -} \ No newline at end of file + opacity: 0.5; +} diff --git a/assets/css/modals/list.css b/assets/css/modals/list.css index 9610df4..32d694a 100644 --- a/assets/css/modals/list.css +++ b/assets/css/modals/list.css @@ -6,4 +6,4 @@ .modal-list.list-grid { display: grid; grid-template-columns: repeat(2, 1fr); -} \ No newline at end of file +} diff --git a/assets/css/modals/modalBodyContent.css b/assets/css/modals/modalBodyContent.css index aa38f19..9babb5d 100644 --- a/assets/css/modals/modalBodyContent.css +++ b/assets/css/modals/modalBodyContent.css @@ -2,4 +2,4 @@ display: flex; flex-direction: column; gap: 15px; -} \ No newline at end of file +} diff --git a/assets/css/modals/org.css b/assets/css/modals/org.css index 3c9d921..9fd702c 100644 --- a/assets/css/modals/org.css +++ b/assets/css/modals/org.css @@ -2,7 +2,7 @@ display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; - padding: 20px!important; + padding: 20px !important; justify-items: stretch; align-items: stretch; grid-auto-rows: min-content; @@ -27,11 +27,13 @@ height: 50px; font-size: 25px; border-radius: 5px; - box-shadow: var(--background) 0px 0px 200px 0px, #00000026 0px 2px 6px 0px; + box-shadow: + var(--background) 0px 0px 200px 0px, + #00000026 0px 2px 6px 0px; font-weight: 500; } .modal-org .modal-org__title { - font-weight: var(--medium-font-weight);; + font-weight: var(--medium-font-weight); font-size: 15px; align-items: center; width: fit-content; @@ -42,7 +44,7 @@ .modal-org .modal-org-description { font-size: small; width: 100%; - opacity: .5; + opacity: 0.5; line-height: 18px; word-wrap: break-word; } @@ -103,7 +105,7 @@ .modal-org .modal-org__section-counters .modal-org__section-counter p.title { font-size: 12px; font-weight: 500; - opacity: .5; + opacity: 0.5; } .modal-org .modal-org__section-counters .modal-org__section-counter p.value { font-weight: 500; @@ -138,4 +140,4 @@ .modal-org .modal-note { margin-top: 0px; -} \ No newline at end of file +} diff --git a/assets/css/modals/placeholder.css b/assets/css/modals/placeholder.css index 31a91eb..4f2b62f 100644 --- a/assets/css/modals/placeholder.css +++ b/assets/css/modals/placeholder.css @@ -1,5 +1,5 @@ .modal-category__item.placeholder-bigdata .modal-category__item-title { - opacity: .5; + opacity: 0.5; } .modal-category__item.placeholder-bigdata .modal-category__item-desc { font-size: 20px; @@ -7,5 +7,5 @@ user-select: all; } .modal-category__item.placeholder-label .modal-category__item-desc { - opacity: .2; -} \ No newline at end of file + opacity: 0.2; +} diff --git a/assets/css/modals/sidebar.css b/assets/css/modals/sidebar.css index 3493546..17d6a09 100644 --- a/assets/css/modals/sidebar.css +++ b/assets/css/modals/sidebar.css @@ -6,16 +6,25 @@ display: flex; flex-direction: column; gap: 5px; - border-right: 1px solid var(--block-divider-border-color); + border-right: 1px solid var(--block-divider-border-color); } -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item.title { +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item.title { font-size: 14px; font-weight: 600; margin-bottom: 5px; background: none; - opacity: .5; -} -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item.title .avatar { + opacity: 0.5; +} +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item.title + .avatar { width: 18px; height: 18px; object-fit: cover; @@ -28,30 +37,57 @@ padding: 5px 10px; border-radius: 5px; font-size: 14px; - transition: .2s; + transition: 0.2s; position: relative; } -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item:hover { +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item:hover { background: var(--body-color); cursor: pointer; } -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item.active { +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item.active { background: var(--body-color); } -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item.active span[class^="material-symbols"] { +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item.active + span[class^="material-symbols"] { opacity: 1; } -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item span[class^="material-symbols"] { +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item + span[class^="material-symbols"] { font-size: 15px; - opacity: .5; -} -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item .modal-sidebar__item-label { - opacity: .5; + opacity: 0.5; +} +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item + .modal-sidebar__item-label { + opacity: 0.5; position: absolute; right: 10px; font-size: 12px; } -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item.sidebar-divider { +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item.sidebar-divider { border-top: 1px solid var(--context-border); border-radius: 0px; margin-left: -10px; @@ -60,7 +96,11 @@ width: 100%; padding: 0px 10px; } -.modal-wrapper .modal.window .modal-body.modal-body-sidebar .modal-sidebar .modal-sidebar__item.sidebar-divider:hover { +.modal-wrapper + .modal.window + .modal-body.modal-body-sidebar + .modal-sidebar + .modal-sidebar__item.sidebar-divider:hover { background: inherit; cursor: default; } @@ -101,7 +141,7 @@ border-radius: 10px; } .modal-body__sidebar-content.modal-row.disabled { - opacity: .5; + opacity: 0.5; pointer-events: none; } .modal-body__sidebar-content.modal-row .modal-category__item { diff --git a/assets/css/modals/sizes.css b/assets/css/modals/sizes.css index ed6c221..975ffb6 100644 --- a/assets/css/modals/sizes.css +++ b/assets/css/modals/sizes.css @@ -4,21 +4,21 @@ height: 80%; } .modal-wrapper .modal.md { - width: 70%!important; - min-height: 60%!important; - height: fit-content!important; + width: 70% !important; + min-height: 60% !important; + height: fit-content !important; } .modal-wrapper .modal.sm { - width: 50%!important; - min-height: 40%!important; - height: fit-content!important; + width: 50% !important; + min-height: 40% !important; + height: fit-content !important; } .modal-wrapper .modal.mini { - min-height: 0px!important; - width: 30%!important; - height: fit-content!important; + min-height: 0px !important; + width: 30% !important; + height: fit-content !important; } .modal-wrapper .modal.full { width: 80%; height: fit-content; -} \ No newline at end of file +} diff --git a/assets/css/notification.css b/assets/css/notification.css index 5ce4b1e..2b97e6a 100644 --- a/assets/css/notification.css +++ b/assets/css/notification.css @@ -22,7 +22,7 @@ overflow: hidden; } .notification-icon.initials .generated-avatar { - background: linear-gradient(0deg, var(--background), var(--background-second))!important; + background: linear-gradient(0deg, var(--background), var(--background-second)) !important; color: var(--foreground); display: flex; align-items: center; @@ -68,7 +68,7 @@ } .notification-info .notification-description { font-size: small; - opacity: .5; + opacity: 0.5; font-weight: 300; line-height: 20px; white-space: pre-wrap; @@ -79,7 +79,7 @@ position: absolute; right: 15px; top: 15px; - opacity: .5; + opacity: 0.5; } .notification-info .notification-close span { font-size: 14px; @@ -87,4 +87,4 @@ .notification-info .notification-close:hover { opacity: 1; cursor: pointer; -} \ No newline at end of file +} diff --git a/assets/css/register.css b/assets/css/register.css index 7d698d6..fa3abbd 100644 --- a/assets/css/register.css +++ b/assets/css/register.css @@ -1,3 +1,3 @@ .user-form__error { bottom: 15%; -} \ No newline at end of file +} diff --git a/assets/css/splash.css b/assets/css/splash.css index b234a5e..f0c9f7a 100644 --- a/assets/css/splash.css +++ b/assets/css/splash.css @@ -15,7 +15,7 @@ h3, h4, h5, button { - font-family: "Inter", sans-serif!important; + font-family: "Inter", sans-serif !important; } .hidden { @@ -76,18 +76,18 @@ p { } .version { - opacity: .2; + opacity: 0.2; font-size: 14px; } .description { - opacity: .5; + opacity: 0.5; margin-top: 10px; text-align: left; } .author { - opacity: .2; + opacity: 0.2; font-size: 10px; margin-top: 10px; } @@ -97,7 +97,7 @@ p { } .status { - opacity: .5; + opacity: 0.5; margin-top: 10px; font-size: 10px; text-align: left; @@ -118,16 +118,18 @@ p { border-radius: 5px; border: none; color: white; - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-family: + system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, + "Open Sans", "Helvetica Neue", sans-serif; padding: 10px 15px; font-weight: 400; cursor: pointer; - transition: .2s; + transition: 0.2s; outline: none; } .buttons button:hover { - opacity: .5; + opacity: 0.5; background: #3c3c3c; } @@ -186,4 +188,4 @@ p { 100% { stroke-dashoffset: -100; } -} \ No newline at end of file +} diff --git a/assets/css/themes/contrast-dark.theme.css b/assets/css/themes/contrast-dark.theme.css index 505710c..3d44378 100644 --- a/assets/css/themes/contrast-dark.theme.css +++ b/assets/css/themes/contrast-dark.theme.css @@ -32,4 +32,4 @@ body[theme="contrast-dark"] { body[theme="contrast-dark"] .ace-tomorrow-night-bright .ace_gutter { background: var(--body-color); border-right: 1px solid var(--block-divider-border-color); -} \ No newline at end of file +} diff --git a/assets/css/themes/light.theme.css b/assets/css/themes/light.theme.css index 1fcaef1..07f4bdf 100644 --- a/assets/css/themes/light.theme.css +++ b/assets/css/themes/light.theme.css @@ -22,7 +22,7 @@ body[theme="light"] { --segment-divider: #ffffff1a; --danger: #ff4949; --warning: #e59036; - + --code-footer-bg: #ffffffcf; --notificator-body-bg: #ffffffb5; --notificator-body-border: #e9e9e9; @@ -55,4 +55,4 @@ body[theme="light"] .explorer-elements .file.active { body[theme="light"] .ace_marker-layer .ace_active-line { background: #bcbcbc2e; -} \ No newline at end of file +} diff --git a/assets/css/themes/terminal.theme.css b/assets/css/themes/terminal.theme.css index a553df1..9cc36db 100644 --- a/assets/css/themes/terminal.theme.css +++ b/assets/css/themes/terminal.theme.css @@ -1,6 +1,6 @@ body[theme="terminal"] * { - transition: none!important; - border-radius: 0!important; + transition: none !important; + border-radius: 0 !important; } body[theme="terminal"] { @@ -52,4 +52,4 @@ body[theme="terminal"] .popup-content { body[theme="terminal"] .explorer-title { background: var(--code-background); backdrop-filter: none; -} \ No newline at end of file +} diff --git a/assets/css/window/global.css b/assets/css/window/global.css index 969818b..108496d 100644 --- a/assets/css/window/global.css +++ b/assets/css/window/global.css @@ -13,9 +13,9 @@ opacity: 1; pointer-events: all; - transition: .2s; + transition: 0.2s; } .top-window.hidden { opacity: 0; pointer-events: none; -} \ No newline at end of file +} diff --git a/assets/css/window/topWindowList.css b/assets/css/window/topWindowList.css index 84dcd3f..19e5d7e 100644 --- a/assets/css/window/topWindowList.css +++ b/assets/css/window/topWindowList.css @@ -13,12 +13,12 @@ } .top-window.list .top-window__list-item { color: var(--text-color); - opacity: .5; + opacity: 0.5; background: transparent; border-radius: 5px; padding: 3px 5px; font-size: 14px; - transition: .2s; + transition: 0.2s; } .top-window.list .top-window__list-item:hover { opacity: 1; @@ -42,5 +42,5 @@ gap: 10px; } .top-window.list .top-window__list-item .top-window__list-item__name-wrapper .secondary { - opacity: .5; -} \ No newline at end of file + opacity: 0.5; +} diff --git a/assets/css/xterm-custom.css b/assets/css/xterm-custom.css index 8245553..f1753b9 100644 --- a/assets/css/xterm-custom.css +++ b/assets/css/xterm-custom.css @@ -1,5 +1,5 @@ .xterm-dom-renderer-owner-1 .xterm-fg-1 { border-left: 2px solid #cc0000; - color: #ff9695!important; + color: #ff9695 !important; padding-left: 10px; -} \ No newline at end of file +} diff --git a/assets/js/ErrorReporter.js b/assets/js/ErrorReporter.js index 2bc87ed..85104f9 100644 --- a/assets/js/ErrorReporter.js +++ b/assets/js/ErrorReporter.js @@ -4,27 +4,26 @@ export class ErrorReporter { type: "syntax", message: error.message, line: error.loc?.line ?? null, - column: error.loc?.column ?? null - } + column: error.loc?.column ?? null, + }; } static fromRuntime(error) { + let line = null; + let column = null; - let line = null - let column = null - - const match = error.stack?.match(/:(\d+):(\d+)/) + const match = error.stack?.match(/:(\d+):(\d+)/); if (match) { - line = Number(match[1]) - column = Number(match[2]) + line = Number(match[1]); + column = Number(match[2]); } return { type: "runtime", message: error.message, line, - column - } + column, + }; } -} \ No newline at end of file +} diff --git a/assets/js/actions.js b/assets/js/actions.js index 429d8e0..3935eee 100644 --- a/assets/js/actions.js +++ b/assets/js/actions.js @@ -1,25 +1,25 @@ export function initActions() { - document.querySelectorAll("[action]").forEach(e => { - const ID = e.getAttribute("action") + document.querySelectorAll("[action]").forEach((e) => { + const Id = e.getAttribute("action"); e.addEventListener("click", async () => { - console.log(ID) - if(ID == "logout") { - await window.electron.logout() - await window.electron.reload() + console.log(Id); + if (Id == "logout") { + await window.electron.logout(); + await window.electron.reload(); } - if(ID == "appclose") { - window.electron.close() + if (Id == "appclose") { + window.electron.close(); } - if(ID == "appminimize") { - window.electron.minimize() + if (Id == "appminimize") { + window.electron.minimize(); } - if(ID == "appmaximize") { - window.electron.maximize() + if (Id == "appmaximize") { + window.electron.maximize(); } - if(ID == "appreload") { - window.electron.reload() + if (Id == "appreload") { + window.electron.reload(); } - }) - }) -} \ No newline at end of file + }); + }); +} diff --git a/assets/js/auth/authRenderer.js b/assets/js/auth/authRenderer.js index 2a2b3aa..5aa95a1 100644 --- a/assets/js/auth/authRenderer.js +++ b/assets/js/auth/authRenderer.js @@ -1,231 +1,242 @@ -import { GLS } from "../lib.js" +import { GLS } from "../lib.js"; -export let inputs = document.querySelectorAll("input") -export let submitBtn = document.querySelector(".form-submit") -export let usernameInput = document.querySelector("#username") -export let emailInput = document.querySelector("#email") -export let codeInput = document.querySelector("#code") -export let passwordInput = document.querySelector("#password") -export let confirmPassword = document.querySelector("#confirm_password") -export let errorBlock = document.querySelector(".user-form__error") +export const inputs = document.querySelectorAll("input"); +export const submitBtn = document.querySelector(".form-submit"); +export const usernameInput = document.querySelector("#username"); +export const emailInput = document.querySelector("#email"); +export const codeInput = document.querySelector("#code"); +export const passwordInput = document.querySelector("#password"); +export const confirmPassword = document.querySelector("#confirm_password"); +export const errorBlock = document.querySelector(".user-form__error"); -export const userFormWrapper = document.querySelector(".user-form__wrapper") +export const userFormWrapper = document.querySelector(".user-form__wrapper"); export function getFormLabel(input) { - if(input) { - return input.parentElement.querySelector(".form-label") + if (input) { + return input.parentElement.querySelector(".form-label"); } } -let submitBtnOriginText = submitBtn.textContent -let loadingHTML = ` +const submitBtnOriginText = submitBtn.textContent; +const loadingHtml = ` -` +`; export function disableButtons() { if (usernameInput) { - usernameInput.parentElement.setAttribute("disabled", true) - usernameInput.setAttribute("disabled", true) + usernameInput.parentElement.setAttribute("disabled", true); + usernameInput.setAttribute("disabled", true); } if (passwordInput) { - passwordInput.parentElement.setAttribute("disabled", true) - passwordInput.setAttribute("disabled", true) + passwordInput.parentElement.setAttribute("disabled", true); + passwordInput.setAttribute("disabled", true); } if (confirmPassword) { - confirmPassword.parentElement.setAttribute("disabled", true) - confirmPassword.setAttribute("disabled", true) + confirmPassword.parentElement.setAttribute("disabled", true); + confirmPassword.setAttribute("disabled", true); } if (emailInput) { - emailInput.parentElement.setAttribute("disabled", true) - emailInput.setAttribute("disabled", true) + emailInput.parentElement.setAttribute("disabled", true); + emailInput.setAttribute("disabled", true); } if (codeInput) { - codeInput.parentElement.setAttribute("disabled", true) - codeInput.setAttribute("disabled", true) + codeInput.parentElement.setAttribute("disabled", true); + codeInput.setAttribute("disabled", true); } } export function unDisableButtons() { if (usernameInput) { - usernameInput.parentElement.removeAttribute("disabled", true) - usernameInput.removeAttribute("disabled", true) + usernameInput.parentElement.removeAttribute("disabled", true); + usernameInput.removeAttribute("disabled", true); } if (passwordInput) { - passwordInput.parentElement.removeAttribute("disabled", true) - passwordInput.removeAttribute("disabled", true) + passwordInput.parentElement.removeAttribute("disabled", true); + passwordInput.removeAttribute("disabled", true); } if (confirmPassword) { - confirmPassword.parentElement.removeAttribute("disabled", true) - confirmPassword.removeAttribute("disabled", true) + confirmPassword.parentElement.removeAttribute("disabled", true); + confirmPassword.removeAttribute("disabled", true); } if (emailInput) { - emailInput.parentElement.removeAttribute("disabled", true) - emailInput.removeAttribute("disabled", true) + emailInput.parentElement.removeAttribute("disabled", true); + emailInput.removeAttribute("disabled", true); } if (codeInput) { - codeInput.parentElement.removeAttribute("disabled", true) - codeInput.removeAttribute("disabled", true) + codeInput.parentElement.removeAttribute("disabled", true); + codeInput.removeAttribute("disabled", true); } } -export function hideEl(ID) { - const el = document.querySelector(`#${ID}`) - if(el) { - el.setAttribute("disabled", true) - el.classList.add("hidden") +export function hideEl(Id) { + const el = document.querySelector(`#${Id}`); + if (el) { + el.setAttribute("disabled", true); + el.classList.add("hidden"); - if(el.querySelector("input")) { - el.querySelector("input").setAttribute("disabled", true) + if (el.querySelector("input")) { + el.querySelector("input").setAttribute("disabled", true); } } } -export function showEl(ID) { - const el = document.querySelector(`#${ID}`) - if(el) { - el.removeAttribute("disabled") - el.classList.remove("hidden") - - if(el.querySelector("input")) { - el.querySelector("input").removeAttribute("disabled") +export function showEl(Id) { + const el = document.querySelector(`#${Id}`); + if (el) { + el.removeAttribute("disabled"); + el.classList.remove("hidden"); + + if (el.querySelector("input")) { + el.querySelector("input").removeAttribute("disabled"); } } } -export function disableEl(ID) { - const el = document.querySelector(`#${ID}`) - if(el) { - el.setAttribute("disabled", true) +export function disableEl(Id) { + const el = document.querySelector(`#${Id}`); + if (el) { + el.setAttribute("disabled", true); - if(el.querySelector("input")) { - el.querySelector("input").setAttribute("disabled", true) + if (el.querySelector("input")) { + el.querySelector("input").setAttribute("disabled", true); } } } -export function unDisableEl(ID) { - const el = document.querySelector(`#${ID}`) - if(el) { - el.removeAttribute("disabled") +export function unDisableEl(Id) { + const el = document.querySelector(`#${Id}`); + if (el) { + el.removeAttribute("disabled"); - if(el.querySelector("input")) { - el.querySelector("input").removeAttribute("disabled") + if (el.querySelector("input")) { + el.querySelector("input").removeAttribute("disabled"); } } } export function showErrBlock(text, time = 5000) { - errorBlock.classList.remove("hidden") - errorBlock.innerText = text + errorBlock.classList.remove("hidden"); + errorBlock.innerText = text; setTimeout(() => { - errorBlock.classList.add("hidden") - }, time) + errorBlock.classList.add("hidden"); + }, time); } export function initInputs() { if (inputs.length > 0) { - inputs.forEach(input => { + inputs.forEach((input) => { input.addEventListener("input", (e) => { if (e.target.value.length > 0) { - input.classList.add("focused") - } - else { - input.classList.remove("focused") + input.classList.add("focused"); + } else { + input.classList.remove("focused"); } - }) - }) + }); + }); } } export function transition(callback) { setTimeout(() => { - userFormWrapper.style.opacity = 0 - userFormWrapper.style.pointerEvents = "none" - }, 0) + userFormWrapper.style.opacity = 0; + userFormWrapper.style.pointerEvents = "none"; + }, 0); setTimeout(() => { - if(callback) callback() - userFormWrapper.style.opacity = 1 - userFormWrapper.style.pointerEvents = "all" - }, 500) + if (callback) callback(); + userFormWrapper.style.opacity = 1; + userFormWrapper.style.pointerEvents = "all"; + }, 500); } // Add a visibility toggle to password inputs document.addEventListener("DOMContentLoaded", async () => { - const gls = await GLS.init() - - if(document.querySelector("#alreadyHaveAccount")) document.querySelector("#alreadyHaveAccount").textContent = gls.get("auth.alreadyHaveAnAccount") - if(document.querySelector("#howToRegisterOrg")) document.querySelector("#howToRegisterOrg").textContent = gls.get("auth.howToRegOrganization") - if(document.querySelector("#registerNewAccount")) document.querySelector("#registerNewAccount").textContent = gls.get("auth.registerNewAccount") - if(document.querySelector("#skipAccountCreation")) document.querySelector("#skipAccountCreation").textContent = gls.get("auth.skipAccountCreation") - if(document.querySelector("#help")) document.querySelector("#help").textContent = gls.get("help") + const gls = await GLS.init(); + + if (document.querySelector("#alreadyHaveAccount")) + document.querySelector("#alreadyHaveAccount").textContent = gls.get( + "auth.alreadyHaveAnAccount", + ); + if (document.querySelector("#howToRegisterOrg")) + document.querySelector("#howToRegisterOrg").textContent = gls.get( + "auth.howToRegOrganization", + ); + if (document.querySelector("#registerNewAccount")) + document.querySelector("#registerNewAccount").textContent = + gls.get("auth.registerNewAccount"); + if (document.querySelector("#skipAccountCreation")) + document.querySelector("#skipAccountCreation").textContent = gls.get( + "auth.skipAccountCreation", + ); + if (document.querySelector("#help")) + document.querySelector("#help").textContent = gls.get("help"); // transition between pages setTimeout(() => { - userFormWrapper.style.opacity = 1 - }, 0) + userFormWrapper.style.opacity = 1; + }, 0); - document.querySelectorAll("a[href]").forEach(link => { + document.querySelectorAll("a[href]").forEach((link) => { link.addEventListener("click", (e) => { - e.preventDefault() + e.preventDefault(); - userFormWrapper.style.opacity = 0 + userFormWrapper.style.opacity = 0; setTimeout(() => { - window.location = e.target.href - }, 200) - }) - }) - // + window.location = e.target.href; + }, 200); + }); + }); + // - inputs.forEach(i => { + inputs.forEach((i) => { if (i.type === "password") { function handleEye({ isVisible, eyeIcon }) { if (isVisible) { - i.type = "text" - eyeIcon.textContent = "visibility_off" + i.type = "text"; + eyeIcon.textContent = "visibility_off"; } else { - i.type = "password" - eyeIcon.textContent = "visibility" + i.type = "password"; + eyeIcon.textContent = "visibility"; } } - const wrapper = document.createElement("div") - let isVisible = false + const wrapper = document.createElement("div"); + let isVisible = false; - const eyeIcon = document.createElement("span") - eyeIcon.classList.add("material-symbols-rounded", "auth-visibility__change") + const eyeIcon = document.createElement("span"); + eyeIcon.classList.add("material-symbols-rounded", "auth-visibility__change"); - handleEye({ isVisible, eyeIcon }) + handleEye({ isVisible, eyeIcon }); eyeIcon.addEventListener("click", () => { - isVisible = !isVisible - handleEye({ isVisible, eyeIcon }) - }) + isVisible = !isVisible; + handleEye({ isVisible, eyeIcon }); + }); - wrapper.appendChild(eyeIcon) - i.parentElement.appendChild(wrapper) + wrapper.appendChild(eyeIcon); + i.parentElement.appendChild(wrapper); } - }) + }); // window.electron.onAuthMsg((data) => { - const content = data.content - const type = data.type + const content = data.content; + const type = data.type; if (type == "err") { - showErrBlock(content) + showErrBlock(content); } - }) + }); if (document.querySelector("#skipAccountCreation")) { document.querySelector("#skipAccountCreation").addEventListener("click", () => { - window.electron.setNonAccountMode(true) - window.electron.reload() - }) + window.electron.setNonAccountMode(true); + window.electron.reload(); + }); } -}) \ No newline at end of file +}); diff --git a/assets/js/auth/login.js b/assets/js/auth/login.js index cac58fc..67013d4 100644 --- a/assets/js/auth/login.js +++ b/assets/js/auth/login.js @@ -1,67 +1,65 @@ +import { GLS } from "../lib.js"; import { - submitBtn, - usernameInput, + disableButtons, emailInput, - passwordInput, errorBlock, - disableButtons, - unDisableButtons, - showErrBlock, getFormLabel, - initInputs -} from "./authRenderer.js" - -import { GLS } from "../lib.js" + initInputs, + passwordInput, + showErrBlock, + submitBtn, + unDisableButtons, + usernameInput, +} from "./authRenderer.js"; document.addEventListener("DOMContentLoaded", async () => { - const gls = await GLS.init() + const gls = await GLS.init(); + + initInputs(); - initInputs() + const params = new URLSearchParams(window.location.search); - const params = new URLSearchParams(window.location.search) + getFormLabel(emailInput).textContent = gls.get("auth.login.inputs.email"); + getFormLabel(passwordInput).textContent = gls.get("auth.login.inputs.password"); - getFormLabel(emailInput).textContent = gls.get("auth.login.inputs.email") - getFormLabel(passwordInput).textContent = gls.get("auth.login.inputs.password") - - submitBtn.textContent = gls.get("auth.login.inputs.submitBtn") + submitBtn.textContent = gls.get("auth.login.inputs.submitBtn"); - document.querySelector(".user-logo__title").textContent = gls.get("auth.login.title") - document.querySelector(".user-logo__desc").textContent = gls.get("auth.login.description") + document.querySelector(".user-logo__title").textContent = gls.get("auth.login.title"); + document.querySelector(".user-logo__desc").textContent = gls.get("auth.login.description"); - if(params.get("email") != null) { - emailInput.value = params.get("email") - emailInput.classList.add("focused") + if (params.get("email") != null) { + emailInput.value = params.get("email"); + emailInput.classList.add("focused"); } - if(params.get("password") != null) { - passwordInput.value = params.get("password") - passwordInput.classList.add("focused") + if (params.get("password") != null) { + passwordInput.value = params.get("password"); + passwordInput.classList.add("focused"); } window.electron.oncb("auth-msg", (data) => { - const type = data.type + const type = data.type; - if(type == "error") { - showErrBlock(data.content) + if (type == "error") { + showErrBlock(data.content); } - }) + }); submitBtn.addEventListener("click", async () => { - let email = emailInput.value - let password = passwordInput.value + const email = emailInput.value; + const password = passwordInput.value; - disableButtons() + disableButtons(); - let res = await window.electron.login(email, password) - console.log(res) + const res = await window.electron.login(email, password); + console.log(res); - if(res.success) { - errorBlock.classList.add("hidden") - await window.electron.reload() - } - else { - showErrBlock(res.result) + if (res.success) { + errorBlock.classList.add("hidden"); + await window.electron.reload(); + } else { + showErrBlock(res.result); } - unDisableButtons() - }) -}) \ No newline at end of file + unDisableButtons(); + }); +}); diff --git a/assets/js/auth/recovery.js b/assets/js/auth/recovery.js index 59787ae..b3d0c2c 100644 --- a/assets/js/auth/recovery.js +++ b/assets/js/auth/recovery.js @@ -1,161 +1,154 @@ +import { createNotify, GLS, secondsToMinutes } from "../lib.js"; import { - submitBtn, - usernameInput, - emailInput, - passwordInput, codeInput, - errorBlock, disableButtons, - unDisableButtons, - showErrBlock, + disableEl, + emailInput, + errorBlock, getFormLabel, - initInputs, - transition, - hideEl, + initInputs, + passwordInput, showEl, - disableEl, - unDisableEl -} from "./authRenderer.js" - -import { createNotify, GLS, secondsToMinutes } from "../lib.js" + showErrBlock, + submitBtn, + transition, + unDisableButtons, + unDisableEl, + usernameInput, +} from "./authRenderer.js"; -const submitBtnID = "recoverySubmitBtn" +const submitBtnId = "recoverySubmitBtn"; function renderVeryCodeStep({ email, gls, descEl }) { - showEl("code_field") + showEl("code_field"); - const submitCodeBtn = submitBtn.cloneNode() - submitCodeBtn.textContent = gls.get("auth.recovery.verifyCodeBtn") + const submitCodeBtn = submitBtn.cloneNode(); + submitCodeBtn.textContent = gls.get("auth.recovery.verifyCodeBtn"); - descEl.textContent = gls.get("auth.recovery.description_code") + descEl.textContent = gls.get("auth.recovery.description_code"); - document.querySelector(".user-form__inputs").appendChild(submitCodeBtn) + document.querySelector(".user-form__inputs").appendChild(submitCodeBtn); submitCodeBtn.addEventListener("click", async () => { - disableEl(submitBtnID) - const codeValue = codeInput.value.replaceAll(/\s/gm, "") + disableEl(submitBtnId); + const codeValue = codeInput.value.replaceAll(/\s/gm, ""); - const res = await window.electron.verifyRecoveryCode(email, codeValue) - - if(res.success) { + const res = await window.electron.verifyRecoveryCode(email, codeValue); + + if (res.success) { transition(() => { - unDisableEl(submitBtnID) - + unDisableEl(submitBtnId); + renderPasswordResetStep({ - email: email, - gls: gls, - descEl: descEl, + email, + gls, + descEl, verifyCodeBtn: submitCodeBtn, - codeInput: codeInput, + codeInput, minutes: secondsToMinutes(res.result.expiresIn), - token: res.result.token - }) - }) + token: res.result.token, + }); + }); + } else { + showErrBlock(res.result); } - else { - showErrBlock(res.result) - } - }) + }); - emailInput.parentElement.remove() - submitBtn.remove() + emailInput.parentElement.remove(); + submitBtn.remove(); } function renderPasswordResetStep({ email, gls, descEl, verifyCodeBtn, codeInput, minutes, token }) { - hideEl("code_field") - showEl("newpass_field") + hideEl("code_field"); + showEl("newpass_field"); - const resetPasswordBtn = verifyCodeBtn.cloneNode() - resetPasswordBtn.textContent = gls.get("auth.recovery.newPassBtn") + const resetPasswordBtn = verifyCodeBtn.cloneNode(); + resetPasswordBtn.textContent = gls.get("auth.recovery.newPassBtn"); - const newPasswordInput = document.querySelector("#newpass") - getFormLabel(newPasswordInput).textContent = gls.get("auth.recovery.inputs.newpass") + const newPasswordInput = document.querySelector("#newpass"); + getFormLabel(newPasswordInput).textContent = gls.get("auth.recovery.inputs.newpass"); - descEl.textContent = gls.get("auth.recovery.description_newpass", { minutes: minutes }) + descEl.textContent = gls.get("auth.recovery.description_newpass", { minutes }); - document.querySelector(".user-form__inputs").appendChild(resetPasswordBtn) + document.querySelector(".user-form__inputs").appendChild(resetPasswordBtn); resetPasswordBtn.addEventListener("click", async () => { - disableEl(submitBtnID) - const newPasswordValue = newPasswordInput.value + disableEl(submitBtnId); + const newPasswordValue = newPasswordInput.value; + + const res = await window.electron.resetPassword(token, newPasswordValue); - const res = await window.electron.resetPassword(token, newPasswordValue) - - if(res.success) { + if (res.success) { transition(() => { - unDisableEl(submitBtnID) + unDisableEl(submitBtnId); - const toLoginPageBtn = resetPasswordBtn.cloneNode() - toLoginPageBtn.textContent = gls.get("auth.recovery.toLoginPageBtn") - document.querySelector(".user-form__inputs").appendChild(toLoginPageBtn) + const toLoginPageBtn = resetPasswordBtn.cloneNode(); + toLoginPageBtn.textContent = gls.get("auth.recovery.toLoginPageBtn"); + document.querySelector(".user-form__inputs").appendChild(toLoginPageBtn); - descEl.textContent = gls.get("auth.recovery.description_newpass_success") + descEl.textContent = gls.get("auth.recovery.description_newpass_success"); toLoginPageBtn.addEventListener("click", () => { transition(() => { - window.location = "login.html" - }) - }) - - document.querySelector("#newpass_field").remove() - document.querySelector(".form-submit").remove() - }) - } - else { - showErrBlock(res.result) + window.location = "login.html"; + }); + }); + + document.querySelector("#newpass_field").remove(); + document.querySelector(".form-submit").remove(); + }); + } else { + showErrBlock(res.result); } - }) + }); - codeInput.parentElement.remove() - verifyCodeBtn.remove() + codeInput.parentElement.remove(); + verifyCodeBtn.remove(); } document.addEventListener("DOMContentLoaded", async () => { - const gls = await GLS.init() + const gls = await GLS.init(); - const descEl = document.querySelector(".user-logo__desc") - const titleEl = document.querySelector(".user-logo__title") + const descEl = document.querySelector(".user-logo__desc"); + const titleEl = document.querySelector(".user-logo__title"); - initInputs() + initInputs(); - getFormLabel(emailInput).textContent = gls.get("auth.recovery.inputs.email") - getFormLabel(codeInput).textContent = gls.get("auth.recovery.inputs.code") + getFormLabel(emailInput).textContent = gls.get("auth.recovery.inputs.email"); + getFormLabel(codeInput).textContent = gls.get("auth.recovery.inputs.code"); - submitBtn.textContent = gls.get("auth.recovery.submitBtn") + submitBtn.textContent = gls.get("auth.recovery.submitBtn"); - titleEl.textContent = gls.get("auth.recovery.title") - descEl.textContent = gls.get("auth.recovery.description") + titleEl.textContent = gls.get("auth.recovery.title"); + descEl.textContent = gls.get("auth.recovery.description"); submitBtn.addEventListener("click", async () => { - let email = emailInput.value + const email = emailInput.value; - disableEl(submitBtnID) + disableEl(submitBtnId); - const res = await window.electron.requestRecoveryCode(email) + const res = await window.electron.requestRecoveryCode(email); - if(res.success) { - errorBlock.classList.add("hidden") + if (res.success) { + errorBlock.classList.add("hidden"); - codeInput.parentElement.removeAttribute("disabled") - codeInput.removeAttribute("disabled") + codeInput.parentElement.removeAttribute("disabled"); + codeInput.removeAttribute("disabled"); - createNotify( - { - type: "success", - icon: "check", - title: gls.get("auth.recovery.successNotification.title"), - content: gls.get("auth.recovery.successNotification.description", { email: email }) - } - ) + createNotify({ + type: "success", + icon: "check", + title: gls.get("auth.recovery.successNotification.title"), + content: gls.get("auth.recovery.successNotification.description", { email }), + }); transition(() => { - unDisableEl(submitBtnID) - renderVeryCodeStep({ email: email, gls: gls, descEl: descEl }) - }) - } - else { - showErrBlock(res.result) + unDisableEl(submitBtnId); + renderVeryCodeStep({ email, gls, descEl }); + }); + } else { + showErrBlock(res.result); } - }) -}) \ No newline at end of file + }); +}); diff --git a/assets/js/auth/register.js b/assets/js/auth/register.js index 654d597..513cd57 100644 --- a/assets/js/auth/register.js +++ b/assets/js/auth/register.js @@ -1,62 +1,58 @@ +import { createNotify, GLS } from "../lib.js"; import { - submitBtn, - usernameInput, - emailInput, - passwordInput, confirmPassword, - errorBlock, disableButtons, - unDisableButtons, - showErrBlock, + emailInput, + errorBlock, getFormLabel, - initInputs -} from "./authRenderer.js" - -import { createNotify, GLS } from "../lib.js" + initInputs, + passwordInput, + showErrBlock, + submitBtn, + unDisableButtons, + usernameInput, +} from "./authRenderer.js"; document.addEventListener("DOMContentLoaded", async () => { - const gls = await GLS.init() + const gls = await GLS.init(); - initInputs() + initInputs(); - getFormLabel(username).textContent = gls.get("auth.register.inputs.username") - getFormLabel(email).textContent = gls.get("auth.register.inputs.email") - getFormLabel(password).textContent = gls.get("auth.register.inputs.password") - getFormLabel(confirmPassword).textContent = gls.get("auth.register.inputs.repeatPassword") - - submitBtn.textContent = gls.get("auth.register.inputs.submitBtn") + getFormLabel(username).textContent = gls.get("auth.register.inputs.username"); + getFormLabel(email).textContent = gls.get("auth.register.inputs.email"); + getFormLabel(password).textContent = gls.get("auth.register.inputs.password"); + getFormLabel(confirmPassword).textContent = gls.get("auth.register.inputs.repeatPassword"); - document.querySelector(".user-logo__title").textContent = gls.get("auth.register.title") - document.querySelector(".user-logo__desc").textContent = gls.get("auth.register.description") + submitBtn.textContent = gls.get("auth.register.inputs.submitBtn"); + + document.querySelector(".user-logo__title").textContent = gls.get("auth.register.title"); + document.querySelector(".user-logo__desc").textContent = gls.get("auth.register.description"); submitBtn.addEventListener("click", async () => { - let confirmPasswordInput = document.querySelector("#confirm_password") - - let username = usernameInput.value - let email = emailInput.value - let password = passwordInput.value - let confirmPassword = confirmPasswordInput.value - - disableButtons() - - let res = await window.electron.register(username, email, password, confirmPassword) - - if(res.success) { - createNotify( - { - type: "success", - icon: "check", - title: gls.get("auth.register.successNotification.title"), - content: gls.get("auth.register.successNotification.description") - } - ) - errorBlock.classList.add("hidden") - window.location.href = `login.html?email=${email}&password=${password}` - } - else { - showErrBlock(res.result) + const confirmPasswordInput = document.querySelector("#confirm_password"); + + const username = usernameInput.value; + const email = emailInput.value; + const password = passwordInput.value; + const confirmPassword = confirmPasswordInput.value; + + disableButtons(); + + const res = await window.electron.register(username, email, password, confirmPassword); + + if (res.success) { + createNotify({ + type: "success", + icon: "check", + title: gls.get("auth.register.successNotification.title"), + content: gls.get("auth.register.successNotification.description"), + }); + errorBlock.classList.add("hidden"); + window.location.href = `login.html?email=${email}&password=${password}`; + } else { + showErrBlock(res.result); } - unDisableButtons() - }) -}) \ No newline at end of file + unDisableButtons(); + }); +}); diff --git a/assets/js/bus.js b/assets/js/bus.js index acdea43..c3bd9b3 100644 --- a/assets/js/bus.js +++ b/assets/js/bus.js @@ -1,14 +1,20 @@ -export const bus = new EventTarget() +export const bus = new EventTarget(); export function sendEvent(name, data) { - bus.dispatchEvent(new CustomEvent(name, { - detail: data - })) + bus.dispatchEvent( + new CustomEvent(name, { + detail: data, + }), + ); } bus["onEditorChange"] = (cb) => { - bus.addEventListener("editor-language-changed", (e) => { cb(e) }) -} + bus.addEventListener("editor-language-changed", (e) => { + cb(e); + }); +}; bus["onEditorClicked"] = (cb) => { - bus.addEventListener("editor-clicked", (e) => { cb(e) }) -} \ No newline at end of file + bus.addEventListener("editor-clicked", (e) => { + cb(e); + }); +}; diff --git a/assets/js/codeContextMenu.js b/assets/js/codeContextMenu.js index 0a07aef..66018cd 100644 --- a/assets/js/codeContextMenu.js +++ b/assets/js/codeContextMenu.js @@ -1,5 +1,5 @@ -import { ContextMenu } from "./handlers/contextMenuHandler.js" -import { normalizePath, parseTwemojiString, copyText } from "./lib.js" +import { ContextMenu } from "./handlers/contextMenuHandler.js"; +import { copyText, normalizePath, parseTwemojiString } from "./lib.js"; let currentCodeContextMenu = null; let currentEditor = null; @@ -28,16 +28,20 @@ export function destroyCodeContextMenu() { export async function initCodeContextMenu(currentPath, pathContext, editor) { destroyCodeContextMenu(); - + const uniqueMenuId = "codeContextMenu_" + Math.random().toString(36).substr(2, 9); - const codeContextMenu = new ContextMenu(uniqueMenuId) + const codeContextMenu = new ContextMenu(uniqueMenuId); currentCodeContextMenu = codeContextMenu; currentEditor = editor; - codeContextMenu.bindOnEditor(editor, editor.dom) + codeContextMenu.bindOnEditor(editor, editor.dom); codeContextMenu.add({ - id: "cut", icon: "content_cut", content: "Cut line", shortcut: "Ctrl+X", func: () => { + id: "cut", + icon: "content_cut", + content: "Cut line", + shortcut: "Ctrl+X", + func: () => { const selected = editor.getSelectedText(); if (selected) { copyText(selected); @@ -47,69 +51,105 @@ export async function initCodeContextMenu(currentPath, pathContext, editor) { copyText(editor.getLineText(row)); editor.removeFullLines(row, row); } - } - }) + }, + }); codeContextMenu.add({ - id: "copy", icon: "content_copy", content: "Copy line", shortcut: "Ctrl+C", func: () => { + id: "copy", + icon: "content_copy", + content: "Copy line", + shortcut: "Ctrl+C", + func: () => { const selected = editor.getSelectedText(); if (selected) { copyText(selected); } else { copyText(editor.getLineText(editor.getCursorPosition().row)); } - } - }) + }, + }); codeContextMenu.add({ - id: "paste", icon: "content_paste", content: "Paste", shortcut: "Ctrl+V", func: async () => { + id: "paste", + icon: "content_paste", + content: "Paste", + shortcut: "Ctrl+V", + func: async () => { await editor.pasteBufferContent(); - } - }) - codeContextMenu.add({ type: "divider" }) + }, + }); + codeContextMenu.add({ type: "divider" }); codeContextMenu.add({ - id: "selectAll", icon: "select_all", content: "Select All", shortcut: "Ctrl+A", func: () => { + id: "selectAll", + icon: "select_all", + content: "Select All", + shortcut: "Ctrl+A", + func: () => { editor.selectAll(); - } - }) + }, + }); codeContextMenu.add({ - id: "duplicateLine", icon: "content_copy", content: "Duplicate Selection", shortcut: "Ctrl+Shift+D", func: () => { + id: "duplicateLine", + icon: "content_copy", + content: "Duplicate Selection", + shortcut: "Ctrl+Shift+D", + func: () => { editor.duplicateSelection(); - } - }) + }, + }); codeContextMenu.add({ - id: "deleteLine", icon: "delete", content: "Delete Line", shortcut: "Ctrl+D", func: () => { + id: "deleteLine", + icon: "delete", + content: "Delete Line", + shortcut: "Ctrl+D", + func: () => { editor.removeCurrentLine(); - } - }) - codeContextMenu.add({ type: "divider" }) + }, + }); + codeContextMenu.add({ type: "divider" }); codeContextMenu.add({ - id: "undo", icon: "undo", content: "Undo", shortcut: "Ctrl+Z", func: () => { + id: "undo", + icon: "undo", + content: "Undo", + shortcut: "Ctrl+Z", + func: () => { editor.undo(); - } - }) + }, + }); codeContextMenu.add({ - id: "redo", icon: "redo", content: "Redo", shortcut: "Ctrl+Shift+Z", func: () => { + id: "redo", + icon: "redo", + content: "Redo", + shortcut: "Ctrl+Shift+Z", + func: () => { editor.redo(); - } - }) - codeContextMenu.add({ type: "divider" }) + }, + }); + codeContextMenu.add({ type: "divider" }); codeContextMenu.add({ - id: "find", icon: "search", content: "Find", shortcut: "Ctrl+F", func: () => { + id: "find", + icon: "search", + content: "Find", + shortcut: "Ctrl+F", + func: () => { editor.openSearch(); - } - }) + }, + }); // codeContextMenu.add({ // id: "goToLine", icon: "tag", content: "Go to Line...", shortcut: "Ctrl+G", func: () => { // editor.commands.byName.gotoLine.exec(editor); // } // }) - codeContextMenu.add({ type: "divider" }) + codeContextMenu.add({ type: "divider" }); codeContextMenu.add({ - id: "toggleComment", icon: "code", content: "Toggle Comment", shortcut: "Ctrl+/", func: () => { + id: "toggleComment", + icon: "code", + content: "Toggle Comment", + shortcut: "Ctrl+/", + func: () => { editor.toggleCommentLine(); - } - }) -} \ No newline at end of file + }, + }); +} diff --git a/assets/js/contextParsers/cssParser.js b/assets/js/contextParsers/cssParser.js index 9ae6367..77e2c8f 100644 --- a/assets/js/contextParsers/cssParser.js +++ b/assets/js/contextParsers/cssParser.js @@ -16,7 +16,8 @@ export class CSSParser { if (line.includes("{")) { const selector = this._parseSelector(line); - if (selector) stack.push({ type: selector.type, label: selector.label, line: i + 1 }); + if (selector) + stack.push({ type: selector.type, label: selector.label, line: i + 1 }); } if (line.includes("}")) { @@ -63,7 +64,12 @@ export class CSSParser { } if (raw.match(/^\d+%$/) || raw === "from" || raw === "to") { - return { type: "keyframe-stop", label: raw, icon: "radio_button_checked", class: "method" }; + return { + type: "keyframe-stop", + label: raw, + icon: "radio_button_checked", + class: "method", + }; } if (raw.startsWith("#")) { @@ -72,7 +78,12 @@ export class CSSParser { if (raw.startsWith(".")) { const pseudo = this._extractPseudo(raw); - return { type: "class", label: raw, icon: pseudo ? "filter_alt" : "circle", class: "function" }; + return { + type: "class", + label: raw, + icon: pseudo ? "filter_alt" : "circle", + class: "function", + }; } if (raw.includes(":")) { @@ -84,7 +95,10 @@ export class CSSParser { } if (raw.includes(",")) { - const short = raw.split(",").map(s => s.trim()).join(", "); + const short = raw + .split(",") + .map((s) => s.trim()) + .join(", "); return { type: "selector", label: short, icon: "select_all", class: "function" }; } @@ -97,7 +111,14 @@ export class CSSParser { } _parseProperty(line) { - if (!line || line.includes("{") || line.includes("}") || line.startsWith("//") || line.startsWith("/*")) return null; + if ( + !line || + line.includes("{") || + line.includes("}") || + line.startsWith("//") || + line.startsWith("/*") + ) + return null; const match = line.match(/^([\w-]+)\s*:\s*(.+?);?$/); if (!match) return null; @@ -112,17 +133,83 @@ export class CSSParser { } _iconForProperty(prop) { - if (["color", "background", "background-color", "border-color", "outline-color"].includes(prop)) return "palette"; - if (["width", "height", "min-width", "max-width", "min-height", "max-height"].includes(prop)) return "straighten"; - if (["margin", "margin-top", "margin-right", "margin-bottom", "margin-left", - "padding", "padding-top", "padding-right", "padding-bottom", "padding-left"].includes(prop)) return "space_bar"; - if (["font", "font-size", "font-family", "font-weight", "font-style", "line-height", "letter-spacing"].includes(prop)) return "text_fields"; - if (["display", "flex", "flex-direction", "flex-wrap", "justify-content", "align-items", "align-self", "gap"].includes(prop)) return "grid_view"; - if (["position", "top", "right", "bottom", "left", "z-index"].includes(prop)) return "open_with"; + if ( + ["color", "background", "background-color", "border-color", "outline-color"].includes( + prop, + ) + ) + return "palette"; + if ( + ["width", "height", "min-width", "max-width", "min-height", "max-height"].includes(prop) + ) + return "straighten"; + if ( + [ + "margin", + "margin-top", + "margin-right", + "margin-bottom", + "margin-left", + "padding", + "padding-top", + "padding-right", + "padding-bottom", + "padding-left", + ].includes(prop) + ) + return "space_bar"; + if ( + [ + "font", + "font-size", + "font-family", + "font-weight", + "font-style", + "line-height", + "letter-spacing", + ].includes(prop) + ) + return "text_fields"; + if ( + [ + "display", + "flex", + "flex-direction", + "flex-wrap", + "justify-content", + "align-items", + "align-self", + "gap", + ].includes(prop) + ) + return "grid_view"; + if (["position", "top", "right", "bottom", "left", "z-index"].includes(prop)) + return "open_with"; if (["transition", "animation", "transform"].includes(prop)) return "animation"; - if (["border", "border-radius", "border-top", "border-right", "border-bottom", "border-left"].includes(prop)) return "border_style"; - if (["opacity", "visibility", "overflow", "pointer-events"].includes(prop)) return "visibility"; - if (["grid", "grid-template", "grid-template-columns", "grid-template-rows", "grid-column", "grid-row"].includes(prop)) return "grid_on"; + if ( + [ + "border", + "border-radius", + "border-top", + "border-right", + "border-bottom", + "border-left", + ].includes(prop) + ) + return "border_style"; + if (["opacity", "visibility", "overflow", "pointer-events"].includes(prop)) + return "visibility"; + if ( + [ + "grid", + "grid-template", + "grid-template-columns", + "grid-template-rows", + "grid-column", + "grid-row", + ].includes(prop) + ) + return "grid_on"; if (["cursor"].includes(prop)) return "mouse"; if (["content"].includes(prop)) return "notes"; if (["box-shadow", "text-shadow"].includes(prop)) return "shadow"; @@ -148,9 +235,9 @@ export class CSSParser { container.appendChild(el); if (i < chain.length - 1) { - const sep = renderSeparator() + const sep = renderSeparator(); container.appendChild(sep); } }); } -} \ No newline at end of file +} diff --git a/assets/js/contextParsers/globals.js b/assets/js/contextParsers/globals.js index aaa4339..e003bf3 100644 --- a/assets/js/contextParsers/globals.js +++ b/assets/js/contextParsers/globals.js @@ -1,7 +1,7 @@ export function renderSeparator() { const sep = document.createElement("span"); - sep.classList.add("material-symbols-rounded", "separator") + sep.classList.add("material-symbols-rounded", "separator"); sep.textContent = "keyboard_arrow_right"; - - return sep -} \ No newline at end of file + + return sep; +} diff --git a/assets/js/contextParsers/goParser.js b/assets/js/contextParsers/goParser.js index 61cc1a5..ab844cf 100644 --- a/assets/js/contextParsers/goParser.js +++ b/assets/js/contextParsers/goParser.js @@ -10,9 +10,7 @@ export class GoParser { traverse(node, row, chain) { if (!node || typeof node !== "object") return; - const inRange = node.loc && - row >= node.loc.start.line && - row <= node.loc.end.line; + const inRange = node.loc && row >= node.loc.start.line && row <= node.loc.end.line; if (inRange) { const item = this.nodeToChainItem(node, row); @@ -92,13 +90,13 @@ export class GoParser { icon: "data_object", label: node.aliasFor ? `${node.id?.name} = ${node.aliasFor}` - : (node.id?.name || "type"), + : node.id?.name || "type", class: "variable", }; case "ShortVarDeclaration": { const names = (node.names || []).join(", "); - const call = (node.values || []).find(v => v?.type === "CallExpression"); + const call = (node.values || []).find((v) => v?.type === "CallExpression"); const suffix = call ? ` := ${call.calleeName}` : " :="; return { icon: "data_object", @@ -108,8 +106,9 @@ export class GoParser { } case "VariableDeclaration": { - const names = (node.names || []) - .concat((node.declarations || []).flatMap(d => d.names || [])); + const names = (node.names || []).concat( + (node.declarations || []).flatMap((d) => d.names || []), + ); if (!names.length) return null; return { icon: "data_object", @@ -119,7 +118,7 @@ export class GoParser { } case "ConstDeclaration": { - const names = (node.declarations || []).flatMap(d => d.names || []); + const names = (node.declarations || []).flatMap((d) => d.names || []); if (!names.length) return null; return { icon: "pin", @@ -129,11 +128,13 @@ export class GoParser { } case "CallExpression": - return node.calleeName ? { - icon: "deployed_code", - label: node.calleeName, - class: "object", - } : null; + return node.calleeName + ? { + icon: "deployed_code", + label: node.calleeName, + class: "object", + } + : null; case "IfStatement": return { icon: "alt_route", label: "if", class: "object" }; @@ -142,10 +143,18 @@ export class GoParser { return { icon: "loop", label: "for", class: "object" }; case "GoStatement": - return { icon: "rocket", label: "go " + (node.call?.calleeName || ""), class: "function" }; + return { + icon: "rocket", + label: "go " + (node.call?.calleeName || ""), + class: "function", + }; case "DeferStatement": - return { icon: "hourglass_empty", label: "defer " + (node.call?.calleeName || ""), class: "function" }; + return { + icon: "hourglass_empty", + label: "defer " + (node.call?.calleeName || ""), + class: "function", + }; default: return null; @@ -156,7 +165,7 @@ export class GoParser { for (const key of ["body", "declarations", "methods", "fields", "values", "call"]) { const val = node[key]; if (Array.isArray(val)) { - val.forEach(v => this.traverse(v, row, chain)); + val.forEach((v) => this.traverse(v, row, chain)); } else if (val && typeof val === "object" && val.loc) { this.traverse(val, row, chain); } @@ -165,10 +174,12 @@ export class GoParser { formatParams(params) { if (!params || params.length === 0) return ""; - return params.map(p => { - const names = (p.names || []).join(", "); - return names ? `${names} ${p.paramType}` : p.paramType; - }).join(", "); + return params + .map((p) => { + const names = (p.names || []).join(", "); + return names ? `${names} ${p.paramType}` : p.paramType; + }) + .join(", "); } renderContext(chain) { @@ -194,4 +205,4 @@ export class GoParser { } }); } -} \ No newline at end of file +} diff --git a/assets/js/contextParsers/htmlParser.js b/assets/js/contextParsers/htmlParser.js index 1ed975b..9aebc5f 100644 --- a/assets/js/contextParsers/htmlParser.js +++ b/assets/js/contextParsers/htmlParser.js @@ -19,14 +19,17 @@ export class HTMLParser { const html = this.expandExpression(expr); - editor.session.replace({ - start: { - row: cursor.row, - column: cursor.column - expr.length + editor.session.replace( + { + start: { + row: cursor.row, + column: cursor.column - expr.length, + }, + end: cursor, }, - end: cursor - }, html); - } + html, + ); + }, }); } @@ -37,7 +40,7 @@ export class HTMLParser { expandExpression(expr) { const parts = expr.split(">"); - let result = ""; + const result = ""; let current = ""; for (let i = parts.length - 1; i >= 0; i--) { @@ -50,15 +53,15 @@ export class HTMLParser { return current; } - expandSingle(part, innerHTML = "") { + expandSingle(part, innerHtml = "") { const multiMatch = part.match(/(.*)\*(\d+)/); if (multiMatch) { const base = multiMatch[1]; - const count = parseInt(multiMatch[2]); + const count = Number.parseInt(multiMatch[2]); let result = ""; for (let i = 0; i < count; i++) { - result += this.expandSingle(base, innerHTML); + result += this.expandSingle(base, innerHtml); } return result; } @@ -70,10 +73,10 @@ export class HTMLParser { return `<${tag} type="${type}">`; } - return this.buildTag(part, innerHTML); + return this.buildTag(part, innerHtml); } - buildTag(expr, innerHTML = "") { + buildTag(expr, innerHtml = "") { let tag = "div"; let id = ""; let classes = []; @@ -85,13 +88,13 @@ export class HTMLParser { if (idMatch) id = idMatch[1]; const classMatches = [...expr.matchAll(/\.([a-zA-Z0-9-_]+)/g)]; - classes = classMatches.map(m => m[1]); + classes = classMatches.map((m) => m[1]); let attrs = ""; if (id) attrs += ` id="${id}"`; if (classes.length) attrs += ` class="${classes.join(" ")}"`; - return `<${tag}${attrs}>${innerHTML}`; + return `<${tag}${attrs}>${innerHtml}`; } showHTMLContext(editor, contextPanel) { @@ -114,7 +117,7 @@ export class HTMLParser { const node = { tag: inlineTag, id: attrs.id ? "#" + attrs.id : "", - cls: attrs.class ? "." + attrs.class.split(/\s+/).join(".") : "" + cls: attrs.class ? "." + attrs.class.split(/\s+/).join(".") : "", }; const last = stack[stack.length - 1]; @@ -131,8 +134,20 @@ export class HTMLParser { const nameRe = /^<\s*\/?\s*([a-zA-Z0-9:-]+)/; const selfClosing = new Set([ - "area","base","br","col","embed","hr","img","input","link","meta", - "param","source","track","wbr" + "area", + "base", + "br", + "col", + "embed", + "hr", + "img", + "input", + "link", + "meta", + "param", + "source", + "track", + "wbr", ]); const ignored = new Set(["script", "style"]); @@ -166,11 +181,10 @@ export class HTMLParser { const node = { tag, id: attrs.id ? "#" + attrs.id : "", - cls: attrs.class ? "." + attrs.class.split(/\s+/).join(".") : "" + cls: attrs.class ? "." + attrs.class.split(/\s+/).join(".") : "", }; - const isSelfClosing = - selfClosing.has(tag) || /\/\s*>$/.test(fullTag); + const isSelfClosing = selfClosing.has(tag) || /\/\s*>$/.test(fullTag); if (!isSelfClosing) { stack.push(node); @@ -220,7 +234,7 @@ export class HTMLParser { contextPanel.appendChild(el); if (i < stack.length - 1) { - const sep = renderSeparator() + const sep = renderSeparator(); contextPanel.appendChild(sep); } }); @@ -235,9 +249,9 @@ export class HTMLParser { li: "token", table: "table", input: "text_fields", - script: "code" + script: "code", }; return icons[tag] || "deployed_code"; } -} \ No newline at end of file +} diff --git a/assets/js/contextParsers/javascriptParser.js b/assets/js/contextParsers/javascriptParser.js index b0cd3f5..5294bee 100644 --- a/assets/js/contextParsers/javascriptParser.js +++ b/assets/js/contextParsers/javascriptParser.js @@ -82,14 +82,29 @@ export class JavascriptParser { case "ClassProperty": return { - icon: node.isPrivate || node.isProtected ? "lock" : node.isStatic ? "variable_add" : "data_object", + icon: + node.isPrivate || node.isProtected + ? "lock" + : node.isStatic + ? "variable_add" + : "data_object", label: `${node.isStatic ? "static " : ""}${node.id?.name || ""}`, class: "variable", }; case "ObjectMethod": { - const prefix = node.isGetter ? "get " : node.isSetter ? "set " : node.isAsync ? "async " : ""; - return { icon: "function", label: `${prefix}${node.id?.name || "anonymous"}()`, class: "method" }; + const prefix = node.isGetter + ? "get " + : node.isSetter + ? "set " + : node.isAsync + ? "async " + : ""; + return { + icon: "function", + label: `${prefix}${node.id?.name || "anonymous"}()`, + class: "method", + }; } case "Property": { @@ -145,13 +160,22 @@ export class JavascriptParser { case "ForOfStatement": return { icon: "loop", - label: node.type === "ForOfStatement" ? "for...of" : node.type === "ForInStatement" ? "for...in" : "for", + label: + node.type === "ForOfStatement" + ? "for...of" + : node.type === "ForInStatement" + ? "for...in" + : "for", class: "object", }; case "WhileStatement": case "DoWhileStatement": - return { icon: "loop", label: node.type === "DoWhileStatement" ? "do...while" : "while", class: "object" }; + return { + icon: "loop", + label: node.type === "DoWhileStatement" ? "do...while" : "while", + class: "object", + }; default: return null; @@ -170,14 +194,15 @@ export class JavascriptParser { namespaces.push(`* as ${specifier.name}`); } else if (specifier.type === "ImportSpecifier") { const imported = specifier.imported || specifier.name; - const alias = imported === specifier.name ? imported : `${imported} as ${specifier.name}`; + const alias = + imported === specifier.name ? imported : `${imported} as ${specifier.name}`; named.push(`${specifier.importKind === "type" ? "type " : ""}${alias}`); } } const source = JSON.stringify(node.source || ""); const attributes = (node.attributes || []) - .map(attribute => `${attribute.key}: ${JSON.stringify(attribute.value)}`) + .map((attribute) => `${attribute.key}: ${JSON.stringify(attribute.value)}`) .join(", "); const suffix = attributes ? ` with { ${attributes} }` : ""; const phase = node.phase ? ` ${node.phase}` : ""; @@ -195,7 +220,7 @@ export class JavascriptParser { for (const key of CHILD_KEYS) { const value = node[key]; if (Array.isArray(value)) { - value.forEach(child => this.traverse(child, row, chain)); + value.forEach((child) => this.traverse(child, row, chain)); } else if (value && typeof value === "object") { this.traverse(value, row, chain); } diff --git a/assets/js/contextParsers/jsonParser.js b/assets/js/contextParsers/jsonParser.js index 00b233b..5ead5dd 100644 --- a/assets/js/contextParsers/jsonParser.js +++ b/assets/js/contextParsers/jsonParser.js @@ -55,15 +55,15 @@ export class JSONParser { } } - path = stack.map(e => { - let icon = e.type === "object" ? "data_object" : "data_array"; - let className = e.type === "object" ? "object" : "array"; - let label = e.key ? e.key : ""; + path = stack.map((e) => { + const icon = e.type === "object" ? "data_object" : "data_array"; + const className = e.type === "object" ? "object" : "array"; + const label = e.key ? e.key : ""; return { icon, label, className }; }); - if (/\"[a-zA-Z0-9_]+\"/.test(lines[pos.row])) { - const match = lines[pos.row].match(/\"([a-zA-Z0-9_]+)\"/); + if (/"[a-zA-Z0-9_]+"/.test(lines[pos.row])) { + const match = lines[pos.row].match(/"([a-zA-Z0-9_]+)"/); if (match) path.push({ icon: "token", label: match[1], className: "object" }); } @@ -89,9 +89,9 @@ export class JSONParser { contextPanel.appendChild(el); if (i < chain.length - 1) { - const sep = renderSeparator() + const sep = renderSeparator(); contextPanel.appendChild(sep); } }); } -} \ No newline at end of file +} diff --git a/assets/js/contextParsers/typescriptParser.js b/assets/js/contextParsers/typescriptParser.js index daa0bec..7da64fc 100644 --- a/assets/js/contextParsers/typescriptParser.js +++ b/assets/js/contextParsers/typescriptParser.js @@ -4,7 +4,11 @@ export class TypescriptParser extends JavascriptParser { nodeToChainItem(node) { switch (node.type) { case "InterfaceDeclaration": - return { icon: "integration_instructions", label: node.id?.name || "", class: "class" }; + return { + icon: "integration_instructions", + label: node.id?.name || "", + class: "class", + }; case "InterfaceMethod": { const returnType = node.returnType ? `: ${node.returnType}` : ""; @@ -41,8 +45,12 @@ export class TypescriptParser extends JavascriptParser { return { icon: "tag", label: "[index]", class: "variable" }; case "ClassDeclaration": { - const extendsClause = node.extends?.length ? ` extends ${node.extends.join(", ")}` : ""; - const implementsClause = node.implements?.length ? ` implements ${node.implements.join(", ")}` : ""; + const extendsClause = node.extends?.length + ? ` extends ${node.extends.join(", ")}` + : ""; + const implementsClause = node.implements?.length + ? ` implements ${node.implements.join(", ")}` + : ""; return { icon: node.isAbstract ? "indeterminate_check_box" : "category", label: `${node.id?.name || "anonymous"}${extendsClause}${implementsClause}`, diff --git a/assets/js/coopHandlers/addBug.js b/assets/js/coopHandlers/addBug.js index 3e5dda0..fc42dc7 100644 --- a/assets/js/coopHandlers/addBug.js +++ b/assets/js/coopHandlers/addBug.js @@ -1,22 +1,27 @@ -import { getCurrentUserDataFromAPI } from "../user.js" - -export async function addBug({ bugModal, bugName, bugContent, bugPriority, bugPrivate, bugAssignTo }) { - bugPrivate = Number.isInteger(bugPrivate) ? bugPrivate : 0 - bugPriority = Number.isInteger(bugPriority) ? bugPriority : 0 - bugAssignTo = Number.isInteger(bugAssignTo) ? bugAssignTo : 0 - - const res = await window.electron.requestAddBug( - { - title: bugName, - description: bugContent, - priority: bugPriority, - private: bugPrivate, - assignTo: bugAssignTo - } - ) - - if(res.success) { - const msg = res.msg +import { getCurrentUserDataFromAPI } from "../user.js"; + +export async function addBug({ + bugModal, + bugName, + bugContent, + bugPriority, + bugPrivate, + bugAssignTo, +}) { + bugPrivate = Number.isInteger(bugPrivate) ? bugPrivate : 0; + bugPriority = Number.isInteger(bugPriority) ? bugPriority : 0; + bugAssignTo = Number.isInteger(bugAssignTo) ? bugAssignTo : 0; + + const res = await window.electron.requestAddBug({ + title: bugName, + description: bugContent, + priority: bugPriority, + private: bugPrivate, + assignTo: bugAssignTo, + }); + + if (res.success) { + const msg = res.msg; const object = { id: msg.id, @@ -25,31 +30,28 @@ export async function addBug({ bugModal, bugName, bugContent, bugPriority, bugPr desc: msg.description, isSelf: bugPrivate, org: false, - type: "created" - } + type: "created", + }; - if("name" in msg.assigned_to) { - object["assignedTo"] = msg.assigned_to + if ("name" in msg.assigned_to) { + object["assignedTo"] = msg.assigned_to; } - if("name" in msg.by) { - object["author"] = msg.by.name + if ("name" in msg.by) { + object["author"] = msg.by.name; } - addToBug(object) + addToBug(object); - bugModal.close() + bugModal.close(); if (document.querySelector(".sidebar-item#bugs")) { - document.querySelector(".sidebar-item#bugs").click() + document.querySelector(".sidebar-item#bugs").click(); } + } else { + createNotify({ + icon: "close", + title: "Error while adding bug on server", + content: res.msg, + }); } - else { - createNotify( - { - icon: "close", - title: "Error while adding bug on server", - content: res.msg - } - ) - } -} \ No newline at end of file +} diff --git a/assets/js/explorerTabsHandlers/bugs.js b/assets/js/explorerTabsHandlers/bugs.js index e101f28..0deff59 100644 --- a/assets/js/explorerTabsHandlers/bugs.js +++ b/assets/js/explorerTabsHandlers/bugs.js @@ -1,54 +1,52 @@ -import { setTabNameCounter, escapeHtml, createNotify, capitilize } from "../lib.js" -import { ELEMENTS_EMPTY_TEXT_COMPONENT } from "./components.js" -import { priorityClasses } from "../objects.js" -import { GLS } from "../lib.js" - -import { requestUser } from "../user.js" -import { appendBugs } from "../userHandlers/appendBugs.js" +import { capitilize, createNotify, escapeHtml, GLS, setTabNameCounter } from "../lib.js"; +import { priorityClasses } from "../objects.js"; +import { requestUser } from "../user.js"; +import { appendBugs } from "../userHandlers/appendBugs.js"; +import { ELEMENTS_EMPTY_TEXT_COMPONENT } from "./components.js"; const root = document.querySelector(`.explorer-elements[data-tab="bugs"] .elements`); const rootParent = document.querySelector(`.explorer-elements[data-tab="bugs"]`); async function refreshBugs() { - const user = await requestUser() + const user = await requestUser(); - const bugsCreated = user.bugsCreated - const bugsAssigned = user.bugsAssigned + const bugsCreated = user.bugsCreated; + const bugsAssigned = user.bugsAssigned; - console.log({ ...bugsCreated, ...bugsAssigned }) + console.log({ ...bugsCreated, ...bugsAssigned }); - appendBugs(bugsCreated, "created") - appendBugs(bugsAssigned, "assigned") + appendBugs(bugsCreated, "created"); + appendBugs(bugsAssigned, "assigned"); - console.log(bugsObject) + console.log(bugsObject); - handleBugsTab(bugsObject) + handleBugsTab(bugsObject); } document.querySelector("#refresh_bugs").addEventListener("click", (e) => { - refreshBugs() + refreshBugs(); - e.target.classList.add("disabled") + e.target.classList.add("disabled"); setTimeout(() => { - e.target.classList.remove("disabled") - }, 5000) -}) + e.target.classList.remove("disabled"); + }, 5000); +}); export async function handleBugsTab(bugsObject) { - console.log(bugsObject) - const gls = await GLS.initLocal() + console.log(bugsObject); + const gls = await GLS.initLocal(); - if (!root) return + if (!root) return; - root.innerHTML = "" + root.innerHTML = ""; - const bugs = Object.entries(bugsObject) - setTabNameCounter(bugs.length) + const bugs = Object.entries(bugsObject); + setTabNameCounter(bugs.length); if (bugs.length === 0) { - root.innerHTML = ELEMENTS_EMPTY_TEXT_COMPONENT - return + root.innerHTML = ELEMENTS_EMPTY_TEXT_COMPONENT; + return; } for (const [id, rec] of bugs) { @@ -62,55 +60,56 @@ export async function handleBugsTab(bugsObject) { organization, author, assignedTo, - type - } = rec + type, + } = rec; - let organizationsHTML = "" - let resolveBtnHTML = "" - let bugPriority = priorityClasses[priority] + let organizationsHtml = ""; + let resolveBtnHtml = ""; + const bugPriority = priorityClasses[priority]; if (organization) { - const splitted = organization.split(",").map(i => i.trim()) + const splitted = organization.split(",").map((i) => i.trim()); if (splitted.length > 1) { - organizationsHTML = ` + organizationsHtml = `

group ${escapeHtml(splitted[0])} ${gls.get("bug.orgMore", { count: splitted.length - 1 })} -

` - } - else { - organizationsHTML = ` +

`; + } else { + organizationsHtml = `

group ${escapeHtml(organization)} -

` +

`; } } if (!resolved) { - resolveBtnHTML = ` + resolveBtnHtml = ` ` + `; } - const columnElementClassList = [] + const columnElementClassList = []; + + if (self) columnElementClassList.push("own"); + if (resolved) columnElementClassList.push("done"); - if(self) columnElementClassList.push("own") - if(resolved) columnElementClassList.push("done") - - columnElementClassList.push(`${bugPriority.name}-priority`) - columnElementClassList.push(type) + columnElementClassList.push(`${bugPriority.name}-priority`); + columnElementClassList.push(type); - root.insertAdjacentHTML("beforeend", ` + root.insertAdjacentHTML( + "beforeend", + `

${escapeHtml(value)}

${escapeHtml(description)}

- ${organizationsHTML} + ${organizationsHtml}
person ${gls.get("bug.createdBy", { name: author })} @@ -119,12 +118,16 @@ export async function handleBugsTab(bugsObject) { commit ${gls.get("bug.assignedTo", { name: assignedTo.name })}
- ${self ? ` + ${ + self + ? `
visibility_off ${gls.get("bug.private")}
- ` : ""} + ` + : "" + }
${gls.get(`bug.priority.${bugPriority.name}`)}
@@ -133,108 +136,106 @@ export async function handleBugsTab(bugsObject) {
-

${/^\d{10}$/.test(String(time)) - ? new Date(time * 1000).format("H:i") - : escapeHtml(String(time || "Unknown"))}

+

${ + /^\d{10}$/.test(String(time)) + ? new Date(time * 1000).format("H:i") + : escapeHtml(String(time || "Unknown")) + }

- ${resolveBtnHTML} + ${resolveBtnHtml}
- `) + `, + ); } if (!root.dataset.listenerAttached) { root.addEventListener("click", async (e) => { - const orgEl = e.target.closest("[data-full-org]") + const orgEl = e.target.closest("[data-full-org]"); if (orgEl) { - const target = orgEl.querySelector("[data-org-target]") - const id = orgEl.closest(".column-element")?.dataset.id - const orgs = bugsObject[id]?.organization + const target = orgEl.querySelector("[data-org-target]"); + const id = orgEl.closest(".column-element")?.dataset.id; + const orgs = bugsObject[id]?.organization; if (target && orgs) { - target.textContent = orgs + target.textContent = orgs; } } - const doneBtn = e.target.closest("[data-done]") + const doneBtn = e.target.closest("[data-done]"); if (doneBtn) { - const item = doneBtn.closest(".column-element") - const id = item?.dataset.id - const bug = bugsObject[id] + const item = doneBtn.closest(".column-element"); + const id = item?.dataset.id; + const bug = bugsObject[id]; - if (!bug) return + if (!bug) return; - bug.resolved = 1 + bug.resolved = 1; - const res = await window.electron.requestMakeVerifyBug({ bugid: id }) + const res = await window.electron.requestMakeVerifyBug({ bugid: id }); - if(res.success) { - item.classList.add("done") - doneBtn.remove() - } - else { - createNotify( - { - icon: "close", - title: "Bug verify error", - content: res.msg - } - ) + if (res.success) { + item.classList.add("done"); + doneBtn.remove(); + } else { + createNotify({ + icon: "close", + title: "Bug verify error", + content: res.msg, + }); } } - }) + }); - root.dataset.listenerAttached = "true" + root.dataset.listenerAttached = "true"; } function showAllBugs() { - rootParent.querySelectorAll(".column-element").forEach(e => { - e.classList.remove("hidden") - }) + rootParent.querySelectorAll(".column-element").forEach((e) => { + e.classList.remove("hidden"); + }); } if (!rootParent.dataset.segmentListenersAttached) { - const tabs = document.querySelectorAll(".segmented-picker label") + const tabs = document.querySelectorAll(".segmented-picker label"); - tabs.forEach(t => { + tabs.forEach((t) => { t.addEventListener("click", (e) => { - let el = e.target - let ID - - if(el.tagName == "SPAN") { - el = el.parentElement - ID = el.getAttribute("for") - } - else { - el = e.target - ID = el.getAttribute("for") + let el = e.target; + let Id; + + if (el.tagName == "SPAN") { + el = el.parentElement; + Id = el.getAttribute("for"); + } else { + el = e.target; + Id = el.getAttribute("for"); } - if(ID != "bugs-all") { - document.querySelector(`#${ID}`)?.addEventListener("click", () => { - showAllBugs() + if (Id == "bugs-all") { + document.querySelector(`#${Id}`)?.addEventListener("click", () => { + showAllBugs(); + }); + } else { + document.querySelector(`#${Id}`)?.addEventListener("click", () => { + showAllBugs(); - const classToActive = el.getAttribute("classToActive") + const classToActive = el.getAttribute("classToActive"); - rootParent.querySelectorAll(".column-element").forEach(e => { + rootParent.querySelectorAll(".column-element").forEach((e) => { if (!e.classList.contains(classToActive)) { - e.classList.add("hidden") + e.classList.add("hidden"); } - }) - }) + }); + }); } - else { - document.querySelector(`#${ID}`)?.addEventListener("click", () => { - showAllBugs() - }) - } - }) - }) + }); + }); - rootParent.dataset.segmentListenersAttached = "true" + rootParent.dataset.segmentListenersAttached = "true"; } -} \ No newline at end of file +} diff --git a/assets/js/explorerTabsHandlers/components.js b/assets/js/explorerTabsHandlers/components.js index 7a77a10..06a5df2 100644 --- a/assets/js/explorerTabsHandlers/components.js +++ b/assets/js/explorerTabsHandlers/components.js @@ -1 +1 @@ -export const ELEMENTS_EMPTY_TEXT_COMPONENT = `

This section is currently empty

` \ No newline at end of file +export const ELEMENTS_EMPTY_TEXT_COMPONENT = `

This section is currently empty

`; diff --git a/assets/js/explorerTabsHandlers/history.js b/assets/js/explorerTabsHandlers/history.js index 71de21a..a74d171 100644 --- a/assets/js/explorerTabsHandlers/history.js +++ b/assets/js/explorerTabsHandlers/history.js @@ -1,31 +1,33 @@ -import { setTabNameCounter, escapeHtml } from "../lib.js" -import { ELEMENTS_EMPTY_TEXT_COMPONENT } from "./components.js" +import { escapeHtml, setTabNameCounter } from "../lib.js"; +import { ELEMENTS_EMPTY_TEXT_COMPONENT } from "./components.js"; const root = document.querySelector(`.explorer-elements[data-tab="history"] .elements`); const typeIcons = { - "created": 'add', - "file-open": 'file_open', - "tab-open": 'layers', - "bug-added": 'bug_report', - "file-saved": 'file_save' + created: "add", + "file-open": "file_open", + "tab-open": "layers", + "bug-added": "bug_report", + "file-saved": "file_save", }; export function handleHistoryTab(historyObject) { if (root) root.innerHTML = ""; - let historyKeys = Object.keys(historyObject) + const historyKeys = Object.keys(historyObject); setTabNameCounter(historyKeys.length); - Object.keys(historyObject).forEach(i => { + Object.keys(historyObject).forEach((i) => { const rec = historyObject[i]; - let value = rec.value - let desc = rec.description - let time = rec.time - let action = rec.action + const value = rec.value; + const desc = rec.description; + const time = rec.time; + const action = rec.action; - root?.insertAdjacentHTML("beforeend", ` + root?.insertAdjacentHTML( + "beforeend", + `
@@ -37,10 +39,11 @@ export function handleHistoryTab(historyObject) {

${time}

-
`); +
`, + ); }); - if(historyKeys.length == 0) { - root.innerHTML = ELEMENTS_EMPTY_TEXT_COMPONENT + if (historyKeys.length == 0) { + root.innerHTML = ELEMENTS_EMPTY_TEXT_COMPONENT; } -} \ No newline at end of file +} diff --git a/assets/js/explorerTree/handlers/bindFileClicksHandler.js b/assets/js/explorerTree/handlers/bindFileClicksHandler.js index 834d21d..1ef70df 100644 --- a/assets/js/explorerTree/handlers/bindFileClicksHandler.js +++ b/assets/js/explorerTree/handlers/bindFileClicksHandler.js @@ -1,10 +1,12 @@ -import { openTab, activateTab } from "../tabHandler.js"; +import { activateTab, openTab } from "../tabHandler.js"; export function bindFileClicks({ scopeEl, tabsByPath, recentlyClosed, pathContext, settings }) { - scopeEl.querySelectorAll(".file[data-path]").forEach(fileEl => { + scopeEl.querySelectorAll(".file[data-path]").forEach((fileEl) => { fileEl.addEventListener("click", async (ev) => { ev.stopPropagation(); - scopeEl.querySelectorAll(".file[data-path]").forEach(btn => btn.classList.remove("active")); + scopeEl + .querySelectorAll(".file[data-path]") + .forEach((btn) => btn.classList.remove("active")); fileEl.classList.add("active"); const filePath = fileEl.getAttribute("data-path"); @@ -17,10 +19,16 @@ export function bindFileClicks({ scopeEl, tabsByPath, recentlyClosed, pathContex } const cached = recentlyClosed.get(filePath); - const isBinaryImage = ["png", "jpg", "jpeg", "gif", "webp", "ico", "bmp"].includes(extension); - const content = cached ? cached.content : (isBinaryImage ? "" : await window.electron.readFileContent(filePath)); + const isBinaryImage = ["png", "jpg", "jpeg", "gif", "webp", "ico", "bmp"].includes( + extension, + ); + const content = cached + ? cached.content + : isBinaryImage + ? "" + : await window.electron.readFileContent(filePath); openTab(filePath, content, extension, name, pathContext, false, settings); }); }); -} \ No newline at end of file +} diff --git a/assets/js/explorerTree/handlers/contextMenuHandler.js b/assets/js/explorerTree/handlers/contextMenuHandler.js index 6d226d2..38856fa 100644 --- a/assets/js/explorerTree/handlers/contextMenuHandler.js +++ b/assets/js/explorerTree/handlers/contextMenuHandler.js @@ -1,8 +1,8 @@ import { BottomWindow } from "../../handlers/BottomWindowHandler.js"; import { Console } from "../../handlers/terminalHandler.js"; import { copyText, normalizePath } from "../../lib.js"; -import { closeTab, updateTabPath } from "../tabHandler.js"; import { renderNodes } from "../render.js"; +import { closeTab, updateTabPath } from "../tabHandler.js"; import { bindFileClicks } from "./bindFileClicksHandler.js"; let menuEl = null; @@ -26,7 +26,7 @@ function relativePath(targetPath, pathContext = {}) { const rootPath = normalizePath(pathContext.rootPath || ""); const normalized = normalizePath(targetPath); - if (!rootPath || !normalized.startsWith(rootPath)) { + if (!(rootPath && normalized.startsWith(rootPath))) { return normalized; } @@ -71,11 +71,11 @@ function addItem({ content, shortcut, disabled, action, icon }) { item.classList.add("context-menu__item"); if (disabled) item.classList.add("disabled"); - const iconHTML = icon ? `${icon}` : ""; + const iconHtml = icon ? `${icon}` : ""; item.innerHTML = `
- ${iconHTML} + ${iconHtml}
${content}
@@ -104,7 +104,7 @@ function showMenu(event, items) { const menu = ensureMenu(); menu.innerHTML = ""; - document.querySelectorAll(".context-menu").forEach(m => { + document.querySelectorAll(".context-menu").forEach((m) => { if (m !== menu) m.classList.add("hidden"); }); @@ -137,10 +137,15 @@ function showMenu(event, items) { async function refreshFolder(dirElement, context) { if (!dirElement) return; - const content = Array.from(dirElement.children).find(child => child.classList.contains("dir-content")); + const content = Array.from(dirElement.children).find((child) => + child.classList.contains("dir-content"), + ); if (!content) return; - const children = await window.electron.readDirTree(dirElement.dataset.path, { maxDepth: 0, ignoreRoot: context.pathContext?.rootPath }); + const children = await window.electron.readDirTree(dirElement.dataset.path, { + maxDepth: 0, + ignoreRoot: context.pathContext?.rootPath, + }); content.innerHTML = await renderNodes(children); dirElement.dataset.loaded = "true"; dirElement.classList.add("expanded"); @@ -149,28 +154,33 @@ async function refreshFolder(dirElement, context) { tabsByPath: context.tabsByPath, recentlyClosed: context.recentlyClosed, pathContext: context.pathContext, - settings: context.settings + settings: context.settings, }); } async function refreshRoot(context) { - if (!context.container || !context.pathContext?.rootPath) return; + if (!(context.container && context.pathContext?.rootPath)) return; - const children = await window.electron.readDirTree(context.pathContext.rootPath, { maxDepth: 0, ignoreRoot: context.pathContext.rootPath }); + const children = await window.electron.readDirTree(context.pathContext.rootPath, { + maxDepth: 0, + ignoreRoot: context.pathContext.rootPath, + }); context.container.innerHTML = await renderNodes(children); bindFileClicks({ scopeEl: context.container, tabsByPath: context.tabsByPath, recentlyClosed: context.recentlyClosed, pathContext: context.pathContext, - settings: context.settings + settings: context.settings, }); } function getCreateContainer(context, dirElement) { if (!dirElement) return context.container; - const content = Array.from(dirElement.children).find(child => child.classList.contains("dir-content")); + const content = Array.from(dirElement.children).find((child) => + child.classList.contains("dir-content"), + ); if (!content) return null; dirElement.classList.add("expanded"); @@ -191,7 +201,8 @@ function startCreateChild(type, dirPath, context, dirElement = null) { } const method = type === "file" ? "createFile" : "createFolder"; - const canCreateFileWithSave = type === "file" && typeof window.electron?.saveFile === "function"; + const canCreateFileWithSave = + type === "file" && typeof window.electron?.saveFile === "function"; if (typeof window.electron?.[method] !== "function" && !canCreateFileWithSave) { window.alert("File creation API is not loaded. Restart CodeMotion and try again."); @@ -216,12 +227,13 @@ function startCreateChild(type, dirPath, context, dirElement = null) { const cleanName = input.value.trim(); pending.remove(); - if (!save || !cleanName) return; + if (!(save && cleanName)) return; const targetPath = joinPath(dirPath, cleanName); - const result = typeof window.electron?.[method] === "function" - ? await window.electron[method](targetPath) - : await window.electron.saveFile(targetPath, ""); + const result = + typeof window.electron?.[method] === "function" + ? await window.electron[method](targetPath) + : await window.electron.saveFile(targetPath, ""); if (!result.success) { console.error(result.error); @@ -272,7 +284,9 @@ async function commitRename(targetPath, targetElement, newName) { targetElement.dataset.path = result.path; targetElement.dataset.loaded = "false"; targetElement.classList.remove("expanded"); - const content = Array.from(targetElement.children).find(child => child.classList.contains("dir-content")); + const content = Array.from(targetElement.children).find((child) => + child.classList.contains("dir-content"), + ); if (content) content.innerHTML = ""; } else { targetElement.dataset.path = result.path; @@ -308,7 +322,7 @@ function renameTarget(targetPath, targetElement) { span.textContent = oldName; input.replaceWith(span); - if (!save || !nextName || nextName === oldName) return; + if (!(save && nextName) || nextName === oldName) return; const newPath = await commitRename(targetPath, targetElement, nextName); if (newPath) { @@ -343,7 +357,10 @@ async function deleteTarget(targetPath, targetElement, context) { const normalizedTarget = normalizePath(targetPath); for (const path of [...context.tabsByPath.keys()]) { const normalizedPath = normalizePath(path); - if (normalizedPath === normalizedTarget || normalizedPath.startsWith(`${normalizedTarget}/`)) { + if ( + normalizedPath === normalizedTarget || + normalizedPath.startsWith(`${normalizedTarget}/`) + ) { closeTab(path); } } @@ -368,22 +385,59 @@ function fileItems(fileEl, context) { const targetDirPath = parentDirElement?.dataset.path || getDirname(filePath); return [ - { content: "New File...", icon: "note_add", action: () => startCreateChild("file", targetDirPath, context, parentDirElement) }, - { content: "New Folder...", icon: "create_new_folder", action: () => startCreateChild("folder", targetDirPath, context, parentDirElement) }, + { + content: "New File...", + icon: "note_add", + action: () => startCreateChild("file", targetDirPath, context, parentDirElement), + }, + { + content: "New Folder...", + icon: "create_new_folder", + action: () => startCreateChild("folder", targetDirPath, context, parentDirElement), + }, { type: "divider" }, { content: "Open With...", icon: "open_in_new", disabled: true }, - { content: "Reveal in File Explorer", icon: "folder_open", shortcut: "Shift+Alt+R", action: () => window.electron.revealInFileExplorer(filePath) }, - { content: "Open in Integrated Terminal", icon: "terminal", action: () => openTerminal(filePath, false) }, + { + content: "Reveal in File Explorer", + icon: "folder_open", + shortcut: "Shift+Alt+R", + action: () => window.electron.revealInFileExplorer(filePath), + }, + { + content: "Open in Integrated Terminal", + icon: "terminal", + action: () => openTerminal(filePath, false), + }, { type: "divider" }, { content: "Cut", icon: "content_cut", shortcut: "Ctrl+X", disabled: true }, { content: "Copy", icon: "content_copy", shortcut: "Ctrl+C", disabled: true }, { content: "Paste", icon: "content_paste", shortcut: "Ctrl+V", disabled: true }, { type: "divider" }, - { content: "Copy Path", icon: "content_copy", shortcut: "Shift+Alt+C", action: () => copyText(filePath) }, - { content: "Copy Relative Path", icon: "content_copy", shortcut: "Ctrl+K Ctrl+Shift+C", action: () => copyText(relativePath(filePath, context.pathContext)) }, + { + content: "Copy Path", + icon: "content_copy", + shortcut: "Shift+Alt+C", + action: () => copyText(filePath), + }, + { + content: "Copy Relative Path", + icon: "content_copy", + shortcut: "Ctrl+K Ctrl+Shift+C", + action: () => copyText(relativePath(filePath, context.pathContext)), + }, { type: "divider" }, - { content: "Rename...", icon: "edit", shortcut: "F2", action: () => renameTarget(filePath, fileEl) }, - { content: "Delete", icon: "delete", shortcut: "Delete", action: () => deleteTarget(filePath, fileEl, context) } + { + content: "Rename...", + icon: "edit", + shortcut: "F2", + action: () => renameTarget(filePath, fileEl), + }, + { + content: "Delete", + icon: "delete", + shortcut: "Delete", + action: () => deleteTarget(filePath, fileEl, context), + }, ]; } @@ -391,21 +445,58 @@ function folderItems(dirElement, context) { const dirPath = dirElement.dataset.path; return [ - { content: "New File...", icon: "note_add", action: () => startCreateChild("file", dirPath, context, dirElement) }, - { content: "New Folder...", icon: "create_new_folder", action: () => startCreateChild("folder", dirPath, context, dirElement) }, - { content: "Reveal in File Explorer", icon: "folder_open", shortcut: "Shift+Alt+R", action: () => window.electron.revealInFileExplorer(dirPath) }, - { content: "Open in Integrated Terminal", icon: "terminal", action: () => openTerminal(dirPath, true) }, + { + content: "New File...", + icon: "note_add", + action: () => startCreateChild("file", dirPath, context, dirElement), + }, + { + content: "New Folder...", + icon: "create_new_folder", + action: () => startCreateChild("folder", dirPath, context, dirElement), + }, + { + content: "Reveal in File Explorer", + icon: "folder_open", + shortcut: "Shift+Alt+R", + action: () => window.electron.revealInFileExplorer(dirPath), + }, + { + content: "Open in Integrated Terminal", + icon: "terminal", + action: () => openTerminal(dirPath, true), + }, { type: "divider" }, { content: "Find in Folder...", icon: "search", shortcut: "Shift+Alt+F", disabled: true }, { type: "divider" }, { content: "Cut", icon: "content_cut", shortcut: "Ctrl+X", disabled: true }, { content: "Copy", icon: "content_copy", shortcut: "Ctrl+C", disabled: true }, { type: "divider" }, - { content: "Copy Path", icon: "content_copy", shortcut: "Shift+Alt+C", action: () => copyText(dirPath) }, - { content: "Copy Relative Path", icon: "content_copy", shortcut: "Ctrl+K Ctrl+Shift+C", action: () => copyText(relativePath(dirPath, context.pathContext)) }, + { + content: "Copy Path", + icon: "content_copy", + shortcut: "Shift+Alt+C", + action: () => copyText(dirPath), + }, + { + content: "Copy Relative Path", + icon: "content_copy", + shortcut: "Ctrl+K Ctrl+Shift+C", + action: () => copyText(relativePath(dirPath, context.pathContext)), + }, { type: "divider" }, - { content: "Rename...", icon: "edit", shortcut: "F2", action: () => renameTarget(dirPath, dirElement) }, - { content: "Delete", icon: "delete", shortcut: "Delete", action: () => deleteTarget(dirPath, dirElement, context) } + { + content: "Rename...", + icon: "edit", + shortcut: "F2", + action: () => renameTarget(dirPath, dirElement), + }, + { + content: "Delete", + icon: "delete", + shortcut: "Delete", + action: () => deleteTarget(dirPath, dirElement, context), + }, ]; } @@ -413,13 +504,35 @@ function rootItems(context) { const rootPath = context.pathContext?.rootPath; return [ - { content: "New File...", icon: "note_add", action: () => startCreateChild("file", rootPath, context) }, - { content: "New Folder...", icon: "create_new_folder", action: () => startCreateChild("folder", rootPath, context) }, + { + content: "New File...", + icon: "note_add", + action: () => startCreateChild("file", rootPath, context), + }, + { + content: "New Folder...", + icon: "create_new_folder", + action: () => startCreateChild("folder", rootPath, context), + }, { type: "divider" }, - { content: "Reveal in File Explorer", icon: "folder_open", shortcut: "Shift+Alt+R", action: () => window.electron.revealInFileExplorer(rootPath) }, - { content: "Open in Integrated Terminal", icon: "terminal", action: () => openTerminal(rootPath, true) }, + { + content: "Reveal in File Explorer", + icon: "folder_open", + shortcut: "Shift+Alt+R", + action: () => window.electron.revealInFileExplorer(rootPath), + }, + { + content: "Open in Integrated Terminal", + icon: "terminal", + action: () => openTerminal(rootPath, true), + }, { type: "divider" }, - { content: "Copy Path", icon: "content_copy", shortcut: "Shift+Alt+C", action: () => copyText(rootPath) } + { + content: "Copy Path", + icon: "content_copy", + shortcut: "Shift+Alt+C", + action: () => copyText(rootPath), + }, ]; } @@ -436,7 +549,9 @@ export function initializeExplorerContextMenu(container, context) { let explorerFocused = false; - const onContainerMousedown = () => { explorerFocused = true; }; + const onContainerMousedown = () => { + explorerFocused = true; + }; const onOutsideMousedown = (e) => { if (!container.contains(e.target)) explorerFocused = false; }; @@ -446,19 +561,25 @@ export function initializeExplorerContextMenu(container, context) { if (!dirTitle) return; const dirEl = dirTitle.closest(".dir[data-path]"); if (!dirEl) return; - container.querySelectorAll(".file.active, .dir.active").forEach(el => el.classList.remove("active")); + container + .querySelectorAll(".file.active, .dir.active") + .forEach((el) => el.classList.remove("active")); dirEl.classList.add("active"); }; const onFileClick = (e) => { const fileEl = e.target.closest(".file[data-path]"); if (!fileEl) return; - container.querySelectorAll(".dir.active").forEach(el => el.classList.remove("active")); + container.querySelectorAll(".dir.active").forEach((el) => el.classList.remove("active")); }; const onKeydown = (e) => { if (!explorerFocused) return; - if (document.activeElement?.tagName === "INPUT" || document.activeElement?.tagName === "TEXTAREA") return; + if ( + document.activeElement?.tagName === "INPUT" || + document.activeElement?.tagName === "TEXTAREA" + ) + return; const activeEl = container.querySelector(".file.active[data-path]") || @@ -519,4 +640,4 @@ export function initializeExplorerContextMenu(container, context) { container.addEventListener("contextmenu", (event) => { event.preventDefault(); }); -} \ No newline at end of file +} diff --git a/assets/js/explorerTree/handlers/openFolderHandler.js b/assets/js/explorerTree/handlers/openFolderHandler.js index c56c4f3..e4fd28c 100644 --- a/assets/js/explorerTree/handlers/openFolderHandler.js +++ b/assets/js/explorerTree/handlers/openFolderHandler.js @@ -1,61 +1,64 @@ -import { closeAllTabs } from "../tabHandler.js"; +import { getFolderIconUrl } from "../../iconRegistry.js"; import { buildTreeHtml, renderNodes } from "../render.js"; +import { closeAllTabs, recentlyClosed, tabsByPath } from "../tabHandler.js"; import { bindFileClicks } from "./bindFileClicksHandler.js"; -import { tabsByPath, recentlyClosed } from "../tabHandler.js"; import { initializeExplorerContextMenu } from "./contextMenuHandler.js"; -import { getFolderIconUrl } from "../../iconRegistry.js"; async function setProjectDataUsedLanguages(path) { - const usedLanguages = await window.electron.getUsedLanguagesByPath(path) - const unknownPercentage = usedLanguages.unknown.percentage + const usedLanguages = await window.electron.getUsedLanguagesByPath(path); + const unknownPercentage = usedLanguages.unknown.percentage; - const graph = document.querySelector("#project_analys_graphic") - const graphItems = document.querySelector("#project_analys_graphic_items") + const graph = document.querySelector("#project_analys_graphic"); + const graphItems = document.querySelector("#project_analys_graphic_items"); - graph.innerHTML = "" - graphItems.innerHTML = "" + graph.innerHTML = ""; + graphItems.innerHTML = ""; - document.querySelector("#project_analys_files").textContent = usedLanguages.totalFiles - document.querySelector("#project_analys_path").textContent = path + document.querySelector("#project_analys_files").textContent = usedLanguages.totalFiles; + document.querySelector("#project_analys_path").textContent = path; function createGraphElement({ name, perc, color }) { - const languageGraphLine = document.createElement("div") - languageGraphLine.classList.add("column-element__linear-graphic__element") - languageGraphLine.style.width = perc + "%" - languageGraphLine.id = name - languageGraphLine.style.background = color + const languageGraphLine = document.createElement("div"); + languageGraphLine.classList.add("column-element__linear-graphic__element"); + languageGraphLine.style.width = perc + "%"; + languageGraphLine.id = name; + languageGraphLine.style.background = color; - graph.appendChild(languageGraphLine) + graph.appendChild(languageGraphLine); - const languageGraphItem = document.createElement("div") - languageGraphItem.classList.add("column-element-linear-graphic__items-item") + const languageGraphItem = document.createElement("div"); + languageGraphItem.classList.add("column-element-linear-graphic__items-item"); languageGraphItem.innerHTML = `
${name}
${perc}%
- ` + `; - graphItems.appendChild(languageGraphItem) + graphItems.appendChild(languageGraphItem); } - usedLanguages.languages.forEach(key => { - const languageName = key.name - const languagePercentage = key.percentage - const languageColor = key.color - - if(languagePercentage != 0) { - createGraphElement({ name: languageName, perc: languagePercentage, color: languageColor }) + usedLanguages.languages.forEach((key) => { + const languageName = key.name; + const languagePercentage = key.percentage; + const languageColor = key.color; + + if (languagePercentage != 0) { + createGraphElement({ + name: languageName, + perc: languagePercentage, + color: languageColor, + }); } - }) + }); - createGraphElement({ name: "Unknown", perc: unknownPercentage, color: "#4747478f" }) + createGraphElement({ name: "Unknown", perc: unknownPercentage, color: "#4747478f" }); } export async function openFolder({ pathRoot, filesPanel, addToHistory, pathContext, settings }) { - setProjectDataUsedLanguages(pathRoot) + setProjectDataUsedLanguages(pathRoot); closeAllTabs(); - + if (!filesPanel) { console.warn("Files panel not found"); return; @@ -64,47 +67,43 @@ export async function openFolder({ pathRoot, filesPanel, addToHistory, pathConte try { filesPanel.innerHTML = await buildTreeHtml(pathRoot); - updatePathContext( - { - pathRoot: pathRoot, - pathContext: pathContext - } - ); + updatePathContext({ + pathRoot, + pathContext, + }); updateTabName(pathContext); - bindFileClicks( - { - scopeEl: filesPanel, - tabsByPath: tabsByPath, - recentlyClosed: recentlyClosed, - pathContext: pathContext, - settings: settings - } - ); + bindFileClicks({ + scopeEl: filesPanel, + tabsByPath, + recentlyClosed, + pathContext, + settings, + }); - addToHistory( - { - actionType: "created", - value: "Project created", - desc: `Project in ${pathRoot} created. Now you can edit and create files` - } - ); + addToHistory({ + actionType: "created", + value: "Project created", + desc: `Project in ${pathRoot} created. Now you can edit and create files`, + }); - window.electron.setSettings({ app: { lastFolder: pathRoot } }) + window.electron.setSettings({ app: { lastFolder: pathRoot } }); initializeFolderToggle(filesPanel, { pathContext, settings }); - initializeExplorerContextMenu(filesPanel, { tabsByPath, recentlyClosed, pathContext, settings }); - + initializeExplorerContextMenu(filesPanel, { + tabsByPath, + recentlyClosed, + pathContext, + settings, + }); } catch (error) { console.error("Error opening folder:", error); - addToHistory( - { - actionType: "error", - value: "Failed to open project", - desc: error.message - } - ); + addToHistory({ + actionType: "error", + value: "Failed to open project", + desc: error.message, + }); } } @@ -134,7 +133,7 @@ export function initializeFolderToggle(container, context = {}) { event.stopPropagation(); const dirElement = dirTitle.closest(".dir"); - + if (!dirElement) return; const isExpanding = !dirElement.classList.contains("expanded"); @@ -146,29 +145,36 @@ export function initializeFolderToggle(container, context = {}) { folderImg.src = getFolderIconUrl(folderName, isExpanding); } - if (!isExpanding || dirElement.dataset.loaded !== "false" || dirElement.dataset.loading === "true") { + if ( + !isExpanding || + dirElement.dataset.loaded !== "false" || + dirElement.dataset.loading === "true" + ) { return; } dirElement.dataset.loading = "true"; - const content = Array.from(dirElement.children).find(child => child.classList.contains("dir-content")); + const content = Array.from(dirElement.children).find((child) => + child.classList.contains("dir-content"), + ); try { if (!content) return; - const children = await window.electron.readDirTree(dirElement.dataset.path, { maxDepth: 0, ignoreRoot: context.pathContext?.rootPath }); + const children = await window.electron.readDirTree(dirElement.dataset.path, { + maxDepth: 0, + ignoreRoot: context.pathContext?.rootPath, + }); content.innerHTML = await renderNodes(children); dirElement.dataset.loaded = "true"; - bindFileClicks( - { - scopeEl: content, - tabsByPath: tabsByPath, - recentlyClosed: recentlyClosed, - pathContext: context.pathContext, - settings: context.settings - } - ); + bindFileClicks({ + scopeEl: content, + tabsByPath, + recentlyClosed, + pathContext: context.pathContext, + settings: context.settings, + }); } catch (error) { console.error("Error loading folder:", error); } finally { @@ -189,7 +195,7 @@ function initializeFolderToggleLegible(container) { const folderIcon = event.target.closest(".folder-icon"); const fileName = event.target.closest(".dir-title .file"); - if (!folderIcon && !fileName) return; + if (!(folderIcon || fileName)) return; event.stopPropagation(); @@ -201,4 +207,4 @@ function initializeFolderToggleLegible(container) { container._toggleHandler = toggleHandler; container.addEventListener("click", toggleHandler); -} \ No newline at end of file +} diff --git a/assets/js/explorerTree/helpers/setEditorContext.js b/assets/js/explorerTree/helpers/setEditorContext.js index ee4b8ab..25e4844 100644 --- a/assets/js/explorerTree/helpers/setEditorContext.js +++ b/assets/js/explorerTree/helpers/setEditorContext.js @@ -1,26 +1,25 @@ -import { JavascriptParser } from "../../contextParsers/javascriptParser.js" -import { TypescriptParser } from "../../contextParsers/typescriptParser.js" -import { JSONParser } from "../../contextParsers/jsonParser.js" -import { HTMLParser } from "../../contextParsers/htmlParser.js" -import { CSSParser } from "../../contextParsers/cssParser.js" +import { CSSParser } from "../../contextParsers/cssParser.js"; +import { GoParser } from "../../contextParsers/goParser.js"; +import { HTMLParser } from "../../contextParsers/htmlParser.js"; +import { JavascriptParser } from "../../contextParsers/javascriptParser.js"; +import { JSONParser } from "../../contextParsers/jsonParser.js"; +import { TypescriptParser } from "../../contextParsers/typescriptParser.js"; +import { addRuntimeError, GLS } from "../../lib.js"; -import { addRuntimeError, GLS } from "../../lib.js" -import { GoParser } from "../../contextParsers/goParser.js" - -let diagnosticTimer = null -let generation = 0 +let diagnosticTimer = null; +let generation = 0; const SEVERITY_MAP = { Warning: "warning", Suggestion: "info", Error: "error", -} +}; function getOxcLanguage(filePath, fallback) { - const path = String(filePath || "").toLowerCase() - if (path.endsWith(".d.ts")) return "dts" + const path = String(filePath || "").toLowerCase(); + if (path.endsWith(".d.ts")) return "dts"; - const extension = path.match(/\.([^.\\/]+)$/)?.[1] + const extension = path.match(/\.([^.\\/]+)$/)?.[1]; const languageByExtension = { js: "js", mjs: "js", @@ -31,117 +30,119 @@ function getOxcLanguage(filePath, fallback) { mts: "ts", cts: "ts", tsx: "tsx", - } + }; - return languageByExtension[extension] || fallback + return languageByExtension[extension] || fallback; } function showDiagnostics(diagnostics, { editor, path }) { - const docLength = editor.getValue().length + const docLength = editor.getValue().length; - const list = diagnostics.map(item => { - const from = clamp(item.from, docLength) - const to = clamp(item.to, docLength, from) + const list = diagnostics.map((item) => { + const from = clamp(item.from, docLength); + const to = clamp(item.to, docLength, from); return { from, to, severity: SEVERITY_MAP[item.category] || "error", message: item.message, - } - }) + }; + }); - editor.setDiagnostics(list) + editor.setDiagnostics(list); - diagnostics.forEach(item => { + diagnostics.forEach((item) => { addRuntimeError({ msg: item.message, line: Math.max(1, Number(item.line) || 1), col: Math.max(0, Number(item.col) || 0), time: Math.floor(Date.now() / 1000), - }) - }) + }); + }); } function clamp(value, max, min = 0) { - return Math.min(Math.max(value, min), max) + return Math.min(Math.max(value, min), max); } -export async function setEditorContext(properties = {}, { editor, language, updateEditorData, path, settings }) { - const gls = GLS.initLocal() - const isErrorsUpdate = properties.errorsUpdate !== false +export async function setEditorContext( + properties = {}, + { editor, language, updateEditorData, path, settings }, +) { + const gls = GLS.initLocal(); + const isErrorsUpdate = properties.errorsUpdate !== false; - clearTimeout(diagnosticTimer) - const currentGen = ++generation + clearTimeout(diagnosticTimer); + const currentGen = ++generation; const setScriptContext = async (isTypeScript) => { - const oxcLanguage = getOxcLanguage(path, isTypeScript ? "ts" : "js") + const oxcLanguage = getOxcLanguage(path, isTypeScript ? "ts" : "js"); const getDiagnostics = isTypeScript ? window.electron.typescriptDiagnostic - : window.electron.javascriptDiagnostic - const getAst = isTypeScript - ? window.electron.typescriptAST - : window.electron.javascriptAST - const parser = isTypeScript ? new TypescriptParser() : new JavascriptParser() + : window.electron.javascriptDiagnostic; + const getAst = isTypeScript ? window.electron.typescriptAST : window.electron.javascriptAST; + const parser = isTypeScript ? new TypescriptParser() : new JavascriptParser(); diagnosticTimer = setTimeout(async () => { - const diagnostics = await getDiagnostics(editor.getValue(), oxcLanguage) + const diagnostics = await getDiagnostics(editor.getValue(), oxcLanguage); - if (currentGen !== generation || !isErrorsUpdate) return - showDiagnostics(diagnostics, { editor, path }) - }, 500) + if (currentGen !== generation || !isErrorsUpdate) return; + showDiagnostics(diagnostics, { editor, path }); + }, 500); - const ast = await getAst(editor.getValue(), oxcLanguage) - if (currentGen !== generation) return + const ast = await getAst(editor.getValue(), oxcLanguage); + if (currentGen !== generation) return; - const row = editor.getCursorPosition().row + 1 - parser.renderContext(parser.getContextChain(ast, row)) - } + const row = editor.getCursorPosition().row + 1; + parser.renderContext(parser.getContextChain(ast, row)); + }; const contextMap = { javascript: () => setScriptContext(false), jsx: () => setScriptContext(false), typescript: () => setScriptContext(true), json: () => { - const jsonParser = new JSONParser() - jsonParser.showJSONContext(editor, document.querySelector(".code-structure")) + const jsonParser = new JSONParser(); + jsonParser.showJSONContext(editor, document.querySelector(".code-structure")); }, html: () => { - const htmlParser = new HTMLParser() - htmlParser.showHTMLContext(editor, document.querySelector(".code-structure")) + const htmlParser = new HTMLParser(); + htmlParser.showHTMLContext(editor, document.querySelector(".code-structure")); }, css: () => { - const cssParser = new CSSParser() - const row = editor.getCursorPosition().row + 1 + const cssParser = new CSSParser(); + const row = editor.getCursorPosition().row + 1; - const chain = cssParser.getContextChain(editor.getValue(), row) - cssParser.renderContext(chain) + const chain = cssParser.getContextChain(editor.getValue(), row); + cssParser.renderContext(chain); }, golang: async () => { - const goParser = new GoParser() - const ast = await window.electron.golangAST(editor.getValue()) - const row = editor.getCursorPosition().row + 1 - - const chain = goParser.getContextChain(ast, row) - goParser.renderContext(chain) - } - } + const goParser = new GoParser(); + const ast = await window.electron.golangAST(editor.getValue()); + const row = editor.getCursorPosition().row + 1; - if ("editor" in settings) { - if ("goContextParser" in settings.editor && settings.editor.goContextParser == false) { - delete contextMap["golang"] - } + const chain = goParser.getContextChain(ast, row); + goParser.renderContext(chain); + }, + }; + + if ( + "editor" in settings && + "goContextParser" in settings.editor && + settings.editor.goContextParser == false + ) { + delete contextMap["golang"]; } - updateEditorData() + updateEditorData(); if (language.mode in contextMap) { - contextMap[language.mode]() - } - else { - const codeStructure = document.querySelector(".code-structure") + contextMap[language.mode](); + } else { + const codeStructure = document.querySelector(".code-structure"); if (codeStructure) { - codeStructure.textContent = gls.get("editor.nocontextFor", { name: language.name }) + codeStructure.textContent = gls.get("editor.nocontextFor", { name: language.name }); } } -} \ No newline at end of file +} diff --git a/assets/js/explorerTree/render.js b/assets/js/explorerTree/render.js index ca62c84..e17b31a 100644 --- a/assets/js/explorerTree/render.js +++ b/assets/js/explorerTree/render.js @@ -1,5 +1,5 @@ -import { escapeHtml } from "../lib.js"; import { getFileIconUrl, getFolderIconUrl } from "../iconRegistry.js"; +import { escapeHtml } from "../lib.js"; function createFileElement(node, ext, fileIcon) { return ` @@ -34,7 +34,7 @@ function normalizeNode(node) { return { ...node, escapedName: escapeHtml(node.name), - escapedPath: escapeHtml(node.path) + escapedPath: escapeHtml(node.path), }; } @@ -44,7 +44,10 @@ function normalizeNode(node) { * @returns {Promise} Rendered HTML string of the file tree. */ export async function buildTreeHtml(rootPath) { - const nodes = await window.electron.readDirTree(rootPath, { maxDepth: 0, ignoreRoot: rootPath }); + const nodes = await window.electron.readDirTree(rootPath, { + maxDepth: 0, + ignoreRoot: rootPath, + }); return renderNodes(nodes); } @@ -100,4 +103,4 @@ export async function renderNodes(nodes) { } return htmlParts.join(""); -} \ No newline at end of file +} diff --git a/assets/js/explorerTree/tabHandler.js b/assets/js/explorerTree/tabHandler.js index 1e7101b..be4516b 100644 --- a/assets/js/explorerTree/tabHandler.js +++ b/assets/js/explorerTree/tabHandler.js @@ -1,197 +1,186 @@ +import { disableSave, enableSave } from "../../../app/renderer.js"; +import { bus, sendEvent } from "../bus.js"; +import { destroyCodeContextMenu, initCodeContextMenu } from "../codeContextMenu.js"; +import { electronAPI } from "../global.js"; +import { BottomWindow, closeAllWindows } from "../handlers/BottomWindowHandler.js"; import { - toBase64, - getCodeByName, + disableErrors, + enableErrors, + setColumn, + setCurrentLanguage, + setErrors, + setLine, + setSymbols, + setTabSize, + toggleCodeFooter, +} from "../handlers/bottomTabHandler.js"; +import { bindImageZoomHandlers } from "../handlers/imageZoomHandler.js"; +import { minifyCSS, minifyJS } from "../handlers/minifyHandlers.js"; +import { Console } from "../handlers/terminalHandler.js"; +import { getFileIconUrl } from "../iconRegistry.js"; +import { + CodeTemplates, capitilize, - escapeHtml, - runCode, - runSandbox, clearRuntimeErrors, - isFloat, - isStringifiedObject, createNotify, - getTheme, - SideBarIconManager, - Languages, - showCodeWindowVisuals, - Filenames, - idify, - CodeTemplates, dedent, + EditorAdapter, + escapeHtml, + Filenames, GLS, + getCodeByName, + getTheme, + idify, + isFloat, + isStringifiedObject, + Languages, + runCode, + runSandbox, + SideBarIconManager, setAppTitle, setTabName, - EditorAdapter -} from "../lib.js" -import { BottomWindow, closeAllWindows } from "../handlers/BottomWindowHandler.js" -import { bindImageZoomHandlers } from "../handlers/imageZoomHandler.js" -import { Setting } from "../settings.js" -import { getFileIconUrl } from "../iconRegistry.js" -import { - setCurrentLanguage, - setColumn, - setTabSize, - setSymbols, - setErrors, - toggleCodeFooter, - setLine, - enableErrors, - disableErrors -} from "../handlers/bottomTabHandler.js" -import { Console } from "../handlers/terminalHandler.js" -import { minifyJS, minifyCSS } from "../handlers/minifyHandlers.js" -import { initCodeContextMenu, destroyCodeContextMenu } from "../codeContextMenu.js" -import { enableSave, disableSave } from "../../../app/renderer.js" -import { bus, sendEvent } from "../bus.js" - -import { renderPyMsgSuccess, renderPyMsgErr } from "../terminalRenderer/PyRuntimeHandler.js" - -import { triggerEditorChanged, triggerEditorClicked } from "./triggers.js" -import { TopWindowList, destroyAllTopWindowLists } from "../topWindowHandler/topWindowList.js" -import { setEditorContext } from "./helpers/setEditorContext.js" -import { Modal } from "../modalsHandler/engine.js" -import { electronAPI } from "../global.js" -import { closeConfirmModal } from "../modals/closeConfirm.js" + showCodeWindowVisuals, + toBase64, +} from "../lib.js"; +import { closeConfirmModal } from "../modals/closeConfirm.js"; +import { Modal } from "../modalsHandler/engine.js"; +import { Setting } from "../settings.js"; +import { renderPyMsgErr, renderPyMsgSuccess } from "../terminalRenderer/PyRuntimeHandler.js"; +import { destroyAllTopWindowLists, TopWindowList } from "../topWindowHandler/topWindowList.js"; +import { setEditorContext } from "./helpers/setEditorContext.js"; +import { triggerEditorChanged, triggerEditorClicked } from "./triggers.js"; export const recentlyClosed = new Map(); export const tabsByPath = new Map(); -export let currentContent = "" +export let currentContent = ""; export let currentPath = null; export const tabsBar = document.querySelector(".code-tabs"); export const editorWrapper = document.querySelector(".code-inner__wrapper"); export const startScreen = document.querySelector("#main-code"); -const codeToolsWrapper = document.querySelector("#code-tools") -const templateChooseCodeTool = document.querySelector("#code-tools_template-choose") +const codeToolsWrapper = document.querySelector("#code-tools"); +const templateChooseCodeTool = document.querySelector("#code-tools_template-choose"); async function bindCodeTools({ editor, extension }) { - const gls = GLS.initLocal() + const gls = GLS.initLocal(); const placeholderRegex = /%\{\{\s*([a-zA-Z0-9_-]+)\s*\}\}/gm; - const oldInstance = TopWindowList.get("chooseTemplate") + const oldInstance = TopWindowList.get("chooseTemplate"); function extractPlaceholders(str) { - return [...str.matchAll(placeholderRegex)].map(match => match[1].trim()); + return [...str.matchAll(placeholderRegex)].map((match) => match[1].trim()); } function clearPlaceholders(str) { - return str.replaceAll(placeholderRegex, "") + return str.replaceAll(placeholderRegex, ""); } function lgls(key, props = {}) { - return gls.get(`modals.templates.${key}`, props) + return gls.get(`modals.templates.${key}`, props); } if (oldInstance != undefined) { - oldInstance.destroy() + oldInstance.destroy(); } - Modal.destroy("templatePlaceholders") + Modal.destroy("templatePlaceholders"); - const list = CodeTemplates.list() + const list = CodeTemplates.list(); if (extension in list) { - templateChooseCodeTool.classList.remove("disabled") + templateChooseCodeTool.classList.remove("disabled"); - const item = list[extension] - const currentTemplates = Object.keys(item).map(id => ({ + const item = list[extension]; + const currentTemplates = Object.keys(item).map((id) => ({ name: item[id].name, - id: id - })) + id, + })); - const chooseTemplateList = new TopWindowList("chooseTemplate", currentTemplates) - chooseTemplateList.bind(templateChooseCodeTool) + const chooseTemplateList = new TopWindowList("chooseTemplate", currentTemplates); + chooseTemplateList.bind(templateChooseCodeTool); chooseTemplateList.on("click", (data) => { - const id = parseInt(data.id) - let templateContent = dedent(item[id].content) - const placeholders = extractPlaceholders(templateContent) + const id = Number.parseInt(data.id); + let templateContent = dedent(item[id].content); + const placeholders = extractPlaceholders(templateContent); + + if (placeholders.length > 0) { + const modalInputs = []; + + placeholders.forEach((p) => { + modalInputs.push({ + type: "input", + placeholder: capitilize(p).replaceAll(/[-_]/g, " "), + id: p, + }); + }); - if(placeholders.length > 0) { - const modalInputs = [] + const modal = Modal.create({ + id: "templatePlaceholders", + name: "templatePlaceholders", + modalClassList: ["window"], + size: "mini", + title: lgls("placeholders.title"), - placeholders.forEach(p => { - modalInputs.push( + content: [ { - type: "input", - placeholder: capitilize(p).replaceAll(/[-_]/g, " "), - id: p - } - ) - }) - - const modal = Modal.create( - { - id: "templatePlaceholders", - name: "templatePlaceholders", - modalClassList: ["window"], - size: "mini", - title: lgls("placeholders.title"), - - content: [ - { - type: "row", - gap: 15, - classList: ['background'], - items: [ - { - type: "placeholder", - title: lgls("placeholders.inner.title"), - description: lgls("placeholders.inner.description") - }, - ...modalInputs, - { - type: "container", - id: "buttonsContainer" - }, - { - type: "button", - id: "templateOk", - title: lgls("placeholders.inner.confirmBtn"), - container: "#buttonsContainer" - }, - { - type: "button", - id: "templateSkip", - title: lgls("placeholders.inner.skipBtn"), - container: "#buttonsContainer", - class: "secondary" - } - ] - } - ] - } - ) + type: "row", + gap: 15, + classList: ["background"], + items: [ + { + type: "placeholder", + title: lgls("placeholders.inner.title"), + description: lgls("placeholders.inner.description"), + }, + ...modalInputs, + { + type: "container", + id: "buttonsContainer", + }, + { + type: "button", + id: "templateOk", + title: lgls("placeholders.inner.confirmBtn"), + container: "#buttonsContainer", + }, + { + type: "button", + id: "templateSkip", + title: lgls("placeholders.inner.skipBtn"), + container: "#buttonsContainer", + class: "secondary", + }, + ], + }, + ], + }); - modal.open() + modal.open(); - const modalEl = modal.el - const skipBtn = modalEl.querySelector("#templateSkip") - const okBtn = modalEl.querySelector("#templateOk") + const modalEl = modal.el; + const skipBtn = modalEl.querySelector("#templateSkip"); + const okBtn = modalEl.querySelector("#templateOk"); skipBtn.onclick = () => { - editor.setValue(clearPlaceholders(templateContent)) - modal.close() - } + editor.setValue(clearPlaceholders(templateContent)); + modal.close(); + }; okBtn.onclick = () => { - templateContent = templateContent.replace( - placeholderRegex, - (_, key) => { - const input = modalEl.querySelector(`#${key.trim()}`); - return input ? input.value : ""; - } - ); - - editor.setValue(templateContent) - modal.close() - } - } - else { - editor.setValue(clearPlaceholders(templateContent)) + templateContent = templateContent.replace(placeholderRegex, (_, key) => { + const input = modalEl.querySelector(`#${key.trim()}`); + return input ? input.value : ""; + }); + + editor.setValue(templateContent); + modal.close(); + }; + } else { + editor.setValue(clearPlaceholders(templateContent)); } - }) - } - else { - templateChooseCodeTool.classList.add("disabled") + }); + } else { + templateChooseCodeTool.classList.add("disabled"); } } @@ -200,10 +189,10 @@ let isLiveServerActive = false; const codeContextMenuPerTab = new Map(); function setTabColor(tab, color) { - tab.style.borderBottomColor = color + tab.style.borderBottomColor = color; } -let settingsObject = {} +let settingsObject = {}; export function updateTabPath(oldPath, newPath, newName) { const rec = tabsByPath.get(oldPath); @@ -224,55 +213,55 @@ export function updateTabPath(oldPath, newPath, newName) { } export class themeEditors { - static current = {} - static themes = window.CodeMirror.ThemeParents + static current = {}; + static themes = window.CodeMirror.ThemeParents; constructor(editor) { - this.editor = editor + this.editor = editor; } static add(id, value) { - this.themes[id] = value + themeEditors.themes[id] = value; } static getThemes() { - return this.themes + return themeEditors.themes; } static has(id) { - return id in this.themes; + return id in themeEditors.themes; } apply(id) { - this.current = id - this.editor.setTheme(themeEditors.themes[id]) + this.current = id; + this.editor.setTheme(themeEditors.themes[id]); } } function addThemeModificator(editor) { function proccess(theme) { if (themeEditors.has(theme)) { - editor.setTheme(themeEditors.themes[theme]) + editor.setTheme(themeEditors.themes[theme]); themeEditors.current = { name: theme, - codemirror: themeEditors.themes[theme] - } + codemirror: themeEditors.themes[theme], + }; } } - proccess(getTheme()) + proccess(getTheme()); const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.type === "attributes" && mutation.attributeName === "theme") { - const theme = document.body.getAttribute("theme") - proccess(theme) + const theme = document.body.getAttribute("theme"); + proccess(theme); } } - }) + }); observer.observe(document.body, { attributes: true, - attributeFilter: ["theme"] - }) + attributeFilter: ["theme"], + }); } function initializeGlobalButtons(settings = {}) { @@ -281,270 +270,272 @@ function initializeGlobalButtons(settings = {}) { const SideBarLiveServerIcon = new SideBarIconManager("startLiveServer"); const handleRuntimeErrorsClick = (e) => { - e.preventDefault() + e.preventDefault(); if (!currentPath) return; const rec = tabsByPath.get(currentPath); if (rec && rec.ErrorsHistoryWindow) { - rec.ErrorsHistoryWindow.toggle() + rec.ErrorsHistoryWindow.toggle(); } - } + }; const runtimeErrorsBtn = document.querySelector("#runtimeErrors"); if (runtimeErrorsBtn) { runtimeErrorsBtn.addEventListener("click", handleRuntimeErrorsClick); } - const handleMDPreviewClick = (e) => { - e.preventDefault() + const handleMdPreviewClick = (e) => { + e.preventDefault(); if (!currentPath) return; const rec = tabsByPath.get(currentPath); if (!rec) return; - const MDPreviewWindow = new BottomWindow("MDPreview", { title: `Preview · ${rec.tabEl.querySelector(".file-name").textContent}` }) - MDPreviewWindow.fullscreen() - MDPreviewWindow.show() - MDPreviewWindow.clear() + const MdPreviewWindow = new BottomWindow("MDPreview", { + title: `Preview · ${rec.tabEl.querySelector(".file-name").textContent}`, + }); + MdPreviewWindow.fullscreen(); + MdPreviewWindow.show(); + MdPreviewWindow.clear(); const editor = rec.editor; - MDPreviewWindow.set(marked.parse(editor.getValue())) - } + MdPreviewWindow.set(marked.parse(editor.getValue())); + }; const mdPreviewBtn = document.querySelector("#MDPreview"); if (mdPreviewBtn) { - mdPreviewBtn.addEventListener("click", handleMDPreviewClick); + mdPreviewBtn.addEventListener("click", handleMdPreviewClick); } - const handleJSMinifyClick = (e) => { - e.preventDefault() + const handleJsMinifyClick = (e) => { + e.preventDefault(); if (!currentPath) return; const rec = tabsByPath.get(currentPath); if (!rec) return; - let value = rec.editor.getValue() - rec.editor.setValue(minifyJS(value)) - } + const value = rec.editor.getValue(); + rec.editor.setValue(minifyJS(value)); + }; const jsMinifyBtn = document.querySelector("#js-minify"); if (jsMinifyBtn) { - jsMinifyBtn.addEventListener("click", handleJSMinifyClick); + jsMinifyBtn.addEventListener("click", handleJsMinifyClick); } - const handleCSSMinifyClick = (e) => { - e.preventDefault() + const handleCssMinifyClick = (e) => { + e.preventDefault(); if (!currentPath) return; const rec = tabsByPath.get(currentPath); if (!rec) return; - let value = rec.editor.getValue() - rec.editor.setValue(minifyCSS(value)) - } + const value = rec.editor.getValue(); + rec.editor.setValue(minifyCSS(value)); + }; const cssMinifyBtn = document.querySelector("#css-minify"); if (cssMinifyBtn) { - cssMinifyBtn.addEventListener("click", handleCSSMinifyClick); + cssMinifyBtn.addEventListener("click", handleCssMinifyClick); } const handleCodeConsoleClick = async (e) => { - e.preventDefault() + e.preventDefault(); - const globalTerminalWindow = new BottomWindow("globalTerminal", { title: "Terminal" }) - globalTerminalWindow.show() - globalTerminalWindow.clear() - globalTerminalWindow.autoScrollBottom() - globalTerminalWindow.win.classList.add("console") + const globalTerminalWindow = new BottomWindow("globalTerminal", { title: "Terminal" }); + globalTerminalWindow.show(); + globalTerminalWindow.clear(); + globalTerminalWindow.autoScrollBottom(); + globalTerminalWindow.win.classList.add("console"); - const rootPath = window.__pathContext?.rootPath + const rootPath = window.__pathContext?.rootPath; if (rootPath) { - new Console(globalTerminalWindow, rootPath) + new Console(globalTerminalWindow, rootPath); } else if (currentPath) { - new Console(globalTerminalWindow, currentPath) + new Console(globalTerminalWindow, currentPath); } else { - const pcInfo = await window.electron.getUserPcInfo() - new Console(globalTerminalWindow, pcInfo.homedir) + const pcInfo = await window.electron.getUserPcInfo(); + new Console(globalTerminalWindow, pcInfo.homedir); } - } + }; const codeConsoleBtn = document.querySelector("#code-console"); if (codeConsoleBtn) { codeConsoleBtn.addEventListener("click", handleCodeConsoleClick); } const handleStartLiveServerClick = async (e) => { - e.preventDefault() + e.preventDefault(); if (!currentPath) return; if (isLiveServerActive == false) { - let server = await window.electron.startLiveServer(currentPath) + const server = await window.electron.startLiveServer(currentPath); if (server.success) { - isLiveServerActive = true - SideBarLiveServerIcon.set("active") - SideBarLiveServerIcon.blink() - - createNotify( - { - type: "success", - icon: "sensors", - title: "Live server enabled", - content: server.url - } - ) - } - else { - createNotify( - { - type: "danger", - icon: "sensors", - title: "Live server error", - content: server.error - } - ) + isLiveServerActive = true; + SideBarLiveServerIcon.set("active"); + SideBarLiveServerIcon.blink(); + + createNotify({ + type: "success", + icon: "sensors", + title: "Live server enabled", + content: server.url, + }); + } else { + createNotify({ + type: "danger", + icon: "sensors", + title: "Live server error", + content: server.error, + }); } - } - else { - let server = await window.electron.stopLiveServer() + } else { + const server = await window.electron.stopLiveServer(); if (server.success) { - isLiveServerActive = false - SideBarLiveServerIcon.set("unactive") - SideBarLiveServerIcon.blink(false) - - createNotify( - { - type: "warn", - icon: "sensors", - title: "Live server disabled", - content: "Live server is not working now" - } - ) - } - else { - isLiveServerActive = false - - createNotify( - { - type: "danger", - icon: "sensors", - title: "Live server error", - content: server.error - } - ) + isLiveServerActive = false; + SideBarLiveServerIcon.set("unactive"); + SideBarLiveServerIcon.blink(false); + + createNotify({ + type: "warn", + icon: "sensors", + title: "Live server disabled", + content: "Live server is not working now", + }); + } else { + isLiveServerActive = false; + + createNotify({ + type: "danger", + icon: "sensors", + title: "Live server error", + content: server.error, + }); } } - } + }; const startLiveServerBtn = document.querySelector("#startLiveServer"); if (startLiveServerBtn) { startLiveServerBtn.addEventListener("click", handleStartLiveServerClick); } const handleRuntimeOutputPythonClick = async (e) => { - const pyInfo = await window.electron.getPython() + const pyInfo = await window.electron.getPython(); - e.preventDefault() + e.preventDefault(); if (!currentPath) return; const rec = tabsByPath.get(currentPath); if (!rec) return; - const RuntimeHistoryWindow = new BottomWindow("runtimeHistoryPython", { title: "Python" }) - RuntimeHistoryWindow.show() - RuntimeHistoryWindow.clear() + const RuntimeHistoryWindow = new BottomWindow("runtimeHistoryPython", { title: "Python" }); + RuntimeHistoryWindow.show(); + RuntimeHistoryWindow.clear(); - let pythonRunMethod = "installed" + let pythonRunMethod = "installed"; if ("editor" in settings && "pythonRunnerMethod" in settings.editor) { - pythonRunMethod = settings.editor.pythonRunnerMethod + pythonRunMethod = settings.editor.pythonRunnerMethod; } - const pythonResult = await window.electron.runPython({ filePath: currentPath, useEmbed: pythonRunMethod == "builtin" }) + const pythonResult = await window.electron.runPython({ + filePath: currentPath, + useEmbed: pythonRunMethod == "builtin", + }); if (pythonResult.type == "success") { - renderPyMsgSuccess({ RuntimeHistoryWindow: RuntimeHistoryWindow, pythonResult: pythonResult, method: pythonRunMethod }) + renderPyMsgSuccess({ + RuntimeHistoryWindow, + pythonResult, + method: pythonRunMethod, + }); } if (pythonResult.type == "error") { - renderPyMsgErr({ RuntimeHistoryWindow: RuntimeHistoryWindow, pythonResult: pythonResult, method: pythonRunMethod }) + renderPyMsgErr({ + RuntimeHistoryWindow, + pythonResult, + method: pythonRunMethod, + }); } - } + }; const runtimeOutputPythonBtn = document.querySelector("#runtimeOutputPython"); if (runtimeOutputPythonBtn) { runtimeOutputPythonBtn.addEventListener("click", handleRuntimeOutputPythonClick); } const handleRuntimeOutputClick = async (e) => { - e.preventDefault() + e.preventDefault(); if (!currentPath) return; const rec = tabsByPath.get(currentPath); if (!rec) return; - const RuntimeHistoryWindow = new BottomWindow("runtimeHistory", { title: "Runtime" }) - RuntimeHistoryWindow.show() - RuntimeHistoryWindow.clear() + const RuntimeHistoryWindow = new BottomWindow("runtimeHistory", { title: "Runtime" }); + RuntimeHistoryWindow.show(); + RuntimeHistoryWindow.clear(); - const evaluatedCode = runSandbox(rec.editor.getValue()) + const evaluatedCode = runSandbox(rec.editor.getValue()); if (typeof evaluatedCode == "object") { - evaluatedCode.forEach(e => { - const type = e.type - let args = e.args - const line = e.line - 2 > 0 ? e.line - 2 : 0 - const col = e.col + evaluatedCode.forEach((e) => { + const type = e.type; + const args = e.args; + const line = e.line - 2 > 0 ? e.line - 2 : 0; + const col = e.col; const icons = { log: "subdirectory_arrow_right", error: "error", - warn: "warning" - } + warn: "warning", + }; const types = { log: "default", error: "error", - warn: "warning" - } + warn: "warning", + }; - let argType = null + let argType = null; if (args.length == 1) { - argType = typeof args[0] + argType = typeof args[0]; if (isStringifiedObject(args[0]) == "object") { - argType = "object:dict" + argType = "object:dict"; } if (isStringifiedObject(args[0]) == "array") { - argType = "object:array" + argType = "object:array"; } if (argType == "number") { - argType = isFloat(args[0]) ? argType += ":float" : argType += ":int" + argType = isFloat(args[0]) ? (argType += ":float") : (argType += ":int"); } } - const runtimeOutputEl = document.createElement("div") - runtimeOutputEl.classList.add(`log-${types[type]} bottom-window__item`) + const runtimeOutputEl = document.createElement("div"); + runtimeOutputEl.classList.add(`log-${types[type]} bottom-window__item`); - const transluentSpan = document.createElement("span") - transluentSpan.className = "translucent bottom-window__item" - transluentSpan.textContent = `${line}:${col}` - runtimeOutputEl.appendChild(transluentSpan) + const transluentSpan = document.createElement("span"); + transluentSpan.className = "translucent bottom-window__item"; + transluentSpan.textContent = `${line}:${col}`; + runtimeOutputEl.appendChild(transluentSpan); if (argType != null) { - const typeSpan = document.createElement("span") - typeSpan.className = `runtime-typeof ${argType.split(":")[0]}` - typeSpan.textContent = argType.toUpperCase() - runtimeOutputEl.appendChild(typeSpan) + const typeSpan = document.createElement("span"); + typeSpan.className = `runtime-typeof ${argType.split(":")[0]}`; + typeSpan.textContent = argType.toUpperCase(); + runtimeOutputEl.appendChild(typeSpan); } - const iconSpan = document.createElement("span") - iconSpan.className = "material-symbols-rounded" - iconSpan.textContent = icons[type] - runtimeOutputEl.appendChild(iconSpan) + const iconSpan = document.createElement("span"); + iconSpan.className = "material-symbols-rounded"; + iconSpan.textContent = icons[type]; + runtimeOutputEl.appendChild(iconSpan); if (args.join(", ").length == 0) { - const emptySpan = document.createElement("span") - emptySpan.className = "translucent" - emptySpan.textContent = "Empty" - runtimeOutputEl.appendChild(emptySpan) + const emptySpan = document.createElement("span"); + emptySpan.className = "translucent"; + emptySpan.textContent = "Empty"; + runtimeOutputEl.appendChild(emptySpan); } else { - const argsSpan = document.createElement("span") - argsSpan.textContent = args.join(", ") - runtimeOutputEl.appendChild(argsSpan) + const argsSpan = document.createElement("span"); + argsSpan.textContent = args.join(", "); + runtimeOutputEl.appendChild(argsSpan); } - RuntimeHistoryWindow.add(runtimeOutputEl) - }) + RuntimeHistoryWindow.add(runtimeOutputEl); + }); } - } + }; const runtimeOutputBtn = document.querySelector("#runtimeOutput"); if (runtimeOutputBtn) { runtimeOutputBtn.addEventListener("click", handleRuntimeOutputClick); @@ -556,102 +547,109 @@ function initializeGlobalButtons(settings = {}) { function initializeChangeTabSizeButton(settings) { let currentTabSize = 2; - if("editor" in settings && "tabSize" in settings.editor) { - if(settings.editor.tabSize != undefined && settings.editor.tabSize.length != 0) { - currentTabSize = settings.editor.tabSize - } + if ( + "editor" in settings && + "tabSize" in settings.editor && + settings.editor.tabSize != undefined && + settings.editor.tabSize.length != 0 + ) { + currentTabSize = settings.editor.tabSize; } - const el = document.querySelector("#changeTabSize") + const el = document.querySelector("#changeTabSize"); function set(size) { if (!currentPath) return; const rec = tabsByPath.get(currentPath); if (!rec) return; - rec.editor.setTabSize(size) - setTabSize(size) + rec.editor.setTabSize(size); + setTabSize(size); } setTimeout(() => { - set(currentTabSize) - }, 100) + set(currentTabSize); + }, 100); - const changeTabSizeList = new TopWindowList("changeTabSizeWindow", - [ - { - name: "2 Tabs", - id: 2 - }, - { - name: "4 Tabs", - id: 4 - }, - { - name: "8 Tabs", - id: 8 - } - ] - ) + const changeTabSizeList = new TopWindowList("changeTabSizeWindow", [ + { + name: "2 Tabs", + id: 2, + }, + { + name: "4 Tabs", + id: 4, + }, + { + name: "8 Tabs", + id: 8, + }, + ]); changeTabSizeList.on("click", (d) => { - set(d.id) - }) + set(d.id); + }); - changeTabSizeList.bind(el) + changeTabSizeList.bind(el); } function updateVisibleOnElements(extension, language) { - document.querySelectorAll("[visibleOn]").forEach(element => { - let val = element.getAttribute("visibleOn") + document.querySelectorAll("[visibleOn]").forEach((element) => { + const val = element.getAttribute("visibleOn"); if (val.includes("language:")) { - let lang = val.split("language:")[1].trim() + const lang = val.split("language:")[1].trim(); if (extension == lang) { - element.classList.remove("hidden") - } - else { - element.classList.add("hidden") + element.classList.remove("hidden"); + } else { + element.classList.add("hidden"); } } if (val.includes("mode:")) { - let mode = val.split("mode:")[1].trim() + const mode = val.split("mode:")[1].trim(); if (language.mode == mode) { - element.classList.remove("hidden") - } - else { - element.classList.add("hidden") + element.classList.remove("hidden"); + } else { + element.classList.add("hidden"); } } - }) + }); } -function initExtensionEditorAPIEvents({ editor }) { +function initExtensionEditorApiEvents({ editor }) { window.electron.ext.editor.api.onReplace((data) => { - const findString = data.findString - const replaceString = data.replaceString + const findString = data.findString; + const replaceString = data.replaceString; editor.find(findString, { caseSensitive: true, wholeWord: false, - regExp: false + regExp: false, }); editor.replace(replaceString); - }) + }); } -export async function openTab(path, content, extension, name, pathContext, isNew = false, settings = {}) { - let language = Languages.get(extension) - const isImage = language.name == "Image" || extension == "svg" +export async function openTab( + path, + content, + extension, + name, + pathContext, + isNew = false, + settings = {}, +) { + const language = Languages.get(extension); + const isImage = language.name == "Image" || extension == "svg"; - closeAllWindows(isImage ? "imagePreview" : null) - setAppTitle(name) + closeAllWindows(isImage ? "imagePreview" : null); + setAppTitle(name); - currentContent = content - settingsObject = settings + currentContent = content; + settingsObject = settings; const cached = recentlyClosed.get(path) || null; const id = toBase64(path); @@ -661,52 +659,48 @@ export async function openTab(path, content, extension, name, pathContext, isNew pane.id = id; editorWrapper.appendChild(pane); - let fileNameInfo = Filenames.get(name) + const fileNameInfo = Filenames.get(name); - const codeMirrorView = window.CodeMirror.create( - document.getElementById(id), - { - value: isImage ? "" : content - } - ) + const codeMirrorView = window.CodeMirror.create(document.getElementById(id), { + value: isImage ? "" : content, + }); const editor = new EditorAdapter(codeMirrorView); - const ErrorsHistoryWindow = new BottomWindow("errorsHistory", { title: "Errors history" }) - clearRuntimeErrors() + const ErrorsHistoryWindow = new BottomWindow("errorsHistory", { title: "Errors history" }); + clearRuntimeErrors(); - const imagePreviewWindow = new BottomWindow("imagePreview", { title: "Preview" }) - imagePreviewWindow.removeClose() + const imagePreviewWindow = new BottomWindow("imagePreview", { title: "Preview" }); + imagePreviewWindow.removeClose(); if (isImage) { - renderImagePreview(imagePreviewWindow, path) - } - else { - enableSave() - imagePreviewWindow.fullscreen(false) - imagePreviewWindow.hide() + renderImagePreview(imagePreviewWindow, path); + } else { + enableSave(); + imagePreviewWindow.fullscreen(false); + imagePreviewWindow.hide(); } - initCodeContextMenu(path, pathContext, editor) - codeContextMenuPerTab.set(path, true) + initCodeContextMenu(path, pathContext, editor); + codeContextMenuPerTab.set(path, true); - initializeGlobalButtons(settings) - initializeChangeTabSizeButton(settings) - updateVisibleOnElements(extension, language) + initializeGlobalButtons(settings); + initializeChangeTabSizeButton(settings); + updateVisibleOnElements(extension, language); // chached value set if (cached) { if (!isImage) editor.setValue(cached.content ?? "", -1); editor.resetUndoManager(); - setErrors(editor.getAnnotations()) + setErrors(editor.getAnnotations()); if (cached.cursor) editor.moveCursorTo(cached.cursor.row, cached.cursor.column); if (typeof cached.scrollTop === "number") editor.setScrollTop(cached.scrollTop); } else { if (!isImage) editor.setValue(content ?? "", -1); editor.resetUndoManager(); - - setErrors(editor.getAnnotations()) + + setErrors(editor.getAnnotations()); } editor.setLanguage(fileNameInfo == false ? extension : fileNameInfo.mode); @@ -716,58 +710,65 @@ export async function openTab(path, content, extension, name, pathContext, isNew enableLiveAutocompletion: true, animatedScroll: true, cursorStyle: "smooth", - fixedWidthGutter: true + fixedWidthGutter: true, }); - addThemeModificator(editor) + addThemeModificator(editor); - window.electron.triggers.sendFileOpened( - { - path: path, - extension: extension, - name: name, - context: pathContext ?? undefined - } - ) - sendEvent("file-opened-event", - { - editor: editor, - path: path, - extension: extension, - name: name, - context: pathContext ?? undefined - } - ) + window.electron.triggers.sendFileOpened({ + path, + extension, + name, + context: pathContext ?? undefined, + }); + sendEvent("file-opened-event", { + editor, + path, + extension, + name, + context: pathContext ?? undefined, + }); // trigger first ace mode changed - triggerEditorChanged({ editor: editor, extension: extension, language: language }) - initExtensionEditorAPIEvents({ editor: editor }) + triggerEditorChanged({ editor, extension, language }); + initExtensionEditorApiEvents({ editor }); - let cursorChangeTimer = null + let cursorChangeTimer = null; function triggerCursorChanged() { - updateEditorData() + updateEditorData(); - clearTimeout(cursorChangeTimer) + clearTimeout(cursorChangeTimer); cursorChangeTimer = setTimeout(() => { - triggerEditorClicked({ editor: editor, extension: extension, language: language }) - }, 100) + triggerEditorClicked({ editor, extension, language }); + }, 100); } // - editor.onWheel((e) => { - if (!e.ctrlKey && !e.metaKey) return - e.preventDefault() - e.stopPropagation() - const px = parseFloat(getComputedStyle(document.body).getPropertyValue('--editor-font-size')) - const next = Math.min(200, Math.max(50, Math.round(px / 15 * 100) + (e.deltaY < 0 ? 5 : -5))) - Setting.editorTextSize(next) - }, { passive: false, capture: true }) - - const languageContextName = fileNameInfo != false ? `${fileNameInfo.name} (${fileNameInfo.mode.toUpperCase()})` : language.name - setCurrentLanguage(languageContextName, { editor: editor }) + editor.onWheel( + (e) => { + if (!(e.ctrlKey || e.metaKey)) return; + e.preventDefault(); + e.stopPropagation(); + const px = Number.parseFloat( + getComputedStyle(document.body).getPropertyValue("--editor-font-size"), + ); + const next = Math.min( + 200, + Math.max(50, Math.round((px / 15) * 100) + (e.deltaY < 0 ? 5 : -5)), + ); + Setting.editorTextSize(next); + }, + { passive: false, capture: true }, + ); + + const languageContextName = + fileNameInfo == false + ? language.name + : `${fileNameInfo.name} (${fileNameInfo.mode.toUpperCase()})`; + setCurrentLanguage(languageContextName, { editor }); if (tabsByPath.has(path)) { activateTab(tabsByPath.get(path).tabEl); @@ -784,36 +785,36 @@ export async function openTab(path, content, extension, name, pathContext, isNew setSymbols(editorValue.length); setErrors(editor.getAnnotations()); - codeToolsWrapper.classList.toggle( - "hidden", - editorValue.trim().length > 0 - ); + codeToolsWrapper.classList.toggle("hidden", editorValue.trim().length > 0); } editor.onAfterRender(() => { - bindCodeTools({ editor: editor, extension: extension }) - }) + bindCodeTools({ editor, extension }); + }); - editor.onChangeCursor(triggerCursorChanged) + editor.onChangeCursor(triggerCursorChanged); - editor.onMouseDown(function () { - updateEditorData() + editor.onMouseDown(() => { + updateEditorData(); }); - editor.onFocus(function () { - updateEditorData() + editor.onFocus(() => { + updateEditorData(); }); editor.onClick(async () => { - await setEditorContext({ errorsUpdate: false }, { - editor: editor, - language: language, - updateEditorData: updateEditorData, - path: path, - settings: settings - }) + await setEditorContext( + { errorsUpdate: false }, + { + editor, + language, + updateEditorData, + path, + settings, + }, + ); }); - + const tab = document.createElement("div"); tab.className = "code-tab"; @@ -822,11 +823,11 @@ export async function openTab(path, content, extension, name, pathContext, isNew // colored tabs if ("editor" in settings && "coloredTabs" in settings.editor && settings.editor.coloredTabs) { - setTabColor(tab, language.color) + setTabColor(tab, language.color); } const iconPath = getFileIconUrl(name); - let tabIcon = `icon`; + const tabIcon = `icon`; tab.innerHTML = ` ${tabIcon} ${escapeHtml(name)} @@ -834,82 +835,82 @@ export async function openTab(path, content, extension, name, pathContext, isNew `; tabsBar.appendChild(tab); - tab.draggable = true + tab.draggable = true; - tab.addEventListener('dragstart', () => { - tab.classList.add('dragging') - console.log('dragstart') - }) - - tab.addEventListener('dragend', () => { - tab.classList.remove('dragging') - tabsBar.querySelectorAll('.drag-over-left, .drag-over-right') - .forEach(t => t.classList.remove('drag-over-left', 'drag-over-right')) + tab.addEventListener("dragstart", () => { + tab.classList.add("dragging"); + console.log("dragstart"); + }); - console.log('dragend') - }) + tab.addEventListener("dragend", () => { + tab.classList.remove("dragging"); + tabsBar + .querySelectorAll(".drag-over-left, .drag-over-right") + .forEach((t) => t.classList.remove("drag-over-left", "drag-over-right")); - tab.addEventListener('dragover', (e) => { - e.preventDefault() - const dragging = tabsBar.querySelector('.dragging') - if (!dragging || dragging === tab) return - tabsBar.querySelectorAll('.drag-over-left, .drag-over-right') - .forEach(t => t.classList.remove('drag-over-left', 'drag-over-right')) - const { left, width } = tab.getBoundingClientRect() - tab.classList.add(e.clientX < left + width / 2 ? 'drag-over-left' : 'drag-over-right') + console.log("dragend"); + }); - console.log('dragover') - }) + tab.addEventListener("dragover", (e) => { + e.preventDefault(); + const dragging = tabsBar.querySelector(".dragging"); + if (!dragging || dragging === tab) return; + tabsBar + .querySelectorAll(".drag-over-left, .drag-over-right") + .forEach((t) => t.classList.remove("drag-over-left", "drag-over-right")); + const { left, width } = tab.getBoundingClientRect(); + tab.classList.add(e.clientX < left + width / 2 ? "drag-over-left" : "drag-over-right"); + + console.log("dragover"); + }); - tab.addEventListener('dragleave', () => { - tab.classList.remove('drag-over-left', 'drag-over-right') + tab.addEventListener("dragleave", () => { + tab.classList.remove("drag-over-left", "drag-over-right"); - console.log('dragleave') - }) + console.log("dragleave"); + }); - tab.addEventListener('drop', (e) => { - e.preventDefault() - const dragging = tabsBar.querySelector('.dragging') - if (!dragging || dragging === tab) return - const { left, width } = tab.getBoundingClientRect() - tabsBar.insertBefore(dragging, e.clientX < left + width / 2 ? tab : tab.nextSibling) - tab.classList.remove('drag-over-left', 'drag-over-right') + tab.addEventListener("drop", (e) => { + e.preventDefault(); + const dragging = tabsBar.querySelector(".dragging"); + if (!dragging || dragging === tab) return; + const { left, width } = tab.getBoundingClientRect(); + tabsBar.insertBefore(dragging, e.clientX < left + width / 2 ? tab : tab.nextSibling); + tab.classList.remove("drag-over-left", "drag-over-right"); - console.log('drop') - }) + console.log("drop"); + }); // if tab is a new file (from dragNdrop or smth) if (isNew) { - showCodeWindowVisuals() - tab.classList.add("not-saved") + showCodeWindowVisuals(); + tab.classList.add("not-saved"); } - // + // tabsByPath.set(path, { - id: id, + id, tabEl: tab, - editor: editor, + editor, paneEl: pane, - ErrorsHistoryWindow: ErrorsHistoryWindow, - language: language, - isImage: isImage, + ErrorsHistoryWindow, + language, + isImage, new: isNew, fileName: name, color: language.color, - extension: extension + extension, }); recentlyClosed.delete(path); - addToHistory( - { - actionType: "file-open", - value: `${name} opened`, - desc: path - } - ) + addToHistory({ + actionType: "file-open", + value: `${name} opened`, + desc: path, + }); tab.addEventListener("click", (ev) => { ev.preventDefault(); @@ -942,49 +943,49 @@ export async function openTab(path, content, extension, name, pathContext, isNew editor.onChange(async () => { tab.classList.add("not-saved"); - await setEditorContext({}, { - editor: editor, - language: language, - updateEditorData: updateEditorData, - path: path, - settings: settings - }) + await setEditorContext( + {}, + { + editor, + language, + updateEditorData, + path, + settings, + }, + ); - triggerEditorChanged({ editor: editor, extension: extension, language: language }) + triggerEditorChanged({ editor, extension, language }); }); activateTab(tab); } bus.addEventListener("on-setting-colored-tabs", (data) => { - const value = data.detail + const value = data.detail; // update settings editor.coloredTabs - if("editor" in settingsObject && "coloredTabs" in settingsObject.editor) { - settingsObject.editor.coloredTabs = value + if ("editor" in settingsObject && "coloredTabs" in settingsObject.editor) { + settingsObject.editor.coloredTabs = value; } - tabsByPath.forEach(item => { - const tabEl = item.tabEl + tabsByPath.forEach((item) => { + const tabEl = item.tabEl; - if(value) { - tabEl.classList.remove("no-color") - setTabColor(tabEl, item.color) - } - else { - tabEl.classList.add("no-color") + if (value) { + tabEl.classList.remove("no-color"); + setTabColor(tabEl, item.color); + } else { + tabEl.classList.add("no-color"); } - }) -}) + }); +}); async function showCloseConfirmModal(path, editor) { const fileName = path.split(/[\\/]/).pop(); - const modal = await closeConfirmModal( - { - fileName: fileName - } - ) + const modal = await closeConfirmModal({ + fileName, + }); const modalEl = modal.el; const saveBtn = modalEl.querySelector("#closeConfirmSave"); @@ -1009,7 +1010,7 @@ async function showCloseConfirmModal(path, editor) { if (isNew) { const saveNewFileRes = await electronAPI.askToSaveNewFile({ filename: path, - content: rec.editor.getValue() + content: rec.editor.getValue(), }); if (saveNewFileRes.success) { const newPath = saveNewFileRes.path; @@ -1043,18 +1044,24 @@ export function closeTab(path) { content: editor.getValue(), cursor: editor.getCursorPosition(), scrollTop: editor.getScrollTop(), - when: Date.now() + when: Date.now(), }; recentlyClosed.set(path, state); destroyCodeContextMenu(); - try { editor.destroy(); } catch (_) { } - + try { + editor.destroy(); + } catch (_) {} + if (paneEl && paneEl.parentNode) paneEl.parentNode.removeChild(paneEl); - const next = tabEl.nextElementSibling?.classList.contains("code-tab") ? tabEl.nextElementSibling : null; - const prev = tabEl.previousElementSibling?.classList.contains("code-tab") ? tabEl.previousElementSibling : null; + const next = tabEl.nextElementSibling?.classList.contains("code-tab") + ? tabEl.nextElementSibling + : null; + const prev = tabEl.previousElementSibling?.classList.contains("code-tab") + ? tabEl.previousElementSibling + : null; const toActivate = next || prev; tabEl.remove(); @@ -1069,11 +1076,11 @@ export function closeTab(path) { imagePreviewWindow.hide(); } startScreen?.classList.remove("hidden"); - toggleCodeFooter(false) + toggleCodeFooter(false); tabsBar.classList.add("hidden"); currentPath = null; - setAppTitle() + setAppTitle(); } else if (toActivate) { activateTab(toActivate); } @@ -1086,7 +1093,9 @@ export function closeTab(path) { export async function reopenLastClosed() { if (!recentlyClosed.size) return; - const [path, state, settings] = [...recentlyClosed.entries()].sort((a, b) => b[1].when - a[1].when)[0]; + const [path, state, settings] = [...recentlyClosed.entries()].sort( + (a, b) => b[1].when - a[1].when, + )[0]; const extension = (path.split(".").pop() || "").toLowerCase(); const name = path.split(/[\\/]/).pop(); @@ -1112,12 +1121,12 @@ export function activateTab(tabEl) { if (!tabEl) return; const id = tabEl.getAttribute("data-id"); const realPath = tabEl.getAttribute("data-path"); - if (!id || !realPath) return; + if (!(id && realPath)) return; destroyCodeContextMenu(); - tabsBar.querySelectorAll(".code-tab").forEach(t => t.classList.remove("active")); - editorWrapper.querySelectorAll(".code").forEach(c => c.classList.remove("active-pane")); + tabsBar.querySelectorAll(".code-tab").forEach((t) => t.classList.remove("active")); + editorWrapper.querySelectorAll(".code").forEach((c) => c.classList.remove("active-pane")); tabEl.classList.add("active"); const pane = document.getElementById(id); @@ -1132,16 +1141,16 @@ export function activateTab(tabEl) { const editor = rec.editor; if (!editor) return; - bindEditorBtns(editor, { fileName: rec.fileName }) - bindCodeTools({ editor: editor, extension: rec.extension }) - initCodeContextMenu(realPath, rec.pathContext, editor) + bindEditorBtns(editor, { fileName: rec.fileName }); + bindCodeTools({ editor, extension: rec.extension }); + initCodeContextMenu(realPath, rec.pathContext, editor); - document.querySelectorAll(".explorer-elements .file").forEach(file => { + document.querySelectorAll(".explorer-elements .file").forEach((file) => { file.classList.toggle("active", file.getAttribute("data-path") === realPath); }); startScreen?.classList.add("hidden"); - toggleCodeFooter(true) + toggleCodeFooter(true); tabsBar.classList.remove("hidden"); const ext = (realPath.split(".").pop() || "").toLowerCase(); @@ -1150,7 +1159,8 @@ export function activateTab(tabEl) { updateVisibleOnElements(ext, rec.language); } - const imagePreviewWindow = BottomWindow.get("imagePreview") || new BottomWindow("imagePreview", { title: "Preview" }); + const imagePreviewWindow = + BottomWindow.get("imagePreview") || new BottomWindow("imagePreview", { title: "Preview" }); if (rec.isImage) { renderImagePreview(imagePreviewWindow, realPath); } else { @@ -1161,39 +1171,37 @@ export function activateTab(tabEl) { } function bindEditorBtns(editor, properties = {}) { - let buttonWrapper = document.querySelector(".code-footer:not(.structure)") + const buttonWrapper = document.querySelector(".code-footer:not(.structure)"); if (!buttonWrapper) return; - let copyBtn = buttonWrapper.querySelector("#code-copy") - let codeSnippet = buttonWrapper.querySelector("#code-snippet") + let copyBtn = buttonWrapper.querySelector("#code-copy"); + let codeSnippet = buttonWrapper.querySelector("#code-snippet"); - if (copyBtn) copyBtn.replaceWith(copyBtn.cloneNode(true)) - if (codeSnippet) codeSnippet.replaceWith(codeSnippet.cloneNode(true)) + if (copyBtn) copyBtn.replaceWith(copyBtn.cloneNode(true)); + if (codeSnippet) codeSnippet.replaceWith(codeSnippet.cloneNode(true)); - copyBtn = buttonWrapper.querySelector("#code-copy") - codeSnippet = buttonWrapper.querySelector("#code-snippet") + copyBtn = buttonWrapper.querySelector("#code-copy"); + codeSnippet = buttonWrapper.querySelector("#code-snippet"); if (copyBtn) { copyBtn.addEventListener("click", () => { - navigator.clipboard.writeText(editor.getValue()) + navigator.clipboard.writeText(editor.getValue()); - createNotify( - { - icon: "content_copy", - title: "Text copied", - content: "Text copied to clipboard!" - } - ) - }) + createNotify({ + icon: "content_copy", + title: "Text copied", + content: "Text copied to clipboard!", + }); + }); } if (codeSnippet) { codeSnippet.addEventListener("click", () => { - const currentMode = editor.currentLanguageId() - const currentTheme = editor.getTheme() + const currentMode = editor.currentLanguageId(); + const currentTheme = editor.getTheme(); - const captureWrapper = document.createElement("div") - captureWrapper.classList.add("code-snippet__wrapper") + const captureWrapper = document.createElement("div"); + captureWrapper.classList.add("code-snippet__wrapper"); captureWrapper.innerHTML = `
@@ -1202,82 +1210,84 @@ function bindEditorBtns(editor, properties = {}) {
${properties.fileName}
-
${capitilize(currentMode.substr(currentMode.lastIndexOf('/') + 1))}
+
${capitilize(currentMode.substr(currentMode.lastIndexOf("/") + 1))}
- ` + `; let value = null; const selectedText = editor.getSelectedText(); - if(selectedText.length > 0) { - value = selectedText - } - else { - value = editor.getValue() + if (selectedText.length > 0) { + value = selectedText; + } else { + value = editor.getValue(); } - - const captureArea = captureWrapper.querySelector("#code-snippet-area") - captureArea.id = "code-snippet-area" - document.body.appendChild(captureWrapper) + const captureArea = captureWrapper.querySelector("#code-snippet-area"); + captureArea.id = "code-snippet-area"; - const captureCodeMirrorView = window.CodeMirror.create( - captureArea, - { - value: value - } - ) + document.body.appendChild(captureWrapper); - const captureEditor = new EditorAdapter(captureCodeMirrorView) + const captureCodeMirrorView = window.CodeMirror.create(captureArea, { + value, + }); + + const captureEditor = new EditorAdapter(captureCodeMirrorView); captureEditor.setLanguage(currentMode); captureEditor.setTheme(currentTheme); captureEditor.scrollPastEnd(0); - captureEditor.setMaxLines(Infinity); + captureEditor.setMaxLines(Number.POSITIVE_INFINITY); captureEditor.wordWrap(true); - captureEditor.readOnly(true) + captureEditor.readOnly(true); - const flashEl = document.createElement("div") - flashEl.classList.add("ace-flash", "hidden") + const flashEl = document.createElement("div"); + flashEl.classList.add("ace-flash", "hidden"); - captureWrapper.style.zIndex = -1 - captureWrapper.style.display = "block" + captureWrapper.style.zIndex = -1; + captureWrapper.style.display = "block"; setTimeout(() => { - captureEditor.tools.toBlob(captureWrapper, { - pixelRatio: 5 - }).then(async blob => { - // flash animation - editor.dom.appendChild(flashEl); - - flashEl.classList.remove("hidden"); - - setTimeout(() => { - flashEl.classList.add("hidden"); - flashEl.addEventListener("transitionend", () => { - flashEl.remove(); - }, { once: true }); - }, 100); - // - - await navigator.clipboard.write([ - new ClipboardItem({ - "image/png": blob - }) - ]); - - createNotify({ - icon: "image", - title: "Screenshot taken!", - content: "Screenshot taken and copied to your clipboard" + captureEditor.tools + .toBlob(captureWrapper, { + pixelRatio: 5, + }) + .then(async (blob) => { + // flash animation + editor.dom.appendChild(flashEl); + + flashEl.classList.remove("hidden"); + + setTimeout(() => { + flashEl.classList.add("hidden"); + flashEl.addEventListener( + "transitionend", + () => { + flashEl.remove(); + }, + { once: true }, + ); + }, 100); + // + + await navigator.clipboard.write([ + new ClipboardItem({ + "image/png": blob, + }), + ]); + + createNotify({ + icon: "image", + title: "Screenshot taken!", + content: "Screenshot taken and copied to your clipboard", + }); + + captureWrapper.style.zIndex = 0; + captureWrapper.style.display = "none"; }); - - captureWrapper.style.zIndex = 0 - captureWrapper.style.display = "none" - }); }, 100); - }) + }); } } @@ -1292,22 +1302,22 @@ export function closeAllTabs() { const codeConsoleBtn = document.querySelector("#code-console"); if (codeConsoleBtn) { codeConsoleBtn.addEventListener("click", async (e) => { - e.preventDefault() + e.preventDefault(); - const globalTerminalWindow = new BottomWindow("globalTerminal", { title: "Terminal" }) - globalTerminalWindow.show() - globalTerminalWindow.clear() - globalTerminalWindow.autoScrollBottom() - globalTerminalWindow.win.classList.add("console") + const globalTerminalWindow = new BottomWindow("globalTerminal", { title: "Terminal" }); + globalTerminalWindow.show(); + globalTerminalWindow.clear(); + globalTerminalWindow.autoScrollBottom(); + globalTerminalWindow.win.classList.add("console"); - const rootPath = window.__pathContext?.rootPath + const rootPath = window.__pathContext?.rootPath; if (rootPath) { - new Console(globalTerminalWindow, rootPath) + new Console(globalTerminalWindow, rootPath); } else if (currentPath) { - new Console(globalTerminalWindow, currentPath) + new Console(globalTerminalWindow, currentPath); } else { - const pcInfo = await window.electron.getUserPcInfo() - new Console(globalTerminalWindow, pcInfo.homedir) + const pcInfo = await window.electron.getUserPcInfo(); + new Console(globalTerminalWindow, pcInfo.homedir); } }); } @@ -1327,9 +1337,9 @@ export function closeFolder() { } if (window.__pathContext) { - Object.keys(window.__pathContext).forEach(k => delete window.__pathContext[k]); + Object.keys(window.__pathContext).forEach((k) => delete window.__pathContext[k]); } setTabName("Explorer"); setAppTitle(); -} \ No newline at end of file +} diff --git a/assets/js/explorerTree/triggers.js b/assets/js/explorerTree/triggers.js index a700c31..6337c6c 100644 --- a/assets/js/explorerTree/triggers.js +++ b/assets/js/explorerTree/triggers.js @@ -1,4 +1,4 @@ -import { sendEvent } from "../bus.js" +import { sendEvent } from "../bus.js"; function getTriggerObj({ editor, language, extension }) { return { @@ -7,25 +7,29 @@ function getTriggerObj({ editor, language, extension }) { editorMode: editor.getCurrentLanguage(), editorLanguage: language.mode, editorLanguageExtension: extension, - errors: editor.getAnnotations().filter(item => item.type === "error").length, + errors: editor.getAnnotations().filter((item) => item.type === "error").length, cursor: { line: editor.getCursorPosition().row + 1, - column: editor.getCursorPosition().column + 1 - } - } + column: editor.getCursorPosition().column + 1, + }, + }; } -export function triggerEditorChanged({ editor, extension, language }) { - window.electron.triggers.sendEditorChanged( - getTriggerObj({ editor: editor, extension: extension, language: language }) - ) +export function triggerEditorChanged({ editor, extension, language }) { + window.electron.triggers.sendEditorChanged(getTriggerObj({ editor, extension, language })); - sendEvent("editor-language-changed", { extension: extension, editor: editor, mode: editor.currentLanguageId() }) + sendEvent("editor-language-changed", { + extension, + editor, + mode: editor.currentLanguageId(), + }); } export function triggerEditorClicked({ editor, extension, language }) { - window.electron.triggers.sendEditorClicked( - getTriggerObj({ editor: editor, extension: extension, language: language }) - ) + window.electron.triggers.sendEditorClicked(getTriggerObj({ editor, extension, language })); - sendEvent("editor-clicked", { extension: extension, editor: editor, mode: editor.currentLanguageId() }) -} \ No newline at end of file + sendEvent("editor-clicked", { + extension, + editor, + mode: editor.currentLanguageId(), + }); +} diff --git a/assets/js/extensionsHandler/events/app/onLocalizationRegister.js b/assets/js/extensionsHandler/events/app/onLocalizationRegister.js index 907e5a7..0438a78 100644 --- a/assets/js/extensionsHandler/events/app/onLocalizationRegister.js +++ b/assets/js/extensionsHandler/events/app/onLocalizationRegister.js @@ -1,5 +1,5 @@ import { bus, sendEvent } from "../../../bus.js"; export function onLocalizationRegister(data) { - sendEvent("extension-localization-register", data) -} \ No newline at end of file + sendEvent("extension-localization-register", data); +} diff --git a/assets/js/extensionsHandler/events/app/onNotification.js b/assets/js/extensionsHandler/events/app/onNotification.js index 8711d17..3f90a32 100644 --- a/assets/js/extensionsHandler/events/app/onNotification.js +++ b/assets/js/extensionsHandler/events/app/onNotification.js @@ -1,12 +1,10 @@ -import { createNotify } from "../../../lib.js" +import { createNotify } from "../../../lib.js"; export function onNotificationCallback({ data, name }) { if ("content" in data) { - data["content"] = `(${name}) ${data.content}` - } - if ("time" in data) { - if (data.time > 15000) data.time = 4000 + data["content"] = `(${name}) ${data.content}`; } + if ("time" in data && data.time > 15_000) data.time = 4000; - createNotify(data) -} \ No newline at end of file + createNotify(data); +} diff --git a/assets/js/extensionsHandler/events/editor/onEditorChangeNewHLRules.js b/assets/js/extensionsHandler/events/editor/onEditorChangeNewHLRules.js index 6df232f..af9e9ce 100644 --- a/assets/js/extensionsHandler/events/editor/onEditorChangeNewHLRules.js +++ b/assets/js/extensionsHandler/events/editor/onEditorChangeNewHLRules.js @@ -1,7 +1,7 @@ export function onEditorChangeNewHLRulesCallback({ data, contexts, refreshEditorHighlight }) { const { fileId, rules } = data; - console.log(data) + console.log(data); contexts[fileId] = new Map(); @@ -10,4 +10,4 @@ export function onEditorChangeNewHLRulesCallback({ data, contexts, refreshEditor } refreshEditorHighlight(); -} \ No newline at end of file +} diff --git a/assets/js/extensionsHandler/events/editor/onFilenamesRegister.js b/assets/js/extensionsHandler/events/editor/onFilenamesRegister.js index 2085dc6..c8fd293 100644 --- a/assets/js/extensionsHandler/events/editor/onFilenamesRegister.js +++ b/assets/js/extensionsHandler/events/editor/onFilenamesRegister.js @@ -1,27 +1,25 @@ import { Filenames } from "../../../lib.js"; export function onFilenamesRegister(data) { - const config = data.config - const extPath = data.extPath + const config = data.config; + const extPath = data.extPath; - Object.keys(config).forEach(item => { - const itemConfig = config[item] + Object.keys(config).forEach((item) => { + const itemConfig = config[item]; - const name = itemConfig.name - const icon = `${extPath}/${itemConfig.icon}` - const iconExt = icon.split(".").pop() == "svg" ? "svg" : "png" - const mode = itemConfig.mode + const name = itemConfig.name; + const icon = `${extPath}/${itemConfig.icon}`; + const iconExt = icon.split(".").pop() == "svg" ? "svg" : "png"; + const mode = itemConfig.mode; - Filenames.add(item, - { - name: name, - icon: icon, - iconExt: iconExt, - mode: mode, - color: "#fff", + Filenames.add(item, { + name, + icon, + iconExt, + mode, + color: "#fff", - customIcon: true - } - ) - }) -} \ No newline at end of file + customIcon: true, + }); + }); +} diff --git a/assets/js/extensionsHandler/events/editor/onLanguageRegister.js b/assets/js/extensionsHandler/events/editor/onLanguageRegister.js index 9efdb00..815dd0d 100644 --- a/assets/js/extensionsHandler/events/editor/onLanguageRegister.js +++ b/assets/js/extensionsHandler/events/editor/onLanguageRegister.js @@ -1,34 +1,34 @@ -import { bus } from "../../../bus.js" -import { ICON_MAP } from "../../../iconRegistry.js" -import { EditorAdapter, Languages } from "../../../lib.js" +import { bus } from "../../../bus.js"; +import { ICON_MAP } from "../../../iconRegistry.js"; +import { EditorAdapter, Languages } from "../../../lib.js"; export function onLanguageRegisterCallback({ data }) { - const name = data.languageName - const displayName = data.languageDisplayName - const extensions = data.languageExtensions - const rules = data.languageRules - const iconPath = data.languageIconPath + const name = data.languageName; + const displayName = data.languageDisplayName; + const extensions = data.languageExtensions; + const rules = data.languageRules; + const iconPath = data.languageIconPath; EditorAdapter.registerLanguage({ id: name, - rules: rules - }) + rules, + }); const languageObject = { name: displayName, icon: iconPath, customIcon: true, - mode: name - } + mode: name, + }; if ("mode" in rules) { - languageObject.mode = rules.mode + languageObject.mode = rules.mode; } - extensions.forEach(id => { - languageObject.id = id + extensions.forEach((id) => { + languageObject.id = id; - ICON_MAP[id] = iconPath - Languages.add(languageObject) - }) -} \ No newline at end of file + ICON_MAP[id] = iconPath; + Languages.add(languageObject); + }); +} diff --git a/assets/js/extensionsHandler/events/editor/onNewDirIconRegister.js b/assets/js/extensionsHandler/events/editor/onNewDirIconRegister.js index a8ece0e..977fa9b 100644 --- a/assets/js/extensionsHandler/events/editor/onNewDirIconRegister.js +++ b/assets/js/extensionsHandler/events/editor/onNewDirIconRegister.js @@ -1,14 +1,12 @@ -import { Dirs } from "../../../lib.js" +import { Dirs } from "../../../lib.js"; export function onNewDirIconRegisterCallback({ data }) { - Object.keys(data).forEach(k => { - Dirs.add( - { - id: k, - icon: data[k], - ext: "svg", - customIcon: true - } - ) - }) -} \ No newline at end of file + Object.keys(data).forEach((k) => { + Dirs.add({ + id: k, + icon: data[k], + ext: "svg", + customIcon: true, + }); + }); +} diff --git a/assets/js/extensionsHandler/events/editor/onNewDocumentationRegister.js b/assets/js/extensionsHandler/events/editor/onNewDocumentationRegister.js index c840795..c9c636d 100644 --- a/assets/js/extensionsHandler/events/editor/onNewDocumentationRegister.js +++ b/assets/js/extensionsHandler/events/editor/onNewDocumentationRegister.js @@ -1,18 +1,18 @@ -import { bus } from "../../../bus.js" -import { enableAceHover } from "../../helpers/aceHover.js" +import { bus } from "../../../bus.js"; +import { enableAceHover } from "../../helpers/aceHover.js"; export function onNewDocumentationRegisterCallback({ data }) { - const docs = data.config - const onMode = data.props.onMode - + const docs = data.config; + const onMode = data.props.onMode; + bus.addEventListener("ace-mode-changed", (e) => { - let detail = e.detail - let mode = detail.mode.trim() - let extension = detail.extension - let editor = detail.editor + const detail = e.detail; + const mode = detail.mode.trim(); + const extension = detail.extension; + const editor = detail.editor; if (mode == onMode) { - enableAceHover(editor, docs, data.props) + enableAceHover(editor, docs, data.props); } - }) -} \ No newline at end of file + }); +} diff --git a/assets/js/extensionsHandler/events/editor/onNewFileExtensionsRegister.js b/assets/js/extensionsHandler/events/editor/onNewFileExtensionsRegister.js index 7fb374b..da4c771 100644 --- a/assets/js/extensionsHandler/events/editor/onNewFileExtensionsRegister.js +++ b/assets/js/extensionsHandler/events/editor/onNewFileExtensionsRegister.js @@ -1,28 +1,26 @@ -import { capitilize, Languages } from "../../../lib.js" +import { capitilize, Languages } from "../../../lib.js"; export function onNewFileExtensionsRegister(data) { - const list = Languages.list() - const config = data.config - const extPath = data.extPath + const list = Languages.list(); + const config = data.config; + const extPath = data.extPath; - Object.keys(config).forEach(item => { - const itemConfig = config[item] + Object.keys(config).forEach((item) => { + const itemConfig = config[item]; - const icon = `${extPath}/${itemConfig.icon}` - const iconExt = icon.split(".").pop() == "svg" ? "svg" : "png" - const mode = itemConfig.mode - const name = `${itemConfig.name} (${capitilize(mode)})` + const icon = `${extPath}/${itemConfig.icon}`; + const iconExt = icon.split(".").pop() == "svg" ? "svg" : "png"; + const mode = itemConfig.mode; + const name = `${itemConfig.name} (${capitilize(mode)})`; - Languages.add( - { - id: item, - icon: icon, - iconExt: iconExt, - mode: mode, - name: name, + Languages.add({ + id: item, + icon, + iconExt, + mode, + name, - customIcon: true - } - ) - }) -} \ No newline at end of file + customIcon: true, + }); + }); +} diff --git a/assets/js/extensionsHandler/events/editor/onTemplatesRegister.js b/assets/js/extensionsHandler/events/editor/onTemplatesRegister.js index caf4efb..f506eae 100644 --- a/assets/js/extensionsHandler/events/editor/onTemplatesRegister.js +++ b/assets/js/extensionsHandler/events/editor/onTemplatesRegister.js @@ -1,9 +1,9 @@ -import { CodeTemplates } from "../../../lib.js" +import { CodeTemplates } from "../../../lib.js"; export function onTemplatesRegister(data) { - const config = data.config + const config = data.config; - Object.keys(config).forEach(item => { - CodeTemplates.add(item, config[item]) - }) -} \ No newline at end of file + Object.keys(config).forEach((item) => { + CodeTemplates.add(item, config[item]); + }); +} diff --git a/assets/js/extensionsHandler/events/ui/onElementCreate.js b/assets/js/extensionsHandler/events/ui/onElementCreate.js index 5abd855..81f06b3 100644 --- a/assets/js/extensionsHandler/events/ui/onElementCreate.js +++ b/assets/js/extensionsHandler/events/ui/onElementCreate.js @@ -1,30 +1,29 @@ export function onElementCreate(data) { - const context = data.extName + const context = data.extName; function apply(wrapper) { - const type = data.type - const id = data.id + const type = data.type; + const id = data.id; - const elements = {} + const elements = {}; - if(type == "image") { - const img = document.createElement("img") - img.id = id - - wrapper.appendChild(img) + if (type == "image") { + const img = document.createElement("img"); + img.id = id; + + wrapper.appendChild(img); } } - if(document.querySelector(`.extension-elements__wrapper[id="${context}"]`)) { - apply(document.querySelector(`.extension-elements__wrapper[id="${context}"]`)) - } - else { - const wrapper = document.createElement("div") - wrapper.classList.add("extension-elements__wrapper") - wrapper.id = context + if (document.querySelector(`.extension-elements__wrapper[id="${context}"]`)) { + apply(document.querySelector(`.extension-elements__wrapper[id="${context}"]`)); + } else { + const wrapper = document.createElement("div"); + wrapper.classList.add("extension-elements__wrapper"); + wrapper.id = context; - document.body.appendChild(wrapper) + document.body.appendChild(wrapper); - apply(wrapper) + apply(wrapper); } -} \ No newline at end of file +} diff --git a/assets/js/extensionsHandler/events/ui/onElementMod.js b/assets/js/extensionsHandler/events/ui/onElementMod.js index 0ec5374..00a97ea 100644 --- a/assets/js/extensionsHandler/events/ui/onElementMod.js +++ b/assets/js/extensionsHandler/events/ui/onElementMod.js @@ -1,135 +1,129 @@ export function getEl(id) { - const wrapper = document.querySelector(`.extension-elements__wrapper`) + const wrapper = document.querySelector(".extension-elements__wrapper"); - return wrapper.querySelector(`[id="${id}"]`) + return wrapper.querySelector(`[id="${id}"]`); } function sendToElement(id, type, data) { - window.electron.ext.ui.element.sendTo( - { - id: id, - type: type, - data: data - } - ) + window.electron.ext.ui.element.sendTo({ + id, + type, + data, + }); } export function onElementMod(data, modules = {}) { - const id = data.id - const type = data.type - const context = data.extName - const value = data.value + const id = data.id; + const type = data.type; + const context = data.extName; + const value = data.value; - const topbarElementInstance = modules.TopBarElement - const idify = modules.idify + const topbarElementInstance = modules.TopBarElement; + const idify = modules.idify; - const el = getEl(id) + const el = getEl(id); - if(type == "setSrc" && el instanceof HTMLImageElement) { - el.src = value + if (type == "setSrc" && el instanceof HTMLImageElement) { + el.src = value; } - if(type == "onEvent" && el instanceof HTMLImageElement) { + if (type == "onEvent" && el instanceof HTMLImageElement) { const events = { - "hover": "mouseenter", - "unhover": "mouseleave", - "click": "click", - "mouseenter": "mouseenter", - "mouseleave": "mouseleave" - } - - if(value in events) { + hover: "mouseenter", + unhover: "mouseleave", + click: "click", + mouseenter: "mouseenter", + mouseleave: "mouseleave", + }; + + if (value in events) { el.addEventListener(events[value], () => { - sendToElement(id, "onEventTriggered", { eventName: events[value] }) - }) + sendToElement(id, "onEventTriggered", { eventName: events[value] }); + }); } } - if(type == "setPosition" && el instanceof HTMLImageElement) { - const availablePositions = value.availablePositions - const positions = value.positions + if (type == "setPosition" && el instanceof HTMLImageElement) { + const availablePositions = value.availablePositions; + const positions = value.positions; - let styles = [] + const styles = []; - Object.keys(positions).forEach(name => { - styles.push( - availablePositions[name].replaceAll("{v}", positions[name]) - ) - }) + Object.keys(positions).forEach((name) => { + styles.push(availablePositions[name].replaceAll("{v}", positions[name])); + }); - el.style.cssText += styles.join(";") + el.style.cssText += styles.join(";"); } - if(type == "setSize" && el instanceof HTMLImageElement) { - const availableSizes = value.availableSizes - const sizes = value.sizes + if (type == "setSize" && el instanceof HTMLImageElement) { + const availableSizes = value.availableSizes; + const sizes = value.sizes; - let styles = [] + const styles = []; - Object.keys(sizes).forEach(name => { - styles.push( - availableSizes[name].replaceAll("{v}", sizes[name]) - ) - }) + Object.keys(sizes).forEach((name) => { + styles.push(availableSizes[name].replaceAll("{v}", sizes[name])); + }); - el.style.cssText += styles.join(";") + el.style.cssText += styles.join(";"); } - if(type == "setTopbarItemSetup") { - const topbarItem = new topbarElementInstance(id) - const item = topbarItem.item + if (type == "setTopbarItemSetup") { + const topbarItem = new topbarElementInstance(id); + const item = topbarItem.item; - if("colors" in value) { - if("background" in value.colors) item.style.background = value.colors.background - if("text" in value.colors) item.style.color = value.colors.text + if ("colors" in value) { + if ("background" in value.colors) item.style.background = value.colors.background; + if ("text" in value.colors) item.style.color = value.colors.text; } - topbarItem.content(value) - topbarItem.show() + topbarItem.content(value); + topbarItem.show(); } - if(type == "setTopbarItemHide") { - const idifiedID = idify(id) + if (type == "setTopbarItemHide") { + const idifiedId = idify(id); - if (topbarElementInstance.instances.has(idifiedID)) { - const topbarItem = topbarElementInstance.instances.get(idifiedID) + if (topbarElementInstance.instances.has(idifiedId)) { + const topbarItem = topbarElementInstance.instances.get(idifiedId); requestAnimationFrame(() => { - topbarItem.hide() - }) + topbarItem.hide(); + }); } } - if(type == "setTopbarItemHideWithIcon") { - const idifiedID = idify(id) + if (type == "setTopbarItemHideWithIcon") { + const idifiedId = idify(id); - if (topbarElementInstance.instances.has(idifiedID)) { - const topbarItem = topbarElementInstance.instances.get(idifiedID) + if (topbarElementInstance.instances.has(idifiedId)) { + const topbarItem = topbarElementInstance.instances.get(idifiedId); requestAnimationFrame(() => { - topbarItem.hide({ iconVisible: true }) - }) + topbarItem.hide({ iconVisible: true }); + }); } } - if(type == "setTopbarItemShow") { - const idifiedID = idify(id) + if (type == "setTopbarItemShow") { + const idifiedId = idify(id); - if (topbarElementInstance.instances.has(idifiedID)) { - const topbarItem = topbarElementInstance.instances.get(idifiedID) + if (topbarElementInstance.instances.has(idifiedId)) { + const topbarItem = topbarElementInstance.instances.get(idifiedId); requestAnimationFrame(() => { - topbarItem.show() - }) + topbarItem.show(); + }); } } - if(type == "setTopbarItemEvent") { - const idifiedID = idify(id) + if (type == "setTopbarItemEvent") { + const idifiedId = idify(id); - if (topbarElementInstance.instances.has(idifiedID)) { - const topbarItem = topbarElementInstance.instances.get(idifiedID) + if (topbarElementInstance.instances.has(idifiedId)) { + const topbarItem = topbarElementInstance.instances.get(idifiedId); - if(value == "click") { - topbarItem.item.classList.add("topbar-item__clickable") + if (value == "click") { + topbarItem.item.classList.add("topbar-item__clickable"); } requestAnimationFrame(() => { topbarItem.on(value, () => { - sendToElement(id, "onEventTriggered", { eventName: value }) - }) - }) + sendToElement(id, "onEventTriggered", { eventName: value }); + }); + }); } } -} \ No newline at end of file +} diff --git a/assets/js/extensionsHandler/events/ui/onLoadCSS.js b/assets/js/extensionsHandler/events/ui/onLoadCSS.js index 65d39bd..a01dbea 100644 --- a/assets/js/extensionsHandler/events/ui/onLoadCSS.js +++ b/assets/js/extensionsHandler/events/ui/onLoadCSS.js @@ -1,7 +1,7 @@ export function onLoadCSSCallback({ id, content }) { - const style = document.createElement("style") - style.id = `css-${id}-${Math.floor(Math.random() * 99999)}` - style.textContent = content + const style = document.createElement("style"); + style.id = `css-${id}-${Math.floor(Math.random() * 99_999)}`; + style.textContent = content; - document.head.appendChild(style) -} \ No newline at end of file + document.head.appendChild(style); +} diff --git a/assets/js/extensionsHandler/events/ui/onThemeRegister.js b/assets/js/extensionsHandler/events/ui/onThemeRegister.js index 1c7a28e..1c8259f 100644 --- a/assets/js/extensionsHandler/events/ui/onThemeRegister.js +++ b/assets/js/extensionsHandler/events/ui/onThemeRegister.js @@ -1,21 +1,21 @@ -import { sendEvent } from "../../../bus.js" -import { themeEditors } from "../../../explorerTree/tabHandler.js" -import { Options } from "../../../lib.js" -import { optionsThemeButtonHandler } from "../../../handlers/themesHandler.js" +import { sendEvent } from "../../../bus.js"; +import { themeEditors } from "../../../explorerTree/tabHandler.js"; +import { optionsThemeButtonHandler } from "../../../handlers/themesHandler.js"; +import { Options } from "../../../lib.js"; export function themeRegisterCallback({ name, data }) { - const themeSelectOptions = Options.edit("themeSelect") - themeSelectOptions.add(data.id, name) + const themeSelectOptions = Options.edit("themeSelect"); + themeSelectOptions.add(data.id, name); - const style = document.createElement("style") - style.id = `theme-${data.id}` - style.textContent = `body[theme="${data.id}"] { ${data.variables} }` + const style = document.createElement("style"); + style.id = `theme-${data.id}`; + style.textContent = `body[theme="${data.id}"] { ${data.variables} }`; - document.head.appendChild(style) + document.head.appendChild(style); - optionsThemeButtonHandler(themeSelectOptions) + optionsThemeButtonHandler(themeSelectOptions); - themeEditors.add(data.id, data.editorTheme) + themeEditors.add(data.id, data.editorTheme); - sendEvent("new-theme-register", { id: data.id, name: name }) -} \ No newline at end of file + sendEvent("new-theme-register", { id: data.id, name }); +} diff --git a/assets/js/extensionsHandler/extensionEventsHandler.js b/assets/js/extensionsHandler/extensionEventsHandler.js index cdf0913..44d114a 100644 --- a/assets/js/extensionsHandler/extensionEventsHandler.js +++ b/assets/js/extensionsHandler/extensionEventsHandler.js @@ -1,94 +1,105 @@ -import { Options, Languages, Dirs, escapeHtml, createNotify, TopBarElement, idify } from "../lib.js" -import { optionsThemeButtonHandler } from "../handlers/themesHandler.js" -import { themeEditors } from "../explorerTree/tabHandler.js" -import { bus, sendEvent } from "../../js/bus.js" -import { disableErrors, enableErrors } from "../handlers/bottomTabHandler.js" +import { bus, sendEvent } from "../../js/bus.js"; +import { themeEditors } from "../explorerTree/tabHandler.js"; +import { disableErrors, enableErrors } from "../handlers/bottomTabHandler.js"; +import { optionsThemeButtonHandler } from "../handlers/themesHandler.js"; +import { + createNotify, + Dirs, + escapeHtml, + idify, + Languages, + Options, + TopBarElement, +} from "../lib.js"; +import { onLocalizationRegister } from "./events/app/onLocalizationRegister.js"; +import { onNotificationCallback } from "./events/app/onNotification.js"; +import { onEditorChangeNewHLRulesCallback } from "./events/editor/onEditorChangeNewHLRules.js"; +import { onFilenamesRegister } from "./events/editor/onFilenamesRegister.js"; +import { onLanguageRegisterCallback } from "./events/editor/onLanguageRegister.js"; +import { onNewDirIconRegisterCallback } from "./events/editor/onNewDirIconRegister.js"; +import { onNewDocumentationRegisterCallback } from "./events/editor/onNewDocumentationRegister.js"; +import { onNewFileExtensionsRegister } from "./events/editor/onNewFileExtensionsRegister.js"; +import { onTemplatesRegister } from "./events/editor/onTemplatesRegister.js"; +import { onElementCreate } from "./events/ui/onElementCreate.js"; +import { onElementMod } from "./events/ui/onElementMod.js"; +import { onLoadCSSCallback } from "./events/ui/onLoadCSS.js"; +import { themeRegisterCallback } from "./events/ui/onThemeRegister.js"; -import { themeRegisterCallback } from "./events/ui/onThemeRegister.js" -import { onLoadCSSCallback } from "./events/ui/onLoadCSS.js" -import { onLanguageRegisterCallback } from "./events/editor/onLanguageRegister.js" -import { onNewFileExtensionsRegister } from "./events/editor/onNewFileExtensionsRegister.js" -import { onNewDirIconRegisterCallback } from "./events/editor/onNewDirIconRegister.js" -import { onEditorChangeNewHLRulesCallback } from "./events/editor/onEditorChangeNewHLRules.js" -import { onNotificationCallback } from "./events/app/onNotification.js" -import { onNewDocumentationRegisterCallback } from "./events/editor/onNewDocumentationRegister.js" -import { onLocalizationRegister } from "./events/app/onLocalizationRegister.js" -import { onFilenamesRegister } from "./events/editor/onFilenamesRegister.js" -import { onElementCreate } from "./events/ui/onElementCreate.js" -import { onElementMod } from "./events/ui/onElementMod.js" -import { onTemplatesRegister } from "./events/editor/onTemplatesRegister.js" +const preloadapi = window.electron; +const extapi = preloadapi.ext; -const preloadapi = window.electron -const extapi = preloadapi.ext - -const contexts = {} -let currentEditor = null +const contexts = {}; +const currentEditor = null; export function handleExtensionEvents() { - const audioProvider = new Audio() - audioProvider.preload = "auto" + const audioProvider = new Audio(); + audioProvider.preload = "auto"; extapi.app.onLog((name, text) => { - console.log(`[LOG FROM "${name}"] ${text}`) - }) + console.log(`[LOG FROM "${name}"] ${text}`); + }); extapi.ui.theme.onRegister((name, data) => { - themeRegisterCallback({ name: name, data: data }) - }) + themeRegisterCallback({ name, data }); + }); extapi.ui.css.onLoad((id, content) => { - onLoadCSSCallback({ id: id, content: content }) - }) - extapi.ui.element.onCreate(data => { - onElementCreate(data) - }) - extapi.ui.element.onMod(data => { - onElementMod(data, { TopBarElement, idify }) - }) + onLoadCSSCallback({ id, content }); + }); + extapi.ui.element.onCreate((data) => { + onElementCreate(data); + }); + extapi.ui.element.onMod((data) => { + onElementMod(data, { TopBarElement, idify }); + }); - extapi.editor.docs.onRegister(data => { - onNewDocumentationRegisterCallback({ data: data }) - }) + extapi.editor.docs.onRegister((data) => { + onNewDocumentationRegisterCallback({ data }); + }); extapi.editor.language.onRegister(async (data) => { - onLanguageRegisterCallback({ data: data }) - }) - extapi.editor.dir.onIconsRegister(data => { - onNewDirIconRegisterCallback({ data: data }) - }) - extapi.editor.language.onChangeHLRules(data => { - onEditorChangeNewHLRulesCallback({ data: data, contexts: contexts, refreshEditorHighlight: refreshEditorHighlight }) - }) - extapi.editor.filenames.onRegister(data => { - onFilenamesRegister(data) - }) - extapi.editor.fileExtensions.onRegister(data => { - onNewFileExtensionsRegister(data) - }) - extapi.editor.templates.onRegister(data => { - onTemplatesRegister(data) - }) + onLanguageRegisterCallback({ data }); + }); + extapi.editor.dir.onIconsRegister((data) => { + onNewDirIconRegisterCallback({ data }); + }); + extapi.editor.language.onChangeHLRules((data) => { + onEditorChangeNewHLRulesCallback({ + data, + contexts, + refreshEditorHighlight, + }); + }); + extapi.editor.filenames.onRegister((data) => { + onFilenamesRegister(data); + }); + extapi.editor.fileExtensions.onRegister((data) => { + onNewFileExtensionsRegister(data); + }); + extapi.editor.templates.onRegister((data) => { + onTemplatesRegister(data); + }); extapi.app.onNotification((name, data) => { - onNotificationCallback({ data: data, name: name }) - }) - extapi.app.onLocalizationRegister(data => { - onLocalizationRegister(data) - }) + onNotificationCallback({ data, name }); + }); + extapi.app.onLocalizationRegister((data) => { + onLocalizationRegister(data); + }); + + extapi.app.onAudioPlay((data) => { + const path = data.path; + const volume = data.volume; + const speed = data.speed; - extapi.app.onAudioPlay(data => { - const path = data.path - let volume = data.volume - let speed = data.speed - - audioProvider.src = path - audioProvider.load() + audioProvider.src = path; + audioProvider.load(); - audioProvider.volume = volume - audioProvider.playbackRate = speed + audioProvider.volume = volume; + audioProvider.playbackRate = speed; audioProvider.addEventListener("loadedmetadata", () => { - if(audioProvider.duration < 31) { - audioProvider.play() + if (audioProvider.duration < 31) { + audioProvider.play(); } - }) - }) -} \ No newline at end of file + }); + }); +} diff --git a/assets/js/extensionsHandler/extensionsHandler.js b/assets/js/extensionsHandler/extensionsHandler.js index 325e39d..8e195d7 100644 --- a/assets/js/extensionsHandler/extensionsHandler.js +++ b/assets/js/extensionsHandler/extensionsHandler.js @@ -1,22 +1,28 @@ -import { createNotify, getAllCSSVariables, normalizePath } from "../lib.js" -import { sendDebugMsg, sendDebugError, sendDebugWarn, sendDebugModuleInfo, sendDebugMarking } from "../handlers/debuggerSignalHandlers.js" -import { handleExtensionEvents } from "./extensionEventsHandler.js" -import { Modal } from "../modalsHandler/engine.js" -import { bus } from "../bus.js" - -const installedExtensionModalData = [] -const extensionErrors = {} +import { bus } from "../bus.js"; +import { + sendDebugError, + sendDebugMarking, + sendDebugModuleInfo, + sendDebugMsg, + sendDebugWarn, +} from "../handlers/debuggerSignalHandlers.js"; +import { createNotify, getAllCSSVariables, normalizePath } from "../lib.js"; +import { Modal } from "../modalsHandler/engine.js"; +import { handleExtensionEvents } from "./extensionEventsHandler.js"; + +const installedExtensionModalData = []; +const extensionErrors = {}; const RISKY_PERMISSIONS = [ "shell.run", "shell.exec", "shell.kill", "window.create", - "window.close" -] + "window.close", +]; function hasRiskyPermissions(permissions) { - return permissions.filter(p => RISKY_PERMISSIONS.includes(p)) + return permissions.filter((p) => RISKY_PERMISSIONS.includes(p)); } function showRiskyPermissionWarning({ displayName, name, riskyPerms }) { @@ -43,95 +49,118 @@ function showRiskyPermissionWarning({ displayName, name, riskyPerms }) {
- ` - } - ] - } - ] - }) - - modal.open() - - const noBtn = modal.el.querySelector("#perm-warning-no") - const yesBtn = modal.el.querySelector("#perm-warning-yes") - - if (noBtn) noBtn.addEventListener("click", () => { - modal.close() - modal.destroy() - resolve(false) - }) - if (yesBtn) yesBtn.addEventListener("click", () => { - modal.close() - modal.destroy() - resolve(true) - }) - }) + `, + }, + ], + }, + ], + }); + + modal.open(); + + const noBtn = modal.el.querySelector("#perm-warning-no"); + const yesBtn = modal.el.querySelector("#perm-warning-yes"); + + if (noBtn) + noBtn.addEventListener("click", () => { + modal.close(); + modal.destroy(); + resolve(false); + }); + if (yesBtn) + yesBtn.addEventListener("click", () => { + modal.close(); + modal.destroy(); + resolve(true); + }); + }); } -const VALID_PLATFORMS = ["windows", "win", "macos", "mac", "linux", "lin", "all"] -const PLATFORM_ALIASES = { win: "windows", mac: "macos", lin: "linux", win32: "windows", darwin: "macos" } +const VALID_PLATFORMS = ["windows", "win", "macos", "mac", "linux", "lin", "all"]; +const PLATFORM_ALIASES = { + win: "windows", + mac: "macos", + lin: "linux", + win32: "windows", + darwin: "macos", +}; function normalizePlatform(p) { - return PLATFORM_ALIASES[p] || p + return PLATFORM_ALIASES[p] || p; } function isPlatformCompatible(platformArray, currentPlatform) { - const normalized = platformArray.map(normalizePlatform) - const normalizedCurrent = normalizePlatform(currentPlatform) - if (normalized.includes("all")) return true - return normalized.includes(normalizedCurrent) + const normalized = platformArray.map(normalizePlatform); + const normalizedCurrent = normalizePlatform(currentPlatform); + if (normalized.includes("all")) return true; + return normalized.includes(normalizedCurrent); } function checkPackage(object) { if (!object || Object.keys(object).length === 0) { - return { success: false, msg: "File missing or empty" } + return { success: false, msg: "File missing or empty" }; } - const requireFields = ["version", "name", "displayName", "main", "permissions", "description", "activeOn", "platform"] + const requireFields = [ + "version", + "name", + "displayName", + "main", + "permissions", + "description", + "activeOn", + "platform", + ]; for (const f of requireFields) { if (!(f in object)) { - return { success: false, msg: `Missing field: ${f}` } + return { success: false, msg: `Missing field: ${f}` }; } } - const platform = object.platform + const platform = object.platform; if (typeof platform === "string") { if (!VALID_PLATFORMS.includes(platform)) { - return { success: false, msg: `Invalid platform "${platform}". Valid: ${VALID_PLATFORMS.join(", ")}` } + return { + success: false, + msg: `Invalid platform "${platform}". Valid: ${VALID_PLATFORMS.join(", ")}`, + }; } - object.platform = [platform] + object.platform = [platform]; } else if (Array.isArray(platform)) { if (platform.length === 0) { - return { success: false, msg: "Field 'platform' must be a non-empty array" } + return { success: false, msg: "Field 'platform' must be a non-empty array" }; } for (const p of platform) { if (!VALID_PLATFORMS.includes(p)) { - return { success: false, msg: `Invalid platform "${p}". Valid: ${VALID_PLATFORMS.join(", ")}` } + return { + success: false, + msg: `Invalid platform "${p}". Valid: ${VALID_PLATFORMS.join(", ")}`, + }; } } } else { - return { success: false, msg: "Field 'platform' must be a string or array" } + return { success: false, msg: "Field 'platform' must be a string or array" }; } - return { success: true, msg: "All fine" } + return { success: true, msg: "All fine" }; } function checkModulePackage(object) { if (!object || Object.keys(object).length === 0) { - return { success: false, msg: "File missing or empty" } + return { success: false, msg: "File missing or empty" }; } - const requireFields = ["version", "name", "displayName", "description", "main", "permissions"] + const requireFields = ["version", "name", "displayName", "description", "main", "permissions"]; for (const f of requireFields) { if (!(f in object)) { - return { success: false, msg: `Missing field: ${f}` } + return { success: false, msg: `Missing field: ${f}` }; } } - return { success: true, msg: "All fine" } + return { success: true, msg: "All fine" }; } function notifyError({ name, content }) { @@ -139,14 +168,14 @@ function notifyError({ name, content }) { type: "danger", icon: "error", title: `Extension "${name}" have errors. Check Debugger for more info`, - content: content - }) + content, + }); } function renderExtensionsModal(properties) { - Modal.destroy("installedExtensions") + Modal.destroy("installedExtensions"); - const items = properties == undefined ? [{ type: "centered", icon: "extension" }] : properties + const items = properties == undefined ? [{ type: "centered", icon: "extension" }] : properties; Modal.create({ id: "installedExtensions", @@ -158,39 +187,39 @@ function renderExtensionsModal(properties) { { type: "row", classList: ["background"], - items: items + items, }, - ] - }) + ], + }); } export async function initExtensions() { - handleExtensionEvents() - renderExtensionsModal() + handleExtensionEvents(); + renderExtensionsModal(); document.querySelector("#extensionsAll")?.addEventListener("click", () => { - Modal.get("installedExtensions")?.open() - }) + Modal.get("installedExtensions")?.open(); + }); - const extensionsRequest = await window.electron.requestExtensions() - const extensionsDir = await window.electron.getExtensionsDir() + const extensionsRequest = await window.electron.requestExtensions(); + const extensionsDir = await window.electron.getExtensionsDir(); - if (!extensionsRequest.success) return + if (!extensionsRequest.success) return; - const names = extensionsRequest.result - const settings = await window.electron.readSettings() - const currentPlatform = await window.electron.getPlatform() - const disabledExtensions = settings?.extensions?.disabledExtensions || [] + const names = extensionsRequest.result; + const settings = await window.electron.readSettings(); + const currentPlatform = await window.electron.getPlatform(); + const disabledExtensions = settings?.extensions?.disabledExtensions || []; // PROCEED EACH EXT for (const name of names) { - const extensionRequest = await window.electron.requestExtension(name) + const extensionRequest = await window.electron.requestExtension(name); if (!extensionRequest.success) { - notifyError({ name: name, content: extensionRequest.result }) - sendDebugError(`(Extension) ${name}: load error. ${extensionRequest.result}`) - if (!extensionErrors[name]) extensionErrors[name] = [] - extensionErrors[name].push(extensionRequest.result) + notifyError({ name, content: extensionRequest.result }); + sendDebugError(`(Extension) ${name}: load error. ${extensionRequest.result}`); + if (!extensionErrors[name]) extensionErrors[name] = []; + extensionErrors[name].push(extensionRequest.result); installedExtensionModalData.push( createInstalledExtensionsModalTemplate({ @@ -201,24 +230,24 @@ export async function initExtensions() { permissions: new Set(), path: "", extensionName: name, - enabled: true - }) - ) - continue + enabled: true, + }), + ); + continue; } - let extensionFinalContent = "" - let allPermissions = new Set() + const extensionFinalContent = ""; + const allPermissions = new Set(); - let extensionPackage = extensionRequest.result.package - let extensionPath = extensionRequest.result.path - let extensionPackageCheck = checkPackage(extensionPackage) + const extensionPackage = extensionRequest.result.package; + const extensionPath = extensionRequest.result.path; + const extensionPackageCheck = checkPackage(extensionPackage); if (!extensionPackageCheck.success) { - notifyError({ name: name, content: extensionPackageCheck.msg }) - sendDebugError(`(Extension) ${name}: package.json error. ${extensionPackageCheck.msg}`) - if (!extensionErrors[name]) extensionErrors[name] = [] - extensionErrors[name].push(extensionPackageCheck.msg) + notifyError({ name, content: extensionPackageCheck.msg }); + sendDebugError(`(Extension) ${name}: package.json error. ${extensionPackageCheck.msg}`); + if (!extensionErrors[name]) extensionErrors[name] = []; + extensionErrors[name].push(extensionPackageCheck.msg); installedExtensionModalData.push( createInstalledExtensionsModalTemplate({ @@ -229,31 +258,31 @@ export async function initExtensions() { permissions: new Set(), path: extensionPath, extensionName: name, - enabled: true - }) - ) - continue + enabled: true, + }), + ); + continue; } - let version = extensionPackage.version - let icon = extensionPackage.icon != undefined ? extensionPackage.icon : false - let description = extensionPackage.description - let displayName = extensionPackage.displayName - let main = extensionPackage.main - let permissions = extensionPackage.permissions || [] - let activeOn = extensionPackage.activeOn + const version = extensionPackage.version; + const icon = extensionPackage.icon == undefined ? false : extensionPackage.icon; + const description = extensionPackage.description; + const displayName = extensionPackage.displayName; + const main = extensionPackage.main; + const permissions = extensionPackage.permissions || []; + const activeOn = extensionPackage.activeOn; + + permissions.forEach((p) => allPermissions.add(p)); - permissions.forEach(p => allPermissions.add(p)) + const permissionsArray = [...allPermissions]; - const permissionsArray = [...allPermissions] - - let isDev = false + let isDev = false; if ("app" in settings && "devMode" in settings.app) { - isDev = settings.app.devMode + isDev = settings.app.devMode; } - const isEnabled = !disabledExtensions.includes(name) + const isEnabled = !disabledExtensions.includes(name); // add extension to the list @@ -261,115 +290,114 @@ export async function initExtensions() { createInstalledExtensionsModalTemplate({ title: displayName, subtitle: `${name} (${version})`, - description: description, + description, image: icon ? `${normalizePath(extensionPath)}/${icon}` : name, permissions: allPermissions, path: extensionPath, extensionName: name, settings: extensionPackage.settings, - enabled: isEnabled - }) - ) + enabled: isEnabled, + }), + ); if (!isEnabled) { - sendDebugWarn(`${name}: extension disabled by user`) - continue + sendDebugWarn(`${name}: extension disabled by user`); + continue; } - if(!Array.isArray(activeOn)) { - sendDebugError(`${name}: activeOn key in package.json must be array`) + if (!Array.isArray(activeOn)) { + sendDebugError(`${name}: activeOn key in package.json must be array`); } - let extensionMainFileContentRes = await window.electron.readFile(`/${name}/${main}.js`, extensionsDir) + const extensionMainFileContentRes = await window.electron.readFile( + `/${name}/${main}.js`, + extensionsDir, + ); if (!extensionMainFileContentRes.success) { - notifyError({ name: displayName, content: extensionMainFileContentRes.result }) + notifyError({ name: displayName, content: extensionMainFileContentRes.result }); } - sendDebugMarking() - sendDebugMsg(`${name}: package.json loaded successfully\nPermissions: ${permissions.length > 0 ? permissions.join(", ") : "none"}`) - sendDebugMsg(`${name}: ${main}.js loaded`) + sendDebugMarking(); + sendDebugMsg( + `${name}: package.json loaded successfully\nPermissions: ${permissions.length > 0 ? permissions.join(", ") : "none"}`, + ); + sendDebugMsg(`${name}: ${main}.js loaded`); createNotify({ type: "success", icon: "check", title: `Extension "${displayName}" successfully added`, - content: `Version: ${version}` - }) + content: `Version: ${version}`, + }); // register providers in package.json - if("language.register" in extensionPackage) { - const languageRegisterConfig = extensionPackage["language.register"] + if ("language.register" in extensionPackage) { + const languageRegisterConfig = extensionPackage["language.register"]; - if(languageRegisterConfig.length > 0) { - window.electron.ext.editor.language.register( - { - configPath: languageRegisterConfig, - extensionPath: normalizePath(extensionPath), - extensionName: name - } - ) + if (languageRegisterConfig.length > 0) { + window.electron.ext.editor.language.register({ + configPath: languageRegisterConfig, + extensionPath: normalizePath(extensionPath), + extensionName: name, + }); } } - if("docs.register" in extensionPackage) { - const docsRegisterConfig = extensionPackage["docs.register"] - - if(docsRegisterConfig.length > 0) { - window.electron.ext.editor.docs.register( - { - configPath: docsRegisterConfig, - extensionPath: normalizePath(extensionPath), - extensionName: name - } - ) + if ("docs.register" in extensionPackage) { + const docsRegisterConfig = extensionPackage["docs.register"]; + + if (docsRegisterConfig.length > 0) { + window.electron.ext.editor.docs.register({ + configPath: docsRegisterConfig, + extensionPath: normalizePath(extensionPath), + extensionName: name, + }); } } - if("filenames.register" in extensionPackage) { - const filenamesConfig = extensionPackage["filenames.register"] - - if(filenamesConfig.length > 0) { - window.electron.ext.editor.filenames.register( - { - configPath: filenamesConfig, - extensionPath: normalizePath(extensionPath), - extensionName: name - } - ) + if ("filenames.register" in extensionPackage) { + const filenamesConfig = extensionPackage["filenames.register"]; + + if (filenamesConfig.length > 0) { + window.electron.ext.editor.filenames.register({ + configPath: filenamesConfig, + extensionPath: normalizePath(extensionPath), + extensionName: name, + }); } } - if("fileExtensions.register" in extensionPackage) { - const fileExtensionsConfig = extensionPackage["fileExtensions.register"] - - if(fileExtensionsConfig.length > 0) { - window.electron.ext.editor.fileExtensions.register( - { - configPath: fileExtensionsConfig, - extensionPath: normalizePath(extensionPath), - extensionName: name - } - ) + if ("fileExtensions.register" in extensionPackage) { + const fileExtensionsConfig = extensionPackage["fileExtensions.register"]; + + if (fileExtensionsConfig.length > 0) { + window.electron.ext.editor.fileExtensions.register({ + configPath: fileExtensionsConfig, + extensionPath: normalizePath(extensionPath), + extensionName: name, + }); } } - if("templates.register" in extensionPackage) { - const templatesConfig = extensionPackage["templates.register"] - - if(templatesConfig.length > 0) { - window.electron.ext.editor.templates.register( - { - configPath: templatesConfig, - extensionPath: normalizePath(extensionPath), - extensionName: name - } - ) + if ("templates.register" in extensionPackage) { + const templatesConfig = extensionPackage["templates.register"]; + + if (templatesConfig.length > 0) { + window.electron.ext.editor.templates.register({ + configPath: templatesConfig, + extensionPath: normalizePath(extensionPath), + extensionName: name, + }); } } - + // platform check - const extPlatforms = Array.isArray(extensionPackage.platform) ? extensionPackage.platform : [extensionPackage.platform] + const extPlatforms = Array.isArray(extensionPackage.platform) + ? extensionPackage.platform + : [extensionPackage.platform]; if (!isPlatformCompatible(extPlatforms, currentPlatform)) { - sendDebugWarn(`${name}: skipped — not compatible with ${currentPlatform} (supports: ${extPlatforms.join(", ")})`) - continue + sendDebugWarn( + `${name}: skipped — not compatible with ${currentPlatform} (supports: ${extPlatforms.join(", ")})`, + ); + continue; } // activation events @@ -378,57 +406,59 @@ export async function initExtensions() { language: (name, onActivate) => { const handler = (data) => { - const mode = data.detail.editor.getCurrentLanguage() + const mode = data.detail.editor.getCurrentLanguage(); if (mode === name) { - onActivate() + onActivate(); } - } + }; - bus.addEventListener("file-opened-event", handler) + bus.addEventListener("file-opened-event", handler); return () => { - bus.removeEventListener("file-opened-event", handler) - } - } - } + bus.removeEventListener("file-opened-event", handler); + }; + }, + }; - activeOn.forEach(event => { - const [eventName, ...args] = event.split(":").map(s => s.trim()) + activeOn.forEach((event) => { + const [eventName, ...args] = event.split(":").map((s) => s.trim()); if (eventName === "load") { - runExtension() + runExtension(); } if (eventName === "language") { activeOnEvents.language(args[0], () => { - runExtension() - }) + runExtension(); + }); } - }) - // - + }); + // + async function runExtension() { - const riskyPerms = hasRiskyPermissions(permissionsArray) + const riskyPerms = hasRiskyPermissions(permissionsArray); if (riskyPerms.length > 0) { - const disableWarning = settings?.extensions?.disableRiskyPermissionWarning === true + const disableWarning = settings?.extensions?.disableRiskyPermissionWarning === true; if (!disableWarning) { const approved = await showRiskyPermissionWarning({ - displayName: displayName, - name: name, - riskyPerms: riskyPerms - }) + displayName, + name, + riskyPerms, + }); if (!approved) { - sendDebugWarn(`${name}: extension disabled by user (risky permissions declined)`) - return + sendDebugWarn( + `${name}: extension disabled by user (risky permissions declined)`, + ); + return; } } } - const extSettingsValues = settings?.extensions?.[name] || {} + const extSettingsValues = settings?.extensions?.[name] || {}; const runResult = await window.electron.runExtension( extensionMainFileContentRes.result, @@ -436,115 +466,129 @@ export async function initExtensions() { { extensionName: name, extensionVersion: version, - extensionPath: extensionPath, - isDev: isDev, + extensionPath, + isDev, allCSSVariables: getAllCSSVariables(), - activeOn: activeOn, - extensionSettings: extSettingsValues - } - ) + activeOn, + extensionSettings: extSettingsValues, + }, + ); - sendDebugMarking() - sendDebugWarn(`Currently, the "${name}" extension and all modules connected to it use special permissions: ${permissionsArray.join(", ")}`) + sendDebugMarking(); + sendDebugWarn( + `Currently, the "${name}" extension and all modules connected to it use special permissions: ${permissionsArray.join(", ")}`, + ); if (!runResult.success) { - sendDebugError(`${name} runtime error: ${runResult.error}`) + sendDebugError(`${name} runtime error: ${runResult.error}`); } } } - renderExtensionsModal(installedExtensionModalData) + renderExtensionsModal(installedExtensionModalData); } function showExtensionErrors(extensionName) { - const errors = extensionErrors[extensionName] || [] - if (errors.length === 0) return + const errors = extensionErrors[extensionName] || []; + if (errors.length === 0) return; - const existing = document.getElementById("extensionErrorsPopup") - if (existing) existing.remove() + const existing = document.getElementById("extensionErrorsPopup"); + if (existing) existing.remove(); - const wrapper = document.createElement("div") - wrapper.id = "extensionErrorsPopup" - wrapper.style.cssText = "position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.4);backdrop-filter:blur(4px);animation:fadeIn .15s ease" + const wrapper = document.createElement("div"); + wrapper.id = "extensionErrorsPopup"; + wrapper.style.cssText = + "position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.4);backdrop-filter:blur(4px);animation:fadeIn .15s ease"; - const modal = document.createElement("div") - modal.className = "modal confirm" - modal.style.cssText = "background:var(--body-color);color:var(--text-color);position:relative;border-radius:15px;overflow:hidden;border:1px solid var(--block-divider-border-color);width:400px;height:auto;min-height:160px;max-height:350px;display:flex;flex-direction:column" + const modal = document.createElement("div"); + modal.className = "modal confirm"; + modal.style.cssText = + "background:var(--body-color);color:var(--text-color);position:relative;border-radius:15px;overflow:hidden;border:1px solid var(--block-divider-border-color);width:400px;height:auto;min-height:160px;max-height:350px;display:flex;flex-direction:column"; - const body = document.createElement("div") - body.style.cssText = "flex:1;overflow-y:auto;padding:20px;padding-bottom:0" + const body = document.createElement("div"); + body.style.cssText = "flex:1;overflow-y:auto;padding:20px;padding-bottom:0"; - const title = document.createElement("div") - title.className = "confirm-title" - title.textContent = `Errors — ${extensionName}` + const title = document.createElement("div"); + title.className = "confirm-title"; + title.textContent = `Errors — ${extensionName}`; - const desc = document.createElement("div") - desc.className = "confirm-desc" + const desc = document.createElement("div"); + desc.className = "confirm-desc"; - const errorList = document.createElement("div") - errorList.style.cssText = "margin-top:8px;display:flex;flex-direction:column;gap:6px" + const errorList = document.createElement("div"); + errorList.style.cssText = "margin-top:8px;display:flex;flex-direction:column;gap:6px"; errors.forEach((err, i) => { - const item = document.createElement("div") - item.className = "extension-error-item" - item.textContent = `${i + 1}. ${err}` - errorList.appendChild(item) - }) - - desc.appendChild(errorList) - body.appendChild(title) - body.appendChild(desc) - - const btnWrapper = document.createElement("div") - btnWrapper.style.cssText = "display:flex;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--block-divider-border-color)" - - const btnStyle = "background:var(--block-divider-border-color);border:none;color:var(--text-color);padding:8px 12px;border-radius:5px;transition:.2s;cursor:pointer;font-family:inherit;font-size:13px" - - const copyBtn = document.createElement("button") - copyBtn.textContent = "Copy" - copyBtn.style.cssText = btnStyle + const item = document.createElement("div"); + item.className = "extension-error-item"; + item.textContent = `${i + 1}. ${err}`; + errorList.appendChild(item); + }); + + desc.appendChild(errorList); + body.appendChild(title); + body.appendChild(desc); + + const btnWrapper = document.createElement("div"); + btnWrapper.style.cssText = + "display:flex;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--block-divider-border-color)"; + + const btnStyle = + "background:var(--block-divider-border-color);border:none;color:var(--text-color);padding:8px 12px;border-radius:5px;transition:.2s;cursor:pointer;font-family:inherit;font-size:13px"; + + const copyBtn = document.createElement("button"); + copyBtn.textContent = "Copy"; + copyBtn.style.cssText = btnStyle; copyBtn.addEventListener("click", () => { - navigator.clipboard.writeText(errors.join("\n")) - createNotify({ type: "success", icon: "check", title: "Errors copied to clipboard" }) - }) - copyBtn.addEventListener("mouseenter", () => { copyBtn.style.opacity = ".5" }) - copyBtn.addEventListener("mouseleave", () => { copyBtn.style.opacity = "1" }) - - const closeBtn = document.createElement("button") - closeBtn.textContent = "Close" - closeBtn.style.cssText = btnStyle - closeBtn.addEventListener("click", () => wrapper.remove()) - closeBtn.addEventListener("mouseenter", () => { closeBtn.style.opacity = ".5" }) - closeBtn.addEventListener("mouseleave", () => { closeBtn.style.opacity = "1" }) - - btnWrapper.appendChild(copyBtn) - btnWrapper.appendChild(closeBtn) - - modal.appendChild(body) - modal.appendChild(btnWrapper) - wrapper.appendChild(modal) + navigator.clipboard.writeText(errors.join("\n")); + createNotify({ type: "success", icon: "check", title: "Errors copied to clipboard" }); + }); + copyBtn.addEventListener("mouseenter", () => { + copyBtn.style.opacity = ".5"; + }); + copyBtn.addEventListener("mouseleave", () => { + copyBtn.style.opacity = "1"; + }); + + const closeBtn = document.createElement("button"); + closeBtn.textContent = "Close"; + closeBtn.style.cssText = btnStyle; + closeBtn.addEventListener("click", () => wrapper.remove()); + closeBtn.addEventListener("mouseenter", () => { + closeBtn.style.opacity = ".5"; + }); + closeBtn.addEventListener("mouseleave", () => { + closeBtn.style.opacity = "1"; + }); + + btnWrapper.appendChild(copyBtn); + btnWrapper.appendChild(closeBtn); + + modal.appendChild(body); + modal.appendChild(btnWrapper); + wrapper.appendChild(modal); wrapper.addEventListener("click", (e) => { - if (e.target === wrapper) wrapper.remove() - }) + if (e.target === wrapper) wrapper.remove(); + }); - document.body.appendChild(wrapper) + document.body.appendChild(wrapper); } async function showExtensionSettings(extensionName, settingsDef, extensionPath) { - const configPath = `${normalizePath(extensionPath)}/config.json` - let currentValues = {} + const configPath = `${normalizePath(extensionPath)}/config.json`; + let currentValues = {}; try { - const configRes = await window.electron.readFileContent(configPath) - if (configRes) currentValues = JSON.parse(configRes) + const configRes = await window.electron.readFileContent(configPath); + if (configRes) currentValues = JSON.parse(configRes); } catch (e) { - settingsDef.forEach(s => { - if (s.default !== undefined) currentValues[s.id] = s.default - }) - await window.electron.saveFile(configPath, JSON.stringify(currentValues, null, 4)) + settingsDef.forEach((s) => { + if (s.default !== undefined) currentValues[s.id] = s.default; + }); + await window.electron.saveFile(configPath, JSON.stringify(currentValues, null, 4)); } - Modal.destroy(`extSettings_${extensionName}`) + Modal.destroy(`extSettings_${extensionName}`); const modal = Modal.create({ id: `extSettings_${extensionName}`, @@ -556,16 +600,16 @@ async function showExtensionSettings(extensionName, settingsDef, extensionPath) { type: "row", classList: ["background"], - items: settingsDef.map(s => { - const val = currentValues[s.id] ?? s.default + items: settingsDef.map((s) => { + const val = currentValues[s.id] ?? s.default; if (s.type === "switch") { return { type: "switch", id: `ext_setting_${extensionName}_${s.id}`, title: s.title, description: s.description || "", - checked: !!val - } + checked: !!val, + }; } if (s.type === "range") { return { @@ -577,8 +621,8 @@ async function showExtensionSettings(extensionName, settingsDef, extensionPath) max: s.max ?? 100, value: val ?? s.default ?? 0, step: s.step ?? 1, - prefix: s.prefix || "" - } + prefix: s.prefix || "", + }; } if (s.type === "input") { return { @@ -586,8 +630,8 @@ async function showExtensionSettings(extensionName, settingsDef, extensionPath) id: `ext_setting_${extensionName}_${s.id}`, title: s.title, description: s.description || "", - placeholder: s.placeholder || "" - } + placeholder: s.placeholder || "", + }; } if (s.type === "dropdown") { return { @@ -596,133 +640,153 @@ async function showExtensionSettings(extensionName, settingsDef, extensionPath) title: s.title, description: s.description || "", options: s.options || [], - selected: val ?? s.default ?? "" - } + selected: val ?? s.default ?? "", + }; } - return { type: "placeholder", title: s.title || "Unknown" } - }) - } - ] - }) + return { type: "placeholder", title: s.title || "Unknown" }; + }), + }, + ], + }); - document.body.prepend(modal.el) - modal.zIndex(200000) + document.body.prepend(modal.el); + modal.zIndex(200_000); requestAnimationFrame(() => { requestAnimationFrame(() => { - modal.open() - }) - }) + modal.open(); + }); + }); - settingsDef.forEach(s => { - const input = document.querySelector(`#ext_setting_${extensionName}_${s.id}`) - if (!input) return + settingsDef.forEach((s) => { + const input = document.querySelector(`#ext_setting_${extensionName}_${s.id}`); + if (!input) return; if (s.type === "dropdown") { - const wrapper = input.closest(".options-selector__wrapper") || input + const wrapper = input.closest(".options-selector__wrapper") || input; wrapper.addEventListener("click", async () => { requestAnimationFrame(() => { - const selected = wrapper.querySelector(".options-selector__item[default]") + const selected = wrapper.querySelector(".options-selector__item[default]"); if (selected) { - currentValues[s.id] = selected.id - window.electron.saveFile(configPath, JSON.stringify(currentValues, null, 4)) + currentValues[s.id] = selected.id; + window.electron.saveFile( + configPath, + JSON.stringify(currentValues, null, 4), + ); } - }) - }) + }); + }); } else { - const eventType = s.type === "range" ? "change" : "input" + const eventType = s.type === "range" ? "change" : "input"; input.addEventListener(eventType, async () => { - const val = s.type === "switch" ? input.checked : input.value - currentValues[s.id] = val - await window.electron.saveFile(configPath, JSON.stringify(currentValues, null, 4)) - }) + const val = s.type === "switch" ? input.checked : input.value; + currentValues[s.id] = val; + await window.electron.saveFile(configPath, JSON.stringify(currentValues, null, 4)); + }); } if (s.type === "switch") { - input.checked = !!currentValues[s.id] + input.checked = !!currentValues[s.id]; } else if (s.type === "range") { - input.value = currentValues[s.id] ?? s.default ?? 0 + input.value = currentValues[s.id] ?? s.default ?? 0; } else if (s.type === "input") { - input.value = currentValues[s.id] ?? "" - if (input.value) input.classList.add("focused") + input.value = currentValues[s.id] ?? ""; + if (input.value) input.classList.add("focused"); } else if (s.type === "dropdown") { - const saved = currentValues[s.id] ?? s.default ?? "" + const saved = currentValues[s.id] ?? s.default ?? ""; if (saved) { - const item = input.querySelector(`.options-selector__item[id="${saved}"]`) + const item = input.querySelector(`.options-selector__item[id="${saved}"]`); if (item) { - input.querySelectorAll(".options-selector__item").forEach(el => el.removeAttribute("default")) - item.setAttribute("default", true) - input.querySelector("#current").textContent = item.querySelector("#option_name").textContent + input + .querySelectorAll(".options-selector__item") + .forEach((el) => el.removeAttribute("default")); + item.setAttribute("default", true); + input.querySelector("#current").textContent = + item.querySelector("#option_name").textContent; } } } - }) + }); } -function createInstalledExtensionsModalTemplate({ title, subtitle, description, image, permissions, path, extensionName, settings: extSettings, enabled }) { - const tags = [] +function createInstalledExtensionsModalTemplate({ + title, + subtitle, + description, + image, + permissions, + path, + extensionName, + settings: extSettings, + enabled, +}) { + const tags = []; for (const p of permissions) { tags.push({ type: "permission", - name: p - }) + name: p, + }); } - const buttons = [] + const buttons = []; if (extensionName && extensionErrors[extensionName]) { buttons.push({ icon: "error", classList: ["text-danger"], onclick: () => { - showExtensionErrors(extensionName) - } - }) + showExtensionErrors(extensionName); + }, + }); } if (extSettings && Array.isArray(extSettings) && extSettings.length > 0) { buttons.push({ icon: "settings", onclick: () => { - Modal.closeAll() + Modal.closeAll(); requestAnimationFrame(() => { - showExtensionSettings(extensionName, extSettings, path) - }) - } - }) + showExtensionSettings(extensionName, extSettings, path); + }); + }, + }); } buttons.push({ icon: "delete", onclick: (data) => { - data.element.remove() - window.electron.removeByPath(path) - } - }) + data.element.remove(); + window.electron.removeByPath(path); + }, + }); const template = { type: "extensionItem", - title: title, - subtitle: subtitle, - description: description, - image: image, - tags: tags, - buttons: buttons, - toggle: extensionName ? { - checked: enabled, - onChange: async (isChecked) => { - const settings = await window.electron.readSettings() - const disabled = settings?.extensions?.disabledExtensions || [] - let updated - if (isChecked) { - updated = disabled.filter(n => n !== extensionName) - } else { - updated = [...disabled, extensionName] - } - await window.electron.setSettings({ extensions: { disabledExtensions: updated } }) - } - } : null - } - - return template -} \ No newline at end of file + title, + subtitle, + description, + image, + tags, + buttons, + toggle: extensionName + ? { + checked: enabled, + onChange: async (isChecked) => { + const settings = await window.electron.readSettings(); + const disabled = settings?.extensions?.disabledExtensions || []; + let updated; + if (isChecked) { + updated = disabled.filter((n) => n !== extensionName); + } else { + updated = [...disabled, extensionName]; + } + await window.electron.setSettings({ + extensions: { disabledExtensions: updated }, + }); + }, + } + : null, + }; + + return template; +} diff --git a/assets/js/extensionsHandler/helpers/aceHover.js b/assets/js/extensionsHandler/helpers/aceHover.js index 6dd3719..2f1d317 100644 --- a/assets/js/extensionsHandler/helpers/aceHover.js +++ b/assets/js/extensionsHandler/helpers/aceHover.js @@ -1,138 +1,138 @@ -import { DocumentationTypes } from "./documentationTypes.js" -import { escapeHtml, truncateString } from "../../lib.js" -import { themeEditors } from "../../explorerTree/tabHandler.js" +import { themeEditors } from "../../explorerTree/tabHandler.js"; +import { escapeHtml, truncateString } from "../../lib.js"; +import { DocumentationTypes } from "./documentationTypes.js"; export function enableAceHover(editor, docs, props) { - const tooltip = document.createElement("div") - tooltip.classList.add("ace-documentation__tooltip", "hidden") - tooltip.style.position = "fixed" - tooltip.style.display = "none" - tooltip.style.zIndex = 9999 - tooltip.style.maxWidth = "800px" - tooltip.style.wordWrap = "break-word" + const tooltip = document.createElement("div"); + tooltip.classList.add("ace-documentation__tooltip", "hidden"); + tooltip.style.position = "fixed"; + tooltip.style.display = "none"; + tooltip.style.zIndex = 9999; + tooltip.style.maxWidth = "800px"; + tooltip.style.wordWrap = "break-word"; - document.body.appendChild(tooltip) + document.body.appendChild(tooltip); - let hoverTimeout = null - let hideTimeout = null - let markerId = null - let isTooltipHovered = false + let hoverTimeout = null; + let hideTimeout = null; + let markerId = null; + let isTooltipHovered = false; - const Range = ace.require("ace/range").Range + const Range = ace.require("ace/range").Range; - let lastText = null - let lastResult = null + let lastText = null; + let lastResult = null; const compiledDocs = Object.entries(docs).map(([key, value]) => { - let regex = null - let isRegex = false + let regex = null; + let isRegex = false; try { if (/[\\[\](){}.+*?^$]/.test(key)) { - regex = new RegExp(key) - isRegex = true + regex = new RegExp(key); + isRegex = true; } - } catch { } + } catch {} - return { key, value, regex, isRegex } - }) + return { key, value, regex, isRegex }; + }); function getWord(editor, pos) { - const session = editor.session - const line = session.getLine(pos.row) + const session = editor.session; + const line = session.getLine(pos.row); - let start = pos.column - let end = pos.column + let start = pos.column; + let end = pos.column; - const leftPart = line.slice(0, pos.column) - const tagStart = leftPart.lastIndexOf("<") - const tagEnd = leftPart.lastIndexOf(">") + const leftPart = line.slice(0, pos.column); + const tagStart = leftPart.lastIndexOf("<"); + const tagEnd = leftPart.lastIndexOf(">"); if (tagStart > tagEnd) { - start = tagStart + start = tagStart; - end = pos.column + end = pos.column; while (end < line.length && line[end] !== ">") { - end++ + end++; } - if (line[end] === ">") end++ + if (line[end] === ">") end++; - const text = line.slice(start, end) + const text = line.slice(start, end); return { text, - range: new Range(pos.row, start, pos.row, end) - } + range: new Range(pos.row, start, pos.row, end), + }; } - while (start > 0 && /[\w.$]/.test(line[start - 1])) start-- - while (end < line.length && /[\w.$()]/.test(line[end])) end++ + while (start > 0 && /[\w.$]/.test(line[start - 1])) start--; + while (end < line.length && /[\w.$()]/.test(line[end])) end++; - const text = line.slice(start, end) + const text = line.slice(start, end); return { text, - range: new Range(pos.row, start, pos.row, end) - } + range: new Range(pos.row, start, pos.row, end), + }; } function clearMarker() { if (markerId !== null) { - editor.session.removeMarker(markerId) - markerId = null + editor.session.removeMarker(markerId); + markerId = null; } } function highlight(range) { - clearMarker() - markerId = editor.session.addMarker(range, "ace_hover_marker", "text", false) + clearMarker(); + markerId = editor.session.addMarker(range, "ace_hover_marker", "text", false); } function findDocEntry(text) { - if (text === lastText) return lastResult + if (text === lastText) return lastResult; - const normalized = text.replace(/\(\)$/, "") + const normalized = text.replace(/\(\)$/, ""); // 1. exact for (const item of compiledDocs) { if (!item.isRegex && item.key === text) { - return (lastResult = { key: item.key, data: item.value, match: text }) + return (lastResult = { key: item.key, data: item.value, match: text }); } } // 2. normalized for (const item of compiledDocs) { if (!item.isRegex && item.key === normalized) { - return (lastResult = { key: item.key, data: item.value, match: normalized }) + return (lastResult = { key: item.key, data: item.value, match: normalized }); } if (!item.isRegex && item.key === normalized + "()") { - return (lastResult = { key: item.key, data: item.value, match: normalized + "()" }) + return (lastResult = { key: item.key, data: item.value, match: normalized + "()" }); } } // 3. regex for (const item of compiledDocs) { - if (!item.isRegex || !item.regex) continue + if (!(item.isRegex && item.regex)) continue; - const match = text.match(item.regex) + const match = text.match(item.regex); if (match) { return (lastResult = { key: item.key, data: item.value, - match: match[0] - }) + match: match[0], + }); } } - lastText = text - return (lastResult = null) + lastText = text; + return (lastResult = null); } function showTooltip(x, y, data, key, match) { - tooltip.classList.remove("hidden") + tooltip.classList.remove("hidden"); - const displayKey = data.displayAs || match || key + const displayKey = data.displayAs || match || key; tooltip.innerHTML = `
${escapeHtml(displayKey)}
@@ -141,33 +141,30 @@ export function enableAceHover(editor, docs, props) {
Description
${escapeHtml(data.description || "No description provided")}
- ` + `; - const docTypesArray = DocumentationTypes.list().map(item => item.name) + const docTypesArray = DocumentationTypes.list().map((item) => item.name); - if (data.type) { - if (docTypesArray.includes(data.type)) { - const type = DocumentationTypes.list().find(item => item.name === data.type) + if (data.type && docTypesArray.includes(data.type)) { + const type = DocumentationTypes.list().find((item) => item.name === data.type); - if (type) { - let tooltipKey = tooltip.querySelector(".ace-documentation__tooltip-key") - let tooltipType = tooltip.querySelector(".ace-documentation__tooltip-type") + if (type) { + const tooltipKey = tooltip.querySelector(".ace-documentation__tooltip-key"); + const tooltipType = tooltip.querySelector(".ace-documentation__tooltip-type"); - tooltipType.textContent = type.displayName + tooltipType.textContent = type.displayName; - if ("className" in type) { - tooltipKey.classList.add(type.className) - } - else { - tooltipKey.style.color = type.color - } + if ("className" in type) { + tooltipKey.classList.add(type.className); + } else { + tooltipKey.style.color = type.color; } } } if (data.example.length > 0) { - let exampleContent = escapeHtml(data.example) - exampleContent = truncateString(exampleContent, 300) + let exampleContent = escapeHtml(data.example); + exampleContent = truncateString(exampleContent, 300); tooltip.innerHTML += `
@@ -179,7 +176,7 @@ export function enableAceHover(editor, docs, props) { requestAnimationFrame(() => { const editor = ace.edit(tooltip.querySelector(`#${key}`)); - editor.setTheme(`ace/theme/${themeEditors.current.ace}`) + editor.setTheme(`ace/theme/${themeEditors.current.ace}`); editor.renderer.setPadding(0); editor.session.setUseWorker(false); @@ -189,9 +186,9 @@ export function enableAceHover(editor, docs, props) { editor.setHighlightActiveLine(false); editor.setOptions({ - maxLines: Infinity, + maxLines: Number.POSITIVE_INFINITY, minLines: 1, - autoScrollEditorIntoView: true + autoScrollEditorIntoView: true, }); editor.session.setMode(`ace/mode/${props.onMode}`); @@ -200,95 +197,98 @@ export function enableAceHover(editor, docs, props) { } if (data.sources.length > 0) { - let sources = data.sources.map(s => - `${escapeHtml(s.title)}` - ).join("") + const sources = data.sources + .map( + (s) => + `${escapeHtml(s.title)}`, + ) + .join(""); tooltip.innerHTML += `
Sources
${sources}
- ` + `; } - tooltip.style.display = "block" + tooltip.style.display = "block"; - const rect = tooltip.getBoundingClientRect() - const screenWidth = window.innerWidth + const rect = tooltip.getBoundingClientRect(); + const screenWidth = window.innerWidth; - let left = x - rect.width / 2 - if (left < 4) left = 4 - if (left + rect.width > screenWidth - 4) left = screenWidth - rect.width - 4 + let left = x - rect.width / 2; + if (left < 4) left = 4; + if (left + rect.width > screenWidth - 4) left = screenWidth - rect.width - 4; - let top = y - rect.height - 8 - if (top < 4) top = y + 8 + let top = y - rect.height - 8; + if (top < 4) top = y + 8; - tooltip.style.left = left + "px" - tooltip.style.top = top + "px" + tooltip.style.left = left + "px"; + tooltip.style.top = top + "px"; } function hideTooltip() { - clearTimeout(hideTimeout) + clearTimeout(hideTimeout); hideTimeout = setTimeout(() => { if (!isTooltipHovered) { - tooltip.classList.add("hidden") - clearMarker() + tooltip.classList.add("hidden"); + clearMarker(); } - }, 120) + }, 120); } tooltip.addEventListener("mouseenter", () => { - isTooltipHovered = true - }) + isTooltipHovered = true; + }); tooltip.addEventListener("mouseleave", () => { - isTooltipHovered = false - hideTooltip() - clearMarker() - }) + isTooltipHovered = false; + hideTooltip(); + clearMarker(); + }); editor.container.addEventListener("mousemove", (e) => { - clearTimeout(hoverTimeout) + clearTimeout(hoverTimeout); hoverTimeout = setTimeout(() => { - const pos = editor.renderer.screenToTextCoordinates(e.clientX, e.clientY) - const { text, range } = getWord(editor, pos) + const pos = editor.renderer.screenToTextCoordinates(e.clientX, e.clientY); + const { text, range } = getWord(editor, pos); if (!text) { - hideTooltip() - clearMarker() - return + hideTooltip(); + clearMarker(); + return; } - const token = editor.session.getTokenAt(pos.row, pos.column - 1) + const token = editor.session.getTokenAt(pos.row, pos.column - 1); if (token && token.type.includes("comment")) { - hideTooltip() - clearMarker() - return + hideTooltip(); + clearMarker(); + return; } - const result = findDocEntry(text) + const result = findDocEntry(text); if (!result) { - hideTooltip() - clearMarker() - return + hideTooltip(); + clearMarker(); + return; } - const coords = editor.renderer.textToScreenCoordinates(pos.row, pos.column) + const coords = editor.renderer.textToScreenCoordinates(pos.row, pos.column); - highlight(range) - showTooltip(coords.pageX, coords.pageY, result.data, result.key, result.match) - }, 300) - }) + highlight(range); + showTooltip(coords.pageX, coords.pageY, result.data, result.key, result.match); + }, 300); + }); editor.container.addEventListener("mouseleave", () => { - clearTimeout(hoverTimeout) + clearTimeout(hoverTimeout); if (!isTooltipHovered) { - hideTooltip() - clearMarker() + hideTooltip(); + clearMarker(); } - }) -} \ No newline at end of file + }); +} diff --git a/assets/js/extensionsHandler/helpers/documentationTypes.js b/assets/js/extensionsHandler/helpers/documentationTypes.js index 1c70532..c4f351d 100644 --- a/assets/js/extensionsHandler/helpers/documentationTypes.js +++ b/assets/js/extensionsHandler/helpers/documentationTypes.js @@ -3,45 +3,45 @@ export class DocumentationTypes { { name: "keyword", displayName: "Keyword", - className: "keyword" + className: "keyword", }, { name: "function", displayName: "Function", - className: "function" + className: "function", }, { name: "variable", displayName: "Variable", - className: "variable" + className: "variable", }, { name: "type", displayName: "Type", - className: "type" + className: "type", }, { name: "string", displayName: "String", - className: "string" + className: "string", }, { name: "number", displayName: "Number", - className: "number" + className: "number", }, { name: "operator", displayName: "Operator", - className: "operator" - } - ] + className: "operator", + }, + ]; static list() { - return this.types + return DocumentationTypes.types; } static add(object) { - this.types.push(object) + DocumentationTypes.types.push(object); } -} \ No newline at end of file +} diff --git a/assets/js/global.js b/assets/js/global.js index 7a4096a..f776a53 100644 --- a/assets/js/global.js +++ b/assets/js/global.js @@ -1,18 +1,18 @@ /** @type {import("../../app/main/types/global").ElectronAPI} */ -export const electronAPI = window.electron +export const electronAPI = window.electron; export async function getDirname() { - let __dirname = await electronAPI.getDirname() - __dirname = __dirname.replaceAll(/\\/g, "/") + let __dirname = await electronAPI.getDirname(); + __dirname = __dirname.replaceAll(/\\/g, "/"); - return __dirname + return __dirname; } export async function readSettings() { - return await electronAPI.readSettings() + return await electronAPI.readSettings(); } export async function enableDevMode() { - await electronAPI.setSettings({ app: { devMode: true }}) + await electronAPI.setSettings({ app: { devMode: true } }); } export async function disableDevMode() { - await electronAPI.setSettings({ app: { devMode: false }}) -} \ No newline at end of file + await electronAPI.setSettings({ app: { devMode: false } }); +} diff --git a/assets/js/handlers/BottomWindowHandler.js b/assets/js/handlers/BottomWindowHandler.js index 726cf50..ebba8a6 100644 --- a/assets/js/handlers/BottomWindowHandler.js +++ b/assets/js/handlers/BottomWindowHandler.js @@ -1,44 +1,44 @@ export class BottomWindow { - static windows = new Map() - static settings = { app: { reduceMotion: false } } + static windows = new Map(); + static settings = { app: { reduceMotion: false } }; constructor(id, { title } = {}) { if (BottomWindow.windows.has(id)) { - return BottomWindow.windows.get(id) + return BottomWindow.windows.get(id); } - this.id = id - this.title = title - this.win = null - this.winContent = null - this.isAutoScrollBottom = false - this.hideHandlers = [] - this.resizeState = null - this.resizeFrame = null - this.nextResizeHeight = null - this.resizePreview = null - this.handleResizeMove = this.#handleResizeMove.bind(this) - this.handleResizeEnd = this.#handleResizeEnd.bind(this) - - this.#loadSettings() - this.#init() - BottomWindow.windows.set(id, this) + this.id = id; + this.title = title; + this.win = null; + this.winContent = null; + this.isAutoScrollBottom = false; + this.hideHandlers = []; + this.resizeState = null; + this.resizeFrame = null; + this.nextResizeHeight = null; + this.resizePreview = null; + this.handleResizeMove = this.#handleResizeMove.bind(this); + this.handleResizeEnd = this.#handleResizeEnd.bind(this); + + this.#loadSettings(); + this.#init(); + BottomWindow.windows.set(id, this); } async #loadSettings() { - if (!window.electron?.readSettings) return + if (!window.electron?.readSettings) return; try { - BottomWindow.settings = await window.electron.readSettings() + BottomWindow.settings = await window.electron.readSettings(); } catch (error) { - console.warn("[BottomWindow] Could not read settings", error) + console.warn("[BottomWindow] Could not read settings", error); } } #init() { - const win = document.createElement("div") - win.classList.add("bottom-window", "hidden") - win.id = this.id + const win = document.createElement("div"); + win.classList.add("bottom-window", "hidden"); + win.id = this.id; win.innerHTML = `
@@ -49,239 +49,235 @@ export class BottomWindow {
There is nothing here yet
- ` + `; - document - .querySelector(".bottom-window__container") - .appendChild(win) + document.querySelector(".bottom-window__container").appendChild(win); - this.win = win - this.winContent = win.querySelector(".bottom-window__content") - this.isFullscreen = false + this.win = win; + this.winContent = win.querySelector(".bottom-window__content"); + this.isFullscreen = false; - win.querySelector("#bottomWindowClose") - .addEventListener("click", () => this.hide()) + win.querySelector("#bottomWindowClose").addEventListener("click", () => this.hide()); - win.querySelector(".bottom-window__resize-handle") - .addEventListener("pointerdown", (event) => this.#handleResizeStart(event)) + win.querySelector(".bottom-window__resize-handle").addEventListener( + "pointerdown", + (event) => this.#handleResizeStart(event), + ); } #handleResizeStart(event) { - if (this.isFullscreen) return + if (this.isFullscreen) return; - const wrapper = this.win.closest(".code-wrapper") - const wrapperRect = wrapper?.getBoundingClientRect() - const winRect = this.win.getBoundingClientRect() - const reduceMotion = BottomWindow.settings?.app?.reduceMotion === true + const wrapper = this.win.closest(".code-wrapper"); + const wrapperRect = wrapper?.getBoundingClientRect(); + const winRect = this.win.getBoundingClientRect(); + const reduceMotion = BottomWindow.settings?.app?.reduceMotion === true; this.resizeState = { bottom: winRect.bottom, maxHeight: Math.max(180, (wrapperRect?.height || window.innerHeight) - 120), - reduceMotion - } + reduceMotion, + }; - document.body.classList.add("bottom-window-resizing") - this.win.classList.add("resizing") - this.win.style.transition = "none" - this.win.style.maxHeight = "none" + document.body.classList.add("bottom-window-resizing"); + this.win.classList.add("resizing"); + this.win.style.transition = "none"; + this.win.style.maxHeight = "none"; - this.win.dispatchEvent(new CustomEvent("bottom-window-resize-start")) + this.win.dispatchEvent(new CustomEvent("bottom-window-resize-start")); if (reduceMotion) { - this.#showResizePreview(winRect) + this.#showResizePreview(winRect); } - document.addEventListener("pointermove", this.handleResizeMove) - document.addEventListener("pointerup", this.handleResizeEnd, { once: true }) - document.addEventListener("pointercancel", this.handleResizeEnd, { once: true }) + document.addEventListener("pointermove", this.handleResizeMove); + document.addEventListener("pointerup", this.handleResizeEnd, { once: true }); + document.addEventListener("pointercancel", this.handleResizeEnd, { once: true }); - event.preventDefault() + event.preventDefault(); } #handleResizeMove(event) { - if (!this.resizeState) return + if (!this.resizeState) return; - const minHeight = 160 - const nextHeight = this.resizeState.bottom - event.clientY - const height = Math.min(Math.max(nextHeight, minHeight), this.resizeState.maxHeight) + const minHeight = 160; + const nextHeight = this.resizeState.bottom - event.clientY; + const height = Math.min(Math.max(nextHeight, minHeight), this.resizeState.maxHeight); - this.nextResizeHeight = height + this.nextResizeHeight = height; - if (this.resizeFrame) return + if (this.resizeFrame) return; this.resizeFrame = requestAnimationFrame(() => { - this.resizeFrame = null - if (this.nextResizeHeight == null) return + this.resizeFrame = null; + if (this.nextResizeHeight == null) return; if (this.resizeState?.reduceMotion) { - this.#moveResizePreview(this.resizeState.bottom - this.nextResizeHeight) - return + this.#moveResizePreview(this.resizeState.bottom - this.nextResizeHeight); + return; } - this.#setHeight(this.nextResizeHeight) - }) + this.#setHeight(this.nextResizeHeight); + }); } #handleResizeEnd() { - const wasResizing = Boolean(this.resizeState) - const applyHeight = this.nextResizeHeight + const wasResizing = Boolean(this.resizeState); + const applyHeight = this.nextResizeHeight; if (this.resizeFrame) { - cancelAnimationFrame(this.resizeFrame) - this.resizeFrame = null + cancelAnimationFrame(this.resizeFrame); + this.resizeFrame = null; } if (applyHeight != null && this.win) { - this.#setHeight(applyHeight) + this.#setHeight(applyHeight); } - this.#hideResizePreview() - this.resizeState = null - this.nextResizeHeight = null - document.body.classList.remove("bottom-window-resizing") - this.win?.classList.remove("resizing") - if (this.win) this.win.style.transition = "" + this.#hideResizePreview(); + this.resizeState = null; + this.nextResizeHeight = null; + document.body.classList.remove("bottom-window-resizing"); + this.win?.classList.remove("resizing"); + if (this.win) this.win.style.transition = ""; - document.removeEventListener("pointermove", this.handleResizeMove) - document.removeEventListener("pointerup", this.handleResizeEnd) - document.removeEventListener("pointercancel", this.handleResizeEnd) + document.removeEventListener("pointermove", this.handleResizeMove); + document.removeEventListener("pointerup", this.handleResizeEnd); + document.removeEventListener("pointercancel", this.handleResizeEnd); if (wasResizing) { - this.win?.dispatchEvent(new CustomEvent("bottom-window-resize-end")) + this.win?.dispatchEvent(new CustomEvent("bottom-window-resize-end")); } } #setHeight(height) { - this.win.style.height = `${height}px` + this.win.style.height = `${height}px`; } #showResizePreview(winRect) { - this.#hideResizePreview() + this.#hideResizePreview(); - const preview = document.createElement("div") - preview.className = "bottom-window__resize-preview" - preview.style.left = `${winRect.left}px` - preview.style.top = `${winRect.top}px` - preview.style.width = `${winRect.width}px` + const preview = document.createElement("div"); + preview.className = "bottom-window__resize-preview"; + preview.style.left = `${winRect.left}px`; + preview.style.top = `${winRect.top}px`; + preview.style.width = `${winRect.width}px`; - document.body.appendChild(preview) - this.resizePreview = preview + document.body.appendChild(preview); + this.resizePreview = preview; } #moveResizePreview(top) { - if (!this.resizePreview) return + if (!this.resizePreview) return; - this.resizePreview.style.top = `${top}px` + this.resizePreview.style.top = `${top}px`; } #hideResizePreview() { - this.resizePreview?.remove() - this.resizePreview = null + this.resizePreview?.remove(); + this.resizePreview = null; } removeClose() { - if(this.win.querySelector("#bottomWindowClose")) { - this.win.querySelector("#bottomWindowClose").remove() + if (this.win.querySelector("#bottomWindowClose")) { + this.win.querySelector("#bottomWindowClose").remove(); } } static get(id) { - return BottomWindow.windows.get(id) + return BottomWindow.windows.get(id); } static log(...args) { - console.log(`[BottomWindow]`, ...args) + console.log("[BottomWindow]", ...args); } autoScrollBottom() { - this.isAutoScrollBottom + this.isAutoScrollBottom; } clear() { - this.winContent.innerHTML = "" + this.winContent.innerHTML = ""; } show() { - this.win.classList.remove("hidden") + this.win.classList.remove("hidden"); - if(this.isFullscreen) { - document.querySelector(".bottom-window__container").classList.add("full") - } - else { - document.querySelector(".bottom-window__container").classList.remove("full") + if (this.isFullscreen) { + document.querySelector(".bottom-window__container").classList.add("full"); + } else { + document.querySelector(".bottom-window__container").classList.remove("full"); } } hide() { - this.win.classList.add("hidden") + this.win.classList.add("hidden"); - if(this.isFullscreen) { - document.querySelector(".bottom-window__container").classList.remove("full") - } - else { - document.querySelector(".bottom-window__container").classList.remove("full") + if (this.isFullscreen) { + document.querySelector(".bottom-window__container").classList.remove("full"); + } else { + document.querySelector(".bottom-window__container").classList.remove("full"); } - this.hideHandlers.forEach(handler => handler()) + this.hideHandlers.forEach((handler) => handler()); } onHide(handler) { - this.hideHandlers.push(handler) + this.hideHandlers.push(handler); } add(el) { - const placeholder = this.winContent.querySelector("#placeholder") + const placeholder = this.winContent.querySelector("#placeholder"); if (placeholder) { - placeholder.remove() + placeholder.remove(); } - this.winContent.appendChild(el) + this.winContent.appendChild(el); - if(this.isAutoScrollBottom) { - this.winContent.scrollTop = this.winContent.scrollHeight + if (this.isAutoScrollBottom) { + this.winContent.scrollTop = this.winContent.scrollHeight; } } set(content) { - const placeholder = this.winContent.querySelector("#placeholder") + const placeholder = this.winContent.querySelector("#placeholder"); if (placeholder) { - placeholder.remove() + placeholder.remove(); } - this.winContent.innerHTML = content + this.winContent.innerHTML = content; } toggle() { - this.win.classList.toggle("hidden") + this.win.classList.toggle("hidden"); } fullscreen(state = true) { - this.isFullscreen = state + this.isFullscreen = state; - if(state) { - this.win.classList.add("fullscreen") - } - else { - this.win.classList.remove("fullscreen") + if (state) { + this.win.classList.add("fullscreen"); + } else { + this.win.classList.remove("fullscreen"); } } state() { - return this.win.classList.contains("hidden") ? "hidden" : "show" + return this.win.classList.contains("hidden") ? "hidden" : "show"; } destroy() { - this.#handleResizeEnd() - this.win?.remove() - BottomWindow.windows.delete(this.id) + this.#handleResizeEnd(); + this.win?.remove(); + BottomWindow.windows.delete(this.id); } } export function closeAllWindows(exceptId = null) { BottomWindow.windows.forEach((window, id) => { - if (id !== exceptId) window.hide() - }) + if (id !== exceptId) window.hide(); + }); if (!exceptId) { - document.querySelector(".bottom-window__container").classList.remove("full") + document.querySelector(".bottom-window__container").classList.remove("full"); } } diff --git a/assets/js/handlers/SidebarResizeHandler.js b/assets/js/handlers/SidebarResizeHandler.js index d105e8d..caff27c 100644 --- a/assets/js/handlers/SidebarResizeHandler.js +++ b/assets/js/handlers/SidebarResizeHandler.js @@ -1,177 +1,177 @@ -const SIDEBAR_WIDTH_STORAGE_KEY = "codemotion.explorerWidth" -const DEFAULT_WIDTH = 300 -const MIN_WIDTH = 220 -const MAX_WIDTH = 520 +const SIDEBAR_WIDTH_STORAGE_KEY = "codemotion.explorerWidth"; +const DEFAULT_WIDTH = 300; +const MIN_WIDTH = 220; +const MAX_WIDTH = 520; export class SidebarResizeHandler { constructor({ explorer, mainWrapper, settings = {}, onResizeEnd = () => {} } = {}) { - this.explorer = explorer - this.mainWrapper = mainWrapper - this.settings = settings - this.onResizeEnd = onResizeEnd - this.resizeState = null - this.resizeFrame = null - this.nextWidth = null - this.resizePreview = null - this.handleResizeMove = this.#handleResizeMove.bind(this) - this.handleResizeEnd = this.#handleResizeEnd.bind(this) + this.explorer = explorer; + this.mainWrapper = mainWrapper; + this.settings = settings; + this.onResizeEnd = onResizeEnd; + this.resizeState = null; + this.resizeFrame = null; + this.nextWidth = null; + this.resizePreview = null; + this.handleResizeMove = this.#handleResizeMove.bind(this); + this.handleResizeEnd = this.#handleResizeEnd.bind(this); this.handleReduceMotionChange = (event) => { this.settings = { ...this.settings, app: { ...this.settings?.app, - reduceMotion: event.detail?.reduceMotion === true - } - } - } + reduceMotion: event.detail?.reduceMotion === true, + }, + }; + }; - if (!this.explorer || !this.mainWrapper) return + if (!(this.explorer && this.mainWrapper)) return; - this.#init() + this.#init(); } #init() { - this.handle = document.createElement("div") - this.handle.className = "explorer__resize-handle" - this.handle.setAttribute("role", "separator") - this.handle.setAttribute("aria-orientation", "vertical") - this.handle.setAttribute("aria-label", "Resize sidebar") - this.explorer.appendChild(this.handle) - - this.#setWidth(this.#getSavedWidth()) - this.handle.addEventListener("pointerdown", (event) => this.#handleResizeStart(event)) - window.addEventListener("codemotion-reduce-motion-change", this.handleReduceMotionChange) + this.handle = document.createElement("div"); + this.handle.className = "explorer__resize-handle"; + this.handle.setAttribute("role", "separator"); + this.handle.setAttribute("aria-orientation", "vertical"); + this.handle.setAttribute("aria-label", "Resize sidebar"); + this.explorer.appendChild(this.handle); + + this.#setWidth(this.#getSavedWidth()); + this.handle.addEventListener("pointerdown", (event) => this.#handleResizeStart(event)); + window.addEventListener("codemotion-reduce-motion-change", this.handleReduceMotionChange); } #handleResizeStart(event) { - const explorerRect = this.explorer.getBoundingClientRect() - const wrapperRect = this.mainWrapper.getBoundingClientRect() - const reduceMotion = this.settings?.app?.reduceMotion === true + const explorerRect = this.explorer.getBoundingClientRect(); + const wrapperRect = this.mainWrapper.getBoundingClientRect(); + const reduceMotion = this.settings?.app?.reduceMotion === true; this.resizeState = { left: explorerRect.left, minWidth: MIN_WIDTH, maxWidth: Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, wrapperRect.width - 280)), - reduceMotion - } + reduceMotion, + }; - this.nextWidth = explorerRect.width - document.body.classList.add("explorer-resizing") - this.explorer.classList.add("resizing") - this.explorer.style.transition = "none" + this.nextWidth = explorerRect.width; + document.body.classList.add("explorer-resizing"); + this.explorer.classList.add("resizing"); + this.explorer.style.transition = "none"; - this.explorer.dispatchEvent(new CustomEvent("explorer-resize-start")) + this.explorer.dispatchEvent(new CustomEvent("explorer-resize-start")); if (reduceMotion) { - this.#showResizePreview(explorerRect) + this.#showResizePreview(explorerRect); } - document.addEventListener("pointermove", this.handleResizeMove) - document.addEventListener("pointerup", this.handleResizeEnd, { once: true }) - document.addEventListener("pointercancel", this.handleResizeEnd, { once: true }) + document.addEventListener("pointermove", this.handleResizeMove); + document.addEventListener("pointerup", this.handleResizeEnd, { once: true }); + document.addEventListener("pointercancel", this.handleResizeEnd, { once: true }); - event.preventDefault() + event.preventDefault(); } #handleResizeMove(event) { - if (!this.resizeState) return + if (!this.resizeState) return; - const nextWidth = event.clientX - this.resizeState.left + const nextWidth = event.clientX - this.resizeState.left; const width = Math.min( Math.max(nextWidth, this.resizeState.minWidth), - this.resizeState.maxWidth - ) + this.resizeState.maxWidth, + ); - this.nextWidth = width + this.nextWidth = width; - if (this.resizeFrame) return + if (this.resizeFrame) return; this.resizeFrame = requestAnimationFrame(() => { - this.resizeFrame = null - if (this.nextWidth == null) return + this.resizeFrame = null; + if (this.nextWidth == null) return; if (this.resizeState?.reduceMotion) { - this.#moveResizePreview(this.resizeState.left + this.nextWidth) - return + this.#moveResizePreview(this.resizeState.left + this.nextWidth); + return; } - this.#setWidth(this.nextWidth) - this.#notifyResize() - }) + this.#setWidth(this.nextWidth); + this.#notifyResize(); + }); } #handleResizeEnd() { - const wasResizing = Boolean(this.resizeState) - const applyWidth = this.nextWidth + const wasResizing = Boolean(this.resizeState); + const applyWidth = this.nextWidth; if (this.resizeFrame) { - cancelAnimationFrame(this.resizeFrame) - this.resizeFrame = null + cancelAnimationFrame(this.resizeFrame); + this.resizeFrame = null; } if (applyWidth != null) { - this.#setWidth(applyWidth) - this.#saveWidth(applyWidth) - this.#notifyResize() + this.#setWidth(applyWidth); + this.#saveWidth(applyWidth); + this.#notifyResize(); } - this.#hideResizePreview() - this.resizeState = null - this.nextWidth = null - document.body.classList.remove("explorer-resizing") - this.explorer?.classList.remove("resizing") - if (this.explorer) this.explorer.style.transition = "" + this.#hideResizePreview(); + this.resizeState = null; + this.nextWidth = null; + document.body.classList.remove("explorer-resizing"); + this.explorer?.classList.remove("resizing"); + if (this.explorer) this.explorer.style.transition = ""; - document.removeEventListener("pointermove", this.handleResizeMove) - document.removeEventListener("pointerup", this.handleResizeEnd) - document.removeEventListener("pointercancel", this.handleResizeEnd) + document.removeEventListener("pointermove", this.handleResizeMove); + document.removeEventListener("pointerup", this.handleResizeEnd); + document.removeEventListener("pointercancel", this.handleResizeEnd); if (wasResizing) { - this.explorer?.dispatchEvent(new CustomEvent("explorer-resize-end")) - this.onResizeEnd() + this.explorer?.dispatchEvent(new CustomEvent("explorer-resize-end")); + this.onResizeEnd(); } } #getSavedWidth() { - const savedWidth = Number(localStorage.getItem(SIDEBAR_WIDTH_STORAGE_KEY)) - if (!Number.isFinite(savedWidth)) return DEFAULT_WIDTH + const savedWidth = Number(localStorage.getItem(SIDEBAR_WIDTH_STORAGE_KEY)); + if (!Number.isFinite(savedWidth)) return DEFAULT_WIDTH; - return Math.min(Math.max(savedWidth, MIN_WIDTH), MAX_WIDTH) + return Math.min(Math.max(savedWidth, MIN_WIDTH), MAX_WIDTH); } #saveWidth(width) { - localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(Math.round(width))) + localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(Math.round(width))); } #setWidth(width) { - this.explorer.style.setProperty("--explorer-width", `${Math.round(width)}px`) + this.explorer.style.setProperty("--explorer-width", `${Math.round(width)}px`); } #notifyResize() { - window.dispatchEvent(new Event("resize")) + window.dispatchEvent(new Event("resize")); } #showResizePreview(explorerRect) { - this.#hideResizePreview() + this.#hideResizePreview(); - const preview = document.createElement("div") - preview.className = "explorer__resize-preview" - preview.style.left = `${explorerRect.right}px` - preview.style.top = `${explorerRect.top}px` - preview.style.height = `${explorerRect.height}px` + const preview = document.createElement("div"); + preview.className = "explorer__resize-preview"; + preview.style.left = `${explorerRect.right}px`; + preview.style.top = `${explorerRect.top}px`; + preview.style.height = `${explorerRect.height}px`; - document.body.appendChild(preview) - this.resizePreview = preview + document.body.appendChild(preview); + this.resizePreview = preview; } #moveResizePreview(left) { - if (!this.resizePreview) return + if (!this.resizePreview) return; - this.resizePreview.style.left = `${left}px` + this.resizePreview.style.left = `${left}px`; } #hideResizePreview() { - this.resizePreview?.remove() - this.resizePreview = null + this.resizePreview?.remove(); + this.resizePreview = null; } } diff --git a/assets/js/handlers/bottomTabHandler.js b/assets/js/handlers/bottomTabHandler.js index becb116..9e3ad11 100644 --- a/assets/js/handlers/bottomTabHandler.js +++ b/assets/js/handlers/bottomTabHandler.js @@ -1,141 +1,138 @@ import { Languages } from "../lib.js"; -import { TopWindowList, destroyAllTopWindowLists } from "../topWindowHandler/topWindowList.js"; +import { destroyAllTopWindowLists, TopWindowList } from "../topWindowHandler/topWindowList.js"; export async function setCurrentLanguage(langName, properties = {}) { - if (!properties.editor) throw new Error(`properties.editor required`) + if (!properties.editor) throw new Error("properties.editor required"); - const aviableLanguageNames = [] + const aviableLanguageNames = []; const languages = Object.entries(Languages.list()) - .filter(([_, lang]) => - !["Image", "Font", "To-Do List", "GIT File"].includes(lang.name) - ) - .filter(([_, lang], index, arr) => - arr.findIndex(([_, l]) => l.name === lang.name) === index - ) + .filter(([_, lang]) => !["Image", "Font", "To-Do List", "GIT File"].includes(lang.name)) + .filter( + ([_, lang], index, arr) => arr.findIndex(([_, l]) => l.name === lang.name) === index, + ); for (const [key, lang] of languages) { - const icon = await Languages.getIconPath(key) + const icon = await Languages.getIconPath(key); aviableLanguageNames.push({ name: lang.name, id: key, secondary: key, - icon - }) + icon, + }); } - const changeLanguageList = new TopWindowList("changeLanguage", aviableLanguageNames) + const changeLanguageList = new TopWindowList("changeLanguage", aviableLanguageNames); changeLanguageList.on("click", (data) => { - document.querySelectorAll("#currentLang").forEach(e => { - properties.editor.setLanguage(data.id) - e.textContent = data.name - }) - }) + document.querySelectorAll("#currentLang").forEach((e) => { + properties.editor.setLanguage(data.id); + e.textContent = data.name; + }); + }); - document.querySelectorAll("#currentLang").forEach(e => { - e.textContent = langName - }) + document.querySelectorAll("#currentLang").forEach((e) => { + e.textContent = langName; + }); - changeLanguageList.bind(document.querySelector("#currentLang")) + changeLanguageList.bind(document.querySelector("#currentLang")); } export function setColumn(col) { - document.querySelectorAll("#currentCol").forEach(e => { + document.querySelectorAll("#currentCol").forEach((e) => { if (e) { - e.textContent = col + e.textContent = col; } - }) + }); } export function setTabSize(size) { - document.querySelectorAll("#currentTabSize").forEach(e => { + document.querySelectorAll("#currentTabSize").forEach((e) => { if (e) { - e.textContent = size + e.textContent = size; } - }) + }); - window.electron.setSettings({ editor: { tabSize: size } }) + window.electron.setSettings({ editor: { tabSize: size } }); } export function setSymbols(len) { - document.querySelectorAll("#currentSymbols").forEach(e => { + document.querySelectorAll("#currentSymbols").forEach((e) => { if (e) { - e.textContent = len + e.textContent = len; } - }) + }); } export function setErrors(object) { - let errorObject = {} - let warningObject = {} + const errorObject = {}; + const warningObject = {}; - for (let e in object) { + for (const e in object) { if (object[e].type == "error") { - errorObject[e] = object[e] + errorObject[e] = object[e]; } if (object[e].type == "warning") { - warningObject[e] = object[e] + warningObject[e] = object[e]; } } - document.querySelectorAll("#errorCount").forEach(e => { + document.querySelectorAll("#errorCount").forEach((e) => { if (e) { - let len = Object.keys(errorObject).length + const len = Object.keys(errorObject).length; - e.parentElement.classList.toggle("text-danger", len > 0) - e.textContent = Object.keys(errorObject).length + e.parentElement.classList.toggle("text-danger", len > 0); + e.textContent = Object.keys(errorObject).length; } - }) - document.querySelectorAll("#warningCount").forEach(e => { + }); + document.querySelectorAll("#warningCount").forEach((e) => { if (e) { - let len = Object.keys(warningObject).length + const len = Object.keys(warningObject).length; - e.parentElement.classList.toggle("text-warning", len > 0) - e.textContent = Object.keys(warningObject).length + e.parentElement.classList.toggle("text-warning", len > 0); + e.textContent = Object.keys(warningObject).length; } - }) + }); } export function toggleCodeFooter(bool) { if (bool) { - document.querySelectorAll(".code-footer").forEach(e => { - e.classList.remove("hidden") - }) - } - else { - document.querySelectorAll(".code-footer").forEach(e => { - e.classList.add("hidden") - }) + document.querySelectorAll(".code-footer").forEach((e) => { + e.classList.remove("hidden"); + }); + } else { + document.querySelectorAll(".code-footer").forEach((e) => { + e.classList.add("hidden"); + }); } } export function setLine(line) { - document.querySelectorAll("#currentLine").forEach(e => { + document.querySelectorAll("#currentLine").forEach((e) => { if (e) { - e.textContent = line + e.textContent = line; } - }) + }); } -const runtimeErrors = document.querySelector("#runtimeErrors") -const bottomWarnings = document.querySelector("#bottomWarnings") -const bottomErrors = document.querySelector("#bottomErrors") +const runtimeErrors = document.querySelector("#runtimeErrors"); +const bottomWarnings = document.querySelector("#bottomWarnings"); +const bottomErrors = document.querySelector("#bottomErrors"); export function disableErrors(editor) { - bottomErrors.classList.add("hidden") - bottomWarnings.classList.add("hidden") + bottomErrors.classList.add("hidden"); + bottomWarnings.classList.add("hidden"); - runtimeErrors.classList.add("disabled") + runtimeErrors.classList.add("disabled"); editor.setOption("useWorker", false); } export function enableErrors(editor) { - bottomErrors.classList.remove("hidden") - bottomWarnings.classList.remove("hidden") + bottomErrors.classList.remove("hidden"); + bottomWarnings.classList.remove("hidden"); - runtimeErrors.classList.remove("disabled") + runtimeErrors.classList.remove("disabled"); editor.setOption("useWorker", true); -} \ No newline at end of file +} diff --git a/assets/js/handlers/contextMenuHandler.js b/assets/js/handlers/contextMenuHandler.js index 24c9491..7bb0ffc 100644 --- a/assets/js/handlers/contextMenuHandler.js +++ b/assets/js/handlers/contextMenuHandler.js @@ -1,83 +1,82 @@ -import { idify } from "../lib.js" +import { idify } from "../lib.js"; export class ContextMenu { constructor(id, elements = {}) { - const context = document.createElement("div") - context.classList.add("context-menu", "hidden") - context.id = idify(id) - this.context = context + const context = document.createElement("div"); + context.classList.add("context-menu", "hidden"); + context.id = idify(id); + this.context = context; context.addEventListener("contextmenu", (e) => { e.preventDefault(); e.stopPropagation(); }); - document.body.appendChild(context) + document.body.appendChild(context); - if(Object.keys(elements).length > 0) { - Object.keys(elements).forEach(key => { - this.add(elements[key]) - }) + if (Object.keys(elements).length > 0) { + Object.keys(elements).forEach((key) => { + this.add(elements[key]); + }); } } on(eventName, callback) { const events = { - open: "contextmenu" - } + open: "contextmenu", + }; - if(eventName in events) { - this.scope.addEventListener(events[eventName], () => { - callback( - { - element: this.context - } - ) - }) + if (eventName in events) { + this.scope.addEventListener(events[eventName], () => { + callback({ + element: this.context, + }); + }); } } removeItem(id) { - const existing = this.context.querySelector(`.context-menu__item[id="${id}"]`) - if(existing) { - existing.remove() + const existing = this.context.querySelector(`.context-menu__item[id="${id}"]`); + if (existing) { + existing.remove(); } } add({ id, content, icon, shortcut, func, type }) { - if(this.context.querySelector(`.context-menu__item[id="${id}"]`)) { - return + if (this.context.querySelector(`.context-menu__item[id="${id}"]`)) { + return; } - let iconHTML = icon == undefined ? "" : `${icon}` - type = type == undefined ? "default" : type + const iconHtml = + icon == undefined ? "" : `${icon}`; + type = type == undefined ? "default" : type; - const item = document.createElement("div") - item.classList.add("context-menu__item") - item.id = id + const item = document.createElement("div"); + item.classList.add("context-menu__item"); + item.id = id; item.innerHTML = ` -
- ${iconHTML} +
+ ${iconHtml}
${content}
- ${shortcut != undefined ? `
${shortcut}
` : ""} + ${shortcut == undefined ? "" : `
${shortcut}
`}
- ` + `; - if(type == "divider") { - item.innerHTML = "" - item.className = "context-menu__item-divider" - item.innerHTML = `
` - item.removeAttribute("id") + if (type == "divider") { + item.innerHTML = ""; + item.className = "context-menu__item-divider"; + item.innerHTML = "
"; + item.removeAttribute("id"); } - this.context.appendChild(item) + this.context.appendChild(item); item.addEventListener("click", () => { - this._hide() - func() - }) + this._hide(); + func(); + }); } _show(x, y) { @@ -108,8 +107,8 @@ export class ContextMenu { } bindOn(scope) { - if(scope) { - this.scope = scope + if (scope) { + this.scope = scope; scope.addEventListener("contextmenu", (e) => { e.preventDefault(); this._show(e.clientX, e.clientY); @@ -125,7 +124,7 @@ export class ContextMenu { this.scope = editorContainer; this._showMenu = (x, y) => { - document.querySelectorAll(".context-menu").forEach(m => { + document.querySelectorAll(".context-menu").forEach((m) => { if (m !== this.context) m.classList.add("hidden"); }); this._show(x, y); @@ -160,4 +159,4 @@ export class ContextMenu { }; document.addEventListener("keydown", this._onKey); } -} \ No newline at end of file +} diff --git a/assets/js/handlers/debuggerSignalHandlers.js b/assets/js/handlers/debuggerSignalHandlers.js index c368a06..a0f4a02 100644 --- a/assets/js/handlers/debuggerSignalHandlers.js +++ b/assets/js/handlers/debuggerSignalHandlers.js @@ -1,15 +1,18 @@ export function sendDebugMsg(text) { - window.electron.sendDebuggerData({ type: "msg", content: text }) + window.electron.sendDebuggerData({ type: "msg", content: text }); } export function sendDebugError(text) { - window.electron.sendDebuggerData({ type: "error", content: text }) + window.electron.sendDebuggerData({ type: "error", content: text }); } export function sendDebugWarn(text) { - window.electron.sendDebuggerData({ type: "warn", content: text }) + window.electron.sendDebuggerData({ type: "warn", content: text }); } export function sendDebugMarking() { - window.electron.sendDebuggerData({ type: "marking" }) + window.electron.sendDebuggerData({ type: "marking" }); } export function sendDebugModuleInfo({ name, version, description, permissions }) { - window.electron.sendDebuggerData({ type: "moduleInfo", info: { name: name, version: version, description: description, permissions: permissions } }) -} \ No newline at end of file + window.electron.sendDebuggerData({ + type: "moduleInfo", + info: { name, version, description, permissions }, + }); +} diff --git a/assets/js/handlers/handlePopovers.js b/assets/js/handlers/handlePopovers.js index 000861a..74681f9 100644 --- a/assets/js/handlers/handlePopovers.js +++ b/assets/js/handlers/handlePopovers.js @@ -1,88 +1,86 @@ import { idify } from "../lib.js"; function addPopover(el, gls) { - if (el.hasAttribute("noPopover")) return - if (el._hasPopover) return + if (el.hasAttribute("noPopover")) return; + if (el._hasPopover) return; - const tooltip = document.createElement("div") - tooltip.role = "tooltip" - tooltip.id = idify(el.id) + const tooltip = document.createElement("div"); + tooltip.role = "tooltip"; + tooltip.id = idify(el.id); - if(typeof gls != "object") { - tooltip.textContent = el.getAttribute("tooltip") - } - else { - tooltip.textContent = gls.get(el.getAttribute("tooltip")) + if (typeof gls == "object") { + tooltip.textContent = gls.get(el.getAttribute("tooltip")); + } else { + tooltip.textContent = el.getAttribute("tooltip"); } - tooltip.className = "tooltip" - tooltip.style.zIndex = "9999" + tooltip.className = "tooltip"; + tooltip.style.zIndex = "9999"; - const tooltipPosition = el.getAttribute("tooltippos") ? el.getAttribute("tooltippos") : "right" - let tooptipOffset + const tooltipPosition = el.getAttribute("tooltippos") ? el.getAttribute("tooltippos") : "right"; + let tooptipOffset; switch (tooltipPosition) { case "right": - tooptipOffset = [0, -10] + tooptipOffset = [0, -10]; break; case "top": - tooptipOffset = [0, 0] + tooptipOffset = [0, 0]; break; } - el.appendChild(tooltip) + el.appendChild(tooltip); const popperInstance = Popper.createPopper(el, tooltip, { placement: tooltipPosition, modifiers: [ { - name: 'offset', + name: "offset", options: { offset: tooptipOffset, }, }, ], - }) + }); function show() { - tooltip.setAttribute("data-show", "") - popperInstance.update() + tooltip.setAttribute("data-show", ""); + popperInstance.update(); } function hide() { - tooltip.removeAttribute("data-show") + tooltip.removeAttribute("data-show"); } - const showEvents = ["mouseenter", "focus"] - const hideEvents = ["mouseleave", "blur"] + const showEvents = ["mouseenter", "focus"]; + const hideEvents = ["mouseleave", "blur"]; - showEvents.forEach((event) => el.addEventListener(event, show)) - hideEvents.forEach((event) => el.addEventListener(event, hide)) + showEvents.forEach((event) => el.addEventListener(event, show)); + hideEvents.forEach((event) => el.addEventListener(event, hide)); - el._hasPopover = true + el._hasPopover = true; } export function handlePopovers(gls) { - document.querySelectorAll("[tooltip]").forEach(e => { - addPopover(e, gls) - }) + document.querySelectorAll("[tooltip]").forEach((e) => { + addPopover(e, gls); + }); const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { - - if (node.nodeType !== 1) return + if (node.nodeType !== 1) return; if (node.matches?.("[tooltip]")) { - addPopover(node, gls) + addPopover(node, gls); } - node.querySelectorAll?.("[tooltip]").forEach(addPopover) - }) - }) - }) + node.querySelectorAll?.("[tooltip]").forEach(addPopover); + }); + }); + }); observer.observe(document.body, { childList: true, - subtree: true - }) -} \ No newline at end of file + subtree: true, + }); +} diff --git a/assets/js/handlers/imageZoomHandler.js b/assets/js/handlers/imageZoomHandler.js index e43f876..3623b70 100644 --- a/assets/js/handlers/imageZoomHandler.js +++ b/assets/js/handlers/imageZoomHandler.js @@ -12,7 +12,9 @@ export function bindImageZoomHandlers(container) { } const handleKeyDown = (e) => { - const isPreviewActive = document.querySelector(".bottom-window__container.full")?.contains(previewEl) && !previewEl.closest(".bottom-window.hidden"); + const isPreviewActive = + document.querySelector(".bottom-window__container.full")?.contains(previewEl) && + !previewEl.closest(".bottom-window.hidden"); if (isPreviewActive) { if (e.key === "+" || e.key === "=") { e.preventDefault(); diff --git a/assets/js/handlers/minifyHandlers.js b/assets/js/handlers/minifyHandlers.js index 1556ed5..a9db38e 100644 --- a/assets/js/handlers/minifyHandlers.js +++ b/assets/js/handlers/minifyHandlers.js @@ -12,152 +12,145 @@ export function minifyCSS(css) { } export function minifyJS(code) { + let out = ""; + let i = 0; + const len = code.length; - let out = "" - let i = 0 - const len = code.length - - let state = "normal" - let quote = null - let prev = "" + let state = "normal"; + let quote = null; + let prev = ""; function isWord(c) { - return /[a-zA-Z0-9_$]/.test(c) + return /[a-zA-Z0-9_$]/.test(c); } function lastOut() { - return out[out.length - 1] + return out[out.length - 1]; } while (i < len) { - - let c = code[i] - let n = code[i + 1] + const c = code[i]; + const n = code[i + 1]; // ---------- STRING ---------- if (state === "string") { - - out += c + out += c; if (c === "\\") { - out += n - i += 2 - continue + out += n; + i += 2; + continue; } if (c === quote) { - state = "normal" + state = "normal"; } - i++ - continue + i++; + continue; } // ---------- TEMPLATE ---------- if (state === "template") { - - out += c + out += c; if (c === "\\") { - out += n - i += 2 - continue + out += n; + i += 2; + continue; } if (c === "`") { - state = "normal" + state = "normal"; } - i++ - continue + i++; + continue; } // ---------- REGEX ---------- if (state === "regex") { - - out += c + out += c; if (c === "\\") { - out += n - i += 2 - continue + out += n; + i += 2; + continue; } if (c === "/") { - state = "normal" + state = "normal"; } - i++ - continue + i++; + continue; } // ---------- STRING START ---------- if (c === '"' || c === "'") { - quote = c - state = "string" - out += c - i++ - continue + quote = c; + state = "string"; + out += c; + i++; + continue; } // ---------- TEMPLATE START ---------- if (c === "`") { - state = "template" - out += c - i++ - continue + state = "template"; + out += c; + i++; + continue; } // ---------- COMMENTS ---------- if (c === "/" && n === "/") { - while (i < len && code[i] !== "\n") i++ - continue + while (i < len && code[i] !== "\n") i++; + continue; } if (c === "/" && n === "*") { - i += 2 - while (i < len && !(code[i] === "*" && code[i+1] === "/")) i++ - i += 2 - continue + i += 2; + while (i < len && !(code[i] === "*" && code[i + 1] === "/")) i++; + i += 2; + continue; } // ---------- REGEX DETECTION ---------- if (c === "/") { - - let prev = lastOut() + const prev = lastOut(); if (!prev || /[({[=,:!&|?;<>+-]/.test(prev)) { - state = "regex" - out += c - i++ - continue + state = "regex"; + out += c; + i++; + continue; } } // ---------- WHITESPACE ---------- if (/\s/.test(c)) { - - let prev = lastOut() - let next = code[i + 1] + const prev = lastOut(); + const next = code[i + 1]; if (isWord(prev) && isWord(next)) { - out += " " + out += " "; } - i++ - continue + i++; + continue; } // ---------- REMOVE EXTRA ; ---------- if (c === ";" && n === "}") { - i++ - continue + i++; + continue; } - out += c - prev = c - i++ + out += c; + prev = c; + i++; } - return out.trim() -} \ No newline at end of file + return out.trim(); +} diff --git a/assets/js/handlers/segmentedControlHandler.js b/assets/js/handlers/segmentedControlHandler.js index 5de192b..4015ca2 100644 --- a/assets/js/handlers/segmentedControlHandler.js +++ b/assets/js/handlers/segmentedControlHandler.js @@ -1,35 +1,30 @@ export function setupSegmentedControl() { - const SEGMENTED_CONTROL_BASE_SELECTOR = ".segmented-control"; - const SEGMENTED_CONTROL_INDIVIDUAL_SEGMENT_SELECTOR = ".segmented-control .option input"; - const SEGMENTED_CONTROL_BACKGROUND_PILL_SELECTOR = ".segmented-control .selection"; + const SegmentedControlBaseSelector = ".segmented-control"; + const SegmentedControlIndividualSegmentSelector = ".segmented-control .option input"; + const SegmentedControlBackgroundPillSelector = ".segmented-control .selection"; - setup() + setup(); function setup() { - forEachElement(SEGMENTED_CONTROL_BASE_SELECTOR, (elem) => { + forEachElement(SegmentedControlBaseSelector, (elem) => { elem.addEventListener("change", updatePillPosition); }); window.addEventListener("resize", updatePillPosition); - } function updatePillPosition() { - forEachElement( - SEGMENTED_CONTROL_INDIVIDUAL_SEGMENT_SELECTOR, - (elem, index) => { - if (elem.checked) moveBackgroundPillToElement(elem, index); - } - ); + forEachElement(SegmentedControlIndividualSegmentSelector, (elem, index) => { + if (elem.checked) moveBackgroundPillToElement(elem, index); + }); } function moveBackgroundPillToElement(elem, index) { console.log(elem.offsetWidth * index); - document.querySelector( - SEGMENTED_CONTROL_BACKGROUND_PILL_SELECTOR - ).style.transform = "translateX(" + elem.offsetWidth * index + "px)"; + document.querySelector(SegmentedControlBackgroundPillSelector).style.transform = + "translateX(" + elem.offsetWidth * index + "px)"; } function forEachElement(className, fn) { Array.from(document.querySelectorAll(className)).forEach(fn); } -} \ No newline at end of file +} diff --git a/assets/js/handlers/terminalHandler.js b/assets/js/handlers/terminalHandler.js index 3466389..cb5415e 100644 --- a/assets/js/handlers/terminalHandler.js +++ b/assets/js/handlers/terminalHandler.js @@ -1,429 +1,457 @@ export class Console { constructor(windowClass, startPath = null) { - this.console = windowClass - this.body = windowClass.winContent - - const fitAddon = new FitAddon.FitAddon() - - this.term = new Terminal( - { - convertEol: true, - cursorBlink: true, - fontFamily: "Consolas, monospace", - fontSize: 14 - } - ) - - this.term.loadAddon(fitAddon) - this.term.open(this.body) - this.fitAddon = fitAddon - this.handleResize = () => this.fit() - this.disposed = false - this.fitFrame = null - this.isPanelResizing = false + this.console = windowClass; + this.body = windowClass.winContent; + + const fitAddon = new FitAddon.FitAddon(); + + this.term = new Terminal({ + convertEol: true, + cursorBlink: true, + fontFamily: "Consolas, monospace", + fontSize: 14, + }); + + this.term.loadAddon(fitAddon); + this.term.open(this.body); + this.fitAddon = fitAddon; + this.handleResize = () => this.fit(); + this.disposed = false; + this.fitFrame = null; + this.isPanelResizing = false; this.handlePanelResizeStart = () => { - this.isPanelResizing = true - } + this.isPanelResizing = true; + }; this.handlePanelResizeEnd = () => { - this.isPanelResizing = false - this.fit() - } - - this.fit() - this.resizeObserver = new ResizeObserver(() => this.fit()) - this.resizeObserver.observe(this.body) - window.addEventListener("resize", this.handleResize) - this.console.win.addEventListener("bottom-window-resize-start", this.handlePanelResizeStart) - this.console.win.addEventListener("bottom-window-resize-end", this.handlePanelResizeEnd) - - this.buffer = "" - this.history = [] - this.historyIndex = -1 - this.cwd = this.toDir(startPath) || "" - this.isWaitingForOutput = false - this.tabMatches = [] - this.tabIndex = -1 - this.tabPrefix = "" + this.isPanelResizing = false; + this.fit(); + }; + + this.fit(); + this.resizeObserver = new ResizeObserver(() => this.fit()); + this.resizeObserver.observe(this.body); + window.addEventListener("resize", this.handleResize); + this.console.win.addEventListener( + "bottom-window-resize-start", + this.handlePanelResizeStart, + ); + this.console.win.addEventListener("bottom-window-resize-end", this.handlePanelResizeEnd); + + this.buffer = ""; + this.history = []; + this.historyIndex = -1; + this.cwd = this.toDir(startPath) || ""; + this.isWaitingForOutput = false; + this.tabMatches = []; + this.tabIndex = -1; + this.tabPrefix = ""; this.customCommandDescriptions = { fs: "Fullscreen mode", "-fs": "Disable fullscreen", "?": "All custom CodeMotion Terminal commands", - "cmexit": "Alias for exit command" - } + cmexit: "Alias for exit command", + }; this.customCommands = { - "fs": () => { - this.console.fullscreen(); - this.console.show(); - this.term.writeln("CodeMotion: \x1b[1;30mFullscreen on\x1b[0m") + fs: () => { + this.console.fullscreen(); + this.console.show(); + this.term.writeln("CodeMotion: \x1b[1;30mFullscreen on\x1b[0m"); }, - "-fs": () => { - this.console.fullscreen(false); - this.console.show(); - this.term.writeln("CodeMotion: \x1b[1;30mFullscreen off\x1b[0m") + "-fs": () => { + this.console.fullscreen(false); + this.console.show(); + this.term.writeln("CodeMotion: \x1b[1;30mFullscreen off\x1b[0m"); }, "?": () => { - Object.keys(this.customCommands).forEach(c => { - this.term.writeln(`${c} \x1b[1;30m${this.customCommandDescriptions[c]}\x1b[0m`) - }) + Object.keys(this.customCommands).forEach((c) => { + this.term.writeln(`${c} \x1b[1;30m${this.customCommandDescriptions[c]}\x1b[0m`); + }); }, - "cmexit": () => { - if(this.isWaitingForOutput) { - this.isWaitingForOutput = false - window.electron?.killProcess?.() - this.term.writeln("\x1b[1;30mProcess terminated\x1b[0m") - this.prompt() + cmexit: () => { + if (this.isWaitingForOutput) { + this.isWaitingForOutput = false; + window.electron?.killProcess?.(); + this.term.writeln("\x1b[1;30mProcess terminated\x1b[0m"); + this.prompt(); } else { - this.term.writeln("\x1b[1;30mNo active process to exit\x1b[0m") + this.term.writeln("\x1b[1;30mNo active process to exit\x1b[0m"); } - } - } + }, + }; - this.prompt() - this.registerEvents() - this.setupIPC() - this.console.onHide(() => this.dispose()) + this.prompt(); + this.registerEvents(); + this.setupIPC(); + this.console.onHide(() => this.dispose()); } toDir(p) { - if (!p) return "" - if (p.endsWith("/") || p.endsWith("\\")) return p - const lastSlash = Math.max(p.lastIndexOf("/"), p.lastIndexOf("\\")) - if (lastSlash <= 0) return p - const lastSegment = p.substring(lastSlash + 1) - if (lastSegment.includes(".")) return p.substring(0, lastSlash) - return p + if (!p) return ""; + if (p.endsWith("/") || p.endsWith("\\")) return p; + const lastSlash = Math.max(p.lastIndexOf("/"), p.lastIndexOf("\\")); + if (lastSlash <= 0) return p; + const lastSegment = p.substring(lastSlash + 1); + if (lastSegment.includes(".")) return p.substring(0, lastSlash); + return p; } fit() { - if (this.disposed) return - if (this.isPanelResizing) return - if (this.fitFrame) return + if (this.disposed) return; + if (this.isPanelResizing) return; + if (this.fitFrame) return; this.fitFrame = requestAnimationFrame(() => { - this.fitFrame = null - if (this.disposed) return - this.fitAddon?.fit() - }) + this.fitFrame = null; + if (this.disposed) return; + this.fitAddon?.fit(); + }); } prompt() { - this.term.write(`\r\n${this.cwd} $ `) + this.term.write(`\r\n${this.cwd} $ `); } registerEvents() { this.term.attachCustomKeyEventHandler((e) => { if (e.ctrlKey && e.shiftKey && e.code === "KeyC") { - const selection = this.term.getSelection() - if (selection) navigator.clipboard.writeText(selection) - return false + const selection = this.term.getSelection(); + if (selection) navigator.clipboard.writeText(selection); + return false; } if (e.ctrlKey && e.shiftKey && e.code === "KeyV") { - navigator.clipboard.readText().then(text => { - if (text) { - const clean = text.replace(/[\r\n]+/g, " ") - this.buffer += clean - this.term.write(clean) - } - }).catch(() => {}) - return false + navigator.clipboard + .readText() + .then((text) => { + if (text) { + const clean = text.replace(/[\r\n]+/g, " "); + this.buffer += clean; + this.term.write(clean); + } + }) + .catch(() => {}); + return false; } - return true - }) - this.term.onData(data => this.handleInput(data)) + return true; + }); + this.term.onData((data) => this.handleInput(data)); } handleInput(data) { - const code = data.charCodeAt(0) - - if(code === 3) { - if(this.isWaitingForOutput) { - this.term.write("^C\r\n") - window.electron?.killProcess?.() - this.isWaitingForOutput = false - } else if(this.buffer.length > 0) { - this.term.write("^C\r\n") - this.buffer = "" + const code = data.charCodeAt(0); + + if (code === 3) { + if (this.isWaitingForOutput) { + this.term.write("^C\r\n"); + window.electron?.killProcess?.(); + this.isWaitingForOutput = false; + } else if (this.buffer.length > 0) { + this.term.write("^C\r\n"); + this.buffer = ""; } - this.prompt() - return + this.prompt(); + return; } - if(code === 22) { - navigator.clipboard.readText().then(text => { - if (text) { - const clean = text.replace(/[\r\n]+/g, " ") - this.buffer += clean - this.term.write(clean) - } - }).catch(() => {}) - return + if (code === 22) { + navigator.clipboard + .readText() + .then((text) => { + if (text) { + const clean = text.replace(/[\r\n]+/g, " "); + this.buffer += clean; + this.term.write(clean); + } + }) + .catch(() => {}); + return; } - if(code === 13) { - this.term.write("\r\n") - this.tabMatches = [] - this.tabIndex = -1 - - if(this.isWaitingForOutput) { - const input = this.buffer + "\n" - console.log(`[Console] Sending input: "${input}"`) - window.electron?.sendInput?.(input) - this.buffer = "" - return + if (code === 13) { + this.term.write("\r\n"); + this.tabMatches = []; + this.tabIndex = -1; + + if (this.isWaitingForOutput) { + const input = this.buffer + "\n"; + console.log(`[Console] Sending input: "${input}"`); + window.electron?.sendInput?.(input); + this.buffer = ""; + return; } - - const trimmedBuffer = this.buffer.trim() - - if(!trimmedBuffer) { - this.prompt() - return + + const trimmedBuffer = this.buffer.trim(); + + if (!trimmedBuffer) { + this.prompt(); + return; } - const firstWord = trimmedBuffer.split(/\s+/)[0] - - if(this.customCommands[firstWord]) { - this.customCommands[firstWord]() - this.history.push(trimmedBuffer) - this.historyIndex = this.history.length - this.buffer = "" - this.prompt() + const firstWord = trimmedBuffer.split(/\s+/)[0]; + + if (this.customCommands[firstWord]) { + this.customCommands[firstWord](); + this.history.push(trimmedBuffer); + this.historyIndex = this.history.length; + this.buffer = ""; + this.prompt(); } else { - const cdMatch = trimmedBuffer.match(/^cd\s+(.*)$/i) + const cdMatch = trimmedBuffer.match(/^cd\s+(.*)$/i); if (cdMatch) { - const target = cdMatch[1].trim().replace(/\/$/, "") - let newPath = this.cwd + const target = cdMatch[1].trim().replace(/\/$/, ""); + let newPath = this.cwd; if (target === "..") { - const parts = this.cwd.replace(/[\\/]+$/, "").split(/[\\/]/) - parts.pop() - newPath = parts.join("\\") || "C:\\" + const parts = this.cwd.replace(/[\\/]+$/, "").split(/[\\/]/); + parts.pop(); + newPath = parts.join("\\") || "C:\\"; } else if (target === ".") { - newPath = this.cwd + newPath = this.cwd; } else if (target.includes(":\\") || target.startsWith("/")) { - newPath = target + newPath = target; } else { - newPath = this.cwd + "\\" + target + newPath = this.cwd + "\\" + target; } - this.history.push(trimmedBuffer) - this.historyIndex = this.history.length - this.buffer = "" - window.electron.readDirTree(newPath, { maxDepth: 0 }).then(res => { - if (res) { - this.cwd = newPath - } else { - this.term.writeln(`\x1b[31mcd: no such file or directory: ${target}\x1b[0m`) - } - this.prompt() - }).catch(() => { - this.term.writeln(`\x1b[31mcd: no such file or directory: ${target}\x1b[0m`) - this.prompt() - }) + this.history.push(trimmedBuffer); + this.historyIndex = this.history.length; + this.buffer = ""; + window.electron + .readDirTree(newPath, { maxDepth: 0 }) + .then((res) => { + if (res) { + this.cwd = newPath; + } else { + this.term.writeln( + `\x1b[31mcd: no such file or directory: ${target}\x1b[0m`, + ); + } + this.prompt(); + }) + .catch(() => { + this.term.writeln( + `\x1b[31mcd: no such file or directory: ${target}\x1b[0m`, + ); + this.prompt(); + }); } else { - this.history.push(trimmedBuffer) - this.historyIndex = this.history.length - this.buffer = "" - this.isWaitingForOutput = true - window.electron?.sendCommand?.({ cmd: trimmedBuffer, cwd: this.cwd }) + this.history.push(trimmedBuffer); + this.historyIndex = this.history.length; + this.buffer = ""; + this.isWaitingForOutput = true; + window.electron?.sendCommand?.({ cmd: trimmedBuffer, cwd: this.cwd }); } } } if (code === 127) { if (this.buffer.length > 0) { - this.buffer = this.buffer.slice(0, -1) - this.term.write("\b \b") + this.buffer = this.buffer.slice(0, -1); + this.term.write("\b \b"); } - return + return; } if (!this.isWaitingForOutput) { - if (data === '\x1B[A') { - if(this.historyIndex > 0) this.replaceBuffer(this.history[--this.historyIndex]) - return + if (data === "\x1B[A") { + if (this.historyIndex > 0) this.replaceBuffer(this.history[--this.historyIndex]); + return; } - if (data === '\x1B[B') { - if(this.historyIndex < this.history.length - 1) this.replaceBuffer(this.history[++this.historyIndex]) - else { this.historyIndex = this.history.length; this.replaceBuffer("") } - return + if (data === "\x1B[B") { + if (this.historyIndex < this.history.length - 1) + this.replaceBuffer(this.history[++this.historyIndex]); + else { + this.historyIndex = this.history.length; + this.replaceBuffer(""); + } + return; } } - if (data === '\t' && !this.isWaitingForOutput) { - this.autocomplete() - return + if (data === "\t" && !this.isWaitingForOutput) { + this.autocomplete(); + return; } - this.buffer += data - this.term.write(data) - if (data !== '\t') { - this.tabMatches = [] - this.tabIndex = -1 + this.buffer += data; + this.term.write(data); + if (data !== "\t") { + this.tabMatches = []; + this.tabIndex = -1; } - if(this.isWaitingForOutput) { - window.electron?.sendInput?.(data) + if (this.isWaitingForOutput) { + window.electron?.sendInput?.(data); } } replaceBuffer(str) { - while(this.buffer.length) { - this.term.write('\b \b') - this.buffer = this.buffer.slice(0, -1) + while (this.buffer.length) { + this.term.write("\b \b"); + this.buffer = this.buffer.slice(0, -1); } - this.buffer = str - this.term.write(str) + this.buffer = str; + this.term.write(str); } async autocomplete() { - const commands = Object.keys(this.customCommands) - const parts = this.buffer.split(/\s+/) - const lastPart = parts[parts.length - 1] || "" + const commands = Object.keys(this.customCommands); + const parts = this.buffer.split(/\s+/); + const lastPart = parts[parts.length - 1] || ""; if (this.tabMatches.length > 0) { - this.tabIndex = (this.tabIndex + 1) % this.tabMatches.length - const completed = this.tabMatches[this.tabIndex] + this.tabIndex = (this.tabIndex + 1) % this.tabMatches.length; + const completed = this.tabMatches[this.tabIndex]; if (parts.length <= 1 && commands.includes(completed)) { - this.replaceBuffer(completed + " ") + this.replaceBuffer(completed + " "); } else { - parts[parts.length - 1] = this.tabPrefix_path + completed - this.replaceBuffer(parts.join(" ")) + parts[parts.length - 1] = this.tabPrefix_path + completed; + this.replaceBuffer(parts.join(" ")); } - return + return; } - let dir = this.cwd - let pathPrefix = "" + let dir = this.cwd; + let pathPrefix = ""; if (lastPart.includes("/") || lastPart.includes("\\")) { - const lastSlash = Math.max(lastPart.lastIndexOf("/"), lastPart.lastIndexOf("\\")) - pathPrefix = lastPart.substring(0, lastSlash + 1) - const relDir = lastPart.substring(0, lastSlash) || lastPart.substring(0, 1) - dir = (relDir.includes(":\\") || relDir.startsWith("/")) ? relDir : this.cwd + "\\" + relDir + const lastSlash = Math.max(lastPart.lastIndexOf("/"), lastPart.lastIndexOf("\\")); + pathPrefix = lastPart.substring(0, lastSlash + 1); + const relDir = lastPart.substring(0, lastSlash) || lastPart.substring(0, 1); + dir = + relDir.includes(":\\") || relDir.startsWith("/") + ? relDir + : this.cwd + "\\" + relDir; } try { - const res = await window.electron.readDirTree(dir, { maxDepth: 0 }) - if (!res || !Array.isArray(res)) return + const res = await window.electron.readDirTree(dir, { maxDepth: 0 }); + if (!(res && Array.isArray(res))) return; - const entries = res.map(e => typeof e === "string" ? e : e.name || "") - const lower = lastPart.toLowerCase() - const fileMatches = entries.filter(e => e.toLowerCase().startsWith(lastPart.split(/[\\/]/).pop().toLowerCase())) + const entries = res.map((e) => (typeof e === "string" ? e : e.name || "")); + const lower = lastPart.toLowerCase(); + const fileMatches = entries.filter((e) => + e.toLowerCase().startsWith(lastPart.split(/[\\/]/).pop().toLowerCase()), + ); - if (fileMatches.length === 0) return + if (fileMatches.length === 0) return; - this.tabMatches = fileMatches - this.tabIndex = 0 - this.tabPrefix_path = pathPrefix + this.tabMatches = fileMatches; + this.tabIndex = 0; + this.tabPrefix_path = pathPrefix; if (fileMatches.length === 1) { - parts[parts.length - 1] = pathPrefix + fileMatches[0] - this.replaceBuffer(parts.join(" ")) + parts[parts.length - 1] = pathPrefix + fileMatches[0]; + this.replaceBuffer(parts.join(" ")); } else { - this.replaceBuffer(pathPrefix + fileMatches[0]) + this.replaceBuffer(pathPrefix + fileMatches[0]); } } catch (e) {} } parseCommand(cmd) { - const regex = /(?:[^\s"]+|"[^"]*")+/g - const args = [] - let match - while((match = regex.exec(cmd)) !== null) { - let arg = match[0] - if(arg.startsWith('"') && arg.endsWith('"')) arg = arg.slice(1,-1) - args.push(arg) + const regex = /(?:[^\s"]+|"[^"]*")+/g; + const args = []; + let match; + while ((match = regex.exec(cmd)) !== null) { + let arg = match[0]; + if (arg.startsWith('"') && arg.endsWith('"')) arg = arg.slice(1, -1); + args.push(arg); } - return args + return args; } executeCommand(cmd) { - if (!cmd) return + if (!cmd) return; - const args = this.parseCommand(cmd) - const command = args.shift() + const args = this.parseCommand(cmd); + const command = args.shift(); if (this.customCommands[command]) { - this.customCommands[command](...args) - return + this.customCommands[command](...args); + return; } - if(window.electron?.sendCommand) { - window.electron.sendCommand({ cmd, cwd: this.cwd }) + if (window.electron?.sendCommand) { + window.electron.sendCommand({ cmd, cwd: this.cwd }); } else { - this.term.writeln(`Command not found: ${command}`) + this.term.writeln(`Command not found: ${command}`); } } setupIPC() { - if(window.electron && window.electron.onCommandResult) { + if (window.electron && window.electron.onCommandResult) { this.commandResultHandler = (result) => { - if (this.disposed) return + if (this.disposed) return; - console.log('[Console] Received result:', result) - this.handleTerminalResult(result) - } + console.log("[Console] Received result:", result); + this.handleTerminalResult(result); + }; - this.removeCommandResultHandler = window.electron.onCommandResult(this.commandResultHandler) + this.removeCommandResultHandler = window.electron.onCommandResult( + this.commandResultHandler, + ); } else { - console.warn('[Console] onCommandResult not available') + console.warn("[Console] onCommandResult not available"); } } handleTerminalResult(result) { - let output = "" - let type = "output" + let output = ""; + let type = "output"; if (!result) { - console.warn('[Console] Empty result') - return + console.warn("[Console] Empty result"); + return; } - if (result && typeof result === 'object') { - type = result.type || "output" - output = result.data || result.output || result.message || "" - } else if (typeof result === 'string') { - output = result + if (result && typeof result === "object") { + type = result.type || "output"; + output = result.data || result.output || result.message || ""; + } else if (typeof result === "string") { + output = result; } else { - output = JSON.stringify(result) + output = JSON.stringify(result); } - console.log(`[Console] Type: "${type}", Output length: ${output.length}`) + console.log(`[Console] Type: "${type}", Output length: ${output.length}`); - if (!output) return + if (!output) return; - switch(type) { + switch (type) { case "error": - this.term.write("\x1b[31m" + output + "\x1b[0m") - break + this.term.write("\x1b[31m" + output + "\x1b[0m"); + break; case "warning": - this.term.write("\x1b[38;5;208m" + output + "\x1b[0m") - break + this.term.write("\x1b[38;5;208m" + output + "\x1b[0m"); + break; case "exit": - this.term.write(output) - this.isWaitingForOutput = false - this.prompt() - return + this.term.write(output); + this.isWaitingForOutput = false; + this.prompt(); + return; default: - this.term.write(output) + this.term.write(output); } - if(type === "exit") { - this.isWaitingForOutput = false - this.prompt() + if (type === "exit") { + this.isWaitingForOutput = false; + this.prompt(); } } dispose() { - if (this.disposed) return - - this.disposed = true - this.isWaitingForOutput = false - window.electron?.cleanupTerminal?.() - this.resizeObserver?.disconnect() - window.removeEventListener("resize", this.handleResize) - this.console.win.removeEventListener("bottom-window-resize-start", this.handlePanelResizeStart) - this.console.win.removeEventListener("bottom-window-resize-end", this.handlePanelResizeEnd) - this.removeCommandResultHandler?.() - if (this.fitFrame) cancelAnimationFrame(this.fitFrame) - this.term?.dispose() + if (this.disposed) return; + + this.disposed = true; + this.isWaitingForOutput = false; + window.electron?.cleanupTerminal?.(); + this.resizeObserver?.disconnect(); + window.removeEventListener("resize", this.handleResize); + this.console.win.removeEventListener( + "bottom-window-resize-start", + this.handlePanelResizeStart, + ); + this.console.win.removeEventListener("bottom-window-resize-end", this.handlePanelResizeEnd); + this.removeCommandResultHandler?.(); + if (this.fitFrame) cancelAnimationFrame(this.fitFrame); + this.term?.dispose(); } } diff --git a/assets/js/handlers/themesHandler.js b/assets/js/handlers/themesHandler.js index bfb6326..5ec2b14 100644 --- a/assets/js/handlers/themesHandler.js +++ b/assets/js/handlers/themesHandler.js @@ -1,4 +1,4 @@ -import { Setting } from "../settings.js" +import { Setting } from "../settings.js"; export function optionsThemeButtonHandler(themeSelect) { themeSelect.on("click", (item) => { @@ -6,4 +6,4 @@ export function optionsThemeButtonHandler(themeSelect) { Setting.themeSelect(id); }); -} \ No newline at end of file +} diff --git a/assets/js/iconRegistry.js b/assets/js/iconRegistry.js index 10afd52..a29bedb 100644 --- a/assets/js/iconRegistry.js +++ b/assets/js/iconRegistry.js @@ -202,7 +202,7 @@ export const ICON_MAP = { diff: "patch.svg", lock: "lock.svg", license: "license.svg", - copying: "license.svg" + copying: "license.svg", }; /** @@ -349,10 +349,10 @@ export function getFolderIcon(name, open = false) { */ export function getFileIconUrl(filename) { const icon = getFileIcon(filename); - const isAbs = isAbsolutePath(icon) + const isAbs = isAbsolutePath(icon); - if(isAbs) return icon; - else return `../assets/media/icons/symbols/files/${icon}`; + if (isAbs) return icon; + return `../assets/media/icons/symbols/files/${icon}`; } /** diff --git a/assets/js/lib.js b/assets/js/lib.js index 200e6ad..b78d586 100644 --- a/assets/js/lib.js +++ b/assets/js/lib.js @@ -1,75 +1,85 @@ -import { ErrorReporter } from "./ErrorReporter.js" -import { BottomWindow } from "./handlers/BottomWindowHandler.js" - -import { _Languages } from "./libClasses/languages.js" -import { _Dirs } from "./libClasses/dirs.js" -import { _Notificator } from "./libClasses/notificator.js" -import { _DragDrop } from "./libClasses/dragndrop.js" -import { _TopBarElement } from "./libClasses/topbarElement.js" -import { _SideBarIconManager } from "./libClasses/sidebarIconManager.js" -import { _Options } from "./libClasses/options.js" -import { _ContextMenuLoader } from "./libClasses/contextMenuLoader.js" -import { _Loader } from "./libClasses/loader.js" -import { valid } from "./modalsHandler/engine.js" -import { createDIV, createIcon } from "./modalsHandler/handlers/helpers.js" -import { _GLS } from "./libClasses/gls.js" -import { _Filenames } from "./libClasses/fillenames.js" -import { _CodeTemplates } from "./libClasses/codeTemplates.js" -import { _EditorAdapter } from "./libClasses/EditorAdapter.js" -import { _GetOrgAvatar } from "./libClasses/avatar.js" -import { _Task } from "./libClasses/task.js" - -let runtimeErrors = [] -let runtimeErrorsCount = 0 - -export const GLOBAL = {} - -export const Languages = _Languages -export const Filenames = _Filenames -export const Dirs = _Dirs -export const DragDrop = _DragDrop -export const Notificator = _Notificator -export const TopBarElement = _TopBarElement -export const SideBarIconManager = _SideBarIconManager -export const Options = _Options -export const ContextMenuLoader = _ContextMenuLoader -export const Loader = _Loader -export const GLS = _GLS -export const CodeTemplates = _CodeTemplates -export const EditorAdapter = _EditorAdapter -export const Task = _Task - -export const GetOrgAvatar = _GetOrgAvatar +import { ErrorReporter } from "./ErrorReporter.js"; +import { BottomWindow } from "./handlers/BottomWindowHandler.js"; +import { _GetOrgAvatar } from "./libClasses/avatar.js"; +import { _CodeTemplates } from "./libClasses/codeTemplates.js"; +import { _ContextMenuLoader } from "./libClasses/contextMenuLoader.js"; +import { _Dirs } from "./libClasses/dirs.js"; +import { _DragDrop } from "./libClasses/dragndrop.js"; +import { _EditorAdapter } from "./libClasses/EditorAdapter.js"; +import { _Filenames } from "./libClasses/fillenames.js"; +import { _GLS } from "./libClasses/gls.js"; +import { _Languages } from "./libClasses/languages.js"; +import { _Loader } from "./libClasses/loader.js"; +import { _Notificator } from "./libClasses/notificator.js"; +import { _Options } from "./libClasses/options.js"; +import { _SideBarIconManager } from "./libClasses/sidebarIconManager.js"; +import { _Task } from "./libClasses/task.js"; +import { _TopBarElement } from "./libClasses/topbarElement.js"; +import { valid } from "./modalsHandler/engine.js"; +import { createDIV, createIcon } from "./modalsHandler/handlers/helpers.js"; + +let runtimeErrors = []; +let runtimeErrorsCount = 0; + +export const GLOBAL = {}; + +export const Languages = _Languages; +export const Filenames = _Filenames; +export const Dirs = _Dirs; +export const DragDrop = _DragDrop; +export const Notificator = _Notificator; +export const TopBarElement = _TopBarElement; +export const SideBarIconManager = _SideBarIconManager; +export const Options = _Options; +export const ContextMenuLoader = _ContextMenuLoader; +export const Loader = _Loader; +export const GLS = _GLS; +export const CodeTemplates = _CodeTemplates; +export const EditorAdapter = _EditorAdapter; + +export const Task = _Task; + +export const GetOrgAvatar = _GetOrgAvatar; // Language: adds a image icons -const imageIcons = ["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg", "ico", "avif", "tif", "tiff", "heic", "heif"] - -imageIcons.forEach(id => { - Languages.add( - { - id: id, - name: "Image", - icon: "image", - iconExt: "svg", - mode: "text" - } - ) -}) +const imageIcons = [ + "png", + "jpg", + "jpeg", + "gif", + "webp", + "bmp", + "svg", + "ico", + "avif", + "tif", + "tiff", + "heic", + "heif", +]; + +imageIcons.forEach((id) => { + Languages.add({ + id, + name: "Image", + icon: "image", + iconExt: "svg", + mode: "text", + }); +}); // Language: adds a font icons -const fontIcons = ["ttf", "otf", "woff", "woff2", "eot"] - -fontIcons.forEach(id => { - Languages.add( - { - id: id, - name: "Font", - icon: "font", - iconExt: "svg", - mode: "text" - } - ) -}) +const fontIcons = ["ttf", "otf", "woff", "woff2", "eot"]; + +fontIcons.forEach((id) => { + Languages.add({ + id, + name: "Font", + icon: "font", + iconExt: "svg", + mode: "text", + }); +}); export const tabName = document.querySelector("#tab-name"); @@ -81,13 +91,13 @@ export function setTabNameCounter(count) { if (old) old.remove(); return; } - + if (old) old.remove(); tabName.insertAdjacentHTML("beforeend", `${count}`); } export function setTabName(text) { if (!tabName) return; - tabName.innerHTML = text + tabName.innerHTML = text; } export function toBase64(str) { @@ -113,7 +123,7 @@ export function getCodeByName(name, raw = false) { todo: "markdown", ps: "prettyscript", py: "python", - php: "php" + php: "php", }; const rawNames = { html: "html", @@ -122,7 +132,7 @@ export function getCodeByName(name, raw = false) { py: "python", md: "markdown", css: "css", - php: "php" + php: "php", }; if (!raw) return names[ext] || "plaintext"; @@ -131,140 +141,156 @@ export function getCodeByName(name, raw = false) { async function getFileIconByName(name) { // fileicon - file name // ext - extenstion of icon, default: svg - let ext = "svg" + let ext = "svg"; - let alts = { + const alts = { ps: { ext: "svg", - fileicon: "prettyscript" + fileicon: "prettyscript", }, todo: { ext: "svg", - fileicon: "todo" + fileicon: "todo", }, ttc: { ext: "svg", - fileicon: "ttf" + fileicon: "ttf", }, otf: { ext: "svg", - fileicon: "ttf" + fileicon: "ttf", }, woff: { ext: "svg", - fileicon: "ttf" - } - } + fileicon: "ttf", + }, + }; if (name in alts) { - ext = alts[name].ext - name = alts[name].fileicon - } - else { - name = getCodeByName(name).replaceAll(/[0-9]/g, "") + ext = alts[name].ext; + name = alts[name].fileicon; + } else { + name = getCodeByName(name).replaceAll(/[0-9]/g, ""); } - let list = await window.electron.getAllIcons(); - let listNames = [] + const list = await window.electron.getAllIcons(); + const listNames = []; - list.forEach(e => { - let filteredName = e.name.replaceAll("." + e.name.split(".").pop(), "") + list.forEach((e) => { + const filteredName = e.name.replaceAll("." + e.name.split(".").pop(), ""); if (filteredName != "default") { - listNames.push(e.name.replaceAll("." + e.name.split(".").pop(), "")) + listNames.push(e.name.replaceAll("." + e.name.split(".").pop(), "")); } - }) + }); if (listNames.includes(name)) { - return `./assets/media/icons/symbols/files/${name}.${ext}` - } - else { - return `./assets/media/icons/symbols/files/document.svg` + return `./assets/media/icons/symbols/files/${name}.${ext}`; } + return "./assets/media/icons/symbols/files/document.svg"; } -let inputs = document.querySelectorAll("input") +const inputs = document.querySelectorAll("input"); if (inputs.length > 0) { - inputs.forEach(input => { + inputs.forEach((input) => { input.addEventListener("input", () => { if (input.value > 0) { - input.classList.add("focused") - } - else { - input.classList.remove("focused") + input.classList.add("focused"); + } else { + input.classList.remove("focused"); } - }) - }) + }); + }); } export function capitilize(text) { - return String(text).charAt(0).toUpperCase() + String(text).slice(1) + return String(text).charAt(0).toUpperCase() + String(text).slice(1); } export function addToHistory({ id, actionType, value, desc, today }) { - const historyID = id != undefined ? id : Object.keys(historyObject).length + 1 - const historyValue = value != undefined ? value : "Untitled" - const historyDesc = desc != undefined ? desc : "No description provided" - const historyToday = today != undefined ? today : new Date().format("H:i") - - historyObject[historyID] = { - time: historyToday, - action: actionType, - value: historyValue, - description: historyDesc + const historyId = id == undefined ? Object.keys(historyObject).length + 1 : id; + const historyValue = value == undefined ? "Untitled" : value; + const historyDesc = desc == undefined ? "No description provided" : desc; + const historyToday = today == undefined ? new Date().format("H:i") : today; + + historyObject[historyId] = { + time: historyToday, + action: actionType, + value: historyValue, + description: historyDesc, }; } -export function addToBug({ id, priority, value, desc, today, isSelf, org, resolved, author, assignedTo, type }) { - const bugID = id != undefined ? id : Object.keys(bugsObject).length + 1 - const bugPriority = (priority != undefined && !Number.isNaN(priority)) ? priority : 0 - const bugDesc = desc != undefined ? desc : "No description provided" - const bugToday = today != undefined ? today : new Date().format("H:i") - const bugIsSelf = isSelf != undefined ? isSelf : false - const bugResolved = resolved != undefined ? resolved : false - const bugAuthor = author != undefined ? author : false - const bugAssignedTo = assignedTo != undefined ? assignedTo : {} - - const priorityInfo = priorityClasses[String(bugPriority)] || priorityClasses["0"] - addToHistory({ actionType: "bug-added", value: value, desc: `Bug "${value}" added with ${priorityInfo.name} priority` }); +export function addToBug({ + id, + priority, + value, + desc, + today, + isSelf, + org, + resolved, + author, + assignedTo, + type, +}) { + const bugID = id != undefined ? id : Object.keys(bugsObject).length + 1; + const bugPriority = priority != undefined && !Number.isNaN(priority) ? priority : 0; + const bugDesc = desc != undefined ? desc : "No description provided"; + const bugToday = today != undefined ? today : new Date().format("H:i"); + const bugIsSelf = isSelf != undefined ? isSelf : false; + const bugResolved = resolved != undefined ? resolved : false; + const bugAuthor = author != undefined ? author : false; + const bugAssignedTo = assignedTo != undefined ? assignedTo : {}; + + const priorityInfo = priorityClasses[String(bugPriority)] || priorityClasses["0"]; + addToHistory({ + actionType: "bug-added", + value, + desc: `Bug "${value}" added with ${priorityInfo.name} priority`, + }); bugsObject[bugID] = { id: bugID, time: bugToday, priority: bugPriority, - value: value, + value, description: bugDesc, self: bugIsSelf, organization: org, resolved: bugResolved, author: bugAuthor, assignedTo: bugAssignedTo, - type: type + type, }; - return bugsObject + return bugsObject; } export function showIndicator(time = 1500, callback) { - let statusIndicator = document.querySelector(".status-indicator") + const statusIndicator = document.querySelector(".status-indicator"); - statusIndicator.classList.remove("hidden") + statusIndicator.classList.remove("hidden"); if (typeof callback === "function") { - callback(statusIndicator) + callback(statusIndicator); } - statusIndicator.addEventListener("transitionend", () => { - setTimeout(() => { - statusIndicator.classList.add("hidden") - }, time) - }, { once: true }) + statusIndicator.addEventListener( + "transitionend", + () => { + setTimeout(() => { + statusIndicator.classList.add("hidden"); + }, time); + }, + { once: true }, + ); } export const animate = { blurReplace: ({ add, remove }) => { - if (!add || !remove) return; + if (!(add && remove)) return; add.classList.remove("hidden", "blur-hidden"); remove.classList.remove("hidden", "blur-hidden"); @@ -284,7 +310,7 @@ export const animate = { }; remove.addEventListener("transitionend", onTransitionEnd); - } + }, }; export function handlePopups() { @@ -293,7 +319,7 @@ export function handlePopups() { document.addEventListener("click", (e) => { let clickedInsidePopup = false; - popups.forEach(popup => { + popups.forEach((popup) => { const popupContent = popup.querySelector(".popup-content"); const popupTitle = popup.querySelector(".popup-title"); @@ -302,12 +328,12 @@ export function handlePopups() { const isOpen = !popupContent.classList.contains("hidden"); - popups.forEach(p => p.querySelector(".popup-content").classList.add("hidden")); - popups.forEach(p => p.querySelector(".popup-title").classList.remove("active")); + popups.forEach((p) => p.querySelector(".popup-content").classList.add("hidden")); + popups.forEach((p) => p.querySelector(".popup-title").classList.remove("active")); if (!isOpen) { popupContent.classList.remove("hidden"); - popupTitle.classList.add("active") + popupTitle.classList.add("active"); } clickedInsidePopup = true; @@ -315,7 +341,7 @@ export function handlePopups() { if (e.target.closest(".popup-content__item") && popup.contains(e.target)) { popupContent.classList.add("hidden"); - popupTitle.classList.remove("active") + popupTitle.classList.remove("active"); clickedInsidePopup = true; } @@ -325,156 +351,148 @@ export function handlePopups() { }); if (!clickedInsidePopup) { - popups.forEach(p => { p.querySelector(".popup-content").classList.add("hidden"); p.querySelector(".popup-title").classList.remove("active") }); + popups.forEach((p) => { + p.querySelector(".popup-content").classList.add("hidden"); + p.querySelector(".popup-title").classList.remove("active"); + }); } }); } export function SmoothScroll(target, speed, smooth) { if (target === document) - target = (document.scrollingElement - || document.documentElement - || document.body.parentNode - || document.body) // cross browser support for document scrolling + target = + document.scrollingElement || + document.documentElement || + document.body.parentNode || + document.body; // cross browser support for document scrolling - var moving = false - var pos = target.scrollTop - var frame = target === document.body - && document.documentElement - ? document.documentElement - : target // safari is the new IE + var moving = false; + var pos = target.scrollTop; + var frame = + target === document.body && document.documentElement ? document.documentElement : target; // safari is the new IE - target.addEventListener('mousewheel', scrolled, { passive: false }) - target.addEventListener('DOMMouseScroll', scrolled, { passive: false }) + target.addEventListener("mousewheel", scrolled, { passive: false }); + target.addEventListener("DOMMouseScroll", scrolled, { passive: false }); function scrolled(e) { e.preventDefault(); // disable default scrolling - var delta = normalizeWheelDelta(e) + var delta = normalizeWheelDelta(e); - pos += -delta * speed - pos = Math.max(0, Math.min(pos, target.scrollHeight - frame.clientHeight)) // limit scrolling + pos += -delta * speed; + pos = Math.max(0, Math.min(pos, target.scrollHeight - frame.clientHeight)); // limit scrolling - if (!moving) update() + if (!moving) update(); } function normalizeWheelDelta(e) { if (e.detail) { - if (e.wheelDelta) - return e.wheelDelta / e.detail / 40 * (e.detail > 0 ? 1 : -1) // Opera - else - return -e.detail / 3 // Firefox - } else - return e.wheelDelta / 120 // IE,Safari,Chrome + if (e.wheelDelta) return (e.wheelDelta / e.detail / 40) * (e.detail > 0 ? 1 : -1); + return -e.detail / 3; // Firefox + } + return e.wheelDelta / 120; // IE,Safari,Chrome } function update() { - moving = true + moving = true; - var delta = (pos - target.scrollTop) / smooth + var delta = (pos - target.scrollTop) / smooth; - target.scrollTop += delta + target.scrollTop += delta; - if (Math.abs(delta) > 0.5) - requestFrame(update) - else - moving = false + if (Math.abs(delta) > 0.5) requestFrame(update); + else moving = false; } - var requestFrame = function () { - return ( - window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function (func) { - window.setTimeout(func, 1000 / 50); - } - ); - }() + var requestFrame = (() => + window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + ((func) => { + window.setTimeout(func, 1000 / 50); + }))(); } export function runSandbox(code) { - const logs = [] + const logs = []; function getPos() { - const stack = new Error().stack.split("\n")[3] - const match = stack.match(/:(\d+):(\d+)/) + const stack = new Error().stack.split("\n")[3]; + const match = stack.match(/:(\d+):(\d+)/); if (match) { return { line: Number(match[1]), - col: Number(match[2]) - } + col: Number(match[2]), + }; } - return {} + return {}; } function formatArgs(args) { - return args.map(arg => { + return args.map((arg) => { if (typeof arg === "object" && arg !== null) { try { - return JSON.stringify(arg) + return JSON.stringify(arg); } catch { - return "[Object]" + return "[Object]"; } } - return arg - }) + return arg; + }); } const consoleProxy = { log: (...args) => { - const pos = getPos() + const pos = getPos(); logs.push({ type: "log", line: pos.line, col: pos.col, - args: formatArgs(args) - }) + args: formatArgs(args), + }); }, warn: (...args) => { - const pos = getPos() + const pos = getPos(); logs.push({ type: "warn", line: pos.line, col: pos.col, - args: formatArgs(args) - }) + args: formatArgs(args), + }); }, error: (...args) => { - const pos = getPos() + const pos = getPos(); logs.push({ type: "error", line: pos.line, col: pos.col, - args: formatArgs(args) - }) - } - } + args: formatArgs(args), + }); + }, + }; try { - const fn = new Function( - "console", - code + "\n//# sourceURL=sandbox.js" - ) + const fn = new Function("console", code + "\n//# sourceURL=sandbox.js"); - fn(consoleProxy) + fn(consoleProxy); } catch (e) { logs.push({ type: "error", - args: [e.message] - }) + args: [e.message], + }); } - return logs + return logs; } export function runCode(code, acorn) { try { @@ -482,91 +500,94 @@ export function runCode(code, acorn) { acorn.parse(code, { ecmaVersion: "latest", locations: true, - sourceType: "module" - }) + sourceType: "module", + }); } catch (err) { - return ErrorReporter.fromAcorn(err) + return ErrorReporter.fromAcorn(err); } try { // sandbox run check - runSandbox(code) + runSandbox(code); } catch (err) { - return ErrorReporter.fromRuntime(err) + return ErrorReporter.fromRuntime(err); } - return null + return null; } -export function addRuntimeError({ msg, line = null, col = null, time = null, isNull = false, win = null }) { - const exists = runtimeErrors.some( - e => e.msg === msg && e.line === line && e.col === col - ) +export function addRuntimeError({ + msg, + line = null, + col = null, + time = null, + isNull = false, + win = null, +}) { + const exists = runtimeErrors.some((e) => e.msg === msg && e.line === line && e.col === col); - const wrapper = BottomWindow.get("errorsHistory") - const badge = document.querySelector("#runtimeErrors .badge") - const el = document.createElement("div") - const items = document.querySelectorAll(".runtime-item#runTimeErrorItem") - const lastItem = items[items.length - 1] + const wrapper = BottomWindow.get("errorsHistory"); + const badge = document.querySelector("#runtimeErrors .badge"); + const el = document.createElement("div"); + const items = document.querySelectorAll(".runtime-item#runTimeErrorItem"); + const lastItem = items[items.length - 1]; - if (isNull && lastItem?.classList.contains("success")) return - if (exists) return + if (isNull && lastItem?.classList.contains("success")) return; + if (exists) return; - const error = { msg, line, col } + const error = { msg, line, col }; - if (!isNull) { - runtimeErrors.push(error) - runtimeErrorsCount += 1 - } - else { - runtimeErrors = [] - badge.classList.add("hidden") + if (isNull) { + runtimeErrors = []; + badge.classList.add("hidden"); + } else { + runtimeErrors.push(error); + runtimeErrorsCount += 1; } - badge.classList.remove("hidden") - badge.textContent = runtimeErrors.length + badge.classList.remove("hidden"); + badge.textContent = runtimeErrors.length; if (runtimeErrors.length == 0) { - badge.classList.add("hidden") + badge.classList.add("hidden"); } - items.forEach(e => { e.classList.add("prev") }) + items.forEach((e) => { + e.classList.add("prev"); + }); - el.classList.add("runtime-item", "bottom-window__item") - el.id = "runTimeErrorItem" + el.classList.add("runtime-item", "bottom-window__item"); + el.id = "runTimeErrorItem"; - if (!isNull) { - el.innerHTML = ` - error - ${msg} - ${line !== null ? `${line}:${col ?? 0}` : ""} - ${time !== null ? `${formatUnix(time)}` : ""} - ` - } - else { - el.classList.add("success") + if (isNull) { + el.classList.add("success"); el.innerHTML = ` check_circle All errors fixed ${runtimeErrorsCount > 0 ? `(${runtimeErrorsCount})` : ""} - ${time !== null ? `${formatUnix(time)}` : ""} - ` - runtimeErrorsCount = 0 + ${time === null ? "" : `${formatUnix(time)}`} + `; + runtimeErrorsCount = 0; + } else { + el.innerHTML = ` + error + ${msg} + ${line === null ? "" : `${line}:${col ?? 0}`} + ${time === null ? "" : `${formatUnix(time)}`} + `; } - wrapper.add(el) + wrapper.add(el); - wrapper.win.lastElementChild.scrollIntoView({ behavior: 'smooth', block: 'end' }); + wrapper.win.lastElementChild.scrollIntoView({ behavior: "smooth", block: "end" }); } export function clearRuntimeErrors() { - runtimeErrors = [] - runtimeErrorsCount = 0 + runtimeErrors = []; + runtimeErrorsCount = 0; - addRuntimeError( - { - isNull: true, - time: Math.floor(Date.now() / 1000) - } - ) + addRuntimeError({ + isNull: true, + time: Math.floor(Date.now() / 1000), + }); } export function formatUnix(ts, format = "{dd}.{mm}.{yyyy}, {hh}:{ii}:{ss}") { @@ -580,24 +601,25 @@ export function formatUnix(ts, format = "{dd}.{mm}.{yyyy}, {hh}:{ii}:{ss}") { const ii = String(date.getMinutes()).padStart(2, "0"); const ss = String(date.getSeconds()).padStart(2, "0"); - if(format) { + if (format) { return format .replaceAll("{dd}", dd) .replaceAll("{mm}", mm) .replaceAll("{hh}", hh) .replaceAll("{ii}", ii) .replaceAll("{ss}", ss) - .replaceAll("{yyyy}", yyyy) - } - else { - return `${dd}.${mm}, ${hh}:${ii}:${ss}`; + .replaceAll("{yyyy}", yyyy); } + return `${dd}.${mm}, ${hh}:${ii}:${ss}`; } export function getInitials(name) { - if (!name) return 'A'; + if (!name) return "A"; const words = name.trim().split(/\s+/); - return words.slice(0, 2).map(w => w[0].toUpperCase()).join(''); + return words + .slice(0, 2) + .map((w) => w[0].toUpperCase()) + .join(""); } export function generateAvatar(name) { @@ -614,46 +636,46 @@ export function generateAvatar(name) { const hslToHex = (h, s, l) => { s /= 100; l /= 100; - const k = n => (n + h / 30) % 12; + const k = (n) => (n + h / 30) % 12; const a = s * Math.min(l, 1 - l); - const f = n => + const f = (n) => Math.round(255 * (l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1))))) .toString(16) - .padStart(2, '0'); + .padStart(2, "0"); return `#${f(0)}${f(8)}${f(4)}`; }; return { foreground: hslToHex(hue, saturation, fgLightness), background: hslToHex(hue, saturation, bgLightness), - background_second: hslToHex(hue, saturation, bgLightness - 10) + background_second: hslToHex(hue, saturation, bgLightness - 10), }; } - let initials = getInitials(name) - let color = stringToColorPair(name) + const initials = getInitials(name); + const color = stringToColorPair(name); - const generated = document.createElement("div") - generated.classList.add("generated-avatar") - generated.style.cssText = `--background: ${color.background};--background-second: ${color.background_second};--foreground: ${color.foreground};` - generated.textContent = initials + const generated = document.createElement("div"); + generated.classList.add("generated-avatar"); + generated.style.cssText = `--background: ${color.background};--background-second: ${color.background_second};--foreground: ${color.foreground};`; + generated.textContent = initials; - return generated.outerHTML + return generated.outerHTML; } export function isFloat(n) { - return typeof n === 'number' && !Number.isInteger(n); + return typeof n === "number" && !Number.isInteger(n); } export function isStringifiedObject(str) { try { const parsed = JSON.parse(str); - if (Array.isArray(parsed)) return "array" - if (typeof parsed === 'object' && parsed !== null) { - return "object" + if (Array.isArray(parsed)) return "array"; + if (typeof parsed === "object" && parsed !== null) { + return "object"; } - return null + return null; } catch (e) { return false; } @@ -664,62 +686,68 @@ export function truncateString(str, maxLength) { return str; } - return str.slice(0, maxLength) + '...'; + return str.slice(0, maxLength) + "..."; } export function createNotify(properties = {}) { - const timeDefault = 3000 + const timeDefault = 3000; - const type = valid(properties.type) ?? "info_i" - const icon = valid(properties.icon) ?? "info_i" - const title = valid(properties.title) ?? "Untitled" - const content = valid(properties.content) ?? "No description provided" - let time = valid(properties.time) ?? 3000 - const image = valid(properties.image) ?? false + const type = valid(properties.type) ?? "info_i"; + const icon = valid(properties.icon) ?? "info_i"; + const title = valid(properties.title) ?? "Untitled"; + const content = valid(properties.content) ?? "No description provided"; + let time = valid(properties.time) ?? 3000; + const image = valid(properties.image) ?? false; - if(time < timeDefault) { - time = timeDefault + if (time < timeDefault) { + time = timeDefault; } - if(time > 10000) { - time = timeDefault + if (time > 10_000) { + time = timeDefault; } const notifyObject = { - title: title, + title, description: content, - timeout: time - } + timeout: time, + }; - if(icon) notifyObject["icon"] = icon - if(type) notifyObject["type"] = type - if(image) notifyObject["image"] = image + if (icon) notifyObject["icon"] = icon; + if (type) notifyObject["type"] = type; + if (image) notifyObject["image"] = image; - window.electron.createNotification(notifyObject) + window.electron.createNotification(notifyObject); } export function getTheme() { - return document.body.getAttribute("theme") != null ? document.body.getAttribute("theme") : "default" + return document.body.getAttribute("theme") == null + ? "default" + : document.body.getAttribute("theme"); } export function handleOnWheelScrollX() { - const elements = document.querySelectorAll(".code-tabs, .commands .commands-suggest") - - elements.forEach(el => { - el.addEventListener("wheel", (event) => { - event.preventDefault() - - el.scrollBy({ - left: event.deltaY / 5 - }) - }, { passive: false }) - }) + const elements = document.querySelectorAll(".code-tabs, .commands .commands-suggest"); + + elements.forEach((el) => { + el.addEventListener( + "wheel", + (event) => { + event.preventDefault(); + + el.scrollBy({ + left: event.deltaY / 5, + }); + }, + { passive: false }, + ); + }); } export function idify(string) { const bytes = new TextEncoder().encode(string); let binary = ""; - bytes.forEach(b => binary += String.fromCharCode(b)); + bytes.forEach((b) => (binary += String.fromCharCode(b))); return btoa(binary).replaceAll("=", ""); } @@ -727,7 +755,7 @@ export function idify(string) { export function linkify(text) { return text.replace( /(https?:\/\/[^\s<]+)/g, - '$1' + '$1', ); } @@ -735,110 +763,105 @@ export function splitCamelCase(str) { return str .replace(/([a-z])([A-Z])/g, "$1 $2") .split(" ") - .map((w, i) => i === 0 - ? w.charAt(0).toUpperCase() + w.slice(1) - : w.toLowerCase() - ) + .map((w, i) => (i === 0 ? w.charAt(0).toUpperCase() + w.slice(1) : w.toLowerCase())); } export function copyText(text) { - navigator.clipboard.writeText(text).then(() => { - console.log("Text copied to clipboard successfully!"); - }).catch(err => { - console.error('Failed to copy text: ', err); - }); + navigator.clipboard + .writeText(text) + .then(() => { + console.log("Text copied to clipboard successfully!"); + }) + .catch((err) => { + console.error("Failed to copy text: ", err); + }); } export function normalizePath(path) { - return path - .replaceAll("\\", "/") - .replaceAll(/\\/g, "/") + return path.replaceAll("\\", "/").replaceAll(/\\/g, "/"); } export function parseTwemojiString(text) { return twemoji.parse(text, { folder: "svg", - ext: ".svg" - }) + ext: ".svg", + }); } export function parseTwemojiElement(element) { - if (!element) return + if (!element) return; twemoji.parse(element, { folder: "svg", - ext: ".svg" - }) + ext: ".svg", + }); } export function scrollToBottomSmooth(el) { el.scrollTo({ top: el.scrollHeight, - behavior: "smooth" + behavior: "smooth", }); } export function getAllCSSVariables() { return Array.from(document.styleSheets) - .filter( - sheet => - sheet.href === null || sheet.href.startsWith(window.location.origin) - ) + .filter((sheet) => sheet.href === null || sheet.href.startsWith(window.location.origin)) .reduce( (acc, sheet) => - (acc = [ - ...acc, - ...Array.from(sheet.cssRules).reduce( - (def, rule) => - (def = - rule.selectorText === ":root" - ? [ - ...def, - ...Array.from(rule.style).filter(name => - name.startsWith("--") - ) - ] - : def), - [] - ) - ]), - [] + (acc = [ + ...acc, + ...Array.from(sheet.cssRules).reduce( + (def, rule) => + (def = + rule.selectorText === ":root" + ? [ + ...def, + ...Array.from(rule.style).filter((name) => + name.startsWith("--"), + ), + ] + : def), + [], + ), + ]), + [], ); } export function type(value) { - const str = value.toString().trim() + const str = value.toString().trim(); - if (/^-?\d+$/.test(str)) return "int" - if (/^-?\d*\.\d+$/.test(str)) return "float" - if (/^(true|false)$/.test(str)) return "boolean" - if (/^\[.*\]$/.test(str)) return "array" - if (/^\{.*\}$/.test(str)) return "object" + if (/^-?\d+$/.test(str)) return "int"; + if (/^-?\d*\.\d+$/.test(str)) return "float"; + if (/^(true|false)$/.test(str)) return "boolean"; + if (/^\[.*\]$/.test(str)) return "array"; + if (/^\{.*\}$/.test(str)) return "object"; - return "string" + return "string"; } export function eventLog(...args) { - console.warn(`[EVENT LOG] -----------\n`, ...args) + console.warn("[EVENT LOG] -----------\n", ...args); } -const CODE_WINDOW_VISUALS_TABS = document.querySelector(".code-tabs") -const CODE_WINDOW_VISUALS_FOOTER = document.querySelector(".code-footer") +const CODE_WINDOW_VISUALS_TABS = document.querySelector(".code-tabs"); +const CODE_WINDOW_VISUALS_FOOTER = document.querySelector(".code-footer"); export function isObject(item) { - return typeof item == "object" && !Array.isArray(item) + return typeof item == "object" && !Array.isArray(item); } export function isArray(item) { - return typeof item == "object" && Array.isArray(item) + return typeof item == "object" && Array.isArray(item); } export function showCodeWindowVisuals() { - CODE_WINDOW_VISUALS_TABS.classList.remove("hidden") - CODE_WINDOW_VISUALS_FOOTER.classList.remove("hidden") + CODE_WINDOW_VISUALS_TABS.classList.remove("hidden"); + CODE_WINDOW_VISUALS_FOOTER.classList.remove("hidden"); } export function hideCodeWindowVisuals() { - CODE_WINDOW_VISUALS_TABS.classList.add("hidden") - CODE_WINDOW_VISUALS_FOOTER.classList.add("hidden") + CODE_WINDOW_VISUALS_TABS.classList.add("hidden"); + CODE_WINDOW_VISUALS_FOOTER.classList.add("hidden"); } export function changeTagName(oldElement, newTagName) { @@ -856,19 +879,27 @@ export function changeTagName(oldElement, newTagName) { } export function showNeedReloadTopBar() { - const needToReloadTopBar = new TopBarElement("needReload") - needToReloadTopBar.content({ icon: "cached", text: "You need to reload application", type: "danger" }) + const needToReloadTopBar = new TopBarElement("needReload"); + needToReloadTopBar.content({ + icon: "cached", + text: "You need to reload application", + type: "danger", + }); setTimeout(() => { - needToReloadTopBar.show() + needToReloadTopBar.show(); setTimeout(() => { - needToReloadTopBar.hide({ iconVisible: true }) - }, 3000) - }, 1000) + needToReloadTopBar.hide({ iconVisible: true }); + }, 3000); + }, 1000); - needToReloadTopBar.on("hover", (instance) => { instance.show() }) - needToReloadTopBar.on("unhover", (instance) => { instance.hide({ iconVisible: true }) }) + needToReloadTopBar.on("hover", (instance) => { + instance.show(); + }); + needToReloadTopBar.on("unhover", (instance) => { + instance.hide({ iconVisible: true }); + }); } export function secondsToMinutes(seconds) { @@ -879,27 +910,28 @@ export function transparentColor(color, alpha = 1) { alpha = Math.max(0, Math.min(1, alpha)); color = color.trim(); - if (color.startsWith('#')) { + if (color.startsWith("#")) { let hex = color.slice(1); if (hex.length === 3) { - hex = hex.split('').map(c => c + c).join(''); + hex = hex + .split("") + .map((c) => c + c) + .join(""); } if (hex.length !== 6) { - throw new Error('Invalid HEX color'); + throw new Error("Invalid HEX color"); } - const r = parseInt(hex.slice(0, 2), 16); - const g = parseInt(hex.slice(2, 4), 16); - const b = parseInt(hex.slice(4, 6), 16); + const r = Number.parseInt(hex.slice(0, 2), 16); + const g = Number.parseInt(hex.slice(2, 4), 16); + const b = Number.parseInt(hex.slice(4, 6), 16); return `rgba(${r}, ${g}, ${b}, ${alpha})`; } - const match = color.match( - /^rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)(?:[,\s/]+([\d.]+))?\s*\)$/i - ); + const match = color.match(/^rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)(?:[,\s/]+([\d.]+))?\s*\)$/i); if (match) { const [, r, g, b] = match; @@ -907,19 +939,17 @@ export function transparentColor(color, alpha = 1) { return `rgba(${r}, ${g}, ${b}, ${alpha})`; } - throw new Error('Unsupported color format'); + throw new Error("Unsupported color format"); } export function dedent(str) { const lines = str.replace(/^\n/, "").split("\n"); const indent = Math.min( - ...lines - .filter(line => line.trim()) - .map(line => line.match(/^ */)[0].length) + ...lines.filter((line) => line.trim()).map((line) => line.match(/^ */)[0].length), ); return lines - .map(line => line.slice(indent)) + .map((line) => line.slice(indent)) .join("\n") .trimEnd(); } @@ -927,20 +957,17 @@ export function fitAceHeight(editor, minHeight = 50, maxHeight = 800) { const lines = editor.session.getLength(); const lineHeight = editor.renderer.lineHeight; - const height = Math.min( - maxHeight, - Math.max(minHeight, lines * lineHeight) - ); + const height = Math.min(maxHeight, Math.max(minHeight, lines * lineHeight)); editor.container.style.height = height + "px"; editor.resize(); } export function setAppTitle(title) { - window.electron.setAppTitle(title) + window.electron.setAppTitle(title); } export async function getGithubToken() { - const localData = await window.electron.getLocal() + const localData = await window.electron.getLocal(); if ( localData && @@ -948,14 +975,14 @@ export async function getGithubToken() { typeof localData.githubToken === "string" && localData.githubToken.length > 0 ) { - return localData.githubToken + return localData.githubToken; } - return false + return false; } -window.Notificator = Notificator -window.addToBug = addToBug -window.addToHistory = addToHistory -window.showIndicator = showIndicator -window.animate = animate \ No newline at end of file +window.Notificator = Notificator; +window.addToBug = addToBug; +window.addToHistory = addToHistory; +window.showIndicator = showIndicator; +window.animate = animate; diff --git a/assets/js/libClasses/EditorAdapter.js b/assets/js/libClasses/EditorAdapter.js index eb62575..3e2666e 100644 --- a/assets/js/libClasses/EditorAdapter.js +++ b/assets/js/libClasses/EditorAdapter.js @@ -1,44 +1,48 @@ +import { fromJSONToTextMate } from "../../../app/dist-esm/textmate/compile.js"; import { Languages } from "../lib.js"; -import { fromJSONToTextMate } from "../../../app/dist-esm/textmate/compile.js" export class _EditorAdapter { - constructor( - { - view, compartments, setOnChange, commands, recreateState, editorView, - editorState, tools - } - ) { - this.instance = view + constructor({ + view, + compartments, + setOnChange, + commands, + recreateState, + editorView, + editorState, + tools, + }) { + this.instance = view; this.languageCompartment = compartments.languageCompartment; this.themeCompartment = compartments.themeCompartment; - this.tabSizeCompartment = compartments.tabSizeCompartment + this.tabSizeCompartment = compartments.tabSizeCompartment; this.setDiagnosticsInternal = compartments.setDiagnostics; - this.wordWrapCompartment = compartments.wordWrapCompartment - this.scrollCompartment = compartments.scrollCompartment - this.readOnlyCompartment = compartments.readOnlyCompartment + this.wordWrapCompartment = compartments.wordWrapCompartment; + this.scrollCompartment = compartments.scrollCompartment; + this.readOnlyCompartment = compartments.readOnlyCompartment; this.setOnChangeInternal = setOnChange; - this.commands = commands - this.recreateState = recreateState + this.commands = commands; + this.recreateState = recreateState; - this.editorView = editorView - this.editorState = editorState - this.tools = tools + this.editorView = editorView; + this.editorState = editorState; + this.tools = tools; - this.language = undefined - this.theme = undefined - this.tabSize = undefined - this.listeners = {} + this.language = undefined; + this.theme = undefined; + this.tabSize = undefined; + this.listeners = {}; - this.dom = view.dom + this.dom = view.dom; } - // + // // other - // + // openSearch() { - this.commands.openSearchPanel(this.instance) + this.commands.openSearchPanel(this.instance); } resetUndoManager() { @@ -50,10 +54,10 @@ export class _EditorAdapter { effects: this.scrollCompartment.reconfigure( this.editorView.theme({ ".cm-content": { - paddingBottom: value === 0 ? "0px" : `${value * 100}vh` - } - }) - ) + paddingBottom: value === 0 ? "0px" : `${value * 100}vh`, + }, + }), + ), }); return this; @@ -64,38 +68,38 @@ export class _EditorAdapter { // getValue() { - return this.instance.state.doc.toString() + return this.instance.state.doc.toString(); } getTheme() { - return this.theme + return this.theme; } getSelectedText() { - const { from, to } = this.instance.state.selection.main - return this.instance.state.sliceDoc(from, to) + const { from, to } = this.instance.state.selection.main; + return this.instance.state.sliceDoc(from, to); } getCurrentLanguage() { - return this.language + return this.language; } getAnnotations() { - return [] + return []; } getScrollTop() { - return this.instance.scrollDOM.scrollTop + return this.instance.scrollDOM.scrollTop; } getCursorPosition() { - const pos = this.instance.state.selection.main.head - const line = this.instance.state.doc.lineAt(pos) + const pos = this.instance.state.selection.main.head; + const line = this.instance.state.doc.lineAt(pos); return { row: line.number - 1, - column: pos - line.from - } + column: pos - line.from, + }; } // lines api @@ -112,7 +116,7 @@ export class _EditorAdapter { } currentLanguageId() { - return this.language + return this.language; } removeFullLines(fromRow, toRow = fromRow) { @@ -127,8 +131,8 @@ export class _EditorAdapter { this.instance.dispatch({ changes: { from: fromLine.from, - to: toLine.to < doc.length ? toLine.to + 1 : toLine.to - } + to: toLine.to < doc.length ? toLine.to + 1 : toLine.to, + }, }); } @@ -141,8 +145,8 @@ export class _EditorAdapter { view.dispatch({ changes: { from: line.from, - to: line.to < state.doc.length ? line.to + 1 : line.to - } + to: line.to < state.doc.length ? line.to + 1 : line.to, + }, }); } @@ -151,12 +155,12 @@ export class _EditorAdapter { changes: { from: range.start, to: range.end, - insert: text - } + insert: text, + }, }); } - // + // // // setters @@ -164,9 +168,7 @@ export class _EditorAdapter { readOnly(enabled) { this.instance.dispatch({ - effects: this.readOnlyCompartment.reconfigure( - this.editorState.readOnly.of(enabled) - ) + effects: this.readOnlyCompartment.reconfigure(this.editorState.readOnly.of(enabled)), }); return this; @@ -175,8 +177,8 @@ export class _EditorAdapter { wordWrap(enabled) { this.instance.dispatch({ effects: this.wordWrapCompartment.reconfigure( - enabled ? this.editorView.lineWrapping : [] - ) + enabled ? this.editorView.lineWrapping : [], + ), }); return this; @@ -185,7 +187,7 @@ export class _EditorAdapter { setMaxLines(lines) { const container = this.instance.dom.parentElement; - if (lines === Infinity) { + if (lines === Number.POSITIVE_INFINITY) { container.style.height = "auto"; container.style.maxHeight = ""; } else { @@ -203,22 +205,22 @@ export class _EditorAdapter { changes: { from: 0, to: this.instance.state.doc.length, - insert: value - } - }) + insert: value, + }, + }); } setLanguage(name) { this.language = name; const langInfo = Languages.get(name); - const mode = langInfo ? langInfo.mode : (name || "text"); + const mode = langInfo ? langInfo.mode : name || "text"; const targetLang = window.CodeMirror?.Languages?.[mode]; if (targetLang) { this.instance.dispatch({ - effects: this.languageCompartment.reconfigure(targetLang) + effects: this.languageCompartment.reconfigure(targetLang), }); } } @@ -231,10 +233,10 @@ export class _EditorAdapter { return; } - this.theme = name + this.theme = name; this.instance.dispatch({ - effects: this.themeCompartment.reconfigure(theme) + effects: this.themeCompartment.reconfigure(theme), }); } @@ -246,10 +248,10 @@ export class _EditorAdapter { return; } - this.tabSize = size + this.tabSize = size; this.instance.dispatch({ - effects: this.tabSizeCompartment.reconfigure(tabSize) + effects: this.tabSizeCompartment.reconfigure(tabSize), }); } @@ -270,17 +272,17 @@ export class _EditorAdapter { } setScrollTop(value) { - this.instance.scrollDOM.scrollTop = value + this.instance.scrollDOM.scrollTop = value; } moveCursorTo(row, column) { - const line = this.instance.state.doc.line(row + 1) + const line = this.instance.state.doc.line(row + 1); this.instance.dispatch({ selection: { - anchor: line.from + column - } - }) + anchor: line.from + column, + }, + }); } // @@ -288,22 +290,18 @@ export class _EditorAdapter { // pasteContent(text) { - this.instance.dispatch( - this.instance.state.replaceSelection(text) - ); + this.instance.dispatch(this.instance.state.replaceSelection(text)); } async pasteBufferContent() { const text = await navigator.clipboard.readText(); - this.instance.dispatch( - this.instance.state.replaceSelection(text) - ); + this.instance.dispatch(this.instance.state.replaceSelection(text)); } selectAll() { this.instance.focus(); - this.commands.selectAll(this.instance) + this.commands.selectAll(this.instance); } duplicateSelection() { @@ -317,12 +315,12 @@ export class _EditorAdapter { view.dispatch({ changes: { from: to, - insert: text + insert: text, }, selection: { anchor: to, - head: to + text.length - } + head: to + text.length, + }, }); return; @@ -333,26 +331,26 @@ export class _EditorAdapter { view.dispatch({ changes: { from: line.to, - insert: "\n" + line.text + insert: "\n" + line.text, }, selection: { anchor: from + line.length + 1, - head: from + line.length + 1 - } + head: from + line.length + 1, + }, }); } undo() { - this.commands.undo(this.instance) + this.commands.undo(this.instance); } redo() { - this.commands.redo(this.instance) + this.commands.redo(this.instance); } toggleCommentLine() { - this.instance.focus() - this.commands.toggleComment(this.instance) + this.instance.focus(); + this.commands.toggleComment(this.instance); } // @@ -360,19 +358,19 @@ export class _EditorAdapter { // onWheel(cb) { - this.instance.scrollDOM.addEventListener("wheel", cb) + this.instance.scrollDOM.addEventListener("wheel", cb); } onMouseDown(cb) { - this.instance.dom.addEventListener("mousedown", cb) + this.instance.dom.addEventListener("mousedown", cb); } onFocus(cb) { - this.instance.dom.addEventListener("focus", cb) + this.instance.dom.addEventListener("focus", cb); } onClick(cb) { - this.instance.dom.addEventListener("click", cb) + this.instance.dom.addEventListener("click", cb); } onChange(cb) { @@ -380,34 +378,38 @@ export class _EditorAdapter { } onChangeCursor(cb) { - this.listeners.cursor = cb + this.listeners.cursor = cb; } onAfterRender(cb) { - this.listeners.render = cb + this.listeners.render = cb; } on(name, cb) { - this.listeners[name] = cb + this.listeners[name] = cb; } off(name) { - delete this.listeners[name] + delete this.listeners[name]; } // regs static async registerLanguage({ id, rules }) { - const { keywords, comment, operators, types } = rules.syntax + const { keywords, comment, operators, types } = rules.syntax; const textMateCompiled = fromJSONToTextMate({ - id, keywords, comment, operators, types - }) + id, + keywords, + comment, + operators, + types, + }); return await window.CodeMirror.registerLanguage({ - id: id, + id, grammar: textMateCompiled, - extends: rules.extends - }) + extends: rules.extends, + }); } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/avatar.js b/assets/js/libClasses/avatar.js index d3c431b..163adf8 100644 --- a/assets/js/libClasses/avatar.js +++ b/assets/js/libClasses/avatar.js @@ -4,7 +4,7 @@ export class _GetOrgAvatar { static async get(id, size = "default") { if (!id || id <= 0) return false; - const url = `${host}/media/org-avatar/${id}.jpg?s=${size}&v=${Math.floor(Math.random() * 99999)}`; + const url = `${host}/media/org-avatar/${id}.jpg?s=${size}&v=${Math.floor(Math.random() * 99_999)}`; try { const response = await fetch(url, { @@ -17,4 +17,4 @@ export class _GetOrgAvatar { return false; } } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/codeTemplates.js b/assets/js/libClasses/codeTemplates.js index 0f1e014..2d2ebe3 100644 --- a/assets/js/libClasses/codeTemplates.js +++ b/assets/js/libClasses/codeTemplates.js @@ -6,12 +6,12 @@ export class _CodeTemplates { content: ` document.addEventListener("DOMContentLoaded", () => { - });` + });`, }, { name: "Utility template", - content: `"use strict";` - } + content: `"use strict";`, + }, ], html: [ { @@ -27,7 +27,7 @@ export class _CodeTemplates { \t - ` + `, }, { name: "Basic HTML Template with CSS & JS", @@ -46,8 +46,8 @@ export class _CodeTemplates { \t - ` - } + `, + }, ], php: [ { @@ -56,23 +56,23 @@ export class _CodeTemplates { { - e.preventDefault() - }) + el.addEventListener("dragover", (e) => { + e.preventDefault(); + }); } onDrop(callback = () => {}) { - this.el.addEventListener('drop', async (e) => { + this.el.addEventListener("drop", async (e) => { e.preventDefault(); const files = e.dataTransfer.files; for (const file of files) { const text = await file.text(); - const name = file.name + const name = file.name; - callback({ content: text, name: name, extension: name.split(".").pop() }) + callback({ content: text, name, extension: name.split(".").pop() }); } }); } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/fillenames.js b/assets/js/libClasses/fillenames.js index cb16f43..0d66063 100644 --- a/assets/js/libClasses/fillenames.js +++ b/assets/js/libClasses/fillenames.js @@ -5,93 +5,87 @@ export class _Filenames { icon: "tsconfig", iconExt: "svg", mode: "json", - color: "#2e70ff" + color: "#2e70ff", }, - "LICENSE": { + LICENSE: { name: "License file", icon: "license", iconExt: "svg", mode: "text", - color: "#929292" + color: "#929292", }, "package.json": { name: "NPM Package file", icon: "npm", iconExt: "svg", mode: "json", - color: "#ff2828" + color: "#ff2828", }, "package-lock.json": { name: "NPM Package file", icon: "npm", iconExt: "svg", mode: "json", - color: "#ff2828" + color: "#ff2828", }, "go.mod": { name: "GO Mod File", icon: "gomod", iconExt: "svg", mode: "gomod", - color: "#eecb80" - } - } + color: "#eecb80", + }, + }; static add(name, properties) { - this.filenames[name] = properties + _Filenames.filenames[name] = properties; } static list() { - return this.filenames + return _Filenames.filenames; } static get(name) { - if (name in this.filenames) { - return this.filenames[name] - } - else { - return false + if (name in _Filenames.filenames) { + return _Filenames.filenames[name]; } + return false; } static async getIcon(name) { - let info = this.get(name) - let allFilenamesIcons = await window.electron.getAllFilenamesIcons() + const info = _Filenames.get(name); + let allFilenamesIcons = await window.electron.getAllFilenamesIcons(); - allFilenamesIcons = allFilenamesIcons.map(item => { if (item.type != "folder") return item.name }) - allFilenamesIcons = allFilenamesIcons.filter(item => item != undefined) + allFilenamesIcons = allFilenamesIcons.map((item) => { + if (item.type != "folder") return item.name; + }); + allFilenamesIcons = allFilenamesIcons.filter((item) => item != undefined); - if (name in this.filenames) { - let fileName = `${this.filenames[name].icon}.${this.filenames[name].iconExt}` + if (name in _Filenames.filenames) { + let fileName = `${_Filenames.filenames[name].icon}.${_Filenames.filenames[name].iconExt}`; if (info.customIcon) { - fileName = this.filenames[name].icon + fileName = _Filenames.filenames[name].icon; } if (allFilenamesIcons.includes(fileName)) { - return fileName + return fileName; } - else { - return fileName - } - } - else { - return false + return fileName; } + return false; } static async getIconPath(name) { - let info = this.get(name) - let icon = await this.getIcon(name) + const info = _Filenames.get(name); + const icon = await _Filenames.getIcon(name); if (info.customIcon) { - return icon - } - else if(icon) { - return `../assets/media/icons/symbols/files/${icon}` + return icon; } - else { - return false + if (icon) { + return `../assets/media/icons/symbols/files/${icon}`; } + return false; } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/gls.js b/assets/js/libClasses/gls.js index ed5b84b..1d65999 100644 --- a/assets/js/libClasses/gls.js +++ b/assets/js/libClasses/gls.js @@ -1,74 +1,74 @@ -import { bus } from "../bus.js" -import { readSettings } from "../global.js" +import { bus } from "../bus.js"; +import { readSettings } from "../global.js"; export class _GLS { constructor(registry, currentLang) { - this.registry = registry - this.currentLang = currentLang + this.registry = registry; + this.currentLang = currentLang; } static _create(registry, currentLang) { - const gls = new _GLS(registry, currentLang) + const gls = new _GLS(registry, currentLang); bus.addEventListener("extension-localization-register", (event) => { - const name = event.detail.langName - const content = event.detail.configContent + const name = event.detail.langName; + const content = event.detail.configContent; - registry[name] = content - }) + registry[name] = content; + }); - return gls + return gls; } static async init(language) { - const settings = await readSettings() - const baseLanguages = await window.electron.getAllLanguagesJSON() + const settings = await readSettings(); + const baseLanguages = await window.electron.getAllLanguagesJSON(); - const registry = { ...baseLanguages } - const currentLang = language ?? settings?.app?.language + const registry = { ...baseLanguages }; + const currentLang = language ?? settings?.app?.language; - return this._create(registry, currentLang) + return _GLS._create(registry, currentLang); } static initLocal() { - const registry = JSON.parse(localStorage.getItem("gls") ?? "{}") - const currentLang = localStorage.getItem("gls.current") + const registry = JSON.parse(localStorage.getItem("gls") ?? "{}"); + const currentLang = localStorage.getItem("gls.current"); - return this._create(registry, currentLang) + return _GLS._create(registry, currentLang); } setLanguage(lang) { - this.currentLang = lang + this.currentLang = lang; } get(key, replacements, depth = 0) { - if (depth > 10) return key + if (depth > 10) return key; - const langPack = this.registry[this.currentLang] - if (!langPack) return key + const langPack = this.registry[this.currentLang]; + if (!langPack) return key; - const parts = key.split(".") - let current = langPack + const parts = key.split("."); + let current = langPack; for (let i = 0; i < parts.length; i++) { - if (current == null) return key - current = current[parts[i]] - if (current === undefined) return key + if (current == null) return key; + current = current[parts[i]]; + if (current === undefined) return key; } if (typeof current !== "string") { - current = String(current) + current = String(current); } - current = current.replace(/\{\{\s*([^{}]+?)\s*\}\}/g, (_, path) => { - return this.get(path.trim(), replacements, depth + 1) - }) + current = current.replace(/\{\{\s*([^{}]+?)\s*\}\}/g, (_, path) => + this.get(path.trim(), replacements, depth + 1), + ); if (typeof replacements === "object" && !Array.isArray(replacements)) { for (const r in replacements) { - current = current.replaceAll(`%{${r}}`, String(replacements[r])) + current = current.replaceAll(`%{${r}}`, String(replacements[r])); } } - return current + return current; } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/languages.js b/assets/js/libClasses/languages.js index fcf044c..f866ecd 100644 --- a/assets/js/libClasses/languages.js +++ b/assets/js/libClasses/languages.js @@ -1,7 +1,7 @@ import { getFileIcon } from "../iconRegistry.js"; export class _Languages { - static contexts = {} + static contexts = {}; static languages = { default: { @@ -9,7 +9,7 @@ export class _Languages { icon: "document", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, js: { name: "JavaScript", @@ -17,406 +17,401 @@ export class _Languages { iconExt: "svg", mode: "javascript", color: "#f7df1e", - }, ts: { name: "TypeScript", icon: "ts", iconExt: "svg", mode: "typescript", - color: "#3178c6" + color: "#3178c6", }, css: { name: "CSS", icon: "css", iconExt: "svg", mode: "css", - color: "#264de4" + color: "#264de4", }, scss: { name: "SCSS", icon: "scss", iconExt: "svg", mode: "sass", - color: "#cf649a" + color: "#cf649a", }, php: { name: "PHP", icon: "php", iconExt: "svg", mode: "php", - color: "#777bb4" + color: "#777bb4", }, html: { name: "HTML", icon: "html", iconExt: "svg", mode: "html", - color: "#e34c26" + color: "#e34c26", }, md: { name: "Markdown document", icon: "md", iconExt: "svg", mode: "markdown", - color: "#083fa1" + color: "#083fa1", }, py: { name: "Python", icon: "py", iconExt: "svg", mode: "python", - color: "#ffd931" + color: "#ffd931", }, todo: { name: "To-Do List", icon: "todo", iconExt: "svg", mode: "markdown", - color: "#6c757d" + color: "#6c757d", }, gitignore: { name: "GIT File", icon: "gitignore", iconExt: "svg", mode: "text", - color: "#f14e32" + color: "#f14e32", }, c: { name: "C", icon: "c", iconExt: "svg", mode: "c_cpp", - color: "#555555" + color: "#555555", }, cs: { name: "C#", icon: "csharp", iconExt: "svg", mode: "csharp", - color: "#178600" + color: "#178600", }, cpp: { name: "C++", icon: "cpp", iconExt: "svg", mode: "c_cpp", - color: "#00599c" + color: "#00599c", }, json: { name: "JSON", icon: "json", iconExt: "svg", mode: "json", - color: "#e9a949" + color: "#e9a949", }, txt: { name: "Text", icon: "default", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, rs: { name: "Rust", icon: "rust", iconExt: "svg", mode: "rust", - color: "#dea584" + color: "#dea584", }, mjs: { name: "JavaScript Module", icon: "js", iconExt: "svg", mode: "javascript", - color: "#f7df1e" + color: "#f7df1e", }, mts: { name: "TypeScript Module", icon: "ts", iconExt: "svg", mode: "typescript", - color: "#3178c6" + color: "#3178c6", }, tsbuildinfo: { name: "TS Build Info", icon: "json", iconExt: "svg", mode: "json", - color: "#9aa0a6" + color: "#9aa0a6", }, example: { name: "Environment Example", icon: "env", iconExt: "svg", mode: "text", - color: "#6c757d" + color: "#6c757d", }, yml: { name: "YAML", icon: "yml", iconExt: "svg", mode: "yaml", - color: "#cb171e" + color: "#cb171e", }, yaml: { name: "YAML", icon: "yml", iconExt: "svg", mode: "yaml", - color: "#cb171e" + color: "#cb171e", }, jsx: { name: "React JavaScript", icon: "react", iconExt: "svg", mode: "jsx", - color: "#61dafb" + color: "#61dafb", }, tsx: { name: "React TypeScript", icon: "react", iconExt: "svg", mode: "typescript", - color: "#3178c6" + color: "#3178c6", }, cjs: { name: "JavaScript (CommonJS)", icon: "js", iconExt: "svg", mode: "javascript", - color: "#f7df1e" + color: "#f7df1e", }, cts: { name: "TypeScript (CommonJS)", icon: "ts", iconExt: "svg", mode: "typescript", - color: "#3178c6" + color: "#3178c6", }, svg: { name: "SVG", icon: "svg", iconExt: "svg", mode: "xml", - color: "#ffb13b" + color: "#ffb13b", }, env: { name: "Environment", icon: "env", iconExt: "svg", mode: "text", - color: "#6c757d" + color: "#6c757d", }, ps1: { name: "PowerShell", icon: "ps", iconExt: "svg", mode: "text", - color: "#012456" + color: "#012456", }, png: { name: "Image", icon: "image", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, jpg: { name: "Image", icon: "image", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, jpeg: { name: "Image", icon: "image", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, gif: { name: "Image", icon: "image", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, webp: { name: "Image", icon: "image", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, ico: { name: "Image", icon: "image", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, bmp: { name: "Image", icon: "image", iconExt: "svg", mode: "text", - color: "#9aa0a6" + color: "#9aa0a6", }, ttf: { name: "Font", icon: "font", iconExt: "svg", mode: "text", - color: "#d4b483" + color: "#d4b483", }, woff: { name: "Font", icon: "font", iconExt: "svg", mode: "text", - color: "#d4b483" + color: "#d4b483", }, woff2: { name: "Font", icon: "font", iconExt: "svg", mode: "text", - color: "#d4b483" + color: "#d4b483", }, otf: { name: "Font", icon: "font", iconExt: "svg", mode: "text", - color: "#d4b483" + color: "#d4b483", }, eot: { name: "Font", icon: "font", iconExt: "svg", mode: "text", - color: "#d4b483" + color: "#d4b483", }, lua: { name: "Lua", icon: "lua", iconExt: "svg", mode: "lua", - color: "#1e81bb" + color: "#1e81bb", }, luau: { name: "Luau", icon: "lua", iconExt: "svg", mode: "lua", - color: "#1e81bb" + color: "#1e81bb", }, go: { name: "GO", icon: "go", iconExt: "svg", mode: "golang", - color: "#00ACD7" + color: "#00ACD7", }, bat: { name: "BAT File", icon: "bat", iconExt: "svg", mode: "batchfile", - color: "#444444" + color: "#444444", }, wasm: { name: "WebAssembly", icon: "wasm", iconExt: "svg", mode: "wast", - color: "#3856ff" + color: "#3856ff", }, java: { name: "Java", icon: "java", iconExt: "svg", mode: "java", - color: "#f03b3b" + color: "#f03b3b", }, kt: { name: "Kotlin", icon: "kotlin", iconExt: "svg", mode: "kotlin", - color: "#cc3bf0" + color: "#cc3bf0", }, vue: { name: "Vue.js", icon: "vue", iconExt: "svg", mode: "vue", - color: "#46cc82" + color: "#46cc82", }, exe: { name: "Executable file", icon: "exe", iconExt: "svg", mode: "text", - color: "#a51212" - } - } + color: "#a51212", + }, + }; static addContext(name, value) { - this.contexts[name] = value + _Languages.contexts[name] = value; } static getContext(name) { - if (name in this.contexts) { - return this.contexts[name].value - } - else { - return null + if (name in _Languages.contexts) { + return _Languages.contexts[name].value; } + return null; } static list() { - return this.languages + return _Languages.languages; } static update(languageObjectName, object) { - if (languageObjectName in this.languages) { - this.languages[languageObjectName] = object + if (languageObjectName in _Languages.languages) { + _Languages.languages[languageObjectName] = object; } } static add({ id, name, icon, iconExt, mode, customIcon, customLanguage }) { - customLanguage = customLanguage == undefined ? false : customLanguage + customLanguage = customLanguage == undefined ? false : customLanguage; - let languageStructure = { - name: name, - icon: icon, - iconExt: iconExt, - mode: mode, - customLanguage: customLanguage - } + const languageStructure = { + name, + icon, + iconExt, + mode, + customLanguage, + }; if (customIcon) { - languageStructure.customIcon = customIcon - delete languageStructure.iconExt + languageStructure.customIcon = customIcon; + delete languageStructure.iconExt; } - this.languages[id] = languageStructure + _Languages.languages[id] = languageStructure; } static get(name) { - if (name in this.languages) { - return this.languages[name] - } - else { - return this.languages.default + if (name in _Languages.languages) { + return _Languages.languages[name]; } + return _Languages.languages.default; } static async getIcon(name) { if (!name) return "document.svg"; - let info = this.get(name); + const info = _Languages.get(name); if (info && info.customIcon) { return info.icon; } @@ -424,14 +419,12 @@ export class _Languages { } static async getIconPath(name) { - let info = this.get(name); - let icon = await this.getIcon(name); + const info = _Languages.get(name); + const icon = await _Languages.getIcon(name); if (info && info.customIcon) { return icon; } - else { - return `../assets/media/icons/symbols/files/${icon}`; - } + return `../assets/media/icons/symbols/files/${icon}`; } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/loader.js b/assets/js/libClasses/loader.js index 3c0bd72..73e844a 100644 --- a/assets/js/libClasses/loader.js +++ b/assets/js/libClasses/loader.js @@ -1,35 +1,35 @@ export class _Loader { constructor(el, settings = {}) { - this.el = el - let settingsReplacement = { - "size": "--uib-size", - "color": "--uib-color", - "speed": "--uib-speed", - "stroke": "--uib-stroke" - } - this.settings = {} - this.clearSettings = settings - this.classlist = [] + this.el = el; + const settingsReplacement = { + size: "--uib-size", + color: "--uib-color", + speed: "--uib-speed", + stroke: "--uib-stroke", + }; + this.settings = {}; + this.clearSettings = settings; + this.classlist = []; if (Object.keys(settings).length > 0) { - Object.keys(settings).forEach(k => { + Object.keys(settings).forEach((k) => { if (k in settingsReplacement) { - this.settings[settingsReplacement[k]] = settings[k] + this.settings[settingsReplacement[k]] = settings[k]; } - }) + }); } - this.finalSettings = [] - Object.keys(this.settings).forEach(k => { - this.finalSettings.push(`${k}: ${this.settings[k]}`) - }) + this.finalSettings = []; + Object.keys(this.settings).forEach((k) => { + this.finalSettings.push(`${k}: ${this.settings[k]}`); + }); - "pos" in settings ? this.classlist.push(settings.pos) : false + "pos" in settings ? this.classlist.push(settings.pos) : false; } render() { if (this.el) { - let html = ` + const html = `
@@ -44,32 +44,30 @@ export class _Loader {
- ` + `; if ("method" in this.clearSettings) { if (this.clearSettings.method == "add") { - this.el.innerHTML += html - } - else if (this.clearSettings.method == "inner") { - this.el.innerHTML = html + this.el.innerHTML += html; + } else if (this.clearSettings.method == "inner") { + this.el.innerHTML = html; } - } - else { - this.el.innerHTML += html + } else { + this.el.innerHTML += html; } setTimeout(() => { - this.el.querySelector("#content-loader").classList.remove("loader-hidden") - }, 200) + this.el.querySelector("#content-loader").classList.remove("loader-hidden"); + }, 200); } } remove() { if (this.el.querySelector("#content-loader")) { - this.el.querySelector("#content-loader").classList.add("content-loader-hidden") + this.el.querySelector("#content-loader").classList.add("content-loader-hidden"); this.el.querySelector("#content-loader").addEventListener("transitionend", () => { - this.el.querySelector("#content-loader").remove() - }) + this.el.querySelector("#content-loader").remove(); + }); } } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/notificator.js b/assets/js/libClasses/notificator.js index d152a81..a631377 100644 --- a/assets/js/libClasses/notificator.js +++ b/assets/js/libClasses/notificator.js @@ -7,18 +7,18 @@ export class _Notificator { this._hideTimer = null; this._visible = !this.element.classList.contains("hidden"); - this.notificatorValue = document.querySelector("#notificator_value") - this.notificatorIcon = document.querySelector("#notificator_icon") + this.notificatorValue = document.querySelector("#notificator_value"); + this.notificatorIcon = document.querySelector("#notificator_icon"); - this.text = "Example" - this.icon = "search" + this.text = "Example"; + this.icon = "search"; } setSize(size = "default") { - const sizes = ["default", "small", "medium", "large", "pill"] + const sizes = ["default", "small", "medium", "large", "pill"]; - if(sizes.includes(size)) { - this.element.classList.add(size) + if (sizes.includes(size)) { + this.element.classList.add(size); } } @@ -28,8 +28,8 @@ export class _Notificator { this._hideTimer = null; } - this.notificatorValue.textContent = this.text - this.notificatorIcon.textContent = this.icon + this.notificatorValue.textContent = this.text; + this.notificatorIcon.textContent = this.icon; if (!this._visible && this._rafId === null) { this._rafId = requestAnimationFrame(() => { @@ -59,4 +59,4 @@ export class _Notificator { this.element.classList.add("hidden"); this._visible = false; } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/options.js b/assets/js/libClasses/options.js index d14ff97..f8dc849 100644 --- a/assets/js/libClasses/options.js +++ b/assets/js/libClasses/options.js @@ -23,16 +23,14 @@ export class _Options { this.el = optionsElement; optionsElement.addEventListener("click", () => { - optionsElement - .querySelector(".options-selector__items") - .classList.toggle("hidden"); + optionsElement.querySelector(".options-selector__items").classList.toggle("hidden"); }); _Options.instances.set(id, this); } clear() { - this.el.querySelector(".options-selector__items").innerHTML = "" + this.el.querySelector(".options-selector__items").innerHTML = ""; } static edit(id) { @@ -44,54 +42,59 @@ export class _Options { } #makeDefault(item) { - this.el.querySelectorAll(".options-selector__item").forEach(el => { + this.el.querySelectorAll(".options-selector__item").forEach((el) => { el.removeAttribute("default"); }); item.setAttribute("default", true); - this.el.querySelector("#current").textContent = item.querySelector("#option_name").textContent; + this.el.querySelector("#current").textContent = + item.querySelector("#option_name").textContent; } add(id, value, additional = {}) { const item = document.createElement("div"); item.className = "options-selector__item"; - const itemName = document.createElement("div") - itemName.textContent = value - itemName.id = "option_name" - - item.appendChild(itemName) + const itemName = document.createElement("div"); + itemName.textContent = value; + itemName.id = "option_name"; + + item.appendChild(itemName); item.id = id; - if(typeof additional == "object") { - if("secondary" in additional && typeof additional.secondary == "string") { - const secondaryItem = document.createElement("div") - secondaryItem.className = "secondary" - secondaryItem.textContent = additional.secondary + if (typeof additional == "object") { + if ("secondary" in additional && typeof additional.secondary == "string") { + const secondaryItem = document.createElement("div"); + secondaryItem.className = "secondary"; + secondaryItem.textContent = additional.secondary; - item.appendChild(secondaryItem) + item.appendChild(secondaryItem); } - if("color" in additional && typeof additional.color == "string") { - item.style.color = additional.color + if ("color" in additional && typeof additional.color == "string") { + item.style.color = additional.color; } - if("badge" in additional && typeof additional.badge == "object" && !Array.isArray(additional.badge)) { - const badgeWrapper = document.createElement("div") - badgeWrapper.classList.add("modal-badge") - - const icon = document.createElement("span") - icon.classList.add("material-symbols-rounded") - - if("icon" in additional.badge) { - icon.textContent = additional.badge.icon - badgeWrapper.appendChild(icon) + if ( + "badge" in additional && + typeof additional.badge == "object" && + !Array.isArray(additional.badge) + ) { + const badgeWrapper = document.createElement("div"); + badgeWrapper.classList.add("modal-badge"); + + const icon = document.createElement("span"); + icon.classList.add("material-symbols-rounded"); + + if ("icon" in additional.badge) { + icon.textContent = additional.badge.icon; + badgeWrapper.appendChild(icon); } - if("color" in additional.badge) { - icon.style.background = transparentColor(additional.badge.color, 0.2) - icon.style.color = additional.badge.color + if ("color" in additional.badge) { + icon.style.background = transparentColor(additional.badge.color, 0.2); + icon.style.color = additional.badge.color; } - item.appendChild(badgeWrapper) + item.appendChild(badgeWrapper); } } @@ -103,7 +106,7 @@ export class _Options { return { default: () => this.#makeDefault(item), - element: item + element: item, }; } @@ -111,7 +114,7 @@ export class _Options { const events = ["click", "dblclick"]; if (events.includes(eventName)) { - this.el.querySelectorAll(".options-selector__item").forEach(item => { + this.el.querySelectorAll(".options-selector__item").forEach((item) => { item.addEventListener(eventName, () => { callback(item); }); @@ -120,12 +123,12 @@ export class _Options { } get(id) { - let item = this.el.querySelector(`.options-selector__item[id="${id}"]`); + const item = this.el.querySelector(`.options-selector__item[id="${id}"]`); if (item) { return { el: item, - default: () => this.#makeDefault(item) + default: () => this.#makeDefault(item), }; } @@ -133,6 +136,6 @@ export class _Options { } appendTo(element) { - element.appendChild(this.el) + element.appendChild(this.el); } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/sidebarIconManager.js b/assets/js/libClasses/sidebarIconManager.js index 678c56d..cd91b3a 100644 --- a/assets/js/libClasses/sidebarIconManager.js +++ b/assets/js/libClasses/sidebarIconManager.js @@ -1,38 +1,38 @@ export class _SideBarIconManager { constructor(selector) { - let element = document.querySelector(`.sidebar-item#${selector}`) - this.element = element + const element = document.querySelector(`.sidebar-item#${selector}`); + this.element = element; } set(icon) { - let iconPath = `../assets/media/icons/external/${icon}.svg` + const iconPath = `../assets/media/icons/external/${icon}.svg`; if (this.icon) { - this.icon.src = iconPath - return + this.icon.src = iconPath; + return; } - const img = document.createElement("img") - img.classList.add("sidebar-icon") - img.src = iconPath + const img = document.createElement("img"); + img.classList.add("sidebar-icon"); + img.src = iconPath; - this.element.appendChild(img) - this.icon = img + this.element.appendChild(img); + this.icon = img; } size(size) { - this.icon.style.cssText += `--size: ${size}px;` + this.icon.style.cssText += `--size: ${size}px;`; } blink(state = true) { if (this.icon) { - this.icon.classList.toggle("blink", state) + this.icon.classList.toggle("blink", state); } } remove() { if (this.icon) { - this.icon.remove() + this.icon.remove(); } } -} \ No newline at end of file +} diff --git a/assets/js/libClasses/topbarElement.js b/assets/js/libClasses/topbarElement.js index 7a2286f..ddbf826 100644 --- a/assets/js/libClasses/topbarElement.js +++ b/assets/js/libClasses/topbarElement.js @@ -1,114 +1,114 @@ -import { idify } from "../lib.js" +import { idify } from "../lib.js"; export class _TopBarElement { - static instances = new Map() + static instances = new Map(); constructor(id) { - const normalizedId = idify(id) + const normalizedId = idify(id); if (_TopBarElement.instances.has(normalizedId)) { - return _TopBarElement.instances.get(normalizedId) + return _TopBarElement.instances.get(normalizedId); } - this.parent = document.querySelector("#topbarCenter .status-indicator") + this.parent = document.querySelector("#topbarCenter .status-indicator"); - let item = document.querySelector(`#${normalizedId}`) + let item = document.querySelector(`#${normalizedId}`); if (!item) { - item = document.createElement("div") - item.className = "topbar-center hidden" - item.id = normalizedId + item = document.createElement("div"); + item.className = "topbar-center hidden"; + item.id = normalizedId; - this.parent.before(item) + this.parent.before(item); } - this.item = item - this._animationToken = 0 + this.item = item; + this._animationToken = 0; - _TopBarElement.instances.set(normalizedId, this) + _TopBarElement.instances.set(normalizedId, this); } content({ text, icon, type, image }) { - this.item.innerHTML = "" + this.item.innerHTML = ""; - const container = document.createElement("div") - container.className = "topbar-center__row" + const container = document.createElement("div"); + container.className = "topbar-center__row"; - if(image) { - icon = false + if (image) { + icon = false; - const imageEl = document.createElement("img") - imageEl.className = "topbar-center__image-icon" - imageEl.src = image - imageEl.id = "icon" + const imageEl = document.createElement("img"); + imageEl.className = "topbar-center__image-icon"; + imageEl.src = image; + imageEl.id = "icon"; - container.appendChild(imageEl) + container.appendChild(imageEl); } if (icon) { - const iconEl = document.createElement("span") - iconEl.className = "material-symbols-rounded" - iconEl.id = "icon" - iconEl.textContent = icon + const iconEl = document.createElement("span"); + iconEl.className = "material-symbols-rounded"; + iconEl.id = "icon"; + iconEl.textContent = icon; - container.appendChild(iconEl) + container.appendChild(iconEl); } if (text) { - const textEl = document.createElement("div") - textEl.className = "topbar-center__text" - textEl.textContent = text + const textEl = document.createElement("div"); + textEl.className = "topbar-center__text"; + textEl.textContent = text; - container.appendChild(textEl) + container.appendChild(textEl); } if (type) { - const types = ["default", "notification", "danger"] + const types = ["default", "notification", "danger"]; - this.item.classList.remove(...types) + this.item.classList.remove(...types); if (types.includes(type)) { - this.item.classList.add(type) + this.item.classList.add(type); } } - this.item.appendChild(container) + this.item.appendChild(container); } show() { - const el = this.item - const icon = el.querySelector("#icon") - const text = el.querySelector(".topbar-center__text") + const el = this.item; + const icon = el.querySelector("#icon"); + const text = el.querySelector(".topbar-center__text"); - el.classList.remove("hidden") + el.classList.remove("hidden"); - if (icon) icon.style.marginLeft = "0px" - if (text) text.classList.remove("hidden") + if (icon) icon.style.marginLeft = "0px"; + if (text) text.classList.remove("hidden"); - const container = el.querySelector(".topbar-center__row") - const targetWidth = container ? container.scrollWidth : el.scrollWidth - void el.offsetHeight + const container = el.querySelector(".topbar-center__row"); + const targetWidth = container ? container.scrollWidth : el.scrollWidth; + void el.offsetHeight; - el.style.maxWidth = targetWidth + "px" - el.style.minWidth = targetWidth + "px" + el.style.maxWidth = targetWidth + "px"; + el.style.minWidth = targetWidth + "px"; } hide({ iconVisible = false } = {}) { - const el = this.item - const icon = el.querySelector("#icon") - const text = el.querySelector(".topbar-center__text") + const el = this.item; + const icon = el.querySelector("#icon"); + const text = el.querySelector(".topbar-center__text"); - const token = ++this._animationToken + const token = ++this._animationToken; - if (!iconVisible) { - el.style.maxWidth = "0px" - el.style.minWidth = "0px" - } else { - el.style.maxWidth = "20px" - el.style.minWidth = "20px" + if (iconVisible) { + el.style.maxWidth = "20px"; + el.style.minWidth = "20px"; - if (icon) icon.style.marginLeft = "-5px" - if (text) text.classList.add("hidden") + if (icon) icon.style.marginLeft = "-5px"; + if (text) text.classList.add("hidden"); + } else { + el.style.maxWidth = "0px"; + el.style.minWidth = "0px"; } } @@ -116,18 +116,18 @@ export class _TopBarElement { const events = { hover: "mouseenter", unhover: "mouseleave", - click: "click" - } + click: "click", + }; if (event in events) { this.item.addEventListener(events[event], () => { - callback(this) - }) + callback(this); + }); } } destroy() { - this.item.remove() - _TopBarElement.instances.delete(this.item.id) + this.item.remove(); + _TopBarElement.instances.delete(this.item.id); } -} \ No newline at end of file +} diff --git a/assets/js/modals/addBugModal.js b/assets/js/modals/addBugModal.js index e10592a..8829bf7 100644 --- a/assets/js/modals/addBugModal.js +++ b/assets/js/modals/addBugModal.js @@ -1,40 +1,40 @@ -import { Modal } from "../modalsHandler/engine.js" -import { createNotify, escapeHtml, Options } from "../lib.js" -import { GLS } from "../lib.js" - -import { addBug } from "../coopHandlers/addBug.js" +import { addBug } from "../coopHandlers/addBug.js"; +import { createNotify, escapeHtml, GLS, Options } from "../lib.js"; +import { Modal } from "../modalsHandler/engine.js"; export async function getAddBugModal() { - const gls = await GLS.initLocal() + const gls = await GLS.initLocal(); + + let priority = 0; + let assignId = 0; - let priority = 0 - let assignID = 0 - - const prioritySelect = new Options("prioritySelect") - const colleaguesSelect = new Options("colleaguesSelect") + const prioritySelect = new Options("prioritySelect"); + const colleaguesSelect = new Options("colleaguesSelect"); - const yourColleaguesRes = await window.electron.requestGetYourOrgColleagues() - const yourColleaguesResMSG = yourColleaguesRes.msg + const yourColleaguesRes = await window.electron.requestGetYourOrgColleagues(); + const yourColleaguesResMsg = yourColleaguesRes.msg; - if(yourColleaguesRes.success) { - for(const item in yourColleaguesResMSG) { - const colleague = yourColleaguesResMSG[item] + if (yourColleaguesRes.success) { + for (const item in yourColleaguesResMsg) { + const colleague = yourColleaguesResMsg[item]; - const colleagueItem = colleaguesSelect.add(colleague.id, colleague.name, { secondary: colleague.organization.name }) + const colleagueItem = colleaguesSelect.add(colleague.id, colleague.name, { + secondary: colleague.organization.name, + }); - if(item == 0) { - assignID = colleague.id - colleagueItem.default() + if (item == 0) { + assignId = colleague.id; + colleagueItem.default(); } } } - prioritySelect.add("0", "Common priority").default() - prioritySelect.add("1", "Medium priority", { color: "#FFB75E" }) - prioritySelect.add("2", "High priority", { color: "#FF3333" }) + prioritySelect.add("0", "Common priority").default(); + prioritySelect.add("1", "Medium priority", { color: "#FFB75E" }); + prioritySelect.add("2", "High priority", { color: "#FF3333" }); function lgls(string) { - return gls.get(`modals.addBug.${string}`) + return gls.get(`modals.addBug.${string}`); } const addBugModal = Modal.create({ @@ -48,12 +48,12 @@ export async function getAddBugModal() { { type: "row", gap: 15, - classList: ['background'], + classList: ["background"], items: [ { type: "placeholder", title: lgls("header.title"), - description: lgls("header.description") + description: lgls("header.description"), }, { type: "input", @@ -75,101 +75,95 @@ export async function getAddBugModal() { type: "placeholder", id: "addBugAssign", title: "Choose who to assign the bug to", - description: "This is a list of people who are members of the same organizations as you" + description: + "This is a list of people who are members of the same organizations as you", }, { type: "switch", id: "isPrivate", checked: false, title: lgls("privateBugSwitch.title"), - description: lgls("privateBugSwitch.description") + description: lgls("privateBugSwitch.description"), }, { type: "container", - id: "buttonsContainer" + id: "buttonsContainer", }, { type: "button", id: "addBugConfirm", title: lgls("confirmBtnPrivate"), - container: "#buttonsContainer" - } - ] + container: "#buttonsContainer", + }, + ], }, - ] - }) + ], + }); - const element = addBugModal.el - const addBtn = element.querySelector("#addBugConfirm") - const addBugAssign = element.querySelector("#addBugAssign") - const addBugPriority = element.querySelector("#addBugPriority") + const element = addBugModal.el; + const addBtn = element.querySelector("#addBugConfirm"); + const addBugAssign = element.querySelector("#addBugAssign"); + const addBugPriority = element.querySelector("#addBugPriority"); - prioritySelect.appendTo(addBugPriority) + prioritySelect.appendTo(addBugPriority); prioritySelect.on("click", (e) => { - priority = parseInt(e.id) - }) + priority = Number.parseInt(e.id); + }); - if(!yourColleaguesRes.success) { - createNotify( - { - icon: "close", - title: "Colleagues list get error", - content: yourColleaguesResMSG - } - ) - } - else { - colleaguesSelect.appendTo(addBugAssign) + if (yourColleaguesRes.success) { + colleaguesSelect.appendTo(addBugAssign); colleaguesSelect.on("click", (e) => { - console.log(e.id) - }) + console.log(e.id); + }); + } else { + createNotify({ + icon: "close", + title: "Colleagues list get error", + content: yourColleaguesResMsg, + }); } element.querySelector("#isPrivate").addEventListener("change", (event) => { - const originalAssignID = assignID - const checked = event.target.checked + const originalAssignId = assignId; + const checked = event.target.checked; - addBtn.textContent = checked ? lgls("confirmBtnPrivate") : lgls("confirmBtn") + addBtn.textContent = checked ? lgls("confirmBtnPrivate") : lgls("confirmBtn"); - if(checked) { - addBugAssign.classList.add("disabled") - } - else { - addBugAssign.classList.remove("disabled") + if (checked) { + addBugAssign.classList.add("disabled"); + } else { + addBugAssign.classList.remove("disabled"); } - }) + }); addBtn.addEventListener("click", async () => { - const bugName = escapeHtml(element.querySelector("#addBugName").value) - const bugContent = escapeHtml(element.querySelector("#addBugContent").value) - const isPrivate = element.querySelector("#isPrivate").checked ? 1 : 0 + const bugName = escapeHtml(element.querySelector("#addBugName").value); + const bugContent = escapeHtml(element.querySelector("#addBugContent").value); + const isPrivate = element.querySelector("#isPrivate").checked ? 1 : 0; if (bugContent.length > 0 && bugContent.length > 0) { const objectToAdd = { bugModal: addBugModal, - bugName: bugName, - bugContent: bugContent, + bugName, + bugContent, bugPriority: priority, bugPrivate: isPrivate, - bugAssignTo: assignID - } + bugAssignTo: assignId, + }; - if(isPrivate) delete objectToAdd["bugAssignTo"] + if (isPrivate) delete objectToAdd["bugAssignTo"]; - await addBug(objectToAdd) - } - else { - createNotify( - { - icon: "close", - title: "Error while bug adding", - content: "All fields must be filled" - } - ) + await addBug(objectToAdd); + } else { + createNotify({ + icon: "close", + title: "Error while bug adding", + content: "All fields must be filled", + }); } - }) + }); - return addBugModal -} \ No newline at end of file + return addBugModal; +} diff --git a/assets/js/modals/closeConfirm.js b/assets/js/modals/closeConfirm.js index e152b87..41ebbdf 100644 --- a/assets/js/modals/closeConfirm.js +++ b/assets/js/modals/closeConfirm.js @@ -2,7 +2,7 @@ import { GLS } from "../lib.js"; import { Modal } from "../modalsHandler/engine.js"; export async function closeConfirmModal({ fileName }) { - const gls = await GLS.initLocal() + const gls = await GLS.initLocal(); const modal = Modal.create({ id: "closeConfirmModal", @@ -15,41 +15,41 @@ export async function closeConfirmModal({ fileName }) { { type: "row", gap: 15, - classList: ['background'], + classList: ["background"], items: [ { type: "placeholder", title: gls.get("modals.closeConfirm.message", { file: fileName }), - description: gls.get("modals.closeConfirm.description") + description: gls.get("modals.closeConfirm.description"), }, { type: "container", - id: "closeConfirmButtons" + id: "closeConfirmButtons", }, { type: "button", id: "closeConfirmYes", title: gls.get("modals.closeConfirm.yes"), container: "#closeConfirmButtons", - class: "danger" + class: "danger", }, { type: "button", id: "closeConfirmSave", title: gls.get("modals.closeConfirm.save"), - container: "#closeConfirmButtons" + container: "#closeConfirmButtons", }, { type: "button", id: "closeConfirmNo", title: gls.get("cancel"), container: "#closeConfirmButtons", - class: "secondary" + class: "secondary", }, - ] - } - ] + ], + }, + ], }); - return modal -} \ No newline at end of file + return modal; +} diff --git a/assets/js/modals/logoutModal.js b/assets/js/modals/logoutModal.js index 77949aa..88e659b 100644 --- a/assets/js/modals/logoutModal.js +++ b/assets/js/modals/logoutModal.js @@ -1,11 +1,11 @@ -import { Modal } from "../modalsHandler/engine.js" -import { GLS } from "../lib.js" +import { GLS } from "../lib.js"; +import { Modal } from "../modalsHandler/engine.js"; export async function getLogoutModal() { - const gls = await GLS.initLocal() + const gls = await GLS.initLocal(); function lgls(string) { - return gls.get(`modals.logout.${string}`) + return gls.get(`modals.logout.${string}`); } const logoutModal = Modal.create({ @@ -19,46 +19,46 @@ export async function getLogoutModal() { { type: "row", gap: 15, - classList: ['background'], + classList: ["background"], items: [ { type: "placeholder", title: lgls("header.title"), - description: lgls("header.description") + description: lgls("header.description"), }, { type: "container", - id: "buttonsContainer" + id: "buttonsContainer", }, { type: "button", id: "logoutConfirm", title: lgls("buttonConfirm"), - container: "#buttonsContainer" + container: "#buttonsContainer", }, { type: "button", id: "logoutCancel", title: gls.get("cancel"), container: "#buttonsContainer", - class: "danger" - } - ] + class: "danger", + }, + ], }, - ] - }) + ], + }); + + const cancelBtn = logoutModal.el.querySelector("#logoutCancel"); + const confirmBtn = logoutModal.el.querySelector("#logoutConfirm"); - const cancelBtn = logoutModal.el.querySelector("#logoutCancel") - const confirmBtn = logoutModal.el.querySelector("#logoutConfirm") - cancelBtn.addEventListener("click", () => { - logoutModal.close() - }) + logoutModal.close(); + }); confirmBtn.addEventListener("click", async () => { - await window.electron.logout() - await window.electron.reload() - }) + await window.electron.logout(); + await window.electron.reload(); + }); - return logoutModal -} \ No newline at end of file + return logoutModal; +} diff --git a/assets/js/modals/settingsModal.js b/assets/js/modals/settingsModal.js index 6f088c2..932d734 100644 --- a/assets/js/modals/settingsModal.js +++ b/assets/js/modals/settingsModal.js @@ -1,11 +1,11 @@ -import { Modal } from "../modalsHandler/engine.js" -import { GLS } from "../lib.js" +import { GLS } from "../lib.js"; +import { Modal } from "../modalsHandler/engine.js"; export async function getSettingsModal({ platform }) { - const gls = await GLS.initLocal() - + const gls = await GLS.initLocal(); + function lgls(string, replacements) { - return gls.get(`modals.appearance.${string}`, replacements) + return gls.get(`modals.appearance.${string}`, replacements); } const appearanceModal = Modal.create({ @@ -22,7 +22,7 @@ export async function getSettingsModal({ platform }) { { type: "category", label: lgls("application.applicationLabel"), - items: [] + items: [], }, { type: "row", @@ -37,68 +37,68 @@ export async function getSettingsModal({ platform }) { max: 4, value: 1, step: 0.1, - prefix: "x" + prefix: "x", }, { type: "placeholder", title: lgls("application.language.title"), description: lgls("application.language.description"), note: gls.get("modals.needToReloadNote"), - id: "setting_language" + id: "setting_language", }, { type: "switch", title: lgls("application.useSystemFonts.title"), description: lgls("application.useSystemFonts.description"), - id: "setting_useSystemFonts" + id: "setting_useSystemFonts", }, { type: "switch", title: lgls("application.splashWindow.title"), description: lgls("application.splashWindow.description"), - id: "setting_splash" + id: "setting_splash", }, { type: "switch", title: lgls("application.reduceMotion.title"), description: lgls("application.reduceMotion.description"), - id: "setting_reduceMotion" + id: "setting_reduceMotion", }, { type: "switch", title: lgls("application.boldFont.title"), description: lgls("application.boldFont.description"), - id: "setting_boldFont" + id: "setting_boldFont", }, { type: "switch", title: lgls("application.restoreFolder.title"), description: lgls("application.restoreFolder.description"), - id: "setting_restoreFolder" + id: "setting_restoreFolder", }, { type: "placeholder", title: lgls("application.theme.title"), description: lgls("application.theme.description"), - id: "setting_theme" + id: "setting_theme", }, { type: "switch", title: lgls("application.developerMode.title"), description: lgls("application.developerMode.description"), note: gls.get("modals.needToReloadNote"), - id: "setting_devMode" + id: "setting_devMode", }, { type: "placeholder", id: "settings_appIcon", title: lgls("application.appIcons.title"), description: lgls("application.appIcons.description"), - note: gls.get("modals.appReloadNote") + note: gls.get("modals.appReloadNote"), }, - ] - } - ] + ], + }, + ], }, { name: lgls("sideBarCategory"), @@ -107,7 +107,7 @@ export async function getSettingsModal({ platform }) { { type: "category", label: lgls("sideBarCategory"), - items: [] + items: [], }, { type: "row", @@ -116,13 +116,14 @@ export async function getSettingsModal({ platform }) { { type: "switch", title: "Show hidden files", - description: "Displays files and folders starting with a dot (e.g. .gitignore)", + description: + "Displays files and folders starting with a dot (e.g. .gitignore)", id: "setting_sidebarShowHiddenFiles", - disabled: true - } - ] - } - ] + disabled: true, + }, + ], + }, + ], }, { name: lgls("terminalCategory"), @@ -131,7 +132,7 @@ export async function getSettingsModal({ platform }) { { type: "category", label: "Appearance", - items: [] + items: [], }, { type: "row", @@ -147,21 +148,21 @@ export async function getSettingsModal({ platform }) { value: 14, step: 1, prefix: "px", - disabled: true + disabled: true, }, { type: "switch", title: "Cursor blink", description: "Enables cursor blinking animation in the terminal", id: "setting_terminalCursorBlink", - disabled: true + disabled: true, }, - ] + ], }, { type: "category", label: "Behaviour", - items: [] + items: [], }, { type: "row", @@ -172,11 +173,11 @@ export async function getSettingsModal({ platform }) { title: "Copy on selection", description: "Copies selected text to the clipboard automatically", id: "setting_terminalCopyOnSelect", - disabled: true - } - ] - } - ] + disabled: true, + }, + ], + }, + ], }, { name: lgls("fileWindowCategory"), @@ -185,7 +186,7 @@ export async function getSettingsModal({ platform }) { { type: "category", label: "Tabs", - items: [] + items: [], }, { type: "row", @@ -195,24 +196,24 @@ export async function getSettingsModal({ platform }) { type: "switch", title: lgls("fileWindow.title"), description: lgls("fileWindow.description"), - id: "setting_coloredTabs" + id: "setting_coloredTabs", }, { type: "switch", title: "Show tab close button", description: "Displays the X close button on editor tabs", id: "setting_tabShowClose", - disabled: true + disabled: true, }, { type: "switch", title: lgls("fileWindow.confirmClose.title"), description: lgls("fileWindow.confirmClose.description"), - id: "setting_confirmCloseTab" - } - ] - } - ] + id: "setting_confirmCloseTab", + }, + ], + }, + ], }, { name: lgls("editorCategory"), @@ -221,7 +222,7 @@ export async function getSettingsModal({ platform }) { { type: "category", label: lgls("editor.editorLabel"), - items: [] + items: [], }, { type: "row", @@ -236,7 +237,7 @@ export async function getSettingsModal({ platform }) { max: 200, value: 100, step: 10, - prefix: "%" + prefix: "%", }, { type: "placeholder", @@ -244,14 +245,17 @@ export async function getSettingsModal({ platform }) { description: lgls("editor.pythonRunner.description"), id: "setting_pythonRunMethod", disabled: platform != "win32", - note: platform == "win32" ? gls.get("modals.needToReloadNote") : `${lgls("editor.builtInPythonCausePlatformNote", { platform: platform.toUpperCase() })}` - } - ] + note: + platform == "win32" + ? gls.get("modals.needToReloadNote") + : `${lgls("editor.builtInPythonCausePlatformNote", { platform: platform.toUpperCase() })}`, + }, + ], }, { type: "category", label: lgls("editor.contextsLabel"), - items: [] + items: [], }, { type: "row", @@ -261,11 +265,11 @@ export async function getSettingsModal({ platform }) { type: "switch", title: lgls("editor.contexts.go.title"), description: lgls("editor.contexts.go.description"), - id: "setting_go_context_parser" + id: "setting_go_context_parser", }, - ] - } - ] + ], + }, + ], }, { name: lgls("extensions.title"), @@ -274,7 +278,7 @@ export async function getSettingsModal({ platform }) { { type: "category", label: "Security", - items: [] + items: [], }, { type: "row", @@ -284,15 +288,15 @@ export async function getSettingsModal({ platform }) { type: "switch", title: lgls("extensions.riskyPermsWarn.title"), description: lgls("extensions.riskyPermsWarn.description"), - id: "setting_disableRiskyPermissionWarning" - } - ] - } - ] + id: "setting_disableRiskyPermissionWarning", + }, + ], + }, + ], }, { - divider: true + divider: true, }, { @@ -306,33 +310,33 @@ export async function getSettingsModal({ platform }) { { type: "placeholder", title: lgls("gitGithub.integration.title"), - description: lgls("gitGithub.integration.description") + description: lgls("gitGithub.integration.description"), }, { - type: "divider" + type: "divider", }, { type: "input", inputType: "password", placeholder: lgls("gitGithub.integration.inputs.token.placeholder"), - id: "setting_githubAccessKey" + id: "setting_githubAccessKey", }, { type: "button", title: lgls("gitGithub.integration.buttons.view"), - id: "setting_githubAccessKeyView" + id: "setting_githubAccessKeyView", }, { type: "button", title: gls.get("save"), - id: "setting_githubAccessKeySave" - } - ] - } - ] - } - ] - }) + id: "setting_githubAccessKeySave", + }, + ], + }, + ], + }, + ], + }); - return appearanceModal -} \ No newline at end of file + return appearanceModal; +} diff --git a/assets/js/modalsHandler/components/badge.js b/assets/js/modalsHandler/components/badge.js index 68f5b7c..73d4c59 100644 --- a/assets/js/modalsHandler/components/badge.js +++ b/assets/js/modalsHandler/components/badge.js @@ -1,23 +1,23 @@ -import { createDIV, createSpan } from "../handlers/helpers.js" +import { createDIV, createSpan } from "../handlers/helpers.js"; export function renderBadge(properties = {}) { - const type = properties.type + const type = properties.type; const badges = { verified: { class: "modal-verified__badge", - icon: "check" - } - } + icon: "check", + }, + }; - const badgeEl = createDIV() - badgeEl.classList.add("modal-badge", badges[type].class) + const badgeEl = createDIV(); + badgeEl.classList.add("modal-badge", badges[type].class); - const iconEl = createSpan() - iconEl.classList.add("material-symbols-rounded") - iconEl.textContent = badges[type].icon + const iconEl = createSpan(); + iconEl.classList.add("material-symbols-rounded"); + iconEl.textContent = badges[type].icon; - badgeEl.appendChild(iconEl) - - return badgeEl -} \ No newline at end of file + badgeEl.appendChild(iconEl); + + return badgeEl; +} diff --git a/assets/js/modalsHandler/components/base.js b/assets/js/modalsHandler/components/base.js index d3394d5..7a6617f 100644 --- a/assets/js/modalsHandler/components/base.js +++ b/assets/js/modalsHandler/components/base.js @@ -1,86 +1,83 @@ -import { showBackdrop, hideBackdrop } from "../engine.js" -import { sideBarHandler } from "../handlers/sidebarHandler.js" -import { defaultContentHandler } from "../handlers/contentHandler.js" +import { hideBackdrop, showBackdrop } from "../engine.js"; +import { defaultContentHandler } from "../handlers/contentHandler.js"; +import { sideBarHandler } from "../handlers/sidebarHandler.js"; export function renderModalBase(options = {}) { - const id = options.id - const isHiddenOnSpawn = options.isHiddenOnSpawn - const modalClassList = options.modalClassList - const title = options.title - const titleAvatar = options.titleAvatar - const pages = options.pages - const size = options.size - - const modalWrapper = document.createElement("div") - modalWrapper.id = id - modalWrapper.classList.add("modal-wrapper", isHiddenOnSpawn ? "hidden" : "") - - const modal = document.createElement("div") - modal.classList.add("modal", size) - - const modalBody = document.createElement("div") - modalBody.classList.add("modal-body") - - const modalHeader = document.createElement("div") - modalHeader.classList.add("modal-header") - - const modalHeaderCloseBtn = document.createElement("div") - modalHeaderCloseBtn.classList.add("modal-header__close") - - const modalHeaderCloseBtnIcon = document.createElement("span") - modalHeaderCloseBtnIcon.textContent = "close" - modalHeaderCloseBtnIcon.classList.add("material-symbols-rounded") - - if(!title) { - modalHeader.classList.add("no-title") - } - else if(pages.length > 0) { - modalHeader.classList.add("no-title") - } - else { - const modalTitle = document.createElement("div") - modalTitle.classList.add("modal-header__title") - modalTitle.textContent = title - - modalHeader.appendChild(modalTitle) + const id = options.id; + const isHiddenOnSpawn = options.isHiddenOnSpawn; + const modalClassList = options.modalClassList; + const title = options.title; + const titleAvatar = options.titleAvatar; + const pages = options.pages; + const size = options.size; + + const modalWrapper = document.createElement("div"); + modalWrapper.id = id; + modalWrapper.classList.add("modal-wrapper", isHiddenOnSpawn ? "hidden" : ""); + + const modal = document.createElement("div"); + modal.classList.add("modal", size); + + const modalBody = document.createElement("div"); + modalBody.classList.add("modal-body"); + + const modalHeader = document.createElement("div"); + modalHeader.classList.add("modal-header"); + + const modalHeaderCloseBtn = document.createElement("div"); + modalHeaderCloseBtn.classList.add("modal-header__close"); + + const modalHeaderCloseBtnIcon = document.createElement("span"); + modalHeaderCloseBtnIcon.textContent = "close"; + modalHeaderCloseBtnIcon.classList.add("material-symbols-rounded"); + + if (!title) { + modalHeader.classList.add("no-title"); + } else if (pages.length > 0) { + modalHeader.classList.add("no-title"); + } else { + const modalTitle = document.createElement("div"); + modalTitle.classList.add("modal-header__title"); + modalTitle.textContent = title; + + modalHeader.appendChild(modalTitle); } - if(modalClassList.length > 0) modal.classList.add(...modalClassList) + if (modalClassList.length > 0) modal.classList.add(...modalClassList); - modalHeaderCloseBtn.appendChild(modalHeaderCloseBtnIcon) + modalHeaderCloseBtn.appendChild(modalHeaderCloseBtnIcon); - modalHeader.appendChild(modalHeaderCloseBtn) - modalWrapper.appendChild(modal) + modalHeader.appendChild(modalHeaderCloseBtn); + modalWrapper.appendChild(modal); - modal.appendChild(modalHeader) - modal.appendChild(modalBody) + modal.appendChild(modalHeader); + modal.appendChild(modalBody); // events modalHeaderCloseBtn.addEventListener("click", () => { - modalWrapper.classList.add("hidden") - hideBackdrop() - }) + modalWrapper.classList.add("hidden"); + hideBackdrop(); + }); modalWrapper.addEventListener("click", (event) => { - if (event.target !== modalWrapper) return + if (event.target !== modalWrapper) return; - modalWrapper.classList.add("hidden") - hideBackdrop() - }) + modalWrapper.classList.add("hidden"); + hideBackdrop(); + }); - if(typeof pages == "object" && pages.length > 0) { + if (typeof pages == "object" && pages.length > 0) { sideBarHandler(pages, { body: modalBody, - title: title, - titleAvatar: titleAvatar - }) - } - else if("content" in options) { - defaultContentHandler(modalBody, options.content) + title, + titleAvatar, + }); + } else if ("content" in options) { + defaultContentHandler(modalBody, options.content); } return { wrapper: modalWrapper, body: modalBody, - header: modalHeader - } -} \ No newline at end of file + header: modalHeader, + }; +} diff --git a/assets/js/modalsHandler/components/button.js b/assets/js/modalsHandler/components/button.js index a17d1ab..4efbf5c 100644 --- a/assets/js/modalsHandler/components/button.js +++ b/assets/js/modalsHandler/components/button.js @@ -1,38 +1,37 @@ -import { createDIV } from "../handlers/helpers.js" +import { createDIV } from "../handlers/helpers.js"; export function renderButton(properties = {}) { - const classes = ["default", "danger"] - const id = properties.id - const title = properties.title - const container = properties.container - const element = properties.element - const btnClass = properties.class - const onclick = properties.onclick + const classes = ["default", "danger"]; + const id = properties.id; + const title = properties.title; + const container = properties.container; + const element = properties.element; + const btnClass = properties.class; + const onclick = properties.onclick; - const button = document.createElement("button") - button.id = id - button.classList.add("modal-button") - button.textContent = title + const button = document.createElement("button"); + button.id = id; + button.classList.add("modal-button"); + button.textContent = title; - if(classes.includes(btnClass)) button.classList.add(btnClass) + if (classes.includes(btnClass)) button.classList.add(btnClass); - if(!title) button.textContent = id + if (!title) button.textContent = id; - if(onclick && typeof onclick === "function") { - button.addEventListener("click", onclick) + if (onclick && typeof onclick === "function") { + button.addEventListener("click", onclick); } - if(!container) { - return button - } - else { - const containerEl = element.querySelector(container) + if (container) { + const containerEl = element.querySelector(container); - if(containerEl) { - containerEl.classList.add("modal-buttons") - containerEl.appendChild(button) + if (containerEl) { + containerEl.classList.add("modal-buttons"); + containerEl.appendChild(button); - return containerEl + return containerEl; } + } else { + return button; } -} \ No newline at end of file +} diff --git a/assets/js/modalsHandler/components/centered.js b/assets/js/modalsHandler/components/centered.js index 21f5438..9500316 100644 --- a/assets/js/modalsHandler/components/centered.js +++ b/assets/js/modalsHandler/components/centered.js @@ -1,15 +1,15 @@ -import { createDIV, createIcon, createSpan } from "../handlers/helpers.js" +import { createDIV, createIcon, createSpan } from "../handlers/helpers.js"; export function renderCentered(properties = {}) { - const icon = properties.icon - - const wrapper = createDIV() - wrapper.classList.add("modal-centered") - - if(icon) { - const iconEl = createIcon(icon) - wrapper.appendChild(iconEl) + const icon = properties.icon; + + const wrapper = createDIV(); + wrapper.classList.add("modal-centered"); + + if (icon) { + const iconEl = createIcon(icon); + wrapper.appendChild(iconEl); } - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/container.js b/assets/js/modalsHandler/components/container.js index 650f911..85876b9 100644 --- a/assets/js/modalsHandler/components/container.js +++ b/assets/js/modalsHandler/components/container.js @@ -1,21 +1,21 @@ -import { createDIV } from "../handlers/helpers.js" +import { createDIV } from "../handlers/helpers.js"; export function renderContainer(properties = {}) { - const id = properties.id - const classList = properties.classList - const html = properties.html + const id = properties.id; + const classList = properties.classList; + const html = properties.html; - const container = createDIV() - container.id = id - container.classList.add("modal-container") + const container = createDIV(); + container.id = id; + container.classList.add("modal-container"); - if(Array.isArray(classList)) { - container.classList.add(...classList) + if (Array.isArray(classList)) { + container.classList.add(...classList); } - if(html) { - container.innerHTML = html + if (html) { + container.innerHTML = html; } - return container -} \ No newline at end of file + return container; +} diff --git a/assets/js/modalsHandler/components/divider.js b/assets/js/modalsHandler/components/divider.js index 0a57b38..93b2578 100644 --- a/assets/js/modalsHandler/components/divider.js +++ b/assets/js/modalsHandler/components/divider.js @@ -1,8 +1,8 @@ -import { createDIV, createSpan } from "../handlers/helpers.js" +import { createDIV, createSpan } from "../handlers/helpers.js"; export function renderDivider() { - const wrapper = createDIV() - wrapper.classList.add("modal-divider") + const wrapper = createDIV(); + wrapper.classList.add("modal-divider"); - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/dropdown.js b/assets/js/modalsHandler/components/dropdown.js index afaa01f..66db0ab 100644 --- a/assets/js/modalsHandler/components/dropdown.js +++ b/assets/js/modalsHandler/components/dropdown.js @@ -1,35 +1,35 @@ -import { _Options } from "../../libClasses/options.js" +import { _Options } from "../../libClasses/options.js"; export function renderDropdown(properties = {}) { - const id = properties.id - const title = properties.title - const description = properties.description - const options = properties.options || [] - const selected = properties.selected || "" + const id = properties.id; + const title = properties.title; + const description = properties.description; + const options = properties.options || []; + const selected = properties.selected || ""; - const wrapper = document.createElement("div") - wrapper.classList.add("modal-category__item") + const wrapper = document.createElement("div"); + wrapper.classList.add("modal-category__item"); - const elementTitle = document.createElement("div") - elementTitle.classList.add("modal-category__item-title") - elementTitle.textContent = title + const elementTitle = document.createElement("div"); + elementTitle.classList.add("modal-category__item-title"); + elementTitle.textContent = title; - const elementDesc = document.createElement("div") - elementDesc.classList.add("modal-category__item-desc") - elementDesc.textContent = description + const elementDesc = document.createElement("div"); + elementDesc.classList.add("modal-category__item-desc"); + elementDesc.textContent = description; - const select = new _Options(id) + const select = new _Options(id); - options.forEach(opt => { - const value = typeof opt === "string" ? opt : opt.value - const label = typeof opt === "string" ? opt : (opt.label || opt.value) - const item = select.add(value, label) - if (value === selected) item.default() - }) + options.forEach((opt) => { + const value = typeof opt === "string" ? opt : opt.value; + const label = typeof opt === "string" ? opt : opt.label || opt.value; + const item = select.add(value, label); + if (value === selected) item.default(); + }); - if (title) wrapper.appendChild(elementTitle) - if (description) wrapper.appendChild(elementDesc) - wrapper.appendChild(select.el) + if (title) wrapper.appendChild(elementTitle); + if (description) wrapper.appendChild(elementDesc); + wrapper.appendChild(select.el); - return wrapper + return wrapper; } diff --git a/assets/js/modalsHandler/components/extensionItem.js b/assets/js/modalsHandler/components/extensionItem.js index b1b425b..d0df30a 100644 --- a/assets/js/modalsHandler/components/extensionItem.js +++ b/assets/js/modalsHandler/components/extensionItem.js @@ -1,144 +1,139 @@ -import { generateAvatar, changeTagName } from "../../lib.js" -import { valid, validArray } from "../engine.js" +import { changeTagName, generateAvatar } from "../../lib.js"; +import { valid, validArray } from "../engine.js"; export function renderExtensionItem(properties = {}) { - const title = properties.title - const subtitle = properties.subtitle - const description = properties.description - const image = properties.image - const tags = properties.tags - const buttons = properties.buttons - const id = properties.id - const toggle = properties.toggle + const title = properties.title; + const subtitle = properties.subtitle; + const description = properties.description; + const image = properties.image; + const tags = properties.tags; + const buttons = properties.buttons; + const id = properties.id; + const toggle = properties.toggle; - const wrapper = document.createElement("div") - wrapper.classList.add("modal-extension__item") + const wrapper = document.createElement("div"); + wrapper.classList.add("modal-extension__item"); - if(id) wrapper.id = id + if (id) wrapper.id = id; - let imageEl = document.createElement("div") + let imageEl = document.createElement("div"); if (!image) { - imageEl.innerHTML = generateAvatar(title) - imageEl = imageEl.firstElementChild - } - else if (typeof image == "string" && /^(?:[A-Za-z]:\/|https?:\/\/)/gm.test(image)) { - imageEl = document.createElement("img") - imageEl.crossOrigin = "anonymous" - imageEl.src = image - } - else if (typeof image == "string") { - imageEl.innerHTML = generateAvatar(image) - imageEl = imageEl.firstElementChild - } - else { - imageEl = document.createElement("img") - imageEl.src = image + imageEl.innerHTML = generateAvatar(title); + imageEl = imageEl.firstElementChild; + } else if (typeof image == "string" && /^(?:[A-Za-z]:\/|https?:\/\/)/gm.test(image)) { + imageEl = document.createElement("img"); + imageEl.crossOrigin = "anonymous"; + imageEl.src = image; + } else if (typeof image == "string") { + imageEl.innerHTML = generateAvatar(image); + imageEl = imageEl.firstElementChild; + } else { + imageEl = document.createElement("img"); + imageEl.src = image; } - const contentEl = document.createElement("div") - contentEl.classList.add("modal-extension__item-content") + const contentEl = document.createElement("div"); + contentEl.classList.add("modal-extension__item-content"); - const contentTitleEl = document.createElement("div") - contentTitleEl.classList.add("modal-extension__item-title") - contentTitleEl.textContent = title + const contentTitleEl = document.createElement("div"); + contentTitleEl.classList.add("modal-extension__item-title"); + contentTitleEl.textContent = title; - const contentSubtitleEl = document.createElement("div") - contentSubtitleEl.classList.add("modal-extension__item-subtitle") - contentSubtitleEl.textContent = subtitle + const contentSubtitleEl = document.createElement("div"); + contentSubtitleEl.classList.add("modal-extension__item-subtitle"); + contentSubtitleEl.textContent = subtitle; - const contentDescEl = document.createElement("div") - contentDescEl.classList.add("modal-extension__item-desc") - contentDescEl.textContent = description + const contentDescEl = document.createElement("div"); + contentDescEl.classList.add("modal-extension__item-desc"); + contentDescEl.textContent = description; - const tagWrapper = document.createElement("div") - tagWrapper.classList.add("modal-extension__item-tag__wrapper") + const tagWrapper = document.createElement("div"); + tagWrapper.classList.add("modal-extension__item-tag__wrapper"); if (tags && Array.isArray(tags)) { - tags.forEach(t => { - const name = valid(t.name) ?? "Unnamed" - const type = valid(t.type) ?? "No tag" + tags.forEach((t) => { + const name = valid(t.name) ?? "Unnamed"; + const type = valid(t.type) ?? "No tag"; - const types = ["module", "permission"] + const types = ["module", "permission"]; - const tag = document.createElement("div") - tag.classList.add("modal-extension__item-tag") + const tag = document.createElement("div"); + tag.classList.add("modal-extension__item-tag"); - const tagName = document.createElement("div") - tagName.classList.add("modal-extension__item-tag__name") - tagName.textContent = name + const tagName = document.createElement("div"); + tagName.classList.add("modal-extension__item-tag__name"); + tagName.textContent = name; - if (types.includes(type)) tag.classList.add(type) + if (types.includes(type)) tag.classList.add(type); - tag.appendChild(tagName) + tag.appendChild(tagName); - tagWrapper.appendChild(tag) - }) + tagWrapper.appendChild(tag); + }); } - const btnWrapper = document.createElement("div") - btnWrapper.classList.add("modal-extension__item-btn__wrapper") + const btnWrapper = document.createElement("div"); + btnWrapper.classList.add("modal-extension__item-btn__wrapper"); if (buttons && Array.isArray(buttons)) { - buttons.forEach(btn => { - const icon = valid(btn.icon) ?? "close" - const callback = valid(btn.onclick) ?? false - const btnClassList = validArray(btn.classList) ?? [] + buttons.forEach((btn) => { + const icon = valid(btn.icon) ?? "close"; + const callback = valid(btn.onclick) ?? false; + const btnClassList = validArray(btn.classList) ?? []; + + const btnEl = document.createElement("button"); + btnEl.classList.add("modal-extension__item-btn"); - const btnEl = document.createElement("button") - btnEl.classList.add("modal-extension__item-btn") + if (btnClassList.length > 0) btnEl.classList.add(...btnClassList); - if(btnClassList.length > 0) btnEl.classList.add(...btnClassList) - - const btnIconEl = document.createElement("span") - btnIconEl.classList.add("material-symbols-rounded") - btnIconEl.textContent = icon + const btnIconEl = document.createElement("span"); + btnIconEl.classList.add("material-symbols-rounded"); + btnIconEl.textContent = icon; - btnEl.appendChild(btnIconEl) + btnEl.appendChild(btnIconEl); btnEl.addEventListener("click", () => { - if(typeof callback === "function") { - callback( - { - element: wrapper - } - ) + if (typeof callback === "function") { + callback({ + element: wrapper, + }); } - }) + }); - btnWrapper.appendChild(btnEl) - }) + btnWrapper.appendChild(btnEl); + }); } if (toggle && typeof toggle.onChange === "function") { - const toggleLabel = document.createElement("label") - toggleLabel.classList.add("round-switch", "modal-extension__toggle") + const toggleLabel = document.createElement("label"); + toggleLabel.classList.add("round-switch", "modal-extension__toggle"); - const toggleInput = document.createElement("input") - toggleInput.type = "checkbox" - toggleInput.checked = toggle.checked !== false + const toggleInput = document.createElement("input"); + toggleInput.type = "checkbox"; + toggleInput.checked = toggle.checked !== false; - const toggleSlider = document.createElement("span") - toggleSlider.classList.add("slider") + const toggleSlider = document.createElement("span"); + toggleSlider.classList.add("slider"); - toggleLabel.appendChild(toggleInput) - toggleLabel.appendChild(toggleSlider) + toggleLabel.appendChild(toggleInput); + toggleLabel.appendChild(toggleSlider); toggleInput.addEventListener("change", () => { - toggle.onChange(toggleInput.checked) - }) + toggle.onChange(toggleInput.checked); + }); - btnWrapper.appendChild(toggleLabel) + btnWrapper.appendChild(toggleLabel); } - contentEl.appendChild(contentTitleEl) - if (subtitle) contentEl.appendChild(contentSubtitleEl) - contentEl.appendChild(contentDescEl) - contentEl.appendChild(tagWrapper) - contentEl.appendChild(btnWrapper) + contentEl.appendChild(contentTitleEl); + if (subtitle) contentEl.appendChild(contentSubtitleEl); + contentEl.appendChild(contentDescEl); + contentEl.appendChild(tagWrapper); + contentEl.appendChild(btnWrapper); - wrapper.appendChild(imageEl) - wrapper.appendChild(contentEl) + wrapper.appendChild(imageEl); + wrapper.appendChild(contentEl); - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/githubRepos.js b/assets/js/modalsHandler/components/githubRepos.js index f93283e..0863203 100644 --- a/assets/js/modalsHandler/components/githubRepos.js +++ b/assets/js/modalsHandler/components/githubRepos.js @@ -1,142 +1,135 @@ import { createNotify, getGithubToken, GLS, Task, linkify } from "../../lib.js"; import { Modal } from "../engine.js"; -import { createDIV, createIcon, createLink, createParagraph, svgToElement } from "../handlers/helpers.js"; +import { + createDIV, + createIcon, + createLink, + createParagraph, + svgToElement, +} from "../handlers/helpers.js"; export function renderGithubRepos(properties = {}) { - const gls = GLS.initLocal() + const gls = GLS.initLocal(); function lgls(key, replacements = {}) { - return gls.get(`taskProgress.githubFork.${key}`, replacements) + return gls.get(`taskProgress.githubFork.${key}`, replacements); } - const id = properties.id - const urls = properties.urls - const forkable = properties.forkable + const id = properties.id; + const urls = properties.urls; + const forkable = properties.forkable; - const wrapper = createDIV() - wrapper.classList.add("modal-githubrepos") - wrapper.id = id + const wrapper = createDIV(); + wrapper.classList.add("modal-githubrepos"); + wrapper.id = id; - urls.forEach(async repo => { - const itemWrapper = createDIV() - itemWrapper.classList.add("modal-githubrepos__item-wrapper") + urls.forEach(async (repo) => { + const itemWrapper = createDIV(); + itemWrapper.classList.add("modal-githubrepos__item-wrapper"); - const githubRepoEl = createLink("https://github.com/" + repo) - githubRepoEl.classList.add("modal-githubrepos__item") + const githubRepoEl = createLink("https://github.com/" + repo); + githubRepoEl.classList.add("modal-githubrepos__item"); - const githubIcon = await svgToElement("../assets/media/external/github.svg") - githubIcon.classList.add("modal-githubrepos__icon") + const githubIcon = await svgToElement("../assets/media/external/github.svg"); + githubIcon.classList.add("modal-githubrepos__icon"); - const githubURL = createParagraph(repo) - - githubRepoEl.appendChild(githubIcon) - githubRepoEl.appendChild(githubURL) + const githubUrl = createParagraph(repo); - itemWrapper.appendChild(githubRepoEl) + githubRepoEl.appendChild(githubIcon); + githubRepoEl.appendChild(githubUrl); - wrapper.appendChild(itemWrapper) + itemWrapper.appendChild(githubRepoEl); - const githubToken = await getGithubToken() + wrapper.appendChild(itemWrapper); - if(forkable && githubToken) { - const forkBtn = document.createElement("button") - forkBtn.classList.add("modal-githubrepos__forkbtn") + const githubToken = await getGithubToken(); - const forkIcon = createIcon("commit") - const forkText = createParagraph("Fork") + if (forkable && githubToken) { + const forkBtn = document.createElement("button"); + forkBtn.classList.add("modal-githubrepos__forkbtn"); - forkBtn.appendChild(forkIcon) - forkBtn.appendChild(forkText) + const forkIcon = createIcon("commit"); + const forkText = createParagraph("Fork"); + + forkBtn.appendChild(forkIcon); + forkBtn.appendChild(forkText); forkBtn.onclick = async () => { - const currentModal = Modal.get("orgPage") - currentModal.close() + const currentModal = Modal.get("orgPage"); + currentModal.close(); - const task = new Task("githubFork") - task.title(lgls("waiting.title", { name: repo })) - task.description(lgls("waiting.description")) - task.show() + const task = new Task("githubFork"); + task.title(lgls("waiting.title", { name: repo })); + task.description(lgls("waiting.description")); + task.show(); function error(title, desc) { - createNotify( - { - type: "danger", - icon: "cancel", - title: lgls("error.title", { name: repo }), - content: `Github: ${data.message}` - } - ) + createNotify({ + type: "danger", + icon: "cancel", + title: lgls("error.title", { name: repo }), + content: `Github: ${data.message}`, + }); - task.finish() - task.hide() + task.finish(); + task.hide(); - currentModal.open() + currentModal.open(); } - - const response = await fetch( - `https://api.github.com/repos/${repo}/forks`, - { - method: "POST", - headers: { - Authorization: `Bearer ${githubToken}`, - Accept: "application/vnd.github+json", - "X-GitHub-Api-Version": "2022-11-28", - }, - } - ); + + const response = await fetch(`https://api.github.com/repos/${repo}/forks`, { + method: "POST", + headers: { + Authorization: `Bearer ${githubToken}`, + Accept: "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", + }, + }); const data = await response.json(); - if(!response.ok) { - error( - lgls("error.title", { name: repo }), - `Github: ${data.message}` - ) - } - else if("fork" in data && data.fork) { - task.title(lgls("done.title")) - task.description() + if (!response.ok) { + error(lgls("error.title", { name: repo }), `Github: ${data.message}`); + } else if ("fork" in data && data.fork) { + task.title(lgls("done.title")); + task.description(); task.buttons([ { text: lgls("buttons.open"), type: "primary", action: () => { - const a = document.createElement("a") - a.href = data.html_url - a.target = "_blank" + const a = document.createElement("a"); + a.href = data.html_url; + a.target = "_blank"; - a.click() - a.remove() - } + a.click(); + a.remove(); + }, }, { text: lgls("buttons.cloneAndOpen"), type: "secondary", action: () => { - const a = document.createElement("a") - a.href = data.html_url - a.target = "_blank" + const a = document.createElement("a"); + a.href = data.html_url; + a.target = "_blank"; - a.click() - a.remove() - } - } - ]) + a.click(); + a.remove(); + }, + }, + ]); - task.finish() - } - else { - error( - lgls("errorAny.title", { name: repo }), - lgls("errorAny.description") - ) + task.finish(); + } else { + error(lgls("errorAny.title", { name: repo }), lgls("errorAny.description")); } - } + }; - itemWrapper.appendChild(forkBtn) + itemWrapper.appendChild(forkBtn); } - }) + }); - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/image.js b/assets/js/modalsHandler/components/image.js index 89f0132..115964a 100644 --- a/assets/js/modalsHandler/components/image.js +++ b/assets/js/modalsHandler/components/image.js @@ -1,17 +1,17 @@ -import { createDIV, createSpan } from "../handlers/helpers.js" +import { createDIV, createSpan } from "../handlers/helpers.js"; export function renderImage(properties = {}) { - const id = properties.id - const src = properties.src + const id = properties.id; + const src = properties.src; - const wrapper = document.createElement("img") - wrapper.classList.add("modal-image") - wrapper.id = id - wrapper.src = "" + const wrapper = document.createElement("img"); + wrapper.classList.add("modal-image"); + wrapper.id = id; + wrapper.src = ""; - if(src) { - wrapper.src = src + if (src) { + wrapper.src = src; } - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/infoBlocks.js b/assets/js/modalsHandler/components/infoBlocks.js index 31899dd..fa59b2e 100644 --- a/assets/js/modalsHandler/components/infoBlocks.js +++ b/assets/js/modalsHandler/components/infoBlocks.js @@ -1,31 +1,31 @@ import { createDIV, createLink, createParagraph, svgToElement } from "../handlers/helpers.js"; export function renderInfoBlocks(properties = {}) { - const id = properties.id - const blocks = properties.blocks + const id = properties.id; + const blocks = properties.blocks; - const wrapper = createDIV() - wrapper.classList.add("modal-infoblocks") - wrapper.id = id + const wrapper = createDIV(); + wrapper.classList.add("modal-infoblocks"); + wrapper.id = id; - blocks.forEach(block => { - const title = block.title - const description = block.description + blocks.forEach((block) => { + const title = block.title; + const description = block.description; - const infoBlock = createDIV() - infoBlock.classList.add("modal-infoblocks__item") + const infoBlock = createDIV(); + infoBlock.classList.add("modal-infoblocks__item"); - const titleEl = createParagraph(title) - titleEl.classList.add("modal-infoblocks__title") + const titleEl = createParagraph(title); + titleEl.classList.add("modal-infoblocks__title"); - const descEl = createParagraph(description) - descEl.classList.add("modal-infoblocks__desc") + const descEl = createParagraph(description); + descEl.classList.add("modal-infoblocks__desc"); - infoBlock.appendChild(titleEl) - infoBlock.appendChild(descEl) + infoBlock.appendChild(titleEl); + infoBlock.appendChild(descEl); - wrapper.appendChild(infoBlock) - }) + wrapper.appendChild(infoBlock); + }); - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/input.js b/assets/js/modalsHandler/components/input.js index 849cad9..522b95e 100644 --- a/assets/js/modalsHandler/components/input.js +++ b/assets/js/modalsHandler/components/input.js @@ -1,68 +1,61 @@ -import { createDIV, createSpan } from "../handlers/helpers.js" +import { createDIV, createSpan } from "../handlers/helpers.js"; export function renderInput(properties = {}) { - const id = properties.id - const title = properties.title - const description = properties.description - const placeholder = properties.placeholder - const prefix = properties.prefix - const inputType = properties.inputType - - const wrapper = document.createElement("div") - wrapper.classList.add("modal-category__item") - - const elementTitle = document.createElement("div") - elementTitle.classList.add("modal-category__item-title") - elementTitle.textContent = title - - const elementDesc = document.createElement("div") - elementDesc.classList.add("modal-category__item-desc") - elementDesc.textContent = description - - const inputWrapper = createDIV() - inputWrapper.classList.add("form-element") - - const input = document.createElement("input") - input.type = inputType ? inputType : "text" - input.spellcheck = "false" - input.id = id - - if(prefix) { - input.classList.add("focused") - input.value = prefix + const id = properties.id; + const title = properties.title; + const description = properties.description; + const placeholder = properties.placeholder; + const prefix = properties.prefix; + const inputType = properties.inputType; + + const wrapper = document.createElement("div"); + wrapper.classList.add("modal-category__item"); + + const elementTitle = document.createElement("div"); + elementTitle.classList.add("modal-category__item-title"); + elementTitle.textContent = title; + + const elementDesc = document.createElement("div"); + elementDesc.classList.add("modal-category__item-desc"); + elementDesc.textContent = description; + + const inputWrapper = createDIV(); + inputWrapper.classList.add("form-element"); + + const input = document.createElement("input"); + input.type = inputType ? inputType : "text"; + input.spellcheck = "false"; + input.id = id; + + if (prefix) { + input.classList.add("focused"); + input.value = prefix; } - const inputName = createSpan() - inputName.classList.add("form-label") - inputName.textContent = placeholder + const inputName = createSpan(); + inputName.classList.add("form-label"); + inputName.textContent = placeholder; - inputWrapper.appendChild(input) - inputWrapper.appendChild(inputName) + inputWrapper.appendChild(input); + inputWrapper.appendChild(inputName); - if(title) wrapper.appendChild(elementTitle) - if(description) wrapper.appendChild(elementDesc) - if(!placeholder) inputName.textContent = title + if (title) wrapper.appendChild(elementTitle); + if (description) wrapper.appendChild(elementDesc); + if (!placeholder) inputName.textContent = title; - wrapper.appendChild(inputWrapper) + wrapper.appendChild(inputWrapper); input.addEventListener("input", (e) => { - if(prefix) { + if (prefix) { if (!e.target.value.startsWith(prefix)) { e.target.value = prefix; } - input.classList.toggle( - "focused", - input.value.length > prefix.length - ); - } - else { - input.classList.toggle( - "focused", - input.value.length > 0 - ); + input.classList.toggle("focused", input.value.length > prefix.length); + } else { + input.classList.toggle("focused", input.value.length > 0); } }); - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/list.js b/assets/js/modalsHandler/components/list.js index 21c0ca1..1c8ba85 100644 --- a/assets/js/modalsHandler/components/list.js +++ b/assets/js/modalsHandler/components/list.js @@ -1,109 +1,111 @@ -import { createDIV, createSpan } from "../handlers/helpers.js" -import { renderButton } from "./button.js" -import { renderInput } from "./input.js" - -function renderInputHelper({ - i, - placeholders, - placeholderAll, - placeholderPrefix, - valuesReadOnly -}) { - let placeholder = placeholders[i] ?? `List item #${i}` +import { createDIV, createSpan } from "../handlers/helpers.js"; +import { renderButton } from "./button.js"; +import { renderInput } from "./input.js"; + +function renderInputHelper({ i, placeholders, placeholderAll, placeholderPrefix, valuesReadOnly }) { + let placeholder = placeholders[i] ?? `List item #${i}`; if (placeholderAll) { - placeholder = placeholderAll + placeholder = placeholderAll; } const input = renderInput({ id: `modal-list__item-${i + 1}`, - placeholder: placeholder, - prefix: placeholderPrefix - }) - - if(valuesReadOnly) { - input.querySelector("input").setAttribute("readonly", true) - } - else { - input.querySelector("input").removeAttribute("readonly") + placeholder, + prefix: placeholderPrefix, + }); + + if (valuesReadOnly) { + input.querySelector("input").setAttribute("readonly", true); + } else { + input.querySelector("input").removeAttribute("readonly"); } - return input + return input; } export function renderList(properties = {}) { - const id = properties.id - const maxElements = properties.maxElements - const renderType = properties.renderType - const placeholders = properties.placeholders - const placeholderAll = properties.placeholderAll - const placeholderPrefix = properties.placeholderPrefix - const values = properties.values - const valuesReadOnly = properties.valuesReadOnly - const onAdd = properties.onAdd - - const addedElements = [] - - const wrapper = createDIV() - wrapper.classList.add("modal-list") - wrapper.id = id - - if(renderType == "immediately") { - for(let i = 0; i < maxElements; i++) { + const id = properties.id; + const maxElements = properties.maxElements; + const renderType = properties.renderType; + const placeholders = properties.placeholders; + const placeholderAll = properties.placeholderAll; + const placeholderPrefix = properties.placeholderPrefix; + const values = properties.values; + const valuesReadOnly = properties.valuesReadOnly; + const onAdd = properties.onAdd; + + const addedElements = []; + + const wrapper = createDIV(); + wrapper.classList.add("modal-list"); + wrapper.id = id; + + if (renderType == "immediately") { + for (let i = 0; i < maxElements; i++) { const input = renderInputHelper({ - i, placeholders, placeholderAll, placeholderPrefix, valuesReadOnly - }) - - wrapper.appendChild(input) + i, + placeholders, + placeholderAll, + placeholderPrefix, + valuesReadOnly, + }); + + wrapper.appendChild(input); } - } - else if(renderType == "byAdding") { + } else if (renderType == "byAdding") { // render first - const minRender = values.length > 1 ? values.length : 1 + const minRender = values.length > 1 ? values.length : 1; - for(let i = 0; i < minRender; i++) { + for (let i = 0; i < minRender; i++) { const input = renderInputHelper({ - i, placeholders, placeholderAll, placeholderPrefix, valuesReadOnly - }) - - if(i in values) { - input.querySelector("input").value += values[i] + i, + placeholders, + placeholderAll, + placeholderPrefix, + valuesReadOnly, + }); + + if (i in values) { + input.querySelector("input").value += values[i]; } - addedElements.push(input) + addedElements.push(input); - wrapper.appendChild(input) + wrapper.appendChild(input); } - const addMoreBtn = renderButton( - { - title: "Add", - id: "modal-list__add-btn" - } - ) + const addMoreBtn = renderButton({ + title: "Add", + id: "modal-list__add-btn", + }); - if(!valuesReadOnly) { - wrapper.appendChild(addMoreBtn) + if (!valuesReadOnly) { + wrapper.appendChild(addMoreBtn); addMoreBtn.addEventListener("click", () => { - const currentID = addedElements.length + 1 + const currentId = addedElements.length + 1; - if(onAdd && typeof onAdd == "function") { - onAdd(currentID) + if (onAdd && typeof onAdd == "function") { + onAdd(currentId); } const input = renderInputHelper({ - currentID, placeholders, placeholderAll, placeholderPrefix, valuesReadOnly - }) - - addedElements.push(input) - addMoreBtn.before(input) - - if (currentID >= maxElements) { - addMoreBtn.classList.add("hidden") + currentID: currentId, + placeholders, + placeholderAll, + placeholderPrefix, + valuesReadOnly, + }); + + addedElements.push(input); + addMoreBtn.before(input); + + if (currentId >= maxElements) { + addMoreBtn.classList.add("hidden"); } - }) + }); } } - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/organization.js b/assets/js/modalsHandler/components/organization.js index dccbba5..7d4e6ea 100644 --- a/assets/js/modalsHandler/components/organization.js +++ b/assets/js/modalsHandler/components/organization.js @@ -1,165 +1,175 @@ -import { generateAvatar, GLS, idify, truncateString } from "../../lib.js" -import { valid } from "../engine.js" -import { createDIV, createParagraph, createIcon, createLink, createBadge, createSpan, wrapTags } from "../handlers/helpers.js" +import { GLS, generateAvatar, idify, truncateString } from "../../lib.js"; +import { valid } from "../engine.js"; +import { + createBadge, + createDIV, + createIcon, + createLink, + createParagraph, + createSpan, + wrapTags, +} from "../handlers/helpers.js"; export function renderOrganization(properties = {}) { - const gls = GLS.initLocal() + const gls = GLS.initLocal(); function lgls(key, replacements = {}) { - return gls.get(`modals.organizations.${key}`, replacements) + return gls.get(`modals.organizations.${key}`, replacements); } - let id = properties.id - const name = properties.name - const description = properties.description - const website = properties.website - const columns = properties.columns - const badgeOwner = properties.badgeOwner - const badgeVerified = properties.badgeVerified - const avatar = properties.avatar - const repos = properties.repos + let id = properties.id; + const name = properties.name; + const description = properties.description; + const website = properties.website; + const columns = properties.columns; + const badgeOwner = properties.badgeOwner; + const badgeVerified = properties.badgeVerified; + const avatar = properties.avatar; + const repos = properties.repos; function createSection() { - const sectionEl = createDIV() - sectionEl.classList.add("modal-org__section") + const sectionEl = createDIV(); + sectionEl.classList.add("modal-org__section"); - return sectionEl + return sectionEl; } function createCounter() { - const counterItemEl = createDIV() - counterItemEl.classList.add("modal-org__section-counter") + const counterItemEl = createDIV(); + counterItemEl.classList.add("modal-org__section-counter"); - return counterItemEl + return counterItemEl; } function createSectionComponent() { - const sectionEl = createDIV() - sectionEl.classList.add("modal-org__section-component") + const sectionEl = createDIV(); + sectionEl.classList.add("modal-org__section-component"); - return sectionEl + return sectionEl; } - if(!id) { - id = idify(name) + if (!id) { + id = idify(name); } - const wrapper = document.createElement("div") - wrapper.classList.add("modal-org") - wrapper.id = id + const wrapper = document.createElement("div"); + wrapper.classList.add("modal-org"); + wrapper.id = id; // first section - const firstSectionEl = createSection() - firstSectionEl.classList.add("row") + const firstSectionEl = createSection(); + firstSectionEl.classList.add("row"); - if(avatar) { - const avatarEl = document.createElement("img") - avatarEl.src = avatar - avatarEl.classList.add("modal-org__section-avatar") + if (avatar) { + const avatarEl = document.createElement("img"); + avatarEl.src = avatar; + avatarEl.classList.add("modal-org__section-avatar"); - firstSectionEl.appendChild(avatarEl) - } - else { - firstSectionEl.innerHTML = generateAvatar(name) + firstSectionEl.appendChild(avatarEl); + } else { + firstSectionEl.innerHTML = generateAvatar(name); } - const countersEl = createDIV() - countersEl.classList.add("modal-org__section-counters") + const countersEl = createDIV(); + countersEl.classList.add("modal-org__section-counters"); + + columns.forEach((col) => { + const name = valid(col.name) ?? "Unnamed"; + const value = valid(col.value) ?? "..."; - columns.forEach(col => { - const name = valid(col.name) ?? "Unnamed" - const value = valid(col.value) ?? "..." + const itemEl = createCounter(); - const itemEl = createCounter() - - const itemTitleEl = createParagraph(name) - itemTitleEl.classList.add("title") + const itemTitleEl = createParagraph(name); + itemTitleEl.classList.add("title"); - const itemValueEl = createParagraph(value) - itemValueEl.classList.add("value") + const itemValueEl = createParagraph(value); + itemValueEl.classList.add("value"); - itemEl.appendChild(itemTitleEl) - itemEl.appendChild(itemValueEl) + itemEl.appendChild(itemTitleEl); + itemEl.appendChild(itemValueEl); - countersEl.appendChild(itemEl) - }) + countersEl.appendChild(itemEl); + }); - firstSectionEl.appendChild(countersEl) + firstSectionEl.appendChild(countersEl); // second section - const secondSectionEl = createSection() + const secondSectionEl = createSection(); + + const secondSectionInfoComponent = createSectionComponent(); - const secondSectionInfoComponent = createSectionComponent() - - const secondSectionInfoComponentTitle = createParagraph(name, true) - secondSectionInfoComponentTitle.classList.add("modal-org__title") + const secondSectionInfoComponentTitle = createParagraph(name, true); + secondSectionInfoComponentTitle.classList.add("modal-org__title"); const secondSectionInfoComponentDesc = createParagraph( - wrapTags( - truncateString(description, 400) - ), false, true) - secondSectionInfoComponentDesc.classList.add("modal-org-description") + wrapTags(truncateString(description, 400)), + false, + true, + ); + secondSectionInfoComponentDesc.classList.add("modal-org-description"); - secondSectionInfoComponent.appendChild(secondSectionInfoComponentTitle) - secondSectionInfoComponent.appendChild(secondSectionInfoComponentDesc) + secondSectionInfoComponent.appendChild(secondSectionInfoComponentTitle); + secondSectionInfoComponent.appendChild(secondSectionInfoComponentDesc); - const secondSectionIconTextWrapper = createDIV() - secondSectionIconTextWrapper.classList.add("modal-org-icontext__wrapper") + const secondSectionIconTextWrapper = createDIV(); + secondSectionIconTextWrapper.classList.add("modal-org-icontext__wrapper"); - if(badgeVerified) { - const badge = createBadge("check") - badge.classList.add("modal-verified__badge") + if (badgeVerified) { + const badge = createBadge("check"); + badge.classList.add("modal-verified__badge"); - secondSectionInfoComponentTitle.appendChild(badge) + secondSectionInfoComponentTitle.appendChild(badge); } - if(badgeOwner) { - const badge = createBadge("crown") - badge.classList.add("modal-owner__badge") + if (badgeOwner) { + const badge = createBadge("crown"); + badge.classList.add("modal-owner__badge"); - secondSectionInfoComponentTitle.appendChild(badge) + secondSectionInfoComponentTitle.appendChild(badge); } - if(website) { - let url = website.startsWith("https://") ? new URL(website) : new URL("https://" + website) - let urlPreview = url.host + if (website) { + const url = website.startsWith("https://") + ? new URL(website) + : new URL("https://" + website); + let urlPreview = url.host; if (url.pathname != "/") { - urlPreview += url.pathname + urlPreview += url.pathname; } - const secondSectionIconText = createDIV() - secondSectionIconText.classList.add("modal-org-icontext") + const secondSectionIconText = createDIV(); + secondSectionIconText.classList.add("modal-org-icontext"); - const secondSectionIconTextIcon = createIcon("link_2") - const secondSectionIconTextLink = createLink(url.href) - secondSectionIconTextLink.textContent = urlPreview + const secondSectionIconTextIcon = createIcon("link_2"); + const secondSectionIconTextLink = createLink(url.href); + secondSectionIconTextLink.textContent = urlPreview; - secondSectionIconText.appendChild(secondSectionIconTextIcon) - secondSectionIconText.appendChild(secondSectionIconTextLink) + secondSectionIconText.appendChild(secondSectionIconTextIcon); + secondSectionIconText.appendChild(secondSectionIconTextLink); - secondSectionIconTextWrapper.appendChild(secondSectionIconText) + secondSectionIconTextWrapper.appendChild(secondSectionIconText); - secondSectionInfoComponent.appendChild(secondSectionIconTextWrapper) + secondSectionInfoComponent.appendChild(secondSectionIconTextWrapper); } - if(repos.length > 0) { - const secondSectionIconText = createDIV() - secondSectionIconText.classList.add("modal-org-icontext") + if (repos.length > 0) { + const secondSectionIconText = createDIV(); + secondSectionIconText.classList.add("modal-org-icontext"); - const secondSectionIconTextIcon = createIcon("commit") - const secondSectionIconTextLink = createSpan() - secondSectionIconTextLink.textContent = lgls("repos", { count: repos.length }) + const secondSectionIconTextIcon = createIcon("commit"); + const secondSectionIconTextLink = createSpan(); + secondSectionIconTextLink.textContent = lgls("repos", { count: repos.length }); - secondSectionIconText.appendChild(secondSectionIconTextIcon) - secondSectionIconText.appendChild(secondSectionIconTextLink) + secondSectionIconText.appendChild(secondSectionIconTextIcon); + secondSectionIconText.appendChild(secondSectionIconTextLink); - secondSectionIconTextWrapper.appendChild(secondSectionIconText) + secondSectionIconTextWrapper.appendChild(secondSectionIconText); - secondSectionInfoComponent.appendChild(secondSectionIconTextWrapper) + secondSectionInfoComponent.appendChild(secondSectionIconTextWrapper); } - secondSectionEl.appendChild(secondSectionInfoComponent) + secondSectionEl.appendChild(secondSectionInfoComponent); - wrapper.appendChild(firstSectionEl) - wrapper.appendChild(secondSectionEl) + wrapper.appendChild(firstSectionEl); + wrapper.appendChild(secondSectionEl); - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/placeholder.js b/assets/js/modalsHandler/components/placeholder.js index 78f3f5d..900a50e 100644 --- a/assets/js/modalsHandler/components/placeholder.js +++ b/assets/js/modalsHandler/components/placeholder.js @@ -1,46 +1,44 @@ -import { createDIV, createLink, createSpan } from "../handlers/helpers.js" -import { renderBadge } from "./badge.js" +import { createDIV, createLink, createSpan } from "../handlers/helpers.js"; +import { renderBadge } from "./badge.js"; export function renderPlaceholder(properties = {}) { - const id = properties.id - const title = properties.title - const description = properties.description - const titleBadge = properties.titleBadge - const link = properties.link - - const wrapper = document.createElement("div") - wrapper.classList.add("modal-category__item") - wrapper.id = id - - const elementTitle = document.createElement("div") - elementTitle.classList.add("modal-category__item-title") - elementTitle.textContent = title - - const elementDesc = document.createElement("div") - elementDesc.classList.add("modal-category__item-desc") - elementDesc.textContent = description - - if(title) wrapper.appendChild(elementTitle) - if(description) wrapper.appendChild(elementDesc) - - if(titleBadge) { - const badgeEl = renderBadge( - { - type: titleBadge - } - ) - - elementTitle.appendChild(badgeEl) + const id = properties.id; + const title = properties.title; + const description = properties.description; + const titleBadge = properties.titleBadge; + const link = properties.link; + + const wrapper = document.createElement("div"); + wrapper.classList.add("modal-category__item"); + wrapper.id = id; + + const elementTitle = document.createElement("div"); + elementTitle.classList.add("modal-category__item-title"); + elementTitle.textContent = title; + + const elementDesc = document.createElement("div"); + elementDesc.classList.add("modal-category__item-desc"); + elementDesc.textContent = description; + + if (title) wrapper.appendChild(elementTitle); + if (description) wrapper.appendChild(elementDesc); + + if (titleBadge) { + const badgeEl = renderBadge({ + type: titleBadge, + }); + + elementTitle.appendChild(badgeEl); } - if(link) { - const url = link.startsWith("https") ? new URL(link) : new URL(`https://${link}`) + if (link) { + const url = link.startsWith("https") ? new URL(link) : new URL(`https://${link}`); - const linkEl = createLink(url.href) - linkEl.textContent = url.host + const linkEl = createLink(url.href); + linkEl.textContent = url.host; - wrapper.appendChild(linkEl) + wrapper.appendChild(linkEl); } - return wrapper -} \ No newline at end of file + return wrapper; +} diff --git a/assets/js/modalsHandler/components/range.js b/assets/js/modalsHandler/components/range.js index 27f53f4..f74a69c 100644 --- a/assets/js/modalsHandler/components/range.js +++ b/assets/js/modalsHandler/components/range.js @@ -1,68 +1,65 @@ function createRangeLabels(properties = {}) { - const min = properties.min - const max = properties.max - const prefix = properties.prefix + const min = properties.min; + const max = properties.max; + const prefix = properties.prefix; - const middle = (min + max) / 2 + const middle = (min + max) / 2; return `
${min}${prefix}
${middle}${prefix}
${max}${prefix}
- ` + `; } export function renderRange(properties = {}) { - const id = properties.id - const title = properties.title - const description = properties.description + const id = properties.id; + const title = properties.title; + const description = properties.description; - const min = properties.min - const max = properties.max - const value = properties.value - const step = properties.step - const prefix = properties.prefix + const min = properties.min; + const max = properties.max; + const value = properties.value; + const step = properties.step; + const prefix = properties.prefix; - const wrapper = document.createElement("div") - wrapper.classList.add("modal-category__item") - - const element = document.createElement("div") - element.classList.add("modal-category__range") + const wrapper = document.createElement("div"); + wrapper.classList.add("modal-category__item"); - const input = document.createElement("input") - input.type = "range" - input.id = id - input.min = min - input.max = max - input.value = value - input.step = step + const element = document.createElement("div"); + element.classList.add("modal-category__range"); - const footer = document.createElement("div") - footer.classList.add("modal-category__range-footer") + const input = document.createElement("input"); + input.type = "range"; + input.id = id; + input.min = min; + input.max = max; + input.value = value; + input.step = step; - footer.innerHTML = createRangeLabels( - { - min: min, - max: max, - prefix: prefix - } - ) + const footer = document.createElement("div"); + footer.classList.add("modal-category__range-footer"); - const elementTitle = document.createElement("div") - elementTitle.classList.add("modal-category__item-title") - elementTitle.textContent = title + footer.innerHTML = createRangeLabels({ + min, + max, + prefix, + }); - const elementDesc = document.createElement("div") - elementDesc.classList.add("modal-category__item-desc") - elementDesc.textContent = description - + const elementTitle = document.createElement("div"); + elementTitle.classList.add("modal-category__item-title"); + elementTitle.textContent = title; - element.appendChild(input) - element.appendChild(footer) + const elementDesc = document.createElement("div"); + elementDesc.classList.add("modal-category__item-desc"); + elementDesc.textContent = description; - wrapper.appendChild(elementTitle) - wrapper.appendChild(elementDesc) - wrapper.appendChild(element) + element.appendChild(input); + element.appendChild(footer); - return wrapper -} \ No newline at end of file + wrapper.appendChild(elementTitle); + wrapper.appendChild(elementDesc); + wrapper.appendChild(element); + + return wrapper; +} diff --git a/assets/js/modalsHandler/components/switch.js b/assets/js/modalsHandler/components/switch.js index f26b780..63ccf11 100644 --- a/assets/js/modalsHandler/components/switch.js +++ b/assets/js/modalsHandler/components/switch.js @@ -1,38 +1,38 @@ export function renderSwitch(properties = {}) { - const id = properties.id - const title = properties.title - const description = properties.description - const checked = properties.checked - - const wrapper = document.createElement("div") - wrapper.classList.add("modal-category__item") - - const element = document.createElement("label") - element.classList.add("round-switch") - - const input = document.createElement("input") - input.type = "checkbox" - input.id = id - - if(checked) input.checked = checked - - const span = document.createElement("span") - span.classList.add("slider") - - const elementTitle = document.createElement("div") - elementTitle.classList.add("modal-category__item-title") - elementTitle.textContent = title - - const elementDesc = document.createElement("div") - elementDesc.classList.add("modal-category__item-desc") - elementDesc.textContent = description - - element.appendChild(input) - element.appendChild(span) - - wrapper.appendChild(elementTitle) - wrapper.appendChild(elementDesc) - wrapper.appendChild(element) - - return wrapper -} \ No newline at end of file + const id = properties.id; + const title = properties.title; + const description = properties.description; + const checked = properties.checked; + + const wrapper = document.createElement("div"); + wrapper.classList.add("modal-category__item"); + + const element = document.createElement("label"); + element.classList.add("round-switch"); + + const input = document.createElement("input"); + input.type = "checkbox"; + input.id = id; + + if (checked) input.checked = checked; + + const span = document.createElement("span"); + span.classList.add("slider"); + + const elementTitle = document.createElement("div"); + elementTitle.classList.add("modal-category__item-title"); + elementTitle.textContent = title; + + const elementDesc = document.createElement("div"); + elementDesc.classList.add("modal-category__item-desc"); + elementDesc.textContent = description; + + element.appendChild(input); + element.appendChild(span); + + wrapper.appendChild(elementTitle); + wrapper.appendChild(elementDesc); + wrapper.appendChild(element); + + return wrapper; +} diff --git a/assets/js/modalsHandler/engine.js b/assets/js/modalsHandler/engine.js index 9c4bc9c..627aa59 100644 --- a/assets/js/modalsHandler/engine.js +++ b/assets/js/modalsHandler/engine.js @@ -1,363 +1,354 @@ -import { renderModalBase } from "./components/base.js" +import { renderModalBase } from "./components/base.js"; -const backdrop = document.createElement("div") -backdrop.classList.add("backdrop", "hidden") +const backdrop = document.createElement("div"); +backdrop.classList.add("backdrop", "hidden"); -document.body.prepend(backdrop) +document.body.prepend(backdrop); // function for object validation inside Modal class export function valid(obj) { - if (obj === undefined || obj === null || obj === false) return undefined + if (obj === undefined || obj === null || obj === false) return; - if (Array.isArray(obj) && obj.length === 0) return undefined + if (Array.isArray(obj) && obj.length === 0) return; - if ( - typeof obj === "object" && - !Array.isArray(obj) && - Object.keys(obj).length === 0 - ) return undefined + if (typeof obj === "object" && !Array.isArray(obj) && Object.keys(obj).length === 0) return; - return obj + return obj; } // for arrays export function validArray(obj) { - if(valid(obj) == undefined) return undefined - if(typeof obj == "object" && !Array.isArray(obj)) return Object.keys(obj) - if(typeof obj != "object") return undefined + if (valid(obj) == undefined) return; + if (typeof obj == "object" && !Array.isArray(obj)) return Object.keys(obj); + if (typeof obj != "object") return; - return obj + return obj; } // for urls export function validHTTPS(url) { - if(!url) return undefined - if(!url.startsWith("https://")) return undefined + if (!url) return; + if (!url.startsWith("https://")) return; - return url + return url; } // for booleans export function validBool(boolean) { - if(typeof boolean == "boolean") return boolean - else return undefined + if (typeof boolean == "boolean") return boolean; } // for objects export function validObject(object) { - if(object !== null && typeof object === 'object' && !Array.isArray(object)) { - return object - } - else { - return undefined + if (object !== null && typeof object === "object" && !Array.isArray(object)) { + return object; } } export function err(text) { - throw new Error(`[CodeMotion.Modals] ${text}`) + throw new Error(`[CodeMotion.Modals] ${text}`); } export function showBackdrop() { - backdrop.classList.remove("hidden") + backdrop.classList.remove("hidden"); } export function hideBackdrop() { - backdrop.classList.add("hidden") + backdrop.classList.add("hidden"); } -const INPUT_EVENT_OPTS = { bubbles: true } +const INPUT_EVENT_OPTS = { bubbles: true }; export class Modal { - static list = {} + static list = {}; static create(config = {}) { - if (!config) err("Modal config can't be empty") + if (!config) err("Modal config can't be empty"); - const id = valid(config.id) ?? crypto.randomUUID().replaceAll("-", "") + const id = valid(config.id) ?? crypto.randomUUID().replaceAll("-", ""); if (Modal.list[id]) { - const existingModal = Modal.list[id] + const existingModal = Modal.list[id]; if (valid(config.content)) { - existingModal.setContent(config.content) + existingModal.setContent(config.content); } if (valid(config.title)) { - existingModal.setTitle(config.title) + existingModal.setTitle(config.title); } - return existingModal + return existingModal; } - const name = valid(config.name) ?? "Untitled" - const isHiddenOnSpawn = valid(config.show) ?? true - const modalClassList = validArray(config.modalClassList) ?? [] - let title = valid(config.title) ?? false - const titleAvatar = valid(config.titleAvatar) ?? false - const pages = valid(config.pages) ?? {} - const content = valid(config.content) ?? {} - const size = valid(config.size) ?? "default" - - let modalBase = null - let wrapper = null - let body = null - let contentEl = null - let titleEl = null - let sidebarPages = null - let sidebarIsBody = false - let pendingZIndex = null - let pendingContent = null - let pendingTitleText = null - let openListeners = [] + const name = valid(config.name) ?? "Untitled"; + const isHiddenOnSpawn = valid(config.show) ?? true; + const modalClassList = validArray(config.modalClassList) ?? []; + const title = valid(config.title) ?? false; + const titleAvatar = valid(config.titleAvatar) ?? false; + const pages = valid(config.pages) ?? {}; + const content = valid(config.content) ?? {}; + const size = valid(config.size) ?? "default"; + + let modalBase = null; + let wrapper = null; + let body = null; + let contentEl = null; + let titleEl = null; + let sidebarPages = null; + let sidebarIsBody = false; + let pendingZIndex = null; + let pendingContent = null; + let pendingTitleText = null; + let openListeners = []; function build() { - if (modalBase) return modalBase + if (modalBase) return modalBase; modalBase = renderModalBase({ - id: id, - isHiddenOnSpawn: isHiddenOnSpawn, - modalClassList: modalClassList, - title: title, - titleAvatar: titleAvatar, - pages: pages, - content: content, - size: size - }) - - wrapper = modalBase.wrapper - body = modalBase.body - - sidebarIsBody = body.classList.contains("modal-body-sidebar") + id, + isHiddenOnSpawn, + modalClassList, + title, + titleAvatar, + pages, + content, + size, + }); + + wrapper = modalBase.wrapper; + body = modalBase.body; + + sidebarIsBody = body.classList.contains("modal-body-sidebar"); if (sidebarIsBody) { - sidebarPages = body.querySelectorAll(".modal-body__sidebar-content") + sidebarPages = body.querySelectorAll(".modal-body__sidebar-content"); } - contentEl = wrapper.querySelector(".modal-content") - titleEl = wrapper.querySelector(".modal-title") + contentEl = wrapper.querySelector(".modal-content"); + titleEl = wrapper.querySelector(".modal-title"); if (pendingZIndex !== null) { - wrapper.style.zIndex = pendingZIndex + wrapper.style.zIndex = pendingZIndex; } if (pendingContent !== null) { - applyContent(pendingContent) - pendingContent = null + applyContent(pendingContent); + pendingContent = null; } if (pendingTitleText !== null) { - applyTitle(pendingTitleText) - pendingTitleText = null + applyTitle(pendingTitleText); + pendingTitleText = null; } - return modalBase + return modalBase; } function applyContent(newContent) { - if (!contentEl) return + if (!contentEl) return; if (typeof newContent === "string") { - contentEl.innerHTML = newContent - } - else if (newContent instanceof HTMLElement) { - contentEl.innerHTML = '' - contentEl.appendChild(newContent) + contentEl.innerHTML = newContent; + } else if (newContent instanceof HTMLElement) { + contentEl.innerHTML = ""; + contentEl.appendChild(newContent); } } function applyTitle(newTitle) { - if (!titleEl) return + if (!titleEl) return; - titleEl.textContent = newTitle + titleEl.textContent = newTitle; } function mount() { - build() + build(); if (!wrapper.isConnected) { - document.body.prepend(wrapper) + document.body.prepend(wrapper); } } function activate() { - mount() + mount(); - requestAnimationFrame(() => { - wrapper.classList.remove("hidden") - showBackdrop() - }) + requestAnimationFrame(() => { + wrapper.classList.remove("hidden"); + showBackdrop(); + }); if (openListeners.length) { - const listeners = openListeners.slice() - listeners.forEach(l => l.callback(api)) - openListeners = openListeners.filter(l => !l.once) + const listeners = openListeners.slice(); + listeners.forEach((l) => l.callback(api)); + openListeners = openListeners.filter((l) => !l.once); } } const api = { - id: id, + id, get el() { - build() - return wrapper + build(); + return wrapper; }, preRender: () => { - mount() + mount(); }, bind: (el) => { function bindClick(el) { el.addEventListener("click", () => { - activate() - }) + activate(); + }); } if (el instanceof NodeList) { - el.forEach(e => { - bindClick(e) - }) - } - else if (el instanceof HTMLElement) { - bindClick(el) + el.forEach((e) => { + bindClick(e); + }); + } else if (el instanceof HTMLElement) { + bindClick(el); } }, zIndex(value) { - if(Number.isInteger(value)) { + if (Number.isInteger(value)) { if (modalBase) { - wrapper.style.zIndex = value + wrapper.style.zIndex = value; } else { - pendingZIndex = value + pendingZIndex = value; } } }, open: () => { - activate() + activate(); }, onOpen: (callback, options = {}) => { - if (typeof callback !== "function") return () => {} + if (typeof callback !== "function") return () => {}; - const once = validBool(options.once) ?? false - const listener = { callback, once } + const once = validBool(options.once) ?? false; + const listener = { callback, once }; - openListeners.push(listener) + openListeners.push(listener); return () => { - openListeners = openListeners.filter(l => l !== listener) - } + openListeners = openListeners.filter((l) => l !== listener); + }; }, close: () => { - if (!modalBase) return + if (!modalBase) return; - hideBackdrop() - wrapper.classList.add("hidden") + hideBackdrop(); + wrapper.classList.add("hidden"); }, destroy: () => { if (modalBase) { - wrapper.remove() + wrapper.remove(); } - modalBase = null - wrapper = null - body = null - contentEl = null - titleEl = null - sidebarPages = null - openListeners = [] + modalBase = null; + wrapper = null; + body = null; + contentEl = null; + titleEl = null; + sidebarPages = null; + openListeners = []; - delete Modal.list[id] + delete Modal.list[id]; }, isSidebar: () => { - build() - return sidebarIsBody + build(); + return sidebarIsBody; }, disableCurrent() { - build() + build(); if (sidebarIsBody) { - sidebarPages.forEach(p => { - if(!p.classList.contains("hidden")) p.classList.add("disabled") - }) + sidebarPages.forEach((p) => { + if (!p.classList.contains("hidden")) p.classList.add("disabled"); + }); } }, unDisableCurrent() { - build() + build(); if (sidebarIsBody) { - sidebarPages.forEach(p => { - if(!p.classList.contains("hidden")) p.classList.remove("disabled") - }) + sidebarPages.forEach((p) => { + if (!p.classList.contains("hidden")) p.classList.remove("disabled"); + }); } }, pageShow: (pageIndex) => { - build() + build(); if (sidebarIsBody) { sidebarPages.forEach((page, index) => { - const pageid = page.id.split("_content")[0] + const pageid = page.id.split("_content")[0]; if (index == pageIndex) { - sidebarPages.forEach(p => p.classList.add("hidden")) - page.classList.remove("hidden") + sidebarPages.forEach((p) => p.classList.add("hidden")); + page.classList.remove("hidden"); - const pageSidebarBtn = wrapper.querySelector(`[id="${pageid}"]`) + const pageSidebarBtn = wrapper.querySelector(`[id="${pageid}"]`); if (pageSidebarBtn) { - wrapper.querySelectorAll(".modal-sidebar__item") - .forEach(i => i.classList.remove("active")) + wrapper + .querySelectorAll(".modal-sidebar__item") + .forEach((i) => i.classList.remove("active")); - pageSidebarBtn.classList.add("active") + pageSidebarBtn.classList.add("active"); } } - }) + }); } }, clear: () => { - if (!modalBase) return + if (!modalBase) return; - body.querySelectorAll("input").forEach(i => { - i.value = '' - i.dispatchEvent(new Event("input", INPUT_EVENT_OPTS)) - }) + body.querySelectorAll("input").forEach((i) => { + i.value = ""; + i.dispatchEvent(new Event("input", INPUT_EVENT_OPTS)); + }); }, setContent: (newContent) => { if (!modalBase) { - pendingContent = newContent - return + pendingContent = newContent; + return; } - applyContent(newContent) + applyContent(newContent); }, setTitle: (newTitle) => { if (!modalBase) { - pendingTitleText = newTitle - return + pendingTitleText = newTitle; + return; } - applyTitle(newTitle) - } - } + applyTitle(newTitle); + }, + }; - Modal.list[id] = api + Modal.list[id] = api; - return api + return api; } static get(id) { - return Modal.list[id] ?? null + return Modal.list[id] ?? null; } static destroy(id) { - const modal = Modal.list[id] + const modal = Modal.list[id]; - if (!modal) return + if (!modal) return; - modal.destroy() + modal.destroy(); } static closeAll() { - Object.values(Modal.list).forEach(modal => { - modal.close() - }) + Object.values(Modal.list).forEach((modal) => { + modal.close(); + }); } -} \ No newline at end of file +} diff --git a/assets/js/modalsHandler/handlers/contentHandler.js b/assets/js/modalsHandler/handlers/contentHandler.js index 40e15fc..b160334 100644 --- a/assets/js/modalsHandler/handlers/contentHandler.js +++ b/assets/js/modalsHandler/handlers/contentHandler.js @@ -1,466 +1,434 @@ -import { valid, validArray, validHTTPS, validBool, validObject } from "../engine.js" - -import { renderSwitch } from "../components/switch.js" -import { renderRange } from "../components/range.js" -import { renderPlaceholder } from "../components/placeholder.js" -import { renderExtensionItem } from "../components/extensionItem.js" -import { renderOrganization } from "../components/organization.js" -import { renderInput } from "../components/input.js" -import { renderButton } from "../components/button.js" -import { renderContainer } from "../components/container.js" -import { renderCentered } from "../components/centered.js" -import { renderDivider } from "../components/divider.js" -import { renderImage } from "../components/image.js" -import { renderDropdown } from "../components/dropdown.js" -import { renderList } from "../components/list.js" -import { renderGithubRepos } from "../components/githubRepos.js" -import { renderInfoBlocks } from "../components/infoBlocks.js" +import { renderButton } from "../components/button.js"; +import { renderCentered } from "../components/centered.js"; +import { renderContainer } from "../components/container.js"; +import { renderDivider } from "../components/divider.js"; +import { renderDropdown } from "../components/dropdown.js"; +import { renderExtensionItem } from "../components/extensionItem.js"; +import { renderGithubRepos } from "../components/githubRepos.js"; +import { renderImage } from "../components/image.js"; +import { renderInfoBlocks } from "../components/infoBlocks.js"; +import { renderInput } from "../components/input.js"; +import { renderList } from "../components/list.js"; +import { renderOrganization } from "../components/organization.js"; +import { renderPlaceholder } from "../components/placeholder.js"; +import { renderRange } from "../components/range.js"; +import { renderSwitch } from "../components/switch.js"; +import { valid, validArray, validBool, validHTTPS, validObject } from "../engine.js"; const types = { columns: (wrapper, data) => { - const cols = valid(data.cols) ?? 0 - const gap = valid(data.gap) ?? 0 + const cols = valid(data.cols) ?? 0; + const gap = valid(data.gap) ?? 0; - wrapper.classList.add("modal-columns") + wrapper.classList.add("modal-columns"); if (cols != 0) { - wrapper.style.cssText += `display: grid;grid-template-columns: repeat(${cols}, 1fr)` + wrapper.style.cssText += `display: grid;grid-template-columns: repeat(${cols}, 1fr)`; } if (gap != 0) { - wrapper.style.cssText += `gap: ${gap}px` + wrapper.style.cssText += `gap: ${gap}px`; } - return wrapper + return wrapper; }, row: (wrapper, data) => { - const classList = validArray(data.classList) ?? [] - const gap = valid(data.gap) ?? 0 + const classList = validArray(data.classList) ?? []; + const gap = valid(data.gap) ?? 0; - wrapper.classList.add("modal-row") + wrapper.classList.add("modal-row"); if (classList != 0) { - wrapper.classList.add(...classList) + wrapper.classList.add(...classList); } if (gap != 0) { - wrapper.style.cssText += `gap: ${gap}px` + wrapper.style.cssText += `gap: ${gap}px`; } - return wrapper + return wrapper; }, "row-clear": (wrapper, data) => { - const classList = validArray(data.classList) ?? [] - const gap = valid(data.gap) ?? 0 + const classList = validArray(data.classList) ?? []; + const gap = valid(data.gap) ?? 0; - wrapper.classList.add("modal-row", "modal-row__clear") + wrapper.classList.add("modal-row", "modal-row__clear"); if (classList != 0) { - wrapper.classList.add(...classList) + wrapper.classList.add(...classList); } if (gap != 0) { - wrapper.style.cssText += `gap: ${gap}px` + wrapper.style.cssText += `gap: ${gap}px`; } - return wrapper + return wrapper; }, category: (wrapper, data) => { - const label = valid(data.label) ?? "" + const label = valid(data.label) ?? ""; - wrapper.classList.add("modal-section-category") + wrapper.classList.add("modal-section-category"); - const labelEl = document.createElement("div") - labelEl.classList.add("modal-section-category__label") - labelEl.textContent = label.toUpperCase() + const labelEl = document.createElement("div"); + labelEl.classList.add("modal-section-category__label"); + labelEl.textContent = label.toUpperCase(); - wrapper.appendChild(labelEl) + wrapper.appendChild(labelEl); - return wrapper - } -} + return wrapper; + }, +}; export function sideBarContentHandler(element, contentData, id) { - const contentWrapper = document.createElement("div") - contentWrapper.id = `${id}_content` - contentWrapper.classList.add("modal-body__sidebar-content", "hidden") + const contentWrapper = document.createElement("div"); + contentWrapper.id = `${id}_content`; + contentWrapper.classList.add("modal-body__sidebar-content", "hidden"); - if (!Array.isArray(contentData)) return + if (!Array.isArray(contentData)) return; - contentData.forEach(contentElement => { - const type = valid(contentElement.type) ?? false + contentData.forEach((contentElement) => { + const type = valid(contentElement.type) ?? false; - if (type != false) { - if (type in types) { - const wrapper = types[type](contentWrapper, contentElement) - const items = valid(contentElement.items) ?? {} + if (type != false && type in types) { + const wrapper = types[type](contentWrapper, contentElement); + const items = valid(contentElement.items) ?? {}; - element.appendChild(wrapper) + element.appendChild(wrapper); - contentItemsHandler(wrapper, items) - } + contentItemsHandler(wrapper, items); } - }) + }); - element.appendChild(contentWrapper) + element.appendChild(contentWrapper); } export function defaultContentHandler(element, contentData) { - const contentWrapper = document.createElement("div") - contentWrapper.classList.add("modal-body__content") + const contentWrapper = document.createElement("div"); + contentWrapper.classList.add("modal-body__content"); - if(!Array.isArray(contentData)) return + if (!Array.isArray(contentData)) return; - contentData.forEach(contentElement => { - const type = valid(contentElement.type) ?? false + contentData.forEach((contentElement) => { + const type = valid(contentElement.type) ?? false; - if (type != false) { - if (type in types) { - const wrapper = types[type](contentWrapper, contentElement) - const items = valid(contentElement.items) ?? {} + if (type != false && type in types) { + const wrapper = types[type](contentWrapper, contentElement); + const items = valid(contentElement.items) ?? {}; - element.appendChild(wrapper) + element.appendChild(wrapper); - contentItemsHandler(wrapper, items) - } + contentItemsHandler(wrapper, items); } - }) + }); } function contentItemsHandler(element, itemsData) { - if(!Array.isArray(itemsData)) return + if (!Array.isArray(itemsData)) return; - itemsData.forEach(item => { - const type = valid(item.type) ?? false + itemsData.forEach((item) => { + const type = valid(item.type) ?? false; if (type == "switch") { - const id = valid(item.id) ?? false - const title = valid(item.title) ?? "Unnamed" - const desc = valid(item.description) ?? "No description provided" - const checked = validBool(item.checked) ?? false - - const switchElement = renderSwitch( - { - id: id, - title: title, - description: desc, - checked: checked - } - ) - - element.appendChild(switchElement) - - appendGlobalProperties(item, switchElement) + const id = valid(item.id) ?? false; + const title = valid(item.title) ?? "Unnamed"; + const desc = valid(item.description) ?? "No description provided"; + const checked = validBool(item.checked) ?? false; + + const switchElement = renderSwitch({ + id, + title, + description: desc, + checked, + }); + + element.appendChild(switchElement); + + appendGlobalProperties(item, switchElement); } if (type == "range") { - const id = valid(item.id) ?? false - const title = valid(item.title) ?? "Unnamed" - const desc = valid(item.description) ?? "No description provided" - const min = valid(item.min) ?? 0 - const max = valid(item.max) ?? 100 - const value = valid(item.value) ?? 0 - const step = valid(item.step) ?? 1 - const prefix = valid(item.prefix) ?? "" - - const rangeElement = renderRange( - { - id: id, - title: title, - description: desc, - min: min, - max: max, - value: value, - step: step, - prefix: prefix - } - ) - - element.appendChild(rangeElement) - - appendGlobalProperties(item, rangeElement) + const id = valid(item.id) ?? false; + const title = valid(item.title) ?? "Unnamed"; + const desc = valid(item.description) ?? "No description provided"; + const min = valid(item.min) ?? 0; + const max = valid(item.max) ?? 100; + const value = valid(item.value) ?? 0; + const step = valid(item.step) ?? 1; + const prefix = valid(item.prefix) ?? ""; + + const rangeElement = renderRange({ + id, + title, + description: desc, + min, + max, + value, + step, + prefix, + }); + + element.appendChild(rangeElement); + + appendGlobalProperties(item, rangeElement); } if (type == "placeholder") { - const id = valid(item.id) ?? false - const title = valid(item.title) ?? false - const description = valid(item.description) ?? false - const titleBadge = valid(item.titleBadge) ?? false - const link = valid(item.link) ?? false - - const placeholderElement = renderPlaceholder( - { - id: id, - title: title, - description: description, - titleBadge: titleBadge, - link: link - } - ) - - element.appendChild(placeholderElement) - - appendGlobalProperties(item, placeholderElement) + const id = valid(item.id) ?? false; + const title = valid(item.title) ?? false; + const description = valid(item.description) ?? false; + const titleBadge = valid(item.titleBadge) ?? false; + const link = valid(item.link) ?? false; + + const placeholderElement = renderPlaceholder({ + id, + title, + description, + titleBadge, + link, + }); + + element.appendChild(placeholderElement); + + appendGlobalProperties(item, placeholderElement); } if (type == "divider") { - const dividerElement = renderDivider() + const dividerElement = renderDivider(); - element.appendChild(dividerElement) + element.appendChild(dividerElement); - appendGlobalProperties(item, dividerElement) + appendGlobalProperties(item, dividerElement); } if (type == "extensionItem") { - const id = valid(item.id) ?? false - const title = valid(item.title) ?? false - const subtitle = valid(item.subtitle) ?? false - const description = valid(item.description) ?? false - const image = valid(item.image) ?? false - const tags = validArray(item.tags) ?? [] - const buttons = validArray(item.buttons) ?? [] - const toggle = valid(item.toggle) ?? null - - const extensionItemElement = renderExtensionItem( - { - title: title, - subtitle: subtitle, - description: description, - image: image, - tags: tags, - buttons: buttons, - id: id, - toggle: toggle - } - ) - - element.appendChild(extensionItemElement) - - appendGlobalProperties(item, extensionItemElement) + const id = valid(item.id) ?? false; + const title = valid(item.title) ?? false; + const subtitle = valid(item.subtitle) ?? false; + const description = valid(item.description) ?? false; + const image = valid(item.image) ?? false; + const tags = validArray(item.tags) ?? []; + const buttons = validArray(item.buttons) ?? []; + const toggle = valid(item.toggle) ?? null; + + const extensionItemElement = renderExtensionItem({ + title, + subtitle, + description, + image, + tags, + buttons, + id, + toggle, + }); + + element.appendChild(extensionItemElement); + + appendGlobalProperties(item, extensionItemElement); } if (type == "organization") { - const id = valid(item.id) ?? false - const name = valid(item.name) ?? "Unnamed" - const description = valid(item.description) ?? "No description provided" - const website = valid(item.website) ?? false - const columns = validArray(item.columns) ?? [] - const badgeOwner = validBool(item.badgeOwner) ?? false - const badgeVerified = validBool(item.badgeVerified) ?? false - const avatar = valid(item.avatar) ?? false - const repos = validArray(item.repos) ?? [] - - const organizationElement = renderOrganization( - { - id: id, - name: name, - description: description, - website: website, - columns: columns, - badgeOwner: badgeOwner, - badgeVerified: badgeVerified, - avatar: avatar, - repos: repos - } - ) - - element.appendChild(organizationElement) - - appendGlobalProperties(item, organizationElement) + const id = valid(item.id) ?? false; + const name = valid(item.name) ?? "Unnamed"; + const description = valid(item.description) ?? "No description provided"; + const website = valid(item.website) ?? false; + const columns = validArray(item.columns) ?? []; + const badgeOwner = validBool(item.badgeOwner) ?? false; + const badgeVerified = validBool(item.badgeVerified) ?? false; + const avatar = valid(item.avatar) ?? false; + const repos = validArray(item.repos) ?? []; + + const organizationElement = renderOrganization({ + id, + name, + description, + website, + columns, + badgeOwner, + badgeVerified, + avatar, + repos, + }); + + element.appendChild(organizationElement); + + appendGlobalProperties(item, organizationElement); } if (type == "input") { - const id = valid(item.id) ?? false - const title = valid(item.title) ?? false - const description = valid(item.description) ?? false - const placeholder = valid(item.placeholder) ?? false - const prefix = valid(item.prefix) ?? false - const values = validArray(item.values) ?? [] - const valuesReadOnly = validBool(item.valuesReadOnly) ?? false - const onAdd = valid(item.onAdd) ?? false - const inputType = valid(item.inputType) ?? false - - const inputElement = renderInput( - { - id: id, - title: title, - description: description, - placeholder: placeholder, - prefix: prefix, - values: values, - valuesReadOnly: valuesReadOnly, - onAdd: onAdd, - inputType: inputType - } - ) - - element.appendChild(inputElement) - - appendGlobalProperties(item, inputElement) + const id = valid(item.id) ?? false; + const title = valid(item.title) ?? false; + const description = valid(item.description) ?? false; + const placeholder = valid(item.placeholder) ?? false; + const prefix = valid(item.prefix) ?? false; + const values = validArray(item.values) ?? []; + const valuesReadOnly = validBool(item.valuesReadOnly) ?? false; + const onAdd = valid(item.onAdd) ?? false; + const inputType = valid(item.inputType) ?? false; + + const inputElement = renderInput({ + id, + title, + description, + placeholder, + prefix, + values, + valuesReadOnly, + onAdd, + inputType, + }); + + element.appendChild(inputElement); + + appendGlobalProperties(item, inputElement); } if (type == "button") { - const id = valid(item.id) ?? false - const title = valid(item.title) ?? false - const container = valid(item.container) ?? false - const btnClass = valid(item.class) ?? "default" - const onclick = valid(item.onclick) ?? false - - const buttonElement = renderButton( - { - id: id, - title: title, - container: container, - element: element, - class: btnClass, - onclick: onclick - } - ) - - element.appendChild(buttonElement) - - appendGlobalProperties(item, buttonElement) + const id = valid(item.id) ?? false; + const title = valid(item.title) ?? false; + const container = valid(item.container) ?? false; + const btnClass = valid(item.class) ?? "default"; + const onclick = valid(item.onclick) ?? false; + + const buttonElement = renderButton({ + id, + title, + container, + element, + class: btnClass, + onclick, + }); + + element.appendChild(buttonElement); + + appendGlobalProperties(item, buttonElement); } if (type == "container") { - const id = valid(item.id) ?? false - const classList = validArray(item.classList) ?? [] - const html = valid(item.html) ?? false + const id = valid(item.id) ?? false; + const classList = validArray(item.classList) ?? []; + const html = valid(item.html) ?? false; - const containerElement = renderContainer( - { - id: id, - classList: classList, - html: html - } - ) + const containerElement = renderContainer({ + id, + classList, + html, + }); - element.appendChild(containerElement) + element.appendChild(containerElement); - appendGlobalProperties(item, containerElement) + appendGlobalProperties(item, containerElement); } if (type == "centered") { - const icon = valid(item.icon) ?? false + const icon = valid(item.icon) ?? false; - const centeredElement = renderCentered( - { - icon: icon - } - ) + const centeredElement = renderCentered({ + icon, + }); - element.appendChild(centeredElement) + element.appendChild(centeredElement); - appendGlobalProperties(item, centeredElement) + appendGlobalProperties(item, centeredElement); } if (type == "image") { - const id = valid(item.id) ?? false - const src = valid(item.src) ?? false + const id = valid(item.id) ?? false; + const src = valid(item.src) ?? false; - const imageElement = renderImage( - { - id: id, - src: src - } - ) + const imageElement = renderImage({ + id, + src, + }); - element.appendChild(imageElement) + element.appendChild(imageElement); - appendGlobalProperties(item, imageElement) + appendGlobalProperties(item, imageElement); } if (type == "dropdown") { - const id = valid(item.id) ?? false - const title = valid(item.title) ?? "Unnamed" - const description = valid(item.description) ?? "No description provided" - const options = validArray(item.options) ?? [] - const selected = valid(item.selected) ?? "" - - const dropdownElement = renderDropdown( - { - id: id, - title: title, - description: description, - options: options, - selected: selected - } - ) - - element.appendChild(dropdownElement) - - appendGlobalProperties(item, dropdownElement) + const id = valid(item.id) ?? false; + const title = valid(item.title) ?? "Unnamed"; + const description = valid(item.description) ?? "No description provided"; + const options = validArray(item.options) ?? []; + const selected = valid(item.selected) ?? ""; + + const dropdownElement = renderDropdown({ + id, + title, + description, + options, + selected, + }); + + element.appendChild(dropdownElement); + + appendGlobalProperties(item, dropdownElement); } if (type == "list") { - const id = valid(item.id) ?? false - const maxElements = valid(item.maxElements) ?? 10 - const renderType = valid(item.renderType) ?? "immediately" - const placeholders = validArray(item.placeholders) ?? [] - const placeholderAll = valid(item.placeholderAll) ?? false - const placeholderPrefix = valid(item.placeholderPrefix) ?? false - - const listElement = renderList( - { - id: id, - maxElements: maxElements, - renderType: renderType, - placeholders: placeholders, - placeholderAll: placeholderAll, - placeholderPrefix: placeholderPrefix - } - ) - - element.appendChild(listElement) - - appendGlobalProperties(item, listElement) + const id = valid(item.id) ?? false; + const maxElements = valid(item.maxElements) ?? 10; + const renderType = valid(item.renderType) ?? "immediately"; + const placeholders = validArray(item.placeholders) ?? []; + const placeholderAll = valid(item.placeholderAll) ?? false; + const placeholderPrefix = valid(item.placeholderPrefix) ?? false; + + const listElement = renderList({ + id, + maxElements, + renderType, + placeholders, + placeholderAll, + placeholderPrefix, + }); + + element.appendChild(listElement); + + appendGlobalProperties(item, listElement); } if (type == "githubRepos") { - const id = valid(item.id) ?? false - const urls = validArray(item.urls) ?? [] - const forkable = validBool(item.forkable) ?? false + const id = valid(item.id) ?? false; + const urls = validArray(item.urls) ?? []; + const forkable = validBool(item.forkable) ?? false; - const githubReposElement = renderGithubRepos( - { - id: id, - urls: urls, - forkable: forkable - } - ) + const githubReposElement = renderGithubRepos({ + id, + urls, + forkable, + }); - element.appendChild(githubReposElement) + element.appendChild(githubReposElement); - appendGlobalProperties(item, githubReposElement) + appendGlobalProperties(item, githubReposElement); } if (type == "infoBlocks") { - const id = valid(item.id) ?? false - const blocks = validArray(item.blocks) ?? [] + const id = valid(item.id) ?? false; + const blocks = validArray(item.blocks) ?? []; - const infoBlocksElement = renderInfoBlocks( - { - id: id, - blocks: blocks - } - ) + const infoBlocksElement = renderInfoBlocks({ + id, + blocks, + }); - element.appendChild(infoBlocksElement) + element.appendChild(infoBlocksElement); - appendGlobalProperties(item, infoBlocksElement) + appendGlobalProperties(item, infoBlocksElement); } - }) + }); } function appendGlobalProperties(item, element) { - let note = false - let disabled = false - let classList = [] - let styles = {} + let note = false; + let disabled = false; + const classList = []; + const styles = {}; if ("note" in item) { - note = document.createElement("div") - note.classList.add("modal-note") - note.textContent = item.note + note = document.createElement("div"); + note.classList.add("modal-note"); + note.textContent = item.note; } - if ("disabled" in item) disabled = item.disabled - if ("classList" in item && Array.isArray(item.classList)) element.classList.add(...item.classList) + if ("disabled" in item) disabled = item.disabled; + if ("classList" in item && Array.isArray(item.classList)) + element.classList.add(...item.classList); if ("styles" in item) { const aliases = { width: "width", height: "height", - borderRadius: "border-radius" - } + borderRadius: "border-radius", + }; - Object.keys(item.styles).forEach(s => { - element.style.cssText += `${aliases[s]}: ${item.styles[s]}` - }) + Object.keys(item.styles).forEach((s) => { + element.style.cssText += `${aliases[s]}: ${item.styles[s]}`; + }); } - if (note) element.appendChild(note) - if (disabled) element.classList.add("disabled") -} \ No newline at end of file + if (note) element.appendChild(note); + if (disabled) element.classList.add("disabled"); +} diff --git a/assets/js/modalsHandler/handlers/helpers.js b/assets/js/modalsHandler/handlers/helpers.js index f151632..25a2749 100644 --- a/assets/js/modalsHandler/handlers/helpers.js +++ b/assets/js/modalsHandler/handlers/helpers.js @@ -1,68 +1,64 @@ export function createDIV() { - return document.createElement("div") + return document.createElement("div"); } -export function createParagraph(text, isWrapper = false, isHTML = false) { - const p = document.createElement("p") +export function createParagraph(text, isWrapper = false, isHtml = false) { + const p = document.createElement("p"); - if(!isHTML) p.textContent = text - if(isHTML) p.innerHTML = text + if (!isHtml) p.textContent = text; + if (isHtml) p.innerHTML = text; - if(isWrapper) { - const wrapper = document.createElement("span") - wrapper.appendChild(p) + if (isWrapper) { + const wrapper = document.createElement("span"); + wrapper.appendChild(p); - return wrapper - } - else { - return p + return wrapper; } + return p; } export function createIcon(name) { - const icon = document.createElement("span") - icon.classList.add("material-symbols-rounded") - icon.textContent = name + const icon = document.createElement("span"); + icon.classList.add("material-symbols-rounded"); + icon.textContent = name; - return icon + return icon; } export function createLink(url) { - const link = document.createElement("a") - link.target = "_blank" - link.href = `http://safety.yurba.one/?t=link&source=${url}` + const link = document.createElement("a"); + link.target = "_blank"; + link.href = `http://safety.yurba.one/?t=link&source=${url}`; - return link + return link; } export function createBadge(icon) { - const badge = document.createElement("div") - badge.classList.add("modal-badge") + const badge = document.createElement("div"); + badge.classList.add("modal-badge"); - const iconEl = document.createElement("span") - iconEl.classList.add("material-symbols-rounded") - iconEl.textContent = icon + const iconEl = document.createElement("span"); + iconEl.classList.add("material-symbols-rounded"); + iconEl.textContent = icon; - badge.appendChild(iconEl) + badge.appendChild(iconEl); - return badge + return badge; } export function createSpan() { - return document.createElement("span") + return document.createElement("span"); } export function replaceVars(text, vars) { - return text.replace(/\%\((.*?)\)/g, (_, key) => { - return key in vars ? String(vars[key]) : _; - }); + return text.replace(/%\((.*?)\)/g, (_, key) => (key in vars ? String(vars[key]) : _)); } export async function svgToElement(url) { - const parser = new DOMParser() + const parser = new DOMParser(); - const res = await fetch(url) - const svg = parser.parseFromString(await res.text(), "image/svg+xml") + const res = await fetch(url); + const svg = parser.parseFromString(await res.text(), "image/svg+xml"); - return svg.documentElement + return svg.documentElement; } -export function wrapTags(text, className = 'tag') { +export function wrapTags(text, className = "tag") { return text.replace( /(^|\s)(#([\p{L}\p{N}_-]+))/gu, - (_, space, tag) => `${space}${tag}` + (_, space, tag) => `${space}${tag}`, ); -} \ No newline at end of file +} diff --git a/assets/js/modalsHandler/handlers/sidebarHandler.js b/assets/js/modalsHandler/handlers/sidebarHandler.js index 5cb18e8..e47f723 100644 --- a/assets/js/modalsHandler/handlers/sidebarHandler.js +++ b/assets/js/modalsHandler/handlers/sidebarHandler.js @@ -1,113 +1,118 @@ -import { idify } from "../../lib.js" -import { valid, validBool } from "../engine.js" -import { sideBarContentHandler } from "./contentHandler.js" +import { idify } from "../../lib.js"; +import { valid, validBool } from "../engine.js"; +import { sideBarContentHandler } from "./contentHandler.js"; export function renderSidebarItem(name, properties = {}) { - const id = properties.id - const isDivider = properties.isDivider - const label = properties.label - const icon = properties.icon + const id = properties.id; + const isDivider = properties.isDivider; + const label = properties.label; + const icon = properties.icon; - const item = document.createElement("div") - item.classList.add("modal-sidebar__item") + const item = document.createElement("div"); + item.classList.add("modal-sidebar__item"); - if(id) item.id = id + if (id) item.id = id; if (isDivider) { - item.classList.add("sidebar-divider") - } - else { - item.textContent = name + item.classList.add("sidebar-divider"); + } else { + item.textContent = name; } if (icon) { - const itemIcon = document.createElement("span") - itemIcon.classList.add("material-symbols-rounded") - itemIcon.textContent = icon + const itemIcon = document.createElement("span"); + itemIcon.classList.add("material-symbols-rounded"); + itemIcon.textContent = icon; - item.prepend(itemIcon) + item.prepend(itemIcon); } if (label) { - const labelEl = document.createElement("span") - labelEl.classList.add("modal-sidebar__item-label") - labelEl.textContent = label + const labelEl = document.createElement("span"); + labelEl.classList.add("modal-sidebar__item-label"); + labelEl.textContent = label; - item.appendChild(labelEl) + item.appendChild(labelEl); } - return item + return item; } export function sideBarHandler(pagesArray = [], properties = {}) { - const body = properties.body - const title = properties.title - const titleAvatar = properties.titleAvatar + const body = properties.body; + const title = properties.title; + const titleAvatar = properties.titleAvatar; - body.classList.add("modal-body-sidebar") + body.classList.add("modal-body-sidebar"); - const sidebar = document.createElement("div") - sidebar.classList.add("modal-sidebar") + const sidebar = document.createElement("div"); + sidebar.classList.add("modal-sidebar"); // setup sidebar title - if(title) { - const sidebarTitle = renderSidebarItem(title) - sidebarTitle.classList.add("title") + if (title) { + const sidebarTitle = renderSidebarItem(title); + sidebarTitle.classList.add("title"); - if(titleAvatar) { - const titleAvatarEl = document.createElement("img") - titleAvatarEl.src = titleAvatar - titleAvatarEl.classList.add("avatar") + if (titleAvatar) { + const titleAvatarEl = document.createElement("img"); + titleAvatarEl.src = titleAvatar; + titleAvatarEl.classList.add("avatar"); - sidebarTitle.prepend(titleAvatarEl) + sidebarTitle.prepend(titleAvatarEl); } - sidebar.appendChild(sidebarTitle) + sidebar.appendChild(sidebarTitle); } - body.appendChild(sidebar) + body.appendChild(sidebar); // adding .modal-sidebar__item to sidebar for (let i = 0; i < pagesArray.length; i++) { - const p = pagesArray[i] + const p = pagesArray[i]; - const name = valid(p.name) ?? "Unnamed" - const icon = valid(p.icon) ?? false - const content = valid(p.content) ?? false - const label = valid(p.label) ?? false - const isDivider = validBool(p.divider) ?? false - const id = idify(name) + const name = valid(p.name) ?? "Unnamed"; + const icon = valid(p.icon) ?? false; + const content = valid(p.content) ?? false; + const label = valid(p.label) ?? false; + const isDivider = validBool(p.divider) ?? false; + const id = idify(name); const item = renderSidebarItem(name, { - icon: icon, - isDivider: isDivider, - label: label, - id: id - }) + icon, + isDivider, + label, + id, + }); // adding click action (show sidebar page) item.addEventListener("click", (e) => { - const thisPageID = e.currentTarget.id + const thisPageId = e.currentTarget.id; - const allPages = body.querySelectorAll(".modal-body__sidebar-content") - const thisPage = body.querySelector(`.modal-body__sidebar-content[id="${thisPageID}_content"]`) + const allPages = body.querySelectorAll(".modal-body__sidebar-content"); + const thisPage = body.querySelector( + `.modal-body__sidebar-content[id="${thisPageId}_content"]`, + ); - allPages.forEach(e => { e.classList.add("hidden") }) - thisPage.classList.remove("hidden") + allPages.forEach((e) => { + e.classList.add("hidden"); + }); + thisPage.classList.remove("hidden"); - body.querySelectorAll(".modal-sidebar__item").forEach(e => { e.classList.remove("active") }) - e.currentTarget.classList.add("active") - }) + body.querySelectorAll(".modal-sidebar__item").forEach((e) => { + e.classList.remove("active"); + }); + e.currentTarget.classList.add("active"); + }); // auto click on first child requestAnimationFrame(() => { - if(i == 0) { - item.click() + if (i == 0) { + item.click(); } - }) + }); - sidebar.appendChild(item) + sidebar.appendChild(item); - sideBarContentHandler(body, content, id) + sideBarContentHandler(body, content, id); } -} \ No newline at end of file +} diff --git a/assets/js/objects.js b/assets/js/objects.js index b1f643d..86fe305 100644 --- a/assets/js/objects.js +++ b/assets/js/objects.js @@ -1,7 +1,7 @@ export const priorityClasses = { - "0": { class: "priority-common", name: "common" }, - "1": { class: "priority-medium", name: "medium" }, - "2": { class: "priority-high", name: "high" } -} + 0: { class: "priority-common", name: "common" }, + 1: { class: "priority-medium", name: "medium" }, + 2: { class: "priority-high", name: "high" }, +}; -window.priorityClasses = priorityClasses \ No newline at end of file +window.priorityClasses = priorityClasses; diff --git a/assets/js/settings.js b/assets/js/settings.js index 84931a8..980a7a8 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -1,494 +1,520 @@ -import { Notificator, Options, showNeedReloadTopBar, GLS, createNotify } from "./lib.js" -import { optionsThemeButtonHandler } from "./handlers/themesHandler.js" - -import { Modal } from "../js/modalsHandler/engine.js" -import { getDirname, readSettings } from "../../assets/js/global.js" -import { capitilize } from "./lib.js" - -import { bus, sendEvent } from "./bus.js" -import { BottomWindow } from "./handlers/BottomWindowHandler.js" - -import { getSettingsModal } from "./modals/settingsModal.js" - -const themeSelect = new Options("themeSelect") -themeSelect.add("default", "Default").default() -themeSelect.add("light", "Default Light") -themeSelect.add("contrast-dark", "Contrast dark") - -const pythonRunnerMethodSelect = new Options("pythonRunnerMethod") -const languageSelect = new Options("languageSelect") - -export let settingsSelectors = {} +import { getDirname, readSettings } from "../../assets/js/global.js"; +import { Modal } from "../js/modalsHandler/engine.js"; +import { bus, sendEvent } from "./bus.js"; +import { BottomWindow } from "./handlers/BottomWindowHandler.js"; +import { optionsThemeButtonHandler } from "./handlers/themesHandler.js"; +import { + capitilize, + createNotify, + GLS, + Notificator, + Options, + showNeedReloadTopBar, +} from "./lib.js"; + +import { getSettingsModal } from "./modals/settingsModal.js"; + +const themeSelect = new Options("themeSelect"); +themeSelect.add("default", "Default").default(); +themeSelect.add("light", "Default Light"); +themeSelect.add("contrast-dark", "Contrast dark"); + +const pythonRunnerMethodSelect = new Options("pythonRunnerMethod"); +const languageSelect = new Options("languageSelect"); + +export let settingsSelectors = {}; export function updateSettingSelectors(object) { - settingsSelectors = object + settingsSelectors = object; } function updateThemeSelectDefault(settingsObject) { if ("ui" in settingsObject && "theme" in settingsObject.ui) { - const instance = themeSelect.get(settingsObject.ui.theme) + const instance = themeSelect.get(settingsObject.ui.theme); - if (instance) instance.default() + if (instance) instance.default(); } } // creating options export async function handleSettings(settingsObject) { - const localObject = await window.electron.getLocal() - const settings = await readSettings() - const platform = await window.electron.getPlatform() - const aviableLanguages = await window.electron.getAllLanguages() - const gls = await GLS.initLocal() + const localObject = await window.electron.getLocal(); + const settings = await readSettings(); + const platform = await window.electron.getPlatform(); + const aviableLanguages = await window.electron.getAllLanguages(); + const gls = await GLS.initLocal(); - const appearanceModal = await getSettingsModal({ platform: platform }) + const appearanceModal = await getSettingsModal({ platform }); - appearanceModal.bind(document.querySelector("#appearance_n")) - appearanceModal.preRender() + appearanceModal.bind(document.querySelector("#appearance_n")); + appearanceModal.preRender(); function get(id) { - return appearanceModal.el.querySelector(`#setting_${id}`) + return appearanceModal.el.querySelector(`#setting_${id}`); } - updateSettingSelectors( - { - editorTextSize: get("editorTextSize"), - useSystemFonts: get("useSystemFonts"), - boldFont: get("boldFont"), - devMode: get("devMode"), - splash: get("splash"), - reduceMotion: get("reduceMotion"), - uiScale: get("uiScale"), + updateSettingSelectors({ + editorTextSize: get("editorTextSize"), + useSystemFonts: get("useSystemFonts"), + boldFont: get("boldFont"), + devMode: get("devMode"), + splash: get("splash"), + reduceMotion: get("reduceMotion"), + uiScale: get("uiScale"), - coloredTabs: get("coloredTabs"), - confirmCloseTab: get("confirmCloseTab"), - restoreFolder: get("restoreFolder"), + coloredTabs: get("coloredTabs"), + confirmCloseTab: get("confirmCloseTab"), + restoreFolder: get("restoreFolder"), - goContextParser: get("go_context_parser"), + goContextParser: get("go_context_parser"), - disableRiskyPermissionWarning: get("disableRiskyPermissionWarning"), + disableRiskyPermissionWarning: get("disableRiskyPermissionWarning"), - gitGithubTokenInput: get("githubAccessKey"), - gitGithubTokenSave: get("githubAccessKeySave"), - gitGithubTokenView: get("githubAccessKeyView"), - } - ) + gitGithubTokenInput: get("githubAccessKey"), + gitGithubTokenSave: get("githubAccessKeySave"), + gitGithubTokenView: get("githubAccessKeyView"), + }); // handler for options button theme cause it need to be updated. Another one in custom theme handler - optionsThemeButtonHandler(themeSelect) + optionsThemeButtonHandler(themeSelect); - const appIconsWrapper = document.createElement("div") - appIconsWrapper.classList.add("modal-appicons") + const appIconsWrapper = document.createElement("div"); + appIconsWrapper.classList.add("modal-appicons"); - document.querySelector("#settings_appIcon .modal-note").after(appIconsWrapper) + document.querySelector("#settings_appIcon .modal-note").after(appIconsWrapper); function renderIcon(pathname, name, id) { - let isActive = settings.app.icon == name.toLowerCase() - let appIcon = document.createElement("div") + const isActive = settings.app.icon == name.toLowerCase(); + const appIcon = document.createElement("div"); - appIcon.id = id + appIcon.id = id; appIcon.innerHTML = `

${name}

- ` + `; - if (isActive) appIcon.classList.add("active") + if (isActive) appIcon.classList.add("active"); - appIconsWrapper.appendChild(appIcon) + appIconsWrapper.appendChild(appIcon); appIcon.addEventListener("click", async () => { - await window.electron.setSettings({ app: { icon: id } }) - await window.electron.reload() - }) + await window.electron.setSettings({ app: { icon: id } }); + await window.electron.reload(); + }); } - renderIcon(`../assets/media/codemotion_icon.png`, "Default", "default") + renderIcon("../assets/media/codemotion_icon.png", "Default", "default"); - const appIcons = await window.electron.getAppIcons() - appIcons.forEach(icon => { - let appIconCode = icon.split("codemotion-icon-")[1].split(".")[0] - let appIconCodeNormalize = capitilize(appIconCode.split("-").join(" ")) + const appIcons = await window.electron.getAppIcons(); + appIcons.forEach((icon) => { + const appIconCode = icon.split("codemotion-icon-")[1].split(".")[0]; + const appIconCodeNormalize = capitilize(appIconCode.split("-").join(" ")); - renderIcon(`../assets/media/app-icons/${icon}`, appIconCodeNormalize, appIconCode) - }) - // + renderIcon(`../assets/media/app-icons/${icon}`, appIconCodeNormalize, appIconCode); + }); // context parsers settingsSelectors.goContextParser.addEventListener("click", (e) => { - let t = e.target - Setting.goContextParser(t.checked) - }) + const t = e.target; + Setting.goContextParser(t.checked); + }); settingsSelectors.disableRiskyPermissionWarning.addEventListener("click", (e) => { - let t = e.target - Setting.disableRiskyPermissionWarning(t.checked) - }) - - // + const t = e.target; + Setting.disableRiskyPermissionWarning(t.checked); + }); settingsSelectors.coloredTabs.addEventListener("click", (e) => { - let t = e.target - Setting.coloredTabs(t.checked) - }) + const t = e.target; + Setting.coloredTabs(t.checked); + }); settingsSelectors.confirmCloseTab.addEventListener("click", (e) => { - let t = e.target - Setting.confirmCloseTab(t.checked) - }) + const t = e.target; + Setting.confirmCloseTab(t.checked); + }); settingsSelectors.restoreFolder.addEventListener("click", (e) => { - let t = e.target - Setting.restoreFolder(t.checked) - }) + const t = e.target; + Setting.restoreFolder(t.checked); + }); settingsSelectors.editorTextSize.addEventListener("change", (e) => { - Setting.editorTextSize(e.target.value) - }) + Setting.editorTextSize(e.target.value); + }); settingsSelectors.useSystemFonts.addEventListener("click", (e) => { - let t = e.target - Setting.useSystemFonts(t.checked) - }) + const t = e.target; + Setting.useSystemFonts(t.checked); + }); settingsSelectors.boldFont.addEventListener("click", (e) => { - let t = e.target - Setting.boldFont(t.checked) - }) + const t = e.target; + Setting.boldFont(t.checked); + }); settingsSelectors.devMode.addEventListener("click", (e) => { - let t = e.target - Setting.devMode(t.checked) - }) + const t = e.target; + Setting.devMode(t.checked); + }); settingsSelectors.splash.addEventListener("click", (e) => { - let t = e.target - Setting.splash(t.checked) - }) + const t = e.target; + Setting.splash(t.checked); + }); settingsSelectors.reduceMotion.addEventListener("click", (e) => { - let t = e.target - Setting.reduceMotion(t.checked) - }) + const t = e.target; + Setting.reduceMotion(t.checked); + }); settingsSelectors.uiScale.addEventListener("change", (e) => { - Setting.uiScale(e.target.value) - }) + Setting.uiScale(e.target.value); + }); settingsSelectors.gitGithubTokenSave.addEventListener("click", () => { - const token = settingsSelectors.gitGithubTokenInput.value + const token = settingsSelectors.gitGithubTokenInput.value; - Setting.githubToken(token) - }) - settingsSelectors.gitGithubTokenView.addEventListener("click", (e) => { - settingsSelectors.gitGithubTokenInput.type = "text" + Setting.githubToken(token); + }); + settingsSelectors.gitGithubTokenView.addEventListener( + "click", + (e) => { + settingsSelectors.gitGithubTokenInput.type = "text"; - e.target.remove() - }, { once: true }) + e.target.remove(); + }, + { once: true }, + ); - themeSelect.appendTo(document.querySelector("#setting_theme")) + themeSelect.appendTo(document.querySelector("#setting_theme")); if (platform == "win32") { - const pyInfo = await window.electron.getPython() + const pyInfo = await window.electron.getPython(); - pythonRunnerMethodSelect.add("builtin", gls.get("modals.appearance.editor.pythonRunner.select.builtIn")).default() + pythonRunnerMethodSelect + .add("builtin", gls.get("modals.appearance.editor.pythonRunner.select.builtIn")) + .default(); if (pyInfo != false) { - pythonRunnerMethodSelect.add("installed", `${gls.get("modals.appearance.editor.pythonRunner.select.userDefined")} (Python ${pyInfo.version})`) + pythonRunnerMethodSelect.add( + "installed", + `${gls.get("modals.appearance.editor.pythonRunner.select.userDefined")} (Python ${pyInfo.version})`, + ); } - pythonRunnerMethodSelect.appendTo(document.querySelector("#setting_pythonRunMethod")) + pythonRunnerMethodSelect.appendTo(document.querySelector("#setting_pythonRunMethod")); pythonRunnerMethodSelect.on("click", (e) => { - const ID = e.id + const Id = e.id; - Setting.pythonRunnerMethod(ID) - }) + Setting.pythonRunnerMethod(Id); + }); } - const aviableExtensionLanguages = [] + const aviableExtensionLanguages = []; if (aviableLanguages) { for (const index in aviableLanguages) { - const id = aviableLanguages[index] + const id = aviableLanguages[index]; - const gls = await GLS.init(id) - const languageName = gls.get("name") - const item = languageSelect.add(id, languageName == "name" ? id.toUpperCase() : languageName) + const gls = await GLS.init(id); + const languageName = gls.get("name"); + const item = languageSelect.add( + id, + languageName == "name" ? id.toUpperCase() : languageName, + ); - if (index == 0) item.default() + if (index == 0) item.default(); } function bindLanguageSelect() { languageSelect.on("click", (e) => { - const ID = e.id + const Id = e.id; - Setting.language(ID) - }) + Setting.language(Id); + }); } // add external languages (from extensions) bus.addEventListener("extension-localization-register", (data) => { - const id = data.detail.langName - const content = data.detail.configContent - const from = data.detail.from + const id = data.detail.langName; + const content = data.detail.configContent; + const from = data.detail.from; - languageSelect.add(id, content.name, { secondary: from }) + languageSelect.add(id, content.name, { secondary: from }); - bindLanguageSelect() - }) + bindLanguageSelect(); + }); - bindLanguageSelect() + bindLanguageSelect(); - languageSelect.appendTo(document.querySelector("#setting_language")) + languageSelect.appendTo(document.querySelector("#setting_language")); } - updateThemeSelectDefault(settingsObject) + updateThemeSelectDefault(settingsObject); bus.addEventListener("new-theme-register", (data) => { - const themeData = data.detail + const themeData = data.detail; - updateThemeSelectDefault(settingsObject) - }) + updateThemeSelectDefault(settingsObject); + }); if (settingsObject.editor) { - if ("fontSize" in settingsObject.editor) Setting.editorTextSize(settingsObject.editor.fontSize, false, false) - if ("pythonRunnerMethod" in settingsObject.editor) Setting.pythonRunnerMethod(settingsObject.editor.pythonRunnerMethod, false) - if ("coloredTabs" in settingsObject.editor) Setting.coloredTabs(settingsObject.editor.coloredTabs, false) - if ("confirmCloseTab" in settingsObject.editor) Setting.confirmCloseTab(settingsObject.editor.confirmCloseTab, false) - - if ("goContextParser" in settingsObject.editor) Setting.goContextParser(settingsObject.editor.goContextParser, false) + if ("fontSize" in settingsObject.editor) + Setting.editorTextSize(settingsObject.editor.fontSize, false, false); + if ("pythonRunnerMethod" in settingsObject.editor) + Setting.pythonRunnerMethod(settingsObject.editor.pythonRunnerMethod, false); + if ("coloredTabs" in settingsObject.editor) + Setting.coloredTabs(settingsObject.editor.coloredTabs, false); + if ("confirmCloseTab" in settingsObject.editor) + Setting.confirmCloseTab(settingsObject.editor.confirmCloseTab, false); + + if ("goContextParser" in settingsObject.editor) + Setting.goContextParser(settingsObject.editor.goContextParser, false); } if (settingsObject.ui) { - if ("useSystemFont" in settingsObject.ui) Setting.useSystemFonts(settingsObject.ui.useSystemFont, false) - if ("boldFont" in settingsObject.ui) Setting.boldFont(settingsObject.ui.boldFont, false) - if ("theme" in settingsObject.ui) Setting.themeSelect(settingsObject.ui.theme, false) + if ("useSystemFont" in settingsObject.ui) + Setting.useSystemFonts(settingsObject.ui.useSystemFont, false); + if ("boldFont" in settingsObject.ui) Setting.boldFont(settingsObject.ui.boldFont, false); + if ("theme" in settingsObject.ui) Setting.themeSelect(settingsObject.ui.theme, false); } if (settingsObject.app) { - if ("devMode" in settingsObject.app) Setting.devMode(settingsObject.app.devMode, false) - if ("splashScreen" in settingsObject.app) Setting.splash(settingsObject.app.splashScreen, false) - if ("reduceMotion" in settingsObject.app) Setting.reduceMotion(settingsObject.app.reduceMotion, false) - if ("uiScale" in settingsObject.app) Setting.uiScale(settingsObject.app.uiScale, false, false) - if ("language" in settingsObject.app) Setting.language(settingsObject.app.language, false) - if ("restoreFolder" in settingsObject.app) Setting.restoreFolder(settingsObject.app.restoreFolder, false) - } - if (settingsObject.extensions) { - if ("disableRiskyPermissionWarning" in settingsObject.extensions) Setting.disableRiskyPermissionWarning(settingsObject.extensions.disableRiskyPermissionWarning, false) + if ("devMode" in settingsObject.app) Setting.devMode(settingsObject.app.devMode, false); + if ("splashScreen" in settingsObject.app) + Setting.splash(settingsObject.app.splashScreen, false); + if ("reduceMotion" in settingsObject.app) + Setting.reduceMotion(settingsObject.app.reduceMotion, false); + if ("uiScale" in settingsObject.app) + Setting.uiScale(settingsObject.app.uiScale, false, false); + if ("language" in settingsObject.app) Setting.language(settingsObject.app.language, false); + if ("restoreFolder" in settingsObject.app) + Setting.restoreFolder(settingsObject.app.restoreFolder, false); } + if (settingsObject.extensions && "disableRiskyPermissionWarning" in settingsObject.extensions) + Setting.disableRiskyPermissionWarning( + settingsObject.extensions.disableRiskyPermissionWarning, + false, + ); if (localObject.githubToken) { - Setting.githubToken(localObject.githubToken, false) + Setting.githubToken(localObject.githubToken, false); } } export class Setting { static editorTextSize(value, notification = true, set = true) { - let v = Number(value) - let defaultFontSize = 15 - let editorFontSize = defaultFontSize * (v / 100) + const v = Number(value); + const defaultFontSize = 15; + const editorFontSize = defaultFontSize * (v / 100); - if (set) window.electron.setSettings({ editor: { fontSize: v } }) + if (set) window.electron.setSettings({ editor: { fontSize: v } }); - settingsSelectors.editorTextSize.value = value + settingsSelectors.editorTextSize.value = value; if (notification) { - const n = new Notificator() - n.text = v + "%" - n.icon = "format_size" - n.show() + const n = new Notificator(); + n.text = v + "%"; + n.icon = "format_size"; + n.show(); } - document.body.style.setProperty("--editor-font-size", editorFontSize + "px") + document.body.style.setProperty("--editor-font-size", editorFontSize + "px"); } static useSystemFonts(value, set = true) { if (value) { - document.body.style.setProperty("--main-font", "system-ui") - document.body.style.setProperty("--second-font", "system-ui") - document.body.style.setProperty("--code-font", "monospace") - } - else { - document.body.style.removeProperty("--main-font") - document.body.style.removeProperty("--second-font") - document.body.style.removeProperty("--code-font") + document.body.style.setProperty("--main-font", "system-ui"); + document.body.style.setProperty("--second-font", "system-ui"); + document.body.style.setProperty("--code-font", "monospace"); + } else { + document.body.style.removeProperty("--main-font"); + document.body.style.removeProperty("--second-font"); + document.body.style.removeProperty("--code-font"); } - settingsSelectors.useSystemFonts.checked = value + settingsSelectors.useSystemFonts.checked = value; - if (set) window.electron.setSettings({ ui: { useSystemFont: value } }) + if (set) window.electron.setSettings({ ui: { useSystemFont: value } }); } static boldFont(value, set = true) { - let styleElement = document.createElement("style") - styleElement.id = "settingsBoldFont" + const styleElement = document.createElement("style"); + styleElement.id = "settingsBoldFont"; if (value) { - document.body.style.setProperty("--default-font-weight", "800") - document.body.style.setProperty("--bold-font-weight", "800") - document.body.style.setProperty("--medium-font-weight", "700") - } - else { - document.body.style.removeProperty("--default-font-weight") - document.body.style.removeProperty("--bold-font-weight") - document.body.style.removeProperty("--medium-font-weight") + document.body.style.setProperty("--default-font-weight", "800"); + document.body.style.setProperty("--bold-font-weight", "800"); + document.body.style.setProperty("--medium-font-weight", "700"); + } else { + document.body.style.removeProperty("--default-font-weight"); + document.body.style.removeProperty("--bold-font-weight"); + document.body.style.removeProperty("--medium-font-weight"); } - settingsSelectors.boldFont.checked = value + settingsSelectors.boldFont.checked = value; - if (set) window.electron.setSettings({ ui: { boldFont: value } }) + if (set) window.electron.setSettings({ ui: { boldFont: value } }); } static themeSelect(value, set = true) { - let styleElement = document.createElement("style") - styleElement.id = "settingsLightTheme" + const styleElement = document.createElement("style"); + styleElement.id = "settingsLightTheme"; - document.body.setAttribute("theme", value) + document.body.setAttribute("theme", value); if (themeSelect.get(value) != false) { - themeSelect.get(value).default() + themeSelect.get(value).default(); } - if (set) window.electron.setSettings({ ui: { theme: value } }) + if (set) window.electron.setSettings({ ui: { theme: value } }); } static async devMode(value, set = true) { - settingsSelectors.devMode.checked = value + settingsSelectors.devMode.checked = value; if (set) { - await window.electron.setSettings({ app: { devMode: value } }) - window.electron.reload() + await window.electron.setSettings({ app: { devMode: value } }); + window.electron.reload(); } } static async splash(value, set = true) { - settingsSelectors.splash.checked = value + settingsSelectors.splash.checked = value; if (set) { - await window.electron.setSettings({ app: { splashScreen: value } }) + await window.electron.setSettings({ app: { splashScreen: value } }); } } static async reduceMotion(value, set = true) { - settingsSelectors.reduceMotion.checked = value + settingsSelectors.reduceMotion.checked = value; BottomWindow.settings = { ...BottomWindow.settings, app: { ...BottomWindow.settings?.app, - reduceMotion: value - } - } - window.dispatchEvent(new CustomEvent("codemotion-reduce-motion-change", { - detail: { reduceMotion: value } - })) + reduceMotion: value, + }, + }; + window.dispatchEvent( + new CustomEvent("codemotion-reduce-motion-change", { + detail: { reduceMotion: value }, + }), + ); if (set) { - await window.electron.setSettings({ app: { reduceMotion: value } }) + await window.electron.setSettings({ app: { reduceMotion: value } }); } } static async pythonRunnerMethod(value, set = true) { - const pythonRunnerMethodSelectGet = pythonRunnerMethodSelect.get(value) + const pythonRunnerMethodSelectGet = pythonRunnerMethodSelect.get(value); if (pythonRunnerMethodSelectGet) { - pythonRunnerMethodSelectGet.default() + pythonRunnerMethodSelectGet.default(); } if (set) { - showNeedReloadTopBar() - await window.electron.setSettings({ editor: { pythonRunnerMethod: value } }) + showNeedReloadTopBar(); + await window.electron.setSettings({ editor: { pythonRunnerMethod: value } }); } } static uiScale(value, notification = true, set = true) { - let v = Number(value) + const v = Number(value); - if (set) window.electron.setSettings({ app: { uiScale: v } }) + if (set) window.electron.setSettings({ app: { uiScale: v } }); - settingsSelectors.uiScale.value = value + settingsSelectors.uiScale.value = value; if (notification) { - const n = new Notificator() - n.text = value + "x" - n.icon = "linear_scale" - n.show() + const n = new Notificator(); + n.text = value + "x"; + n.icon = "linear_scale"; + n.show(); } - document.body.style.setProperty("--ui-scale", value) + document.body.style.setProperty("--ui-scale", value); } static async language(value, set = true) { async function update() { - const languageSelectGet = languageSelect.get(value) + const languageSelectGet = languageSelect.get(value); if (languageSelectGet) { - languageSelectGet.default() + languageSelectGet.default(); } if (set) { - showNeedReloadTopBar() - await window.electron.setSettings({ app: { language: value } }) + showNeedReloadTopBar(); + await window.electron.setSettings({ app: { language: value } }); } } - update() + update(); - bus.addEventListener("extension-localization-register", update) + bus.addEventListener("extension-localization-register", update); } static async coloredTabs(value, set = true) { - settingsSelectors.coloredTabs.checked = value + settingsSelectors.coloredTabs.checked = value; - sendEvent("on-setting-colored-tabs", value) + sendEvent("on-setting-colored-tabs", value); if (set) { - await window.electron.setSettings({ editor: { coloredTabs: value } }) + await window.electron.setSettings({ editor: { coloredTabs: value } }); } } static async restoreFolder(value, set = true) { - settingsSelectors.restoreFolder.checked = value + settingsSelectors.restoreFolder.checked = value; if (set) { - await window.electron.setSettings({ app: { restoreFolder: value } }) + await window.electron.setSettings({ app: { restoreFolder: value } }); } } static async confirmCloseTab(value, set = true) { - settingsSelectors.confirmCloseTab.checked = value + settingsSelectors.confirmCloseTab.checked = value; if (set) { - await window.electron.setSettings({ editor: { confirmCloseTab: value } }) + await window.electron.setSettings({ editor: { confirmCloseTab: value } }); } } static async goContextParser(value, set = true) { - settingsSelectors.goContextParser.checked = value + settingsSelectors.goContextParser.checked = value; if (set) { - await window.electron.setSettings({ editor: { goContextParser: value } }) + await window.electron.setSettings({ editor: { goContextParser: value } }); } } static async disableRiskyPermissionWarning(value, set = true) { - settingsSelectors.disableRiskyPermissionWarning.checked = value + settingsSelectors.disableRiskyPermissionWarning.checked = value; if (set) { - await window.electron.setSettings({ extensions: { disableRiskyPermissionWarning: value } }) + await window.electron.setSettings({ + extensions: { disableRiskyPermissionWarning: value }, + }); } } static async githubToken(value, set = true) { - const gls = GLS.initLocal() + const gls = GLS.initLocal(); - settingsSelectors.gitGithubTokenInput.value = value + settingsSelectors.gitGithubTokenInput.value = value; if (value.length > 0) { - settingsSelectors.gitGithubTokenInput.classList.add("focused") + settingsSelectors.gitGithubTokenInput.classList.add("focused"); } if (set) { - const res = window.electron.setLocal({ "githubToken": value }) + const res = window.electron.setLocal({ githubToken: value }); if (res) { createNotify({ type: "success", icon: "check", title: gls.get("modals.appearance.gitGithub.notifications.success.title"), - content: gls.get("modals.appearance.gitGithub.notifications.success.description") - }) - } - else { + content: gls.get( + "modals.appearance.gitGithub.notifications.success.description", + ), + }); + } else { createNotify({ type: "danger", icon: "cancel", title: gls.get("modals.appearance.gitGithub.notifications.error.title"), - content: gls.get("modals.appearance.gitGithub.notifications.error.description") - }) + content: gls.get("modals.appearance.gitGithub.notifications.error.description"), + }); } } } -} \ No newline at end of file +} diff --git a/assets/js/sidebar/ExplorerSidebar.js b/assets/js/sidebar/ExplorerSidebar.js index 5d21771..c37f334 100644 --- a/assets/js/sidebar/ExplorerSidebar.js +++ b/assets/js/sidebar/ExplorerSidebar.js @@ -1,55 +1,55 @@ -const explorerSidebar = document.querySelector(".explorer") -const sidebarHideBottomBtn = document.querySelector("#sidebar-hide") +const explorerSidebar = document.querySelector(".explorer"); +const sidebarHideBottomBtn = document.querySelector("#sidebar-hide"); -const localStorageKey = "codemotion.explorerSidebarVisible" +const localStorageKey = "codemotion.explorerSidebarVisible"; export class ExplorerSidebar { static init() { - if(this.getState()) { - explorerSidebar.classList.remove("zero-width") - } - else { - explorerSidebar.classList.add("zero-width") + if (ExplorerSidebar.getState()) { + explorerSidebar.classList.remove("zero-width"); + } else { + explorerSidebar.classList.add("zero-width"); } } static getState() { - return localStorage.getItem(localStorageKey) == null ? false : JSON.parse(localStorage.getItem(localStorageKey)) + return localStorage.getItem(localStorageKey) == null + ? false + : JSON.parse(localStorage.getItem(localStorageKey)); } static setZeroWidth() { - localStorage.setItem(localStorageKey, false) + localStorage.setItem(localStorageKey, false); - explorerSidebar.classList.add("zero-width") - sidebarHideBottomBtn.classList.remove("active") + explorerSidebar.classList.add("zero-width"); + sidebarHideBottomBtn.classList.remove("active"); } static setDefaultWidth() { - localStorage.setItem(localStorageKey, true) + localStorage.setItem(localStorageKey, true); - explorerSidebar.classList.remove("zero-width") - sidebarHideBottomBtn.classList.add("active") + explorerSidebar.classList.remove("zero-width"); + sidebarHideBottomBtn.classList.add("active"); } static isToggled() { - return explorerSidebar.classList.contains("zero-width") + return explorerSidebar.classList.contains("zero-width"); } static toggleWidth() { - if(this.isToggled()) { - this.setDefaultWidth() - } - else { - this.setZeroWidth() + if (ExplorerSidebar.isToggled()) { + ExplorerSidebar.setDefaultWidth(); + } else { + ExplorerSidebar.setZeroWidth(); } } static bindEvent(name) { setTimeout(() => { - if(name == "showInSidebarItemClick") { - const sidebarItems = document.querySelectorAll(".sidebar-item") + if (name == "showInSidebarItemClick") { + const sidebarItems = document.querySelectorAll(".sidebar-item"); - sidebarItems.forEach(i => { + sidebarItems.forEach((i) => { i.addEventListener("click", () => { - this.setDefaultWidth() - }) - }) + ExplorerSidebar.setDefaultWidth(); + }); + }); } - }, 500) + }, 500); } -} \ No newline at end of file +} diff --git a/assets/js/terminalRenderer/PyRuntimeHandler.js b/assets/js/terminalRenderer/PyRuntimeHandler.js index 5224126..ac2bd01 100644 --- a/assets/js/terminalRenderer/PyRuntimeHandler.js +++ b/assets/js/terminalRenderer/PyRuntimeHandler.js @@ -1,48 +1,49 @@ export function renderPyMsgSuccess({ RuntimeHistoryWindow, pythonResult, method }) { - const item = document.createElement("div") - item.className = "log bottom-window__item" - const itemContent = document.createElement("span") - itemContent.className = "translucent" - itemContent.textContent = pythonResult.file + " >>" - item.appendChild(itemContent) + const item = document.createElement("div"); + item.className = "log bottom-window__item"; + const itemContent = document.createElement("span"); + itemContent.className = "translucent"; + itemContent.textContent = pythonResult.file + " >>"; + item.appendChild(itemContent); - const stdoutSpan = document.createElement("span") - stdoutSpan.textContent = pythonResult.stdout - item.appendChild(stdoutSpan) + const stdoutSpan = document.createElement("span"); + stdoutSpan.textContent = pythonResult.stdout; + item.appendChild(stdoutSpan); - RuntimeHistoryWindow.add(item) + RuntimeHistoryWindow.add(item); - const exitCodeItem = document.createElement("div") - exitCodeItem.className = "log whitespaced bottom-window__item" - exitCodeItem.textContent = `Exit code ${pythonResult.exitCode}` + const exitCodeItem = document.createElement("div"); + exitCodeItem.className = "log whitespaced bottom-window__item"; + exitCodeItem.textContent = `Exit code ${pythonResult.exitCode}`; - RuntimeHistoryWindow.add(exitCodeItem) + RuntimeHistoryWindow.add(exitCodeItem); } export function renderPyMsgErr({ RuntimeHistoryWindow, pythonResult, method }) { - const item = document.createElement("div") - item.className = "log whitespaced bottom-window__item" + const item = document.createElement("div"); + item.className = "log whitespaced bottom-window__item"; - const fileSpan = document.createElement("span") - fileSpan.className = "translucent" - fileSpan.textContent = pythonResult.file + " >>" - item.appendChild(fileSpan) + const fileSpan = document.createElement("span"); + fileSpan.className = "translucent"; + fileSpan.textContent = pythonResult.file + " >>"; + item.appendChild(fileSpan); - const errorDiv = document.createElement("div") - errorDiv.className = "log-error" - errorDiv.textContent = `${pythonResult.stderr}` + const errorDiv = document.createElement("div"); + errorDiv.className = "log-error"; + errorDiv.textContent = `${pythonResult.stderr}`; - if(method == "builtin" && pythonResult.stderr.includes("ModuleNotFoundError")) { - errorDiv.textContent += `\nThis may be because you are using the built-in launch method. Custom modules are not available with this method. To ensure full functionality, you need to install Python from the official website and, after restarting the application, select your installed Python version in the settings: https://www.python.org/downloads/` + if (method == "builtin" && pythonResult.stderr.includes("ModuleNotFoundError")) { + errorDiv.textContent += + "\nThis may be because you are using the built-in launch method. Custom modules are not available with this method. To ensure full functionality, you need to install Python from the official website and, after restarting the application, select your installed Python version in the settings: https://www.python.org/downloads/"; } - item.appendChild(errorDiv) + item.appendChild(errorDiv); - RuntimeHistoryWindow.add(item) + RuntimeHistoryWindow.add(item); - const exitCodeItem = document.createElement("div") - exitCodeItem.className = "log bottom-window__item" - exitCodeItem.textContent = `Exit code ${pythonResult.exitCode}` + const exitCodeItem = document.createElement("div"); + exitCodeItem.className = "log bottom-window__item"; + exitCodeItem.textContent = `Exit code ${pythonResult.exitCode}`; - RuntimeHistoryWindow.add(exitCodeItem) -} \ No newline at end of file + RuntimeHistoryWindow.add(exitCodeItem); +} diff --git a/assets/js/topWindowHandler/topWindowList.js b/assets/js/topWindowHandler/topWindowList.js index 81dd480..4698375 100644 --- a/assets/js/topWindowHandler/topWindowList.js +++ b/assets/js/topWindowHandler/topWindowList.js @@ -1,141 +1,145 @@ -import { isArray, isObject } from "../lib.js" +import { isArray, isObject } from "../lib.js"; -const instances = new Map() -let autoId = 0 +const instances = new Map(); +let autoId = 0; document.addEventListener("click", (event) => { - instances.forEach(instance => { + instances.forEach((instance) => { if ( - !instance.window.contains(event.target) && - !instance.boundElements?.some(el => el.contains(event.target)) + !( + instance.window.contains(event.target) || + instance.boundElements?.some((el) => el.contains(event.target)) + ) ) { - instance.hide() + instance.hide(); } - }) -}) + }); +}); export function destroyAllTopWindowLists() { - instances.forEach(instance => instance.destroy()) - instances.clear() + instances.forEach((instance) => instance.destroy()); + instances.clear(); } export class TopWindowList { constructor(id = null, list = {}) { - id ??= `top-window-${++autoId}` + id ??= `top-window-${++autoId}`; if (instances.has(id)) { - return instances.get(id) + return instances.get(id); } - this.boundElements = [] - this.id = id - this.list = list + this.boundElements = []; + this.id = id; + this.list = list; - const window = document.createElement("div") - window.classList.add("top-window", "list", "hidden") - window.id = id + const window = document.createElement("div"); + window.classList.add("top-window", "list", "hidden"); + window.id = id; if (isArray(list)) { - list.forEach(item => { - if (!isObject(item)) return + list.forEach((item) => { + if (!isObject(item)) return; - const itemElement = document.createElement("div") - itemElement.classList.add("top-window__list-item") + const itemElement = document.createElement("div"); + itemElement.classList.add("top-window__list-item"); - const nameElement = document.createElement("div") - const nameWrapper = document.createElement("div") + const nameElement = document.createElement("div"); + const nameWrapper = document.createElement("div"); - nameWrapper.classList.add("top-window__list-item__name-wrapper") + nameWrapper.classList.add("top-window__list-item__name-wrapper"); if ("name" in item) { - nameElement.classList.add("top-window__list-item__name") - const nameElementSpan = document.createElement("span") - nameElementSpan.classList.add("name") - nameElementSpan.textContent = item.name + nameElement.classList.add("top-window__list-item__name"); + const nameElementSpan = document.createElement("span"); + nameElementSpan.classList.add("name"); + nameElementSpan.textContent = item.name; - nameElement.appendChild(nameElementSpan) + nameElement.appendChild(nameElementSpan); } if ("secondary" in item) { - const secondaryElementSpawn = document.createElement("span") - secondaryElementSpawn.textContent = item.secondary - secondaryElementSpawn.classList.add("secondary") + const secondaryElementSpawn = document.createElement("span"); + secondaryElementSpawn.textContent = item.secondary; + secondaryElementSpawn.classList.add("secondary"); - nameElement.appendChild(secondaryElementSpawn) + nameElement.appendChild(secondaryElementSpawn); } if ("id" in item) { - nameElement.id = item.id + nameElement.id = item.id; } if ("icon" in item) { - const iconEl = document.createElement("img") - iconEl.src = item.icon + const iconEl = document.createElement("img"); + iconEl.src = item.icon; - nameWrapper.prepend(iconEl) + nameWrapper.prepend(iconEl); } - nameWrapper.appendChild(nameElement) - itemElement.appendChild(nameWrapper) + nameWrapper.appendChild(nameElement); + itemElement.appendChild(nameWrapper); itemElement.addEventListener("click", () => { - this.hide() - }) + this.hide(); + }); - window.appendChild(itemElement) - }) + window.appendChild(itemElement); + }); } - this.window = window - document.body.prepend(window) + this.window = window; + document.body.prepend(window); - instances.set(id, this) + instances.set(id, this); } static get(id) { - return instances.get(id) + return instances.get(id); } on(eventName, cb) { - if (eventName !== "click") return + if (eventName !== "click") return; - this.window.querySelectorAll(".top-window__list-item").forEach(e => { - e.addEventListener("click", event => { - let target = event.target + this.window.querySelectorAll(".top-window__list-item").forEach((e) => { + e.addEventListener("click", (event) => { + let target = event.target; - if(target.tagName == "SPAN") target = target.parentElement + if (target.tagName == "SPAN") target = target.parentElement; cb({ - target: target, + target, id: target.id, name: target.querySelector(".name").textContent, - secondary: target.querySelector(".secondary") ? target.querySelector(".secondary").textContent : false - }) - }) - }) + secondary: target.querySelector(".secondary") + ? target.querySelector(".secondary").textContent + : false, + }); + }); + }); } bind(element) { if (element instanceof HTMLElement) { - this.boundElements.push(element) + this.boundElements.push(element); element.addEventListener("click", (event) => { - event.stopPropagation() - this.show() - }) + event.stopPropagation(); + this.show(); + }); } } show() { - this.window.classList.remove("hidden") + this.window.classList.remove("hidden"); } hide() { - this.window.classList.add("hidden") + this.window.classList.add("hidden"); } destroy() { - this.window.remove() - instances.delete(this.id) + this.window.remove(); + instances.delete(this.id); } -} \ No newline at end of file +} diff --git a/assets/js/user.js b/assets/js/user.js index a756984..80a7d79 100644 --- a/assets/js/user.js +++ b/assets/js/user.js @@ -1,12 +1,9 @@ -import { generateAvatar, truncateString, GLOBAL, GLS } from "./lib.js"; -import { Modal } from "./modalsHandler/engine.js"; - -import { spawnSideBarOrganizationsButton } from "./userHandlers/spawn.js" -import { createUserOrgsModalStructure } from "./userHandlers/orgModal.js"; -import { appendBugs } from "./userHandlers/appendBugs.js" -import { createUserOrgModal } from "./userHandlers/orgModal.js"; - import { bus } from "./bus.js"; +import { GLOBAL, GLS, generateAvatar, truncateString } from "./lib.js"; +import { Modal } from "./modalsHandler/engine.js"; +import { appendBugs } from "./userHandlers/appendBugs.js"; +import { createUserOrgModal, createUserOrgsModalStructure } from "./userHandlers/orgModal.js"; +import { spawnSideBarOrganizationsButton } from "./userHandlers/spawn.js"; import { setUserPcInfo } from "./userHandlers/userPC.js"; export async function requestUser() { @@ -19,79 +16,77 @@ export async function requestUser() { user: user.result.result.user, organizations: user.result.result.organizations, bugsCreated: user.result.result.bugs.created, - bugsAssigned: user.result.result.bugs.assigned - } - } - else { - return { - success: false, - result: user.result.result - } + bugsAssigned: user.result.result.bugs.assigned, + }; } + return { + success: false, + result: user.result.result, + }; } export async function getCurrentUserDataFromAPI(properties = {}) { - const gls = GLS.initLocal() - const user = await requestUser() - const greeting = document.querySelector("#greeting") + const gls = GLS.initLocal(); + const user = await requestUser(); + const greeting = document.querySelector("#greeting"); bus.addEventListener("org-created", async () => { - await getCurrentUserDataFromAPI({ orgsModalOpen: true }) - }) + await getCurrentUserDataFromAPI({ orgsModalOpen: true }); + }); bus.addEventListener("org-removed", async () => { - await getCurrentUserDataFromAPI({ orgsModalOpen: true }) - }) + await getCurrentUserDataFromAPI({ orgsModalOpen: true }); + }); bus.addEventListener("org-joined", async () => { - await getCurrentUserDataFromAPI({ orgsModalOpen: true }) - }) + await getCurrentUserDataFromAPI({ orgsModalOpen: true }); + }); bus.addEventListener("org-update", async () => { - await getCurrentUserDataFromAPI({ orgsModalOpen: true }) - }) + await getCurrentUserDataFromAPI({ orgsModalOpen: true }); + }); - setUserPcInfo() + setUserPcInfo(); if (!user.success) return user; - const userJSON = user.user; + const userJson = user.user; const userOrgs = user.organizations; - const bugsCreated = user.bugsCreated - const bugsAssigned = user.bugsAssigned + const bugsCreated = user.bugsCreated; + const bugsAssigned = user.bugsAssigned; - GLOBAL["user"] = userJSON + GLOBAL["user"] = userJson; // organizations - spawnSideBarOrganizationsButton({ userOrgs: userOrgs }) + spawnSideBarOrganizationsButton({ userOrgs }); - Modal.destroy("organizations") - const organizationsModal = await createUserOrgModal( - { - userOrgs: userOrgs, - userJSON: userJSON - } - ) - organizationsModal.bind(document.querySelectorAll("#yourOrganizations")) + Modal.destroy("organizations"); + const organizationsModal = await createUserOrgModal({ + userOrgs, + userJSON: userJson, + }); + organizationsModal.bind(document.querySelectorAll("#yourOrganizations")); if ("orgsModalOpen" in properties && properties.orgsModalOpen) { - organizationsModal.open() + organizationsModal.open(); } - // + // - document.querySelectorAll("#username").forEach(e => e.textContent = userJSON.name); - document.querySelectorAll("#greeting").forEach(e => e.textContent = gls.get("greeting.default", { name: userJSON.name })); - document.querySelectorAll("#bug_counter").forEach(e => { + document.querySelectorAll("#username").forEach((e) => (e.textContent = userJson.name)); + document + .querySelectorAll("#greeting") + .forEach((e) => (e.textContent = gls.get("greeting.default", { name: userJson.name }))); + document.querySelectorAll("#bug_counter").forEach((e) => { e.innerHTML = `
${Object.keys(bugsAssigned).length}
${Object.keys(bugsCreated).length}
-
${Object.keys({...bugsAssigned, ...bugsCreated}).length}
- ` +
${Object.keys({ ...bugsAssigned, ...bugsCreated }).length}
+ `; }); - document.querySelector("#userAvatar").innerHTML = generateAvatar(userJSON.name) + document.querySelector("#userAvatar").innerHTML = generateAvatar(userJson.name); - appendBugs(bugsCreated, "created") - appendBugs(bugsAssigned, "assigned") + appendBugs(bugsCreated, "created"); + appendBugs(bugsAssigned, "assigned"); return user.data; -} \ No newline at end of file +} diff --git a/assets/js/userHandlers/appendBugs.js b/assets/js/userHandlers/appendBugs.js index a9c7e6f..70ae9be 100644 --- a/assets/js/userHandlers/appendBugs.js +++ b/assets/js/userHandlers/appendBugs.js @@ -1,29 +1,29 @@ import { addToBug } from "../lib.js"; export function appendBugs(bugs, type) { - if(bugs) { - Object.keys(bugs).forEach((bugID, index) => { - const bug = bugs[bugID] + if (bugs) { + Object.keys(bugs).forEach((bugId, index) => { + const bug = bugs[bugId]; - const date = new Date(parseInt(bug.date) * 1000); + const date = new Date(Number.parseInt(bug.date) * 1000); const hours = date.format("d.m, H:i"); const day = date.format("l jS"); const object = { id: bug.id, - priority: parseInt(bug.priority), + priority: Number.parseInt(bug.priority), value: bug.title, - desc: bug.description ?? '', + desc: bug.description ?? "", today: hours, isSelf: bug.private == 1, org: bug.by.organization, resolved: bug.resolved, author: bug.by.name, assignedTo: bug.assigned_to, - type: type - } + type, + }; - addToBug(object) - }) + addToBug(object); + }); } -} \ No newline at end of file +} diff --git a/assets/js/userHandlers/orgModal.js b/assets/js/userHandlers/orgModal.js index 68f0f43..4c376fe 100644 --- a/assets/js/userHandlers/orgModal.js +++ b/assets/js/userHandlers/orgModal.js @@ -1,183 +1,164 @@ -import { Modal } from "../modalsHandler/engine.js" -import { createNotify, getInitials, GetOrgAvatar, GLS, Options, truncateString } from "../lib.js" -import { dashboardModalHandle, dashboardModalObject } from "./organizationModal/dashboard.js" -import { createNewModalHandle, createNewModalObject } from "./organizationModal/create-new.js" -import { joinModalHandle, joinModalObject } from "./organizationModal/join.js" -import { searchModalHandle, searchModalObject } from "./organizationModal/search.js" +import { createNotify, GetOrgAvatar, GLS, getInitials, Options, truncateString } from "../lib.js"; +import { Modal } from "../modalsHandler/engine.js"; +import { createNewModalHandle, createNewModalObject } from "./organizationModal/create-new.js"; +import { dashboardModalHandle, dashboardModalObject } from "./organizationModal/dashboard.js"; +import { joinModalHandle, joinModalObject } from "./organizationModal/join.js"; +import { searchModalHandle, searchModalObject } from "./organizationModal/search.js"; export async function getModalOrgStructure(organizationData) { - const gls = GLS.initLocal() - const isOwner = organizationData.is_owner + const gls = GLS.initLocal(); + const isOwner = organizationData.is_owner; const preparedData = { type: "organization", name: organizationData.name, - description: - organizationData.description, + description: organizationData.description, - website: - organizationData.website, + website: organizationData.website, columns: [ { - name: gls.get( - "modals.organizations.membersLabel" - ), + name: gls.get("modals.organizations.membersLabel"), - value: - organizationData.members_count - } + value: organizationData.members_count, + }, ], badgeOwner: isOwner, - badgeVerified: - organizationData.verified == 1 - } + badgeVerified: organizationData.verified == 1, + }; - const orgAvatar = await GetOrgAvatar.get(organizationData.avatarID, "large") + const orgAvatar = await GetOrgAvatar.get(organizationData.avatarID, "large"); if (orgAvatar) { - preparedData["avatar"] = orgAvatar + preparedData["avatar"] = orgAvatar; } if ("github_repos" in organizationData) { - preparedData["repos"] = organizationData.github_repos + preparedData["repos"] = organizationData.github_repos; } - return preparedData + return preparedData; } export async function createUserOrgsModalStructure({ userOrgs, userJSON, roleVisible }) { - const gls = GLS.initLocal() + const gls = GLS.initLocal(); - roleVisible = roleVisible == undefined ? true : roleVisible + roleVisible = roleVisible == undefined ? true : roleVisible; const organizationsModalData = await Promise.all( userOrgs.map(async (organization) => { - const organizationReq = - await window.electron.getOrgDataFromAPI(organization.id) + const organizationReq = await window.electron.getOrgDataFromAPI(organization.id); if (!organizationReq.success) { - createNotify( - { - type: "warn", - icon: "close", - title: "Organization Fetch Error", - content: `Error getting organization data: ${organization.id}` - } - ) + createNotify({ + type: "warn", + icon: "close", + title: "Organization Fetch Error", + content: `Error getting organization data: ${organization.id}`, + }); } - const organizationData = organizationReq.msg + const organizationData = organizationReq.msg; - const organizationRole = - organization.role?.length > 0 - ? organization.role - : "No role" + const organizationRole = organization.role?.length > 0 ? organization.role : "No role"; - const isOwner = organizationData.is_owner + const isOwner = organizationData.is_owner; // get modal structure - const preparedData = await getModalOrgStructure(organizationData) + const preparedData = await getModalOrgStructure(organizationData); // set role - preparedData["columns"].push( - { - name: gls.get( - "modals.organizations.roleLabel" - ), - - value: isOwner - ? gls.get( - "modals.organizations.ownerRoleLabel" - ) - : organizationRole - } - ) - - const orgAvatar = await GetOrgAvatar.get(organizationData.avatarID, "large") + preparedData["columns"].push({ + name: gls.get("modals.organizations.roleLabel"), + + value: isOwner ? gls.get("modals.organizations.ownerRoleLabel") : organizationRole, + }); + + const orgAvatar = await GetOrgAvatar.get(organizationData.avatarID, "large"); if (orgAvatar) { - preparedData["avatar"] = orgAvatar + preparedData["avatar"] = orgAvatar; } if ("github_repos" in organizationData) { - preparedData["repos"] = organizationData.github_repos + preparedData["repos"] = organizationData.github_repos; } if (!roleVisible) { - delete preparedData["columns"][1] + delete preparedData["columns"][1]; } if (isOwner) { preparedData.note = ` ${gls.get("modals.organizations.ownerLabel")} - ${organization.role?.length > 0 - ? gls.get( - "modals.organizations.ownerLabel", - { - role: organization.role - } - ) - : "" + ${ + organization.role?.length > 0 + ? gls.get("modals.organizations.ownerLabel", { + role: organization.role, + }) + : "" } - ` - .trim() + `.trim(); } - return preparedData - }) - ) + return preparedData; + }), + ); - return organizationsModalData + return organizationsModalData; } export async function createUserOrgModal({ userOrgs, userJSON }) { - const gls = GLS.initLocal() + const gls = GLS.initLocal(); function lgls(string, variables = {}) { - return gls.get(`modals.organizations.${string}`, variables) + return gls.get(`modals.organizations.${string}`, variables); } - const exploreOrganizationsRes = await window.electron.requestExploreOrganizations() + const exploreOrganizationsRes = await window.electron.requestExploreOrganizations(); const errorPlaceholder = { type: "placeholder", title: gls.get("errorPlaceholder.title"), - description: gls.get("errorPlaceholder.description") - } + description: gls.get("errorPlaceholder.description"), + }; - let exploreItems = [] - let membershipItems = [] + let exploreItems = []; + let membershipItems = []; if (exploreOrganizationsRes.success) { if (exploreOrganizationsRes.msg.length == 0) { exploreItems = [ { type: "centered", - icon: "explore" - } - ] + icon: "explore", + }, + ]; + } else { + exploreItems = await createUserOrgsModalStructure({ + userOrgs: exploreOrganizationsRes.msg, + userJSON, + roleVisible: false, + }); } - else { - exploreItems = await createUserOrgsModalStructure({ userOrgs: exploreOrganizationsRes.msg, userJSON: userJSON, roleVisible: false }) - } - } - else { - exploreItems = [errorPlaceholder] + } else { + exploreItems = [errorPlaceholder]; } if (Object.keys(userOrgs).length == 0) { membershipItems = [ { type: "centered", - icon: "group" - } - ] - } - else { - membershipItems = await createUserOrgsModalStructure({ userOrgs: userOrgs, userJSON: userJSON }) + icon: "group", + }, + ]; + } else { + membershipItems = await createUserOrgsModalStructure({ + userOrgs, + userJSON, + }); } const orgModal = Modal.create({ @@ -190,16 +171,18 @@ export async function createUserOrgModal({ userOrgs, userJSON }) { { name: lgls("explore.title"), icon: "explore", - label: exploreOrganizationsRes.success ? Object.keys(exploreOrganizationsRes.msg).length : 0, + label: exploreOrganizationsRes.success + ? Object.keys(exploreOrganizationsRes.msg).length + : 0, content: [ { type: "columns", cols: 2, gap: 10, - items: exploreItems - } - ] + items: exploreItems, + }, + ], }, { name: lgls("membership.title"), @@ -210,74 +193,72 @@ export async function createUserOrgModal({ userOrgs, userJSON }) { { type: "row", gap: 10, - items: membershipItems - } - ] + items: membershipItems, + }, + ], }, - dashboardModalObject({ lgls: lgls }), + dashboardModalObject({ lgls }), { - divider: true + divider: true, }, - createNewModalObject({ lgls: lgls }), - joinModalObject({ lgls: lgls }), + createNewModalObject({ lgls }), + joinModalObject({ lgls }), { - divider: true + divider: true, }, - searchModalObject({ lgls: lgls }), + searchModalObject({ lgls }), { - divider: true - } - ] - }) + divider: true, + }, + ], + }); - const element = orgModal.el - const createOrgNameField = element.querySelector("#orgName") - const createOrgDescField = element.querySelector("#orgDesc") - const createOrgWebsiteField = element.querySelector("#orgWebsite") - const createOrgSubmitBtn = element.querySelector("#orgConfirm") - const modalPreview = element.querySelector(".modal-org#orgPreview") + const element = orgModal.el; + const createOrgNameField = element.querySelector("#orgName"); + const createOrgDescField = element.querySelector("#orgDesc"); + const createOrgWebsiteField = element.querySelector("#orgWebsite"); + const createOrgSubmitBtn = element.querySelector("#orgConfirm"); + const modalPreview = element.querySelector(".modal-org#orgPreview"); // create organization - createNewModalHandle( - { - lgls: lgls, - modalPreview: modalPreview, - createOrgNameField: createOrgNameField, - createOrgDescField: createOrgDescField, - createOrgWebsiteField: createOrgWebsiteField, - createOrgSubmitBtn: createOrgSubmitBtn, - orgModal: orgModal, - element: element - } - ) + createNewModalHandle({ + lgls, + modalPreview, + createOrgNameField, + createOrgDescField, + createOrgWebsiteField, + createOrgSubmitBtn, + orgModal, + element, + }); // dashboard dashboardModalHandle({ - userOrgs: userOrgs, - element: element, - orgModal: orgModal - }) + userOrgs, + element, + orgModal, + }); - // + // // join joinModalHandle({ - element: element, - lgls: lgls - }) + element, + lgls, + }); - // + // // search searchModalHandle({ modal: orgModal, - element: element, - lgls: lgls - }) + element, + lgls, + }); - return orgModal -} \ No newline at end of file + return orgModal; +} diff --git a/assets/js/userHandlers/organizationModal/create-new.js b/assets/js/userHandlers/organizationModal/create-new.js index d8fb928..d40595a 100644 --- a/assets/js/userHandlers/organizationModal/create-new.js +++ b/assets/js/userHandlers/organizationModal/create-new.js @@ -1,5 +1,5 @@ -import { sendEvent } from "../../bus.js" -import { createNotify, getInitials, truncateString } from "../../lib.js" +import { sendEvent } from "../../bus.js"; +import { createNotify, getInitials, truncateString } from "../../lib.js"; export function createNewModalObject({ lgls }) { return { @@ -14,30 +14,30 @@ export function createNewModalObject({ lgls }) { { type: "placeholder", title: lgls("createNew.header.title"), - description: lgls("createNew.header.description") + description: lgls("createNew.header.description"), }, { type: "input", placeholder: lgls("createNew.inputs.name"), - id: "orgName" + id: "orgName", }, { type: "input", placeholder: lgls("createNew.inputs.about"), - id: "orgDesc" + id: "orgDesc", }, { type: "input", placeholder: lgls("createNew.inputs.website"), - id: "orgWebsite" + id: "orgWebsite", }, { - type: "divider" + type: "divider", }, { type: "placeholder", title: lgls("createNew.preview.title"), - description: lgls("createNew.preview.description") + description: lgls("createNew.preview.description"), }, { id: "orgPreview", @@ -47,106 +47,109 @@ export function createNewModalObject({ lgls }) { columns: [ { name: lgls("membersLabel"), - value: 1 + value: 1, }, { name: lgls("roleLabel"), - value: lgls("ownerRoleLabel") - } + value: lgls("ownerRoleLabel"), + }, ], website: "https://example.com/", - badgeOwner: true + badgeOwner: true, }, { type: "container", - id: "buttonsContainer" + id: "buttonsContainer", }, { type: "button", id: "orgConfirm", title: lgls("buttons.create"), - container: "#buttonsContainer" - } - ] - } - ] - } + container: "#buttonsContainer", + }, + ], + }, + ], + }; } -export function createNewModalHandle( - { - lgls, - createOrgNameField, - modalPreview, - createOrgDescField, - createOrgWebsiteField, - createOrgSubmitBtn, - orgModal, - element - } -) { +export function createNewModalHandle({ + lgls, + createOrgNameField, + modalPreview, + createOrgDescField, + createOrgWebsiteField, + createOrgSubmitBtn, + orgModal, + element, +}) { createOrgNameField.addEventListener("input", (e) => { - modalPreview.querySelector(".modal-org__title p").textContent = e.target.value - modalPreview.querySelector(".generated-avatar").textContent = getInitials(e.target.value) + modalPreview.querySelector(".modal-org__title p").textContent = e.target.value; + modalPreview.querySelector(".generated-avatar").textContent = getInitials(e.target.value); if (e.target.value.length == 0) { - modalPreview.querySelector(".modal-org__title p").textContent = lgls("createNew.preview.emptyName") - modalPreview.querySelector(".generated-avatar").textContent = getInitials("U") + modalPreview.querySelector(".modal-org__title p").textContent = lgls( + "createNew.preview.emptyName", + ); + modalPreview.querySelector(".generated-avatar").textContent = getInitials("U"); } - }) + }); createOrgDescField.addEventListener("input", (e) => { - modalPreview.querySelector(".modal-org-description").textContent = truncateString(e.target.value, 100) + modalPreview.querySelector(".modal-org-description").textContent = truncateString( + e.target.value, + 100, + ); if (e.target.value.length == 0) { - modalPreview.querySelector(".modal-org-description").textContent = lgls("createNew.preview.emptyDescription") + modalPreview.querySelector(".modal-org-description").textContent = lgls( + "createNew.preview.emptyDescription", + ); } - }) + }); createOrgWebsiteField.addEventListener("input", (e) => { - modalPreview.querySelector(".modal-org-icontext a").textContent = e.target.value + modalPreview.querySelector(".modal-org-icontext a").textContent = e.target.value; if (e.target.value.length == 0) { - modalPreview.querySelector(".modal-org-icontext a").textContent = "example.com" + modalPreview.querySelector(".modal-org-icontext a").textContent = "example.com"; } - }) + }); createOrgSubmitBtn.addEventListener("click", async () => { - const name = createOrgNameField.value - const desc = createOrgDescField.value - const website = createOrgWebsiteField.value + const name = createOrgNameField.value; + const desc = createOrgDescField.value; + const website = createOrgWebsiteField.value; - const createOrgRes = await window.electron.createOrganization( - { - name: name, - description: desc, - website: website - } - ) + const createOrgRes = await window.electron.createOrganization({ + name, + description: desc, + website, + }); - if (!createOrgRes.success) { - createNotify( - { - type: "danger", - icon: "close", - title: lgls("notifications.creatingError.title"), - content: createOrgRes.msg.message == undefined ? createOrgRes.msg : createOrgRes.msg.message - } - ) - } - else { - orgModal.close() + if (createOrgRes.success) { + orgModal.close(); element.addEventListener("transitionend", () => { - sendEvent("org-created", {}) - }) + sendEvent("org-created", {}); + }); - createNotify( - { - type: "success", - icon: "check", - title: lgls("notifications.creatingSuccess.title"), - content: lgls("notifications.creatingSuccess.description", { name: createOrgRes.msg.name }) - } - ) + createNotify({ + type: "success", + icon: "check", + title: lgls("notifications.creatingSuccess.title"), + content: lgls("notifications.creatingSuccess.description", { + name: createOrgRes.msg.name, + }), + }); + } else { + createNotify({ + type: "danger", + icon: "close", + title: lgls("notifications.creatingError.title"), + content: + createOrgRes.msg.message == undefined + ? createOrgRes.msg + : createOrgRes.msg.message, + }); } - }) -} \ No newline at end of file + }); +} diff --git a/assets/js/userHandlers/organizationModal/dashboard.js b/assets/js/userHandlers/organizationModal/dashboard.js index b1d9ae7..91a5050 100644 --- a/assets/js/userHandlers/organizationModal/dashboard.js +++ b/assets/js/userHandlers/organizationModal/dashboard.js @@ -1,16 +1,16 @@ -import { sendEvent } from "../../bus.js" -import { createNotify, truncateString, Options, formatUnix, GetOrgAvatar, GLS } from "../../lib.js" -import { renderList } from "../../modalsHandler/components/list.js" -import { Modal } from "../../modalsHandler/engine.js" +import { sendEvent } from "../../bus.js"; +import { createNotify, formatUnix, GetOrgAvatar, GLS, Options, truncateString } from "../../lib.js"; +import { renderList } from "../../modalsHandler/components/list.js"; +import { Modal } from "../../modalsHandler/engine.js"; function encodeInviteCode(code) { - if(!code) { - return "****" + if (!code) { + return "****"; } return code .split("-") - .map(part => "*".repeat(part.length)) - .join("-") + .map((part) => "*".repeat(part.length)) + .join("-"); } export function dashboardModalObject({ lgls }) { @@ -26,15 +26,15 @@ export function dashboardModalObject({ lgls }) { { type: "placeholder", title: lgls("dashboard.title"), - description: lgls("dashboard.description") + description: lgls("dashboard.description"), }, { type: "placeholder", - id: "dashboardOrgSelect" + id: "dashboardOrgSelect", }, { - type: "divider" + type: "divider", }, { @@ -43,21 +43,21 @@ export function dashboardModalObject({ lgls }) { styles: { width: "30px", height: "30px", - borderRadius: "5px" + borderRadius: "5px", }, id: "dashboardOrgAvatar", - classList: ["hidden"] + classList: ["hidden"], }, { type: "placeholder", title: "...", description: "...", id: "dashboardOrgInfo", - classList: ["hidden"] + classList: ["hidden"], }, { - type: "divider" + type: "divider", }, { @@ -65,31 +65,31 @@ export function dashboardModalObject({ lgls }) { title: lgls("dashboard.members.title"), id: "dashboardOrgMembers", description: "--", - classList: ["placeholder-bigdata"] + classList: ["placeholder-bigdata"], }, { type: "placeholder", title: lgls("dashboard.inviteCode.title"), id: "dashboardOrgInviteCode", description: "--", - classList: ["placeholder-bigdata"] + classList: ["placeholder-bigdata"], }, { type: "placeholder", description: "...", classList: ["hidden", "placeholder-label"], - id: "dashboardOrgInviteCodeLastUpdated" + id: "dashboardOrgInviteCodeLastUpdated", }, { type: "placeholder", title: lgls("dashboard.createdAt.title"), id: "dashboardOrgCreatedAt", description: "--", - classList: ["placeholder-bigdata"] + classList: ["placeholder-bigdata"], }, { - type: "divider" + type: "divider", }, // edit zone @@ -97,28 +97,28 @@ export function dashboardModalObject({ lgls }) { type: "placeholder", id: "dashboardOrgEditZoneTitle", title: lgls("dashboard.edit.title"), - description: lgls("dashboard.edit.description") + description: lgls("dashboard.edit.description"), }, { type: "container", id: "dashboardOrgEditZoneButtons", - disabled: true + disabled: true, }, { type: "button", title: lgls("dashboard.edit.resetInviteCode.title"), id: "dashboardOrgEditResetInvite", - container: "#dashboardOrgEditZoneButtons" + container: "#dashboardOrgEditZoneButtons", }, { type: "button", title: "Upload new avatar", id: "dashboardOrgEditUploadAvatar", - container: "#dashboardOrgEditZoneButtons" + container: "#dashboardOrgEditZoneButtons", }, { - type: "divider" + type: "divider", }, // github links zone @@ -126,154 +126,150 @@ export function dashboardModalObject({ lgls }) { type: "placeholder", id: "dashboardOrgGitHubLinksTitle", title: lgls("dashboard.githubRepos.title", { current: 0, max: 0 }), - description: lgls("dashboard.githubRepos.loadRequest") + description: lgls("dashboard.githubRepos.loadRequest"), }, { type: "placeholder", - id: "dashboardOrgGitHubLinks" + id: "dashboardOrgGitHubLinks", }, { type: "button", title: "Save", id: "dashboardOrgGitHubLinksSave", - classList: ["hidden"] + classList: ["hidden"], }, // danger zone { - type: "divider" + type: "divider", }, - + { type: "switch", id: "dashboardOrgDangerZoneSwitch", title: lgls("dashboard.dangerZone.switch.title"), - description: lgls("dashboard.dangerZone.switch.description") + description: lgls("dashboard.dangerZone.switch.description"), }, { type: "placeholder", id: "dashboardOrgDangerZoneTitle", title: lgls("dashboard.dangerZone.title"), classList: ["text-danger"], - disabled: true + disabled: true, }, { type: "container", id: "dashboardOrgButtons", - disabled: true + disabled: true, }, { type: "button", class: "danger", title: lgls("dashboard.dangerZone.deleteBtn"), id: "dashboardOrgRemoveBtn", - container: "#dashboardOrgButtons" - } - ] - } - ] - } + container: "#dashboardOrgButtons", + }, + ], + }, + ], + }; } export async function dashboardModalHandle({ userOrgs, element, orgModal }) { - const gls = await GLS.initLocal() + const gls = await GLS.initLocal(); function lgls(key, replacements = {}) { - return gls.get(`modals.organizations.dashboard.${key}`, replacements) + return gls.get(`modals.organizations.dashboard.${key}`, replacements); } - const dashboardOrgSelect = new Options("dashboardOrgSelect") - dashboardOrgSelect.clear() - dashboardOrgSelect.add("none", "None").default() + const dashboardOrgSelect = new Options("dashboardOrgSelect"); + dashboardOrgSelect.clear(); + dashboardOrgSelect.add("none", "None").default(); - Object.keys(userOrgs).forEach(index => { - const org = userOrgs[index] - const orgItemData = {} + Object.keys(userOrgs).forEach((index) => { + const org = userOrgs[index]; + const orgItemData = {}; if (org.verified == 1) { - orgItemData["badge"] = { color: "rgb(47 119 255)", icon: "check" } + orgItemData["badge"] = { color: "rgb(47 119 255)", icon: "check" }; } if (org.description) { - orgItemData["secondary"] = truncateString(org.description, 50) + orgItemData["secondary"] = truncateString(org.description, 50); } - const item = dashboardOrgSelect.add(org.id, org.name, orgItemData) - }) + const item = dashboardOrgSelect.add(org.id, org.name, orgItemData); + }); - dashboardOrgSelect.appendTo(element.querySelector("#dashboardOrgSelect")) + dashboardOrgSelect.appendTo(element.querySelector("#dashboardOrgSelect")); - const alreadyLoadedDashboardOrgs = new Map() + const alreadyLoadedDashboardOrgs = new Map(); - const removeBtn = element.querySelector("#dashboardOrgRemoveBtn") - const buttonsContainer = element.querySelector("#dashboardOrgButtons") - const membersCount = element.querySelector("#dashboardOrgMembers .modal-category__item-desc") - const inviteCode = element.querySelector("#dashboardOrgInviteCode .modal-category__item-desc") - const inviteCodeLastUpdateWrapper = element.querySelector("#dashboardOrgInviteCodeLastUpdated") - const inviteCodeLastUpdate = inviteCodeLastUpdateWrapper.querySelector(".modal-category__item-desc") - const createdAt = element.querySelector("#dashboardOrgCreatedAt .modal-category__item-desc") + const removeBtn = element.querySelector("#dashboardOrgRemoveBtn"); + const buttonsContainer = element.querySelector("#dashboardOrgButtons"); + const membersCount = element.querySelector("#dashboardOrgMembers .modal-category__item-desc"); + const inviteCode = element.querySelector("#dashboardOrgInviteCode .modal-category__item-desc"); + const inviteCodeLastUpdateWrapper = element.querySelector("#dashboardOrgInviteCodeLastUpdated"); + const inviteCodeLastUpdate = inviteCodeLastUpdateWrapper.querySelector( + ".modal-category__item-desc", + ); + const createdAt = element.querySelector("#dashboardOrgCreatedAt .modal-category__item-desc"); - const infoWrapper = element.querySelector("#dashboardOrgInfo") - const infoName = infoWrapper.querySelector("#dashboardOrgInfo .modal-category__item-title") - const infoDesc = infoWrapper.querySelector("#dashboardOrgInfo .modal-category__item-desc") + const infoWrapper = element.querySelector("#dashboardOrgInfo"); + const infoName = infoWrapper.querySelector("#dashboardOrgInfo .modal-category__item-title"); + const infoDesc = infoWrapper.querySelector("#dashboardOrgInfo .modal-category__item-desc"); - const avatar = element.querySelector("#dashboardOrgAvatar") + const avatar = element.querySelector("#dashboardOrgAvatar"); - const githubLinksWrapper = element.querySelector("#dashboardOrgGitHubLinks") - const githubLinksListAddBtn = githubLinksWrapper.querySelector("#modal-list__add-btn") - const githubLinksSaveBtn = element.querySelector("#dashboardOrgGitHubLinksSave") - const githubLinksTitleWrapper = element.querySelector("#dashboardOrgGitHubLinksTitle") - const githubLinksTitle = githubLinksTitleWrapper.querySelector(".modal-category__item-title") - const githubLinksDesc = githubLinksTitleWrapper.querySelector(".modal-category__item-desc") + const githubLinksWrapper = element.querySelector("#dashboardOrgGitHubLinks"); + const githubLinksListAddBtn = githubLinksWrapper.querySelector("#modal-list__add-btn"); + const githubLinksSaveBtn = element.querySelector("#dashboardOrgGitHubLinksSave"); + const githubLinksTitleWrapper = element.querySelector("#dashboardOrgGitHubLinksTitle"); + const githubLinksTitle = githubLinksTitleWrapper.querySelector(".modal-category__item-title"); + const githubLinksDesc = githubLinksTitleWrapper.querySelector(".modal-category__item-desc"); - const editButtons = element.querySelector("#dashboardOrgEditZoneButtons") - const editResetInvite = element.querySelector("#dashboardOrgEditResetInvite") - const editUploadAvatar = element.querySelector("#dashboardOrgEditUploadAvatar") + const editButtons = element.querySelector("#dashboardOrgEditZoneButtons"); + const editResetInvite = element.querySelector("#dashboardOrgEditResetInvite"); + const editUploadAvatar = element.querySelector("#dashboardOrgEditUploadAvatar"); - const dangerZoneSwitch = element.querySelector("#dashboardOrgDangerZoneSwitch") - const dangerZoneTitle = element.querySelector("#dashboardOrgDangerZoneTitle") + const dangerZoneSwitch = element.querySelector("#dashboardOrgDangerZoneSwitch"); + const dangerZoneTitle = element.querySelector("#dashboardOrgDangerZoneTitle"); - let isOrganizationsSelected = false + let isOrganizationsSelected = false; function toggleDangerZone(value) { - if(typeof value == "boolean") { - if(value) { - buttonsContainer.classList.remove("disabled") - dangerZoneTitle.classList.remove("disabled") - } - else { - buttonsContainer.classList.add("disabled") - dangerZoneTitle.classList.add("disabled") + if (typeof value == "boolean") { + if (value) { + buttonsContainer.classList.remove("disabled"); + dangerZoneTitle.classList.remove("disabled"); + } else { + buttonsContainer.classList.add("disabled"); + dangerZoneTitle.classList.add("disabled"); } } } dangerZoneSwitch.addEventListener("change", (e) => { - if(isOrganizationsSelected && e.target.checked) { - toggleDangerZone(true) - } - else { - toggleDangerZone(false) + if (isOrganizationsSelected && e.target.checked) { + toggleDangerZone(true); + } else { + toggleDangerZone(false); } - }) + }); dashboardOrgSelect.on("click", async (e) => { async function render(data) { - const isOwner = data.is_owner - const maxGithubRepos = 8 - const inviteCodeResetAt = data.invite_reset_at - const githubRepos = data.github_repos - - githubLinksTitle.textContent = lgls("githubRepos.title", - { - current: githubRepos.length, - max: maxGithubRepos - } - ) - githubLinksDesc.textContent = lgls("githubRepos.description", - { - max: maxGithubRepos - } - ) + const isOwner = data.is_owner; + const maxGithubRepos = 8; + const inviteCodeResetAt = data.invite_reset_at; + const githubRepos = data.github_repos; + + githubLinksTitle.textContent = lgls("githubRepos.title", { + current: githubRepos.length, + max: maxGithubRepos, + }); + githubLinksDesc.textContent = lgls("githubRepos.description", { + max: maxGithubRepos, + }); const githubReposList = renderList({ maxElements: maxGithubRepos, @@ -284,188 +280,176 @@ export async function dashboardModalHandle({ userOrgs, element, orgModal }) { values: githubRepos, valuesReadOnly: !isOwner, onAdd: (count) => { - githubLinksTitle.textContent = `Github projects (${count}/${maxGithubRepos})` - } - }) - githubReposList.classList.add("list-grid") + githubLinksTitle.textContent = `Github projects (${count}/${maxGithubRepos})`; + }, + }); + githubReposList.classList.add("list-grid"); - githubLinksWrapper.innerHTML = `` - githubLinksWrapper.appendChild(githubReposList) + githubLinksWrapper.innerHTML = ""; + githubLinksWrapper.appendChild(githubReposList); - infoWrapper.classList.remove("hidden") - infoName.textContent = data.name - infoDesc.textContent = data.description + infoWrapper.classList.remove("hidden"); + infoName.textContent = data.name; + infoDesc.textContent = data.description; - const avatarUrl = await GetOrgAvatar.get(data.avatarID) - - if(avatarUrl) { - avatar.classList.remove("hidden") - avatar.src = avatarUrl - } - else { - avatar.classList.add("hidden") - } + const avatarUrl = await GetOrgAvatar.get(data.avatarID); - if(inviteCodeResetAt > 0) { - inviteCodeLastUpdateWrapper.classList.remove("hidden") - inviteCodeLastUpdate.textContent = gls.get("modals.organizations.dashboard.inviteCode.lastResetAt", { date: formatUnix(inviteCodeResetAt, "{dd}.{mm}.{yyyy}, {hh}:{ii}") }) - } - else { - inviteCodeLastUpdateWrapper.classList.add("hidden") + if (avatarUrl) { + avatar.classList.remove("hidden"); + avatar.src = avatarUrl; + } else { + avatar.classList.add("hidden"); } - membersCount.textContent = data.members_count - inviteCode.textContent = encodeInviteCode(data.invite_code) - createdAt.textContent = formatUnix(data.created_at, "{dd}.{mm}.{yyyy}, {hh}:{ii}") - - inviteCode.onclick = () => { - inviteCode.textContent = data.invite_code == false ? "--" : data.invite_code + if (inviteCodeResetAt > 0) { + inviteCodeLastUpdateWrapper.classList.remove("hidden"); + inviteCodeLastUpdate.textContent = gls.get( + "modals.organizations.dashboard.inviteCode.lastResetAt", + { date: formatUnix(inviteCodeResetAt, "{dd}.{mm}.{yyyy}, {hh}:{ii}") }, + ); + } else { + inviteCodeLastUpdateWrapper.classList.add("hidden"); } - if(!isOwner) { - dangerZoneTitle.classList.add("hidden") - dangerZoneSwitch.closest(".modal-category__item").classList.add("hidden") - buttonsContainer.classList.add("hidden") + membersCount.textContent = data.members_count; + inviteCode.textContent = encodeInviteCode(data.invite_code); + createdAt.textContent = formatUnix(data.created_at, "{dd}.{mm}.{yyyy}, {hh}:{ii}"); - editButtons.classList.add("disabled") + inviteCode.onclick = () => { + inviteCode.textContent = data.invite_code == false ? "--" : data.invite_code; + }; - githubLinksSaveBtn.classList.add("hidden") - } - else { - githubLinksSaveBtn.classList.remove("hidden") + if (isOwner) { + githubLinksSaveBtn.classList.remove("hidden"); - dangerZoneTitle.classList.remove("hidden") - dangerZoneSwitch.closest(".modal-category__item").classList.remove("hidden") - buttonsContainer.classList.remove("hidden") + dangerZoneTitle.classList.remove("hidden"); + dangerZoneSwitch.closest(".modal-category__item").classList.remove("hidden"); + buttonsContainer.classList.remove("hidden"); - editButtons.classList.remove("disabled") + editButtons.classList.remove("disabled"); editUploadAvatar.onclick = async () => { - const res = await window.electron.uploadOrgAvatar(data.id) - - if(res.success) { - sendEvent("org-update", {}) - } - else { - createNotify( - { - type: "danger", - icon: "cancel", - title: "Avatar updating error", - content: String(res.msg) - } - ) + const res = await window.electron.uploadOrgAvatar(data.id); + + if (res.success) { + sendEvent("org-update", {}); + } else { + createNotify({ + type: "danger", + icon: "cancel", + title: "Avatar updating error", + content: String(res.msg), + }); } - } + }; + } else { + dangerZoneTitle.classList.add("hidden"); + dangerZoneSwitch.closest(".modal-category__item").classList.add("hidden"); + buttonsContainer.classList.add("hidden"); + + editButtons.classList.add("disabled"); + + githubLinksSaveBtn.classList.add("hidden"); } // remove btn handler removeBtn.onclick = async () => { - orgModal.disableCurrent() + orgModal.disableCurrent(); - const removeOrgRes = await window.electron.removeOrg(data.id) + const removeOrgRes = await window.electron.removeOrg(data.id); if (removeOrgRes.success) { - sendEvent("org-removed", {}) - } - else { - createNotify( - { - type: "danger", - icon: "close", - title: "Organization delete error", - content: String(removeOrgRes.msg) - } - ) + sendEvent("org-removed", {}); + } else { + createNotify({ + type: "danger", + icon: "close", + title: "Organization delete error", + content: String(removeOrgRes.msg), + }); } - orgModal.unDisableCurrent() - } - // + orgModal.unDisableCurrent(); + }; + // // resend code btn handler editResetInvite.onclick = async () => { - orgModal.disableCurrent() + orgModal.disableCurrent(); - const resetOrgInviteCodeRes = await window.electron.resetOrgInviteCode(data.id) + const resetOrgInviteCodeRes = await window.electron.resetOrgInviteCode(data.id); if (resetOrgInviteCodeRes.success) { - const code = resetOrgInviteCodeRes.msg.invite_code - inviteCode.textContent = code + const code = resetOrgInviteCodeRes.msg.invite_code; + inviteCode.textContent = code; - editButtons.classList.add("disabled") + editButtons.classList.add("disabled"); setTimeout(() => { - editButtons.classList.remove("disabled") - }, 300000) - } - else { - createNotify( - { - type: "danger", - icon: "close", - title: "Organization invite code reset error", - content: String(resetOrgInviteCodeRes.msg) - } - ) + editButtons.classList.remove("disabled"); + }, 300_000); + } else { + createNotify({ + type: "danger", + icon: "close", + title: "Organization invite code reset error", + content: String(resetOrgInviteCodeRes.msg), + }); } - orgModal.unDisableCurrent() - } + orgModal.unDisableCurrent(); + }; // github linkk githubLinksSaveBtn.onclick = async () => { - const inputs = githubLinksWrapper.querySelectorAll("input") - let repos = [] + const inputs = githubLinksWrapper.querySelectorAll("input"); + let repos = []; - inputs.forEach(input => { - repos.push(input.value.split("https://github.com/")[1]) - }) + inputs.forEach((input) => { + repos.push(input.value.split("https://github.com/")[1]); + }); - repos = repos.filter(item => item.length > 0) + repos = repos.filter((item) => item.length > 0); - const res = await window.electron.setOrgGithubRepos(data.id, repos) - - if(res.success) { - sendEvent("org-update", {}) + const res = await window.electron.setOrgGithubRepos(data.id, repos); + + if (res.success) { + sendEvent("org-update", {}); createNotify({ type: "success", icon: "check", title: "Github repo's setted", - content: `Github repo's for "${data.name}" successfully setted` - }) - } - else { + content: `Github repo's for "${data.name}" successfully setted`, + }); + } else { createNotify({ type: "danger", icon: "cancel", title: "Github repo's error", - content: res.msg - }) + content: res.msg, + }); } - } + }; } - isOrganizationsSelected = true + isOrganizationsSelected = true; - if(e.id == "none") { - toggleDangerZone(false) - isOrganizationsSelected = false - } - else if(e.id != "none" && dangerZoneSwitch.checked) { - toggleDangerZone(true) + if (e.id == "none") { + toggleDangerZone(false); + isOrganizationsSelected = false; + } else if (e.id != "none" && dangerZoneSwitch.checked) { + toggleDangerZone(true); } - if (!alreadyLoadedDashboardOrgs.has(e.id)) { - const orgRes = await window.electron.getOrgDataFromAPI(e.id) + if (alreadyLoadedDashboardOrgs.has(e.id)) { + await render(alreadyLoadedDashboardOrgs.get(e.id)); + } else { + const orgRes = await window.electron.getOrgDataFromAPI(e.id); if (orgRes.success) { - const data = orgRes.msg - await render(data) - alreadyLoadedDashboardOrgs.set(e.id, data) + const data = orgRes.msg; + await render(data); + alreadyLoadedDashboardOrgs.set(e.id, data); } } - else { - await render(alreadyLoadedDashboardOrgs.get(e.id)) - } - }) -} \ No newline at end of file + }); +} diff --git a/assets/js/userHandlers/organizationModal/join.js b/assets/js/userHandlers/organizationModal/join.js index 5dd6319..bba518a 100644 --- a/assets/js/userHandlers/organizationModal/join.js +++ b/assets/js/userHandlers/organizationModal/join.js @@ -1,6 +1,6 @@ -import { sendEvent } from "../../bus.js" -import { createNotify, truncateString, Options, formatUnix } from "../../lib.js" -import { Modal } from "../../modalsHandler/engine.js" +import { sendEvent } from "../../bus.js"; +import { createNotify, formatUnix, Options, truncateString } from "../../lib.js"; +import { Modal } from "../../modalsHandler/engine.js"; export function joinModalObject({ lgls }) { return { @@ -15,54 +15,49 @@ export function joinModalObject({ lgls }) { { type: "placeholder", title: lgls("join.title"), - description: lgls("join.description") + description: lgls("join.description"), }, { type: "input", placeholder: lgls("join.inputs.inviteCode"), - id: "joinOrgInviteCode" + id: "joinOrgInviteCode", }, { type: "button", title: lgls("join.buttons.join"), - id: "joinOrgBtn" - } - ] - } - ] - } + id: "joinOrgBtn", + }, + ], + }, + ], + }; } export function joinModalHandle({ element, lgls }) { - const joinOrgInviteCode = element.querySelector("#joinOrgInviteCode") - const joinOrgBtn = element.querySelector("#joinOrgBtn") + const joinOrgInviteCode = element.querySelector("#joinOrgInviteCode"); + const joinOrgBtn = element.querySelector("#joinOrgBtn"); joinOrgBtn.addEventListener("click", async () => { - const value = joinOrgInviteCode.value + const value = joinOrgInviteCode.value; - const joinOrgRes = await window.electron.joinOrg(value) + const joinOrgRes = await window.electron.joinOrg(value); - if(joinOrgRes.success) { - createNotify( - { - type: "success", - icon: "check", - title: lgls("join.successNotification.title", { name: joinOrgRes.msg.name }), - content: lgls("join.successNotification.description") - } - ) + if (joinOrgRes.success) { + createNotify({ + type: "success", + icon: "check", + title: lgls("join.successNotification.title", { name: joinOrgRes.msg.name }), + content: lgls("join.successNotification.description"), + }); - sendEvent("org-joined", { name: joinOrgRes.msg.name }) - } - else { - createNotify( - { - type: "danger", - icon: "close", - title: lgls("join.errorNotification.title"), - content: joinOrgRes.msg - } - ) + sendEvent("org-joined", { name: joinOrgRes.msg.name }); + } else { + createNotify({ + type: "danger", + icon: "close", + title: lgls("join.errorNotification.title"), + content: joinOrgRes.msg, + }); } - }) -} \ No newline at end of file + }); +} diff --git a/assets/js/userHandlers/organizationModal/orgPage/about.js b/assets/js/userHandlers/organizationModal/orgPage/about.js index 2f5fb96..a5335ac 100644 --- a/assets/js/userHandlers/organizationModal/orgPage/about.js +++ b/assets/js/userHandlers/organizationModal/orgPage/about.js @@ -1,49 +1,47 @@ -import { formatUnix } from "../../../lib.js" +import { formatUnix } from "../../../lib.js"; export async function renderAboutPage(lgls, data = {}) { - const name = data.name - const avatar = data.avatar - const desc = data.description - const isVerified = data.verified - const ownerID = data.ownerID - - const ownerRes = await window.electron.getUser(ownerID) - const additionalInfoBlocks = [] - - if(ownerRes.success) { - additionalInfoBlocks.push( - { - title: lgls("about.page.info.owner"), - description: ownerRes.msg.name - } - ) - - console.log(additionalInfoBlocks) + const name = data.name; + const avatar = data.avatar; + const desc = data.description; + const isVerified = data.verified; + const ownerId = data.ownerID; + + const ownerRes = await window.electron.getUser(ownerId); + const additionalInfoBlocks = []; + + if (ownerRes.success) { + additionalInfoBlocks.push({ + title: lgls("about.page.info.owner"), + description: ownerRes.msg.name, + }); + + console.log(additionalInfoBlocks); } - let avatarData = {} + let avatarData = {}; - if(avatar) { + if (avatar) { avatarData = { type: "image", src: avatar, styles: { width: "50px", height: "50px", - borderRadius: "10px" - } - } + borderRadius: "10px", + }, + }; } const about = [ { type: "placeholder", - title: lgls("about.page.title", { name: name }), - description: lgls("about.page.description") + title: lgls("about.page.title", { name }), + description: lgls("about.page.description"), }, { - type: "divider" + type: "divider", }, avatarData, @@ -52,11 +50,11 @@ export async function renderAboutPage(lgls, data = {}) { type: "placeholder", title: name, titleBadge: isVerified ? "verified" : "", - description: desc + description: desc, }, { - type: "divider" + type: "divider", }, { @@ -66,60 +64,50 @@ export async function renderAboutPage(lgls, data = {}) { ...additionalInfoBlocks, { title: lgls("about.page.info.members"), - description: data.members_count + description: data.members_count, }, { title: lgls("about.page.info.createdAt"), - description: formatUnix(data.created_at, "{dd}.{mm}.{yyyy}, {hh}:{ii}") + description: formatUnix(data.created_at, "{dd}.{mm}.{yyyy}, {hh}:{ii}"), }, { title: lgls("about.page.info.repos"), - description: data.github_repos.length + description: data.github_repos.length, }, - ] - } - ] - - if(data.website) { - about.push( - { - type: "divider" - } - ) - about.push( - { - type: "placeholder", - title: lgls("about.page.website.title"), - link: data.website - } - ) + ], + }, + ]; + + if (data.website) { + about.push({ + type: "divider", + }); + about.push({ + type: "placeholder", + title: lgls("about.page.website.title"), + link: data.website, + }); } - console.log(data) - - if(data.github_repos && data.github_repos.length > 0) { - const repos = data.github_repos - - about.push( - { - type: "divider" - } - ) - about.push( - { - type: "placeholder", - title: lgls("about.page.githubRepos.title") - } - ) - about.push( - { - type: "githubRepos", - id: "orgPageGithubRepos", - urls: repos, - forkable: true - } - ) + console.log(data); + + if (data.github_repos && data.github_repos.length > 0) { + const repos = data.github_repos; + + about.push({ + type: "divider", + }); + about.push({ + type: "placeholder", + title: lgls("about.page.githubRepos.title"), + }); + about.push({ + type: "githubRepos", + id: "orgPageGithubRepos", + urls: repos, + forkable: true, + }); } - return about -} \ No newline at end of file + return about; +} diff --git a/assets/js/userHandlers/organizationModal/orgPage/main.js b/assets/js/userHandlers/organizationModal/orgPage/main.js index a96c41b..cfd8693 100644 --- a/assets/js/userHandlers/organizationModal/orgPage/main.js +++ b/assets/js/userHandlers/organizationModal/orgPage/main.js @@ -3,46 +3,44 @@ import { Modal } from "../../../modalsHandler/engine.js"; import { renderAboutPage } from "./about.js"; export async function createOrgPage(data = {}) { - Modal.destroy("orgPage") + Modal.destroy("orgPage"); - const gls = GLS.initLocal() + const gls = GLS.initLocal(); function lgls(key, replacements = {}) { - return gls.get(`modals.organizations.orgPage.${key}`, replacements) + return gls.get(`modals.organizations.orgPage.${key}`, replacements); } - const id = data.id - const name = data.name - const avatar = await GetOrgAvatar.get(data.avatarID, "large") - const desc = data.description - - const modal = Modal.create( - { - id: "orgPage", - name: name, - modalClassList: ["window"], - title: name, - titleAvatar: avatar, - - pages: [ - { - name: lgls("about.title"), - icon: "info", - - content: [ - { - type: "row-clear", - gap: 10, - items: await renderAboutPage(lgls, { - ...data, - avatar: avatar - }) - } - ] - }, - ] - } - ) - - return modal -} \ No newline at end of file + const id = data.id; + const name = data.name; + const avatar = await GetOrgAvatar.get(data.avatarID, "large"); + const desc = data.description; + + const modal = Modal.create({ + id: "orgPage", + name, + modalClassList: ["window"], + title: name, + titleAvatar: avatar, + + pages: [ + { + name: lgls("about.title"), + icon: "info", + + content: [ + { + type: "row-clear", + gap: 10, + items: await renderAboutPage(lgls, { + ...data, + avatar, + }), + }, + ], + }, + ], + }); + + return modal; +} diff --git a/assets/js/userHandlers/organizationModal/search.js b/assets/js/userHandlers/organizationModal/search.js index 59b63c3..740b26b 100644 --- a/assets/js/userHandlers/organizationModal/search.js +++ b/assets/js/userHandlers/organizationModal/search.js @@ -1,11 +1,11 @@ -import { sendEvent } from "../../bus.js" -import { createNotify, truncateString, Options, formatUnix } from "../../lib.js" -import { renderOrganization } from "../../modalsHandler/components/organization.js" -import { renderPlaceholder } from "../../modalsHandler/components/placeholder.js" -import { Modal } from "../../modalsHandler/engine.js" -import { renderSidebarItem } from "../../modalsHandler/handlers/sidebarHandler.js" -import { getModalOrgStructure } from "../orgModal.js" -import { createOrgPage } from "./orgPage/main.js" +import { sendEvent } from "../../bus.js"; +import { createNotify, formatUnix, Options, truncateString } from "../../lib.js"; +import { renderOrganization } from "../../modalsHandler/components/organization.js"; +import { renderPlaceholder } from "../../modalsHandler/components/placeholder.js"; +import { Modal } from "../../modalsHandler/engine.js"; +import { renderSidebarItem } from "../../modalsHandler/handlers/sidebarHandler.js"; +import { getModalOrgStructure } from "../orgModal.js"; +import { createOrgPage } from "./orgPage/main.js"; export function searchModalObject({ lgls }) { return { @@ -20,61 +20,60 @@ export function searchModalObject({ lgls }) { { type: "placeholder", title: lgls("search.title"), - description: lgls("search.description") + description: lgls("search.description"), }, { type: "input", placeholder: lgls("search.inputs.search"), - id: "searchInput" + id: "searchInput", }, { type: "placeholder", - id: "searchResults" - } - ] - } - ] - } + id: "searchResults", + }, + ], + }, + ], + }; } export function searchModalHandle({ modal, element, lgls }) { - const searchInput = element.querySelector("#searchInput") - const searchResults = element.querySelector("#searchResults") - + const searchInput = element.querySelector("#searchInput"); + const searchResults = element.querySelector("#searchResults"); + searchInput.addEventListener("change", async (e) => { - searchResults.innerHTML = "" + searchResults.innerHTML = ""; - const value = e.target.value + const value = e.target.value; - const res = await window.electron.searchOrg(value) + const res = await window.electron.searchOrg(value); - console.log(res) + console.log(res); - if(res.success) { - const results = res.msg + if (res.success) { + const results = res.msg; - if(results.length > 0) { - results.forEach(async org => { - const struct = await getModalOrgStructure(org) - const render = renderOrganization(struct) + if (results.length > 0) { + results.forEach(async (org) => { + const struct = await getModalOrgStructure(org); + const render = renderOrganization(struct); - searchResults.appendChild(render) + searchResults.appendChild(render); render.onclick = async () => { - modal.close() + modal.close(); - const orgPageModal = await createOrgPage(org) - orgPageModal.open() - } - }) - } - else { + const orgPageModal = await createOrgPage(org); + orgPageModal.open(); + }; + }); + } else { const noResulstPlaceholder = renderPlaceholder({ - description: lgls("search.noResults.text", { name: value }) - }) + description: lgls("search.noResults.text", { name: value }), + }); - searchResults.appendChild(noResulstPlaceholder) + searchResults.appendChild(noResulstPlaceholder); } } - }) -} \ No newline at end of file + }); +} diff --git a/assets/js/userHandlers/spawn.js b/assets/js/userHandlers/spawn.js index 9ac9588..0762fc4 100644 --- a/assets/js/userHandlers/spawn.js +++ b/assets/js/userHandlers/spawn.js @@ -1,25 +1,24 @@ -import { GLS } from "../lib.js" +import { GLS } from "../lib.js"; export function spawnSideBarOrganizationsButton({ userOrgs }) { - const gls = GLS.initLocal() + const gls = GLS.initLocal(); if (userOrgs.length > 0) { - if(!document.querySelector(".sidebar-item#yourOrganizations")) { - const orgSideBarBtn = document.createElement("div") - orgSideBarBtn.className = "sidebar-item" - orgSideBarBtn.id = "yourOrganizations" - orgSideBarBtn.setAttribute("tooltip", gls.get("tooltips.organizations")) - orgSideBarBtn.setAttribute("nondefault", null) + if (document.querySelector(".sidebar-item#yourOrganizations")) { + const el = document.querySelector(".sidebar-item#yourOrganizations"); + el.querySelector(".badge").textContent = userOrgs.length; + } else { + const orgSideBarBtn = document.createElement("div"); + orgSideBarBtn.className = "sidebar-item"; + orgSideBarBtn.id = "yourOrganizations"; + orgSideBarBtn.setAttribute("tooltip", gls.get("tooltips.organizations")); + orgSideBarBtn.setAttribute("nondefault", null); orgSideBarBtn.innerHTML = ` ${userOrgs.length} group - ` - document.querySelector(".sidebar").appendChild(orgSideBarBtn) - } - else { - const el = document.querySelector(".sidebar-item#yourOrganizations") - el.querySelector(".badge").textContent = userOrgs.length + `; + document.querySelector(".sidebar").appendChild(orgSideBarBtn); } } -} \ No newline at end of file +} diff --git a/assets/js/userHandlers/userPC.js b/assets/js/userHandlers/userPC.js index f96a744..b975d6a 100644 --- a/assets/js/userHandlers/userPC.js +++ b/assets/js/userHandlers/userPC.js @@ -1,10 +1,14 @@ export async function setUserPcInfo() { const info = await window.electron.getUserPcInfo(); - document.querySelectorAll("#username").forEach(e => { e.textContent = info.name; }); + document.querySelectorAll("#username").forEach((e) => { + e.textContent = info.name; + }); function updateTime() { const now = new Date().format("F j, H:i"); - document.querySelectorAll("#current_hours").forEach(el => { el.textContent = now; }); + document.querySelectorAll("#current_hours").forEach((el) => { + el.textContent = now; + }); } updateTime(); @@ -15,4 +19,4 @@ export async function setUserPcInfo() { updateTime(); setInterval(updateTime, 60 * 1000); }, msToNextMinute); -} \ No newline at end of file +} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..114298c --- /dev/null +++ b/biome.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.5.6/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "includes": [ + "**", + "!!ace", + "!!app/dist", + "!!app/dist-esm", + "!!app/main/runtime/python", + "!!assets/css/material-icons", + "!!assets/fonts", + "!!assets/js/external", + "!!assets/media", + "!!assets/plugins", + "!!codemirror/dist", + "!!codemirror/package-lock.json", + "!!package-lock.json" + ], + "ignoreUnknown": true + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 4, + "lineEnding": "lf", + "lineWidth": 100, + "attributePosition": "auto", + "bracketSpacing": true, + "expand": "auto", + "useEditorconfig": true + }, + "linter": { + "enabled": true, + "rules": { + "preset": "recommended", + "a11y": "warn", + "complexity": "warn", + "correctness": "warn", + "performance": "warn", + "security": "warn", + "style": "warn", + "suspicious": "warn" + } + }, + "assist": { + "enabled": false + }, + "javascript": { + "formatter": { + "arrowParentheses": "always", + "bracketSameLine": false, + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "quoteStyle": "double", + "semicolons": "always", + "trailingCommas": "all" + } + }, + "json": { + "parser": { + "allowComments": false, + "allowTrailingCommas": false + } + }, + "css": { + "linter": { + "enabled": true + } + }, + "overrides": [ + { + "includes": ["languages/*.json", "codemirror/src/snippets/**/*.json"], + "linter": { + "enabled": false + } + } + ] +} diff --git a/codemirror/build.js b/codemirror/build.js index c53331b..4efbc97 100644 --- a/codemirror/build.js +++ b/codemirror/build.js @@ -1,11 +1,13 @@ const esbuild = require("esbuild"); -esbuild.build({ - entryPoints: ["src/index.js"], - bundle: true, - format: "iife", - globalName: "CodeMirrorBundle", - outfile: "dist/codemirror.js", - sourcemap: true, - minify: false -}).catch(() => process.exit(1)); \ No newline at end of file +esbuild + .build({ + entryPoints: ["src/index.js"], + bundle: true, + format: "iife", + globalName: "CodeMirrorBundle", + outfile: "dist/codemirror.js", + sourcemap: true, + minify: false, + }) + .catch(() => process.exit(1)); diff --git a/codemirror/package.json b/codemirror/package.json index 739d605..c15f1a1 100644 --- a/codemirror/package.json +++ b/codemirror/package.json @@ -1,52 +1,52 @@ { - "name": "codemirror", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "build": "node build.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@babel/parser": "^8.0.4", - "@babel/runtime": "^8.0.0", - "@babel/traverse": "^8.0.4", - "@codemirror/autocomplete": "^6.20.3", - "@codemirror/commands": "^6.10.4", - "@codemirror/lang-css": "^6.3.1", - "@codemirror/lang-go": "^6.0.1", - "@codemirror/lang-html": "^6.4.11", - "@codemirror/lang-java": "^6.0.2", - "@codemirror/lang-javascript": "^6.2.5", - "@codemirror/lang-json": "^6.0.2", - "@codemirror/lang-markdown": "^6.5.1", - "@codemirror/lang-php": "^6.0.2", - "@codemirror/lang-python": "^6.2.1", - "@codemirror/lang-rust": "^6.0.2", - "@codemirror/lang-sass": "^6.0.2", - "@codemirror/lang-vue": "^0.1.3", - "@codemirror/lang-wast": "^6.0.2", - "@codemirror/lang-xml": "^6.1.0", - "@codemirror/lang-yaml": "^6.1.3", - "@codemirror/language": "^6.12.4", - "@codemirror/lint": "^6.9.7", - "@codemirror/search": "^6.7.1", - "@codemirror/state": "^6.7.1", - "@codemirror/theme-one-dark": "^6.1.3", - "@codemirror/view": "^6.43.6", - "@replit/codemirror-indentation-markers": "^6.5.3", - "@uiw/codemirror-extensions-color": "^4.25.11", - "@uiw/codemirror-theme-github": "^4.25.11", - "@uiw/codemirror-themes": "^4.25.11", - "@uiw/codemirror-themes-all": "^4.25.11", - "codemirror": "^6.0.2", - "html-to-image": "^1.11.13", - "vscode-oniguruma": "^2.0.1", - "vscode-textmate": "^9.3.2" - }, - "devDependencies": { - "esbuild": "^0.28.1" - } + "name": "codemirror", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "build": "node build.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@babel/parser": "^8.0.4", + "@babel/runtime": "^8.0.0", + "@babel/traverse": "^8.0.4", + "@codemirror/autocomplete": "^6.20.3", + "@codemirror/commands": "^6.10.4", + "@codemirror/lang-css": "^6.3.1", + "@codemirror/lang-go": "^6.0.1", + "@codemirror/lang-html": "^6.4.11", + "@codemirror/lang-java": "^6.0.2", + "@codemirror/lang-javascript": "^6.2.5", + "@codemirror/lang-json": "^6.0.2", + "@codemirror/lang-markdown": "^6.5.1", + "@codemirror/lang-php": "^6.0.2", + "@codemirror/lang-python": "^6.2.1", + "@codemirror/lang-rust": "^6.0.2", + "@codemirror/lang-sass": "^6.0.2", + "@codemirror/lang-vue": "^0.1.3", + "@codemirror/lang-wast": "^6.0.2", + "@codemirror/lang-xml": "^6.1.0", + "@codemirror/lang-yaml": "^6.1.3", + "@codemirror/language": "^6.12.4", + "@codemirror/lint": "^6.9.7", + "@codemirror/search": "^6.7.1", + "@codemirror/state": "^6.7.1", + "@codemirror/theme-one-dark": "^6.1.3", + "@codemirror/view": "^6.43.6", + "@replit/codemirror-indentation-markers": "^6.5.3", + "@uiw/codemirror-extensions-color": "^4.25.11", + "@uiw/codemirror-theme-github": "^4.25.11", + "@uiw/codemirror-themes": "^4.25.11", + "@uiw/codemirror-themes-all": "^4.25.11", + "codemirror": "^6.0.2", + "html-to-image": "^1.11.13", + "vscode-oniguruma": "^2.0.1", + "vscode-textmate": "^9.3.2" + }, + "devDependencies": { + "esbuild": "^0.28.1" + } } diff --git a/codemirror/src/index.js b/codemirror/src/index.js index a228f5b..933ee01 100644 --- a/codemirror/src/index.js +++ b/codemirror/src/index.js @@ -1,81 +1,102 @@ -import { EditorState, Compartment, EditorSelection, Prec } from "@codemirror/state"; import { - EditorView, keymap, lineNumbers, highlightActiveLine, - highlightActiveLineGutter -} from "@codemirror/view"; -import { - closeBrackets, autocompletion, completionKeymap, completeFromList, - acceptCompletion, completionStatus + acceptCompletion, + autocompletion, + closeBrackets, + completeFromList, + completionKeymap, + completionStatus, } from "@codemirror/autocomplete"; -import { indentUnit, language } from "@codemirror/language"; -import { linter, lintGutter, forceLinting } from "@codemirror/lint"; - // commands import { - defaultKeymap, indentWithTab, history, historyKeymap, - selectAll, undo, redo, toggleComment + defaultKeymap, + history, + historyKeymap, + indentWithTab, + redo, + selectAll, + toggleComment, + undo, } from "@codemirror/commands"; +import { indentUnit, language } from "@codemirror/language"; +import { forceLinting, linter, lintGutter } from "@codemirror/lint"; +import { closeSearchPanel, findNext, findPrevious, openSearchPanel } from "@codemirror/search"; +import { Compartment, EditorSelection, EditorState, Prec } from "@codemirror/state"; import { - openSearchPanel, closeSearchPanel, findNext, - findPrevious -} from "@codemirror/search"; -// + EditorView, + highlightActiveLine, + highlightActiveLineGutter, + keymap, + lineNumbers, +} from "@codemirror/view"; +// // themes -import { vscodeDark, vscodeLight, atomone, githubDark } from '@uiw/codemirror-themes-all'; -// +import { atomone, githubDark, vscodeDark, vscodeLight } from "@uiw/codemirror-themes-all"; +// + +import { css } from "@codemirror/lang-css"; +import { go } from "@codemirror/lang-go"; +import { html } from "@codemirror/lang-html"; +import { java } from "@codemirror/lang-java"; // languages import { javascript } from "@codemirror/lang-javascript"; -import { html } from "@codemirror/lang-html"; -import { css } from "@codemirror/lang-css"; import { json } from "@codemirror/lang-json"; +import { markdown } from "@codemirror/lang-markdown"; import { php } from "@codemirror/lang-php"; -import { go } from "@codemirror/lang-go"; -import { yaml } from "@codemirror/lang-yaml"; import { python } from "@codemirror/lang-python"; -import { sass } from "@codemirror/lang-sass"; import { rust } from "@codemirror/lang-rust"; -import { xml } from "@codemirror/lang-xml"; -import { wast } from "@codemirror/lang-wast"; -import { java } from "@codemirror/lang-java"; +import { sass } from "@codemirror/lang-sass"; import { vue } from "@codemirror/lang-vue"; -import { markdown } from "@codemirror/lang-markdown"; -// +import { wast } from "@codemirror/lang-wast"; +import { xml } from "@codemirror/lang-xml"; +import { yaml } from "@codemirror/lang-yaml"; + +// +import { indentationMarkers } from "@replit/codemirror-indentation-markers"; +import { color } from "@uiw/codemirror-extensions-color"; // extensions import { colorComments, colorCommentsTheme } from "./plugins/colorComments"; import { fromVSCodeSnippets } from "./plugins/snippets"; -import { suggestionField, suggestionTheme, suggestPlugin, suggestUpdateListener, acceptSuggestion, dismissSuggestion, initSuggestListener } from "./plugins/suggest"; +import { + acceptSuggestion, + dismissSuggestion, + initSuggestListener, + suggestionField, + suggestionTheme, + suggestPlugin, + suggestUpdateListener, +} from "./plugins/suggest"; import { atomoneOverride, githubDarkOverride, vscodeDarkOverride } from "./themes/overrides"; -import { indentationMarkers } from "@replit/codemirror-indentation-markers"; -import { color } from "@uiw/codemirror-extensions-color"; -// +// + +import javascriptGlobalsJson from "./snippets/js/globals.json"; // javascript & typescript snippet support -import javascriptSnippetsJSON from "./snippets/js/snippets.json" -import javascriptGlobalsJSON from "./snippets/js/globals.json" +import javascriptSnippetsJson from "./snippets/js/snippets.json"; import { identifierJavaScriptCompletionSource } from "./snippets/js/source"; -// +// // json snippet support import { identifierJSONCompletionSource } from "./snippets/json/source"; -// +// // external -import { toPng, toBlob } from "html-to-image"; +import { toBlob, toPng } from "html-to-image"; + // +import { loadWASM, OnigScanner, OnigString } from "vscode-oniguruma"; // lang-reg import { Registry } from "vscode-textmate"; -import { loadWASM, OnigScanner, OnigString } from "vscode-oniguruma"; import { textMateHighlighter } from "./plugins/textmate/highlighter.js"; import { textMateBaseTheme } from "./plugins/textmate/theme.js"; -// +// -export const javascriptSnippets = fromVSCodeSnippets(javascriptSnippetsJSON); +export const javascriptSnippets = fromVSCodeSnippets(javascriptSnippetsJson); export const javascriptGlobals = completeFromList( - javascriptGlobalsJSON.map(label => ({ label, type: "variable" })) + javascriptGlobalsJson.map((label) => ({ label, type: "variable" })), ); function forLanguage(name, source) { @@ -88,21 +109,29 @@ function forLanguage(name, source) { const javascriptLang = javascript({ jsx: true, typescript: false }); const typescriptLang = javascript({ jsx: true, typescript: true }); -const htmlLang = html({ matchClosingTags: true, selfClosingTags: true, autoCloseTags: true }) -const jsonLang = json() +const htmlLang = html({ matchClosingTags: true, selfClosingTags: true, autoCloseTags: true }); +const jsonLang = json(); const javascriptHighlight = javascriptLang; const javascriptAutocomplete = [ - javascriptLang.language.data.of({ autocomplete: forLanguage("javascript", completeFromList(javascriptSnippets)) }), + javascriptLang.language.data.of({ + autocomplete: forLanguage("javascript", completeFromList(javascriptSnippets)), + }), javascriptLang.language.data.of({ autocomplete: forLanguage("javascript", javascriptGlobals) }), - javascriptLang.language.data.of({ autocomplete: forLanguage("javascript", identifierJavaScriptCompletionSource) }) + javascriptLang.language.data.of({ + autocomplete: forLanguage("javascript", identifierJavaScriptCompletionSource), + }), ]; const typescriptHighlight = typescriptLang; const typescriptAutocomplete = [ - typescriptLang.language.data.of({ autocomplete: forLanguage("typescript", completeFromList(javascriptSnippets)) }), + typescriptLang.language.data.of({ + autocomplete: forLanguage("typescript", completeFromList(javascriptSnippets)), + }), typescriptLang.language.data.of({ autocomplete: forLanguage("typescript", javascriptGlobals) }), - typescriptLang.language.data.of({ autocomplete: forLanguage("typescript", identifierJavaScriptCompletionSource) }) + typescriptLang.language.data.of({ + autocomplete: forLanguage("typescript", identifierJavaScriptCompletionSource), + }), ]; const htmlHighlight = [htmlLang, color]; @@ -110,7 +139,9 @@ const cssHighlight = [css(), color]; const jsonHighlight = jsonLang; const jsonAutocomplete = [ - jsonLang.language.data.of({ autocomplete: forLanguage("json", identifierJSONCompletionSource) }) + jsonLang.language.data.of({ + autocomplete: forLanguage("json", identifierJSONCompletionSource), + }), ]; export const Languages = { @@ -130,7 +161,7 @@ export const Languages = { java: java(), vue: vue(), - markdown: markdown() + markdown: markdown(), }; export const LanguageHighlighters = { @@ -149,41 +180,32 @@ export const LanguageHighlighters = { wast: Languages.wast, java: Languages.java, vue: Languages.vue, - markdown: Languages.markdown + markdown: Languages.markdown, }; export const LanguageAutocompletes = { javascript: javascriptAutocomplete, typescript: typescriptAutocomplete, - json: jsonAutocomplete + json: jsonAutocomplete, }; export const Themes = { - vscodeDark: [ - vscodeDark, - vscodeDarkOverride - ], - vscodeLight: vscodeLight, - atomone: [ - atomone, - atomoneOverride - ], - githubDark: [ - githubDark, - githubDarkOverride - ] + vscodeDark: [vscodeDark, vscodeDarkOverride], + vscodeLight, + atomone: [atomone, atomoneOverride], + githubDark: [githubDark, githubDarkOverride], }; export const ThemeParents = { default: "vscodeDark", light: "vscodeLight", - "contrast-dark": "atomone" -} + "contrast-dark": "atomone", +}; export const TabSizes = { - "2": EditorState.tabSize.of(2), - "4": EditorState.tabSize.of(4), - "8": EditorState.tabSize.of(8) + 2: EditorState.tabSize.of(2), + 4: EditorState.tabSize.of(4), + 8: EditorState.tabSize.of(8), }; const insertTab = (view) => { @@ -199,12 +221,10 @@ const insertTab = (view) => { changes: { from: state.selection.main.from, to: state.selection.main.to, - insert: "\t" + insert: "\t", }, - selection: EditorSelection.cursor( - state.selection.main.from + 1 - ) - }) + selection: EditorSelection.cursor(state.selection.main.from + 1), + }), ); return true; @@ -223,9 +243,9 @@ const grammarInstances = new Map(); async function getTextMateRegistry() { if (tmRegistry) return tmRegistry; - onigReady ??= fetch( - "../codemirror/node_modules/vscode-oniguruma/release/onig.wasm" - ).then(r => r.arrayBuffer()).then(loadWASM); + onigReady ??= fetch("../codemirror/node_modules/vscode-oniguruma/release/onig.wasm") + .then((r) => r.arrayBuffer()) + .then(loadWASM); await onigReady; @@ -236,10 +256,10 @@ async function getTextMateRegistry() { }, createOnigString(text) { return new OnigString(text); - } + }, }), - loadGrammar: async (scopeName) => rawGrammars.get(scopeName) ?? null + loadGrammar: async (scopeName) => rawGrammars.get(scopeName) ?? null, }); return tmRegistry; @@ -281,14 +301,14 @@ window.CodeMirror = { keymap.of([ { key: "Tab", - run: insertTab + run: insertTab, }, { key: "Escape", - run: escapeHandler + run: escapeHandler, }, ...defaultKeymap, - ...historyKeymap + ...historyKeymap, ]), languageCompartment.of([]), @@ -318,15 +338,15 @@ window.CodeMirror = { dark: "#ffffff1a", activeLight: "#00000070", activeDark: "#ffffff33", - } - }) - ] + }, + }), + ], }); } const view = new EditorView({ state: createState(options.value ?? ""), - parent + parent, }); initSuggestListener(); @@ -340,7 +360,7 @@ window.CodeMirror = { tabSizeCompartment, wordWrapCompartment, scrollCompartment, - readOnlyCompartment + readOnlyCompartment, }, setDiagnostics(value) { @@ -356,7 +376,7 @@ window.CodeMirror = { undo, redo, openSearchPanel, - toggleComment + toggleComment, }, recreateState(doc) { @@ -365,24 +385,24 @@ window.CodeMirror = { editorView: { theme: EditorView.theme, - lineWrapping: EditorView.lineWrapping + lineWrapping: EditorView.lineWrapping, }, editorState: { - readOnly: EditorState.readOnly + readOnly: EditorState.readOnly, }, tools: { - toPng: toPng, - toBlob: toBlob - } - } + toPng, + toBlob, + }, + }; }, - Languages: Languages, - Themes: Themes, - ThemeParents: ThemeParents, - TabSizes: TabSizes, + Languages, + Themes, + ThemeParents, + TabSizes, async registerLanguage({ id, grammar, extends: inherits = {} }) { const scopeName = `source.${id}`; @@ -401,28 +421,29 @@ window.CodeMirror = { if (inherits.highlight) { const base = LanguageHighlighters[inherits.highlight]; - if (!base) { - console.warn(`registerLanguage(${id}): unknown highlight base "${inherits.highlight}"`); - } else { + if (base) { extension.push(base); + } else { + console.warn( + `registerLanguage(${id}): unknown highlight base "${inherits.highlight}"`, + ); } } - extension.push(Prec.highest([ - textMateHighlighter(tmGrammar), - textMateBaseTheme - ])); + extension.push(Prec.highest([textMateHighlighter(tmGrammar), textMateBaseTheme])); if (inherits.autocomplete) { const auto = LanguageAutocompletes[inherits.autocomplete]; - if (!auto) { - console.warn(`registerLanguage(${id}): unknown autocomplete base "${inherits.autocomplete}"`); - } else { + if (auto) { extension.push(...auto); + } else { + console.warn( + `registerLanguage(${id}): unknown autocomplete base "${inherits.autocomplete}"`, + ); } } Languages[id] = extension; return extension; - } -}; \ No newline at end of file + }, +}; diff --git a/codemirror/src/plugins/colorComments.js b/codemirror/src/plugins/colorComments.js index 8886860..a90b022 100644 --- a/codemirror/src/plugins/colorComments.js +++ b/codemirror/src/plugins/colorComments.js @@ -1,6 +1,6 @@ -import { EditorView, Decoration, ViewPlugin } from "@codemirror/view"; import { syntaxTree } from "@codemirror/language"; import { RangeSetBuilder } from "@codemirror/state"; +import { Decoration, EditorView, ViewPlugin } from "@codemirror/view"; const markers = [ { regex: /^\?/, className: "cm-comment-info" }, @@ -28,7 +28,11 @@ function buildDecorations(view) { for (const marker of markers) { if (marker.regex.test(body)) { - builder.add(node.from, node.to, Decoration.mark({ class: marker.className })); + builder.add( + node.from, + node.to, + Decoration.mark({ class: marker.className }), + ); break; } } @@ -50,21 +54,23 @@ export const colorComments = ViewPlugin.fromClass( } } }, - { decorations: (v) => v.decorations } + { decorations: (v) => v.decorations }, ); export const colorCommentsTheme = EditorView.baseTheme({ ".cm-comment-info *": { color: "#e5c07b", - opacity: ".8" + opacity: ".8", }, - ".cm-comment-alert *": { - color: "#e06c75", fontWeight: "bold" + ".cm-comment-alert *": { + color: "#e06c75", + fontWeight: "bold", }, - ".cm-comment-highlight *": { - color: "#98c379" + ".cm-comment-highlight *": { + color: "#98c379", }, - ".cm-comment-todo *": { - color: "#61afef", fontWeight: "bold" + ".cm-comment-todo *": { + color: "#61afef", + fontWeight: "bold", }, -}); \ No newline at end of file +}); diff --git a/codemirror/src/plugins/snippets.js b/codemirror/src/plugins/snippets.js index 801cc2e..54c1ccf 100644 --- a/codemirror/src/plugins/snippets.js +++ b/codemirror/src/plugins/snippets.js @@ -26,4 +26,4 @@ export function fromVSCodeSnippets(json, type = "keyword") { } return completions; -} \ No newline at end of file +} diff --git a/codemirror/src/plugins/suggest.js b/codemirror/src/plugins/suggest.js index 020bb23..de22a43 100644 --- a/codemirror/src/plugins/suggest.js +++ b/codemirror/src/plugins/suggest.js @@ -1,5 +1,5 @@ -import { EditorView, Decoration, ViewPlugin, WidgetType } from "@codemirror/view"; -import { StateField, StateEffect } from "@codemirror/state"; +import { StateEffect, StateField } from "@codemirror/state"; +import { Decoration, EditorView, ViewPlugin, WidgetType } from "@codemirror/view"; const setSuggestion = StateEffect.define(); const clearSuggestion = StateEffect.define(); @@ -42,7 +42,7 @@ const suggestionField = StateField.define({ } return value; - } + }, }); const suggestionTheme = EditorView.baseTheme({ @@ -50,8 +50,8 @@ const suggestionTheme = EditorView.baseTheme({ opacity: "0.4", fontStyle: "italic", pointerEvents: "none", - color: "inherit" - } + color: "inherit", + }, }); let debounceTimer = null; @@ -64,7 +64,7 @@ function setLanguage(lang) { function buildDecorations(view) { try { const field = view.state.field(suggestionField, false); - if (!field || !field.text) return Decoration.none; + if (!(field && field.text)) return Decoration.none; const lines = field.text.split("\n"); const decorations = []; @@ -75,8 +75,8 @@ function buildDecorations(view) { Decoration.widget({ widget: new GhostLineWidget(firstLineSuffix), side: 1, - block: false - }).range(firstLine.to) + block: false, + }).range(firstLine.to), ); for (let i = 1; i < lines.length; i++) { @@ -87,8 +87,8 @@ function buildDecorations(view) { Decoration.widget({ widget: new GhostLineWidget(lines[i]), side: 1, - block: false - }).range(targetLine.to) + block: false, + }).range(targetLine.to), ); } @@ -109,20 +109,20 @@ const suggestPlugin = ViewPlugin.fromClass( } }, { - decorations: (v) => v.decorations - } + decorations: (v) => v.decorations, + }, ); function acceptSuggestion(view) { try { const field = view.state.field(suggestionField, false); - if (!field || !field.text) return false; + if (!(field && field.text)) return false; const to = field.from + field.text.length; view.dispatch({ changes: { from: field.from, insert: field.text }, selection: { anchor: to }, - effects: clearSuggestion.of(null) + effects: clearSuggestion.of(null), }); return true; } catch { @@ -133,7 +133,7 @@ function acceptSuggestion(view) { function dismissSuggestion(view) { try { const field = view.state.field(suggestionField, false); - if (!field || !field.text) return false; + if (!(field && field.text)) return false; view.dispatch({ effects: clearSuggestion.of(null) }); return true; @@ -159,28 +159,28 @@ const suggestUpdateListener = EditorView.updateListener.of((update) => { const cursor = view.state.selection.main.head; const line = view.state.doc.lineAt(cursor).number; - const electronAPI = typeof window !== "undefined" && window.electron; - if (!electronAPI || typeof electronAPI.sendCodeSuggestRequest !== "function") return; + const electronApi = typeof window !== "undefined" && window.electron; + if (!electronApi || typeof electronApi.sendCodeSuggestRequest !== "function") return; - electronAPI.sendCodeSuggestRequest({ + electronApi.sendCodeSuggestRequest({ code: fullCode, - cursor: cursor, + cursor, cursorLine: line, - language: currentLanguage + language: currentLanguage, }); }, 800); }); function initSuggestListener() { - const electronAPI = typeof window !== "undefined" && window.electron; - if (!electronAPI || typeof electronAPI.onCodeSuggestResult !== "function") return; + const electronApi = typeof window !== "undefined" && window.electron; + if (!electronApi || typeof electronApi.onCodeSuggestResult !== "function") return; - electronAPI.onCodeSuggestResult((result) => { + electronApi.onCodeSuggestResult((result) => { if (!pendingView) return; const view = pendingView; - if (!result || !result.text) { + if (!(result && result.text)) { view.dispatch({ effects: clearSuggestion.of(null) }); return; } @@ -188,21 +188,21 @@ function initSuggestListener() { view.dispatch({ effects: setSuggestion.of({ text: result.text, - from: view.state.selection.main.head - }) + from: view.state.selection.main.head, + }), }); }); } export { + acceptSuggestion, + clearSuggestion, + dismissSuggestion, + initSuggestListener, + setLanguage, + setSuggestion, suggestionField, suggestionTheme, suggestPlugin, suggestUpdateListener, - setSuggestion, - clearSuggestion, - acceptSuggestion, - dismissSuggestion, - setLanguage, - initSuggestListener }; diff --git a/codemirror/src/plugins/textmate/highlighter.js b/codemirror/src/plugins/textmate/highlighter.js index b52a1c9..28df5b2 100644 --- a/codemirror/src/plugins/textmate/highlighter.js +++ b/codemirror/src/plugins/textmate/highlighter.js @@ -1,111 +1,114 @@ -import { ViewPlugin, Decoration } from "@codemirror/view"; import { RangeSetBuilder } from "@codemirror/state"; +import { Decoration, ViewPlugin } from "@codemirror/view"; import { INITIAL } from "vscode-textmate"; import { scopesToClass } from "./scopeMap.js"; export function textMateHighlighter(grammar) { - return ViewPlugin.fromClass(class { - constructor(view) { - this.grammar = grammar; - this.cache = new Map(); - this.decorations = Decoration.none; - this.rebuild(view); - } - - update(update) { - if (!this.grammar) return; - - if (update.docChanged) { - this.invalidate(update); + return ViewPlugin.fromClass( + class { + constructor(view) { + this.grammar = grammar; + this.cache = new Map(); + this.decorations = Decoration.none; + this.rebuild(view); } - if (update.docChanged || update.viewportChanged) { - this.rebuild(update.view); + update(update) { + if (!this.grammar) return; + + if (update.docChanged) { + this.invalidate(update); + } + + if (update.docChanged || update.viewportChanged) { + this.rebuild(update.view); + } } - } - invalidate(update) { - let firstDirty = Infinity; + invalidate(update) { + let firstDirty = Number.POSITIVE_INFINITY; - update.changes.iterChangedRanges((_fromA, _toA, fromB) => { - const line = update.state.doc.lineAt(fromB).number; - if (line < firstDirty) firstDirty = line; - }); + update.changes.iterChangedRanges((_fromA, _toA, fromB) => { + const line = update.state.doc.lineAt(fromB).number; + if (line < firstDirty) firstDirty = line; + }); - if (firstDirty === Infinity) return; + if (firstDirty === Number.POSITIVE_INFINITY) return; - for (const line of this.cache.keys()) { - if (line >= firstDirty) this.cache.delete(line); + for (const line of this.cache.keys()) { + if (line >= firstDirty) this.cache.delete(line); + } } - } - - stackBefore(view, lineNumber) { - if (lineNumber <= 1) return INITIAL; - const prev = this.cache.get(lineNumber - 1); - if (prev) return prev.stackAfter; + stackBefore(view, lineNumber) { + if (lineNumber <= 1) return INITIAL; - let start = lineNumber - 1; - while (start > 1 && !this.cache.has(start - 1)) start--; + const prev = this.cache.get(lineNumber - 1); + if (prev) return prev.stackAfter; - let stack = start === 1 ? INITIAL : this.cache.get(start - 1).stackAfter; + let start = lineNumber - 1; + while (start > 1 && !this.cache.has(start - 1)) start--; - for (let ln = start; ln < lineNumber; ln++) { - stack = this.tokenizeLine(view, ln, stack).stackAfter; - } + let stack = start === 1 ? INITIAL : this.cache.get(start - 1).stackAfter; - return stack; - } + for (let ln = start; ln < lineNumber; ln++) { + stack = this.tokenizeLine(view, ln, stack).stackAfter; + } - tokenizeLine(view, lineNumber, stackBefore) { - const line = view.state.doc.line(lineNumber); - const result = this.grammar.tokenizeLine(line.text, stackBefore ?? INITIAL); + return stack; + } - const entry = { - text: line.text, - stackAfter: result.ruleStack, - tokens: result.tokens - }; + tokenizeLine(view, lineNumber, stackBefore) { + const line = view.state.doc.line(lineNumber); + const result = this.grammar.tokenizeLine(line.text, stackBefore ?? INITIAL); - this.cache.set(lineNumber, entry); - return entry; - } + const entry = { + text: line.text, + stackAfter: result.ruleStack, + tokens: result.tokens, + }; - rebuild(view) { - const builder = new RangeSetBuilder(); + this.cache.set(lineNumber, entry); + return entry; + } - for (const { from, to } of view.visibleRanges) { - let pos = from; + rebuild(view) { + const builder = new RangeSetBuilder(); - while (pos <= to) { - const line = view.state.doc.lineAt(pos); - let entry = this.cache.get(line.number); + for (const { from, to } of view.visibleRanges) { + let pos = from; - if (!entry || entry.text !== line.text) { - const stackBefore = this.stackBefore(view, line.number); - entry = this.tokenizeLine(view, line.number, stackBefore); - } + while (pos <= to) { + const line = view.state.doc.lineAt(pos); + let entry = this.cache.get(line.number); - for (const token of entry.tokens) { - if (token.startIndex === token.endIndex) continue; + if (!entry || entry.text !== line.text) { + const stackBefore = this.stackBefore(view, line.number); + entry = this.tokenizeLine(view, line.number, stackBefore); + } - const className = scopesToClass(token.scopes); - if (className) { - builder.add( - line.from + token.startIndex, - line.from + token.endIndex, - Decoration.mark({ class: className }) - ); + for (const token of entry.tokens) { + if (token.startIndex === token.endIndex) continue; + + const className = scopesToClass(token.scopes); + if (className) { + builder.add( + line.from + token.startIndex, + line.from + token.endIndex, + Decoration.mark({ class: className }), + ); + } } - } - pos = line.to + 1; + pos = line.to + 1; + } } - } - this.decorations = builder.finish(); - } - }, { - decorations: v => v.decorations - }); -} \ No newline at end of file + this.decorations = builder.finish(); + } + }, + { + decorations: (v) => v.decorations, + }, + ); +} diff --git a/codemirror/src/plugins/textmate/scopeMap.js b/codemirror/src/plugins/textmate/scopeMap.js index 1a151d0..f2ea42f 100644 --- a/codemirror/src/plugins/textmate/scopeMap.js +++ b/codemirror/src/plugins/textmate/scopeMap.js @@ -32,4 +32,4 @@ export function scopesToClass(scopes) { cache.set(key, match); return match; -} \ No newline at end of file +} diff --git a/codemirror/src/plugins/textmate/theme.js b/codemirror/src/plugins/textmate/theme.js index 59a8d03..b1645ab 100644 --- a/codemirror/src/plugins/textmate/theme.js +++ b/codemirror/src/plugins/textmate/theme.js @@ -12,5 +12,5 @@ export const textMateBaseTheme = EditorView.theme({ ".cm-tm-tag": { color: "#569cd6" }, ".cm-tm-attribute": { color: "#9cdcfe" }, ".cm-tm-variable": { color: "#9cdcfe" }, - ".cm-tm-punctuation": { color: "#d4d4d4" } -}); \ No newline at end of file + ".cm-tm-punctuation": { color: "#d4d4d4" }, +}); diff --git a/codemirror/src/snippets/js/globals.json b/codemirror/src/snippets/js/globals.json index a7b0efe..7fccaea 100644 --- a/codemirror/src/snippets/js/globals.json +++ b/codemirror/src/snippets/js/globals.json @@ -1,6 +1,19 @@ [ - "document", "window", "console", "navigator", "localStorage", "sessionStorage", - "fetch", "setTimeout", "setInterval", "requestAnimationFrame", - "addEventListener", "removeEventListener", "querySelector", "querySelectorAll", - "getElementById", "getElementsByClassName", "createElement" -] \ No newline at end of file + "document", + "window", + "console", + "navigator", + "localStorage", + "sessionStorage", + "fetch", + "setTimeout", + "setInterval", + "requestAnimationFrame", + "addEventListener", + "removeEventListener", + "querySelector", + "querySelectorAll", + "getElementById", + "getElementsByClassName", + "createElement" +] diff --git a/codemirror/src/snippets/js/snippets.json b/codemirror/src/snippets/js/snippets.json index c847e4f..7ae531d 100644 --- a/codemirror/src/snippets/js/snippets.json +++ b/codemirror/src/snippets/js/snippets.json @@ -1,594 +1,600 @@ { - "arrayMerge": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["am"], - "body": ["[...${0:array}]"], - "description": "Shallow-copy a single array (clone) or multiple arrays (merge) to a new array literal via the spread operator." - }, - - "uniq": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["uniq"], - "body": ["[...new Set(${0:array})]"], - "description": "Creates a duplicate-free version of an array." - }, - - "range": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["range"], - "body": ["[...Array(${0:length}).keys()]"], - "description": "An array containing a sequence of numbers from 0 up to, but not including, length." - }, - - "forEach": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["foreach"], - "body": ["${1:array}.forEach((${2}) => {", " $0", "});"], - "description": "Array.prototype.forEach() method." - }, - - "map": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["map"], - "body": ["${1:array}.map((${2:element}) => {", " $0", "});"], - "description": "Array.prototype.map() method." - }, - - "reduce": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["reduce"], - "body": ["${1:array}.reduce((${2:accumulator}, ${3:currentValue}) => {", " $0", "}$4);"], - "description": "Array.prototype.reduce() method." - }, - - "reduceRight": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["reduceright"], - "body": ["${1:array}.reduceRight((${2:accumulator}, ${3:currentValue}) => {", " $0", "}$4);"], - "description": "Array.prototype.reduceRight() method." - }, - - "filter": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["filter"], - "body": ["${1:array}.filter((${2:element}) => {", " $0", "});"], - "description": "Array.prototype.filter() method." - }, - - "find": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["find"], - "body": ["${1:array}.find((${2:element}) => {", " $0", "});"], - "description": "Array.prototype.find() method." - }, - - "findIndex": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["findindex"], - "body": ["${1:array}.findIndex((${2:element}) => {", " $0", "});"], - "description": "Array.prototype.findIndex() method." - }, - - "some": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["some"], - "body": ["${1:array}.some((${2:element}) => {", " $0", "});"], - "description": "Array.prototype.some() method." - }, - - "every": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["every"], - "body": ["${1:array}.every((${2:element}) => {", " $0", "});"], - "description": "Array.prototype.every() method." - }, - - "flatMap": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["flatmap"], - "body": ["${1:array}.flatMap((${2:element}) => {", " $0", "});"], - "description": "Array.prototype.flatMap() method." - }, - - "constAssignment": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ca"], - "body": ["const ${1:name} = $0"], - "description": "Const assignment." - }, - - "letAssignment": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["la"], - "body": ["let ${1:name} = $0"], - "description": "Let assignment." - }, - - "constAssignmentDestructuring": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["cad"], - "body": ["const { ${0:key} } = ${1:object};"], - "description": "Const object destructuring assignment." - }, - - "letAssignmentDestructuring": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["lad"], - "body": ["let { ${0:key} } = ${1:object};"], - "description": "Let object destructuring assignment." - }, - - "class": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["cs"], - "body": [ - "class ${1:${TM_FILEPATH/.*[\\/\\\\]([^\\/\\\\]+)[\\/\\\\]index\\.[jt]s$|.*[\\/\\\\](.*?)(?:\\.[^.]*)$/$1$2/}} {", - " $0", - "}", - "", - "export default ${1: ${TM_FILEPATH/.*[\\/\\\\]([^\\/\\\\]+)[\\/\\\\]index\\.[jt]s$|.*[\\/\\\\](.*?)(?:\\.[^.]*)$/$1$2/}};" - ], - "description": "Class exported as default and named after the file (if file is not named index, in which case the class is named after the parent folder)." - }, - - "classExtends": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["cse"], - "body": [ - "class ${1:${TM_FILEPATH/.*[\\/\\\\]([^\\/\\\\]+)[\\/\\\\]index\\.[jt]s$|.*[\\/\\\\](.*?)(?:\\.[^.]*)$/$1$2/}} extends ${2:SuperClass} {", - " $0", - "}", - "", - "export default ${1: ${TM_FILEPATH/.*[\\/\\\\]([^\\/\\\\]+)[\\/\\\\]index\\.[jt]s$|.*[\\/\\\\](.*?)(?:\\.[^.]*)$/$1$2/}};" - ], - "description": "Subclass exported as default and named after the file (if file is not named index, in which case the class is named after the parent folder)." - }, - - "constructor": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ctr"], - "body": ["constructor($1) {", " super($2);", " $0", "}"], - "description": "Class constructor." - }, - - "method": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["met"], - "body": ["${1:name}($2) {", " $0", "}"], - "description": "Class method." - }, - - "if": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["if"], - "body": ["if (${1:condition}) {", " $0", "}"], - "description": "If statement." - }, - - "else": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["el"], - "body": ["else {", " $0", "}"], - "description": "Else statement." - }, - - "elseIf": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ei"], - "body": ["else if (${1:condition}) {", " $0", "}"], - "description": "Else-if statement." - }, - - "ternary": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ter"], - "body": ["${1:condition} ? ${2:expressionIfTrue} : ${0:expressionIfFalse}"], - "description": "Ternary operator." - }, - - "switch": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["switch"], - "body": [ - "switch (${1:key}) {", - " case ${2:value}:", - " $0", - " break;", - "", - " default:", - " break;", - "}" - ], - "description": "Switch statement." - }, - - "case": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["case"], - "body": ["case ${1:value}:", " $0", " break;"], - "description": "Case clause." - }, - - "consoleLog": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["cl"], - "body": ["console.log(${0});"], - "description": "Console log." - }, - - "consoleLogReturn": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["clr"], - "body": [" console.log(${0}) ||"], - "description": "Console log. Appended by the logical OR operator (for convenient logging in front of an arrow function's implicit return value)." - }, - - "consoleError": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ce"], - "body": ["console.error(${0});"], - "description": "Console error." - }, - - "consoleWarn": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["cw"], - "body": ["console.warn(${0});"], - "description": "Console warn." - }, - - "consoleLogClipboard": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["clc"], - "body": ["console.log({ $CLIPBOARD });${0}"], - "description": "Console log the value you have copied to your clipboard, inside of an object (for an automatic label)." - }, - - "consoleLogMessage": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["clm"], - "body": ["console.log('${0}');"], - "description": "Console log message." - }, - - "consoleLogMessageReturn": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["clmr"], - "body": [" console.log('${0}') ||"], - "description": "Console log message. Appended by the logical OR operator (for convenient logging in front of an arrow function's implicit return value)." - }, - - "consoleLogObject": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["clo"], - "body": ["console.log({ ${0} });"], - "description": "Console log an object, in which variables can be inserted (for automatic labels)." - }, - - "consoleLogObjectReturn": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["clor"], - "body": [" console.log({ ${0} }) ||"], - "description": "Console log an object, in which variables can be inserted (for automatic labels). Appended by the logical OR operator (for convenient logging in front of an arrow function's implicit return value)." - }, - - "consoleLogGroup": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["clg"], - "body": [ - "// ====== LOG START ======", - "console.log('\\n');", - "console.group('Log');", - "console.log(${1});", - "console.groupEnd();", - "console.log('\\n');", - "// ====== LOG END ======", - "${0}" - ], - "description": "Console log, wrapped in a formatted and styled console group." - }, - - "consoleLogAnalysis": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["cla"], - "body": [ - "// ====== LOG START ======", - "const logStandardDetails = (key, value) => {", - " console.group('value');", - " console.log(value);", - " console.groupEnd();", - " console.group('type');", - " console.log(typeof value);", - " console.groupEnd();", - " console.group('count');", - " console.count(key);", - " console.groupEnd();", - " console.group('trace');", - " console.trace();", - " console.groupEnd();", - "}", - "", - "const logObjectDetails = (value) => {", - " let logValue = value;", - " let isCircularStructure = false;", - "", - " try {", - " // Snapshot of log-time value, rather than current (potentially-mutated) value.", - " logValue = JSON.parse(JSON.stringify(value));", - " } catch (error) {", - " // Handle values that can't be converted to JSON (e.g.window).", - " isCircularStructure = true;", - " }", - "", - " console.group('log-time value (before any potential mutations)');", - "", - " if (isCircularStructure) {", - " console.log('Not determined (object is a circular structure).');", - " } else {", - " console.log(logValue);", - " }", - "", - " console.groupEnd();", - " console.group('table');", - " console.table(logValue);", - " console.groupEnd();", - "}", - "", - "const logDetails = (key, value) => {", - " logStandardDetails(key, value);", - " ", - " if (typeof value === 'object' && value !== null) {", - " logObjectDetails(value);", - " }", - "}", - "", - "const logAllValues = () => {", - " Object.entries({ ${1} }).forEach(([key, value]) => {", - " console.groupCollapsed(`%c\\${key}`, 'color: blue;');", - " logDetails(key, value)", - " console.groupEnd();", - " });", - "}", - "", - "console.log('\\n');", - "console.group('Log');", - "logAllValues()", - "console.groupEnd();", - "console.log('\\n');", - "// ====== LOG END ======", - "${0}" - ], - "description": "Console log an object, in which variables can be inserted. Includes value, type, count, and trace for all values. Includes log-time value and table for objects. Wrapped in a formatted and styled console group." - }, - - "tryCatch": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["tc"], - "body": ["try {", " $0", "} catch (error) {", "", "}"], - "description": "Try-catch statement." - }, - - "tryCatchFinally": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["tcf"], - "body": ["try {", " $0", "} catch (error) {", "", "} finally {", "", "}"], - "description": "Try-catch-finally statement." - }, - - "tryFinally": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["tf"], - "body": ["try {", " $0", "} finally {", "", "}"], - "description": "Try-finally statement." - }, - - "throwError": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["te"], - "body": ["throw new ${1|Error,TypeError,RangeError|}(${0});"], - "description": "Throw error object exception." - }, - - "function": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["function"], - "body": ["function ${1:name}($2) {", " $0", "}"], - "description": "Named function declaration." - }, - - "arrowFunction": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["af"], - "body": ["($1) => $0"], - "description": "Anonymous arrow function expression." - }, - - "jsonParse": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["jp"], - "body": ["JSON.parse(${1:json})$0"], - "description": "JSON.parse() method." - }, - - "jsonStringify": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["js"], - "body": ["JSON.stringify(${1:value})$0"], - "description": "JSON.stringify() method." - }, - - "doWhile": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["dowhile"], - "body": ["do {", " $0", "} while (${1:condition});"], - "description": "Do-while loop." - }, - - "while": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["while"], - "body": ["while (${1:condition}) {", " $0", "}"], - "description": "While loop." - }, - - "for": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["for"], - "body": [ - "for (let ${1:index} = 0; $1 < ${2:array}.length; $1++) {", - " const ${3:element} = $2[$1];", - " $0", - "}" - ], - "description": "For loop." - }, - - "forIn": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["forin"], - "body": [ - "for (const ${1:key} in ${2:object}) {", - " if ($2.hasOwnProperty($1)) {", - " const ${3:element} = $2[$1];", - " $0", - " }", - "}" - ], - "description": "For-in loop." - }, - - "forOf": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["forof"], - "body": ["for (const ${1:iterator} of ${2:object}) {", " $0", "}"], - "description": "For-of loop." - }, - - "useStrict": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["use"], - "body": ["'use strict';$0"], - "description": "Use strict statement." - }, - - "import": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["imp"], - "body": ["import ${0:module} from '${1}';"], - "description": "Import module." - }, - - "exportDefault": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["expd"], - "body": ["export default $0"], - "description": "Default export." - }, - - "export": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["exp"], - "body": ["export $0"], - "description": "Named export." - }, - - "objectMerge": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["om"], - "body": ["{ ...${0:object} }"], - "description": "Shallow-copy a single object (clone) or multiple objects (merge) to a new object literal via the spread operator. Similar to the Object.assign() method, but has the added benefit of not allowing for shallow mutations." - }, - - "objectEntries": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["oe"], - "body": ["Object.entries(${0:object})"], - "description": "Object.entries() method." - }, - - "objectFromEntries": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ofe"], - "body": ["Object.fromEntries(${0:iterable})"], - "description": "Object.fromEntries() method." - }, - - "objectKeys": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ok"], - "body": ["Object.keys(${0:object})"], - "description": "Object.keys() method." - }, - - "objectValues": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ov"], - "body": ["Object.values(${0:object})"], - "description": "Object.values() method." - }, - - "return": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["ret"], - "body": ["return $0"], - "description": "Return statement." - }, - - "returnMultiline": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["retm"], - "body": ["return (", " $0", ");"], - "description": "Return statement for multiline expression that includes complex values (e.g. JSX)." - }, - - "setTimeout": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["st"], - "body": ["setTimeout(() => {", " $0", "}, ${1:delay});"], - "description": "setTimeout() method." - }, - - "setInterval": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["si"], - "body": ["setInterval(() => {", " $0", "}, ${1:delay});"], - "description": "setInterval() method." - }, - - "typeof": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["to"], - "body": [ - "typeof ${0:operand} === '${1|bigint,boolean,function,number,object,string,symbol,undefined|}'" - ], - "description": "typeof operator." - }, - - "instanceof": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["io"], - "body": ["${1:object} instanceof ${0:constructor}"], - "description": "instanceof operator." - }, - - "arrayIsArray": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["aia"], - "body": ["Array.isArray(${0:value})"], - "description": "Array.isArray() method." - }, - - "isPlainObject": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["isPlainObject"], - "body": ["typeof ${0:value} === 'object' && !Array.isArray(${0:value}) && ${0:value} !== null"], - "description": "Check if value is a plain object." - }, - - "isNil": { - "scope": "javascript,typescript,javascriptreact,typescriptreact", - "prefix": ["isNil"], - "body": ["typeof ${0:value} === 'undefined' || ${0:value} === null"], - "description": "Check if value is null or undefined." - } + "arrayMerge": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["am"], + "body": ["[...${0:array}]"], + "description": "Shallow-copy a single array (clone) or multiple arrays (merge) to a new array literal via the spread operator." + }, + + "uniq": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["uniq"], + "body": ["[...new Set(${0:array})]"], + "description": "Creates a duplicate-free version of an array." + }, + + "range": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["range"], + "body": ["[...Array(${0:length}).keys()]"], + "description": "An array containing a sequence of numbers from 0 up to, but not including, length." + }, + + "forEach": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["foreach"], + "body": ["${1:array}.forEach((${2}) => {", " $0", "});"], + "description": "Array.prototype.forEach() method." + }, + + "map": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["map"], + "body": ["${1:array}.map((${2:element}) => {", " $0", "});"], + "description": "Array.prototype.map() method." + }, + + "reduce": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["reduce"], + "body": ["${1:array}.reduce((${2:accumulator}, ${3:currentValue}) => {", " $0", "}$4);"], + "description": "Array.prototype.reduce() method." + }, + + "reduceRight": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["reduceright"], + "body": [ + "${1:array}.reduceRight((${2:accumulator}, ${3:currentValue}) => {", + " $0", + "}$4);" + ], + "description": "Array.prototype.reduceRight() method." + }, + + "filter": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["filter"], + "body": ["${1:array}.filter((${2:element}) => {", " $0", "});"], + "description": "Array.prototype.filter() method." + }, + + "find": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["find"], + "body": ["${1:array}.find((${2:element}) => {", " $0", "});"], + "description": "Array.prototype.find() method." + }, + + "findIndex": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["findindex"], + "body": ["${1:array}.findIndex((${2:element}) => {", " $0", "});"], + "description": "Array.prototype.findIndex() method." + }, + + "some": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["some"], + "body": ["${1:array}.some((${2:element}) => {", " $0", "});"], + "description": "Array.prototype.some() method." + }, + + "every": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["every"], + "body": ["${1:array}.every((${2:element}) => {", " $0", "});"], + "description": "Array.prototype.every() method." + }, + + "flatMap": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["flatmap"], + "body": ["${1:array}.flatMap((${2:element}) => {", " $0", "});"], + "description": "Array.prototype.flatMap() method." + }, + + "constAssignment": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ca"], + "body": ["const ${1:name} = $0"], + "description": "Const assignment." + }, + + "letAssignment": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["la"], + "body": ["let ${1:name} = $0"], + "description": "Let assignment." + }, + + "constAssignmentDestructuring": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["cad"], + "body": ["const { ${0:key} } = ${1:object};"], + "description": "Const object destructuring assignment." + }, + + "letAssignmentDestructuring": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["lad"], + "body": ["let { ${0:key} } = ${1:object};"], + "description": "Let object destructuring assignment." + }, + + "class": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["cs"], + "body": [ + "class ${1:${TM_FILEPATH/.*[\\/\\\\]([^\\/\\\\]+)[\\/\\\\]index\\.[jt]s$|.*[\\/\\\\](.*?)(?:\\.[^.]*)$/$1$2/}} {", + " $0", + "}", + "", + "export default ${1: ${TM_FILEPATH/.*[\\/\\\\]([^\\/\\\\]+)[\\/\\\\]index\\.[jt]s$|.*[\\/\\\\](.*?)(?:\\.[^.]*)$/$1$2/}};" + ], + "description": "Class exported as default and named after the file (if file is not named index, in which case the class is named after the parent folder)." + }, + + "classExtends": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["cse"], + "body": [ + "class ${1:${TM_FILEPATH/.*[\\/\\\\]([^\\/\\\\]+)[\\/\\\\]index\\.[jt]s$|.*[\\/\\\\](.*?)(?:\\.[^.]*)$/$1$2/}} extends ${2:SuperClass} {", + " $0", + "}", + "", + "export default ${1: ${TM_FILEPATH/.*[\\/\\\\]([^\\/\\\\]+)[\\/\\\\]index\\.[jt]s$|.*[\\/\\\\](.*?)(?:\\.[^.]*)$/$1$2/}};" + ], + "description": "Subclass exported as default and named after the file (if file is not named index, in which case the class is named after the parent folder)." + }, + + "constructor": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ctr"], + "body": ["constructor($1) {", " super($2);", " $0", "}"], + "description": "Class constructor." + }, + + "method": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["met"], + "body": ["${1:name}($2) {", " $0", "}"], + "description": "Class method." + }, + + "if": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["if"], + "body": ["if (${1:condition}) {", " $0", "}"], + "description": "If statement." + }, + + "else": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["el"], + "body": ["else {", " $0", "}"], + "description": "Else statement." + }, + + "elseIf": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ei"], + "body": ["else if (${1:condition}) {", " $0", "}"], + "description": "Else-if statement." + }, + + "ternary": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ter"], + "body": ["${1:condition} ? ${2:expressionIfTrue} : ${0:expressionIfFalse}"], + "description": "Ternary operator." + }, + + "switch": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["switch"], + "body": [ + "switch (${1:key}) {", + " case ${2:value}:", + " $0", + " break;", + "", + " default:", + " break;", + "}" + ], + "description": "Switch statement." + }, + + "case": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["case"], + "body": ["case ${1:value}:", " $0", " break;"], + "description": "Case clause." + }, + + "consoleLog": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["cl"], + "body": ["console.log(${0});"], + "description": "Console log." + }, + + "consoleLogReturn": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["clr"], + "body": [" console.log(${0}) ||"], + "description": "Console log. Appended by the logical OR operator (for convenient logging in front of an arrow function's implicit return value)." + }, + + "consoleError": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ce"], + "body": ["console.error(${0});"], + "description": "Console error." + }, + + "consoleWarn": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["cw"], + "body": ["console.warn(${0});"], + "description": "Console warn." + }, + + "consoleLogClipboard": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["clc"], + "body": ["console.log({ $CLIPBOARD });${0}"], + "description": "Console log the value you have copied to your clipboard, inside of an object (for an automatic label)." + }, + + "consoleLogMessage": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["clm"], + "body": ["console.log('${0}');"], + "description": "Console log message." + }, + + "consoleLogMessageReturn": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["clmr"], + "body": [" console.log('${0}') ||"], + "description": "Console log message. Appended by the logical OR operator (for convenient logging in front of an arrow function's implicit return value)." + }, + + "consoleLogObject": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["clo"], + "body": ["console.log({ ${0} });"], + "description": "Console log an object, in which variables can be inserted (for automatic labels)." + }, + + "consoleLogObjectReturn": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["clor"], + "body": [" console.log({ ${0} }) ||"], + "description": "Console log an object, in which variables can be inserted (for automatic labels). Appended by the logical OR operator (for convenient logging in front of an arrow function's implicit return value)." + }, + + "consoleLogGroup": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["clg"], + "body": [ + "// ====== LOG START ======", + "console.log('\\n');", + "console.group('Log');", + "console.log(${1});", + "console.groupEnd();", + "console.log('\\n');", + "// ====== LOG END ======", + "${0}" + ], + "description": "Console log, wrapped in a formatted and styled console group." + }, + + "consoleLogAnalysis": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["cla"], + "body": [ + "// ====== LOG START ======", + "const logStandardDetails = (key, value) => {", + " console.group('value');", + " console.log(value);", + " console.groupEnd();", + " console.group('type');", + " console.log(typeof value);", + " console.groupEnd();", + " console.group('count');", + " console.count(key);", + " console.groupEnd();", + " console.group('trace');", + " console.trace();", + " console.groupEnd();", + "}", + "", + "const logObjectDetails = (value) => {", + " let logValue = value;", + " let isCircularStructure = false;", + "", + " try {", + " // Snapshot of log-time value, rather than current (potentially-mutated) value.", + " logValue = JSON.parse(JSON.stringify(value));", + " } catch (error) {", + " // Handle values that can't be converted to JSON (e.g.window).", + " isCircularStructure = true;", + " }", + "", + " console.group('log-time value (before any potential mutations)');", + "", + " if (isCircularStructure) {", + " console.log('Not determined (object is a circular structure).');", + " } else {", + " console.log(logValue);", + " }", + "", + " console.groupEnd();", + " console.group('table');", + " console.table(logValue);", + " console.groupEnd();", + "}", + "", + "const logDetails = (key, value) => {", + " logStandardDetails(key, value);", + " ", + " if (typeof value === 'object' && value !== null) {", + " logObjectDetails(value);", + " }", + "}", + "", + "const logAllValues = () => {", + " Object.entries({ ${1} }).forEach(([key, value]) => {", + " console.groupCollapsed(`%c\\${key}`, 'color: blue;');", + " logDetails(key, value)", + " console.groupEnd();", + " });", + "}", + "", + "console.log('\\n');", + "console.group('Log');", + "logAllValues()", + "console.groupEnd();", + "console.log('\\n');", + "// ====== LOG END ======", + "${0}" + ], + "description": "Console log an object, in which variables can be inserted. Includes value, type, count, and trace for all values. Includes log-time value and table for objects. Wrapped in a formatted and styled console group." + }, + + "tryCatch": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["tc"], + "body": ["try {", " $0", "} catch (error) {", "", "}"], + "description": "Try-catch statement." + }, + + "tryCatchFinally": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["tcf"], + "body": ["try {", " $0", "} catch (error) {", "", "} finally {", "", "}"], + "description": "Try-catch-finally statement." + }, + + "tryFinally": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["tf"], + "body": ["try {", " $0", "} finally {", "", "}"], + "description": "Try-finally statement." + }, + + "throwError": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["te"], + "body": ["throw new ${1|Error,TypeError,RangeError|}(${0});"], + "description": "Throw error object exception." + }, + + "function": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["function"], + "body": ["function ${1:name}($2) {", " $0", "}"], + "description": "Named function declaration." + }, + + "arrowFunction": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["af"], + "body": ["($1) => $0"], + "description": "Anonymous arrow function expression." + }, + + "jsonParse": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["jp"], + "body": ["JSON.parse(${1:json})$0"], + "description": "JSON.parse() method." + }, + + "jsonStringify": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["js"], + "body": ["JSON.stringify(${1:value})$0"], + "description": "JSON.stringify() method." + }, + + "doWhile": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["dowhile"], + "body": ["do {", " $0", "} while (${1:condition});"], + "description": "Do-while loop." + }, + + "while": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["while"], + "body": ["while (${1:condition}) {", " $0", "}"], + "description": "While loop." + }, + + "for": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["for"], + "body": [ + "for (let ${1:index} = 0; $1 < ${2:array}.length; $1++) {", + " const ${3:element} = $2[$1];", + " $0", + "}" + ], + "description": "For loop." + }, + + "forIn": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["forin"], + "body": [ + "for (const ${1:key} in ${2:object}) {", + " if ($2.hasOwnProperty($1)) {", + " const ${3:element} = $2[$1];", + " $0", + " }", + "}" + ], + "description": "For-in loop." + }, + + "forOf": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["forof"], + "body": ["for (const ${1:iterator} of ${2:object}) {", " $0", "}"], + "description": "For-of loop." + }, + + "useStrict": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["use"], + "body": ["'use strict';$0"], + "description": "Use strict statement." + }, + + "import": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["imp"], + "body": ["import ${0:module} from '${1}';"], + "description": "Import module." + }, + + "exportDefault": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["expd"], + "body": ["export default $0"], + "description": "Default export." + }, + + "export": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["exp"], + "body": ["export $0"], + "description": "Named export." + }, + + "objectMerge": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["om"], + "body": ["{ ...${0:object} }"], + "description": "Shallow-copy a single object (clone) or multiple objects (merge) to a new object literal via the spread operator. Similar to the Object.assign() method, but has the added benefit of not allowing for shallow mutations." + }, + + "objectEntries": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["oe"], + "body": ["Object.entries(${0:object})"], + "description": "Object.entries() method." + }, + + "objectFromEntries": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ofe"], + "body": ["Object.fromEntries(${0:iterable})"], + "description": "Object.fromEntries() method." + }, + + "objectKeys": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ok"], + "body": ["Object.keys(${0:object})"], + "description": "Object.keys() method." + }, + + "objectValues": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ov"], + "body": ["Object.values(${0:object})"], + "description": "Object.values() method." + }, + + "return": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["ret"], + "body": ["return $0"], + "description": "Return statement." + }, + + "returnMultiline": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["retm"], + "body": ["return (", " $0", ");"], + "description": "Return statement for multiline expression that includes complex values (e.g. JSX)." + }, + + "setTimeout": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["st"], + "body": ["setTimeout(() => {", " $0", "}, ${1:delay});"], + "description": "setTimeout() method." + }, + + "setInterval": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["si"], + "body": ["setInterval(() => {", " $0", "}, ${1:delay});"], + "description": "setInterval() method." + }, + + "typeof": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["to"], + "body": [ + "typeof ${0:operand} === '${1|bigint,boolean,function,number,object,string,symbol,undefined|}'" + ], + "description": "typeof operator." + }, + + "instanceof": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["io"], + "body": ["${1:object} instanceof ${0:constructor}"], + "description": "instanceof operator." + }, + + "arrayIsArray": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["aia"], + "body": ["Array.isArray(${0:value})"], + "description": "Array.isArray() method." + }, + + "isPlainObject": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["isPlainObject"], + "body": [ + "typeof ${0:value} === 'object' && !Array.isArray(${0:value}) && ${0:value} !== null" + ], + "description": "Check if value is a plain object." + }, + + "isNil": { + "scope": "javascript,typescript,javascriptreact,typescriptreact", + "prefix": ["isNil"], + "body": ["typeof ${0:value} === 'undefined' || ${0:value} === null"], + "description": "Check if value is null or undefined." + } } diff --git a/codemirror/src/snippets/js/source.js b/codemirror/src/snippets/js/source.js index 77a355b..78b7bb7 100644 --- a/codemirror/src/snippets/js/source.js +++ b/codemirror/src/snippets/js/source.js @@ -9,7 +9,7 @@ export function identifierJavaScriptCompletionSource(context) { try { ast = parse(context.state.doc.toString(), { sourceType: "module", - plugins: ["jsx", "typescript"] + plugins: ["jsx", "typescript"], }); } catch { return null; @@ -21,14 +21,22 @@ export function identifierJavaScriptCompletionSource(context) { if (path.isReferencedIdentifier()) return; names.add(path.node.name); }, - ImportSpecifier(path) { names.add(path.node.local.name); }, - ImportDefaultSpecifier(path) { names.add(path.node.local.name); }, - FunctionDeclaration(path) { if (path.node.id) names.add(path.node.id.name); }, - VariableDeclarator(path) { if (path.node.id.name) names.add(path.node.id.name); } + ImportSpecifier(path) { + names.add(path.node.local.name); + }, + ImportDefaultSpecifier(path) { + names.add(path.node.local.name); + }, + FunctionDeclaration(path) { + if (path.node.id) names.add(path.node.id.name); + }, + VariableDeclarator(path) { + if (path.node.id.name) names.add(path.node.id.name); + }, }); return { from: word.from, - options: [...names].map(label => ({ label, type: "variable" })) + options: [...names].map((label) => ({ label, type: "variable" })), }; -} \ No newline at end of file +} diff --git a/codemirror/src/snippets/json/source.js b/codemirror/src/snippets/json/source.js index 3618c5d..e625511 100644 --- a/codemirror/src/snippets/json/source.js +++ b/codemirror/src/snippets/json/source.js @@ -24,6 +24,6 @@ export function identifierJSONCompletionSource(context) { return { from: word.from, - options: [...keys].map(label => ({ label, type: "property" })) + options: [...keys].map((label) => ({ label, type: "property" })), }; -} \ No newline at end of file +} diff --git a/codemirror/src/themes/overrides.js b/codemirror/src/themes/overrides.js index 135f922..15ede03 100644 --- a/codemirror/src/themes/overrides.js +++ b/codemirror/src/themes/overrides.js @@ -2,22 +2,22 @@ import { EditorView } from "@codemirror/view"; export const vscodeDarkOverride = EditorView.theme({ "&": { - backgroundColor: "#101010!important" + backgroundColor: "#101010!important", }, ".cm-gutters": { - backgroundColor: "#101010!important" - } + backgroundColor: "#101010!important", + }, }); export const atomoneOverride = EditorView.theme({ "&": { - backgroundColor: "#26262b!important" + backgroundColor: "#26262b!important", }, ".cm-gutters": { - backgroundColor: "#0b0b0b!important" - } + backgroundColor: "#0b0b0b!important", + }, }); export const githubDarkOverride = EditorView.theme({ ".cm-gutters": { - backgroundColor: "#0d1117!important" - } -}); \ No newline at end of file + backgroundColor: "#0d1117!important", + }, +}); diff --git a/helpers/debuggerWindow/debuggerWindow.js b/helpers/debuggerWindow/debuggerWindow.js index 55c19ad..7efefcb 100644 --- a/helpers/debuggerWindow/debuggerWindow.js +++ b/helpers/debuggerWindow/debuggerWindow.js @@ -1,15 +1,15 @@ -const { BrowserWindow, nativeImage, app, ipcMain, clipboard } = require("electron") -const path = require("path") -const fs = require("fs") -const { exec } = require("child_process") -const bus = require("../eventBus.js") +const { BrowserWindow, nativeImage, app, ipcMain, clipboard } = require("electron"); +const path = require("path"); +const fs = require("fs"); +const { exec } = require("child_process"); +const bus = require("../eventBus.js"); -const { getAppIcon } = require("../../app/main/helpers/requests.js") -const { ASSETS_PATH } = require("../../app/main/helpers/paths.js") +const { getAppIcon } = require("../../app/main/helpers/requests.js"); +const { ASSETS_PATH } = require("../../app/main/helpers/paths.js"); async function createDebuggerWindow(mainWindow, title = "Debugger") { - const overlayIconPath = path.join(ASSETS_PATH, "media", "debugger_icon.png") - const appIcon = await getAppIcon() + const overlayIconPath = path.join(ASSETS_PATH, "media", "debugger_icon.png"); + const appIcon = await getAppIcon(); const win = new BrowserWindow({ width: 800, @@ -21,92 +21,94 @@ async function createDebuggerWindow(mainWindow, title = "Debugger") { webPreferences: { contextIsolation: true, nodeIntegration: false, - preload: path.join(__dirname, "preload.js") - } - }) - win.setMenu(null) + preload: path.join(import.meta.dirname, "preload.js"), + }, + }); + win.setMenu(null); - win.loadFile(path.join(__dirname, "index.html")) + win.loadFile(path.join(import.meta.dirname, "index.html")); try { - const overlay = nativeImage.createFromPath(overlayIconPath) + const overlay = nativeImage.createFromPath(overlayIconPath); if (!overlay.isEmpty()) { - win.setOverlayIcon(overlay, "Debugger active") + win.setOverlayIcon(overlay, "Debugger active"); } } catch (err) { - console.warn("Overlay icon error:", err) + console.warn("Overlay icon error:", err); } - debuggerWindow = win - debuggerWindow.name = "debuggerWindow" + debuggerWindow = win; + debuggerWindow.name = "debuggerWindow"; win.on("closed", () => { - debuggerWindow = null - }) + debuggerWindow = null; + }); ipcMain.on("debugger-ready", (event) => { - mainWindow.webContents.send("debugger-ready") + mainWindow.webContents.send("debugger-ready"); bus.emit("debugger-ready", event.sender); ipcMain.on("debugger-data", (event, data) => { if (debuggerWindow && !debuggerWindow.isDestroyed()) { debuggerWindow.webContents.send("debug-event", { data, - time: Date.now() - }) + time: Date.now(), + }); } - }) - }) + }); + }); - ipcMain.on('close-window', () => { + ipcMain.on("close-window", () => { if (debuggerWindow) { debuggerWindow.close(); } }); - ipcMain.on('debugger-copy-text', (event, text) => { - clipboard.writeText(text) + ipcMain.on("debugger-copy-text", (event, text) => { + clipboard.writeText(text); }); - ipcMain.on('debugger-copy-as-file', (event, text) => { - const now = new Date() - const pad = (n) => String(n).padStart(2, "0") - const datetime = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}` - const filename = `Debugger-cdmtn-${datetime}.txt` - const tmpDir = app.getPath("temp") - const filePath = path.join(tmpDir, filename) - - fs.writeFileSync(filePath, text, "utf-8") - - const escapedPS = filePath.replace(/'/g, "''") - const escapedOSA = filePath.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\$/g, "\\$").replace(/`/g, "\\`") - const escapedURL = "file://" + filePath.replace(/\\/g, "/").replace(/[^a-zA-Z0-9-._~:/?#\[\]@!'()*+,;=%]/g, encodeURIComponent) - - if (process.platform === 'win32') { - exec( - `powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Clipboard]::SetFileDropList(@('${escapedPS}'))"`, - (err) => { - if (err) clipboard.writeText(text) - } - ) - } else if (process.platform === 'darwin') { + ipcMain.on("debugger-copy-as-file", (event, text) => { + const now = new Date(); + const pad = (n) => String(n).padStart(2, "0"); + const datetime = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`; + const filename = `Debugger-cdmtn-${datetime}.txt`; + const tmpDir = app.getPath("temp"); + const filePath = path.join(tmpDir, filename); + + fs.writeFileSync(filePath, text, "utf-8"); + + const escapedPs = filePath.replace(/'/g, "''"); + const escapedOsa = filePath + .replace(/\\/g, "\\\\") + .replace(/"/g, '\\"') + .replace(/\$/g, "\\$") + .replace(/`/g, "\\`"); + const escapedUrl = + "file://" + + filePath + .replace(/\\/g, "/") + .replace(/[^a-zA-Z0-9-._~:/?#[\]@!'()*+,;=%]/g, encodeURIComponent); + + if (process.platform === "win32") { exec( - `osascript -e 'set the clipboard to (POSIX file "${escapedOSA}")'`, + `powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Clipboard]::SetFileDropList(@('${escapedPs}'))"`, (err) => { - if (err) clipboard.writeText(text) - } - ) + if (err) clipboard.writeText(text); + }, + ); + } else if (process.platform === "darwin") { + exec(`osascript -e 'set the clipboard to (POSIX file "${escapedOsa}")'`, (err) => { + if (err) clipboard.writeText(text); + }); } else { - exec( - `xclip -selection clipboard -t text/uri-list <<< "${escapedURL}"`, - (err) => { - if (err) clipboard.writeText(text) - } - ) + exec(`xclip -selection clipboard -t text/uri-list <<< "${escapedUrl}"`, (err) => { + if (err) clipboard.writeText(text); + }); } }); - return win + return win; } -module.exports = { createDebuggerWindow } \ No newline at end of file +module.exports = { createDebuggerWindow }; diff --git a/helpers/debuggerWindow/index.css b/helpers/debuggerWindow/index.css index fd080f3..c13b509 100644 --- a/helpers/debuggerWindow/index.css +++ b/helpers/debuggerWindow/index.css @@ -27,12 +27,18 @@ body { background-color: #212121; } -p, h1, h2, h3, h4, h5, h6 { +p, +h1, +h2, +h3, +h4, +h5, +h6 { margin: 0; } .transparent { - opacity: .5; + opacity: 0.5; } .marking::after { @@ -80,8 +86,8 @@ p, h1, h2, h3, h4, h5, h6 { } important { - color: #3da4ff; - font-weight: 700; + color: #3da4ff; + font-weight: 700; } .commands { @@ -119,7 +125,9 @@ important { color: white; cursor: pointer; white-space: nowrap; - transition: background .15s, opacity .15s; + transition: + background 0.15s, + opacity 0.15s; display: flex; align-items: center; justify-content: center; @@ -128,7 +136,7 @@ important { background: #333333cc; } .commands button:active { - opacity: .7; + opacity: 0.7; } .commands .commands-suggest { @@ -141,7 +149,7 @@ important { font-size: 12px; display: flex; gap: 5px; - transition: .2s; + transition: 0.2s; overflow: hidden; overflow-x: auto; } @@ -156,7 +164,7 @@ important { padding: 5px 8px; width: fit-content; border-radius: 5px; - transition: .2s; + transition: 0.2s; white-space: nowrap; } .commands .commands-suggest .commands-suggest__item:hover { @@ -167,11 +175,11 @@ important { code { background: #222222; border-radius: 5px; - transition: .2s; + transition: 0.2s; } code:hover { cursor: pointer; - opacity: .5; + opacity: 0.5; } #main { @@ -179,4 +187,4 @@ code:hover { flex-direction: column; gap: 5px; padding-bottom: 80px; -} \ No newline at end of file +} diff --git a/helpers/debuggerWindow/index.js b/helpers/debuggerWindow/index.js index 75d9c2f..cff2bf4 100644 --- a/helpers/debuggerWindow/index.js +++ b/helpers/debuggerWindow/index.js @@ -1,42 +1,42 @@ -import { type, handleOnWheelScrollX } from "../../assets/js/lib.js" -import { parse, trimSpaces, createCommandRegex } from "./parse.js" +import { handleOnWheelScrollX, type } from "../../assets/js/lib.js"; +import { createCommandRegex, parse, trimSpaces } from "./parse.js"; -const main = document.querySelector("#main") -const commandInput = document.querySelector("#command") -const btnCopy = document.querySelector("#btn-copy") -const btnCopyFile = document.querySelector("#btn-copy-file") -const time = `[${formatTimeHTML(Date.now())}]` -window.electron.ready() +const main = document.querySelector("#main"); +const commandInput = document.querySelector("#command"); +const btnCopy = document.querySelector("#btn-copy"); +const btnCopyFile = document.querySelector("#btn-copy-file"); +const time = `[${formatTimeHtml(Date.now())}]`; +window.electron.ready(); -const modules = {} -let variables = {} -let logs = [] +const modules = {}; +const variables = {}; +let logs = []; function setVariable({ name, value, type }) { - type = type == undefined ? "default" : type - variables[name] = { value: value, type: type } + type = type == undefined ? "default" : type; + variables[name] = { value, type }; } function parseFontCommand(fontName) { if (fontName == "system") { - localStorage.setItem("font", fontName) - document.body.style.cssText = "font-family: monospace" + localStorage.setItem("font", fontName); + document.body.style.cssText = "font-family: monospace"; } if (fontName == "default") { - localStorage.setItem("font", fontName) - document.body.style.cssText = "" + localStorage.setItem("font", fontName); + document.body.style.cssText = ""; } } -if(localStorage.getItem("font") != null) { - parseFontCommand(localStorage.getItem("font")) +if (localStorage.getItem("font") != null) { + parseFontCommand(localStorage.getItem("font")); } function findMatches(text, values) { const query = text.toLowerCase(); return values - .map(value => { + .map((value) => { const v = value.toLowerCase(); let score = 0; @@ -44,7 +44,7 @@ function findMatches(text, values) { if (v.includes(query)) score += 10; let i = 0; - for (let char of v) { + for (const char of v) { if (char === query[i]) { i++; score++; @@ -53,226 +53,234 @@ function findMatches(text, values) { return { value, score }; }) - .filter(item => item.score > 0) + .filter((item) => item.score > 0) .sort((a, b) => b.score - a.score) - .map(item => item.value); + .map((item) => item.value); } const commands = { log: (text) => { - renderMsg(time, text) + renderMsg(time, text); }, - "print": (text) => { - commands.log(text) + print: (text) => { + commands.log(text); }, ">>": (text) => { - commands.log(text) + commands.log(text); }, ">!": (text) => { - commands.err(text) + commands.err(text); }, ">?": (text) => { - commands.warn(text) + commands.warn(text); }, warn: (text) => { - renderWarn(time, text) + renderWarn(time, text); }, err: (text) => { - renderError(time, text) + renderError(time, text); }, modules: () => { - renderMsg(time, `List of all installed modules: ${Object.keys(modules).join(", ")}`) + renderMsg(time, `List of all installed modules: ${Object.keys(modules).join(", ")}`); }, seslen: () => { - renderMsg(time, `Commands executed during the session: ${logs.length}`) + renderMsg(time, `Commands executed during the session: ${logs.length}`); }, clear: () => { - logs.forEach(i => { - i.remove() - }) - logs = [] + logs.forEach((i) => { + i.remove(); + }); + logs = []; }, "-m": (name) => { if (name in modules) { - renderMsg(time, `${name}@${modules[name].version} Module. ${modules[name].description}\nGet module version: -mv ${name}\nGet module permissions: -mp ${name}`) - } - else if (name.length == 0) { - renderError(time, `Argument 0:{name} is empty`) - } - else { - renderError(time, `Module "${name}" not defined in this scope. Defined modules: ${Object.keys(modules).join(", ")}`) + renderMsg( + time, + `${name}@${modules[name].version} Module. ${modules[name].description}\nGet module version: -mv ${name}\nGet module permissions: -mp ${name}`, + ); + } else if (name.length == 0) { + renderError(time, "Argument 0:{name} is empty"); + } else { + renderError( + time, + `Module "${name}" not defined in this scope. Defined modules: ${Object.keys(modules).join(", ")}`, + ); } }, "-mv": (name) => { if (name in modules) { - renderMsg(time, modules[name].version) - } - else if (name.length == 0) { - renderError(time, `Argument 0:{name} is empty`) - } - else { - renderError(time, `Module "${name}" not defined in this scope`) + renderMsg(time, modules[name].version); + } else if (name.length == 0) { + renderError(time, "Argument 0:{name} is empty"); + } else { + renderError(time, `Module "${name}" not defined in this scope`); } }, "-mp": (name) => { if (name in modules) { - renderMsg(time, modules[name].permissions.join(", ")) - } - else if (name.length == 0) { - renderError(time, `Argument 0:{name} is empty`) - } - else { - renderError(time, `Module "${name}" not defined in this scope`) + renderMsg(time, modules[name].permissions.join(", ")); + } else if (name.length == 0) { + renderError(time, "Argument 0:{name} is empty"); + } else { + renderError(time, `Module "${name}" not defined in this scope`); } }, font: (name) => { - const fonts = ["system", "default"] - - if(name.length == 0) { - renderMsg(time, `Aviable fonts: ${fonts.join(", ")}. Current: ${localStorage.getItem("font") != null ? localStorage.getItem("font") : "default"}`) - } - else if(fonts.includes(name)) { - parseFontCommand(name) + const fonts = ["system", "default"]; + + if (name.length == 0) { + renderMsg( + time, + `Aviable fonts: ${fonts.join(", ")}. Current: ${localStorage.getItem("font") == null ? "default" : localStorage.getItem("font")}`, + ); + } else if (fonts.includes(name)) { + parseFontCommand(name); } }, fetch: async (url) => { - if(url.startsWith("http")) { - let f = await fetch(url) - let result = await f.text() + if (url.startsWith("http")) { + const f = await fetch(url); + const result = await f.text(); try { - let parsed = JSON.parse(result) - renderMsg(time, JSON.stringify(parsed)) - } - catch(e) { - renderError(time, `JSON parse error: ${e}`) + const parsed = JSON.parse(result); + renderMsg(time, JSON.stringify(parsed)); + } catch (e) { + renderError(time, `JSON parse error: ${e}`); } - } - else { - renderError(time, `The fetch command accepts only URLs. \nExample: fetch https://`) + } else { + renderError( + time, + "The fetch command accepts only URLs. \nExample: fetch https://", + ); } }, var: (name) => { - variables[name] = { value: false } + variables[name] = { value: false }; }, vars: () => { - renderMsg(time, Object.keys(variables).map(item => `$${item}`).join(", ")) + renderMsg( + time, + Object.keys(variables) + .map((item) => `$${item}`) + .join(", "), + ); }, exit: () => { - window.electron.close() - } -} + window.electron.close(); + }, +}; function parseCommand(command, silent = false) { setTimeout(() => { - window.scrollTo(0, document.body.scrollHeight) - }, 0) + window.scrollTo(0, document.body.scrollHeight); + }, 0); - const time = `[${formatTimeHTML(Date.now())}]` - const response = document.createElement("div") - response.classList.add("debug-item", "transparent") - if(!silent) response.textContent = `>> ${command}` + const time = `[${formatTimeHtml(Date.now())}]`; + const response = document.createElement("div"); + response.classList.add("debug-item", "transparent"); + if (!silent) response.textContent = `>> ${command}`; command = command.replace(/\$([a-zA-Z0-9_]+)/g, (match, varName) => { - if(varName in variables) { - return variables[varName].value + if (varName in variables) { + return variables[varName].value; } - return undefined - }) + }); command = command.replace(createCommandRegex("type"), (match, value) => { - value = trimSpaces(value) - if(value.startsWith("$")) { - value = value.replace("$", "") - if(value in variables) { - return type(variables[value].value) + value = trimSpaces(value); + if (value.startsWith("$")) { + value = value.replace("$", ""); + if (value in variables) { + return type(variables[value].value); } } - return type(value) - }) + return type(value); + }); command = command.replace(createCommandRegex("str"), (match, value) => { - value = trimSpaces(value) + value = trimSpaces(value); - return value.trim() - }) + return value.trim(); + }); command = command.replace(createCommandRegex("empty"), (match, value) => { - value = trimSpaces(value) - return value.length == 0 - }) + value = trimSpaces(value); + return value.length == 0; + }); command = command.replace(createCommandRegex("len"), (match, value) => { - value = trimSpaces(value) - return value.length - }) + value = trimSpaces(value); + return value.length; + }); command = command.replace(createCommandRegex("rand"), (match, value) => { - value = trimSpaces(value) - let min = 0 - let max = 999999 + value = trimSpaces(value); + let min = 0; + let max = 999_999; if (value) { - let splitted = value.split(",") + const splitted = value.split(","); - if (splitted[0]) min = Number(splitted[0].trim()) - if (splitted[1]) max = Number(splitted[1].trim()) + if (splitted[0]) min = Number(splitted[0].trim()); + if (splitted[1]) max = Number(splitted[1].trim()); } - if (isNaN(min)) min = 0 - if (isNaN(max)) max = 999999 + if (isNaN(min)) min = 0; + if (isNaN(max)) max = 999_999; - if (min > max) [min, max] = [max, min] + if (min > max) [min, max] = [max, min]; - return Math.floor(Math.random() * (max - min + 1)) + min - }) + return Math.floor(Math.random() * (max - min + 1)) + min; + }); command = command.replace(createCommandRegex("time"), (match, value) => { - value = trimSpaces(value) - const now = new Date() - const pad = (num) => String(num).padStart(2, "0") + value = trimSpaces(value); + const now = new Date(); + const pad = (num) => String(num).padStart(2, "0"); const map = { - "dd": pad(now.getDate()), - "d": now.getDate(), + dd: pad(now.getDate()), + d: now.getDate(), - "mm": pad(now.getMonth() + 1), - "m": now.getMonth() + 1, + mm: pad(now.getMonth() + 1), + m: now.getMonth() + 1, - "yyyy": now.getFullYear(), - "yy": String(now.getFullYear()).slice(-2), + yyyy: now.getFullYear(), + yy: String(now.getFullYear()).slice(-2), - "hh": pad(now.getHours()), - "h": now.getHours(), + hh: pad(now.getHours()), + h: now.getHours(), - "ii": pad(now.getMinutes()), - "i": now.getMinutes() - } + ii: pad(now.getMinutes()), + i: now.getMinutes(), + }; if (value.length === 0) { - return `${map.dd}.${map.mm}.${map.yyyy}, ${map.hh}:${map.ii}` + return `${map.dd}.${map.mm}.${map.yyyy}, ${map.hh}:${map.ii}`; } - let result = value - const tokens = Object.keys(map).sort((a, b) => b.length - a.length) + let result = value; + const tokens = Object.keys(map).sort((a, b) => b.length - a.length); for (const token of tokens) { - result = result.replace(new RegExp(token, "g"), map[token]) + result = result.replace(new RegExp(token, "g"), map[token]); } - return result - }) - - Object.keys(variables).forEach(v => { - commands[`set:${v}`] = (value) => { - if(variables[v].type != "const") { - setVariable({ name: v, value: value, type: "default" }) + return result; + }); + + Object.keys(variables).forEach((v) => { + commands[`set:${v}`] = (value) => { + if (variables[v].type == "const") { + renderError( + time, + `Error in the declaration of the variable "${v}": the variable is a constant`, + ); + } else { + setVariable({ name: v, value, type: "default" }); } - else { - renderError(time, `Error in the declaration of the variable "${v}": the variable is a constant`) - } - - } - }) + }; + }); - main.appendChild(response) + main.appendChild(response); - logs.push(response) + logs.push(response); commands["-c"] = () => { const commandList = Object.entries(commands).map(([name, fn]) => { @@ -283,186 +291,188 @@ function parseCommand(command, silent = false) { renderMsg(time, `Commands: \n${commandList.join("\n")}`); }; - command.split(";").map(item => item.trim()).forEach(i => { - executeCommand(i) - }) + command + .split(";") + .map((item) => item.trim()) + .forEach((i) => { + executeCommand(i); + }); function executeCommand(command) { - const splitted = command.split(/\s/g) - const prefix = splitted[0] + const splitted = command.split(/\s/g); + const prefix = splitted[0]; if (prefix in commands) { - return commands[prefix](splitted.filter(item => item != prefix).join(" ")) + return commands[prefix](splitted.filter((item) => item != prefix).join(" ")); } - else { - let error = `Command "${prefix}" doesn't exists` - renderError(time, error) + const error = `Command "${prefix}" doesn't exists`; + renderError(time, error); - return error - } + return error; } - main.querySelectorAll("code").forEach(el => { + main.querySelectorAll("code").forEach((el) => { el.addEventListener("click", (e) => { - commandInput.value = e.target.textContent - }) - }) + commandInput.value = e.target.textContent; + }); + }); // set variables - setVariable({ name: "seslen", value: logs.length, type: "const" }) + setVariable({ name: "seslen", value: logs.length, type: "const" }); } -function formatTimeHTML(timestampMs) { - const date = new Date(timestampMs) +function formatTimeHtml(timestampMs) { + const date = new Date(timestampMs); - const h = String(date.getHours()).padStart(2, "0") - const m = String(date.getMinutes()).padStart(2, "0") - const s = String(date.getSeconds()).padStart(2, "0") + const h = String(date.getHours()).padStart(2, "0"); + const m = String(date.getMinutes()).padStart(2, "0"); + const s = String(date.getSeconds()).padStart(2, "0"); - return `${h}h:${m}m:${s}s` + return `${h}h:${m}m:${s}s`; } function renderMsg(time, content, from = false) { - const item = document.createElement("div") - item.classList.add("debug-item") - item.innerHTML = `${from != false ? `${from}` : ""}
${time}
${parse(content)}
` + const item = document.createElement("div"); + item.classList.add("debug-item"); + item.innerHTML = `${from == false ? "" : `${from}`}
${time}
${parse(content)}
`; - if (from != false) item.classList.add("foreign") + if (from != false) item.classList.add("foreign"); - main.appendChild(item) + main.appendChild(item); - logs.push(item) + logs.push(item); } function renderError(time, content, from = false) { - const item = document.createElement("div") - item.classList.add("debug-item", "error") - item.innerHTML = `${from != false ? `${from}` : ""}
${time}
${parse(content)}
` + const item = document.createElement("div"); + item.classList.add("debug-item", "error"); + item.innerHTML = `${from == false ? "" : `${from}`}
${time}
${parse(content)}
`; - if (from != false) item.classList.add("foreign") + if (from != false) item.classList.add("foreign"); - main.appendChild(item) + main.appendChild(item); - logs.push(item) + logs.push(item); } function renderWarn(time, content, from = false) { - const item = document.createElement("div") - item.classList.add("debug-item", "warn") - item.innerHTML = `${from != false ? `${from}` : ""}
${time}
${parse(content)}
` + const item = document.createElement("div"); + item.classList.add("debug-item", "warn"); + item.innerHTML = `${from == false ? "" : `${from}`}
${time}
${parse(content)}
`; - if (from != false) item.classList.add("foreign") + if (from != false) item.classList.add("foreign"); - main.appendChild(item) + main.appendChild(item); - logs.push(item) + logs.push(item); } function renderMarking() { - const item = document.createElement("div") - item.classList.add("marking") + const item = document.createElement("div"); + item.classList.add("marking"); - main.appendChild(item) + main.appendChild(item); - logs.push(item) + logs.push(item); } window.electron.onDebugData((data) => { - let type = data.data.type - let time = `[${formatTimeHTML(data.time)}]` + const type = data.data.type; + const time = `[${formatTimeHtml(data.time)}]`; if (type == "msg") { - renderMsg(time, data.data.content, data.data.from) + renderMsg(time, data.data.content, data.data.from); } if (type == "error") { - renderError(time, `❌ ${data.data.content}`, data.data.from) + renderError(time, `❌ ${data.data.content}`, data.data.from); } if (type == "warn") { - renderWarn(time, `⚠️ ${data.data.content}`, data.data.from) + renderWarn(time, `⚠️ ${data.data.content}`, data.data.from); } if (type == "marking") { - renderMarking() + renderMarking(); } if (type == "moduleInfo") { - let module = data.data.info + const module = data.data.info; modules[module.name] = { version: module.version, description: module.description, - permissions: module.permissions - } + permissions: module.permissions, + }; } if (type == "newCommand") { - const time = `[${formatTimeHTML(Date.now())}]` - let command = data.data.command + const time = `[${formatTimeHtml(Date.now())}]`; + const command = data.data.command; - renderMsg(time, `Added new command: ${command.name}`, data.data.from) + renderMsg(time, `Added new command: ${command.name}`, data.data.from); commands[command.name] = () => { - renderMsg(time, command.response) - } + renderMsg(time, command.response); + }; } if (type == "execCommand") { - let command = data.data.command - parseCommand(command, true) + const command = data.data.command; + parseCommand(command, true); } -}) +}); -commandInput.addEventListener("keydown", function (event) { +commandInput.addEventListener("keydown", (event) => { if (event.key === "Enter") { event.preventDefault(); - parseCommand(event.target.value) - document.querySelector(".commands-suggest").classList.add("hidden") - event.target.value = "" + parseCommand(event.target.value); + document.querySelector(".commands-suggest").classList.add("hidden"); + event.target.value = ""; } }); commandInput.addEventListener("input", (event) => { - handleOnWheelScrollX() + handleOnWheelScrollX(); - let text = event.target.value - let finder = findMatches(text, Object.keys(commands)) + const text = event.target.value; + const finder = findMatches(text, Object.keys(commands)); - let suggest = document.querySelector(".commands-suggest") - suggest.innerHTML = "" + const suggest = document.querySelector(".commands-suggest"); + suggest.innerHTML = ""; - if(text.length == 0 || finder.length == 0) { - suggest.classList.add("hidden") - } - else if(finder.includes(text)) { - suggest.classList.add("hidden") - } - else { - suggest.classList.remove("hidden") - finder.forEach(item => { - const suggestItem = document.createElement("div") - suggestItem.classList.add("commands-suggest__item") - suggestItem.textContent = item + if (text.length == 0 || finder.length == 0) { + suggest.classList.add("hidden"); + } else if (finder.includes(text)) { + suggest.classList.add("hidden"); + } else { + suggest.classList.remove("hidden"); + finder.forEach((item) => { + const suggestItem = document.createElement("div"); + suggestItem.classList.add("commands-suggest__item"); + suggestItem.textContent = item; - suggest.appendChild(suggestItem) + suggest.appendChild(suggestItem); suggestItem.addEventListener("click", () => { - event.target.value = item - event.target.focus() - suggest.classList.add("hidden") - }) - }) + event.target.value = item; + event.target.focus(); + suggest.classList.add("hidden"); + }); + }); } -}) +}); function getAllDebugLines() { - const items = main.querySelectorAll(".debug-item") - return Array.from(items).map(el => el.textContent.trim()).filter(t => t.length > 0).join("\n") + const items = main.querySelectorAll(".debug-item"); + return Array.from(items) + .map((el) => el.textContent.trim()) + .filter((t) => t.length > 0) + .join("\n"); } btnCopy.addEventListener("click", () => { - const text = getAllDebugLines() + const text = getAllDebugLines(); if (text.length > 0) { - window.electron.copyText(text) + window.electron.copyText(text); } -}) +}); btnCopyFile.addEventListener("click", () => { - const text = getAllDebugLines() + const text = getAllDebugLines(); if (text.length > 0) { - window.electron.copyAsFile(text) + window.electron.copyAsFile(text); } -}) \ No newline at end of file +}); diff --git a/helpers/debuggerWindow/parse.css b/helpers/debuggerWindow/parse.css index 113ffc2..9034a92 100644 --- a/helpers/debuggerWindow/parse.css +++ b/helpers/debuggerWindow/parse.css @@ -1,4 +1,5 @@ -.parse-boolean, .parse-number { +.parse-boolean, +.parse-number { color: #ae6eff; } .parse-string { @@ -7,10 +8,11 @@ .parse-string { color: #ffffff; } -.parse-null, .parse-undefined { +.parse-null, +.parse-undefined { color: gray; } .json { font-size: 14px; -} \ No newline at end of file +} diff --git a/helpers/debuggerWindow/parse.js b/helpers/debuggerWindow/parse.js index c3e0c48..1b109c8 100644 --- a/helpers/debuggerWindow/parse.js +++ b/helpers/debuggerWindow/parse.js @@ -1,47 +1,45 @@ -import { parseTwemojiString } from "../../assets/js/lib.js" +import { parseTwemojiString } from "../../assets/js/lib.js"; -const BOOLEAN_RE = /\b(true|false)\b/g -const NUMBER_RE = /(?$1`) .replace(NULL_RE, `null`) .replace(UNDEFINED_RE, `undefined`) - .replace(NUMBER_RE, `$&`) + .replace(NUMBER_RE, `$&`); - content = parseTwemojiString(content) + content = parseTwemojiString(content); - return pretifyJSON(content) + return pretifyJson(content); } export function trimSpaces(value) { - return value.replaceAll("%%", " ") + return value.replaceAll("%%", " "); } -function pretifyJSON(input) { +function pretifyJson(input) { if (typeof input !== "string") input = String(input); const match = input.match(/\{[\s\S]*\}/); if (!match) return input; - let jsonStr = match[0]; + const jsonStr = match[0]; try { const obj = JSON.parse(jsonStr); @@ -60,7 +58,7 @@ function pretifyJSON(input) { } export function createCommandRegex(command) { - const safeCommand = command.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + const safeCommand = command.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - return new RegExp(`\\b${safeCommand}\\{([^}]*)\\}`, "g") -} \ No newline at end of file + return new RegExp(`\\b${safeCommand}\\{([^}]*)\\}`, "g"); +} diff --git a/helpers/debuggerWindow/preload.js b/helpers/debuggerWindow/preload.js index c9fa2ef..9a0ed1d 100644 --- a/helpers/debuggerWindow/preload.js +++ b/helpers/debuggerWindow/preload.js @@ -1,10 +1,11 @@ -const { contextBridge, ipcRenderer } = require('electron'); +const { contextBridge, ipcRenderer } = require("electron"); -contextBridge.exposeInMainWorld('electron', { +contextBridge.exposeInMainWorld("electron", { ready: () => ipcRenderer.send("debugger-ready"), close: () => ipcRenderer.send("close-window"), onDebugData: (callback) => ipcRenderer.on("debug-event", (_, data) => callback(data)), - runExtension: (code, permissions, meta) => ipcRenderer.invoke("run-extension", code, permissions, meta), + runExtension: (code, permissions, meta) => + ipcRenderer.invoke("run-extension", code, permissions, meta), copyText: (text) => ipcRenderer.send("debugger-copy-text", text), - copyAsFile: (text) => ipcRenderer.send("debugger-copy-as-file", text) -}); \ No newline at end of file + copyAsFile: (text) => ipcRenderer.send("debugger-copy-as-file", text), +}); diff --git a/helpers/eventBus.js b/helpers/eventBus.js index 95af37d..293c387 100644 --- a/helpers/eventBus.js +++ b/helpers/eventBus.js @@ -1,4 +1,4 @@ const { EventEmitter } = require("events"); const bus = new EventEmitter(); -module.exports = bus; \ No newline at end of file +module.exports = bus; diff --git a/helpers/getPython.js b/helpers/getPython.js index 21b9f47..dcb6ff3 100644 --- a/helpers/getPython.js +++ b/helpers/getPython.js @@ -9,36 +9,36 @@ function getPythonInfo() { for (const cmd of commands) { exec(`${cmd} --version`, (err, stdout, stderr) => { - if (!err) { - const versionOutput = stdout || stderr; - - exec(process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`, (err2, stdout2) => { - if (!err2) { - resolve({ - version: versionOutput.replace("Python", "").trim(), - path: stdout2.split("\n")[0].trim(), - command: cmd - }); - } else { - resolve({ - version: versionOutput.replace("Python", "").trim(), - path: null, - command: cmd - }); - } - }); - - } else { + if (err) { checked++; if (checked === commands.length) { resolve(false); } + } else { + const versionOutput = stdout || stderr; + + exec( + process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`, + (err2, stdout2) => { + if (err2) { + resolve({ + version: versionOutput.replace("Python", "").trim(), + path: null, + command: cmd, + }); + } else { + resolve({ + version: versionOutput.replace("Python", "").trim(), + path: stdout2.split("\n")[0].trim(), + command: cmd, + }); + } + }, + ); } }); } }); } -ipcMain.handle("get-python-info", async (event) => { - return await getPythonInfo() -}) \ No newline at end of file +ipcMain.handle("get-python-info", async (event) => await getPythonInfo()); diff --git a/helpers/minify.js b/helpers/minify.js index e637072..7dc007f 100644 --- a/helpers/minify.js +++ b/helpers/minify.js @@ -1,10 +1,10 @@ -function basicMinifyCSS(cssCode) { - cssCode = cssCode.replace(/\/\*[\s\S]*?\*\//g, ''); - cssCode = cssCode.replace(/(\r\n|\n|\r)/gm, ''); - cssCode = cssCode.replace(/\s+/g, ' '); - cssCode = cssCode.replace(/\s*([{};:])\s*/g, '$1'); - cssCode = cssCode.replace(/;}/g, '}'); +function basicMinifyCss(cssCode) { + cssCode = cssCode.replace(/\/\*[\s\S]*?\*\//g, ""); + cssCode = cssCode.replace(/(\r\n|\n|\r)/gm, ""); + cssCode = cssCode.replace(/\s+/g, " "); + cssCode = cssCode.replace(/\s*([{};:])\s*/g, "$1"); + cssCode = cssCode.replace(/;}/g, "}"); return cssCode.trim(); } -module.exports = { basicMinifyCSS } \ No newline at end of file +module.exports = { basicMinifyCSS: basicMinifyCss }; diff --git a/languages/be.json b/languages/be.json index 13a7c34..72664fe 100644 --- a/languages/be.json +++ b/languages/be.json @@ -433,4 +433,4 @@ "high": "Высокі прыярытэт" } } -} \ No newline at end of file +} diff --git a/languages/en.json b/languages/en.json index bfe1d73..b995099 100644 --- a/languages/en.json +++ b/languages/en.json @@ -531,4 +531,4 @@ "high": "High priority" } } -} \ No newline at end of file +} diff --git a/languages/pl.json b/languages/pl.json index fdbb7d9..b2c0903 100644 --- a/languages/pl.json +++ b/languages/pl.json @@ -433,4 +433,4 @@ "high": "Wysoki priorytet" } } -} \ No newline at end of file +} diff --git a/languages/ru.json b/languages/ru.json index 2a6b657..aee7ebc 100644 --- a/languages/ru.json +++ b/languages/ru.json @@ -434,4 +434,4 @@ "high": "Высокий приоритет" } } -} \ No newline at end of file +} diff --git a/languages/uk.json b/languages/uk.json index 1193386..10b5122 100644 --- a/languages/uk.json +++ b/languages/uk.json @@ -15,7 +15,7 @@ "offlineBtn": "Увійти без облікового запису", "offlineMode": "Офлайн режим" }, - + "auth": { "register": { "title": "Реєстрація", @@ -430,4 +430,4 @@ "high": "Високий пріоритет" } } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 8a2d8bf..5753c21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "ws": "^8.19.0" }, "devDependencies": { + "@biomejs/biome": "2.5.6", "@types/electron": "^1.4.38", "@types/node": "^25.9.1", "electron": "^39.2.3", @@ -77,6 +78,181 @@ "node": ">=6.9.0" } }, + "node_modules/@biomejs/biome": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.6.tgz", + "integrity": "sha512-lxVNjv7UF6KfhMJfL9gaUHbWdJdHbsAj6OSmwSYNdhRuG67NxNQ4Xdvh3TUxsSK9sBzJBQhEJj3AopmmNJ5pSA==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.5.6", + "@biomejs/cli-darwin-x64": "2.5.6", + "@biomejs/cli-linux-arm64": "2.5.6", + "@biomejs/cli-linux-arm64-musl": "2.5.6", + "@biomejs/cli-linux-x64": "2.5.6", + "@biomejs/cli-linux-x64-musl": "2.5.6", + "@biomejs/cli-win32-arm64": "2.5.6", + "@biomejs/cli-win32-x64": "2.5.6" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-zMOLZP4oMrjh6m1zcSj1ud2awUPgTuMVbmQhYYWL7J8HwCnbHHBvTm7VBTRuY7epT5bez76IpKYQ11ZAqHFlnw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.6.tgz", + "integrity": "sha512-JAC1VqzvO7Th5ZplU0G2uGfkZbxEe9uDDektPAhF0JLusoz1w+T4okp2bkykI0bbaO2vslKiRfj4gU43JaGreA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.6.tgz", + "integrity": "sha512-6XsYwCFkp5sMxl85ffhgeGpGgs6A7dRYFnkceZ7WVxvycuTnGdD5xa534Z3xfrBQ0JCMK/mujT6ZNPJoghedwg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-eUa3jeeYvfMt19LBeh6E5PUZpxnTC4JqNWo+EDjTtQjAr2xLGnWaxACtVU1DQqmHYbvThlJzLX+ZsYgrqh2qVw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.6.tgz", + "integrity": "sha512-Pop9VXCFUhFTMfFefZ39S+u2rOPyNp5iHlxbZRwXGACHLy2r0jjiRgJHmaEKJzL3SyxlVeGShXhvvElvWowonA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-2Vp13QdKysH3HIWLaYLhUUwbK+jbZonJD1K+Lr0d0RO4wH7mkYd43vJixEDm8cUWrowoRz4UUHF1nm9Ae7ym8A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.6.tgz", + "integrity": "sha512-tDGshcm6BdkZOCGnTDX0Y8/U4IfBSlnUU7T56nNDuPEfed+aHg+u8G36NB43fJVl0Os6+QURXIE1yuD7AaEofA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.6.tgz", + "integrity": "sha512-WN05KwXnTO/2J45RQPvzZMXf7tZUIofHoR35xIPfCo7pQ2RFidxI8sfb5mGsaTxdMmEOzHzOPRCdA5/fCpc7xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@electron/asar": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", diff --git a/package.json b/package.json index c8ebed3..bc36f8d 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,11 @@ "build": "tsc && tsc -p tsconfig.esm.json", "test": "node --test tests/unit/*.test.mjs", "cdbuild": "cd codemirror && npm i && npm run build", + "check": "biome check .", + "check:fix": "biome check --write .", + "format": "biome format --write .", + "format:check": "biome format .", + "lint": "biome lint .", "start": "npm run cdbuild && npm run build && electron .", "dist": "npm run cdbuild && npm run build && electron-builder", "dist-linux": "npm run cdbuild && npm run build && electron-builder --linux" @@ -45,6 +50,7 @@ } }, "devDependencies": { + "@biomejs/biome": "2.5.6", "@types/electron": "^1.4.38", "@types/node": "^25.9.1", "electron": "^39.2.3", diff --git a/tests/helpers/debuggerEscape.test.js b/tests/helpers/debuggerEscape.test.js index a42acce..e43930d 100644 --- a/tests/helpers/debuggerEscape.test.js +++ b/tests/helpers/debuggerEscape.test.js @@ -1,95 +1,104 @@ -import { describe, it, expect } from "vitest" +import { describe, expect, it } from "vitest"; -function escapePS(filePath) { - return filePath.replace(/'/g, "''") +function escapePs(filePath) { + return filePath.replace(/'/g, "''"); } -function escapeOSA(filePath) { - return filePath.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\$/g, "\\$").replace(/`/g, "\\`") +function escapeOsa(filePath) { + return filePath + .replace(/\\/g, "\\\\") + .replace(/"/g, '\\"') + .replace(/\$/g, "\\$") + .replace(/`/g, "\\`"); } -function escapeURL(filePath) { - return "file://" + filePath.replace(/\\/g, "/").replace(/[^a-zA-Z0-9-._~:/?#\[\]@!'()*+,;=%]/g, encodeURIComponent) +function escapeUrl(filePath) { + return ( + "file://" + + filePath + .replace(/\\/g, "/") + .replace(/[^a-zA-Z0-9-._~:/?#[\]@!'()*+,;=%]/g, encodeURIComponent) + ); } describe("debugger copy-as-file escaping", () => { - const normalPath = "/tmp/Debugger-cdmtn-20260723_143022.txt" + const normalPath = "/tmp/Debugger-cdmtn-20260723_143022.txt"; describe("PowerShell escaping", () => { it("handles normal path", () => { - expect(escapePS(normalPath)).toBe(normalPath) - }) + expect(escapePs(normalPath)).toBe(normalPath); + }); it("escapes single quotes", () => { - expect(escapePS("/tmp/test'file.txt")).toBe("/tmp/test''file.txt") - }) + expect(escapePs("/tmp/test'file.txt")).toBe("/tmp/test''file.txt"); + }); it("escapes multiple single quotes", () => { - expect(escapePS("it's a 'file'.txt")).toBe("it''s a ''file''.txt") - }) + expect(escapePs("it's a 'file'.txt")).toBe("it''s a ''file''.txt"); + }); it("leaves double quotes alone", () => { - expect(escapePS('/tmp/test"file.txt')).toBe('/tmp/test"file.txt') - }) - }) + expect(escapePs('/tmp/test"file.txt')).toBe('/tmp/test"file.txt'); + }); + }); describe("osascript escaping", () => { it("handles normal path", () => { - expect(escapeOSA(normalPath)).toBe(normalPath) - }) + expect(escapeOsa(normalPath)).toBe(normalPath); + }); it("escapes double quotes", () => { - expect(escapeOSA('/tmp/test"file.txt')).toBe('/tmp/test\\"file.txt') - }) + expect(escapeOsa('/tmp/test"file.txt')).toBe('/tmp/test\\"file.txt'); + }); it("escapes backslashes", () => { - expect(escapeOSA("C:\\Users\\test\\file.txt")).toBe("C:\\\\Users\\\\test\\\\file.txt") - }) + expect(escapeOsa("C:\\Users\\test\\file.txt")).toBe("C:\\\\Users\\\\test\\\\file.txt"); + }); it("escapes both backslashes and double quotes", () => { - expect(escapeOSA('C:\\Users\\test"file.txt')).toBe('C:\\\\Users\\\\test\\"file.txt') - }) + expect(escapeOsa('C:\\Users\\test"file.txt')).toBe('C:\\\\Users\\\\test\\"file.txt'); + }); it("blocks $(cmd) injection", () => { - const injected = '/tmp/$(rm -rf /)/file.txt' - const escaped = escapeOSA(injected) - expect(escaped).toContain("\\$(") - }) + const injected = "/tmp/$(rm -rf /)/file.txt"; + const escaped = escapeOsa(injected); + expect(escaped).toContain("\\$("); + }); it("blocks backtick injection", () => { - const injected = '/tmp/`whoami`/file.txt' - const escaped = escapeOSA(injected) - expect(escaped).toContain("\\`whoami\\`") - }) - }) + const injected = "/tmp/`whoami`/file.txt"; + const escaped = escapeOsa(injected); + expect(escaped).toContain("\\`whoami\\`"); + }); + }); describe("URL escaping", () => { it("handles normal path", () => { - expect(escapeURL(normalPath)).toBe("file://" + normalPath) - }) + expect(escapeUrl(normalPath)).toBe("file://" + normalPath); + }); it("encodes spaces", () => { - expect(escapeURL("/tmp/my file.txt")).toBe("file:///tmp/my%20file.txt") - }) + expect(escapeUrl("/tmp/my file.txt")).toBe("file:///tmp/my%20file.txt"); + }); it("encodes special characters", () => { - expect(escapeURL("/tmp/test&file.txt")).toBe("file:///tmp/test%26file.txt") - }) + expect(escapeUrl("/tmp/test&file.txt")).toBe("file:///tmp/test%26file.txt"); + }); it("encodes shell metacharacters", () => { - const injected = "/tmp/$(rm -rf /)/file.txt" - const escaped = escapeURL(injected) - expect(escaped).toContain("%24(") - }) + const injected = "/tmp/$(rm -rf /)/file.txt"; + const escaped = escapeUrl(injected); + expect(escaped).toContain("%24("); + }); it("encodes backticks", () => { - const escaped = escapeURL("/tmp/`whoami`/file.txt") - expect(escaped).not.toContain("`") - expect(escaped).toContain("%60") - }) + const escaped = escapeUrl("/tmp/`whoami`/file.txt"); + expect(escaped).not.toContain("`"); + expect(escaped).toContain("%60"); + }); it("converts Windows backslashes to forward slashes", () => { - expect(escapeURL("C:\\Users\\test\\file.txt")).toBe("file://C:/Users/test/file.txt") - }) - }) -}) + expect(escapeUrl("C:\\Users\\test\\file.txt")).toBe("file://C:/Users/test/file.txt"); + }); + }); +}); diff --git a/tests/helpers/platform.test.js b/tests/helpers/platform.test.js index 972310f..e7c6c23 100644 --- a/tests/helpers/platform.test.js +++ b/tests/helpers/platform.test.js @@ -1,10 +1,11 @@ -import { describe, it, expect } from "vitest" -import fs from "fs" -import os from "os" +import process from "node:process"; +import fs from "fs"; +import os from "os"; +import { describe, expect, it } from "vitest"; function detectShell() { - if (process.platform === 'win32') { - return 'cmd.exe'; + if (process.platform === "win32") { + return "cmd.exe"; } const userShell = process.env.SHELL; @@ -13,68 +14,68 @@ function detectShell() { return userShell; } - for (const shell of ['/bin/zsh', '/bin/bash', '/bin/sh']) { + for (const shell of ["/bin/zsh", "/bin/bash", "/bin/sh"]) { if (fs.existsSync(shell)) { return shell; } } - return '/bin/sh'; + return "/bin/sh"; } function getPythonBinary() { - return process.platform === 'win32' ? 'python.exe' : 'python3' + return process.platform === "win32" ? "python.exe" : "python3"; } function getFallbackCommand() { - return process.platform === 'win32' ? 'py' : 'python3' + return process.platform === "win32" ? "py" : "python3"; } describe("detectShell", () => { it("returns a string", () => { - expect(typeof detectShell()).toBe("string") - }) + expect(typeof detectShell()).toBe("string"); + }); it("returns a valid shell path", () => { - const shell = detectShell() - expect(shell).toBeTruthy() - expect(typeof shell).toBe("string") - }) + const shell = detectShell(); + expect(shell).toBeTruthy(); + expect(typeof shell).toBe("string"); + }); it("does not return /bin/bash on macOS when zsh is default", () => { - if (process.platform === 'darwin') { - const shell = detectShell() - expect(shell).not.toBe("/bin/bash") + if (process.platform === "darwin") { + const shell = detectShell(); + expect(shell).not.toBe("/bin/bash"); } - }) + }); it("returns cmd.exe on Windows", () => { - if (process.platform === 'win32') { - expect(detectShell()).toBe("cmd.exe") + if (process.platform === "win32") { + expect(detectShell()).toBe("cmd.exe"); } - }) -}) + }); +}); describe("getPythonBinary", () => { it("returns correct binary for current platform", () => { - const binary = getPythonBinary() + const binary = getPythonBinary(); - if (process.platform === 'win32') { - expect(binary).toBe("python.exe") + if (process.platform === "win32") { + expect(binary).toBe("python.exe"); } else { - expect(binary).toBe("python3") + expect(binary).toBe("python3"); } - }) -}) + }); +}); describe("getFallbackCommand", () => { it("returns correct fallback for current platform", () => { - const fallback = getFallbackCommand() + const fallback = getFallbackCommand(); - if (process.platform === 'win32') { - expect(fallback).toBe("py") + if (process.platform === "win32") { + expect(fallback).toBe("py"); } else { - expect(fallback).toBe("python3") + expect(fallback).toBe("python3"); } - }) -}) + }); +}); diff --git a/tsconfig.esm.json b/tsconfig.esm.json index d6b73b9..a56adc1 100644 --- a/tsconfig.esm.json +++ b/tsconfig.esm.json @@ -4,7 +4,5 @@ "module": "ES2022", "outDir": "app/dist-esm" }, - "include": [ - "app/main/textmate/compile.ts" - ] -} \ No newline at end of file + "include": ["app/main/textmate/compile.ts"] +} diff --git a/tsconfig.json b/tsconfig.json index ef54085..572119f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,19 +6,11 @@ "rootDir": "app/main", "strict": true, "types": ["node", "electron"], - "lib": [ - "ES2022" - ], + "lib": ["ES2022"], "esModuleInterop": true, "skipLibCheck": true, "allowJs": true }, "include": ["app/main/**/*", "assets/js/editor/colorComments.js", "textmate/**/*"], - "exclude": [ - "ace/**/*", - "assets/**/*", - "helpers/**/*", - "node_modules", - "dist" - ] -} \ No newline at end of file + "exclude": ["ace/**/*", "assets/**/*", "helpers/**/*", "node_modules", "dist"] +}