Skip to content

Commit cc0c33f

Browse files
Merge pull request #24 from ramezio/main
feat: desktop app port (issue #23)
2 parents 2745de8 + cbc523a commit cc0c33f

25 files changed

Lines changed: 3941 additions & 0 deletions
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
name: Build Desktop App Binaries
2+
3+
on:
4+
push:
5+
tags:
6+
- "desktop-v*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v4
18+
19+
- name: Setup Node.js
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: "lts/*"
23+
24+
- name: Setup Neutralinojs binaries
25+
working-directory: desktop-app
26+
run: npm run setup
27+
28+
- name: Build all binaries (embedded + portable)
29+
working-directory: desktop-app
30+
run: npm run build:all
31+
32+
- name: Stage release assets
33+
working-directory: desktop-app
34+
run: |
35+
VERSION="${GITHUB_REF_NAME#desktop-}"
36+
STAGING="release-assets"
37+
mkdir -p "$STAGING"
38+
39+
# --- Embedded single-file executables ---
40+
for bin in dist/markdown-viewer/markdown-viewer-*; do
41+
[ -f "$bin" ] || continue
42+
filename=$(basename "$bin")
43+
44+
if [[ "$filename" == *.exe ]]; then
45+
# Windows .exe — ship as-is
46+
cp "$bin" "$STAGING/$filename"
47+
else
48+
# Linux/macOS — tar.gz for Unix convention
49+
tar -czf "$STAGING/${filename}.tar.gz" -C "$(dirname "$bin")" "$filename"
50+
fi
51+
done
52+
53+
# --- Portable ZIP bundle (from neu build --release) ---
54+
for zip in dist/*.zip; do
55+
[ -f "$zip" ] || continue
56+
cp "$zip" "$STAGING/"
57+
done
58+
59+
# --- Source archives ---
60+
cd ..
61+
tar -czf "desktop-app/$STAGING/source.tar.gz" \
62+
--exclude='desktop-app/dist' \
63+
--exclude='desktop-app/bin' \
64+
--exclude='desktop-app/node_modules' \
65+
--exclude='desktop-app/output' \
66+
--exclude='.git' \
67+
desktop-app/
68+
cd desktop-app
69+
70+
# --- SHA256 checksums ---
71+
cd "$STAGING"
72+
sha256sum * > SHA256SUMS.txt
73+
74+
- name: Create GitHub Release
75+
uses: softprops/action-gh-release@v2
76+
with:
77+
name: "Markdown Viewer Desktop ${{ github.ref_name }}"
78+
generate_release_notes: true
79+
files: desktop-app/release-assets/*

desktop-app/.dockerignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Build-generated resources
2+
resources/js/script.js
3+
resources/styles.css
4+
resources/assets/
5+
resources/index.html
6+
7+
# Git
8+
.git
9+
.gitignore
10+
.gitattributes
11+
12+
# Neutralinojs builds and binaries
13+
bin/
14+
dist/
15+
node_modules/
16+
17+
# Logs and temp files
18+
*.log
19+
.storage
20+
.tmp
21+
.lite_workspace.lua

desktop-app/.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Dependencies
2+
node_modules/
3+
4+
# Developer tools' files
5+
.lite_workspace.lua
6+
7+
# Neutralinojs binaries and builds
8+
/bin
9+
/dist
10+
11+
# Neutralinojs client (minified)
12+
neutralino.js
13+
14+
# Build-generated resources (copied from root by prepare.js)
15+
/resources/js/script.js
16+
/resources/styles.css
17+
/resources/assets/
18+
/resources/index.html
19+
20+
# Neutralinojs related files
21+
.storage
22+
*.log
23+
24+
# neutralinojs tmp files
25+
.tmp
26+
27+
# Docker build output
28+
/output

desktop-app/Dockerfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Build Neutralinojs desktop app binaries
2+
#
3+
# Context: repo root (see docker-compose.yml)
4+
# Output: /output/ contains dist/ artifacts
5+
6+
FROM node:lts-alpine AS build
7+
8+
WORKDIR /app
9+
10+
# Copy the entire repo (context is the repo root)
11+
COPY . .
12+
13+
WORKDIR /app/desktop-app
14+
15+
# Setup (download binaries + prepare resources) and build all variants
16+
RUN npm run build:all
17+
18+
# Final stage: Export the dist artifacts
19+
FROM alpine:latest
20+
21+
WORKDIR /output
22+
23+
COPY --from=build /app/desktop-app/dist/ .
24+
25+
CMD ["echo", "Build artifacts are in /output. Use 'docker cp' to extract them."]

desktop-app/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 Neutralinojs and contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

desktop-app/README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Markdown Viewer Desktop App Port
2+
3+
This is a desktop app port of [Markdown Viewer](https://github.com/ThisIs-Developer/Markdown-Viewer), see [README](../README.md). It is built using [Neutralinojs](https://github.com/neutralinojs/neutralinojs).
4+
5+
## Architecture
6+
7+
The desktop app **shares** its core files (`script.js`, `styles.css`, `assets/`) with the browser version in the repo root. A build script (`prepare.js`) copies these files into `resources/` and injects Neutralinojs-specific additions into `index.html` at build time.
8+
9+
Neutralinojs platform binaries are managed by `setup-binaries.js`, which downloads them on first use and caches them in `bin/` (gitignored). The download is version-locked to `cli.binaryVersion` in `neutralino.config.json` and only re-triggered when that version changes.
10+
11+
Desktop-only files (not generated):
12+
13+
- `resources/js/main.js` — Neutralinojs lifecycle, tray menu, window events
14+
- `resources/js/neutralino.js` — Neutralinojs client library
15+
- `neutralino.config.json` — App configuration
16+
- `setup-binaries.js` — Idempotent binary setup (downloads on first use)
17+
18+
## Development
19+
20+
### Requirements
21+
22+
- [Node.js](https://nodejs.org/)
23+
24+
### Setup
25+
26+
No installation is required. The app is built and run using `npx` (via npm scripts).
27+
28+
Neutralinojs platform binaries are downloaded automatically on first build or dev run. To manually trigger the download:
29+
30+
```bash
31+
npm run setup
32+
```
33+
34+
Binaries are cached in `bin/` (gitignored) and only re-downloaded when `cli.binaryVersion` in `neutralino.config.json` changes.
35+
36+
### Running the app
37+
38+
```bash
39+
npm run dev
40+
```
41+
42+
This automatically runs `setup` (downloads binaries if needed and prepares resources) before starting the app. Hot-reload is enabled by default. Enable the browser inspector by setting `"enableInspector": true` in `neutralino.config.json`.
43+
44+
For more information, see the [Neutralinojs documentation](https://neutralino.js.org/docs/cli/neu-cli#installation).
45+
46+
### Building the app
47+
48+
**Default** — Single-file executables with embedded resources:
49+
50+
```bash
51+
npm run build
52+
```
53+
54+
**Portable** — ZIP bundle with separate `resources.neu` file:
55+
56+
```bash
57+
npm run build:portable
58+
```
59+
60+
**Both** — Build embedded + portable in one step:
61+
62+
```bash
63+
npm run build:all
64+
```
65+
66+
Build output is placed in `dist/`.
67+
68+
For more information, see the [Neutralinojs documentation](https://neutralino.js.org/docs/cli/neu-cli#neu-build).
69+
70+
### Building with Docker
71+
72+
Build binaries without installing Node.js locally:
73+
74+
```bash
75+
docker compose up --build
76+
```
77+
78+
Build artifacts will be output to `desktop-app/output/`.
79+
80+
## Releases
81+
82+
Prebuilt binaries are automatically built and published as GitHub Releases when a tag matching `desktop-v*` is pushed (e.g., `desktop-v1.0.0`). See [`.github/workflows/desktop-build.yml`](../.github/workflows/desktop-build.yml).
83+
84+
Each release includes:
85+
86+
| Asset | Description |
87+
| ----- | ----------- |
88+
| `markdown-viewer-win_x64.exe` | Windows x64 executable |
89+
| `markdown-viewer-linux_x64.tar.gz` | Linux x64 executable (tarball) |
90+
| `markdown-viewer-linux_arm64.tar.gz` | Linux ARM64 executable (tarball) |
91+
| `markdown-viewer-mac_*.tar.gz` | macOS executables (tarball) |
92+
| `markdown-viewer-release.zip` | Portable bundle with `resources.neu` (all platforms) |
93+
| `source.tar.gz` | Desktop app source archive |
94+
| `SHA256SUMS.txt` | Checksums for all release assets |
95+
96+
## License
97+
98+
**MIT**.
99+
100+
The desktop version uses [Neutralinojs](https://github.com/neutralinojs/neutralinojs), which is also licensed under the MIT License.
101+
102+
- [Neutralinojs](https://github.com/neutralinojs/neutralinojs): [LICENSE (MIT)](LICENSE)
103+
- [Markdown Viewer & Desktop Port](https://github.com/ThisIs-Developer/Markdown-Viewer): [LICENSE (MIT)](../LICENSE)
104+
105+
## Contributors
106+
107+
[![Contributors](https://contrib.rocks/image?repo=ThisIs-Developer/Markdown-Viewer)](https://github.com/ThisIs-Developer/Markdown-Viewer/graphs/contributors)

desktop-app/docker-compose.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
services:
2+
desktop-build:
3+
build:
4+
context: ..
5+
dockerfile: desktop-app/Dockerfile
6+
container_name: markdown-viewer-desktop-build
7+
volumes:
8+
- ./output:/export
9+
entrypoint:
10+
[
11+
"sh",
12+
"-c",
13+
"cp -r /output/* /export/ && echo '✓ Build artifacts copied to desktop-app/output/'",
14+
]

desktop-app/neutralino.config.json

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/neutralinojs/neutralinojs/main/schemas/neutralino.config.schema.json",
3+
"applicationId": "js.neutralino.sample",
4+
"version": "1.0.0",
5+
"defaultMode": "window",
6+
"port": 0,
7+
"documentRoot": "/resources/",
8+
"url": "/",
9+
"enableServer": true,
10+
"enableNativeAPI": true,
11+
"tokenSecurity": "one-time",
12+
"logging": {
13+
"enabled": true,
14+
"writeToLogFile": true
15+
},
16+
"nativeAllowList": ["app.*", "os.*", "debug.log"],
17+
"globalVariables": {},
18+
"modes": {
19+
"window": {
20+
"title": "Markdown Viewer",
21+
"width": 800,
22+
"height": 500,
23+
"minWidth": 400,
24+
"minHeight": 200,
25+
"center": true,
26+
"fullScreen": false,
27+
"alwaysOnTop": false,
28+
"icon": "/resources/assets/icon.jpg",
29+
"enableInspector": false,
30+
"borderless": false,
31+
"maximize": false,
32+
"hidden": false,
33+
"resizable": true,
34+
"exitProcessOnClose": false
35+
},
36+
"browser": {
37+
"globalVariables": {},
38+
"nativeBlockList": ["filesystem.*"]
39+
},
40+
"cloud": {
41+
"url": "/resources/#cloud",
42+
"nativeAllowList": ["app.*"]
43+
},
44+
"chrome": {
45+
"width": 800,
46+
"height": 500,
47+
"args": "--user-agent=\"Neutralinojs chrome mode\"",
48+
"nativeBlockList": ["filesystem.*", "os.*"]
49+
}
50+
},
51+
"cli": {
52+
"binaryName": "markdown-viewer",
53+
"resourcesPath": "/resources/",
54+
"extensionsPath": "/extensions/",
55+
"clientLibrary": "/resources/js/neutralino.js",
56+
"binaryVersion": "6.5.0",
57+
"clientVersion": "6.5.0"
58+
}
59+
}

desktop-app/package-lock.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

desktop-app/package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "markdown-viewer-desktop",
3+
"version": "1.0.0",
4+
"private": true,
5+
"description": "Neutralinojs desktop port of Markdown Viewer",
6+
"scripts": {
7+
"setup": "node setup-binaries.js",
8+
"postsetup": "node prepare.js",
9+
"predev": "npm run setup",
10+
"dev": "npx -y @neutralinojs/neu@11.7.0 run",
11+
"prebuild": "npm run setup",
12+
"build": "npx -y @neutralinojs/neu@11.7.0 build --embed-resources",
13+
"build:portable": "npx -y @neutralinojs/neu@11.7.0 build --release",
14+
"build:all": "npm run build && npm run build:portable"
15+
},
16+
"dependencies": {}
17+
}

0 commit comments

Comments
 (0)