Merge pull request #2 from gamosoft/features/new-features

Features/new features
This commit is contained in:
Gamosoft 2025-11-09 10:18:09 +01:00 committed by GitHub
commit a413622250
5 changed files with 107 additions and 26 deletions

7
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,7 @@
# GitHub Sponsors configuration
# This adds a "Sponsor" button to your repository
# PayPal donation link (can add up to 4 custom links)
custom:
- 'https://paypal.me/gamosoft'

View File

@ -1,16 +1,15 @@
name: Build and Push Docker Image to GHCR
on:
push:
pull_request:
types:
- closed
branches:
- main
- master
push:
tags:
- 'v*.*.*'
pull_request:
branches:
- main
- master
workflow_dispatch:
env:
@ -19,6 +18,11 @@ env:
jobs:
build-and-push:
# Only run if PR was merged (not just closed) or if triggered by tag/manual
if: |
(github.event_name == 'pull_request' && github.event.pull_request.merged == true) ||
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
@ -44,19 +48,17 @@ jobs:
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=latest,enable=true
- name: Build and push Docker image
id: build-push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha

View File

@ -45,6 +45,8 @@ NoteDiscovery is a **lightweight, self-hosted note-taking application** that put
Use the pre-built image directly from GHCR - no building required!
> **💡 Tip**: Always use `ghcr.io/gamosoft/notediscovery:latest` to get the newest features and fixes. Images are automatically built when PRs are merged to main.
> **📁 Important - Volume Mapping**: The container needs local folders/files to work:
> - **Required**: `data` folder (your notes will be stored here)
> - **Required**: `themes` folder with theme `.css` files (at least light.css and dark.css)
@ -200,6 +202,10 @@ Once you've started NoteDiscovery, you'll find comprehensive guides on:
💡 **Tip:** These documentation files are regular markdown notes—edit them, add your own notes, or use them as templates. It's your knowledge base!
## 💖 Support Development
If you find NoteDiscovery useful, consider [☕ buying me a coffee](https://paypal.me/gamosoft) to help keep the project going. Every bit helps with new features, bug fixes, and improvements. Thank you!
## 🔒 Security Considerations
NoteDiscovery is designed for **self-hosted, private use**. Please keep these security considerations in mind:
@ -230,18 +236,6 @@ NoteDiscovery is designed for **self-hosted, private use**. Please keep these se
**TL;DR**: Perfect for personal use on your local machine or home network. Add a reverse proxy with authentication if exposing to wider networks.
## 💖 Support Development
If NoteDiscovery makes your life easier, consider buying me a coffee! Your support helps keep this project alive and growing.
**[☕ Buy Me a Coffee](https://paypal.me/gamosoft)**
Every contribution, no matter how small, is deeply appreciated and helps fund:
- 🛠️ New features and improvements
- 🐛 Bug fixes and maintenance
- 📚 Documentation and tutorials
- 🎨 Design enhancements
## 📄 License
MIT License - Free to use, modify, and distribute.

View File

@ -81,6 +81,10 @@ function noteApp() {
sidebarWidth: CONFIG.DEFAULT_SIDEBAR_WIDTH,
isResizing: false,
// Split view resize state
editorWidth: 50, // percentage
isResizingSplit: false,
// DOM element cache (to avoid repeated querySelector calls)
_domCache: {
editor: null,
@ -96,6 +100,7 @@ function noteApp() {
await this.loadNotes();
await this.checkStatsPlugin();
this.loadSidebarWidth();
this.loadEditorWidth();
this.loadViewMode();
// Parse URL and load specific note if provided
@ -2025,6 +2030,55 @@ function noteApp() {
document.addEventListener('mouseup', stopResize);
},
// Start resizing split panes (editor/preview)
startSplitResize(event) {
this.isResizingSplit = true;
event.preventDefault();
const container = event.target.parentElement;
const resize = (e) => {
if (!this.isResizingSplit) return;
const containerRect = container.getBoundingClientRect();
const mouseX = e.clientX - containerRect.left;
const percentage = (mouseX / containerRect.width) * 100;
// Clamp between 20% and 80%
if (percentage >= 20 && percentage <= 80) {
this.editorWidth = percentage;
}
};
const stopResize = () => {
if (this.isResizingSplit) {
this.isResizingSplit = false;
this.saveEditorWidth();
document.removeEventListener('mousemove', resize);
document.removeEventListener('mouseup', stopResize);
}
};
document.addEventListener('mousemove', resize);
document.addEventListener('mouseup', stopResize);
},
// Load editor width from localStorage
loadEditorWidth() {
const saved = localStorage.getItem('editorWidth');
if (saved) {
const width = parseFloat(saved);
if (width >= 20 && width <= 80) {
this.editorWidth = width;
}
}
},
// Save editor width to localStorage
saveEditorWidth() {
localStorage.setItem('editorWidth', this.editorWidth.toString());
},
// Scroll to top of editor and preview
scrollToTop() {
// Disable scroll sync temporarily to prevent interference

View File

@ -340,7 +340,7 @@
top: 0;
bottom: 0;
width: 1px;
background-color: var(--border-primary);
background-color: var(--text-tertiary);
opacity: 0.4;
}
@ -392,6 +392,21 @@
background-color: var(--accent-hover) !important;
}
/* Split view resize handle */
.split-resize-handle {
position: relative;
user-select: none;
flex-shrink: 0;
}
.split-resize-handle:hover {
background-color: var(--accent-primary) !important;
}
.split-resize-handle:active {
background-color: var(--accent-hover) !important;
}
/* Enhanced Shell/Bash Syntax Highlighting */
.markdown-preview pre code.language-shell .hljs-meta,
.markdown-preview pre code.language-bash .hljs-meta,
@ -870,14 +885,13 @@
</div>
<!-- Editor/Preview -->
<div class="flex-1 flex" style="min-height: 0;">
<div class="flex-1 flex relative" style="min-height: 0;">
<!-- Editor -->
<div
x-show="viewMode === 'edit' || viewMode === 'split'"
:class="viewMode === 'split' ? 'w-1/2' : 'w-full'"
class="flex flex-col"
style="min-height: 0;"
:style="'border-right: ' + (viewMode === 'split' ? '1px solid var(--border-primary)' : 'none')"
:style="viewMode === 'split' ? `width: ${editorWidth}%;` : 'width: 100%;'"
>
<textarea
x-model="noteContent"
@ -892,12 +906,22 @@
></textarea>
</div>
<!-- Split view resize handle -->
<div
x-show="viewMode === 'split'"
@mousedown="startSplitResize($event)"
class="split-resize-handle"
style="width: 4px; cursor: col-resize; background-color: transparent; transition: background-color 0.2s; position: relative; z-index: 10;"
@mouseover="$el.style.backgroundColor='var(--accent-primary)'"
@mouseout="if(!isResizingSplit) $el.style.backgroundColor='transparent'"
></div>
<!-- Preview -->
<div
x-show="viewMode === 'preview' || viewMode === 'split'"
:class="viewMode === 'split' ? 'w-1/2' : 'w-full'"
class="overflow-y-auto overflow-x-hidden custom-scrollbar"
style="background-color: var(--bg-primary); min-height: 0;"
:style="viewMode === 'split' ? `width: ${100 - editorWidth}%;` : 'width: 100%;'"
>
<div
class="p-6 markdown-preview"