Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -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'

20 changes: 11 additions & 9 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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
Expand All @@ -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
Expand Down
18 changes: 6 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand Down
54 changes: 54 additions & 0 deletions frontend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
34 changes: 29 additions & 5 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@
top: 0;
bottom: 0;
width: 1px;
background-color: var(--border-primary);
background-color: var(--text-tertiary);
opacity: 0.4;
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -870,14 +885,13 @@ <h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary);" x-text="
</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"
Expand All @@ -892,12 +906,22 @@ <h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary);" x-text="
></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"
Expand Down