{"owner":"jgraph","repo":"drawio-desktop","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# CLAUDE.md - AI Assistant Guide for draw.io Desktop\n\n## Project Overview\n\nDraw.io Desktop is an Electron-based desktop application that wraps the core draw.io diagramming editor (included as a git submodule). It enables creating flowcharts, UML diagrams, and more, with a security-first design that isolates diagram data from the internet.\n\n**Repository:** https://github.com/jgraph/drawio-desktop\n**License:** Apache 2.0\n**Version:** see `drawio/VERSION` (stamped into `package.json` by `npm run sync`)\n\n## Quick Reference\n\n```bash\n# Clone (MUST be recursive for submodule)\ngit clone --recursive https://github.com/jgraph/drawio-desktop.git\n\n# Install dependencies\nnpm install\n\n# Run application\nnpm start\n\n# Run with DevTools enabled\nDRAWIO_ENV=dev npm start\n\n# Sync version before building (required)\nnpm run sync\n\n# Build for specific platforms\nnpm run release-win       # Windows x64\nnpm run release-linux     # Linux (AppImage, deb, rpm)\nnpm run release-appx      # Windows Store\n```\n\n## Project Structure\n\n```\ndrawio-desktop/\n├── src/main/\n│   ├── electron.js           # Main Electron process (3,700+ lines)\n│   ├── electron-preload.js   # IPC bridge with contextBridge\n│   ├── args.js               # CLI argument definitions and parser\n│   ├── progress-bar.js       # Progress bar for long-running operations\n│   └── disableUpdate.js      # Generated by sync script\n├── src/test/\n│   ├── cli-args.test.js      # CLI argument parsing tests (npm test)\n│   └── msi-project-created.test.js # MSI shortcut icon hook tests (npm test)\n├── drawio/                   # Git submodule - core draw.io editor\n│   └── src/main/webapp/      # Web application loaded in Electron\n├── build/                    # Build resources\n│   ├── notarize.mjs          # macOS Quick Look setup, signing + notarization\n│   ├── sign-trusted.mjs      # Windows signing hook (Azure Trusted Signing)\n│   ├── fuses.mjs             # Electron security fuses\n│   ├── msi-project-created.mjs # msiProjectCreated hook: MSI shortcuts use exe icon, not the C:\\Windows\\Installer icon cache\n│   ├── dmg-hidden-files.mjs  # beforePack hook: parks hidden DMG support files outside the installer window\n│   ├── quicklook-preview.html # Quick Look preview page (viewer-static.min.js)\n│   ├── quicklook-entitlements.plist # Sandbox entitlements for .appex\n│   └── entitlements.mac.plist\n├── doc/\n│   ├── RELEASE_PROCESS.md    # Release workflow documentation\n│   └── BUILDING_FOR_PERSONAL_USE.md # Guide for unsigned fork/personal builds\n├── electron-builder-*.json   # Platform-specific build configs\n├── sync.cjs                  # Version sync script\n└── package.json\n```\n\n## Tech Stack\n\n- **Runtime:** Node.js 22.12+ (`engines` in `package.json`; CI builds on Node 24)\n- **Framework:** Electron (version pinned in `package.json`)\n- **Language:** JavaScript (ES6 modules)\n- **Build Tool:** electron-builder\n- **Package Manager:** npm\n\n## Key Files\n\n| File | Purpose |\n|------|---------|\n| `src/main/electron.js` | Main process: window management, IPC handlers, menus, auto-update |\n| `src/main/electron-preload.js` | Secure IPC bridge between renderer and main process |\n| `src/main/args.js` | CLI option definitions and argument parser (used by CLI export) |\n| `sync.cjs` | Pre-build script that syncs version from `drawio/VERSION` |\n| `electron-builder-*.json` | Platform-specific build configurations |\n| `build/sign-trusted.mjs` | electron-builder Windows signing hook (Azure Trusted Signing) |\n\n## Code Style\n\n- **ES6 modules** with `import`/`export`\n- **Tab indentation**\n- **Allman brace style** (opening brace on new line)\n- **camelCase** for variables, **PascalCase** for classes\n- No ESLint/Prettier - manual style consistency\n- Sparse comments; code clarity preferred\n\n## Git Conventions\n\n### Branches\n- `dev` - Main development branch (PR target)\n- `release` - Production releases\n- `releases/v*.*.*` - Version-specific release branches\n\n### Commit Messages\n- Lowercase sentence style without period\n- Issue references: `[jgraph/drawio-desktop#XXXX]`\n- Examples:\n  - `Fixes paste error`\n  - `Adds buffer as dependency [jgraph/drawio-desktop#2301]`\n  - `Prepare release v29.3.0`\n\n### Version Tags\nFormat: `v{MAJOR}.{MINOR}.{PATCH}` (e.g., `v29.3.0`)\nTags trigger CI/CD build workflows.\n\n## Build Process\n\n1. **Sync version:** `npm run sync` reads `drawio/VERSION` and updates `package.json`\n2. **Install:** `npm ci` for clean install\n3. **Build:** `electron-builder` with platform-specific config\n4. **Post-build:** Security fuses applied, Quick Look extension assembled (macOS), notarization (macOS)\n\n### Code Signing\n- **Windows:** Azure Trusted Signing via the `signtoolOptions.sign` hook `build/sign-trusted.mjs` (configured in `electron-builder-win*.json`, not CSC_LINK certificates). CI (`electron-builder-win.yml`) downloads the signing dlib, locates `signtool.exe`, and authenticates with `AZURE_TENANT_ID`/`AZURE_CLIENT_ID`/`AZURE_CLIENT_SECRET` secrets\n- **macOS:** Apple Developer certificate + notarization in `build/notarize.mjs`\n- **Unsigned builds:** `DRAWIO_UNSIGNED=true` skips signing (Windows) and notarization (macOS) for personal/fork builds\n\n### Personal / Fork Builds\n- `doc/BUILDING_FOR_PERSONAL_USE.md` documents building unsigned from a fork (the project is closed to contributions but Apache 2.0 licensed)\n- Set `DRAWIO_UNSIGNED=true` and run `electron-builder` directly with `--publish never`; use `npm run sync -- disableUpdate` so auto-update doesn't replace the custom build\n- `.github/workflows/personal-build.yml` is a manual (`workflow_dispatch`) workflow that builds unsigned installers on a fork with no secrets and attaches them as run artifacts\n\n> **CI override:** The release build workflows check out the private `jgraph/drawio-dev` repo at its `release` branch, copy the built `*.min.js` **and** `VERSION` into the public `drawio/` submodule tree, then run `npm run sync` as normal. This lets CI ship from an internal release that is ahead of the public `drawio` tag without any change to `sync.cjs`. Out-of-tree builders (who have no access to `drawio-dev`) fall through to the public submodule's `VERSION` as before.\n\n### Platform Build Commands\n| Command | Target |\n|---------|--------|\n| `npm run release-win` | Windows x64 (NSIS + MSI) |\n| `npm run release-win32` | Windows 32-bit |\n| `npm run release-win-arm64` | Windows ARM64 |\n| `npm run release-linux` | Linux (AppImage, deb, rpm) |\n| `npm run release-appx` | Windows Store |\n| `npm run release-snap` | Snap package |\n\n## Architecture Notes\n\n### Security Model\n- **Content Security Policy** prevents remote script execution\n- **contextBridge** exposes only specific APIs to renderer\n- **validateSender()** ensures IPC calls originate from local draw.io\n- No external transmission of diagram data\n- **Built-in plugins only** - external/third-party plugins were removed (07/2026). The `isPluginsEnabled` IPC action is retained, hardcoded `false`, so an older bundled webapp degrades to the \"plugins disabled\" dialog rather than failing\n\n### IPC Pattern\nThe preload script uses a request/response pattern with unique IDs:\n```javascript\n// Renderer sends request\nelectron.request({action: 'save', data: ...}, callbackId);\n\n// Main process handles and responds via IPC\nipcMain.on('request', (e, data) => { ... });\n```\n\n### macOS Quick Look Preview\n- Pressing Space in Finder shows a rendered preview of `.drawio` files\n- Uses `quicklookjs` to embed a Quick Look App Extension (`.appex`) in the app bundle\n- The `.appex` loads `viewer-static.min.js` (with embedded shapes) in a WKWebView\n- **Build flow:** `afterPack` (fuses.mjs) applies security fuses, then `afterSign` (notarize.mjs) assembles the `.appex`, signs it with sandbox entitlements, re-signs the outer `.app`, and notarizes\n- The `.appex` is inserted in `afterSign` (not `afterPack`) so it is never present unsigned during electron-builder's signing verification\n- Quick Look extensions require `app-sandbox`, but Electron helpers must not be sandboxed — so the `.appex` gets different entitlements than `entitlementsInherit`\n- The UTI `com.jgraph.drawio` is declared via `extendInfo` in `electron-builder-linux-mac.json`\n- `viewer-static.min.js` is saved to `build/` during CI before the cleanup step removes it from the drawio submodule; for local dev, it's read from the submodule directly\n\n### Auto-Update\n- Checks GitHub releases on startup\n- Disable via `DRAWIO_DISABLE_UPDATE=true` or `--disable-update` flag\n- Flatpak detection disables updates automatically\n\n### Data Storage\n- **macOS:** `~/Library/Application Support/draw.io`\n- **Windows:** `%APPDATA%\\draw.io\\`\n- Uses `electron-store` for persistent settings\n\n## Testing\n\n`npm test` runs the unit tests in `src/test/` (CLI argument parsing, MSI shortcut icon hook; Node's built-in test runner). Everything else is manual testing, documented in `doc/RELEASE_PROCESS.md`:\n- Launch, create diagram, add shapes, save, open\n- Export (PNG, PDF, SVG)\n- Undo/redo functionality\n- About dialog verification\n\n## CI/CD Workflows\n\n| Workflow | Trigger | Purpose |\n|----------|---------|---------|\n| `electron-builder.yml` | Version tag | macOS/Linux builds |\n| `electron-builder-win.yml` | Version tag | Windows builds (Azure Trusted Signing) |\n| `prepare-release.yml` | Manual | Automated release prep |\n| `hash-gen.yml` | Manual | Generate checksums |\n| `personal-build.yml` | Manual | Unsigned fork builds, artifacts only (no secrets, no publish) |\n| `stale.yml` | Schedule | Mark stale issues/PRs |\n\n## Important Constraints\n\n1. **Recursive clone required** - drawio submodule must be initialized\n2. **Run `npm run sync` before building** - Updates version from submodule\n3. **Version source of truth** - `drawio/VERSION` for public builds; `drawio-dev/VERSION` is copied over `drawio/VERSION` at CI time so the internal release number wins for packaged builds\n4. **Closed to contributions** - PRs not accepted; maintained by JGraph (forks for personal use are fine, see `doc/BUILDING_FOR_PERSONAL_USE.md`)\n5. **Node 22.12+ required** - see `engines` in `package.json`\n\n## Development Tips\n\n- Set `DRAWIO_ENV=dev` to auto-open DevTools\n- Use `npm start --enable-logging` for verbose output\n- If using symlink instead of submodule, also symlink `node_modules`\n- Main process logs to console; check terminal for errors\n\n## Key Dependencies\n\n| Package | Purpose |\n|---------|---------|\n| `electron` | Desktop app framework |\n| `electron-builder` | Build/package tool |\n| `electron-updater` | Auto-update mechanism |\n| `electron-store` | Persistent storage |\n| `electron-log` | Logging |\n| `@cantoo/pdf-lib` | PDF export |\n| `quicklookjs` | macOS Quick Look preview extension (dev) |\n\nCLI argument parsing is hand-rolled in `src/main/args.js` (no `commander`).\n"},"files":{"CLAUDE.md":"# CLAUDE.md - AI Assistant Guide for draw.io Desktop\n\n## Project Overview\n\nDraw.io Desktop is an Electron-based desktop application that wraps the core draw.io diagramming editor (included as a git submodule). It enables creating flowcharts, UML diagrams, and more, with a security-first design that isolates diagram data from the internet.\n\n**Repository:** https://github.com/jgraph/drawio-desktop\n**License:** Apache 2.0\n**Version:** see `drawio/VERSION` (stamped into `package.json` by `npm run sync`)\n\n## Quick Reference\n\n```bash\n# Clone (MUST be recursive for submodule)\ngit clone --recursive https://github.com/jgraph/drawio-desktop.git\n\n# Install dependencies\nnpm install\n\n# Run application\nnpm start\n\n# Run with DevTools enabled\nDRAWIO_ENV=dev npm start\n\n# Sync version before building (required)\nnpm run sync\n\n# Build for specific platforms\nnpm run release-win       # Windows x64\nnpm run release-linux     # Linux (AppImage, deb, rpm)\nnpm run release-appx      # Windows Store\n```\n\n## Project Structure\n\n```\ndrawio-desktop/\n├── src/main/\n│   ├── electron.js           # Main Electron process (3,700+ lines)\n│   ├── electron-preload.js   # IPC bridge with contextBridge\n│   ├── args.js               # CLI argument definitions and parser\n│   ├── progress-bar.js       # Progress bar for long-running operations\n│   └── disableUpdate.js      # Generated by sync script\n├── src/test/\n│   ├── cli-args.test.js      # CLI argument parsing tests (npm test)\n│   └── msi-project-created.test.js # MSI shortcut icon hook tests (npm test)\n├── drawio/                   # Git submodule - core draw.io editor\n│   └── src/main/webapp/      # Web application loaded in Electron\n├── build/                    # Build resources\n│   ├── notarize.mjs          # macOS Quick Look setup, signing + notarization\n│   ├── sign-trusted.mjs      # Windows signing hook (Azure Trusted Signing)\n│   ├── fuses.mjs             # Electron security fuses\n│   ├── msi-project-created.mjs # msiProjectCreated hook: MSI shortcuts use exe icon, not the C:\\Windows\\Installer icon cache\n│   ├── dmg-hidden-files.mjs  # beforePack hook: parks hidden DMG support files outside the installer window\n│   ├── quicklook-preview.html # Quick Look preview page (viewer-static.min.js)\n│   ├── quicklook-entitlements.plist # Sandbox entitlements for .appex\n│   └── entitlements.mac.plist\n├── doc/\n│   ├── RELEASE_PROCESS.md    # Release workflow documentation\n│   └── BUILDING_FOR_PERSONAL_USE.md # Guide for unsigned fork/personal builds\n├── electron-builder-*.json   # Platform-specific build configs\n├── sync.cjs                  # Version sync script\n└── package.json\n```\n\n## Tech Stack\n\n- **Runtime:** Node.js 22.12+ (`engines` in `package.json`; CI builds on Node 24)\n- **Framework:** Electron (version pinned in `package.json`)\n- **Language:** JavaScript (ES6 modules)\n- **Build Tool:** electron-builder\n- **Package Manager:** npm\n\n## Key Files\n\n| File | Purpose |\n|------|---------|\n| `src/main/electron.js` | Main process: window management, IPC handlers, menus, auto-update |\n| `src/main/electron-preload.js` | Secure IPC bridge between renderer and main process |\n| `src/main/args.js` | CLI option definitions and argument parser (used by CLI export) |\n| `sync.cjs` | Pre-build script that syncs version from `drawio/VERSION` |\n| `electron-builder-*.json` | Platform-specific build configurations |\n| `build/sign-trusted.mjs` | electron-builder Windows signing hook (Azure Trusted Signing) |\n\n## Code Style\n\n- **ES6 modules** with `import`/`export`\n- **Tab indentation**\n- **Allman brace style** (opening brace on new line)\n- **camelCase** for variables, **PascalCase** for classes\n- No ESLint/Prettier - manual style consistency\n- Sparse comments; code clarity preferred\n\n## Git Conventions\n\n### Branches\n- `dev` - Main development branch (PR target)\n- `release` - Production releases\n- `releases/v*.*.*` - Version-specific release branches\n\n### Commit Messages\n- Lowercase sentence style without period\n- Issue references: `[jgraph/drawio-desktop#XXXX]`\n- Examples:\n  - `Fixes paste error`\n  - `Adds buffer as dependency [jgraph/drawio-desktop#2301]`\n  - `Prepare release v29.3.0`\n\n### Version Tags\nFormat: `v{MAJOR}.{MINOR}.{PATCH}` (e.g., `v29.3.0`)\nTags trigger CI/CD build workflows.\n\n## Build Process\n\n1. **Sync version:** `npm run sync` reads `drawio/VERSION` and updates `package.json`\n2. **Install:** `npm ci` for clean install\n3. **Build:** `electron-builder` with platform-specific config\n4. **Post-build:** Security fuses applied, Quick Look extension assembled (macOS), notarization (macOS)\n\n### Code Signing\n- **Windows:** Azure Trusted Signing via the `signtoolOptions.sign` hook `build/sign-trusted.mjs` (configured in `electron-builder-win*.json`, not CSC_LINK certificates). CI (`electron-builder-win.yml`) downloads the signing dlib, locates `signtool.exe`, and authenticates with `AZURE_TENANT_ID`/`AZURE_CLIENT_ID`/`AZURE_CLIENT_SECRET` secrets\n- **macOS:** Apple Developer certificate + notarization in `build/notarize.mjs`\n- **Unsigned builds:** `DRAWIO_UNSIGNED=true` skips signing (Windows) and notarization (macOS) for personal/fork builds\n\n### Personal / Fork Builds\n- `doc/BUILDING_FOR_PERSONAL_USE.md` documents building unsigned from a fork (the project is closed to contributions but Apache 2.0 licensed)\n- Set `DRAWIO_UNSIGNED=true` and run `electron-builder` directly with `--publish never`; use `npm run sync -- disableUpdate` so auto-update doesn't replace the custom build\n- `.github/workflows/personal-build.yml` is a manual (`workflow_dispatch`) workflow that builds unsigned installers on a fork with no secrets and attaches them as run artifacts\n\n> **CI override:** The release build workflows check out the private `jgraph/drawio-dev` repo at its `release` branch, copy the built `*.min.js` **and** `VERSION` into the public `drawio/` submodule tree, then run `npm run sync` as normal. This lets CI ship from an internal release that is ahead of the public `drawio` tag without any change to `sync.cjs`. Out-of-tree builders (who have no access to `drawio-dev`) fall through to the public submodule's `VERSION` as before.\n\n### Platform Build Commands\n| Command | Target |\n|---------|--------|\n| `npm run release-win` | Windows x64 (NSIS + MSI) |\n| `npm run release-win32` | Windows 32-bit |\n| `npm run release-win-arm64` | Windows ARM64 |\n| `npm run release-linux` | Linux (AppImage, deb, rpm) |\n| `npm run release-appx` | Windows Store |\n| `npm run release-snap` | Snap package |\n\n## Architecture Notes\n\n### Security Model\n- **Content Security Policy** prevents remote script execution\n- **contextBridge** exposes only specific APIs to renderer\n- **validateSender()** ensures IPC calls originate from local draw.io\n- No external transmission of diagram data\n- **Built-in plugins only** - external/third-party plugins were removed (07/2026). The `isPluginsEnabled` IPC action is retained, hardcoded `false`, so an older bundled webapp degrades to the \"plugins disabled\" dialog rather than failing\n\n### IPC Pattern\nThe preload script uses a request/response pattern with unique IDs:\n```javascript\n// Renderer sends request\nelectron.request({action: 'save', data: ...}, callbackId);\n\n// Main process handles and responds via IPC\nipcMain.on('request', (e, data) => { ... });\n```\n\n### macOS Quick Look Preview\n- Pressing Space in Finder shows a rendered preview of `.drawio` files\n- Uses `quicklookjs` to embed a Quick Look App Extension (`.appex`) in the app bundle\n- The `.appex` loads `viewer-static.min.js` (with embedded shapes) in a WKWebView\n- **Build flow:** `afterPack` (fuses.mjs) applies security fuses, then `afterSign` (notarize.mjs) assembles the `.appex`, signs it with sandbox entitlements, re-signs the outer `.app`, and notarizes\n- The `.appex` is inserted in `afterSign` (not `afterPack`) so it is never present unsigned during electron-builder's signing verification\n- Quick Look extensions require `app-sandbox`, but Electron helpers must not be sandboxed — so the `.appex` gets different entitlements than `entitlementsInherit`\n- The UTI `com.jgraph.drawio` is declared via `extendInfo` in `electron-builder-linux-mac.json`\n- `viewer-static.min.js` is saved to `build/` during CI before the cleanup step removes it from the drawio submodule; for local dev, it's read from the submodule directly\n\n### Auto-Update\n- Checks GitHub releases on startup\n- Disable via `DRAWIO_DISABLE_UPDATE=true` or `--disable-update` flag\n- Flatpak detection disables updates automatically\n\n### Data Storage\n- **macOS:** `~/Library/Application Support/draw.io`\n- **Windows:** `%APPDATA%\\draw.io\\`\n- Uses `electron-store` for persistent settings\n\n## Testing\n\n`npm test` runs the unit tests in `src/test/` (CLI argument parsing, MSI shortcut icon hook; Node's built-in test runner). Everything else is manual testing, documented in `doc/RELEASE_PROCESS.md`:\n- Launch, create diagram, add shapes, save, open\n- Export (PNG, PDF, SVG)\n- Undo/redo functionality\n- About dialog verification\n\n## CI/CD Workflows\n\n| Workflow | Trigger | Purpose |\n|----------|---------|---------|\n| `electron-builder.yml` | Version tag | macOS/Linux builds |\n| `electron-builder-win.yml` | Version tag | Windows builds (Azure Trusted Signing) |\n| `prepare-release.yml` | Manual | Automated release prep |\n| `hash-gen.yml` | Manual | Generate checksums |\n| `personal-build.yml` | Manual | Unsigned fork builds, artifacts only (no secrets, no publish) |\n| `stale.yml` | Schedule | Mark stale issues/PRs |\n\n## Important Constraints\n\n1. **Recursive clone required** - drawio submodule must be initialized\n2. **Run `npm run sync` before building** - Updates version from submodule\n3. **Version source of truth** - `drawio/VERSION` for public builds; `drawio-dev/VERSION` is copied over `drawio/VERSION` at CI time so the internal release number wins for packaged builds\n4. **Closed to contributions** - PRs not accepted; maintained by JGraph (forks for personal use are fine, see `doc/BUILDING_FOR_PERSONAL_USE.md`)\n5. **Node 22.12+ required** - see `engines` in `package.json`\n\n## Development Tips\n\n- Set `DRAWIO_ENV=dev` to auto-open DevTools\n- Use `npm start --enable-logging` for verbose output\n- If using symlink instead of submodule, also symlink `node_modules`\n- Main process logs to console; check terminal for errors\n\n## Key Dependencies\n\n| Package | Purpose |\n|---------|---------|\n| `electron` | Desktop app framework |\n| `electron-builder` | Build/package tool |\n| `electron-updater` | Auto-update mechanism |\n| `electron-store` | Persistent storage |\n| `electron-log` | Logging |\n| `@cantoo/pdf-lib` | PDF export |\n| `quicklookjs` | macOS Quick Look preview extension (dev) |\n\nCLI argument parsing is hand-rolled in `src/main/args.js` (no `commander`).\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md - AI Assistant Guide for draw.io Desktop\n\n## Project Overview\n\nDraw.io Desktop is an Electron-based desktop application that wraps the core draw.io diagramming editor (included as a git submodule). It enables creating flowcharts, UML diagrams, and more, with a security-first design that isolates diagram data from the internet.\n\n**Repository:** https://github.com/jgraph/drawio-desktop\n**License:** Apache 2.0\n**Version:** see `drawio/VERSION` (stamped into `package.json` by `npm run sync`)\n\n## Quick Reference\n\n```bash\n# Clone (MUST be recursive for submodule)\ngit clone --recursive https://github.com/jgraph/drawio-desktop.git\n\n# Install dependencies\nnpm install\n\n# Run application\nnpm start\n\n# Run with DevTools enabled\nDRAWIO_ENV=dev npm start\n\n# Sync version before building (required)\nnpm run sync\n\n# Build for specific platforms\nnpm run release-win       # Windows x64\nnpm run release-linux     # Linux (AppImage, deb, rpm)\nnpm run release-appx      # Windows Store\n```\n\n## Project Structure\n\n```\ndrawio-desktop/\n├── src/main/\n│   ├── electron.js           # Main Electron process (3,700+ lines)\n│   ├── electron-preload.js   # IPC bridge with contextBridge\n│   ├── args.js               # CLI argument definitions and parser\n│   ├── progress-bar.js       # Progress bar for long-running operations\n│   └── disableUpdate.js      # Generated by sync script\n├── src/test/\n│   ├── cli-args.test.js      # CLI argument parsing tests (npm test)\n│   └── msi-project-created.test.js # MSI shortcut icon hook tests (npm test)\n├── drawio/                   # Git submodule - core draw.io editor\n│   └── src/main/webapp/      # Web application loaded in Electron\n├── build/                    # Build resources\n│   ├── notarize.mjs          # macOS Quick Look setup, signing + notarization\n│   ├── sign-trusted.mjs      # Windows signing hook (Azure Trusted Signing)\n│   ├── fuses.mjs             # Electron security fuses\n│   ├── msi-project-created.mjs # msiProjectCreated hook: MSI shortcuts use exe icon, not the C:\\Windows\\Installer icon cache\n│   ├── dmg-hidden-files.mjs  # beforePack hook: parks hidden DMG support files outside the installer window\n│   ├── quicklook-preview.html # Quick Look preview page (viewer-static.min.js)\n│   ├── quicklook-entitlements.plist # Sandbox entitlements for .appex\n│   └── entitlements.mac.plist\n├── doc/\n│   ├── RELEASE_PROCESS.md    # Release workflow documentation\n│   └── BUILDING_FOR_PERSONAL_USE.md # Guide for unsigned fork/personal builds\n├── electron-builder-*.json   # Platform-specific build configs\n├── sync.cjs                  # Version sync script\n└── package.json\n```\n\n## Tech Stack\n\n- **Runtime:** Node.js 22.12+ (`engines` in `package.json`; CI builds on Node 24)\n- **Framework:** Electron (version pinned in `package.json`)\n- **Language:** JavaScript (ES6 modules)\n- **Build Tool:** electron-builder\n- **Package Manager:** npm\n\n## Key Files\n\n| File | Purpose |\n|------|---------|\n| `src/main/electron.js` | Main process: window management, IPC handlers, menus, auto-update |\n| `src/main/electron-preload.js` | Secure IPC bridge between renderer and main process |\n| `src/main/args.js` | CLI option definitions and argument parser (used by CLI export) |\n| `sync.cjs` | Pre-build script that syncs version from `drawio/VERSION` |\n| `electron-builder-*.json` | Platform-specific build configurations |\n| `build/sign-trusted.mjs` | electron-builder Windows signing hook (Azure Trusted Signing) |\n\n## Code Style\n\n- **ES6 modules** with `import`/`export`\n- **Tab indentation**\n- **Allman brace style** (opening brace on new line)\n- **camelCase** for variables, **PascalCase** for classes\n- No ESLint/Prettier - manual style consistency\n- Sparse comments; code clarity preferred\n\n## Git Conventions\n\n### Branches\n- `dev` - Main development branch (PR target)\n- `release` - Production releases\n- `releases/v*.*.*` - Version-specific release branches\n\n### Commit Messages\n- Lowercase sentence style without period\n- Issue references: `[jgraph/drawio-desktop#XXXX]`\n- Examples:\n  - `Fixes paste error`\n  - `Adds buffer as dependency [jgraph/drawio-desktop#2301]`\n  - `Prepare release v29.3.0`\n\n### Version Tags\nFormat: `v{MAJOR}.{MINOR}.{PATCH}` (e.g., `v29.3.0`)\nTags trigger CI/CD build workflows.\n\n## Build Process\n\n1. **Sync version:** `npm run sync` reads `drawio/VERSION` and updates `package.json`\n2. **Install:** `npm ci` for clean install\n3. **Build:** `electron-builder` with platform-specific config\n4. **Post-build:** Security fuses applied, Quick Look extension assembled (macOS), notarization (macOS)\n\n### Code Signing\n- **Windows:** Azure Trusted Signing via the `signtoolOptions.sign` hook `build/sign-trusted.mjs` (configured in `electron-builder-win*.json`, not CSC_LINK certificates). CI (`electron-builder-win.yml`) downloads the signing dlib, locates `signtool.exe`, and authenticates with `AZURE_TENANT_ID`/`AZURE_CLIENT_ID`/`AZURE_CLIENT_SECRET` secrets\n- **macOS:** Apple Developer certificate + notarization in `build/notarize.mjs`\n- **Unsigned builds:** `DRAWIO_UNSIGNED=true` skips signing (Windows) and notarization (macOS) for personal/fork builds\n\n### Personal / Fork Builds\n- `doc/BUILDING_FOR_PERSONAL_USE.md` documents building unsigned from a fork (the project is closed to contributions but Apache 2.0 licensed)\n- Set `DRAWIO_UNSIGNED=true` and run `electron-builder` directly with `--publish never`; use `npm run sync -- disableUpdate` so auto-update doesn't replace the custom build\n- `.github/workflows/personal-build.yml` is a manual (`workflow_dispatch`) workflow that builds unsigned installers on a fork with no secrets and attaches them as run artifacts\n\n> **CI override:** The release build workflows check out the private `jgraph/drawio-dev` repo at its `release` branch, copy the built `*.min.js` **and** `VERSION` into the public `drawio/` submodule tree, then run `npm run sync` as normal. This lets CI ship from an internal release that is ahead of the public `drawio` tag without any change to `sync.cjs`. Out-of-tree builders (who have no access to `drawio-dev`) fall through to the public submodule's `VERSION` as before.\n\n### Platform Build Commands\n| Command | Target |\n|---------|--------|\n| `npm run release-win` | Windows x64 (NSIS + MSI) |\n| `npm run release-win32` | Windows 32-bit |\n| `npm run release-win-arm64` | Windows ARM64 |\n| `npm run release-linux` | Linux (AppImage, deb, rpm) |\n| `npm run release-appx` | Windows Store |\n| `npm run release-snap` | Snap package |\n\n## Architecture Notes\n\n### Security Model\n- **Content Security Policy** prevents remote script execution\n- **contextBridge** exposes only specific APIs to renderer\n- **validateSender()** ensures IPC calls originate from local draw.io\n- No external transmission of diagram data\n- **Built-in plugins only** - external/third-party plugins were removed (07/2026). The `isPluginsEnabled` IPC action is retained, hardcoded `false`, so an older bundled webapp degrades to the \"plugins disabled\" dialog rather than failing\n\n### IPC Pattern\nThe preload script uses a request/response pattern with unique IDs:\n```javascript\n// Renderer sends request\nelectron.request({action: 'save', data: ...}, callbackId);\n\n// Main process handles and responds via IPC\nipcMain.on('request', (e, data) => { ... });\n```\n\n### macOS Quick Look Preview\n- Pressing Space in Finder shows a rendered preview of `.drawio` files\n- Uses `quicklookjs` to embed a Quick Look App Extension (`.appex`) in the app bundle\n- The `.appex` loads `viewer-static.min.js` (with embedded shapes) in a WKWebView\n- **Build flow:** `afterPack` (fuses.mjs) applies security fuses, then `afterSign` (notarize.mjs) assembles the `.appex`, signs it with sandbox entitlements, re-signs the outer `.app`, and notarizes\n- The `.appex` is inserted in `afterSign` (not `afterPack`) so it is never present unsigned during electron-builder's signing verification\n- Quick Look extensions require `app-sandbox`, but Electron helpers must not be sandboxed — so the `.appex` gets different entitlements than `entitlementsInherit`\n- The UTI `com.jgraph.drawio` is declared via `extendInfo` in `electron-builder-linux-mac.json`\n- `viewer-static.min.js` is saved to `build/` during CI before the cleanup step removes it from the drawio submodule; for local dev, it's read from the submodule directly\n\n### Auto-Update\n- Checks GitHub releases on startup\n- Disable via `DRAWIO_DISABLE_UPDATE=true` or `--disable-update` flag\n- Flatpak detection disables updates automatically\n\n### Data Storage\n- **macOS:** `~/Library/Application Support/draw.io`\n- **Windows:** `%APPDATA%\\draw.io\\`\n- Uses `electron-store` for persistent settings\n\n## Testing\n\n`npm test` runs the unit tests in `src/test/` (CLI argument parsing, MSI shortcut icon hook; Node's built-in test runner). Everything else is manual testing, documented in `doc/RELEASE_PROCESS.md`:\n- Launch, create diagram, add shapes, save, open\n- Export (PNG, PDF, SVG)\n- Undo/redo functionality\n- About dialog verification\n\n## CI/CD Workflows\n\n| Workflow | Trigger | Purpose |\n|----------|---------|---------|\n| `electron-builder.yml` | Version tag | macOS/Linux builds |\n| `electron-builder-win.yml` | Version tag | Windows builds (Azure Trusted Signing) |\n| `prepare-release.yml` | Manual | Automated release prep |\n| `hash-gen.yml` | Manual | Generate checksums |\n| `personal-build.yml` | Manual | Unsigned fork builds, artifacts only (no secrets, no publish) |\n| `stale.yml` | Schedule | Mark stale issues/PRs |\n\n## Important Constraints\n\n1. **Recursive clone required** - drawio submodule must be initialized\n2. **Run `npm run sync` before building** - Updates version from submodule\n3. **Version source of truth** - `drawio/VERSION` for public builds; `drawio-dev/VERSION` is copied over `drawio/VERSION` at CI time so the internal release number wins for packaged builds\n4. **Closed to contributions** - PRs not accepted; maintained by JGraph (forks for personal use are fine, see `doc/BUILDING_FOR_PERSONAL_USE.md`)\n5. **Node 22.12+ required** - see `engines` in `package.json`\n\n## Development Tips\n\n- Set `DRAWIO_ENV=dev` to auto-open DevTools\n- Use `npm start --enable-logging` for verbose output\n- If using symlink instead of submodule, also symlink `node_modules`\n- Main process logs to console; check terminal for errors\n\n## Key Dependencies\n\n| Package | Purpose |\n|---------|---------|\n| `electron` | Desktop app framework |\n| `electron-builder` | Build/package tool |\n| `electron-updater` | Auto-update mechanism |\n| `electron-store` | Persistent storage |\n| `electron-log` | Logging |\n| `@cantoo/pdf-lib` | PDF export |\n| `quicklookjs` | macOS Quick Look preview extension (dev) |\n\nCLI argument parsing is hand-rolled in `src/main/args.js` (no `commander`).\n","category":"root","tokens":2687}]}