markupr 2.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/review-feedback.md +47 -0
- package/.eslintrc.json +35 -0
- package/.github/CODEOWNERS +16 -0
- package/.github/FUNDING.yml +1 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +56 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +54 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +89 -0
- package/.github/dependabot.yml +70 -0
- package/.github/workflows/ci.yml +184 -0
- package/.github/workflows/deploy-landing.yml +134 -0
- package/.github/workflows/nightly.yml +288 -0
- package/.github/workflows/release.yml +318 -0
- package/CHANGELOG.md +127 -0
- package/CLAUDE.md +137 -0
- package/CODE_OF_CONDUCT.md +9 -0
- package/CONTRIBUTING.md +390 -0
- package/LICENSE +21 -0
- package/PRODUCT_VISION.md +277 -0
- package/README.md +517 -0
- package/SECURITY.md +51 -0
- package/SIGNING_INSTRUCTIONS.md +284 -0
- package/assets/DMG_BACKGROUND_INSTRUCTIONS.md +130 -0
- package/assets/svg-source/dmg-background.svg +70 -0
- package/assets/svg-source/icon.svg +20 -0
- package/assets/svg-source/tray-icon-processing.svg +7 -0
- package/assets/svg-source/tray-icon-recording.svg +7 -0
- package/assets/svg-source/tray-icon.svg +6 -0
- package/assets/tray-complete.png +0 -0
- package/assets/tray-complete@2x.png +0 -0
- package/assets/tray-completeTemplate.png +0 -0
- package/assets/tray-completeTemplate@2x.png +0 -0
- package/assets/tray-error.png +0 -0
- package/assets/tray-error@2x.png +0 -0
- package/assets/tray-errorTemplate.png +0 -0
- package/assets/tray-errorTemplate@2x.png +0 -0
- package/assets/tray-icon-processing.png +0 -0
- package/assets/tray-icon-processing@2x.png +0 -0
- package/assets/tray-icon-processingTemplate.png +0 -0
- package/assets/tray-icon-processingTemplate@2x.png +0 -0
- package/assets/tray-icon-recording.png +0 -0
- package/assets/tray-icon-recording@2x.png +0 -0
- package/assets/tray-icon-recordingTemplate.png +0 -0
- package/assets/tray-icon-recordingTemplate@2x.png +0 -0
- package/assets/tray-icon.png +0 -0
- package/assets/tray-icon@2x.png +0 -0
- package/assets/tray-iconTemplate.png +0 -0
- package/assets/tray-iconTemplate@2x.png +0 -0
- package/assets/tray-idle.png +0 -0
- package/assets/tray-idle@2x.png +0 -0
- package/assets/tray-idleTemplate.png +0 -0
- package/assets/tray-idleTemplate@2x.png +0 -0
- package/assets/tray-processing-0.png +0 -0
- package/assets/tray-processing-0@2x.png +0 -0
- package/assets/tray-processing-0Template.png +0 -0
- package/assets/tray-processing-0Template@2x.png +0 -0
- package/assets/tray-processing-1.png +0 -0
- package/assets/tray-processing-1@2x.png +0 -0
- package/assets/tray-processing-1Template.png +0 -0
- package/assets/tray-processing-1Template@2x.png +0 -0
- package/assets/tray-processing-2.png +0 -0
- package/assets/tray-processing-2@2x.png +0 -0
- package/assets/tray-processing-2Template.png +0 -0
- package/assets/tray-processing-2Template@2x.png +0 -0
- package/assets/tray-processing-3.png +0 -0
- package/assets/tray-processing-3@2x.png +0 -0
- package/assets/tray-processing-3Template.png +0 -0
- package/assets/tray-processing-3Template@2x.png +0 -0
- package/assets/tray-processing.png +0 -0
- package/assets/tray-processing@2x.png +0 -0
- package/assets/tray-processingTemplate.png +0 -0
- package/assets/tray-processingTemplate@2x.png +0 -0
- package/assets/tray-recording.png +0 -0
- package/assets/tray-recording@2x.png +0 -0
- package/assets/tray-recordingTemplate.png +0 -0
- package/assets/tray-recordingTemplate@2x.png +0 -0
- package/build/DMG_BACKGROUND_SPEC.md +50 -0
- package/build/dmg-background.png +0 -0
- package/build/dmg-background@2x.png +0 -0
- package/build/entitlements.mac.inherit.plist +27 -0
- package/build/entitlements.mac.plist +41 -0
- package/build/favicon-16.png +0 -0
- package/build/favicon-180.png +0 -0
- package/build/favicon-192.png +0 -0
- package/build/favicon-32.png +0 -0
- package/build/favicon-48.png +0 -0
- package/build/favicon-512.png +0 -0
- package/build/favicon-64.png +0 -0
- package/build/icon-128.png +0 -0
- package/build/icon-16.png +0 -0
- package/build/icon-24.png +0 -0
- package/build/icon-256.png +0 -0
- package/build/icon-32.png +0 -0
- package/build/icon-48.png +0 -0
- package/build/icon-64.png +0 -0
- package/build/icon.icns +0 -0
- package/build/icon.ico +0 -0
- package/build/icon.iconset/icon_128x128.png +0 -0
- package/build/icon.iconset/icon_128x128@2x.png +0 -0
- package/build/icon.iconset/icon_16x16.png +0 -0
- package/build/icon.iconset/icon_16x16@2x.png +0 -0
- package/build/icon.iconset/icon_256x256.png +0 -0
- package/build/icon.iconset/icon_256x256@2x.png +0 -0
- package/build/icon.iconset/icon_32x32.png +0 -0
- package/build/icon.iconset/icon_32x32@2x.png +0 -0
- package/build/icon.iconset/icon_512x512.png +0 -0
- package/build/icon.iconset/icon_512x512@2x.png +0 -0
- package/build/icon.png +0 -0
- package/build/installer-header.bmp +0 -0
- package/build/installer-header.png +0 -0
- package/build/installer-sidebar.bmp +0 -0
- package/build/installer-sidebar.png +0 -0
- package/build/installer.nsh +45 -0
- package/build/overlay-processing.png +0 -0
- package/build/overlay-recording.png +0 -0
- package/build/toolbar-record.png +0 -0
- package/build/toolbar-screenshot.png +0 -0
- package/build/toolbar-settings.png +0 -0
- package/build/toolbar-stop.png +0 -0
- package/dist/main/index.mjs +12612 -0
- package/dist/preload/index.mjs +907 -0
- package/dist/renderer/assets/index-CCmUjl9K.js +19495 -0
- package/dist/renderer/assets/index-CUqz_Gs6.css +2270 -0
- package/dist/renderer/index.html +27 -0
- package/docs/AI_AGENT_QUICKSTART.md +42 -0
- package/docs/AI_PIPELINE_DESIGN.md +595 -0
- package/docs/API.md +514 -0
- package/docs/ARCHITECTURE.md +460 -0
- package/docs/CONFIGURATION.md +336 -0
- package/docs/DEVELOPMENT.md +508 -0
- package/docs/EXPORT_FORMATS.md +451 -0
- package/docs/GETTING_STARTED.md +236 -0
- package/docs/KEYBOARD_SHORTCUTS.md +334 -0
- package/docs/TROUBLESHOOTING.md +418 -0
- package/docs/landing/index.html +672 -0
- package/docs/landing/script.js +342 -0
- package/docs/landing/styles.css +1543 -0
- package/electron-builder.yml +140 -0
- package/electron.vite.config.ts +63 -0
- package/package.json +108 -0
- package/railway.json +12 -0
- package/scripts/build.mjs +51 -0
- package/scripts/generate-icons.mjs +314 -0
- package/scripts/generate-installer-images.cjs +253 -0
- package/scripts/generate-tray-icons.mjs +258 -0
- package/scripts/notarize.cjs +180 -0
- package/scripts/one-click-clean-test.sh +147 -0
- package/scripts/postinstall.mjs +36 -0
- package/scripts/setup-markupr.sh +55 -0
- package/setup +17 -0
- package/site/index.html +1835 -0
- package/site/package.json +11 -0
- package/site/railway.json +12 -0
- package/site/server.js +31 -0
- package/src/main/AutoUpdater.ts +392 -0
- package/src/main/CrashRecovery.ts +655 -0
- package/src/main/ErrorHandler.ts +703 -0
- package/src/main/HotkeyManager.ts +399 -0
- package/src/main/MenuManager.ts +529 -0
- package/src/main/PermissionManager.ts +420 -0
- package/src/main/SessionController.ts +1465 -0
- package/src/main/TrayManager.ts +540 -0
- package/src/main/ai/AIPipelineManager.ts +199 -0
- package/src/main/ai/ClaudeAnalyzer.ts +339 -0
- package/src/main/ai/ImageOptimizer.ts +176 -0
- package/src/main/ai/StructuredMarkdownBuilder.ts +379 -0
- package/src/main/ai/index.ts +16 -0
- package/src/main/ai/types.ts +258 -0
- package/src/main/analysis/ClarificationGenerator.ts +385 -0
- package/src/main/analysis/FeedbackAnalyzer.ts +531 -0
- package/src/main/analysis/index.ts +19 -0
- package/src/main/audio/AudioCapture.ts +978 -0
- package/src/main/audio/audioUtils.ts +100 -0
- package/src/main/audio/index.ts +20 -0
- package/src/main/capture/index.ts +1 -0
- package/src/main/index.ts +1693 -0
- package/src/main/ipc/captureHandlers.ts +272 -0
- package/src/main/ipc/index.ts +45 -0
- package/src/main/ipc/outputHandlers.ts +302 -0
- package/src/main/ipc/sessionHandlers.ts +56 -0
- package/src/main/ipc/settingsHandlers.ts +471 -0
- package/src/main/ipc/types.ts +56 -0
- package/src/main/ipc/windowHandlers.ts +277 -0
- package/src/main/output/ClipboardService.ts +369 -0
- package/src/main/output/ExportService.ts +539 -0
- package/src/main/output/FileManager.ts +416 -0
- package/src/main/output/MarkdownGenerator.ts +791 -0
- package/src/main/output/MarkdownPatcher.ts +299 -0
- package/src/main/output/index.ts +186 -0
- package/src/main/output/sessionAdapter.ts +207 -0
- package/src/main/output/templates/html-template.ts +553 -0
- package/src/main/pipeline/FrameExtractor.ts +330 -0
- package/src/main/pipeline/PostProcessor.ts +399 -0
- package/src/main/pipeline/TranscriptAnalyzer.ts +226 -0
- package/src/main/pipeline/index.ts +36 -0
- package/src/main/platform/WindowsTaskbar.ts +600 -0
- package/src/main/platform/index.ts +16 -0
- package/src/main/settings/SettingsManager.ts +730 -0
- package/src/main/settings/index.ts +19 -0
- package/src/main/transcription/ModelDownloadManager.ts +494 -0
- package/src/main/transcription/TierManager.ts +219 -0
- package/src/main/transcription/TranscriptionRecoveryService.ts +340 -0
- package/src/main/transcription/WhisperService.ts +748 -0
- package/src/main/transcription/index.ts +56 -0
- package/src/main/transcription/types.ts +135 -0
- package/src/main/windows/PopoverManager.ts +284 -0
- package/src/main/windows/TaskbarIntegration.ts +452 -0
- package/src/main/windows/index.ts +23 -0
- package/src/preload/index.ts +1047 -0
- package/src/renderer/App.tsx +515 -0
- package/src/renderer/AppWrapper.tsx +28 -0
- package/src/renderer/assets/logo-dark.svg +7 -0
- package/src/renderer/assets/logo.svg +7 -0
- package/src/renderer/audio/AudioCaptureRenderer.ts +454 -0
- package/src/renderer/capture/ScreenRecordingRenderer.ts +492 -0
- package/src/renderer/components/AnnotationOverlay.tsx +836 -0
- package/src/renderer/components/AudioWaveform.tsx +811 -0
- package/src/renderer/components/ClarificationQuestions.tsx +656 -0
- package/src/renderer/components/CountdownTimer.tsx +495 -0
- package/src/renderer/components/CrashRecoveryDialog.tsx +632 -0
- package/src/renderer/components/DonateButton.tsx +127 -0
- package/src/renderer/components/ErrorBoundary.tsx +308 -0
- package/src/renderer/components/ExportDialog.tsx +872 -0
- package/src/renderer/components/HotkeyHint.tsx +261 -0
- package/src/renderer/components/KeyboardShortcuts.tsx +787 -0
- package/src/renderer/components/ModelDownloadDialog.tsx +844 -0
- package/src/renderer/components/Onboarding.tsx +1830 -0
- package/src/renderer/components/ProcessingOverlay.tsx +157 -0
- package/src/renderer/components/RecordingOverlay.tsx +423 -0
- package/src/renderer/components/SessionHistory.tsx +1746 -0
- package/src/renderer/components/SessionReview.tsx +1321 -0
- package/src/renderer/components/SettingsPanel.tsx +217 -0
- package/src/renderer/components/Skeleton.tsx +347 -0
- package/src/renderer/components/StatusIndicator.tsx +86 -0
- package/src/renderer/components/ThemeProvider.tsx +429 -0
- package/src/renderer/components/Tooltip.tsx +370 -0
- package/src/renderer/components/TranscriptionPreview.tsx +183 -0
- package/src/renderer/components/TranscriptionTierSelector.tsx +640 -0
- package/src/renderer/components/UpdateNotification.tsx +377 -0
- package/src/renderer/components/WindowSelector.tsx +947 -0
- package/src/renderer/components/index.ts +99 -0
- package/src/renderer/components/primitives/ApiKeyInput.tsx +98 -0
- package/src/renderer/components/primitives/ColorPicker.tsx +65 -0
- package/src/renderer/components/primitives/DangerButton.tsx +45 -0
- package/src/renderer/components/primitives/DirectoryPicker.tsx +41 -0
- package/src/renderer/components/primitives/Dropdown.tsx +34 -0
- package/src/renderer/components/primitives/KeyRecorder.tsx +117 -0
- package/src/renderer/components/primitives/SettingsSection.tsx +32 -0
- package/src/renderer/components/primitives/Slider.tsx +43 -0
- package/src/renderer/components/primitives/Toggle.tsx +36 -0
- package/src/renderer/components/primitives/index.ts +10 -0
- package/src/renderer/components/settings/AdvancedTab.tsx +174 -0
- package/src/renderer/components/settings/AppearanceTab.tsx +77 -0
- package/src/renderer/components/settings/GeneralTab.tsx +40 -0
- package/src/renderer/components/settings/HotkeysTab.tsx +79 -0
- package/src/renderer/components/settings/RecordingTab.tsx +84 -0
- package/src/renderer/components/settings/index.ts +9 -0
- package/src/renderer/components/settings/settingsStyles.ts +673 -0
- package/src/renderer/components/settings/tabConfig.tsx +85 -0
- package/src/renderer/components/settings/useSettingsPanel.ts +447 -0
- package/src/renderer/contexts/ProcessingContext.tsx +227 -0
- package/src/renderer/contexts/RecordingContext.tsx +683 -0
- package/src/renderer/contexts/UIContext.tsx +326 -0
- package/src/renderer/contexts/index.ts +24 -0
- package/src/renderer/donateMessages.ts +69 -0
- package/src/renderer/hooks/index.ts +75 -0
- package/src/renderer/hooks/useAnimation.tsx +544 -0
- package/src/renderer/hooks/useTheme.ts +313 -0
- package/src/renderer/index.html +26 -0
- package/src/renderer/main.tsx +52 -0
- package/src/renderer/styles/animations.css +1093 -0
- package/src/renderer/styles/app-shell.css +662 -0
- package/src/renderer/styles/globals.css +515 -0
- package/src/renderer/styles/theme.ts +578 -0
- package/src/renderer/types/electron.d.ts +385 -0
- package/src/shared/hotkeys.ts +283 -0
- package/src/shared/types.ts +809 -0
- package/tests/clipboard.test.ts +228 -0
- package/tests/e2e/criticalPaths.test.ts +594 -0
- package/tests/feedbackAnalyzer.test.ts +303 -0
- package/tests/integration/sessionFlow.test.ts +583 -0
- package/tests/markdownGenerator.test.ts +418 -0
- package/tests/output.test.ts +96 -0
- package/tests/setup.ts +486 -0
- package/tests/unit/appIntegration.test.ts +676 -0
- package/tests/unit/appViewState.test.ts +281 -0
- package/tests/unit/audioIpcChannels.test.ts +17 -0
- package/tests/unit/exportService.test.ts +492 -0
- package/tests/unit/hotkeys.test.ts +92 -0
- package/tests/unit/navigationPreload.test.ts +94 -0
- package/tests/unit/onboardingFlow.test.ts +345 -0
- package/tests/unit/permissionManager.test.ts +175 -0
- package/tests/unit/permissionManagerExpanded.test.ts +296 -0
- package/tests/unit/screenRecordingRenderer.test.ts +368 -0
- package/tests/unit/sessionController.test.ts +515 -0
- package/tests/unit/tierManager.test.ts +61 -0
- package/tests/unit/tierManagerExpanded.test.ts +142 -0
- package/tests/unit/transcriptAnalyzer.test.ts +64 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +46 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# electron-builder.yml
|
|
2
|
+
# macOS Distribution Configuration for markupr
|
|
3
|
+
# Version: 0.4.0
|
|
4
|
+
|
|
5
|
+
appId: com.eddiesanjuan.markupr
|
|
6
|
+
productName: markupr
|
|
7
|
+
executableName: markupr
|
|
8
|
+
copyright: Copyright 2026 Eddie San Juan
|
|
9
|
+
|
|
10
|
+
directories:
|
|
11
|
+
output: release
|
|
12
|
+
buildResources: build
|
|
13
|
+
|
|
14
|
+
# Rebuild native modules for Electron's Node.js version
|
|
15
|
+
npmRebuild: true
|
|
16
|
+
|
|
17
|
+
files:
|
|
18
|
+
- dist/**/*
|
|
19
|
+
- package.json
|
|
20
|
+
|
|
21
|
+
extraResources:
|
|
22
|
+
- from: assets
|
|
23
|
+
to: assets
|
|
24
|
+
filter:
|
|
25
|
+
- "**/*"
|
|
26
|
+
# Windows taskbar icons (overlay and thumbnail toolbar)
|
|
27
|
+
- from: build
|
|
28
|
+
to: build
|
|
29
|
+
filter:
|
|
30
|
+
- "overlay-*.png"
|
|
31
|
+
- "toolbar-*.png"
|
|
32
|
+
|
|
33
|
+
# =============================================================================
|
|
34
|
+
# macOS Configuration
|
|
35
|
+
# =============================================================================
|
|
36
|
+
mac:
|
|
37
|
+
category: public.app-category.productivity
|
|
38
|
+
icon: build/icon.icns
|
|
39
|
+
hardenedRuntime: true
|
|
40
|
+
gatekeeperAssess: false
|
|
41
|
+
entitlements: build/entitlements.mac.plist
|
|
42
|
+
entitlementsInherit: build/entitlements.mac.inherit.plist
|
|
43
|
+
# Hide from dock and Cmd+Tab - pure menu bar app
|
|
44
|
+
extendInfo:
|
|
45
|
+
LSUIElement: true
|
|
46
|
+
target:
|
|
47
|
+
- target: dmg
|
|
48
|
+
arch:
|
|
49
|
+
- x64
|
|
50
|
+
- arm64
|
|
51
|
+
- target: zip
|
|
52
|
+
arch:
|
|
53
|
+
- x64
|
|
54
|
+
- arm64
|
|
55
|
+
|
|
56
|
+
# =============================================================================
|
|
57
|
+
# DMG Installer Configuration
|
|
58
|
+
# =============================================================================
|
|
59
|
+
dmg:
|
|
60
|
+
background: build/dmg-background.png
|
|
61
|
+
iconSize: 100
|
|
62
|
+
iconTextSize: 12
|
|
63
|
+
window:
|
|
64
|
+
width: 660
|
|
65
|
+
height: 400
|
|
66
|
+
contents:
|
|
67
|
+
- x: 180
|
|
68
|
+
y: 170
|
|
69
|
+
type: file
|
|
70
|
+
- x: 480
|
|
71
|
+
y: 170
|
|
72
|
+
type: link
|
|
73
|
+
path: /Applications
|
|
74
|
+
title: "Install markupr"
|
|
75
|
+
artifactName: "markupr-${version}-${arch}.dmg"
|
|
76
|
+
|
|
77
|
+
# =============================================================================
|
|
78
|
+
# Windows Configuration
|
|
79
|
+
# =============================================================================
|
|
80
|
+
win:
|
|
81
|
+
icon: build/icon.ico
|
|
82
|
+
target:
|
|
83
|
+
- target: nsis
|
|
84
|
+
arch: [x64]
|
|
85
|
+
- target: portable
|
|
86
|
+
arch: [x64]
|
|
87
|
+
publisherName: "markupr"
|
|
88
|
+
verifyUpdateCodeSignature: false
|
|
89
|
+
# File associations
|
|
90
|
+
fileAssociations:
|
|
91
|
+
- ext: markupr
|
|
92
|
+
name: markupr Session
|
|
93
|
+
description: markupr feedback session file
|
|
94
|
+
icon: build/icon.ico
|
|
95
|
+
role: Editor
|
|
96
|
+
|
|
97
|
+
nsis:
|
|
98
|
+
oneClick: false
|
|
99
|
+
perMachine: true
|
|
100
|
+
allowElevation: true
|
|
101
|
+
allowToChangeInstallationDirectory: true
|
|
102
|
+
installerIcon: build/icon.ico
|
|
103
|
+
uninstallerIcon: build/icon.ico
|
|
104
|
+
installerHeader: build/installer-header.bmp
|
|
105
|
+
installerSidebar: build/installer-sidebar.bmp
|
|
106
|
+
license: LICENSE
|
|
107
|
+
createDesktopShortcut: true
|
|
108
|
+
createStartMenuShortcut: true
|
|
109
|
+
shortcutName: "markupr"
|
|
110
|
+
artifactName: "markupr-Setup-${version}.exe"
|
|
111
|
+
include: build/installer.nsh
|
|
112
|
+
deleteAppDataOnUninstall: false
|
|
113
|
+
|
|
114
|
+
# =============================================================================
|
|
115
|
+
# Linux Configuration (for future use)
|
|
116
|
+
# =============================================================================
|
|
117
|
+
linux:
|
|
118
|
+
target:
|
|
119
|
+
- target: AppImage
|
|
120
|
+
arch:
|
|
121
|
+
- x64
|
|
122
|
+
- target: deb
|
|
123
|
+
arch:
|
|
124
|
+
- x64
|
|
125
|
+
category: Development
|
|
126
|
+
icon: build/icons
|
|
127
|
+
|
|
128
|
+
# =============================================================================
|
|
129
|
+
# Code Signing & Notarization
|
|
130
|
+
# =============================================================================
|
|
131
|
+
afterSign: scripts/notarize.cjs
|
|
132
|
+
|
|
133
|
+
# =============================================================================
|
|
134
|
+
# Publishing Configuration
|
|
135
|
+
# =============================================================================
|
|
136
|
+
publish:
|
|
137
|
+
provider: github
|
|
138
|
+
owner: eddiesanjuan
|
|
139
|
+
repo: markupr
|
|
140
|
+
releaseType: release
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
|
2
|
+
import react from '@vitejs/plugin-react'
|
|
3
|
+
import { resolve } from 'path'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
main: {
|
|
7
|
+
plugins: [externalizeDepsPlugin()],
|
|
8
|
+
build: {
|
|
9
|
+
outDir: 'dist/main',
|
|
10
|
+
lib: {
|
|
11
|
+
entry: resolve(__dirname, 'src/main/index.ts'),
|
|
12
|
+
formats: ['es']
|
|
13
|
+
},
|
|
14
|
+
rollupOptions: {
|
|
15
|
+
input: {
|
|
16
|
+
index: resolve(__dirname, 'src/main/index.ts')
|
|
17
|
+
},
|
|
18
|
+
output: {
|
|
19
|
+
format: 'es',
|
|
20
|
+
entryFileNames: '[name].mjs'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
preload: {
|
|
26
|
+
plugins: [externalizeDepsPlugin()],
|
|
27
|
+
build: {
|
|
28
|
+
outDir: 'dist/preload',
|
|
29
|
+
lib: {
|
|
30
|
+
entry: resolve(__dirname, 'src/preload/index.ts'),
|
|
31
|
+
formats: ['es']
|
|
32
|
+
},
|
|
33
|
+
rollupOptions: {
|
|
34
|
+
input: {
|
|
35
|
+
index: resolve(__dirname, 'src/preload/index.ts')
|
|
36
|
+
},
|
|
37
|
+
output: {
|
|
38
|
+
format: 'es',
|
|
39
|
+
entryFileNames: '[name].mjs'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
renderer: {
|
|
45
|
+
root: 'src/renderer',
|
|
46
|
+
build: {
|
|
47
|
+
outDir: 'dist/renderer',
|
|
48
|
+
rollupOptions: {
|
|
49
|
+
input: {
|
|
50
|
+
index: resolve(__dirname, 'src/renderer/index.html')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
plugins: [react()],
|
|
55
|
+
resolve: {
|
|
56
|
+
alias: {
|
|
57
|
+
'@': resolve(__dirname, 'src'),
|
|
58
|
+
'@renderer': resolve(__dirname, 'src/renderer'),
|
|
59
|
+
'@shared': resolve(__dirname, 'src/shared')
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
})
|
package/package.json
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "markupr",
|
|
3
|
+
"version": "2.1.8",
|
|
4
|
+
"description": "AI-ready developer feedback capture tool with voice narration and intelligent screenshots",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/main/index.mjs",
|
|
7
|
+
"author": "Eddie San Juan",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"homepage": "https://markupr.com",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/eddiesanjuan/markupr.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/eddiesanjuan/markupr/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"markupr",
|
|
19
|
+
"feedback",
|
|
20
|
+
"voice",
|
|
21
|
+
"transcription",
|
|
22
|
+
"screenshot",
|
|
23
|
+
"electron",
|
|
24
|
+
"ai",
|
|
25
|
+
"developer-tools",
|
|
26
|
+
"menu-bar",
|
|
27
|
+
"macos",
|
|
28
|
+
"windows",
|
|
29
|
+
"whisper"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
36
|
+
"rebuild": "electron-rebuild",
|
|
37
|
+
"dev": "electron-vite dev",
|
|
38
|
+
"build": "node scripts/build.mjs",
|
|
39
|
+
"start": "node site/server.js",
|
|
40
|
+
"build:desktop": "electron-vite build",
|
|
41
|
+
"preview": "electron-vite preview",
|
|
42
|
+
"package": "electron-builder --config electron-builder.yml",
|
|
43
|
+
"package:mac": "electron-builder --mac --config electron-builder.yml",
|
|
44
|
+
"package:mac:unsigned": "CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --mac --config electron-builder.yml",
|
|
45
|
+
"package:win": "electron-builder --win --config electron-builder.yml",
|
|
46
|
+
"dist:mac": "npm run build && electron-builder --mac --config electron-builder.yml",
|
|
47
|
+
"dist:mac:universal": "npm run build && electron-builder --mac --universal --config electron-builder.yml",
|
|
48
|
+
"dist:mac:x64": "npm run build && electron-builder --mac --x64 --config electron-builder.yml",
|
|
49
|
+
"dist:mac:arm64": "npm run build && electron-builder --mac --arm64 --config electron-builder.yml",
|
|
50
|
+
"dist:win": "electron-builder --win",
|
|
51
|
+
"dist:win:portable": "electron-builder --win portable",
|
|
52
|
+
"dist:win:nsis": "electron-builder --win nsis",
|
|
53
|
+
"package:linux": "electron-builder --linux --config electron-builder.yml",
|
|
54
|
+
"release": "electron-builder --publish always --config electron-builder.yml",
|
|
55
|
+
"test": "vitest",
|
|
56
|
+
"test:unit": "vitest tests/unit",
|
|
57
|
+
"test:integration": "vitest tests/integration",
|
|
58
|
+
"test:e2e": "vitest tests/e2e",
|
|
59
|
+
"test:ci": "vitest run --coverage",
|
|
60
|
+
"test:coverage": "vitest --coverage",
|
|
61
|
+
"test:watch": "vitest --watch",
|
|
62
|
+
"test:ui": "vitest --ui",
|
|
63
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
64
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
65
|
+
"audit": "npm audit --omit=dev --audit-level=high",
|
|
66
|
+
"setup:markupr": "bash ./scripts/setup-markupr.sh",
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"generate:icons": "node scripts/generate-icons.mjs",
|
|
69
|
+
"generate:tray-icons": "node scripts/generate-tray-icons.mjs",
|
|
70
|
+
"generate:installer-images": "node scripts/generate-installer-images.cjs",
|
|
71
|
+
"prebuild:win": "npm run generate:installer-images"
|
|
72
|
+
},
|
|
73
|
+
"devDependencies": {
|
|
74
|
+
"@electron/notarize": "^2.2.0",
|
|
75
|
+
"@electron/rebuild": "^4.0.3",
|
|
76
|
+
"@types/node": "^20.10.0",
|
|
77
|
+
"@types/react": "^18.2.0",
|
|
78
|
+
"@types/react-dom": "^18.2.0",
|
|
79
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
80
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
81
|
+
"@vitejs/plugin-react": "^5.1.3",
|
|
82
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
83
|
+
"electron": "^28.0.0",
|
|
84
|
+
"electron-builder": "^24.0.0",
|
|
85
|
+
"electron-vite": "^2.0.0",
|
|
86
|
+
"eslint": "^8.0.0",
|
|
87
|
+
"eslint-plugin-react": "^7.0.0",
|
|
88
|
+
"eslint-plugin-react-hooks": "^4.0.0",
|
|
89
|
+
"png2icons": "^2.0.1",
|
|
90
|
+
"sharp": "^0.34.5",
|
|
91
|
+
"typescript": "^5.3.0",
|
|
92
|
+
"vite": "^5.0.0",
|
|
93
|
+
"vitest": "^1.0.0"
|
|
94
|
+
},
|
|
95
|
+
"dependencies": {
|
|
96
|
+
"@anthropic-ai/sdk": "^0.73.0",
|
|
97
|
+
"electron-log": "^5.4.3",
|
|
98
|
+
"electron-store": "^11.0.2",
|
|
99
|
+
"electron-updater": "^6.7.3",
|
|
100
|
+
"keytar": "^7.9.0",
|
|
101
|
+
"react": "^18.2.0",
|
|
102
|
+
"react-dom": "^18.2.0",
|
|
103
|
+
"whisper-node": "^1.1.1"
|
|
104
|
+
},
|
|
105
|
+
"build": {
|
|
106
|
+
"extends": null
|
|
107
|
+
}
|
|
108
|
+
}
|
package/railway.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://railway.com/railway.schema.json",
|
|
3
|
+
"build": {
|
|
4
|
+
"builder": "NIXPACKS"
|
|
5
|
+
},
|
|
6
|
+
"deploy": {
|
|
7
|
+
"startCommand": "node site/server.js",
|
|
8
|
+
"healthcheckPath": "/",
|
|
9
|
+
"restartPolicyType": "ON_FAILURE",
|
|
10
|
+
"restartPolicyMaxRetries": 3
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const repoRoot = join(__dirname, '..');
|
|
10
|
+
const siteDir = join(repoRoot, 'site');
|
|
11
|
+
const distDir = join(repoRoot, 'dist');
|
|
12
|
+
|
|
13
|
+
function isRailwayEnvironment() {
|
|
14
|
+
return Object.keys(process.env).some((key) => key.startsWith('RAILWAY_'));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function run(command, args) {
|
|
18
|
+
const result = spawnSync(command, args, {
|
|
19
|
+
stdio: 'inherit',
|
|
20
|
+
env: process.env,
|
|
21
|
+
cwd: repoRoot,
|
|
22
|
+
shell: true,
|
|
23
|
+
});
|
|
24
|
+
if (result.status !== 0) {
|
|
25
|
+
process.exit(result.status ?? 1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!isRailwayEnvironment()) {
|
|
30
|
+
run('npx', ['electron-vite', 'build']);
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
console.log('[build] Railway environment detected. Building landing page artifact from /site.');
|
|
35
|
+
rmSync(distDir, { recursive: true, force: true });
|
|
36
|
+
mkdirSync(distDir, { recursive: true });
|
|
37
|
+
|
|
38
|
+
const sourceIndex = join(siteDir, 'index.html');
|
|
39
|
+
if (!existsSync(sourceIndex)) {
|
|
40
|
+
console.error('[build] Missing site/index.html; cannot produce landing artifact.');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
cpSync(sourceIndex, join(distDir, 'index.html'));
|
|
45
|
+
|
|
46
|
+
const optionalAssetsDir = join(siteDir, 'assets');
|
|
47
|
+
if (existsSync(optionalAssetsDir)) {
|
|
48
|
+
cpSync(optionalAssetsDir, join(distDir, 'assets'), { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log('[build] Landing page artifact ready at /dist/index.html');
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* markupr Icon Generation Script
|
|
4
|
+
*
|
|
5
|
+
* Generates all app icons and brand assets from SVG sources using sharp.
|
|
6
|
+
*
|
|
7
|
+
* Usage: node scripts/generate-icons.mjs
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { execSync } from 'child_process';
|
|
14
|
+
import sharp from 'sharp';
|
|
15
|
+
|
|
16
|
+
// Get __dirname equivalent in ES modules
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = path.dirname(__filename);
|
|
19
|
+
|
|
20
|
+
// Paths
|
|
21
|
+
const PROJECT_ROOT = path.join(__dirname, '..');
|
|
22
|
+
const SVG_SOURCE_DIR = path.join(PROJECT_ROOT, 'assets', 'svg-source');
|
|
23
|
+
const BUILD_DIR = path.join(PROJECT_ROOT, 'build');
|
|
24
|
+
const ASSETS_DIR = path.join(PROJECT_ROOT, 'assets');
|
|
25
|
+
const RENDERER_ASSETS_DIR = path.join(PROJECT_ROOT, 'src', 'renderer', 'assets');
|
|
26
|
+
|
|
27
|
+
// Ensure directories exist
|
|
28
|
+
[BUILD_DIR, ASSETS_DIR, RENDERER_ASSETS_DIR, SVG_SOURCE_DIR].forEach((dir) => {
|
|
29
|
+
if (!fs.existsSync(dir)) {
|
|
30
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Tray icon sizes
|
|
35
|
+
const TRAY_SIZES = { normal: 22, retina: 44 };
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert SVG to PNG at specified size using sharp
|
|
39
|
+
*/
|
|
40
|
+
async function svgToPng(svgPath, outputPath, width, height = width) {
|
|
41
|
+
const svgBuffer = fs.readFileSync(svgPath);
|
|
42
|
+
|
|
43
|
+
await sharp(svgBuffer)
|
|
44
|
+
.resize(width, height, {
|
|
45
|
+
fit: 'contain',
|
|
46
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
47
|
+
})
|
|
48
|
+
.png()
|
|
49
|
+
.toFile(outputPath);
|
|
50
|
+
|
|
51
|
+
console.log(` Generated: ${path.basename(outputPath)} (${width}x${height})`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Generate main app icon in all sizes
|
|
56
|
+
*/
|
|
57
|
+
async function generateAppIcon() {
|
|
58
|
+
console.log('\n=== Generating App Icon ===');
|
|
59
|
+
|
|
60
|
+
const svgPath = path.join(SVG_SOURCE_DIR, 'icon.svg');
|
|
61
|
+
|
|
62
|
+
if (!fs.existsSync(svgPath)) {
|
|
63
|
+
console.error('Error: icon.svg not found in assets/svg-source/');
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Generate master 1024x1024 PNG
|
|
68
|
+
const masterPath = path.join(BUILD_DIR, 'icon.png');
|
|
69
|
+
await svgToPng(svgPath, masterPath, 1024);
|
|
70
|
+
|
|
71
|
+
// Generate individual sizes for iconset
|
|
72
|
+
const iconsetDir = path.join(BUILD_DIR, 'icon.iconset');
|
|
73
|
+
if (fs.existsSync(iconsetDir)) {
|
|
74
|
+
fs.rmSync(iconsetDir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
fs.mkdirSync(iconsetDir, { recursive: true });
|
|
77
|
+
|
|
78
|
+
// macOS iconset naming convention
|
|
79
|
+
const macOsSizes = [
|
|
80
|
+
{ size: 16, suffix: '16x16' },
|
|
81
|
+
{ size: 32, suffix: '16x16@2x' },
|
|
82
|
+
{ size: 32, suffix: '32x32' },
|
|
83
|
+
{ size: 64, suffix: '32x32@2x' },
|
|
84
|
+
{ size: 128, suffix: '128x128' },
|
|
85
|
+
{ size: 256, suffix: '128x128@2x' },
|
|
86
|
+
{ size: 256, suffix: '256x256' },
|
|
87
|
+
{ size: 512, suffix: '256x256@2x' },
|
|
88
|
+
{ size: 512, suffix: '512x512' },
|
|
89
|
+
{ size: 1024, suffix: '512x512@2x' },
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
for (const { size, suffix } of macOsSizes) {
|
|
93
|
+
const outputPath = path.join(iconsetDir, `icon_${suffix}.png`);
|
|
94
|
+
await svgToPng(svgPath, outputPath, size);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Generate .icns using iconutil (macOS only)
|
|
98
|
+
const icnsPath = path.join(BUILD_DIR, 'icon.icns');
|
|
99
|
+
if (process.platform === 'darwin') {
|
|
100
|
+
try {
|
|
101
|
+
execSync(`iconutil -c icns "${iconsetDir}" -o "${icnsPath}"`);
|
|
102
|
+
console.log(` Generated: icon.icns`);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error(' Warning: Could not generate .icns (iconutil failed)');
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
console.log(' Skipping .icns generation (not on macOS)');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Generate Windows .ico
|
|
111
|
+
await generateWindowsIcon(svgPath);
|
|
112
|
+
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Generate Windows .ico file by creating a multi-size PNG fallback
|
|
118
|
+
*/
|
|
119
|
+
async function generateWindowsIcon(svgPath) {
|
|
120
|
+
console.log('\n=== Generating Windows Icon Assets ===');
|
|
121
|
+
|
|
122
|
+
const sizes = [16, 24, 32, 48, 64, 128, 256];
|
|
123
|
+
|
|
124
|
+
for (const size of sizes) {
|
|
125
|
+
const outputPath = path.join(BUILD_DIR, `icon-${size}.png`);
|
|
126
|
+
await svgToPng(svgPath, outputPath, size);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Try to use png2icons if available
|
|
130
|
+
try {
|
|
131
|
+
const png2icons = await import('png2icons');
|
|
132
|
+
const input = fs.readFileSync(path.join(BUILD_DIR, 'icon.png'));
|
|
133
|
+
const output = png2icons.default.createICO(input, png2icons.default.BICUBIC2, 0, true, true);
|
|
134
|
+
fs.writeFileSync(path.join(BUILD_DIR, 'icon.ico'), output);
|
|
135
|
+
console.log(` Generated: icon.ico`);
|
|
136
|
+
} catch {
|
|
137
|
+
console.log(' Note: png2icons not installed. Windows icon sizes generated as PNGs.');
|
|
138
|
+
console.log(' Run: npm install --save-dev png2icons');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Generate tray icons for all states
|
|
144
|
+
*/
|
|
145
|
+
async function generateTrayIcons() {
|
|
146
|
+
console.log('\n=== Generating Tray Icons ===');
|
|
147
|
+
|
|
148
|
+
const states = ['tray-icon', 'tray-icon-recording', 'tray-icon-processing'];
|
|
149
|
+
|
|
150
|
+
for (const state of states) {
|
|
151
|
+
const svgPath = path.join(SVG_SOURCE_DIR, `${state}.svg`);
|
|
152
|
+
|
|
153
|
+
if (!fs.existsSync(svgPath)) {
|
|
154
|
+
console.log(` Skipping ${state}.svg (not found)`);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Generate normal size (22x22)
|
|
159
|
+
const normalPath = path.join(ASSETS_DIR, `${state}.png`);
|
|
160
|
+
await svgToPng(svgPath, normalPath, TRAY_SIZES.normal);
|
|
161
|
+
|
|
162
|
+
// Generate Template version (for macOS auto-tinting)
|
|
163
|
+
const templatePath = path.join(ASSETS_DIR, `${state}Template.png`);
|
|
164
|
+
await svgToPng(svgPath, templatePath, TRAY_SIZES.normal);
|
|
165
|
+
|
|
166
|
+
// Generate @2x retina versions
|
|
167
|
+
const retina2xPath = path.join(ASSETS_DIR, `${state}@2x.png`);
|
|
168
|
+
await svgToPng(svgPath, retina2xPath, TRAY_SIZES.retina);
|
|
169
|
+
|
|
170
|
+
const template2xPath = path.join(ASSETS_DIR, `${state}Template@2x.png`);
|
|
171
|
+
await svgToPng(svgPath, template2xPath, TRAY_SIZES.retina);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Generate processing animation frames
|
|
175
|
+
await generateProcessingFrames();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Generate processing animation frames
|
|
180
|
+
*/
|
|
181
|
+
async function generateProcessingFrames() {
|
|
182
|
+
console.log('\n=== Generating Processing Animation Frames ===');
|
|
183
|
+
|
|
184
|
+
const baseSvgPath = path.join(SVG_SOURCE_DIR, 'tray-icon-processing.svg');
|
|
185
|
+
|
|
186
|
+
if (!fs.existsSync(baseSvgPath)) {
|
|
187
|
+
console.log(' Skipping processing frames (SVG not found)');
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const baseSvg = fs.readFileSync(baseSvgPath, 'utf8');
|
|
192
|
+
|
|
193
|
+
// Generate 4 frames with rotated spinner
|
|
194
|
+
for (let frame = 0; frame < 4; frame++) {
|
|
195
|
+
const rotation = frame * 90;
|
|
196
|
+
|
|
197
|
+
// Modify SVG to rotate the spinner
|
|
198
|
+
const frameSvg = baseSvg.replace(
|
|
199
|
+
'stroke-dasharray="10 6"',
|
|
200
|
+
`stroke-dasharray="10 6" transform="rotate(${rotation}, 16, 5)"`
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
const tempSvgPath = path.join(SVG_SOURCE_DIR, `tray-processing-frame-${frame}.svg`);
|
|
204
|
+
fs.writeFileSync(tempSvgPath, frameSvg);
|
|
205
|
+
|
|
206
|
+
// Generate PNGs
|
|
207
|
+
const normalPath = path.join(ASSETS_DIR, `tray-processing-${frame}.png`);
|
|
208
|
+
const templatePath = path.join(ASSETS_DIR, `tray-processing-${frame}Template.png`);
|
|
209
|
+
const retina2xPath = path.join(ASSETS_DIR, `tray-processing-${frame}@2x.png`);
|
|
210
|
+
const template2xPath = path.join(ASSETS_DIR, `tray-processing-${frame}Template@2x.png`);
|
|
211
|
+
|
|
212
|
+
await svgToPng(tempSvgPath, normalPath, TRAY_SIZES.normal);
|
|
213
|
+
await svgToPng(tempSvgPath, templatePath, TRAY_SIZES.normal);
|
|
214
|
+
await svgToPng(tempSvgPath, retina2xPath, TRAY_SIZES.retina);
|
|
215
|
+
await svgToPng(tempSvgPath, template2xPath, TRAY_SIZES.retina);
|
|
216
|
+
|
|
217
|
+
// Cleanup temp SVG
|
|
218
|
+
fs.unlinkSync(tempSvgPath);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Generate DMG background images
|
|
224
|
+
*/
|
|
225
|
+
async function generateDmgBackground() {
|
|
226
|
+
console.log('\n=== Generating DMG Background ===');
|
|
227
|
+
|
|
228
|
+
const svgPath = path.join(SVG_SOURCE_DIR, 'dmg-background.svg');
|
|
229
|
+
|
|
230
|
+
if (!fs.existsSync(svgPath)) {
|
|
231
|
+
console.log(' Skipping DMG background (SVG not found)');
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Standard resolution (660x400)
|
|
236
|
+
const normalPath = path.join(BUILD_DIR, 'dmg-background.png');
|
|
237
|
+
await svgToPng(svgPath, normalPath, 660, 400);
|
|
238
|
+
|
|
239
|
+
// Retina resolution (1320x800)
|
|
240
|
+
const retinaPath = path.join(BUILD_DIR, 'dmg-background@2x.png');
|
|
241
|
+
await svgToPng(svgPath, retinaPath, 1320, 800);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Check logo SVGs exist
|
|
246
|
+
*/
|
|
247
|
+
async function checkLogos() {
|
|
248
|
+
console.log('\n=== Checking Logo SVGs ===');
|
|
249
|
+
|
|
250
|
+
const logos = ['logo.svg', 'logo-dark.svg'];
|
|
251
|
+
|
|
252
|
+
for (const logo of logos) {
|
|
253
|
+
const srcPath = path.join(RENDERER_ASSETS_DIR, logo);
|
|
254
|
+
if (fs.existsSync(srcPath)) {
|
|
255
|
+
console.log(` Found: ${logo}`);
|
|
256
|
+
} else {
|
|
257
|
+
console.log(` Missing: ${logo}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Generate favicons for web use
|
|
264
|
+
*/
|
|
265
|
+
async function generateFavicons() {
|
|
266
|
+
console.log('\n=== Generating Favicons ===');
|
|
267
|
+
|
|
268
|
+
const svgPath = path.join(SVG_SOURCE_DIR, 'icon.svg');
|
|
269
|
+
|
|
270
|
+
if (!fs.existsSync(svgPath)) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const sizes = [16, 32, 48, 64, 180, 192, 512];
|
|
275
|
+
|
|
276
|
+
for (const size of sizes) {
|
|
277
|
+
const outputPath = path.join(BUILD_DIR, `favicon-${size}.png`);
|
|
278
|
+
await svgToPng(svgPath, outputPath, size);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Main execution
|
|
284
|
+
*/
|
|
285
|
+
async function main() {
|
|
286
|
+
console.log('=========================================');
|
|
287
|
+
console.log(' markupr Icon Generator (sharp)');
|
|
288
|
+
console.log('=========================================');
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
await generateAppIcon();
|
|
292
|
+
await generateTrayIcons();
|
|
293
|
+
await generateDmgBackground();
|
|
294
|
+
await checkLogos();
|
|
295
|
+
await generateFavicons();
|
|
296
|
+
|
|
297
|
+
console.log('\n=========================================');
|
|
298
|
+
console.log(' Icon generation complete!');
|
|
299
|
+
console.log('=========================================\n');
|
|
300
|
+
|
|
301
|
+
console.log('Generated files:');
|
|
302
|
+
console.log(' build/icon.png - Master app icon (1024x1024)');
|
|
303
|
+
console.log(' build/icon.icns - macOS icon bundle');
|
|
304
|
+
console.log(' build/icon-*.png - Windows icon sizes');
|
|
305
|
+
console.log(' build/dmg-background.png - DMG installer background');
|
|
306
|
+
console.log(' assets/tray-*.png - Menu bar tray icons');
|
|
307
|
+
console.log(' src/renderer/assets/ - In-app logo SVGs');
|
|
308
|
+
} catch (error) {
|
|
309
|
+
console.error('\nError during icon generation:', error);
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
main();
|