Skip to content
Open
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
6 changes: 5 additions & 1 deletion desktop-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ Desktop-only files:
- Document metadata loads at startup; Markdown content loads only when a document is opened and is kept in a bounded in-memory cache.
- Native Markdown/HTML save and Markdown open flows use Neutralino dialogs and filesystem APIs.
- A Markdown file passed as a launch argument is loaded into the editor.
- Files opened from disk can remain linked to their original path. Workspace (Vault) copies are separate documents; converting a linked file to a copy leaves its source untouched.
- Linked files keep an app-local draft, but write to the original only on Ctrl+S. Reopening the same path selects its existing document rather than making another copy.
- **Link a Markdown folder** adds its Markdown files under Linked Locations. Files added or changed outside the app are detected while the desktop app is running; a locally edited draft is not silently overwritten by an external change.
- Removing a link removes the app's reference, not the original file or folder. Native file drops are not covered by the linked-file flow in this build.
- The app asks before closing the window.
- Prepared desktop resources load dynamic libraries from local `/libs/...` paths after setup.
- Private mode pauses document-state persistence for the current page session without deleting the vault, shows an active incognito status, and resets on reload or exit. **Reset workspace** permanently deletes documents, folders, review data, settings, Secret Workspace records, history, trash, and recovery journals after confirmation.
Expand Down Expand Up @@ -81,7 +85,7 @@ Seven self-contained executables are written to `desktop-app/dist/markdown-viewe
| Token security | One-time |
| Logging | Disabled |

Native APIs are intentionally allowlisted: app exit, open/save dialogs, message boxes, external URL/folder open, tray setup, scoped file and folder operations, path lookup, and storage get/set/remove. Command execution is not part of the default allowlist.
Native APIs are intentionally allowlisted: app exit, open/save/folder dialogs, message boxes, external URL/folder open, tray setup, scoped file and folder operations, filesystem watchers, path lookup, and storage get/set/remove. Command execution is not part of the default allowlist.

## Local Renderer Security

Expand Down
4 changes: 4 additions & 0 deletions desktop-app/neutralino.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"nativeAllowList": [
"app.exit",
"os.showOpenDialog",
"os.showFolderDialog",
"os.showSaveDialog",
"os.showMessageBox",
"os.getPath",
Expand All @@ -34,6 +35,9 @@
"filesystem.copy",
"filesystem.move",
"filesystem.remove",
"filesystem.createWatcher",
"filesystem.removeWatcher",
"filesystem.getWatchers",
"storage.setData",
"storage.getData",
"storage.getKeys",
Expand Down
10 changes: 9 additions & 1 deletion desktop-app/resources/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ <h1 class="h4 mb-0">Markdown Viewer<span class="visually-hidden"> - Online Markd
</button>
<ul class="dropdown-menu app-command-menu header-command-menu header-new-menu" aria-labelledby="importDropdown">
<li><a class="dropdown-item app-menu-item" href="#" id="header-new-document"><i class="lucide lucide-file-plus-2" aria-hidden="true"></i><span class="app-menu-label">New document</span></a></li>
<li><a class="dropdown-item app-menu-item" href="#" id="import-from-file"><i class="lucide lucide-upload" aria-hidden="true"></i><span class="app-menu-label">From files</span></a></li>
<li><a class="dropdown-item app-menu-item" href="#" id="import-from-file"><i class="lucide lucide-files" aria-hidden="true"></i><span class="app-menu-label">Import copies</span></a></li>
<li class="desktop-linked-command" hidden><a class="dropdown-item app-menu-item" href="#" id="link-from-file"><i class="lucide lucide-link-2" aria-hidden="true"></i><span class="app-menu-label">Link files…</span></a></li>
<li class="desktop-linked-command" hidden><a class="dropdown-item app-menu-item" href="#" id="link-from-folder"><i class="lucide lucide-folder-open" aria-hidden="true"></i><span class="app-menu-label">Link folder…</span></a></li>
<li><a class="dropdown-item app-menu-item" href="#" id="import-from-github"><i class="bi bi-github" aria-hidden="true"></i><span class="app-menu-label">From GitHub</span></a></li>
</ul>
</div>
Expand Down Expand Up @@ -346,6 +348,12 @@ <h2 id="document-sidebar-title">Explorer</h2>
<button id="sidebar-new-folder" class="document-sidebar-icon-btn" type="button" aria-label="Create a folder" title="New folder">
<i class="lucide lucide-folder-plus" aria-hidden="true"></i>
</button>
<button id="sidebar-link-files" class="document-sidebar-icon-btn desktop-linked-command" type="button" aria-label="Link Markdown files" title="Link Markdown files" hidden>
<i class="lucide lucide-link-2" aria-hidden="true"></i>
</button>
<button id="sidebar-link-folder" class="document-sidebar-icon-btn desktop-linked-command" type="button" aria-label="Link a Markdown folder" title="Link a Markdown folder" hidden>
<i class="lucide lucide-folder-open" aria-hidden="true"></i>
</button>
<button id="sidebar-trash-button" class="document-sidebar-icon-btn" type="button" aria-label="Open Trash" title="Trash">
<i class="lucide lucide-trash-2" aria-hidden="true"></i>
</button>
Expand Down
13 changes: 11 additions & 2 deletions desktop-app/resources/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ if (isNeutralinoRuntime()) {
// TODO: Fix https://github.com/neutralinojs/neutralinojs/issues/615
setTray();
}

window.addEventListener('markdown-viewer:ready', function() {
if (typeof window.NL_START_LINKED_MONITORING === 'function') {
window.NL_START_LINKED_MONITORING().catch(function(error) {
console.warn('Linked source monitoring initialization failed:', error);
});
}
}, { once: true });
}

// Open file passed as command-line argument (e.g. when double-clicking a .md file)
Expand All @@ -146,12 +154,13 @@ if (isNeutralinoRuntime()) {

window.NL_INITIAL_FILE_CONTENT = {
name: fileName,
content: content
content: content,
sourcePath: filePath
};

// Callback hook in case script.js loaded first
if (window.NL_IMPORT_EXTERNAL_FILE) {
window.NL_IMPORT_EXTERNAL_FILE(content, fileName);
window.NL_IMPORT_EXTERNAL_FILE(content, fileName, filePath);
}
} catch (e) {
console.warn('Could not open initial file:', e);
Expand Down
Loading
Loading