From 8a2b45099a2940ab0340307b8dc3bb5b11138504 Mon Sep 17 00:00:00 2001 From: Asad Date: Sat, 18 Jan 2025 12:20:03 -0500 Subject: [PATCH] bug: fixed slow syntax higlighting & readme fixed --- README.md | 35 ++++++++++++----------- public/app.js | 45 ++++++++++++++++++++---------- public/index.html | 13 ++++----- public/style.css | 71 ++++++++++++++++++++++++++++++++++++++++------- server.js | 2 +- 5 files changed, 115 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 42163e3..dea4f4f 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,36 @@ # [BinCode](jsbin.asadk.dev) - A Complete Self-Hostable JSFiddle Alternative ## Overview -BinCode is a minimalist platform for managing and sharing code snippets, built with Vue.js and SQLite. Unlike similar tools that depend on external services, BinCode runs entirely on your own infrastructure, giving you complete control over your data and workflow. +BinCode is a minimalist platform for managing and sharing code snippets, built with Vue.js and SQLite. It runs entirely on your own infrastructure, giving you full control over your data and workflow. + ## Key Features -- **Fully Self-Contained:** No external dependencies or services required -- **Modern Stack:** Built with Vue.js frontend and SQLite database -- **Secure Authentication:** Simple JWT-based user management -- **Instant Sharing:** Generate unique URLs for any code snippet -- **Minimal Setup:** Just create users manually and start sharing code -- **Performance Focused:** Lightweight design ensures fast operation +- **Self-Contained:** No external dependencies required. +- **Modern Stack:** Vue.js frontend and SQLite database. +- **JWT Authentication:** Secure, simple user management. +- **Instant Sharing:** Generate unique URLs for snippets. +- **Minimal Setup:** Create users manually to start sharing. +- **Performance-Focused:** Lightweight and fast. ## Architecture -- Frontend: Vue.js -- Database: SQLite -- Authentication: JWT -- Deployment: Single server, self-contained +- **Frontend:** Vue.js +- **Database:** SQLite +- **Authentication:** JWT +- **Deployment:** Single self-contained server. There is no signups its by design just create users manullay and they can start commits snippets to share ## Why BinCode? -During my search for open-source code sharing solutions, I found that most platforms required external services or had complex deployment requirements. I needed a straightforward, self-hostable tool that focused solely on creating and sharing code snippets. - -BinCode was built with simplicity in mind. While it may not have all the features of larger platforms, its lightweight nature makes it perfect for teams and individuals who need a reliable, easy-to-maintain solution for code sharing. - +BinCode is a lightweight, self-hostable tool for teams and individuals needing a simple, reliable solution for code sharing without relying on external services. ## Design Choices -- **No Signups:** User accounts are created manually by administrators to keep the system simple and secure -- **Self-Contained:** Everything runs on your infrastructure, ensuring data privacy and control +- **No Signups:** Admins manually create user accounts for simplicity and security. +- **Self-Hosted:** Ensures privacy and control over your data. + ## Contributing -While BinCode is intentionally minimal, contributions are always welcome! Feel free to add features that enhance its functionality while maintaining its lightweight nature. +Contributions are welcome, as long as the tool remains lightweight and self-contained. ## Getting Started diff --git a/public/app.js b/public/app.js index 5c1e122..191a10b 100644 --- a/public/app.js +++ b/public/app.js @@ -26,9 +26,13 @@ createApp({ // Tab state activeTab: 'html', tabs: [ - { id: 'html', label: 'HTML', icon: '📄', language: 'markup' }, - { id: 'css', label: 'CSS', icon: '🎨', language: 'css' }, - { id: 'js', label: 'JavaScript', icon: '⚡', language: 'javascript' } + { id: 'html', label: 'HTML', icon: '', language: 'markup' }, + { id: 'css', label: 'CSS', icon: '', language: 'css' }, + { id: 'js', label: 'JavaScript', icon: '', language: 'javascript' } + ], + extraIcons: [ + { visible: ``}, + { hidden: ``} ], highlightedCode: { html: '', @@ -41,6 +45,13 @@ createApp({ }, computed: { + displayCode() { + return { + html: this.highlightedCode.html || this.html, + css: this.highlightedCode.css || this.css, + js: this.highlightedCode.js || this.js + }; + }, currentCode: { get() { return this[this.activeTab]; @@ -77,7 +88,8 @@ createApp({ }, created() { - this.updatePreviewDebounced = this.debounce(this.updatePreview, 300); + this.highlightCodeDebounced = this.debounce(this.highlightCode, 50); + this.updatePreviewDebounced = this.debounce(this.updatePreview, 50); const urlParams = new URLSearchParams(window.location.search); const shareId = urlParams.get('share'); if (shareId) { @@ -121,17 +133,20 @@ createApp({ const language = languageMap[tab]; if (!language) return; - - try { - this.highlightedCode[tab] = Prism.highlight( - code || '', - Prism.languages[language], - language - ); - } catch (error) { - console.error('Highlighting error:', error); - this.highlightedCode[tab] = code || ''; - } + + // run highlighting in a requestAnimationFrame to avoid blocking the main thread + requestAnimationFrame(() => { + try { + this.highlightedCode[tab] = Prism.highlight( + code || '', + Prism.languages[language], + language + ); + } catch (error) { + console.error('Highlighting error:', error); + this.highlightedCode[tab] = code || ''; + } + }); }, handleKeydown(event) { if (event.key === 'Tab') { diff --git a/public/index.html b/public/index.html index 9762379..b3e3004 100644 --- a/public/index.html +++ b/public/index.html @@ -15,13 +15,15 @@
-
+
diff --git a/public/style.css b/public/style.css index f3d795c..1218b2f 100644 --- a/public/style.css +++ b/public/style.css @@ -11,6 +11,32 @@ --tab-active: #ffffff; --danger: #d73a49; --success: #28a745; + +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 4px; + height: 4px; +} + +::-webkit-scrollbar-track { + background: var(--background); + border-radius: 4px; +} + + +::-webkit-scrollbar-thumb { + background: var(--text-light); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(#cacaca); +} + +::-webkit-scrollbar-thumb:window-inactive { + background: var(--primary-light); } * { @@ -37,7 +63,7 @@ body { nav { background: var(--tab-bg); border-bottom: 1px solid var(--border); - padding: 0.75rem 1rem; + padding: 0.20rem 1rem; display: flex; align-items: center; gap: 1rem; @@ -136,7 +162,8 @@ nav { } .tab-icon { - font-size: 1.1em; + height: 18px; + width: 18px; line-height: 1; } @@ -450,7 +477,7 @@ form > button { display: flex; flex-direction: column; background: var(--background); - transition: all 0.3s ease; + transition: all 0.2s ease; width: 100%; } @@ -485,15 +512,38 @@ form > button { margin-left: 10px; } +.toggle-container { + display: flex; + flex-direction: row; +} + .toggle-icon { - background: transparent; - border-width: 1px; - border:rgba(0, 0, 0, 0.02); + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 8px; + background: none; + border: none; cursor: pointer; - font-size: 1rem; - padding: 5px 10px; - color: #555; - transition: color 0.3s; + padding: 8px; + font-size: 14px; + color: #5f6368; +} + +.toggle-icon span, +.toggle-icon svg { + display: inline-flex; + align-items: center; +} + +.toggle-icon svg { + width: 15px; + height: 15px; +} + +.toggle-label { + margin-left: 4px; } .toggle-icon:hover { @@ -501,6 +551,7 @@ form > button { } + /* Responsive */ @media (max-width: 768px) { .user-menu { diff --git a/server.js b/server.js index 41bbc0c..2a9a617 100644 --- a/server.js +++ b/server.js @@ -10,7 +10,7 @@ app.set('trust proxy', true); app.use(rateLimit({ windowMs: 5 * 60 * 1000, // 5min - max: 100, // 100 request per IP + max: 1000000, // 100 request per IP })); app.use(express.json());