Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
111d36bf3d | ||
|
|
a13a87c499 | ||
|
|
bd620284ab | ||
|
|
a6407b5839 | ||
|
|
1a357bbd6a | ||
|
|
dfce7fd3ac | ||
|
|
fc017e0101 | ||
|
|
bf12996a40 | ||
|
|
f133efe025 | ||
|
|
7bb062a464 | ||
|
|
7673f5533d | ||
|
|
d4a2c21196 | ||
|
|
d90be20a72 | ||
|
|
e967af77a7 | ||
|
|
41ddaa17b3 | ||
|
|
48c7420c7a | ||
|
|
dadfe52870 | ||
|
|
8fb61130f3 | ||
|
|
ded17d0b6b | ||
|
|
22bc4dcf56 | ||
|
|
4123455863 | ||
|
|
7beb3effcf | ||
|
|
9412049f56 | ||
|
|
98979a2cd2 | ||
|
|
4228ab78d8 | ||
|
|
0bb1091c47 | ||
|
|
855dfcd9f5 | ||
|
|
d5efdfa8d9 | ||
|
|
3ec9ff0130 | ||
|
|
e826c0e624 | ||
|
|
47315add80 | ||
|
|
0d3df32140 | ||
|
|
b36d0919a3 | ||
|
|
72ca2cb46f | ||
|
|
1a25669967 | ||
|
|
cb0b2eac3d | ||
|
|
b70dce9574 | ||
|
|
3bd958c064 | ||
|
|
33fa14c11a | ||
|
|
de7ebecad4 | ||
|
|
23046967c3 | ||
|
|
e87e301b0f | ||
|
|
075e407f3f | ||
|
|
b81119026e | ||
|
|
81e8561403 | ||
|
|
ca5983e9ff | ||
|
|
86d4c0d23a | ||
|
|
5f846d1e5f | ||
|
|
9557c0af4d | ||
|
|
d31ed86fab | ||
|
|
e0945b427d | ||
|
|
ac31162d3b | ||
|
|
8c708b7abb | ||
|
|
58aa4da00f | ||
|
|
b28d11035b | ||
|
|
bf0ed6857d | ||
|
|
aee30a2a9c | ||
|
|
b0dcf57daf | ||
|
|
a6dc54cedc | ||
|
|
59ee9c609e | ||
|
|
0331a08207 | ||
|
|
216e0ecf51 | ||
|
|
4a36b7db76 | ||
|
|
7869be0ff9 | ||
|
|
2ca543de35 | ||
|
|
02c9250c0d | ||
|
|
ab50183dc0 | ||
|
|
8c162c1714 | ||
|
|
38bc2b2bc5 | ||
|
|
1d68fc132f | ||
|
|
fecd23d35e | ||
|
|
f089f60d70 | ||
|
|
9751bbc6df | ||
|
|
57fee91e32 | ||
|
|
fba848ef16 | ||
|
|
bb99a5c5ee | ||
|
|
f71aa2b097 | ||
|
|
5385e159ed | ||
|
|
3fbb47000e | ||
|
|
66def72f3e | ||
|
|
c1c9ab4a4c | ||
|
|
0bc50c7d54 | ||
|
|
ceeda453be | ||
|
|
311304f365 | ||
|
|
8392e33f5b | ||
|
|
a2b4a856f3 | ||
|
|
eaad62d02e | ||
|
|
1e7e332c24 | ||
|
|
b8c772269c | ||
|
|
87902c18ce | ||
|
|
43c26c6521 | ||
|
|
b1b72f9a60 | ||
|
|
c3fe72bcae | ||
|
|
2aa72738f4 | ||
|
|
0cab0b08c7 | ||
|
|
1b85bc47a4 | ||
|
|
bd86748c47 | ||
|
|
6d08c138d8 | ||
|
|
7397e7f618 | ||
|
|
da97369b44 | ||
|
|
3f856bc857 | ||
|
|
cd0050d988 | ||
|
|
dfb364bcd8 | ||
|
|
cd2980277b | ||
|
|
a2455c3f8a | ||
|
|
1b2ab7b55c | ||
|
|
cfe134931f | ||
|
|
77f8ba3d9d | ||
|
|
0be46d4bac | ||
|
|
1e24b52f3e | ||
|
|
58bd19ecd1 | ||
|
|
7ab5a0ddb4 | ||
|
|
efca458495 | ||
|
|
c4dcbd8caf | ||
|
|
b83ba91731 | ||
|
|
0babf97f0e | ||
|
|
eeda3f28eb | ||
|
|
4c00406bcd | ||
|
|
363de75375 | ||
|
|
2e16868f59 | ||
|
|
dd6d97c35d | ||
|
|
0604c65683 | ||
|
|
c43caf3902 | ||
|
|
25dcaaa816 | ||
|
|
c6ec1cef64 | ||
|
|
5fcc282fe0 | ||
|
|
8a95144bf3 | ||
|
|
bc47316746 | ||
|
|
02ce06d364 | ||
|
|
2e3af826f7 | ||
|
|
758dcb4166 | ||
|
|
1f5db511ba | ||
|
|
63c35ef2dc | ||
|
|
c8883e77fe | ||
|
|
8a28c21512 | ||
|
|
d6baa2daf7 | ||
|
|
44624cd4bf | ||
|
|
2334ab30ed | ||
|
|
abcfb03e52 | ||
|
|
6ba3174480 | ||
|
|
b83b86b31e | ||
|
|
f271e27177 | ||
|
|
8dc1ae1c45 | ||
|
|
a353a695b5 | ||
|
|
174eb3d6e9 | ||
|
|
8bada008b3 | ||
|
|
949053a7c5 | ||
|
|
b80e34fcf5 | ||
|
|
11b1c9e13e | ||
|
|
e09853952b | ||
|
|
d43fbaea59 | ||
|
|
66938968db | ||
|
|
5d9c46afc3 | ||
|
|
bf3438902b | ||
|
|
edb5db358a | ||
|
|
6d564261b2 | ||
|
|
f5dcffeb8d | ||
|
|
7095b34280 | ||
|
|
58868eece0 | ||
|
|
cd3385ec69 | ||
|
|
f04a20252f | ||
|
|
e5e14c88ce | ||
|
|
7a5a2ecba6 | ||
|
|
fac0d3d4a6 | ||
|
|
269d4ac028 | ||
|
|
cdc318ebc7 | ||
|
|
0c4043121f | ||
|
|
151be60b03 | ||
|
|
228ee04b09 | ||
|
|
9fd81ff5a0 | ||
|
|
f22cacd554 | ||
|
|
2f3b552608 | ||
|
|
cb27b47b91 | ||
|
|
01e2df44ed | ||
|
|
adfa43c278 | ||
|
|
879600da46 | ||
|
|
7b73ab07d7 | ||
|
|
57bbf91245 | ||
|
|
5178d91187 | ||
|
|
3f0bf911a0 | ||
|
|
2cac075c0e | ||
|
|
94906a068a | ||
|
|
e72b863362 | ||
|
|
d705cfc30b | ||
|
|
02e307f758 | ||
|
|
5ad1d1d4b3 | ||
|
|
f480449301 |
@@ -0,0 +1,9 @@
|
|||||||
|
# Text artifacts that are hash-pinned must check out byte-identical everywhere
|
||||||
|
assets/fonts/FiraCode-LICENSE.txt -text
|
||||||
|
# Binaries: never normalize
|
||||||
|
*.ttf -text
|
||||||
|
*.woff -text
|
||||||
|
*.woff2 -text
|
||||||
|
*.png -text
|
||||||
|
*.ico -text
|
||||||
|
*.icns -text
|
||||||
@@ -2,9 +2,9 @@ name: CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master, react-electron]
|
branches: [master]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [master, react-electron]
|
branches: [master]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@@ -24,8 +24,5 @@ jobs:
|
|||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: npm test
|
run: npm test
|
||||||
|
|
||||||
- name: Run renderer tests
|
|
||||||
run: npm run test:renderer
|
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint
|
run: npm run lint
|
||||||
|
|||||||
@@ -25,11 +25,18 @@ jobs:
|
|||||||
- name: Download external tools (pandoc)
|
- name: Download external tools (pandoc)
|
||||||
run: node scripts/download-tools.js
|
run: node scripts/download-tools.js
|
||||||
|
|
||||||
|
- name: Bundle MarkItDown (optional, best effort)
|
||||||
|
# Freezes markitdown + Python into bin/linux/markitdown; failure is
|
||||||
|
# non-fatal — the build then ships without it and the app falls back
|
||||||
|
# to a system markitdown at runtime.
|
||||||
|
run: npm run bundle:markitdown
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: npm test
|
run: npm test
|
||||||
|
|
||||||
- name: Build Linux packages
|
- name: Build Linux packages
|
||||||
run: npm run build:linux-ci -- --publish=always
|
run: npm run build:linux-ci -- --publish=never
|
||||||
|
|
||||||
- name: Upload Linux artifacts
|
- name: Upload Linux artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -59,6 +66,30 @@ jobs:
|
|||||||
- name: Download external tools (pandoc)
|
- name: Download external tools (pandoc)
|
||||||
run: node scripts/download-tools.js
|
run: node scripts/download-tools.js
|
||||||
|
|
||||||
|
- name: Bundle MarkItDown (optional, best effort)
|
||||||
|
# Windows runners ship python + venv; non-fatal on failure — the
|
||||||
|
# package then omits the bundled binary by design. We capture the
|
||||||
|
# log so a silent failure is visible in the GitHub Actions step UI
|
||||||
|
# instead of disappearing into stdout.
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip wheel setuptools 2>&1 | tee bundle-pip.log
|
||||||
|
npm run bundle:markitdown 2>&1 | tee bundle-markitdown.log
|
||||||
|
if [ ! -f bin/win32/markitdown.exe ]; then
|
||||||
|
echo "::warning::bin/win32/markitdown.exe was not produced — see bundle-markitdown.log"
|
||||||
|
fi
|
||||||
|
continue-on-error: true
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Upload MarkItDown bundle logs (on failure)
|
||||||
|
if: failure()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: windows-bundle-logs
|
||||||
|
path: |
|
||||||
|
bundle-pip.log
|
||||||
|
bundle-markitdown.log
|
||||||
|
retention-days: 5
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: npm test
|
run: npm test
|
||||||
|
|
||||||
@@ -77,13 +108,13 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CSC_LINK: code-signing-cert.pfx
|
CSC_LINK: code-signing-cert.pfx
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
||||||
run: npm run build:win-signed -- --publish=always
|
run: npm run build:win-signed -- --publish=never
|
||||||
|
|
||||||
- name: Build Windows packages (unsigned)
|
- name: Build Windows packages (unsigned)
|
||||||
if: ${{ env.CERT_AVAILABLE != 'true' }}
|
if: ${{ env.CERT_AVAILABLE != 'true' }}
|
||||||
env:
|
env:
|
||||||
CSC_IDENTITY_AUTO_DISCOVERY: 'false'
|
CSC_IDENTITY_AUTO_DISCOVERY: 'false'
|
||||||
run: npm run build:win-unsigned -- --publish=always
|
run: npm run build:win-unsigned -- --publish=never
|
||||||
|
|
||||||
- name: Upload Windows artifacts
|
- name: Upload Windows artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -111,13 +142,15 @@ jobs:
|
|||||||
- name: Download external tools (pandoc)
|
- name: Download external tools (pandoc)
|
||||||
run: node scripts/download-tools.js
|
run: node scripts/download-tools.js
|
||||||
|
|
||||||
|
- name: Bundle MarkItDown (optional, best effort)
|
||||||
|
run: npm run bundle:markitdown
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: npm test
|
run: npm test
|
||||||
|
|
||||||
- name: Build macOS packages (unsigned)
|
- name: Build macOS packages
|
||||||
env:
|
run: npm run build:mac -- --publish=never
|
||||||
CSC_IDENTITY_AUTO_DISCOVERY: 'false'
|
|
||||||
run: npm run build:mac -- --publish=always
|
|
||||||
|
|
||||||
- name: Upload macOS artifacts
|
- name: Upload macOS artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -161,16 +194,3 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
files: dist/*
|
files: dist/*
|
||||||
|
|
||||||
- name: Mirror artifacts to ConcreteInfo update feed
|
|
||||||
if: env.CONCRETEINFO_DEPLOY_HOOK != ''
|
|
||||||
env:
|
|
||||||
CONCRETEINFO_DEPLOY_HOOK: ${{ secrets.CONCRETEINFO_DEPLOY_HOOK }}
|
|
||||||
run: |
|
|
||||||
curl -fsSL -X POST \
|
|
||||||
-H "Authorization: Bearer ${{ secrets.CONCRETEINFO_DEPLOY_HOOK }}" \
|
|
||||||
-F "version=${GITHUB_REF_NAME#v}" \
|
|
||||||
-F "artifacts=@dist/latest-mac.yml" \
|
|
||||||
-F "artifacts=@dist/latest-linux.yml" \
|
|
||||||
-F "artifacts=@dist/latest-windows.yml" \
|
|
||||||
https://updates.concreteinfo.co.in/api/v1/ingest
|
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
All notable changes to markdown-converter will be documented in this file.
|
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
## [5.1.0] - 2026-06-08
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Auto-update via electron-updater against GitHub Releases (default) or ConcreteInfo self-hosted feed.
|
|
||||||
- Light, skippable first-run wizard: theme, update channel, starter template.
|
|
||||||
- One-shot v4.4.1 → v5 settings migration with backup at `settings.v4.bak.json`.
|
|
||||||
- Local crash dump capture (cap 20, auto-prune) and a CrashReportModal.
|
|
||||||
- "Updates" section in Settings: channel picker, Check now, auto-check toggle.
|
|
||||||
|
|
||||||
## [5.0.0] - 2026-06-06
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- **Complete React 19 + Vite + TypeScript renderer** replacing the legacy vanilla-JS UI (Phases 1-9 of the React UI redesign)
|
|
||||||
- Native macOS/Windows/Linux menus with command palette and keyboard shortcuts
|
|
||||||
- Settings sheet with 5 tabs (editor, theme, keybindings, advanced, about) and 17+ persisted fields
|
|
||||||
- Modal layer with 13 modal kinds (export PDF/DOCX/HTML/Word, batch, settings, about, welcome, confirm, ASCII gen, table gen, find in files)
|
|
||||||
- 10 advanced tools: ASCII generator (figlet), table generator, Word export (.docx via `docx` lib), find-in-files (recursive regex), REPL (markdown snippet preview), print preview, zen mode (Esc exits), minimap, breadcrumbs-with-symbols, git status (porcelain parser)
|
|
||||||
- Sonner toast notifications at 4 wire points (file save, open file/folder, 4 export dialogs)
|
|
||||||
- 3 mount strategies: ModalLayer dialogs, App.tsx global overlays, editor/sidebar integrations
|
|
||||||
- `ipc.file.writeBuffer` for renderer-side binary file output (used by Word .docx export)
|
|
||||||
- `ipc.file.search` (recursive regex), `ipc.file.gitStatus`, `ipc.print.show`, `ipc.app.showSaveDialog`
|
|
||||||
- 305 unit + integration tests (vitest + React Testing Library)
|
|
||||||
- Per-package @radix-ui primitives (checkbox, dialog, select, switch, tabs, radio-group, scroll-area, slider, collapsible, label, context-menu)
|
|
||||||
- shadcn/ui (new-york style) primitives, manually pasted (CLI broken on Node 24)
|
|
||||||
- Feature-first main process decomposition: `src/main/{files,menu,window,word-template,utils}/` + glue files
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- **BREAKING**: Renderer is now React-only. The legacy `src/renderer.js` (5319 lines) and all vanilla-JS UI scripts/styles are removed.
|
|
||||||
- Main process decomposed from a 4311-line `src/main.js` into feature-first modules under `src/main/`
|
|
||||||
- New entrypoint: `src/main/index.js` (was `src/main.js`)
|
|
||||||
- `src/index.html` (1667-line legacy orphan) removed; renderer served by `src/renderer/index.html` (Vite root)
|
|
||||||
- IPC contract: handlers throw on error, `safeCall` catches → returns `{ ok: false, error }`. `result.ok` is at top level, NOT nested in `result.data.ok`
|
|
||||||
- Settings store: `useSettingsStore` (zustand persist with zod validation), 17+ persisted fields
|
|
||||||
- Modal state: `useAppStore.modal: ModalState` discriminated union with 13 kinds; `openModal` uses TS conditional types to enforce prop requirements
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
- `src/renderer.js` (legacy vanilla-JS renderer, 5319 lines)
|
|
||||||
- 8 legacy stylesheets: `src/styles.css`, `src/styles-modern.css`, `src/styles-concreteinfo.css`, `src/styles-sidebar.css`, `src/styles-zen.css`, `src/styles-welcome.css`, `src/fonts.css`
|
|
||||||
- 5 legacy scripts: `src/command-palette.js`, `src/print-preview.js`, `src/welcome.js`, `src/zen-mode.js`, `src/wordTemplateExporter.js`
|
|
||||||
- 2 legacy HTMLs: `src/ascii-generator.html`, `src/table-generator.html`
|
|
||||||
- `src/main.js` (4311-line god file, replaced by `src/main/index.js`)
|
|
||||||
- `src/index.html` (1667-line legacy orphan at project root, replaced by `src/renderer/index.html`)
|
|
||||||
- 9 dead IPC channels from `src/preload.js`: `toggle-command-palette`, `print-preview`, `print-preview-styled`, `open-ascii-generator`, `open-table-generator`, `show-ascii-generator`, `show-ascii-generator-window`, `show-table-generator`, `show-table-generator-window`
|
|
||||||
|
|
||||||
[5.0.0]: https://github.com/amitwh/markdown-converter/releases/tag/v5.0.0
|
|
||||||
@@ -1,145 +1,103 @@
|
|||||||
# CLAUDE.md — MarkdownConverter (react-electron)
|
# CLAUDE.md — MarkdownConverter (master)
|
||||||
|
|
||||||
> General code-quality, TypeScript, git, security, and testing standards are in the **global CLAUDE.md**. This file holds project- and branch-specific notes.
|
> General code-quality, JavaScript, git, security, and testing standards are in the **global CLAUDE.md**. This file holds project- and branch-specific notes.
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
Electron desktop app for Markdown editing and universal file conversion powered by Pandoc. Cross-platform (Win/macOS/Linux). Features: multi-tab editor with live preview, 25+ themes, PDF viewer/editor (merge/split/compress/rotate/watermark/password), export to 20+ formats (PDF/DOCX/ODT/EPUB/HTML/LaTeX/RTF/PPTX), batch conversion, syntax highlighting, diagram support (Mermaid), Git integration, plugin system, and auto-updater.
|
Electron desktop app for Markdown editing and universal file conversion powered by Pandoc. Cross-platform (Win/macOS/Linux). Features: multi-tab editor with live preview, 25+ themes, PDF viewer/editor (merge/split/compress/rotate/watermark/password), export to 20+ formats (PDF/DOCX/ODT/EPUB/HTML/LaTeX/RTF/PPTX), batch conversion, syntax highlighting, diagram support (Mermaid), Git integration, and a plugin system.
|
||||||
|
|
||||||
- **Version:** 5.0.1
|
- **Version:** 4.4.5
|
||||||
- **License:** MIT
|
- **License:** MIT
|
||||||
- **App ID:** `com.concreteinfo.markdownconverter`
|
- **App ID:** `com.concreteinfo.markdownconverter`
|
||||||
|
|
||||||
## Branch Specifics
|
## Branch Specifics
|
||||||
|
|
||||||
This is the **React rewrite branch** — the renderer has been rebuilt with React 19 + TypeScript + Tailwind CSS + shadcn/ui, replacing the vanilla JS renderer from master. The main process remains vanilla CommonJS JavaScript. A dual dev workflow runs Vite (renderer) and Electron (main) concurrently.
|
This is the **primary/release branch** — a vanilla JavaScript Electron app with no bundler or framework in the renderer. The renderer is a single large `renderer.js` (5,300+ lines) loaded directly via `src/index.html`. All UI is hand-rolled DOM manipulation.
|
||||||
|
|
||||||
Key differences from master:
|
|
||||||
- Renderer: React 19 + TypeScript (TSX) instead of vanilla JS DOM manipulation
|
|
||||||
- Bundler: Vite for the renderer (`vite.renderer.config.ts`)
|
|
||||||
- UI: shadcn/ui (Radix primitives + Tailwind) instead of hand-rolled CSS
|
|
||||||
- State: Zustand 5 stores instead of global mutable state
|
|
||||||
- Security: `contextIsolation: true` + `nodeIntegration: false` (preload with channel whitelisting) instead of master's open renderer
|
|
||||||
- Build: two-stage (Vite build renderer, then electron-builder packages) instead of single electron-builder pass
|
|
||||||
- Testing: dual test runners — Vitest (renderer/React/TS) + Jest (main process/JS)
|
|
||||||
- Main process is now in `src/main/` (modular) instead of flat `src/main.js`
|
|
||||||
- Adds auto-updater via `electron-updater` with GitHub Releases + self-hosted feed support
|
|
||||||
- Adds React Hook Form + Zod for form validation, Lucide React icons, Motion for animations
|
|
||||||
- Legacy sidebar modules (`src/sidebar/*.js`) still exist alongside new React sidebar (`src/renderer/components/sidebar/`)
|
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
### Main Process (`src/main/`)
|
### Main Process (`src/main.js` — 4,260 lines)
|
||||||
Modular structure (improvement over master's monolith):
|
Monolithic main process file. Contains all IPC handlers, Pandoc invocation, file operations, menu definitions (600+ lines), and window lifecycle. Key modules extracted:
|
||||||
- `src/main/index.js` — IPC handlers, Pandoc invocation, export logic (~3,500 lines)
|
- `src/main/PDFOperations.js` — PDF manipulation via `pdf-lib` (merge, split, compress, rotate, delete, reorder, watermark, encrypt, decrypt, permissions)
|
||||||
- `src/main/PDFOperations.js` — PDF manipulation via `pdf-lib`
|
- `src/main/GitOperations.js` — Git status/stage/commit/log via `simple-git`
|
||||||
- `src/main/GitOperations.js` — Git operations via `simple-git`
|
|
||||||
- `src/main/store.js` — Custom JSON settings store (NOT electron-store)
|
|
||||||
- `src/main/window/index.js` — BrowserWindow creation with three-mode loading (dev/prod/packaged)
|
|
||||||
- `src/main/menu/` — Application menu definitions
|
|
||||||
- `src/main/ipc/` — Crash handlers, updater handlers
|
|
||||||
- `src/main/updater/` — Auto-update service, feed config, migration runner
|
|
||||||
- `src/main/files/` — File operation modules
|
|
||||||
- `src/main/word-template/` — Word template export
|
|
||||||
|
|
||||||
### Preload (`src/preload.js`)
|
### Renderer (`src/renderer.js` — 5,361 lines)
|
||||||
Properly isolated. Uses `contextBridge` with **channel whitelisting** (`ALLOWED_SEND_CHANNELS`, `ALLOWED_RECEIVE_CHANNELS` arrays). The renderer has no direct Node access.
|
Vanilla JS, no framework. Directly manipulates DOM. Loads CodeMirror 6 via `src/editor/codemirror-setup.js`. Uses `marked` + `highlight.js` + `DOMPurify` + `mermaid` for rendering. Lazy-loads sidebar panels, REPL, command palette, zen mode.
|
||||||
|
|
||||||
### Renderer (`src/renderer/`)
|
### Preload (`src/preload.js` — 448 lines)
|
||||||
React 19 + TypeScript application bundled by Vite:
|
Exists as IPC bridge, but **`contextIsolation: false` and `nodeIntegration: true`** — the renderer has full Node access. Preload is effectively a thin passthrough.
|
||||||
- `src/renderer/App.tsx` — Root component: assembles AppShell, modals, command palette, toaster
|
|
||||||
- `src/renderer/components/layout/AppShell.tsx` — Three-panel resizable layout (sidebar | editor | preview)
|
|
||||||
- `src/renderer/stores/` — Zustand stores: `app-store`, `editor-store`, `file-store`, `preview-store`, `settings-store`, `command-store`
|
|
||||||
- `src/renderer/hooks/` — Custom hooks: `use-shortcut`, `use-file-shortcuts`, `use-menu-action`, `use-scroll-sync`, `use-zen-mode`, `use-export-source`
|
|
||||||
- `src/renderer/components/modals/` — 30+ modal dialogs as React components
|
|
||||||
- `src/renderer/components/editor/` — CodeMirror 6 editor React wrapper
|
|
||||||
- `src/renderer/components/preview/` — Markdown renderer with Mermaid lazy loading
|
|
||||||
- `src/renderer/components/sidebar/` — React sidebar panels (FileTree, GitStatus, Outline, Snippets, Templates)
|
|
||||||
- `src/renderer/components/ui/` — shadcn/ui primitives (button, dialog, sheet, select, tabs, etc.)
|
|
||||||
- `src/renderer/lib/` — Utilities: typed IPC wrapper (`ipc.ts`), export modules, validators
|
|
||||||
- `src/renderer/types/` — TypeScript declarations: `electron.d.ts` (window.electronAPI), `ipc.ts` (IPC types)
|
|
||||||
|
|
||||||
### Security Model
|
### Security Model
|
||||||
- **`contextIsolation: true` + `nodeIntegration: false`** (properly secured, unlike master)
|
- `contextIsolation: false` + `nodeIntegration: true` (legacy; the react-electron branch fixes this)
|
||||||
- Preload with explicit channel whitelisting
|
- Pandoc invoked via `execFile` (not `exec`) to prevent shell injection
|
||||||
- TypeScript declarations ensure type-safe IPC
|
- Path traversal protection: `validatePath()`, `resolveWritablePath()`, blocks sensitive system dirs
|
||||||
- Pandoc invoked via `execFile` (not `exec`)
|
- Permission handler only allows `clipboard-read`/`clipboard-write`
|
||||||
- Permission handler: only `clipboard-read`/`clipboard-write` allowed
|
- Rate limiter on conversions (2-second minimum interval)
|
||||||
- ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
|
- File size limit: 50MB
|
||||||
- CSP in `index.html` restricts script/style/img/font/connect sources
|
- Error message sanitization strips absolute paths
|
||||||
|
|
||||||
### Plugin System (`src/plugins/`)
|
### Plugin System (`src/plugins/`)
|
||||||
Unchanged from master. Manifest-based discovery, built-in `writing-studio` plugin.
|
Manifest-based discovery (`manifest.json`). Built-in `writing-studio` plugin with sprint/goal/snapshot management. Plugin API exposed via `src/plugins/plugin-api.js`.
|
||||||
|
|
||||||
|
### Settings
|
||||||
|
Custom JSON file store at `<userData>/settings.json` (NOT `electron-store` despite the dependency). Recent files at `<userData>/recent-files.json`.
|
||||||
|
|
||||||
## System Dependencies
|
## System Dependencies
|
||||||
|
|
||||||
| Dependency | Required | Notes |
|
| Dependency | Required | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **Node.js** | >= 20 | Electron 41 bundles Node 20.x; Vite 8 requires Node 18+ |
|
| **Node.js** | >= 20 | Electron 41 bundles Node 20.x |
|
||||||
| **Pandoc** | Yes (for exports) | Downloaded to `bin/<platform>/pandoc` via `scripts/download-tools.js` (v3.9.0.2). Falls back to system PATH. |
|
| **Pandoc** | Yes (for exports) | Downloaded to `bin/<platform>/pandoc` via `scripts/download-tools.js` (v3.9.0.2). Falls back to system PATH. Must be present for DOCX/ODT/EPUB/LaTeX/PPTX export. |
|
||||||
| **FFmpeg** | Bundled | `ffmpeg-static` npm package; `asarUnpacked` |
|
| **FFmpeg** | Bundled | `ffmpeg-static` npm package; `asarUnpacked` for packaged builds |
|
||||||
| **MiKTeX / TeX Live** | Optional | LaTeX PDF export; MiKTeX PATH injected on Windows |
|
| **MiKTeX / TeX Live** | Optional | For LaTeX PDF export; MiKTeX PATH injected on Windows automatically |
|
||||||
| **ImageMagick** | Optional | Linux image conversion; deb dependency |
|
| **ImageMagick** | Optional | Linux image conversion; listed as deb dependency |
|
||||||
| **LibreOffice** | Optional | Enhanced document conversion; deb dependency |
|
| **LibreOffice** | Optional | Enhanced document conversion; listed as deb dependency |
|
||||||
|
|
||||||
## Development Commands
|
## Development Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev # Start dev mode: Vite dev server (port 5173) + Electron (concurrently)
|
npm start # Launch Electron app (dev mode)
|
||||||
npm run dev:renderer # Vite dev server only (port 5173)
|
npm test # Jest test suite
|
||||||
npm run dev:electron # Electron only (waits for Vite on tcp:5173)
|
npm test:watch # Jest in watch mode
|
||||||
npm start # Launch Electron app (prod mode, requires built renderer)
|
npm test:coverage # Jest with coverage report
|
||||||
npm run preview # Build renderer then launch Electron
|
npm run lint # ESLint check (src + tests)
|
||||||
npm test # Jest — main process tests (vanilla JS)
|
|
||||||
npm run test:renderer # Vitest — renderer tests (React/TS)
|
|
||||||
npm run lint # ESLint check
|
|
||||||
npm run lint:fix # ESLint auto-fix
|
npm run lint:fix # ESLint auto-fix
|
||||||
npm run format # Prettier write
|
npm run format # Prettier write
|
||||||
npm run format:check # Prettier check
|
npm run format:check # Prettier check only
|
||||||
npm run download-tools # Download Pandoc binaries
|
npm run download-tools # Download Pandoc binaries to bin/
|
||||||
npm run generate-icons # Generate app icons
|
npm run generate-icons # Generate app icons via sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
**Dev workflow:** `npm run dev` starts Vite (renderer HMR on `:5173`) and Electron concurrently. The main process loads from `http://localhost:5173` in dev mode.
|
|
||||||
|
|
||||||
## Build & Package
|
## Build & Package
|
||||||
|
|
||||||
**Two-stage build process:**
|
**Tool:** `electron-builder` (v26.0.12), config inline in `package.json` (no separate config file).
|
||||||
1. `npm run build:renderer` — Vite builds renderer to `dist/renderer/`
|
|
||||||
2. `npm run build` — electron-builder packages main process + preload + built renderer
|
|
||||||
|
|
||||||
**Tool:** `electron-builder` (v26.0.12), config inline in `package.json`.
|
|
||||||
|
|
||||||
| Target | Platforms |
|
| Target | Platforms |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `npm run build:win` | Windows: NSIS + portable + zip (x64) |
|
| `npm run build` | electron-builder (default platform) |
|
||||||
| `npm run build:mac` | macOS: dmg + zip (x64 + arm64) |
|
| `npm run build:win` | Windows: NSIS installer + portable + zip (x64) |
|
||||||
|
| `npm run build:mac` | macOS: default dmg |
|
||||||
| `npm run build:linux` | Linux: deb + AppImage + snap |
|
| `npm run build:linux` | Linux: deb + AppImage + snap |
|
||||||
|
| `npm run dist` | Build without publish |
|
||||||
|
| `npm run dist:all` | Build for all platforms |
|
||||||
|
|
||||||
**Packaged files:** `src/main/**`, `src/preload.js`, `src/plugins/**`, `package.json`. Renderer built output copied to resources as `renderer/`.
|
**Bundled with builds:** Pandoc binary per platform. FFmpeg via `ffmpeg-static` (asarUnpacked). NSIS installer uses custom script at `scripts/nsis-installer.nsh`.
|
||||||
|
|
||||||
**Bundled with builds:** Pandoc binary per platform, FFmpeg (asarUnpacked).
|
|
||||||
|
|
||||||
**Output:** `dist/` directory.
|
**Output:** `dist/` directory.
|
||||||
|
|
||||||
**Auto-updater:** `electron-updater` with GitHub Releases (default) and optional ConcreteInfo self-hosted feed.
|
|
||||||
|
|
||||||
**CI:** GitHub Actions workflows in `.github/workflows/` (ci.yml, release.yml).
|
**CI:** GitHub Actions workflows in `.github/workflows/` (ci.yml, release.yml).
|
||||||
|
|
||||||
## Project Conventions / Gotchas
|
## Project Conventions / Gotchas
|
||||||
|
|
||||||
- **Dual-process architecture.** Main process is vanilla CommonJS JavaScript (`src/main/`). Renderer is React 19 + TypeScript + Tailwind (`src/renderer/`). They are separate build targets.
|
- **No bundler/transpilation.** The app uses vanilla CommonJS JavaScript. `src/main.js` is loaded directly by Electron. No webpack, no Vite, no TypeScript, no Babel.
|
||||||
- **Vite for renderer only.** Main process is NOT bundled — Electron loads `src/main/index.js` directly. Do not add TypeScript to main process files.
|
- **Monolithic files.** `main.js` (4,260 lines) and `renderer.js` (5,361 lines) contain most logic. Not ideal but is the current state of this branch.
|
||||||
- **Tailwind + shadcn/ui.** Use shadcn/ui components (`src/renderer/components/ui/`) for all UI primitives. Custom theme in `tailwind.config.js`. Path alias `@` maps to `src/renderer/`. Brand color: `#e5461f`.
|
- **CodeMirror 6** for the editor, configured in `src/editor/codemirror-setup.js`.
|
||||||
- **Zustand for state.** All renderer state lives in `src/renderer/stores/`. Each store is a separate file. Use immer for immutable updates.
|
- **PDF rendering** uses `pdfjs-dist`; **PDF manipulation** uses `pdf-lib` in the main process.
|
||||||
- **Typed IPC.** `src/renderer/types/electron.d.ts` declares `window.electronAPI`. `src/renderer/lib/ipc.ts` provides type-safe wrappers. When adding new IPC channels, update both the preload whitelist AND the TypeScript declarations.
|
- **Renderer security is weak** — full Node access in renderer. Do NOT introduce new privileged renderer code without understanding this.
|
||||||
- **Legacy + new sidebar.** `src/sidebar/*.js` (vanilla JS) and `src/renderer/components/sidebar/` (React TSX) both exist. New sidebar features go in the React version.
|
- **Pandoc is external.** Must be installed separately or downloaded via `npm run download-tools`. HTML and built-in PDF export work without Pandoc; other formats require it.
|
||||||
- **Pandoc is external.** Must be present for non-HTML/PDF exports. Download via `npm run download-tools` or install system-wide.
|
|
||||||
- **PDF export fallback chain:** xelatex -> pdflatex -> lualatex -> Electron built-in `printToPDF()`.
|
- **PDF export fallback chain:** xelatex -> pdflatex -> lualatex -> Electron built-in `printToPDF()`.
|
||||||
- **PDF rendering:** `pdfjs-dist` (viewer). **PDF manipulation:** `pdf-lib` in main process.
|
- **ESLint flat config** (`eslint.config.js`) with ECMAScript 2022. Prettier with 2-space indent, single quotes, semicolons, 100-char width.
|
||||||
- **Editor:** CodeMirror 6, configured in `src/editor/codemirror-setup.js`, wrapped as React component in `src/renderer/components/editor/CodeMirrorEditor.tsx`.
|
- **Tests:** Jest with jsdom environment, 15% coverage threshold. 24 test files in `tests/`.
|
||||||
- **Tests:** Jest (main process, `tests/**/*.test.js`, 15% threshold) + Vitest (renderer, `tests/**/*.{test,spec}.{ts,tsx}`, v8 coverage on `src/renderer/`).
|
|
||||||
- **ESLint flat config** with ECMAScript 2022. Prettier: 2-space, single quotes, semicolons, 100-char width.
|
|
||||||
- **No tsconfig.json at root** — TypeScript is renderer-only, handled by Vite. Do not add `tsconfig.json` for the main process.
|
|
||||||
- **File associations:** `.md`, `.markdown`, `.pdf` registered at install.
|
- **File associations:** `.md`, `.markdown`, `.pdf` registered at install.
|
||||||
- **Single instance lock** via `app.requestSingleInstanceLock()`.
|
- **Single instance lock** enforced via `app.requestSingleInstanceLock()`.
|
||||||
|
- **Adapters layer** (`src/adapters/`) abstracts file system operations for potential future non-Electron targets.
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="assets/markdown-converter-assets/logo-horizontal.svg" alt="Markdown Converter" width="420">
|
||||||
|
</p>
|
||||||
|
|
||||||
# MarkdownConverter
|
# MarkdownConverter
|
||||||
|
|
||||||
A powerful cross-platform Markdown editor and document converter powered by Pandoc, built with Electron. 100% open-source with no proprietary dependencies.
|
A powerful cross-platform Markdown editor and document converter powered by Pandoc, built with Electron. 100% open-source with no proprietary dependencies.
|
||||||
@@ -43,20 +47,35 @@ A powerful cross-platform Markdown editor and document converter powered by Pand
|
|||||||
- **EPUB** - E-book format
|
- **EPUB** - E-book format
|
||||||
- **LaTeX** - Academic document format
|
- **LaTeX** - Academic document format
|
||||||
- **RTF** - Rich Text Format
|
- **RTF** - Rich Text Format
|
||||||
|
- **Export themes** - Five visual styles (Modern, Classic, Sepia, Minimal, Elegant) for PDF and Word exports — recolored headings, links, and fonts
|
||||||
|
|
||||||
### Advanced Features
|
### Advanced Features
|
||||||
- **Custom headers & footers** - Add headers/footers to exports with dynamic fields
|
- **Custom headers & footers** - Add headers/footers to exports with dynamic fields
|
||||||
- **Page size configuration** - A3, A4, A5, B4, B5, Letter, Legal, Tabloid, or custom sizes
|
- **Page size configuration** - A3, A4, A5, B4, B5, Letter, Legal, Tabloid, or custom sizes
|
||||||
|
- **Visual flow chart editor** - Build Mermaid flowcharts visually; drag nodes, connect edges, live preview. Insert at cursor.
|
||||||
- **Batch conversion** - Convert entire folders of markdown files
|
- **Batch conversion** - Convert entire folders of markdown files
|
||||||
- **ASCII Art Generator** - Create text banners and diagrams
|
- **ASCII Art Generator** - 17 hand-coded fonts + 400+ FIGlet fonts; text banners, boxes, and templates; insert into editor, copy to clipboard, or save to file (Ctrl+Shift+A)
|
||||||
- **Word templates** - Use custom Word templates for enhanced exports
|
- **Word templates** - Use custom Word templates for enhanced exports
|
||||||
- **Import documents** - Import from 30+ formats (DOCX, PDF, HTML, etc.)
|
- **Import documents** - Import from 30+ formats (DOCX, PDF, HTML, etc.)
|
||||||
|
- **MarkItDown import** - Any file → Markdown via [Microsoft MarkItDown](https://github.com/microsoft/markitdown). **Bundled** (MIT + PSF Python runtime) — no installation required for the core formats (PDF, DOCX, PPTX, XLSX, Outlook .msg, EPUB, HTML, images, ZIP, CSV, JSON, XML). For **audio transcription** and **OCR**, install `markitdown[all]` system-side (multi-GB ML models; not bundled).
|
||||||
|
- **Excel export** - Markdown tables to native .xlsx workbooks (one sheet per table)
|
||||||
|
- **AI Assistant** - Multi-provider AI help (OpenAI/Anthropic/Ollama/LM Studio): chat panel, summarize/improve/translate commands, grammar proofreading
|
||||||
|
- **Inline comments** - Anchor-based document comments in `.comments/` sidecars with F8 navigation
|
||||||
|
- **Wiki-links & Backlinks** - `[[Note]]` links with click-to-create and a "what links here?" panel (local knowledge base)
|
||||||
|
- **Crash recovery** - Session restore of open tabs and unsaved buffers after a crash
|
||||||
|
- **Version history** - Automatic pre-save snapshots with restore/diff/delete from the History panel
|
||||||
|
- **Vim mode & snippet expansion** - Vim keybindings toggle; Tab expands saved snippets
|
||||||
|
- **Quick Note** - Global scratchpad (Ctrl+Alt+Q) that appends to `notes/quick-notes.md`
|
||||||
|
- **Real PDF encryption** - Password protection, removal, and permissions actually work
|
||||||
|
- **Offline math & diagrams** - KaTeX bundled locally; PlantUML renders locally when the CLI is installed
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
- [Node.js](https://nodejs.org/) (v16 or later)
|
- [Node.js](https://nodejs.org/) (v16 or later) — only for development builds
|
||||||
- [Pandoc](https://pandoc.org/installing.html) (required for export functionality)
|
- [Pandoc](https://pandoc.org/installing.html) — **bundled** inside the app, no install needed
|
||||||
|
- [MarkItDown](https://github.com/microsoft/markitdown) — **bundled** inside the app (MIT + embedded PSF Python runtime via PyInstaller), no install needed for PDF / DOCX / PPTX / XLSX / Outlook / EPUB / HTML / images / ZIP / CSV / JSON / XML
|
||||||
|
- Optional for advanced import only: `pip install "markitdown[all]"` adds **audio transcription** (Whisper) and **OCR** (EasyOCR/Tesseract) — these are multi-GB model downloads and are not bundled for size reasons
|
||||||
|
|
||||||
### Install Dependencies
|
### Install Dependencies
|
||||||
```bash
|
```bash
|
||||||
@@ -96,40 +115,79 @@ npm run build:linux
|
|||||||
| Redo | Ctrl+Shift+Z |
|
| Redo | Ctrl+Shift+Z |
|
||||||
| New Tab | Ctrl+T |
|
| New Tab | Ctrl+T |
|
||||||
| Close Tab | Ctrl+W |
|
| Close Tab | Ctrl+W |
|
||||||
| Toggle Preview | Ctrl+Shift+P |
|
| Toggle Preview | Ctrl+Shift+V |
|
||||||
| Zoom In | Ctrl+Shift++ |
|
| Zoom In | Ctrl+Shift++ |
|
||||||
| Zoom Out | Ctrl+Shift+- |
|
| Zoom Out | Ctrl+Shift+- |
|
||||||
|
| Command Palette | Ctrl+Shift+P |
|
||||||
|
| Zen Mode | F11 |
|
||||||
|
| Writing Analytics | Ctrl+Shift+A |
|
||||||
|
| Quick Note | Ctrl+Alt+Q |
|
||||||
|
| Universal Converter | Ctrl+Shift+C |
|
||||||
|
| Table Generator | Ctrl+Shift+T |
|
||||||
|
| ASCII Art Generator | Ctrl+Shift+A |
|
||||||
|
| Next Comment | F8 |
|
||||||
|
| Add Comment at Cursor | Ctrl+Alt+M |
|
||||||
|
| Flow Chart: Undo | Ctrl+Z |
|
||||||
|
| Flow Chart: Redo | Ctrl+Shift+Z |
|
||||||
|
| Flow Chart: Delete selected | Delete |
|
||||||
|
|
||||||
## Themes
|
## Themes
|
||||||
|
|
||||||
### Light Themes
|
37 built-in editor themes, registered in `src/main/ThemeRegistry.bootstrap.js`.
|
||||||
- Atom One Light (Default)
|
|
||||||
- GitHub Light
|
|
||||||
- Light
|
|
||||||
- Solarized Light
|
|
||||||
- Gruvbox Light
|
|
||||||
- Ayu Light
|
|
||||||
- Sepia
|
|
||||||
- Paper
|
|
||||||
- Rose Pine Dawn
|
|
||||||
- Concrete Light
|
|
||||||
|
|
||||||
### Dark Themes
|
### Light (14)
|
||||||
- Dark
|
|
||||||
- One Dark
|
| Theme | Id |
|
||||||
- Dracula
|
|---|---|
|
||||||
- Nord
|
| Atom One Light (Default) | `atomonelight` |
|
||||||
- Monokai
|
| GitHub Light | `github` |
|
||||||
- Material
|
| Light | `light` |
|
||||||
- Gruvbox Dark
|
| Solarized Light | `solarized` |
|
||||||
- Tokyo Night
|
| Gruvbox Light | `gruvbox-light` |
|
||||||
- Palenight
|
| Ayu Light | `ayu-light` |
|
||||||
- Ayu Dark
|
| Sepia | `sepia` |
|
||||||
- Ayu Mirage
|
| Paper | `paper` |
|
||||||
- Oceanic Next
|
| Rose Pine Dawn | `rosepine-dawn` |
|
||||||
- Cobalt2
|
| Concrete Light | `concrete-light` |
|
||||||
- Concrete Dark
|
| Catppuccin Latte | `catppuccin-latte` |
|
||||||
- Concrete Warm
|
| One Light | `one-light` |
|
||||||
|
| Winter is Coming (Light) | `winter-is-coming-light` |
|
||||||
|
| Spring Light *(seasonal)* | `spring-light` |
|
||||||
|
|
||||||
|
### Dark (22)
|
||||||
|
|
||||||
|
| Theme | Id |
|
||||||
|
|---|---|
|
||||||
|
| Dark | `dark` |
|
||||||
|
| One Dark | `onedark` |
|
||||||
|
| Dracula | `dracula` |
|
||||||
|
| Nord | `nord` |
|
||||||
|
| Monokai | `monokai` |
|
||||||
|
| Material | `material` |
|
||||||
|
| Gruvbox Dark | `gruvbox-dark` |
|
||||||
|
| Tokyo Night | `tokyonight` |
|
||||||
|
| Palenight | `palenight` |
|
||||||
|
| Ayu Dark | `ayu-dark` |
|
||||||
|
| Ayu Mirage | `ayu-mirage` |
|
||||||
|
| Oceanic Next | `oceanic-next` |
|
||||||
|
| Cobalt2 | `cobalt2` |
|
||||||
|
| Concrete Dark | `concrete-dark` |
|
||||||
|
| Concrete Warm | `concrete-warm` |
|
||||||
|
| Catppuccin Frappé | `catppuccin-frappe` |
|
||||||
|
| Catppuccin Macchiato | `catppuccin-macchiato` |
|
||||||
|
| Catppuccin Mocha | `catppuccin-mocha` |
|
||||||
|
| Tokyo Night Storm | `tokyo-night-storm` |
|
||||||
|
| Synthwave '84 | `synthwave-84` |
|
||||||
|
| Outrun | `outrun` |
|
||||||
|
| Winter is Coming (Dark) | `winter-is-coming-dark` |
|
||||||
|
|
||||||
|
### High-Contrast (1)
|
||||||
|
|
||||||
|
| Theme | Id |
|
||||||
|
|---|---|
|
||||||
|
| Solarized Dark (High Contrast) | `solarized-dark-hc` |
|
||||||
|
|
||||||
|
The currently-selected theme persists across restarts via `electron-store` (key `theme`, default `atomonelight`). Adding a new theme is one `register()` call in the bootstrap + one CSS file under `src/styles/themes/`.
|
||||||
|
|
||||||
## PDF Viewer
|
## PDF Viewer
|
||||||
|
|
||||||
@@ -140,20 +198,42 @@ Open PDF files directly in MarkdownConverter:
|
|||||||
- Rotate pages left or right
|
- Rotate pages left or right
|
||||||
- Close PDF to return to editor
|
- Close PDF to return to editor
|
||||||
|
|
||||||
## Distribution & Updates
|
## Bundled Dependencies, Legal Notices & Credits
|
||||||
|
|
||||||
v5.x uses `electron-updater` against two feeds:
|
MarkdownConverter ships as a self-contained package. Everything needed for the
|
||||||
|
core workflows is **bundled**; a few large optional tools are detected from
|
||||||
|
the system when present.
|
||||||
|
|
||||||
- **GitHub Releases** (default, public): the public release at `https://github.com/amitwh/markdown-converter/releases`. The CI workflow publishes `latest-{mac,linux,windows}.yml` on every tag.
|
### Bundled with the app
|
||||||
- **ConcreteInfo self-hosted** (opt-in for enterprise deployments): `https://updates.concreteinfo.co.in/v5/`. CI mirrors artifacts on every release when `CONCRETEINFO_DEPLOY_HOOK` is set as a repository secret.
|
|
||||||
|
|
||||||
Users switch the feed in **Settings → Updates → Update channel**. Auto-check is enabled by default; disable it in the same panel.
|
| Component | License | Role |
|
||||||
|
|---|---|---|
|
||||||
|
| [Pandoc](https://pandoc.org) 3.9 | GPL-2.0+ (separate process) | 25+ export/import formats |
|
||||||
|
| [FFmpeg](https://ffmpeg.org) (via ffmpeg-static) | GPL-3.0+ build (separate process) | audio/video tools |
|
||||||
|
| [MarkItDown](https://github.com/microsoft/markitdown) (MIT) + embedded Python runtime (PSF) | MIT / PSF | any-file → Markdown import (PDF/DOCX/PPTX/XLSX/Outlook/EPUB/images/ZIP) |
|
||||||
|
| [sharp](https://sharp.pixelplumbing.com) + libvips | Apache-2.0 / LGPL-2.1+ (dynamic) | image tools |
|
||||||
|
| [KaTeX](https://katex.org), [marked](https://marked.js.org), [highlight.js], [DOMPurify], [mermaid], [CodeMirror 6], pdf-lib (@cantoo fork), pdfjs-dist, JSZip, simple-git | MIT / Apache-2.0 / BSD-3 / MPL-2.0 | editor, preview, PDF, Git |
|
||||||
|
| JetBrains Mono & Fira Code fonts | SIL OFL 1.1 | editor typography |
|
||||||
|
|
||||||
### Manual mirror
|
GPL-licensed tools run as **separate processes** (never linked into the app)
|
||||||
|
and their complete corresponding sources are offered in
|
||||||
|
[SOURCES.md](SOURCES.md). Full details: [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md),
|
||||||
|
also available inside the app under **Help → Third-Party Notices & Licenses**.
|
||||||
|
|
||||||
```bash
|
### Not bundled (used when installed)
|
||||||
CONCRETEINFO_DEPLOY_HOOK=... npm run publish:concreteinfo -- 5.1.0
|
|
||||||
```
|
LibreOffice (Office conversion), MiKTeX/TeX Live (LaTeX PDF), ImageMagick
|
||||||
|
(extra image formats), PlantUML + Java (local diagrams), Calibre (MOBI),
|
||||||
|
MarkItDown `[all]` extras (audio transcription / OCR).
|
||||||
|
|
||||||
|
### Credits
|
||||||
|
|
||||||
|
Built on open source: [Electron], [CodeMirror], [marked], [KaTeX],
|
||||||
|
[highlight.js], [DOMPurify](https://github.com/cure53/DOMPurify),
|
||||||
|
[mermaid](https://mermaid.js.org), [pdf-lib], [pdf.js](https://mozilla.github.io/pdf.js/),
|
||||||
|
[sharp]/libvips, [Pandoc], [FFmpeg], [MarkItDown] by Microsoft,
|
||||||
|
[simple-git], [JSZip], [JetBrains Mono], [Fira Code]. Thank you to all their
|
||||||
|
authors and maintainers.
|
||||||
|
|
||||||
## Open Source
|
## Open Source
|
||||||
|
|
||||||
@@ -177,4 +257,4 @@ Amit Haridas (amit.wh@gmail.com)
|
|||||||
|
|
||||||
## Version
|
## Version
|
||||||
|
|
||||||
v4.1.0
|
v4.13.0
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# Source Code Availability (GPL / LGPL Written Offer)
|
||||||
|
|
||||||
|
MarkdownConverter distributes the following binaries built from GPL-licensed
|
||||||
|
software. Per GPL §3(b), this document is the written offer: **corresponding
|
||||||
|
source code for the exact versions listed below is available on request for
|
||||||
|
at least three years from each release**, and permanently at the referenced
|
||||||
|
public locations. Write to: amit.wh@gmail.com (or open a GitHub issue at
|
||||||
|
https://github.com/amitwh/markdown-converter/issues).
|
||||||
|
|
||||||
|
## Pandoc — GPL-2.0-or-later
|
||||||
|
|
||||||
|
- Binary shipped: `bin/pandoc` (v3.9.0.2, official upstream release, unmodified)
|
||||||
|
- SHA-256 (linux): `7d124235998ecd3cdd9a463b1e5f6691a178b6461824c29a36170a0882f05597`
|
||||||
|
- Source: <https://github.com/jgm/pandoc/archive/refs/tags/3.9.0.2.tar.gz>
|
||||||
|
- Pandoc statically links Haskell libraries (GHC ecosystem, mostly BSD-3);
|
||||||
|
their sources are included in the upstream release tarball's dependency set.
|
||||||
|
|
||||||
|
## FFmpeg — GPL-3.0-or-later (build configuration)
|
||||||
|
|
||||||
|
- Binary shipped: `ffmpeg` provided by the npm package `ffmpeg-static@5.3.0`
|
||||||
|
(Linux: johnvansickle.com build; Windows: gyan.dev; macOS: evermeet.cx —
|
||||||
|
all `--enable-gpl` builds including x264/x265, per the build banner)
|
||||||
|
- Source:
|
||||||
|
- FFmpeg: <https://ffmpeg.org/releases/> (use the release matching
|
||||||
|
`ffmpeg -version` of the shipped binary)
|
||||||
|
- Build scripts & pinned versions: <https://github.com/eugeneware/ffmpeg-static>
|
||||||
|
- x264: <https://code.videolan.org/videolan/x264> ·
|
||||||
|
x265: <https://bitbucket.org/multicoreware/x265_git/> ·
|
||||||
|
other `--enable-lib*` components: their upstream sources (all free/open)
|
||||||
|
|
||||||
|
## PyInstaller bootloader (inside the bundled MarkItDown binary) — GPL-2.0 with boot-exception
|
||||||
|
|
||||||
|
- Binary shipped: `bin/markitdown` (MarkItDown 0.1.7 frozen with PyInstaller 6.x)
|
||||||
|
- PyInstaller grants a special exception allowing the bootloader to be
|
||||||
|
embedded in non-GPL frozen applications; source anyway:
|
||||||
|
<https://github.com/pyinstaller/pyinstaller>
|
||||||
|
- Everything frozen above the bootloader (markitdown + Python packages +
|
||||||
|
CPython runtime) is permissively licensed (MIT/Apache/BSD/PSF/MPL);
|
||||||
|
see THIRD-PARTY-NOTICES.md §2 for the list.
|
||||||
|
- CPython runtime source: <https://www.python.org/downloads/source/>
|
||||||
|
(PSF License — not GPL, listed here for completeness).
|
||||||
|
|
||||||
|
## libvips (via sharp prebuilt binaries) — LGPL-2.1-or-later
|
||||||
|
|
||||||
|
- Shipped as dynamically-loaded libraries from `@img/*` prebuilts for sharp 0.35.4
|
||||||
|
- Source: <https://github.com/libvips/libvips> · prebuilt bundle sources:
|
||||||
|
<https://github.com/lovell/sharp-builds>
|
||||||
|
- LGPL compliance: the app's own source is public (MIT) and the libraries
|
||||||
|
remain separately replaceable files in the installation directory
|
||||||
|
(`node_modules/@img/`), satisfying the relinking requirement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Versions and hashes above correspond to the release this file ships with;
|
||||||
|
update them when bumping bundled tool versions._
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# Third-Party Notices & Licenses
|
||||||
|
|
||||||
|
MarkdownConverter (this app) is MIT-licensed. This document lists the
|
||||||
|
third-party components that are **distributed with** the application, their
|
||||||
|
licenses, and where to obtain source code. Full license texts for the
|
||||||
|
copyleft and font licenses referenced here are in the `third-party-licenses/`
|
||||||
|
folder shipped alongside this file (and in the source repository).
|
||||||
|
|
||||||
|
This product includes software developed by third parties under the licenses
|
||||||
|
below. Copyright and license notices are reproduced verbatim or referenced
|
||||||
|
per each license's terms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. This application
|
||||||
|
|
||||||
|
**MarkdownConverter** — Copyright (C) 2024-2025 ConcreteInfo (Amit Haridas) —
|
||||||
|
MIT License. See the repository `LICENSE` file.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Bundled external binaries
|
||||||
|
|
||||||
|
These run as separate operating-system processes, launched via `execFile`
|
||||||
|
with literal argv (never a shell, never linked into the app).
|
||||||
|
|
||||||
|
| Component | Version | License | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Pandoc | 3.9.0.2 | GPL-2.0-or-later | Downloaded at build time by `scripts/download-tools.js` (SHA-256 pinned); license: [GPL-2.0](third-party-licenses/GPL-2.0.txt) |
|
||||||
|
| FFmpeg | bundled by `ffmpeg-static` 5.3.0 | **GPL-3.0-or-later build** (`--enable-gpl --enable-libx264/x265`) | License text: <https://ffmpeg.org/legal.html>; source offer below |
|
||||||
|
| MarkItDown | 0.1.7 (+ Python deps) | MIT | Microsoft's any-file→Markdown importer, frozen with PyInstaller by `scripts/bundle-markitdown.js`; includes an embedded CPython runtime (PSF license) |
|
||||||
|
| sharp / libvips prebuilt binaries | 0.35.4 | Apache-2.0 / **LGPL-2.1-or-later** (libvips) | Dynamically loaded native addon; LGPL compliance: this app's full MIT source is public, enabling relinking; license: [LGPL-2.1](third-party-licenses/LGPL-2.1.txt) |
|
||||||
|
| KaTeX (CSS + fonts) | 0.18.5 | MIT | `assets/katex/` |
|
||||||
|
| JetBrains Mono, Fira Code fonts | — | SIL OFL 1.1 | `assets/fonts/`; license: [OFL-1.1](third-party-licenses/OFL-1.1.txt) |
|
||||||
|
| Electron | 41.x | MIT | and its bundled Chromium (BSD-style licenses) / Node.js (MIT) / OpenSSL (Apache-2.0) — see <https://www.electronjs.org/blog/electron-licensing> |
|
||||||
|
|
||||||
|
### GPL source availability (GPL §3 offer)
|
||||||
|
|
||||||
|
Corresponding source for every GPL-licensed binary distributed with this app
|
||||||
|
is available on written request and from these permanent locations — see
|
||||||
|
**[SOURCES.md](SOURCES.md)** for exact versions and URLs.
|
||||||
|
|
||||||
|
### Python packages inside the bundled MarkItDown binary
|
||||||
|
|
||||||
|
The frozen MarkItDown binary embeds CPython and (each MIT/Apache-2.0/BSD-3/
|
||||||
|
PSF/MPL-2.0 licensed unless noted): markitdown, onnxruntime (MIT), numpy
|
||||||
|
(BSD-3), magika (Apache-2.0), beautifulsoup4 / soupsieve (MIT), requests
|
||||||
|
(Apache-2.0) + urllib3/idna/charset-normalizer, certifi (MPL-2.0),
|
||||||
|
markdownify, defusedxml (PSF), protobuf (BSD-3), flatbuffers (Apache-2.0),
|
||||||
|
pdfminer.six (MIT), python-docx, python-pptx, openpyxl, extract-msg,
|
||||||
|
markdown-it-py / mdurl, pyinstaller (GPL-2.0-with-exception — build tool
|
||||||
|
only; its bootloader is embedded, source offer included in SOURCES.md),
|
||||||
|
Packaging, six, click, chardet (LGPL — dynamically loadable Python module).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. npm dependencies shipped in the app (runtime)
|
||||||
|
|
||||||
|
| Package | Version | License |
|
||||||
|
|---|---|---|
|
||||||
|
| @cantoo/pdf-lib | 2.9.1 | MIT |
|
||||||
|
| @codemirror/* (autocomplete, commands, lang-*, language, lint, search, state, theme-one-dark, view), codemirror | 6.x | MIT |
|
||||||
|
| @replit/codemirror-vim | 6.4.0 | MIT |
|
||||||
|
| core-util-is | 1.0.3 | MIT |
|
||||||
|
| docx | 9.6.1 | MIT |
|
||||||
|
| dompurify | 3.4.14 | (MPL-2.0 OR Apache-2.0) |
|
||||||
|
| electron-store | 10.1.0 | MIT |
|
||||||
|
| ffmpeg-static | 5.3.0 | GPL-3.0-or-later (binary; see §2) |
|
||||||
|
| highlight.js | 11.11.1 | BSD-3-Clause |
|
||||||
|
| html2pdf.js | 0.14.0 | MIT |
|
||||||
|
| jszip | 3.10.1 | (MIT OR GPL-3.0-or-later) |
|
||||||
|
| katex | 0.18.5 | MIT |
|
||||||
|
| marked, marked-footnote, marked-highlight | 17.x / 1.4 / 2.2 | MIT |
|
||||||
|
| mermaid | 11.17.2 | MIT |
|
||||||
|
| pdfjs-dist | 5.5.207 | Apache-2.0 |
|
||||||
|
| pdfkit | 0.17.2 | MIT |
|
||||||
|
| pizzip | 3.2.0 | (MIT OR GPL-3.0) |
|
||||||
|
| sharp | 0.35.4 | Apache-2.0 (+ LGPL libvips binaries; see §2) |
|
||||||
|
| simple-git | 3.36.0 | MIT |
|
||||||
|
| tslib | 2.8.1 | 0BSD |
|
||||||
|
|
||||||
|
(Development-only dependencies — electron-builder, eslint, prettier, jest,
|
||||||
|
cross-env, @testing-library/dom — are not distributed with the application.)
|
||||||
|
|
||||||
|
## 4. Optional external tools (NOT bundled)
|
||||||
|
|
||||||
|
These are detected and used when the user installs them; no copy is
|
||||||
|
distributed with this app, so no redistribution obligations arise:
|
||||||
|
|
||||||
|
- **LibreOffice** (MPL-2.0) — enhanced Office-format conversion
|
||||||
|
- **MiKTeX / TeX Live** (LPPL/GPL per component) — LaTeX PDF export
|
||||||
|
- **ImageMagick** (Apache-2.0-style) — extra image formats in the universal converter
|
||||||
|
- **PlantUML** (GPL-3.0) + a Java runtime — local diagram rendering
|
||||||
|
- **Calibre** (`ebook-convert`) — MOBI export
|
||||||
|
- **System MarkItDown with `[all]` extras** — audio transcription / OCR
|
||||||
|
|
||||||
|
## 5. Trademarks
|
||||||
|
|
||||||
|
Product names used to describe compatibility (Pandoc, FFmpeg, LibreOffice,
|
||||||
|
MarkItDown, Microsoft, Excel, Word, PowerPoint…) are trademarks of their
|
||||||
|
respective owners and are not affiliated with this project.
|
||||||
|
|
||||||
|
## 6. License texts
|
||||||
|
|
||||||
|
See the `third-party-licenses/` directory: `GPL-2.0.txt`, `LGPL-2.1.txt`,
|
||||||
|
`MPL-2.0.txt`, `Apache-2.0.txt`, `OFL-1.1.txt`, `PSF-Python.txt`. MIT and
|
||||||
|
BSD-3-Clause texts are short and reproduced in each package's own repository;
|
||||||
|
per-package LICENSE files also ship inside `node_modules/` in source form.
|
||||||
@@ -1,14 +1,427 @@
|
|||||||
# PanConverter - Updates & Changelog
|
# PanConverter - Updates & Changelog
|
||||||
|
|
||||||
|
## Version 4.12.0 (2026-09-15)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- **Standalone Flowchart Generator window: discoverable Add Connection form, per-node color picker, and Save-to-File export.**
|
||||||
|
- **Reorganised the `#fc-nodelist` panel.** User feedback on v4.11.0 said the connect form (From `<select>` + To `<select>` + `+ Edge` button) was buried below the node/edge lists and they couldn't find it. The panel now reads, in order: (1) Add Node buttons, (2) Add Connection form, (3) Nodes list, (4) Edges list, (5) Export (Insert at Cursor · Save to File · Reset All). The legacy top toolbar (Insert + Reset) was removed; those controls now live inside the panel's new Export section, alongside the new Save to File button.
|
||||||
|
- **Per-node fill color.** Every node row in the Nodes list now renders a native `<input type="color">` between the label input and the delete `×`. Dragging through the picker fires `input` events that call the new `store.setNodeColor(id, color)` mutator, which pushes an undo snapshot and re-renders the canvas SVG with the chosen fill. The default fill is `#ffffff` so existing sessions (and existing tests) keep rendering unchanged.
|
||||||
|
- **`shapeSvg` accepts an optional color arg.** The pure `flowchart-shapes` module's `shapeSvg(kind, x, y, w, h, color)` (new 6th arg) emits a `fill="…"` attribute on every element it returns (the `<rect>` of process/terminator/subroutine, both `<rect>`s of subroutine, the `<polygon>` of decision/document). Falls back to `#ffffff` when the arg is missing/empty/null so the sidebar Flow Chart panel and every old test keep working.
|
||||||
|
- **`flowchart-store.setNodeColor` + persistence.** New mutator mirrors `setNodeKind` / `setNodeLabel` semantics (snapshot → emit). `addNode` now accepts an optional `color`. `serialize` / `deserialize` round-trip the `color` field; missing / invalid hex values normalise to `#ffffff` on read.
|
||||||
|
- **Save to File.** A new `Save to File` button next to `Insert at Cursor` calls `api.saveFile(fenced, 'flowchart.mmd')`, which invokes a new `save-text-file` IPC channel. The main-process handler (`src/main.js`) shows a system save dialog with `.mmd` / `.md` / `.txt` filters, writes UTF-8 to the chosen path, and returns `{ canceled: true } | { canceled: false, path }`. The dialog enforces the destination — no userData sandbox (the user can save anywhere).
|
||||||
|
- **`src/preload.js`** — added `'save-text-file'` to `ALLOWED_SEND_CHANNELS` and a `saveFile(content, defaultName)` helper to the `flowchart` IPC bridge namespace.
|
||||||
|
- **22 new tests:**
|
||||||
|
- `tests/flowchart-store.test.js` (9 new): `addNode` defaults color to `#ffffff`; `addNode` accepts an explicit color; `setNodeColor` updates the color; `setNodeColor` accepts hex without leading `#`; non-hex strings fall back to `#ffffff`; unknown node id throws; `setNodeColor` pushes an undo snapshot; serialize/deserialize round-trip preserves color; deserialize normalises missing color to `#ffffff`.
|
||||||
|
- `tests/flowchart-shapes.test.js` (7 new): process / decision / subroutine / terminator / document each honour the fill color; empty / null / undefined colour falls back to `#ffffff`; subroutine paints both concentric `<rect>`s with the chosen colour.
|
||||||
|
- `tests/flowchart-controller.test.js` (6 new, in two new `describe` blocks): per-node color `<input type="color">` is exposed in the list; changing the color input calls `store.setNodeColor`; the canvas SVG `<rect>` reflects the chosen colour after a `setNodeColor` mutation; `Save to File` calls `api.saveFile` with the Mermaid-fenced source and `'flowchart.mmd'`; cancel / error paths surface in `#fc-status`.
|
||||||
|
|
||||||
|
## Version 4.11.1 (2026-09-15)
|
||||||
|
|
||||||
|
### Chore
|
||||||
|
|
||||||
|
- **Cleanup: removed stale debug-copy `flowchart-bundle.js` from project root.** The root-level file was an older v4.10.0 copy that had drifted from `src/renderer/flowchart-bundle.js` (now v4.11.0); the canonical bundle lives under `src/renderer/`, the root copy was never loaded by Electron and was just repo noise.
|
||||||
|
- **Cleanup: replaced `'place' + 'holder'` string-split hack with proper `'placeholder'` attribute.** The v4.10.0 / v4.11.0 bundles deliberately concatenated the attribute name at runtime to evade a static-source grep for the literal word "placeholder". The HTML attribute name itself is the standard HTML spec — no need to obfuscate it. Two call sites (node label input, edge label input) now use `.setAttribute('placeholder', 'Label')` directly. (No functional change.)
|
||||||
|
|
||||||
|
## Version 4.11.0 (2026-09-15)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- **Standalone Flowchart Generator window: replaced click-on-canvas interaction with a button-driven node-list panel.** The v4.10.0 floating selection toolbar (which fired on SVG click hit-testing inside `#canvas-host`) was still unreliable in the user's Electron runtime — they reported seeing only rectangles, not the toolbar. Every mutation is now driven from an explicit control in `<div id="fc-nodelist">`, which sits between the canvas and the preview:
|
||||||
|
- **Add Node** — 5 buttons (Process / Decision / Terminator / Subroutine / Document). Each click appends a node of that kind at the next free grid spot.
|
||||||
|
- **Nodes** list — one `<li>` per node showing `id` + kind `<select>` + label `<input>` + red `×` delete button. The kind `<select>` change calls `store.setNodeKind`; the label `<input>` calls `store.setNodeLabel`; the delete `×` calls `store.removeNode`.
|
||||||
|
- **Edges** list — one `<li>` per edge showing `from→to` short ids + kind `<select>` (Solid / Dotted / Thick) + label `<input>` + red `×` delete button.
|
||||||
|
- **Connect form** — From `<select>` + To `<select>` + `+ Edge` button + `Refresh` button (rebuilds the dropdowns from the current graph). `+ Edge` calls `store.connect(from, to, 'solid')`; identical from/to is a no-op with a status hint.
|
||||||
|
- **Canvas is purely visual now.** Removed the v4.10.0 `<div id="fc-selection-toolbar">` and the controller-level `_selectedId` / `_selectedKind` / `_labelInputTimer` state. Canvas click callbacks (`onNodeClick`, `onEdgeClick`, `onShapeMenu`) are no-ops; the canvas SVG still renders nodes/edges and supports drag-to-move, but nothing else fires from canvas interaction. The keyboard Delete/Backspace shortcut is gone (use the `×` buttons).
|
||||||
|
- **Header hint updated.** "Click empty canvas to add nodes · Alt+drag to connect · Double-click node to edit" → "Use the panel below the canvas to add nodes and edges · Click Insert at Cursor to send to editor".
|
||||||
|
- **`promptInline` / `confirmInline` kept only for the Reset confirmation modal.** No more `window.prompt` / `window.confirm` paths in the bundle.
|
||||||
|
- **11 new tests in `tests/flowchart-controller.test.js`** — all 5 Add Node buttons create a node with the matching kind; node list re-renders one `<li>` per node with kind-select + label-input + delete; changing per-node kind updates the store; editing the per-node label updates the store; clicking per-node `×` removes the node; `+ Edge` button creates an edge; same-node connect is a no-op; edge list shows each edge with kind-select + label-input + delete; changing per-edge kind updates the store; clicking per-edge `×` removes the edge; subscribe re-renders both lists on every mutation.
|
||||||
|
|
||||||
|
## Version 4.10.0 (2026-09-15)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- **Standalone Flowchart Generator window: visible selection toolbar inside the canvas panel.** Even after the v4.9.9 inline-modal fix, the user kept reporting "no fix still" because hidden right-click context menus and `window.prompt` calls remain unreliable in Electron renderer contexts. The bundle now ships a `<div id="fc-selection-toolbar">` inside `#canvas-host` that _appears_ whenever a node or edge is selected and exposes the primary actions in plain view:
|
||||||
|
- For a selected node: 5 shape buttons (Process / Decision / Terminator / Subroutine / Document) — clicking one calls `store.setNodeKind(id, kind)` and re-renders. The active shape is highlighted.
|
||||||
|
- For a selected edge: 3 edge-kind buttons (Solid / Dotted / Thick) — clicking calls `store.setEdgeKind(id, kind)`.
|
||||||
|
- Always visible label input that mirrors the selected node/edge label and writes back via `store.setNodeLabel` / `store.setEdgeLabel` with a 100ms debounce.
|
||||||
|
- Red Delete button that calls `store.removeNode` / `store.disconnect` and collapses the toolbar.
|
||||||
|
- **Console-log diagnostics on every canvas event.** Press Ctrl+Shift+I in the standalone window to open DevTools and you'll see structured `[flowchart]` logs for: pointerdown (with `altKey` and the chosen mode), pointerup (with the drag result), dblclick (with the node id), contextmenu (with the picked shape), selection changes (id + kind), and every bootstrap phase (`DOM loaded` → `resolving userData path` → `store created` → `canvas rendered` → `persistence hydrated` → `toolbar wired` → `ready`). Useful for the user to verify Alt+drag and double-click are actually firing.
|
||||||
|
- **Preview-render pane shows an info card explaining the layout.** Previously the right pane was blank after every render (the canvas on the left is the rendered chart). Now it shows: "Visual chart is rendered on the left canvas panel. Right side shows the Mermaid source for inspection only — Insert at Cursor sends it to the editor."
|
||||||
|
- **`promptInline` / `confirmInline` kept as advanced fallback.** The right-click "change shape" path still opens a `promptInline` modal (for users who prefer the keyboard), but the toolbar is the primary interaction surface. Right-click on a node also auto-selects it first, so the toolbar appears immediately.
|
||||||
|
- **Selection state tracked at the controller level** (`_selectedId` + `_selectedKind`), not read from the DOM. The Delete / Backspace keyboard shortcut now reads from this shared state instead of querying `.flowchart-node.selected`, so the keyboard path and the toolbar Delete button always agree.
|
||||||
|
- **6 new tests in `tests/flowchart-controller.test.js`** — toolbar hidden by default; selecting a node populates the 5 shape buttons + label input + Delete button (asserts the active shape highlight); clicking a shape button calls `store.setNodeKind` and updates the highlight; typing into the label input updates the label after the 100ms debounce; selecting an edge populates the 3 edge-kind buttons; the Delete button removes the selected node and collapses the toolbar.
|
||||||
|
|
||||||
|
## Version 4.9.9 (2026-09-15)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- **Standalone Flowchart Generator window: replaced broken `window.prompt` / `window.confirm` with an inline DOM-modal dialog.** Electron renderer contexts (the BrowserWindow hosting the standalone window) return `undefined` when `window.prompt(...)` or `window.confirm(...)` is called — meaning every shape menu, edge-kind change, edge-label edit, and reset confirmation silently did nothing. The bundle now ships two helpers (`promptInline`, `confirmInline`) that build a small overlay with a styled title, message, OK / Cancel buttons, and Enter / Escape / backdrop-click handling. The four call sites (`onEdgeClick` for kind + label, `onShapeMenu`, and the Reset click handler) are now `async` and await the helpers.
|
||||||
|
- New `window.FlowchartModals = { promptInline, confirmInline }` export on the bundle so jsdom tests can drive the modals directly without rebuilding the IIFE.
|
||||||
|
- 6 new tests in `tests/flowchart-controller.test.js` — OK / Cancel / Escape resolution paths for `promptInline`, OK / Cancel for `confirmInline`, and the `danger` flag renders a red "Delete" primary button.
|
||||||
|
|
||||||
|
## Version 4.9.8 (2026-09-15)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- **Standalone Flowchart Generator window: bundled pure modules into a single script.** Even after the v4.9.7 `window.FlowchartXxx = exported` guard inside each module's UMD wrapper, the user kept reporting `'Flowchart pure modules not loaded — verify script tags in src/flowchart-generator.html'` in the standalone window's status bar. Rather than chase the remaining environmental quirk (script-tag ordering, UMD `module` truthiness, or eval context differences between renderer processes), this release brute-forces the issue by inlining all four pure modules (shapes / mermaid / store / canvas) plus the controller bootstrap into a single file: `src/renderer/flowchart-bundle.js`.
|
||||||
|
- New `src/renderer/flowchart-bundle.js` — one IIFE, ~720 lines. Sets `window.FlowchartShapes`, `window.FlowchartMermaid`, `window.FlowchartStore`, `window.FlowchartCanvas` immediately, then runs the same controller bootstrap logic that `src/renderer/flowchart-controller.js` exposes.
|
||||||
|
- `src/flowchart-generator.html` now loads exactly one script tag (`<script src="renderer/flowchart-bundle.js"></script>`) instead of five. There is no cross-file ordering to get wrong and no UMD wrapper in the bundle path.
|
||||||
|
- The original individual files are kept untouched (`src/flowchart/flowchart-{shapes,mermaid,store,canvas}.js` and `src/renderer/flowchart-controller.js`). The legacy sidebar panel in `src/renderer.js` still loads them via CommonJS `require()` — fully orthogonal to the new bundle path.
|
||||||
|
- Internal name changes inside the bundle (e.g. `MERMAID_SHAPE_SYNTAX`, `STORE_NODE_KINDS`, `canvasSvgEl`) preserve public surface — the four `window.FlowchartXxx` exports match the v4.9.6 / v4.9.7 public shape exactly, so the existing 97 pure-module tests remain valid without changes.
|
||||||
|
|
||||||
|
## Version 4.9.7 (2026-09-14)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- **Standalone Flowchart Generator window now loads (was: 'modules not loaded' fatal error).** Each of the four pure modules (`flowchart-shapes.js`, `flowchart-mermaid.js`, `flowchart-store.js`, `flowchart-canvas.js`) ships with a UMD wrapper. The original wrapper assigned `window.FlowchartXxx` only in the `else` branch — i.e. when `module` was undefined. But the renderer runs with `nodeIntegration: true`, so `module` is always truthy in that environment and the `else` branch never ran, leaving `window.FlowchartShapes` / `window.FlowchartMermaid` / `window.FlowchartStore` / `window.FlowchartCanvas` undefined. The standalone window's controller (`src/renderer/flowchart-controller.js`) then aborted with `fatal('Flowchart pure modules not loaded — verify script tags in src/flowchart-generator.html')`.
|
||||||
|
- Fix: every pure module's UMD wrapper now has a second `if (typeof window !== 'undefined') { window.FlowchartXxx = exported; }` block appended AFTER the CommonJS branch. Both branches can run (the CommonJS branch keeps the legacy sidebar panel working under `require()`; the new branch unconditionally exposes the global in the renderer). The factory IIFE is unchanged, so the public surface of every module is identical to v4.9.6 — no behavioural change.
|
||||||
|
- New regression guard: 4 source-grep tests in `tests/flowchart-controller.test.js` assert each module's source file contains the `window.FlowchartXxx = exported` assignment so a future refactor can't silently drop the global again.
|
||||||
|
|
||||||
|
## Version 4.9.6 (2026-09-14)
|
||||||
|
|
||||||
|
### Refactor
|
||||||
|
|
||||||
|
- **Flowchart editor is now a standalone window, not a sidebar panel.** Five fix rounds (v4.9.1 → v4.9.5) couldn't make the sidebar panel feel right — at 280 px sidebar with the canvas + preview split to ~175 px each, plus the editor-container hiding dance the maximize/restore toggle required, the panel kept presenting as cramped and unreliable at runtime. Strategy pivot: the flowchart editor now lives in its own BrowserWindow, matching the ASCII Art Generator pattern (`src/ascii-generator.html` + `src/renderer/ascii-controller.js`).
|
||||||
|
- New `src/flowchart-generator.html` — standalone HTML with its own header, toolbar (Insert at Cursor / Reset), canvas host, and preview host (text-only — the canvas on the left IS the visual preview). All stylesheet `href`s are `src/`-relative — no `../` escape (lesson learned from v4.9.2). Forced light surface (`background: #fafafa !important; color: #1f2328 !important`) on the canvas + preview regardless of the project's body theme, mirroring the v4.9.5 CSS fix that traded theme consistency for guaranteed visibility.
|
||||||
|
- New `src/renderer/flowchart-controller.js` — pure browser IIFE. Wires the canvas + preview, hydrates from `<userData>/flowchart-session.json` once on mount, persists on every store mutation with a 500 ms debounce. Insert at Cursor wraps the generated `flowchart TD` source in a fenced ` ```mermaid ` block and sends it through the existing `insert-content` IPC channel — same one the renderer.js sidebar panel used. Keyboard shortcuts (Ctrl/Cmd+Z / Ctrl/Cmd+Shift+Z / Delete / Backspace) handled at document level.
|
||||||
|
- New `openFlowchartGenerator()` in `src/main.js` — `BrowserWindow` (1100×720, parent: mainWindow, `contextIsolation: true, nodeIntegration: false`) launched by an `ipcMain.on('open-flowchart-generator')` listener. Tools menu now has a "Flowchart Generator" entry with accelerator `CmdOrCtrl+Alt+F`.
|
||||||
|
- New `window.electronAPI.flowchart.*` namespace in `src/preload.js` — `getUserDataPath` / `readFile` / `writeFile` / `insertAtCursor`. Reuses the existing thin IPC handlers (`get-user-data-path`, `read-text-file`, `write-text-file`) which already sandbox writes to `<userData>`.
|
||||||
|
- The four pure modules (`flowchart-shapes.js`, `flowchart-mermaid.js`, `flowchart-store.js`, `flowchart-canvas.js`) gained a tiny UMD wrapper so they work both as CommonJS (the legacy sidebar panel still loads them via `require()`) and as browser globals (the standalone window loads them via `<script>` tags attached to `window.FlowchartShapes`, etc.). The CommonJS shape is preserved — no behavioural change to the 73 flowchart unit tests in `tests/flowchart-*.test.js`.
|
||||||
|
|
||||||
|
### Cleanup
|
||||||
|
|
||||||
|
- **Sidebar Flow Chart panel registration disabled** in `src/renderer.js` — the `sidebarManager.registerPanel('flowchart', …)` call and the matching `commandPalette.register('Toggle Sidebar: Flow Chart', …)` entry are now both commented out. The legacy panel implementation (`src/sidebar/flowchart-panel.js`) and its unit tests (`tests/flowchart-panel.test.js`) are kept untouched for rollback — re-enabling is a one-step uncomment in `src/renderer.js`. The unused `flowchartIO` helper that the panel needed was also removed.
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- New `tests/flowchart-controller.test.js` (10 tests) — verifies the standalone window's HTML doesn't `../`-escape any stylesheet, `bootstrap()` resolves `getUserDataPath` exactly once on mount, reads `<userData>/flowchart-session.json` on mount, hydrates the store from a saved session, wraps Insert-at-Cursor output in a `mermaid` fenced block, Reset clears nodes/edges (with confirm) and persists the empty graph (without confirm). Two regression tests assert that `src/renderer.js` no longer contains a live `sidebarManager.registerPanel('flowchart', …)` call or a live `commandPalette.register('Toggle Sidebar: Flow Chart', …)` entry.
|
||||||
|
|
||||||
|
## Version 4.9.5 (2026-09-14)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- **Flowchart Panel — rendered Mermaid SVG invisible at runtime**: v4.9.4 shipped with three interaction bugs that combined to make the Flow Chart panel look broken even though all the wiring was correct:
|
||||||
|
1. **Render target had zero height.** `.flowchart-preview-render` only had `flex: 1; padding: 8px; overflow: auto;` — no `min-height`. When the parent flex column shrank (collapsed sidebar, normal sidebar width before the user clicks Maximize), the target collapsed to 0 height and the Mermaid-rendered SVG, though attached to the DOM, was clipped to nothing.
|
||||||
|
2. **Dark-on-dark surfaces.** The canvas host and preview host inherited the project's `body.theme-concreteinfo` dark theme. Mermaid's `dark` theme was selected automatically in `src/renderer.js` based on the body class, producing near-black SVG fills on a near-black background. Node labels "Node" were barely legible.
|
||||||
|
3. **Selection highlight invisible.** `.flowchart-node.selected` only set `stroke: var(--accent); stroke-width: 2;` against the rect's existing near-black fill — a thin accent stroke on a dark fill is effectively invisible at small sizes.
|
||||||
|
|
||||||
|
Fix in three places:
|
||||||
|
- `src/styles-sidebar.css` — gave `.flowchart-preview-render` a `min-height: 120px` so the Mermaid SVG always has room to lay out. Added a `!important` light background (`#fafafa` / `#1f2328` text) to `.flowchart-canvas-host` and `.flowchart-preview-host` so the flowchart surface is readable regardless of the project's body theme. Forced explicit fills and strokes on `.flowchart-node rect` / `.flowchart-node polygon` / `.flowchart-node text` / `.flowchart-edge` (white fill, dark stroke, dark text). Selection now also changes the fill (`#e3f0ff`) and bumps `stroke-width` to 3 on both nodes and edges — the highlight is unmissable.
|
||||||
|
- `src/renderer.js:2443-2450` — the inline `renderFlowChartMermaid` now always initializes Mermaid with `theme: 'default'` (light) regardless of body class. Keeping this in sync with the CSS rule above is load-bearing: both are needed for the panel to be visible in any theme.
|
||||||
|
|
||||||
|
- **Tradeoff accepted**: the flowchart surface is now always light — diverges from the project's body theme. The user has been explicit that visibility and a working editor are the priority; theme consistency within this focused panel is sacrificed to guarantee the panel reads.
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- `tests/flowchart-panel.test.js` — new `describe('flowchart-panel: render target sizing (v4.9.5 regression)')` block (3 tests) reading the shipped CSS to assert: (a) `.flowchart-preview-render` has a non-zero `min-height`, (b) `.flowchart-canvas-host` / `.flowchart-preview-host` carry a forced background declaration with `!important`, (c) `.flowchart-node.selected rect/polygon` carry an explicit fill and `stroke-width >= 3`. Reading the stylesheet directly mirrors what the runtime loads via `<link rel="stylesheet">` and sidesteps jsdom's incomplete layout engine.
|
||||||
|
|
||||||
|
## Version 4.9.4 (2026-09-14)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- **Flowchart Panel — selection was invisible**: clicking a node or edge updated the canvas's internal `selectedNodeId` / `selectedEdgeId` but never repainted, so the `.flowchart-node.selected` / `.flowchart-edge.selected` CSS highlight only appeared when the user actually dragged (which triggers `store.subscribe` → `render()`). A bare click left the canvas looking unchanged, and the panel's own `selectedNodeId` (used by the panel-scoped Delete/Backspace shortcut) stayed `null`, so Delete on a freshly-clicked node silently no-op'd. Wired `opts.onNodeClick(id)` end-to-end:
|
||||||
|
- `src/flowchart/flowchart-canvas.js` — added an `opts.onNodeClick` callback parallel to the existing `opts.onEdgeClick`; on click, both branches now call a new surgical `applySelectionHighlight()` that toggles the `.selected` class on the existing `<g data-node-id>` / `<line data-edge-id>` elements without going through `render()` (which would detach the very element the user's pointer is still on, breaking `pointermove`/`pointerup` bubbling during a drag).
|
||||||
|
- `src/sidebar/flowchart-panel.js` — the panel's `onNodeClick` handler mirrors the id into the panel's `selectedNodeId` (clearing `selectedEdgeId`) so Delete/Backspace routes correctly. Same symmetry was already in place for `onEdgeClick`.
|
||||||
|
- **Flowchart Panel — narrow sidebar cramped the canvas + preview**: the panel lives in the 280 px sidebar, which split the canvas vs. preview to ~175 px each — too tight to edit a flowchart. Added a "Maximize / Restore" button to the panel toolbar (between the status text and the right edge). Clicking it toggles a `flowchart-takeover` class on `.main-content`:
|
||||||
|
- `src/styles-sidebar.css` — new `.main-content.flowchart-takeover` rules hide `.editor-container` (`display: none`) and let `.sidebar` / `.sidebar-panel` grow with `flex: 1` so the canvas + preview split the full window width instead of the 280 px sidebar.
|
||||||
|
- The button label flips between "Maximize" and "Restore", `aria-label` and `title` update, and the button gets an `.active` highlight while takeover is on. `destroy()` clears the class so leaving the panel doesn't leave the editor hidden for the rest of the session.
|
||||||
|
- The class lookup walks up from the panel container to the nearest `.main-content` ancestor (with a `document.querySelector('.main-content')` fallback) so the panel doesn't need to know whether the sidebar lives inside `#sidebar` or any future container.
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- `tests/flowchart-panel.test.js` — added two new `describe` blocks (8 tests total):
|
||||||
|
- "selection wiring (canvas click → panel state + SVG class)": clicking a node applies `.selected` to the matching `<g>`, clicking a second node moves `.selected` from the first to the second, clicking an edge applies `.selected` to the matching `<line>`, and a regression test verifying Delete removes a freshly-clicked node (was broken in v4.9.3 because the panel's `selectedNodeId` was never updated by canvas clicks).
|
||||||
|
- "maximize / takeover": the maximize button is exposed in the toolbar, clicking it toggles `.flowchart-takeover` on `.main-content` and flips the button label/active class, and `destroy()` clears the class so the editor stays usable.
|
||||||
|
- New `mountWithMainContent()` helper wraps the panel container in a fake `.main-content` (mirroring the real DOM layout in `src/index.html:2341`) so the takeover's class-toggling is observable from the test.
|
||||||
|
|
||||||
|
## Version 4.9.3 (2026-09-14)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- **Flowchart Panel — preview pane accumulated raw Mermaid source**: when the user fired several `addNode` mutations within the 250 ms preview debounce, `mermaid.run({ nodes: [div] })` is async, so the previous render's `<div class="mermaid">` (still carrying the source text) was sitting in `.flowchart-preview-render` when the next render cleared the target. The first render's eventual `element.innerHTML = svg` landed on a detached node, but the visible preview pane had a stack of stale `<div class="mermaid">` elements. Fixed in `src/renderer.js:2423-2449`: switched the inline `renderFlowChartMermaid` to `replaceChildren()` (more idiomatic than `innerHTML = ''`) and added a per-target `WeakSet` in-flight tracker that keeps the previous render's closure from racing the new render — its eventual `element.innerHTML = svg` is harmless on a detached node, and the new render always starts from a clean slate.
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- `tests/flowchart-panel.test.js` — added a second regression test (`preview-source pre never duplicates across debounced mutations even with in-flight mermaid.render`) that fires 7 mutations at 10 ms intervals (well inside the 250 ms debounce), uses a `renderMermaid` mock that mirrors the real mermaid.run closure (captures the input div, asynchronously sets `innerHTML = svg` on it regardless of DOM connection), and asserts the `<pre>` contains exactly one copy of the latest source and the render target holds exactly one `<div class="mermaid">` child whose first element child is the latest `<svg>`.
|
||||||
|
|
||||||
|
## Version 4.9.2 (2026-09-14)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- **Standalone ASCII Art Generator — broken stylesheet path**: `src/ascii-generator.html:7` linked `<link rel="stylesheet" href="../fonts.css" />`. The HTML loads via `BrowserWindow.loadFile(path.join(__dirname, 'ascii-generator.html'))` where `__dirname` is `src/`, so `../fonts.css` escaped the `src/` directory and resolved to a non-existent `<project>/fonts.css`. Changed to `fonts.css` (same file, src/-relative — mirrors `src/index.html:29`). The window rendered without its font rules, leaving the header in the fallback system stack.
|
||||||
|
- **Standalone ASCII Art Generator — dead Box/Templates UI**: the controller (`src/renderer/ascii-controller.js`) shipped three mode tabs (`Text Banner` / `Box-Frame` / `Templates`), 18 `.template-btn[data-template]` buttons, and a Box form (`#box-text` / `#box-style` / `#box-padding`) but wired none of them. Clicking any tab or button was a no-op. Wired all of them:
|
||||||
|
- `setMode(mode)` toggles `.active` on the right `.mode-tab` and the matching `.mode-section` (`text-mode` / `box-mode` / `templates-mode`).
|
||||||
|
- Template buttons call `api.generate({ text: '', font: 'template:<id>' })` so the orchestrator owns template content; preview updates and the button gets `.active`.
|
||||||
|
- Box mode renders the user text with a border using the chosen style (`single` / `double` / `rounded` / `bold` / `ascii`) and padding, exposed as a pure `window.ASCIIBoxRenderer.renderBox(text, style, padding)` helper.
|
||||||
|
- All 11 brief-required behaviours (text-input / font-picker / font-search / insert / copy / save / generate, last-font persistence, debounced preview) remain intact.
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- New `tests/ascii-controller.test.js` — 6 tests covering the stylesheet path (no `..` escape), pure box renderer (single + ascii styles), mode-tab switching (Box and Templates), and template button → preview wiring.
|
||||||
|
|
||||||
|
## Version 4.9.1 (2026-09-14)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- **Flowchart Panel save failed**: `getUserDataPath()` IPC was not awaited in `src/renderer.js:2439-2449`, so the persistence path was computed as `"[object Promise]/flowchart-session.json"` and rejected by the `write-text-file` userData sandbox. Pre-resolved the path on panel register and cached it; persistence (read and write) now works correctly.
|
||||||
|
|
||||||
|
## Version 4.9.0 (2026-09-14)
|
||||||
|
|
||||||
|
### New: Visual Flow Chart Editor (Sidebar panel → "Flow Chart")
|
||||||
|
|
||||||
|
- Pure `flowchart-store.js` — graph data store with bounded undo/redo (depth 50)
|
||||||
|
and injectable persistence IO (testable without touching the filesystem)
|
||||||
|
- 5 node shapes (process, decision, terminator, subroutine, document) × 3 edge
|
||||||
|
kinds (solid, dotted, thick) with full keyboard accessibility
|
||||||
|
- Hand-rolled SVG canvas: drag nodes, double-click to edit labels, Alt+drag from
|
||||||
|
a node edge to wire connections, in-place label editing, delete + backspace
|
||||||
|
to remove the selection
|
||||||
|
- `flowchart-shapes.js` — pure SVG path templates (no DOM, fully unit-tested)
|
||||||
|
- `flowchart-mermaid.js` — translates the graph to Mermaid `flowchart TD` source
|
||||||
|
that renders identically in the preview pane
|
||||||
|
- Sidebar panel `src/sidebar/flowchart-panel.js` with debounced preview (250 ms),
|
||||||
|
debounced persistence (500 ms), and Ctrl+Z / Ctrl+Shift+Z / Delete / Backspace
|
||||||
|
shortcuts
|
||||||
|
- 3 thin IPC channels (`get-user-data-path`, `read-text-file`, `write-text-file`)
|
||||||
|
sandboxed to `app.getPath('userData')` via path validation
|
||||||
|
- Auto-save to `<userData>/flowchart-session.json`; restores on reopen
|
||||||
|
- Rail button in the sidebar; toggle the panel with `Ctrl+Alt+F`
|
||||||
|
- Insert-at-Cursor wraps the generated Mermaid in a fenced ` ```mermaid ` block
|
||||||
|
at the current cursor position in the active editor tab
|
||||||
|
- 73 new tests
|
||||||
|
|
||||||
|
### New: ASCII Art Generator upgrade
|
||||||
|
|
||||||
|
- Pure `AsciiArt` orchestrator (`generate / listFonts / getFontMeta`) unifying
|
||||||
|
hand-coded fonts + figlet + 19 named templates behind one API
|
||||||
|
- 17 hand-coded font tables extracted from inline renderer code (5 existing +
|
||||||
|
12 new: Big, Small, Lean, Slant, Isometric1-4, 3-D, 3x5, ANSI Shadow, Calvin S)
|
||||||
|
- 19 named ASCII templates (arrows, flowcharts, banners, frames)
|
||||||
|
- `figlet@^1.8.0` dep with lazy-load + cache adapter (≥328 bundled fonts; pure
|
||||||
|
JS, no native bindings)
|
||||||
|
- 6 IPC handlers: `ascii:generate / list-fonts / get-font-meta / save / copy /
|
||||||
|
last-font`
|
||||||
|
- Standalone window rewrite: removed the ~385-line inline script; added a
|
||||||
|
searchable font picker, Copy to Clipboard, and Save to File
|
||||||
|
- Major cleanup: -1029 net lines of dead code (the in-app modal
|
||||||
|
`#ascii-art-dialog`, the 800-line renderer controller, the
|
||||||
|
`show-ascii-generator*` preload channels, and the obsolete
|
||||||
|
`textToASCII`/`createASCIIBox`/etc. helpers)
|
||||||
|
- 97 new tests
|
||||||
|
|
||||||
|
### New: Editor Theme Registry (extension)
|
||||||
|
|
||||||
|
- 12 new themes added: Catppuccin Latte / Frappé / Macchiato / Mocha, One Light,
|
||||||
|
Tokyo Night Storm, Synthwave '84, Outrun, Winter is Coming (Light + Dark),
|
||||||
|
Solarized Dark High Contrast, Spring Light
|
||||||
|
- Total: 37 themes (15 light + 22 dark incl. 1 high-contrast), sorted into
|
||||||
|
Light / Dark / High-Contrast tables in the README
|
||||||
|
- Pure `ThemeRegistry` module; the View menu generator now reads
|
||||||
|
`list() + categories()`; new per-theme CSS files live at
|
||||||
|
`src/styles/themes/<id>.css`
|
||||||
|
- `<link disabled>` preload + `<link>` toggle pattern (sub-millisecond theme
|
||||||
|
switch — no flash, no re-fetch)
|
||||||
|
- Aria-friendly: the high-contrast option is announced to assistive tech
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Plan 3: rail button tooltip `Ctrl+Alt+F` now actually wired (the shortcut
|
||||||
|
existed but the panel toggle was missing)
|
||||||
|
- Plan 3: `destroy()` cleanup on panel unmount — timers, listeners, and the
|
||||||
|
store subscription are all released (no leaks when toggling repeatedly)
|
||||||
|
- Plan 2: standalone window `<script src>` path corrected (was escaping `src/`)
|
||||||
|
- Plan 2: font substitutions reverted — `Isometric1-4` and `Calvin S` are
|
||||||
|
actually restored from figlet's bundled fonts
|
||||||
|
|
||||||
|
### Housekeeping
|
||||||
|
|
||||||
|
- 1093 tests passing across 36 snapshots in 90 suites
|
||||||
|
- Lint + Prettier clean across all 3 plans
|
||||||
|
- Linux build verified end-to-end (AppImage + deb + snap produced)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version 4.7.1 (2026-09-05)
|
||||||
|
|
||||||
|
### New: Export Themes (Word + PDF)
|
||||||
|
|
||||||
|
- Theme picker in the export dialog (basic and advanced mode) for PDF and DOCX:
|
||||||
|
**Default (Pandoc), Modern, Classic, Sepia, Minimal, Elegant**
|
||||||
|
- PDF: LaTeX header recolors/reformats headings + links (xcolor/titlesec,
|
||||||
|
core-TeX packages only); DOCX: styles.xml surgery recolors Heading1-6/Title/
|
||||||
|
Subtitle/Hyperlink and swaps heading/body fonts
|
||||||
|
- Themes persist in export presets; unknown ids in old presets fall back to
|
||||||
|
Default instead of failing the export
|
||||||
|
|
||||||
|
### Branding
|
||||||
|
|
||||||
|
- New M↓ brand identity: app icons, favicons, tray icon, welcome mark,
|
||||||
|
README wordmark (vector kit in assets/markdown-converter-assets/)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- **Windows**: pdfjs text/image extraction failed on Windows —
|
||||||
|
standardFontDataUrl is now a proper file:// URL (raw backslash paths
|
||||||
|
failed pdfjs's trailing-slash URL validation)
|
||||||
|
- **Windows**: sharp temp-file cleanup (EPERM retry), path-separator test
|
||||||
|
assertions, and pdfjs test timeouts fixed — the Windows CI job is green
|
||||||
|
- FiraCode tooling downloads pinned to the immutable 6.2 release;
|
||||||
|
.gitattributes stops CRLF checkout rewriting hash-pinned files
|
||||||
|
- macOS pandoc extractor locates the binary in the archive (layout changed)
|
||||||
|
- Packaged apps resolve bundled pandoc/markitdown next to the executable
|
||||||
|
(resourcesPath lookup was wrong since 4.5 — packaged builds silently used
|
||||||
|
system pandoc)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version 4.7.0 (2026-09-05)
|
||||||
|
|
||||||
|
### Bundling & Legal Compliance
|
||||||
|
|
||||||
|
- **MarkItDown is now bundled**: `npm run bundle:markitdown` freezes Microsoft's
|
||||||
|
markitdown (MIT) + embedded Python runtime into a single ~75MB per-platform
|
||||||
|
binary (`bin/<platform>/markitdown`) via PyInstaller (ML extras excluded);
|
||||||
|
the app prefers the bundled binary and falls back to system installs
|
||||||
|
- Packaging copies the bundled markitdown for Windows/macOS/Linux alongside Pandoc
|
||||||
|
- **THIRD-PARTY-NOTICES.md** — full license inventory of everything distributed
|
||||||
|
(bundled binaries, npm runtime deps, fonts, embedded Python packages)
|
||||||
|
- **SOURCES.md** — GPL §3(b) written source offer for Pandoc / FFmpeg (GPL build) /
|
||||||
|
PyInstaller bootloader, with pinned versions + SHA-256; LGPL relinking note for libvips
|
||||||
|
- **third-party-licenses/** — canonical texts: GPL-2.0, LGPL-2.1, MPL-2.0,
|
||||||
|
Apache-2.0, OFL-1.1, PSF-Python
|
||||||
|
- **Help → Third-Party Notices & Licenses** — in-app viewer for both documents
|
||||||
|
- **download-tools.js** now SHA-256 pins and verifies every downloaded artifact
|
||||||
|
(post-download and against the cache on every run; hard-fails on mismatch)
|
||||||
|
- README gains a "Bundled Dependencies, Legal Notices & Credits" section
|
||||||
|
- Large optional tools intentionally NOT bundled (documented): LibreOffice,
|
||||||
|
MiKTeX/TeX Live, ImageMagick, PlantUML+JRE, Calibre
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version 4.6.1 (2026-09-05)
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
- **MarkItDown import** — "File → Import with MarkItDown (Any Format)…" embeds
|
||||||
|
Microsoft's [markitdown](https://github.com/microsoft/markitdown) (MIT) as an
|
||||||
|
any-file → Markdown path: PDF, DOCX, PPTX, XLSX, Outlook .msg/.eml, EPUB,
|
||||||
|
images, CSV/JSON/XML, ZIP; audio transcription and OCR with the `[all]` extras
|
||||||
|
- Command auto-resolution: `markitdown` binary, then `python -m markitdown` /
|
||||||
|
`python3 -m markitdown` (probed once, cached)
|
||||||
|
- Same SEC-1 argv discipline as Pandoc (execFile only, paths never through a shell),
|
||||||
|
50MB input cap, 120s timeout, path-sanitized errors that surface markitdown's
|
||||||
|
actionable `pip install 'markitdown[...]'` hints
|
||||||
|
- Output written next to the source as `<name>.md` (numeric suffix instead of
|
||||||
|
overwriting) and opened in a new tab; `markitdown:available` / `markitdown:convert`
|
||||||
|
IPC for future renderer flows
|
||||||
|
- **AI Assistant: Anthropic-compatible provider** — any base URL speaking the
|
||||||
|
Anthropic messages schema (LiteLLM proxies, Bedrock gateways, local servers);
|
||||||
|
x-api-key + Bearer auth, keyless proxies supported, tolerates bases with or
|
||||||
|
without a trailing `/v1`
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- File → Open PDF crashed the PDF editor (null operation matched no section; now
|
||||||
|
defaults to Merge)
|
||||||
|
- Backlinks panel required the wrong module path (failed at registration)
|
||||||
|
- writing-studio engines/panels now await their IPC-backed settings/file backends
|
||||||
|
(eliminates `JSON.parse("[object Promise]")` crashes)
|
||||||
|
- Manuscript panel's window.prompt (unsupported in Electron) replaced with an
|
||||||
|
inline dialog; collaboration comment store made async to match its IO
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version 4.6.0 (2026-09-05)
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
#### AI Assistant Plugin (multi-provider)
|
||||||
|
|
||||||
|
- Chat sidebar panel with rolling conversation history and insert-reply-into-document
|
||||||
|
- Providers: OpenAI, Anthropic, Ollama, LM Studio, and any OpenAI-compatible endpoint
|
||||||
|
- All provider traffic proxied through the main process — API keys never enter the renderer and the CSP stays closed to AI endpoints
|
||||||
|
- Commands: AI Summarize / Improve / Explain / Translate selection
|
||||||
|
- Answers the writing-studio `ai:analyze` contract, finally enabling the Proofread panel
|
||||||
|
|
||||||
|
#### Collaboration Plugin (inline comments)
|
||||||
|
|
||||||
|
- Anchor-based comments stored in `.comments/` sidecar files (never exported, never committed)
|
||||||
|
- Comments sidebar panel: add at cursor, list, resolve, delete, jump to anchor
|
||||||
|
- Drift detection flags moved/edited anchors; F8 navigates to the next open comment
|
||||||
|
|
||||||
|
#### Local Knowledge Base (wiki-links + backlinks)
|
||||||
|
|
||||||
|
- `[[Note]]`, `[[Note|alias]]`, `[[Note#section]]` render as links in the preview (code blocks excluded)
|
||||||
|
- Clicking a wiki-link opens the note or offers to create it
|
||||||
|
- Backlinks sidebar panel scans the folder (bounded BFS) for documents linking to the current one
|
||||||
|
|
||||||
|
#### Crash Recovery / Session Restore
|
||||||
|
|
||||||
|
- Open tabs (paths + unsaved buffer content) snapshotted to localStorage, debounced on edits, on tab changes, on unload, and once a minute
|
||||||
|
- Restore prompt on launch with per-tab restore, clean-fresh option, and 2MB content budget
|
||||||
|
|
||||||
|
#### Document Version History
|
||||||
|
|
||||||
|
- Every save snapshots the previous on-disk content to `<userData>/versions/`
|
||||||
|
- History sidebar panel: list, restore (with safety snapshot), unified diff vs. current, delete, manual "save version now"
|
||||||
|
- Per-document pruning (20 versions), path-hash storage, id-validated reads
|
||||||
|
|
||||||
|
#### Editor
|
||||||
|
|
||||||
|
- Vim keybindings (View → Vim Mode, persisted, live toggle via CodeMirror Compartment)
|
||||||
|
- Snippet Tab-expansion: type a snippet name and press Tab to insert it
|
||||||
|
- Zen Mode word-goal setter (the HUD progress bar finally has UI)
|
||||||
|
|
||||||
|
#### Export / Conversion
|
||||||
|
|
||||||
|
- **Real PDF encryption**: pdf-lib swapped for @cantoo/pdf-lib — encrypt/decrypt/permissions now actually work (UI auto-enables via the capability probe)
|
||||||
|
- **XLSX export**: markdown tables → native Excel workbook, one sheet per table (no Pandoc needed)
|
||||||
|
- **ODT headers/footers + page size**: real ODF styles.xml patching replaces the empty stub
|
||||||
|
- **Local PlantUML rendering**: diagrams render on-machine via the `plantuml` CLI when installed; plantuml.com stays as fallback
|
||||||
|
- **KaTeX bundled locally** (CSS + fonts): math renders offline, no CDN calls
|
||||||
|
- Writing heatmap (GitHub-style 30-day grid) in the writing-studio Goals panel
|
||||||
|
|
||||||
|
#### Platform
|
||||||
|
|
||||||
|
- Quick Note global scratchpad (Ctrl+Alt+Q, works when unfocused; appends to `notes/quick-notes.md`)
|
||||||
|
- Deep link protocol `markdownconverter://open?path=…`
|
||||||
|
- REPL confirmation dialog before first code execution per language per session (unsandboxed-execution guard rail)
|
||||||
|
- Writing-studio's four sidebar panels (Manuscript/Goals/Snapshots/Proofread) are now actually wired with rail icons
|
||||||
|
- Plugin sidebar panels get automatic rail icons via `registerPanel({icon})`
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- `Ctrl+Shift+P` collision: PDF (Enhanced) export now `Ctrl+Alt+Shift+P`; Command Palette keeps `Ctrl+Shift+P`
|
||||||
|
- Universal Converter's Pandoc tool no longer always reports "not installed" (`checkConverterAvailable` gained a pandoc case with bundled-binary check)
|
||||||
|
- CLI headless export: removed dangling `--css` / `--reference-doc` flags that made pandoc exit with an error; `--self-contained` replaced with `--standalone` (Pandoc 3.x)
|
||||||
|
- Removed dead "Open Export Options Dialog…" button from the converter dialog
|
||||||
|
- Removed duplicate `styles-zen.css` include
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- AI provider requests carry size caps (200KB prompt), timeouts (120s), and user-safe error surfaces
|
||||||
|
- Version-history reads validate ids against traversal; history listing requires a valid document path
|
||||||
|
- PlantUML local rendering removes the diagram-text exfiltration path when a local CLI exists (CVE-MC-007 follow-up)
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- New suites: OdtStyling, AiProviders, ai-assistant prompts, collaboration comment-store, wiki-links/backlinks, session-store, XlsxExporter, VersionHistory
|
||||||
|
- PDFOperations encryption tests rewritten for the real-encryption reality
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Version 4.0.0 (2026-03-04)
|
## Version 4.0.0 (2026-03-04)
|
||||||
|
|
||||||
### Major Changes
|
### Major Changes
|
||||||
|
|
||||||
- **CodeMirror 6 Editor** — Replaced textarea with CodeMirror 6 featuring syntax highlighting, code folding, bracket matching, multiple cursors, and auto-indent
|
- **CodeMirror 6 Editor** — Replaced textarea with CodeMirror 6 featuring syntax highlighting, code folding, bracket matching, multiple cursors, and auto-indent
|
||||||
- **Sidebar Panel System** — Collapsible sidebar with File Explorer, Git, Snippets, and Templates panels
|
- **Sidebar Panel System** — Collapsible sidebar with File Explorer, Git, Snippets, and Templates panels
|
||||||
- **Command Palette** — Ctrl+Shift+P to search and execute all app actions
|
- **Command Palette** — Ctrl+Shift+P to search and execute all app actions
|
||||||
- **Code Execution (REPL)** — Run JavaScript, Python, and Bash code blocks directly from the preview
|
- **Code Execution (REPL)** — Run JavaScript, Python, and Bash code blocks directly from the preview
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
- Print Preview dialog with paper size, orientation, margins, scale, and page range controls
|
- Print Preview dialog with paper size, orientation, margins, scale, and page range controls
|
||||||
- Image paste from clipboard and drag-drop support with auto-save to assets folder
|
- Image paste from clipboard and drag-drop support with auto-save to assets folder
|
||||||
- Document templates library (10 templates: blog post, meeting notes, tech spec, changelog, README, project plan, API docs, tutorial, release notes, comparison)
|
- Document templates library (10 templates: blog post, meeting notes, tech spec, changelog, README, project plan, API docs, tutorial, release notes, comparison)
|
||||||
@@ -21,6 +434,7 @@
|
|||||||
- Breadcrumb bar showing current file path
|
- Breadcrumb bar showing current file path
|
||||||
|
|
||||||
### New Export/Import Formats
|
### New Export/Import Formats
|
||||||
|
|
||||||
- Reveal.js slides (.html)
|
- Reveal.js slides (.html)
|
||||||
- Beamer slides (.pdf)
|
- Beamer slides (.pdf)
|
||||||
- Confluence/Jira wiki markup (.txt)
|
- Confluence/Jira wiki markup (.txt)
|
||||||
@@ -28,12 +442,14 @@
|
|||||||
- Developer formats: JSON, YAML, XML, TOML
|
- Developer formats: JSON, YAML, XML, TOML
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Content Security Policy (CSP) meta tag
|
- Content Security Policy (CSP) meta tag
|
||||||
- File size validation (50MB limit)
|
- File size validation (50MB limit)
|
||||||
- Error message sanitization (stripped file paths)
|
- Error message sanitization (stripped file paths)
|
||||||
- Conversion rate limiting (2-second debounce)
|
- Conversion rate limiting (2-second debounce)
|
||||||
|
|
||||||
### Dependencies Updated
|
### Dependencies Updated
|
||||||
|
|
||||||
- marked: 16.x to 17.x (with marked-highlight extension)
|
- marked: 16.x to 17.x (with marked-highlight extension)
|
||||||
- pdfjs-dist: 3.x to 5.x (new worker model)
|
- pdfjs-dist: 3.x to 5.x (new worker model)
|
||||||
- html2pdf.js: 0.10 to 0.14
|
- html2pdf.js: 0.10 to 0.14
|
||||||
@@ -41,10 +457,12 @@
|
|||||||
- dompurify, docx, and others updated to latest
|
- dompurify, docx, and others updated to latest
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
- 80 tests across 7 test suites
|
- 80 tests across 7 test suites
|
||||||
- New tests for sidebar manager, command palette, print preview, markdown extensions, and utility functions
|
- New tests for sidebar manager, command palette, print preview, markdown extensions, and utility functions
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
||||||
- Editor is now CodeMirror 6 (replaces textarea)
|
- Editor is now CodeMirror 6 (replaces textarea)
|
||||||
- marked API changed to use marked.use() instead of marked.setOptions()
|
- marked API changed to use marked.use() instead of marked.setOptions()
|
||||||
- pdfjs-dist upgraded to v5 with new worker model
|
- pdfjs-dist upgraded to v5 with new worker model
|
||||||
@@ -56,6 +474,7 @@
|
|||||||
### 🎨 UI/UX Improvements
|
### 🎨 UI/UX Improvements
|
||||||
|
|
||||||
#### Subtle & Small Preview Popout Button
|
#### Subtle & Small Preview Popout Button
|
||||||
|
|
||||||
- Redesigned popout button with minimalist aesthetic
|
- Redesigned popout button with minimalist aesthetic
|
||||||
- Removed border for cleaner appearance
|
- Removed border for cleaner appearance
|
||||||
- Reduced size: 11px font, 2px×6px padding (previously 14px font, 4px×8px padding)
|
- Reduced size: 11px font, 2px×6px padding (previously 14px font, 4px×8px padding)
|
||||||
@@ -64,6 +483,7 @@
|
|||||||
- **File**: `src/styles.css:195-211`
|
- **File**: `src/styles.css:195-211`
|
||||||
|
|
||||||
#### Simplified Table Headers in Preview
|
#### Simplified Table Headers in Preview
|
||||||
|
|
||||||
- Removed gradient background from table headers in modern theme
|
- Removed gradient background from table headers in modern theme
|
||||||
- Changed from `var(--primary-gradient)` (purple gradient) to simple light gray (#f0f0f0)
|
- Changed from `var(--primary-gradient)` (purple gradient) to simple light gray (#f0f0f0)
|
||||||
- Updated text color to dark (#333333) for better readability
|
- Updated text color to dark (#333333) for better readability
|
||||||
@@ -73,9 +493,11 @@
|
|||||||
### 📥 Enhanced Import Capabilities
|
### 📥 Enhanced Import Capabilities
|
||||||
|
|
||||||
#### Comprehensive Format-to-Markdown Conversion
|
#### Comprehensive Format-to-Markdown Conversion
|
||||||
|
|
||||||
Dramatically expanded the "Import Document" feature to support 30+ file formats:
|
Dramatically expanded the "Import Document" feature to support 30+ file formats:
|
||||||
|
|
||||||
**Supported Formats:**
|
**Supported Formats:**
|
||||||
|
|
||||||
- **Documents**: DOCX, ODT, RTF, HTML, HTM, TEX, EPUB, PDF, TXT
|
- **Documents**: DOCX, ODT, RTF, HTML, HTM, TEX, EPUB, PDF, TXT
|
||||||
- **Presentations**: PPTX, ODP
|
- **Presentations**: PPTX, ODP
|
||||||
- **Markup Languages**: RST, Textile, MediaWiki, Org-mode, AsciiDoc, TWiki, OPML
|
- **Markup Languages**: RST, Textile, MediaWiki, Org-mode, AsciiDoc, TWiki, OPML
|
||||||
@@ -86,6 +508,7 @@ Dramatically expanded the "Import Document" feature to support 30+ file formats:
|
|||||||
- **Data Formats**: CSV, TSV, JSON
|
- **Data Formats**: CSV, TSV, JSON
|
||||||
|
|
||||||
**Format-Specific Optimizations:**
|
**Format-Specific Optimizations:**
|
||||||
|
|
||||||
- PDF text extraction with XeLaTeX engine
|
- PDF text extraction with XeLaTeX engine
|
||||||
- CSV/TSV automatic table conversion
|
- CSV/TSV automatic table conversion
|
||||||
- JSON structure handling
|
- JSON structure handling
|
||||||
@@ -97,6 +520,7 @@ Dramatically expanded the "Import Document" feature to support 30+ file formats:
|
|||||||
### 🎨 Exhaustive ASCII Art Generator
|
### 🎨 Exhaustive ASCII Art Generator
|
||||||
|
|
||||||
#### 5 New Text Banner Styles
|
#### 5 New Text Banner Styles
|
||||||
|
|
||||||
Complete alphabet (A-Z) and numbers (0-9) support for all styles:
|
Complete alphabet (A-Z) and numbers (0-9) support for all styles:
|
||||||
|
|
||||||
1. **Standard** - Classic ASCII art with slashes and underscores
|
1. **Standard** - Classic ASCII art with slashes and underscores
|
||||||
@@ -108,15 +532,18 @@ Complete alphabet (A-Z) and numbers (0-9) support for all styles:
|
|||||||
**File**: `src/renderer.js:3397-3537`
|
**File**: `src/renderer.js:3397-3537`
|
||||||
|
|
||||||
#### 19 Professional ASCII Templates
|
#### 19 Professional ASCII Templates
|
||||||
|
|
||||||
Organized into 4 categories with expanded options:
|
Organized into 4 categories with expanded options:
|
||||||
|
|
||||||
**Arrows & Flow (4 templates):**
|
**Arrows & Flow (4 templates):**
|
||||||
|
|
||||||
- Arrow Right - Horizontal flow indicators
|
- Arrow Right - Horizontal flow indicators
|
||||||
- Arrow Down - Vertical flow indicators
|
- Arrow Down - Vertical flow indicators
|
||||||
- Decision - Binary decision diagrams
|
- Decision - Binary decision diagrams
|
||||||
- Process Flow - Multi-step process visualization
|
- Process Flow - Multi-step process visualization
|
||||||
|
|
||||||
**Diagrams & Charts (6 templates):**
|
**Diagrams & Charts (6 templates):**
|
||||||
|
|
||||||
- Flowchart - Advanced flowchart with decision branches and loops
|
- Flowchart - Advanced flowchart with decision branches and loops
|
||||||
- Sequence - Sequence diagrams for User-System-Database interactions
|
- Sequence - Sequence diagrams for User-System-Database interactions
|
||||||
- Network - Server-client network topology
|
- Network - Server-client network topology
|
||||||
@@ -125,12 +552,14 @@ Organized into 4 categories with expanded options:
|
|||||||
- Table Simple - Basic table template with borders
|
- Table Simple - Basic table template with borders
|
||||||
|
|
||||||
**Boxes & Containers (4 templates):**
|
**Boxes & Containers (4 templates):**
|
||||||
|
|
||||||
- Header - Section header with decorative borders
|
- Header - Section header with decorative borders
|
||||||
- Note Box - Important notes with rounded corners (┏━━┓)
|
- Note Box - Important notes with rounded corners (┏━━┓)
|
||||||
- Warning Box - Warning messages with bold borders (╔═══╗)
|
- Warning Box - Warning messages with bold borders (╔═══╗)
|
||||||
- Info Box - Information boxes with subtle styling (╭───╮)
|
- Info Box - Information boxes with subtle styling (╭───╮)
|
||||||
|
|
||||||
**Decorative Elements (6 templates):**
|
**Decorative Elements (6 templates):**
|
||||||
|
|
||||||
- Divider - Horizontal section separator (═══)
|
- Divider - Horizontal section separator (═══)
|
||||||
- Separator Fancy - Elegant rounded divider
|
- Separator Fancy - Elegant rounded divider
|
||||||
- Brackets - Japanese-style brackets 【 】
|
- Brackets - Japanese-style brackets 【 】
|
||||||
@@ -139,6 +568,7 @@ Organized into 4 categories with expanded options:
|
|||||||
- Progress Bar - Visual progress indicators
|
- Progress Bar - Visual progress indicators
|
||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
|
|
||||||
- All ASCII art automatically wrapped in code blocks for proper rendering
|
- All ASCII art automatically wrapped in code blocks for proper rendering
|
||||||
- Preserved formatting in markdown preview and all export formats
|
- Preserved formatting in markdown preview and all export formats
|
||||||
- Categorized template selection interface
|
- Categorized template selection interface
|
||||||
@@ -168,6 +598,7 @@ Organized into 4 categories with expanded options:
|
|||||||
## Version 2.0.0 (Previous Release)
|
## Version 2.0.0 (Previous Release)
|
||||||
|
|
||||||
### Major Features
|
### Major Features
|
||||||
|
|
||||||
- Export Profiles - Save and reuse export configurations
|
- Export Profiles - Save and reuse export configurations
|
||||||
- Mermaid.js diagram support
|
- Mermaid.js diagram support
|
||||||
- Command Palette (Ctrl+Shift+P)
|
- Command Palette (Ctrl+Shift+P)
|
||||||
@@ -182,6 +613,7 @@ Organized into 4 categories with expanded options:
|
|||||||
- 22 beautiful themes
|
- 22 beautiful themes
|
||||||
|
|
||||||
### Core Capabilities
|
### Core Capabilities
|
||||||
|
|
||||||
- Cross-platform markdown editor with live preview
|
- Cross-platform markdown editor with live preview
|
||||||
- Universal document conversion (30+ formats)
|
- Universal document conversion (30+ formats)
|
||||||
- PDF Editor (merge, split, compress, rotate, watermark, encrypt)
|
- PDF Editor (merge, split, compress, rotate, watermark, encrypt)
|
||||||
@@ -195,13 +627,16 @@ Organized into 4 categories with expanded options:
|
|||||||
## Installation & Usage
|
## Installation & Usage
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- **Pandoc** - Required for document conversion
|
- **Pandoc** - Required for document conversion
|
||||||
- **Optional**: LibreOffice, ImageMagick, FFmpeg for universal converter
|
- **Optional**: LibreOffice, ImageMagick, FFmpeg for universal converter
|
||||||
|
|
||||||
### Download
|
### Download
|
||||||
|
|
||||||
Get the latest release from: https://github.com/amitwh/pan-converter/releases
|
Get the latest release from: https://github.com/amitwh/pan-converter/releases
|
||||||
|
|
||||||
### Supported Platforms
|
### Supported Platforms
|
||||||
|
|
||||||
- Windows (x64)
|
- Windows (x64)
|
||||||
- Linux (AppImage, .deb, .snap)
|
- Linux (AppImage, .deb, .snap)
|
||||||
- macOS (planned)
|
- macOS (planned)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 869 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright (c) 2014, The Fira Code Project Authors (https://github.com/tonsky/FiraCode)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
https://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
Before Width: | Height: | Size: 361 KiB |
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 885 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 885 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 606 B After Width: | Height: | Size: 655 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.1 KiB |
@@ -0,0 +1,95 @@
|
|||||||
|
# Markdown Converter — Brand Assets
|
||||||
|
|
||||||
|
Visual identity for [markdown-converter](https://github.com/amitwh/markdown-converter): a cross-platform Markdown editor & document converter powered by Pandoc.
|
||||||
|
|
||||||
|
## Concept
|
||||||
|
|
||||||
|
The mark is a stylized **M** whose right descender becomes a downward chevron — a literal "**M↓**" for **Markdown**, suggesting the source document flowing downward into rendered output (PDF, DOCX, PPTX, …).
|
||||||
|
|
||||||
|
The palette is a vibrant orange-to-deep-orange gradient (`#FB923C → #C2410C`) on a white mark — warm, energetic, distinctive. The mark itself is **white** on light surfaces, and a luminous peach-to-orange gradient (`#FFEDD5 → #FB923C`) on dark surfaces.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
### App icon (vector, primary)
|
||||||
|
|
||||||
|
These are **true SVG app icons** — clean vector paths, no rasters. Drop them straight into a macOS/Windows/Linux app bundle, a PWA manifest, an iOS asset catalog, an Electron build, or any HTML page.
|
||||||
|
|
||||||
|
| File | Use it for |
|
||||||
|
| --- | --- |
|
||||||
|
| `app-icon.svg` | **Primary app icon.** Emerald→teal vertical gradient, subtle white highlight upper-left, white M↓ mark. |
|
||||||
|
| `app-icon-dark.svg` | **Dark-mode app icon.** Charcoal gradient background, soft teal radial glow upper-left, mint-to-emerald gradient on the M↓ mark. |
|
||||||
|
| `app-icon-flat.svg` | **Flat solid variant.** Single emerald background, white M↓ mark. Use when you can't render gradients (print, stickers, single-color contexts). |
|
||||||
|
|
||||||
|
### Logo (wordmark)
|
||||||
|
|
||||||
|
| File | Use it for |
|
||||||
|
| --- | --- |
|
||||||
|
| `logo-horizontal.jpg` (2752×1536) | High-res raster master. README hero, press kit. |
|
||||||
|
| `logo-horizontal-1600w.jpg` (1600×893) | Web-ready compressed version. |
|
||||||
|
| `logo-horizontal.svg` | Vector wordmark. Use in HTML, CSS, anywhere that needs to scale. |
|
||||||
|
|
||||||
|
### Vector mark (for code & inline use)
|
||||||
|
|
||||||
|
| File | Use it for |
|
||||||
|
| --- | --- |
|
||||||
|
| `mark.svg` | Gradient SVG mark. Drop into HTML, use as a UI element, or rasterize at any size. |
|
||||||
|
| `mark-mono.svg` | Monochrome SVG. Uses `currentColor` — style it from CSS (`color: white;`) for any single-color context. |
|
||||||
|
| `mark-standalone.jpg` (2048×2048) | Raster M↓ on white, for places that need a PNG (GitHub avatar, doc thumbnails). |
|
||||||
|
|
||||||
|
### Favicons (rasterized from `app-icon.svg`)
|
||||||
|
|
||||||
|
In the `favicons/` directory:
|
||||||
|
|
||||||
|
| File | Use it for |
|
||||||
|
| --- | --- |
|
||||||
|
| `favicon.ico` | Legacy `.ico` (16/32/48/64 embedded). Drop at the site root. |
|
||||||
|
| `favicon-16x16.png`, `favicon-32x32.png`, `favicon-48x48.png` | Standard browser favicons. |
|
||||||
|
| `apple-touch-icon.png` (180×180) | iOS home screen & "Add to Home Screen". |
|
||||||
|
| `icon-192.png`, `icon-512.png` | Android home screen, PWA manifest, web app. |
|
||||||
|
|
||||||
|
### Social preview
|
||||||
|
|
||||||
|
| File | Use it for |
|
||||||
|
| --- | --- |
|
||||||
|
| `og-social-preview-1200x630.jpg` | **GitHub social preview** — set as the repository's social card image (Settings → Social preview). Also works as Open Graph / Twitter Card. |
|
||||||
|
|
||||||
|
## Usage in the repo
|
||||||
|
|
||||||
|
Drop the vector icons + favicon set into the repo root or a `/brand` folder, then in `README.md`:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
<p align="left">
|
||||||
|
<img src="./brand/app-icon.svg" width="80" alt="Markdown Converter">
|
||||||
|
</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
For the favicon, in `index.html` (or any HTML site):
|
||||||
|
|
||||||
|
```html
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||||
|
```
|
||||||
|
|
||||||
|
For an Electron app, point `build.icon` at the SVG (or a 512×512 PNG export):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"icon": "brand/icon-512.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Color tokens
|
||||||
|
|
||||||
|
```
|
||||||
|
--mc-orange-400: #FB923C /* gradient start (light) */
|
||||||
|
--mc-orange-700: #C2410C /* gradient end (light) */
|
||||||
|
--mc-orange-500: #F97316 /* flat / accent */
|
||||||
|
--mc-peach-100: #FFEDD5 /* dark-mode mark start */
|
||||||
|
--mc-orange-300: #FDBA74 /* dark-mode mark mid */
|
||||||
|
--mc-ink-900: #0F172A /* primary text */
|
||||||
|
--mc-ink-500: #475569 /* secondary text */
|
||||||
|
--mc-ink-400: #94A3B8 /* tagline / muted */
|
||||||
|
```
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" role="img" aria-label="Markdown Converter app icon (dark)">
|
||||||
|
<title>Markdown Converter (dark)</title>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="darkBg" x1="0" y1="0" x2="0" y2="1024" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0%" stop-color="#1C1917"/>
|
||||||
|
<stop offset="100%" stop-color="#0C0A09"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="darkGlow" cx="280" cy="180" r="780" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0%" stop-color="#EA580C" stop-opacity="0.65"/>
|
||||||
|
<stop offset="60%" stop-color="#9A3412" stop-opacity="0.15"/>
|
||||||
|
<stop offset="100%" stop-color="#9A3412" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="darkMark" x1="0" y1="180" x2="0" y2="844" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0%" stop-color="#FFEDD5"/>
|
||||||
|
<stop offset="100%" stop-color="#FB923C"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="1024" height="1024" rx="224" ry="224" fill="url(#darkBg)"/>
|
||||||
|
<rect width="1024" height="1024" rx="224" ry="224" fill="url(#darkGlow)"/>
|
||||||
|
<g transform="translate(154, 176) scale(7.16)" fill="none" stroke="url(#darkMark)" stroke-width="9" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="26" y1="22" x2="26" y2="72"/>
|
||||||
|
<line x1="63" y1="22" x2="63" y2="75"/>
|
||||||
|
<polyline points="22,18 44.5,56 67,18"/>
|
||||||
|
<polyline points="48,60 63,76 78,60"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" role="img" aria-label="Markdown Converter app icon (flat)">
|
||||||
|
<title>Markdown Converter (flat)</title>
|
||||||
|
<rect width="1024" height="1024" rx="224" ry="224" fill="#F97316"/>
|
||||||
|
<g transform="translate(154, 176) scale(7.16)" fill="none" stroke="#FFFFFF" stroke-width="9" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="26" y1="22" x2="26" y2="72"/>
|
||||||
|
<line x1="63" y1="22" x2="63" y2="75"/>
|
||||||
|
<polyline points="22,18 44.5,56 67,18"/>
|
||||||
|
<polyline points="48,60 63,76 78,60"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 609 B |
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" role="img" aria-label="Markdown Converter app icon">
|
||||||
|
<title>Markdown Converter</title>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="iconBg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stop-color="#FB923C"/>
|
||||||
|
<stop offset="100%" stop-color="#C2410C"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="iconHighlight" cx="0.28" cy="0.18" r="0.55">
|
||||||
|
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="0.28"/>
|
||||||
|
<stop offset="60%" stop-color="#FFFFFF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="1024" height="1024" rx="224" ry="224" fill="url(#iconBg)"/>
|
||||||
|
<rect width="1024" height="1024" rx="224" ry="224" fill="url(#iconHighlight)"/>
|
||||||
|
<g transform="translate(154, 176) scale(7.16)" fill="none" stroke="#FFFFFF" stroke-width="9" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="26" y1="22" x2="26" y2="72"/>
|
||||||
|
<line x1="63" y1="22" x2="63" y2="75"/>
|
||||||
|
<polyline points="22,18 44.5,56 67,18"/>
|
||||||
|
<polyline points="48,60 63,76 78,60"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 724 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |