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
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,36 @@ npm run package

Output goes to the `dist/` folder. Targets: NSIS/ZIP (Windows), DMG/ZIP (macOS), AppImage/DEB (Linux).

---

## Installing on Linux

**DEB** (Debian, Ubuntu, Mint, Pop!_OS, and other Debian-based distros):

```bash
sudo apt install ./moilstack-md_*.deb
```

**AppImage** (works on virtually any distro — Fedora, Arch, openSUSE, Ubuntu, etc. — no installation required):

```bash
chmod +x moilstack-md-*.AppImage
./moilstack-md-*.AppImage
```

If it fails to launch with a FUSE-related error (some minimal or newer distros, e.g. Fedora 41+, ship without FUSE2 by default), either install FUSE:

```bash
# Fedora
sudo dnf install fuse fuse-libs
# Ubuntu/Debian
sudo apt install fuse
```

or skip FUSE entirely and extract-and-run instead:

```bash
./moilstack-md-*.AppImage --appimage-extract-and-run
```

## AI Assistant Setup

Expand Down
Binary file added build/icons/1024x1024.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/icons/128x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/icons/16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/icons/256x256.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/icons/32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/icons/48x48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/icons/512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/icons/64x64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 21 additions & 4 deletions build/make-app-icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ const fs = require('fs');
const path = require('path');
const os = require('os');

const PNG_SRC = path.join(__dirname, '../src/assets/icon.png');
const ICO_DEST = path.join(__dirname, '../src/assets/icon.ico');
const APPX_DIR = path.join(__dirname, 'appx');
const SIZES = [16, 32, 44, 48, 150, 256, 310];
const PNG_SRC = path.join(__dirname, '../src/assets/icon.png');
const ICO_DEST = path.join(__dirname, '../src/assets/icon.ico');
const APPX_DIR = path.join(__dirname, 'appx');
const LINUX_DIR = path.join(__dirname, 'icons');
const SIZES = [16, 32, 44, 48, 150, 256, 310];
// electron-builder's Linux icon set: named by size so its packager can read
// dimensions from the filename instead of decoding the PNG (see build/icons
// vs. a single flat icon.png — the latter trips app-builder's size sniffer).
const LINUX_SIZES = [16, 32, 48, 64, 128, 256, 512, 1024];

const APPX_ASSETS = [
{ name: 'Square44x44Logo.png', size: 44 },
Expand Down Expand Up @@ -52,6 +57,18 @@ async function run() {
console.log(` ${asset.name} (${w}x${h}) ✓`);
}
console.log(`Done → ${APPX_DIR}`);

console.log('Generating Linux icon set…');
if (!fs.existsSync(LINUX_DIR)) fs.mkdirSync(LINUX_DIR);
for (const size of LINUX_SIZES) {
const outPath = path.join(LINUX_DIR, `${size}x${size}.png`);
await sharp(pngBuffer)
.resize(size, size, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })
.png()
.toFile(outPath);
console.log(` ${size}x${size} ✓`);
}
console.log(`Done → ${LINUX_DIR}`);
}

run().catch(err => {
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
},
"build": {
"appId": "com.moilstack.markdown",
"productName": "MoilStack .md",
"productName": "moilstack-md",
"icon": "build/icons",
"copyright": "Copyright © 2026 MoilStack",
"directories": {
"output": "dist"
Expand All @@ -38,14 +39,14 @@
"zip"
],
"icon": "src/assets/icon.ico",
"artifactName": "MoilStack.md.${ext}"
"artifactName": "moilstack-md.${ext}"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "MoilStack .md",
"shortcutName": "moilstack-md",
"include": "build/installer.nsh"
},
"appx": {
Expand Down
17 changes: 17 additions & 0 deletions src/renderer/markdownRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,26 @@ const MarkdownRenderer = (() => {
* @param {string} src Raw Markdown source.
* @returns {string} HTML output.
*/
/**
* Strip a leading YAML frontmatter block (used for tags, etc.) so it never
* renders as visible content — mirrors the skip logic in ipc.js's
* _extractFirstLine/_extractTags on the main-process side.
*/
function _stripFrontmatter(src) {
if (!src.startsWith('---')) return src;
const fmEnd = src.indexOf('\n---', 3);
if (fmEnd === -1) return src;
const afterDelim = fmEnd + 4; // past "\n---"
const nextNewline = src.indexOf('\n', afterDelim);
return nextNewline === -1 ? '' : src.slice(nextNewline + 1);
}

function parseMarkdown(src) {
if (!src || !src.trim()) return '';

src = _stripFrontmatter(src);
if (!src.trim()) return '';

const lines = src.split('\n');
const out = [];
let i = 0;
Expand Down
Loading