regen.mde 0.7.0 → 0.8.0

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.
Files changed (41) hide show
  1. package/LICENSE +16 -16
  2. package/bin/build-corpus-editor.js +83 -83
  3. package/bin/build-corpus.js +41 -41
  4. package/bin/regen-mdeditor-install.js +27 -27
  5. package/bin/regen-mdeditor-uninstall.js +19 -19
  6. package/bin/validate-katex.js +93 -93
  7. package/desktop/BuildCorpusEditor/BuildCorpusEditor.csproj +22 -22
  8. package/desktop/BuildCorpusEditor/app.manifest +16 -16
  9. package/dist/release/{regen-mde-0.7.0-win-x64.zip → regen-mde-0.8.0-win-x64.zip} +0 -0
  10. package/dist/windows-editor/BuildCorpusEditor.dll +0 -0
  11. package/dist/windows-editor/BuildCorpusEditor.exe +0 -0
  12. package/dist/windows-editor/BuildCorpusEditor.pdb +0 -0
  13. package/dist/windows-editor/BuildCorpusEditor.runtimeconfig.json +1 -1
  14. package/dist/windows-editor/wwwroot/index.html +20 -20
  15. package/editor-web/index.html +21 -21
  16. package/editor-web/vite.config.js +13 -13
  17. package/examples/build-corpus.config.example.json +21 -21
  18. package/installer/install-regen-mde.ps1 +214 -214
  19. package/installer/regen-mde.nsi +81 -81
  20. package/package.json +90 -90
  21. package/pyproject.toml +34 -35
  22. package/requirements.txt +0 -1
  23. package/scripts/build-windows-editor.ps1 +47 -47
  24. package/scripts/package-windows-editor.ps1 +90 -90
  25. package/scripts/run-corpus.ps1 +28 -28
  26. package/scripts/run-editor-implementation-plane.ps1 +226 -226
  27. package/scripts/run-required-tests.ps1 +98 -98
  28. package/scripts/run-smoke.ps1 +28 -28
  29. package/src/build_corpus/__init__.py +1 -1
  30. package/src/build_corpus/equations.py +1345 -80
  31. package/src/build_corpus/templates/__init__.py +1 -1
  32. package/src/build_corpus/validate_assets.py +46 -46
  33. package/tools/audit_corpus.py +203 -203
  34. package/tools/collect_microsoft_word_templates.py +228 -228
  35. package/tools/collect_online_docx_corpus.py +272 -272
  36. package/tools/collect_online_pptx_corpus.py +252 -252
  37. package/tools/compare_pptx_inputs_outputs.py +87 -87
  38. package/tools/roundtrip_docx_corpus.py +171 -171
  39. package/dist/release/regen-mde-0.3.0-win-x64-setup.exe +0 -0
  40. package/dist/release/regen-mde-0.3.0-win-x64.zip +0 -0
  41. package/dist/release/regen-mde-0.7.0-win-x64-setup.exe +0 -0
@@ -13,7 +13,7 @@
13
13
  ],
14
14
  "configProperties": {
15
15
  "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
16
- "CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS": false
16
+ "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": true
17
17
  }
18
18
  }
19
19
  }
@@ -1,22 +1,22 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>regen-mde</title>
7
- <script>
8
- window.__REGEN_MDEDITOR_ERROR = "";
9
- window.addEventListener("error", function (event) {
10
- window.__REGEN_MDEDITOR_ERROR = event.message || "window error";
11
- });
12
- window.addEventListener("unhandledrejection", function (event) {
13
- window.__REGEN_MDEDITOR_ERROR = event.reason && event.reason.message ? event.reason.message : String(event.reason || "unhandled rejection");
14
- });
15
- </script>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>regen-mde</title>
7
+ <script>
8
+ window.__REGEN_MDEDITOR_ERROR = "";
9
+ window.addEventListener("error", function (event) {
10
+ window.__REGEN_MDEDITOR_ERROR = event.message || "window error";
11
+ });
12
+ window.addEventListener("unhandledrejection", function (event) {
13
+ window.__REGEN_MDEDITOR_ERROR = event.reason && event.reason.message ? event.reason.message : String(event.reason || "unhandled rejection");
14
+ });
15
+ </script>
16
16
  <script type="module" crossorigin src="./assets/index-C_VxJk4k.js"></script>
17
17
  <link rel="stylesheet" crossorigin href="./assets/index-Wt9zSjIw.css">
18
- </head>
19
- <body>
20
- <div id="root"></div>
21
- </body>
22
- </html>
18
+ </head>
19
+ <body>
20
+ <div id="root"></div>
21
+ </body>
22
+ </html>
@@ -1,21 +1,21 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>regen-mde</title>
7
- <script>
8
- window.__REGEN_MDEDITOR_ERROR = "";
9
- window.addEventListener("error", function (event) {
10
- window.__REGEN_MDEDITOR_ERROR = event.message || "window error";
11
- });
12
- window.addEventListener("unhandledrejection", function (event) {
13
- window.__REGEN_MDEDITOR_ERROR = event.reason && event.reason.message ? event.reason.message : String(event.reason || "unhandled rejection");
14
- });
15
- </script>
16
- </head>
17
- <body>
18
- <div id="root"></div>
19
- <script type="module" src="/src/main.jsx"></script>
20
- </body>
21
- </html>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>regen-mde</title>
7
+ <script>
8
+ window.__REGEN_MDEDITOR_ERROR = "";
9
+ window.addEventListener("error", function (event) {
10
+ window.__REGEN_MDEDITOR_ERROR = event.message || "window error";
11
+ });
12
+ window.addEventListener("unhandledrejection", function (event) {
13
+ window.__REGEN_MDEDITOR_ERROR = event.reason && event.reason.message ? event.reason.message : String(event.reason || "unhandled rejection");
14
+ });
15
+ </script>
16
+ </head>
17
+ <body>
18
+ <div id="root"></div>
19
+ <script type="module" src="/src/main.jsx"></script>
20
+ </body>
21
+ </html>
@@ -1,13 +1,13 @@
1
- import { defineConfig } from "vite";
2
- import react from "@vitejs/plugin-react";
3
- import path from "node:path";
4
-
5
- export default defineConfig({
6
- root: path.resolve(import.meta.dirname),
7
- base: "./",
8
- plugins: [react()],
9
- build: {
10
- outDir: "../desktop/BuildCorpusEditor/wwwroot",
11
- emptyOutDir: true,
12
- },
13
- });
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import path from "node:path";
4
+
5
+ export default defineConfig({
6
+ root: path.resolve(import.meta.dirname),
7
+ base: "./",
8
+ plugins: [react()],
9
+ build: {
10
+ outDir: "../desktop/BuildCorpusEditor/wwwroot",
11
+ emptyOutDir: true,
12
+ },
13
+ });
@@ -1,21 +1,21 @@
1
- {
2
- "conversion": {
3
- "equations": "tex",
4
- "images": "assets"
5
- },
6
- "output": {
7
- "out": ".codex/build-corpus/out",
8
- "out_same_dir": false
9
- },
10
- "s3": {
11
- "bucket": "build-corpus-assets",
12
- "public_base_url": "https://assets.example.com",
13
- "prefix": "build-corpus",
14
- "endpoint_url": "https://ACCOUNT_ID.r2.cloudflarestorage.com",
15
- "region_name": "auto",
16
- "access_key_id": "%R2_ACCESS_KEY_ID%",
17
- "secret_access_key": "%R2_SECRET_ACCESS_KEY%",
18
- "cache_control": "public, max-age=31536000, immutable",
19
- "acl": null
20
- }
21
- }
1
+ {
2
+ "conversion": {
3
+ "equations": "tex",
4
+ "images": "assets"
5
+ },
6
+ "output": {
7
+ "out": ".codex/build-corpus/out",
8
+ "out_same_dir": false
9
+ },
10
+ "s3": {
11
+ "bucket": "build-corpus-assets",
12
+ "public_base_url": "https://assets.example.com",
13
+ "prefix": "build-corpus",
14
+ "endpoint_url": "https://ACCOUNT_ID.r2.cloudflarestorage.com",
15
+ "region_name": "auto",
16
+ "access_key_id": "%R2_ACCESS_KEY_ID%",
17
+ "secret_access_key": "%R2_SECRET_ACCESS_KEY%",
18
+ "cache_control": "public, max-age=31536000, immutable",
19
+ "acl": null
20
+ }
21
+ }
@@ -1,214 +1,214 @@
1
- [CmdletBinding()]
2
- param(
3
- [string]$PackageRoot = "",
4
- [string]$InstallDir = "$env:LOCALAPPDATA\Programs\regen-mde"
5
- )
6
-
7
- $ErrorActionPreference = "Stop"
8
-
9
- if ([string]::IsNullOrWhiteSpace($PackageRoot)) {
10
- $PackageApp = Join-Path $PSScriptRoot "app"
11
- if (Test-Path -LiteralPath (Join-Path $PackageApp "BuildCorpusEditor.exe")) {
12
- $PackageRoot = $PackageApp
13
- } else {
14
- $PackageRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
15
- }
16
- }
17
-
18
- $ProductName = "regen-mde"
19
- $LegacyProductNames = @("Manuscript Forge", "Regen.MDeditor")
20
- $AppSource = if (Test-Path -LiteralPath (Join-Path $PackageRoot "BuildCorpusEditor.exe")) {
21
- $PackageRoot
22
- } else {
23
- Join-Path $PackageRoot "dist\windows-editor"
24
- }
25
- $AppExe = Join-Path $AppSource "BuildCorpusEditor.exe"
26
- $StartMenuDir = Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\LIFE AI"
27
- $ShortcutPath = Join-Path $StartMenuDir "$ProductName.lnk"
28
- $UninstallShortcutPath = Join-Path $StartMenuDir "Uninstall $ProductName.lnk"
29
- $LegacyInstallDir = Join-Path $env:LOCALAPPDATA "Programs\Manuscript Forge"
30
- $LegacyInstallDir2 = Join-Path $env:LOCALAPPDATA "Programs\Regen.MDeditor"
31
-
32
- if (-not (Test-Path -LiteralPath $AppExe)) {
33
- throw "Package is missing BuildCorpusEditor.exe"
34
- }
35
-
36
- function Remove-FileVerb {
37
- param(
38
- [string]$Extension,
39
- [string]$Verb
40
- )
41
- Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\$Extension\shell\$Verb" -Recurse -Force -ErrorAction SilentlyContinue
42
- }
43
-
44
- Get-Process BuildCorpusEditor -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
45
- foreach ($legacyProductName in $LegacyProductNames) {
46
- Remove-Item -LiteralPath (Join-Path $StartMenuDir "$legacyProductName.lnk") -Force -ErrorAction SilentlyContinue
47
- Remove-Item -LiteralPath (Join-Path $StartMenuDir "Uninstall $legacyProductName.lnk") -Force -ErrorAction SilentlyContinue
48
- }
49
- Remove-Item -LiteralPath $ShortcutPath -Force -ErrorAction SilentlyContinue
50
- Remove-Item -LiteralPath $UninstallShortcutPath -Force -ErrorAction SilentlyContinue
51
- foreach ($ext in @(".md", ".docx", ".pptx", ".ppt")) {
52
- foreach ($verb in @("ManuscriptForgeOpen", "BuildCorpusOpenEditor", "RegenMDEditorOpen", "BuildCorpusToMarkdown", "BuildCorpusToWord", "BuildCorpusInlineImages")) {
53
- Remove-FileVerb -Extension $ext -Verb $verb
54
- }
55
- }
56
- Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\Directory\shell\BuildCorpusFolderToMarkdown" -Recurse -Force -ErrorAction SilentlyContinue
57
- if ((Test-Path -LiteralPath $LegacyInstallDir) -and ($LegacyInstallDir -ne $InstallDir)) {
58
- Remove-Item -LiteralPath $LegacyInstallDir -Recurse -Force -ErrorAction SilentlyContinue
59
- }
60
- if ((Test-Path -LiteralPath $LegacyInstallDir2) -and ($LegacyInstallDir2 -ne $InstallDir)) {
61
- Remove-Item -LiteralPath $LegacyInstallDir2 -Recurse -Force -ErrorAction SilentlyContinue
62
- }
63
-
64
- New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
65
- foreach ($item in @("wwwroot", "runtimes")) {
66
- Remove-Item -LiteralPath (Join-Path $InstallDir $item) -Recurse -Force -ErrorAction SilentlyContinue
67
- }
68
- foreach ($pattern in @("BuildCorpusEditor.*", "Microsoft.Web.WebView2.*", "WebView2Loader.dll")) {
69
- Get-ChildItem -LiteralPath $InstallDir -Filter $pattern -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue
70
- }
71
- Copy-Item -Path (Join-Path $AppSource "*") -Destination $InstallDir -Recurse -Force
72
- foreach ($item in @("bin", "src")) {
73
- $sourcePath = Join-Path $PackageRoot $item
74
- if (Test-Path -LiteralPath $sourcePath) {
75
- $destinationPath = Join-Path $InstallDir $item
76
- Remove-Item -LiteralPath $destinationPath -Recurse -Force -ErrorAction SilentlyContinue
77
- Copy-Item -LiteralPath $sourcePath -Destination $InstallDir -Recurse -Force
78
- }
79
- }
80
- foreach ($item in @("requirements.txt", "pyproject.toml", "package.json", "package-lock.json")) {
81
- $sourcePath = Join-Path $PackageRoot $item
82
- if (Test-Path -LiteralPath $sourcePath) {
83
- Copy-Item -LiteralPath $sourcePath -Destination $InstallDir -Force
84
- }
85
- }
86
-
87
- $InstalledExe = Join-Path $InstallDir "BuildCorpusEditor.exe"
88
- $UninstallScript = Join-Path $InstallDir "uninstall-regen-mde.ps1"
89
-
90
- if (-not (Get-Command node -ErrorAction SilentlyContinue)) {
91
- throw "Node.js is required on PATH for DOCX/Markdown conversion."
92
- }
93
- $NodeExe = (Get-Command node -ErrorAction Stop).Source
94
-
95
- $requirements = Join-Path $InstallDir "requirements.txt"
96
- $pythonReady = $false
97
- foreach ($candidate in @("py", "python")) {
98
- if (-not (Get-Command $candidate -ErrorAction SilentlyContinue)) { continue }
99
- if ($candidate -eq "py") {
100
- & py -3 -c "import omml2latex, boto3, PIL, docx" 2>$null
101
- } else {
102
- & python -c "import omml2latex, boto3, PIL, docx" 2>$null
103
- }
104
- if ($LASTEXITCODE -eq 0) {
105
- $pythonReady = $true
106
- break
107
- }
108
- }
109
-
110
- if (-not $pythonReady) {
111
- Write-Warning "Python conversion dependencies are not already installed. Install them later with: py -3 -m pip install -r `"$requirements`""
112
- }
113
-
114
- New-Item -ItemType Directory -Force -Path $StartMenuDir | Out-Null
115
- $shell = New-Object -ComObject WScript.Shell
116
- $shortcut = $shell.CreateShortcut($ShortcutPath)
117
- $shortcut.TargetPath = $InstalledExe
118
- $shortcut.WorkingDirectory = $InstallDir
119
- $shortcut.IconLocation = "$InstalledExe,0"
120
- $shortcut.Description = "$ProductName Word and Markdown editor"
121
- $shortcut.Save()
122
-
123
- function Set-FileVerb {
124
- param(
125
- [string]$Extension,
126
- [string]$Verb,
127
- [string]$Label,
128
- [string]$Command
129
- )
130
- $key = "Registry::HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\$Extension\shell\$Verb"
131
- $commandKey = Join-Path $key "command"
132
- New-Item -Path $commandKey -Force | Out-Null
133
- New-ItemProperty -Path $key -Name "MUIVerb" -Value $Label -PropertyType String -Force | Out-Null
134
- New-ItemProperty -Path $key -Name "Icon" -Value $InstalledExe -PropertyType ExpandString -Force | Out-Null
135
- [Microsoft.Win32.Registry]::SetValue(
136
- "HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\$Extension\shell\$Verb\command",
137
- "",
138
- $Command,
139
- [Microsoft.Win32.RegistryValueKind]::String)
140
- }
141
-
142
- function Set-FolderVerb {
143
- param(
144
- [string]$Verb,
145
- [string]$Label,
146
- [string]$Command
147
- )
148
- $key = "Registry::HKEY_CURRENT_USER\Software\Classes\Directory\shell\$Verb"
149
- $commandKey = Join-Path $key "command"
150
- New-Item -Path $commandKey -Force | Out-Null
151
- New-ItemProperty -Path $key -Name "MUIVerb" -Value $Label -PropertyType String -Force | Out-Null
152
- New-ItemProperty -Path $key -Name "Icon" -Value $InstalledExe -PropertyType ExpandString -Force | Out-Null
153
- [Microsoft.Win32.Registry]::SetValue(
154
- "HKEY_CURRENT_USER\Software\Classes\Directory\shell\$Verb\command",
155
- "",
156
- $Command,
157
- [Microsoft.Win32.RegistryValueKind]::String)
158
- }
159
-
160
- Set-FileVerb -Extension ".md" -Verb "RegenMDEditorOpen" -Label "Open in regen-mde" -Command "`"$InstalledExe`" `"%1`""
161
- Set-FileVerb -Extension ".docx" -Verb "RegenMDEditorOpen" -Label "Open in regen-mde" -Command "`"$InstalledExe`" `"%1`""
162
- Set-FileVerb -Extension ".docx" -Verb "BuildCorpusToMarkdown" -Label "Convert to Markdown" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --out-same-dir"
163
- Set-FileVerb -Extension ".pptx" -Verb "BuildCorpusToMarkdown" -Label "Convert to Markdown" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --out-same-dir"
164
- Set-FileVerb -Extension ".ppt" -Verb "BuildCorpusToMarkdown" -Label "Convert to Markdown" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --out-same-dir"
165
- Set-FileVerb -Extension ".md" -Verb "BuildCorpusToWord" -Label "Convert to Word" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --to word --out-same-dir"
166
- Set-FileVerb -Extension ".md" -Verb "BuildCorpusInlineImages" -Label "Inline Markdown Images" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --inline-images"
167
- Set-FolderVerb -Verb "BuildCorpusFolderToMarkdown" -Label "Convert Documents to Markdown" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%V`" --out-same-dir"
168
- New-Item -Path "Registry::HKEY_CURRENT_USER\Software\Classes\.md\ShellNew" -Force | Out-Null
169
- New-ItemProperty -Path "Registry::HKEY_CURRENT_USER\Software\Classes\.md" -Name "Content Type" -Value "text/markdown" -PropertyType String -Force | Out-Null
170
- New-ItemProperty -Path "Registry::HKEY_CURRENT_USER\Software\Classes\.md\ShellNew" -Name "NullFile" -Value "" -PropertyType String -Force | Out-Null
171
-
172
- $uninstall = @"
173
- `$ErrorActionPreference = "Stop"
174
- `$ProductName = "regen-mde"
175
- `$InstallDir = Split-Path -Parent `$MyInvocation.MyCommand.Path
176
- `$StartMenuDir = Join-Path `$env:APPDATA "Microsoft\Windows\Start Menu\Programs\LIFE AI"
177
- Get-Process BuildCorpusEditor -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
178
- Remove-Item -LiteralPath (Join-Path `$StartMenuDir "`$ProductName.lnk") -Force -ErrorAction SilentlyContinue
179
- Remove-Item -LiteralPath (Join-Path `$StartMenuDir "Uninstall `$ProductName.lnk") -Force -ErrorAction SilentlyContinue
180
- Remove-Item -LiteralPath (Join-Path `$StartMenuDir "Regen.MDeditor.lnk") -Force -ErrorAction SilentlyContinue
181
- Remove-Item -LiteralPath (Join-Path `$StartMenuDir "Manuscript Forge.lnk") -Force -ErrorAction SilentlyContinue
182
- Remove-Item -LiteralPath (Join-Path `$StartMenuDir "Uninstall Regen.MDeditor.lnk") -Force -ErrorAction SilentlyContinue
183
- foreach (`$ext in @(".md", ".docx", ".pptx", ".ppt")) {
184
- foreach (`$verb in @("RegenMDEditorOpen", "BuildCorpusToMarkdown", "BuildCorpusToWord", "BuildCorpusInlineImages", "ManuscriptForgeOpen", "BuildCorpusOpenEditor")) {
185
- Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\`$ext\shell\`$verb" -Recurse -Force -ErrorAction SilentlyContinue
186
- }
187
- }
188
- Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\Directory\shell\BuildCorpusFolderToMarkdown" -Recurse -Force -ErrorAction SilentlyContinue
189
- Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\.md\ShellNew" -Recurse -Force -ErrorAction SilentlyContinue
190
- for (`$i = 0; `$i -lt 10; `$i++) {
191
- Start-Sleep -Milliseconds 250
192
- try {
193
- Remove-Item -LiteralPath `$InstallDir -Recurse -Force
194
- break
195
- } catch {
196
- if (`$i -eq 9) { throw }
197
- }
198
- }
199
- Write-Host "`$ProductName removed."
200
- "@
201
- Set-Content -LiteralPath $UninstallScript -Value $uninstall -Encoding UTF8
202
-
203
- $uninstallShortcut = $shell.CreateShortcut($UninstallShortcutPath)
204
- $uninstallShortcut.TargetPath = "powershell.exe"
205
- $uninstallShortcut.Arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$UninstallScript`""
206
- $uninstallShortcut.WorkingDirectory = $InstallDir
207
- $uninstallShortcut.IconLocation = "$InstalledExe,0"
208
- $uninstallShortcut.Description = "Uninstall $ProductName"
209
- $uninstallShortcut.Save()
210
-
211
- Write-Host "$ProductName installed."
212
- Write-Host "InstallDir=$InstallDir"
213
- Write-Host "Shortcut=$ShortcutPath"
214
- Write-Host "Executable=$InstalledExe"
1
+ [CmdletBinding()]
2
+ param(
3
+ [string]$PackageRoot = "",
4
+ [string]$InstallDir = "$env:LOCALAPPDATA\Programs\regen-mde"
5
+ )
6
+
7
+ $ErrorActionPreference = "Stop"
8
+
9
+ if ([string]::IsNullOrWhiteSpace($PackageRoot)) {
10
+ $PackageApp = Join-Path $PSScriptRoot "app"
11
+ if (Test-Path -LiteralPath (Join-Path $PackageApp "BuildCorpusEditor.exe")) {
12
+ $PackageRoot = $PackageApp
13
+ } else {
14
+ $PackageRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
15
+ }
16
+ }
17
+
18
+ $ProductName = "regen-mde"
19
+ $LegacyProductNames = @("Manuscript Forge", "Regen.MDeditor")
20
+ $AppSource = if (Test-Path -LiteralPath (Join-Path $PackageRoot "BuildCorpusEditor.exe")) {
21
+ $PackageRoot
22
+ } else {
23
+ Join-Path $PackageRoot "dist\windows-editor"
24
+ }
25
+ $AppExe = Join-Path $AppSource "BuildCorpusEditor.exe"
26
+ $StartMenuDir = Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\LIFE AI"
27
+ $ShortcutPath = Join-Path $StartMenuDir "$ProductName.lnk"
28
+ $UninstallShortcutPath = Join-Path $StartMenuDir "Uninstall $ProductName.lnk"
29
+ $LegacyInstallDir = Join-Path $env:LOCALAPPDATA "Programs\Manuscript Forge"
30
+ $LegacyInstallDir2 = Join-Path $env:LOCALAPPDATA "Programs\Regen.MDeditor"
31
+
32
+ if (-not (Test-Path -LiteralPath $AppExe)) {
33
+ throw "Package is missing BuildCorpusEditor.exe"
34
+ }
35
+
36
+ function Remove-FileVerb {
37
+ param(
38
+ [string]$Extension,
39
+ [string]$Verb
40
+ )
41
+ Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\$Extension\shell\$Verb" -Recurse -Force -ErrorAction SilentlyContinue
42
+ }
43
+
44
+ Get-Process BuildCorpusEditor -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
45
+ foreach ($legacyProductName in $LegacyProductNames) {
46
+ Remove-Item -LiteralPath (Join-Path $StartMenuDir "$legacyProductName.lnk") -Force -ErrorAction SilentlyContinue
47
+ Remove-Item -LiteralPath (Join-Path $StartMenuDir "Uninstall $legacyProductName.lnk") -Force -ErrorAction SilentlyContinue
48
+ }
49
+ Remove-Item -LiteralPath $ShortcutPath -Force -ErrorAction SilentlyContinue
50
+ Remove-Item -LiteralPath $UninstallShortcutPath -Force -ErrorAction SilentlyContinue
51
+ foreach ($ext in @(".md", ".docx", ".pptx", ".ppt")) {
52
+ foreach ($verb in @("ManuscriptForgeOpen", "BuildCorpusOpenEditor", "RegenMDEditorOpen", "BuildCorpusToMarkdown", "BuildCorpusToWord", "BuildCorpusInlineImages")) {
53
+ Remove-FileVerb -Extension $ext -Verb $verb
54
+ }
55
+ }
56
+ Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\Directory\shell\BuildCorpusFolderToMarkdown" -Recurse -Force -ErrorAction SilentlyContinue
57
+ if ((Test-Path -LiteralPath $LegacyInstallDir) -and ($LegacyInstallDir -ne $InstallDir)) {
58
+ Remove-Item -LiteralPath $LegacyInstallDir -Recurse -Force -ErrorAction SilentlyContinue
59
+ }
60
+ if ((Test-Path -LiteralPath $LegacyInstallDir2) -and ($LegacyInstallDir2 -ne $InstallDir)) {
61
+ Remove-Item -LiteralPath $LegacyInstallDir2 -Recurse -Force -ErrorAction SilentlyContinue
62
+ }
63
+
64
+ New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
65
+ foreach ($item in @("wwwroot", "runtimes")) {
66
+ Remove-Item -LiteralPath (Join-Path $InstallDir $item) -Recurse -Force -ErrorAction SilentlyContinue
67
+ }
68
+ foreach ($pattern in @("BuildCorpusEditor.*", "Microsoft.Web.WebView2.*", "WebView2Loader.dll")) {
69
+ Get-ChildItem -LiteralPath $InstallDir -Filter $pattern -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue
70
+ }
71
+ Copy-Item -Path (Join-Path $AppSource "*") -Destination $InstallDir -Recurse -Force
72
+ foreach ($item in @("bin", "src")) {
73
+ $sourcePath = Join-Path $PackageRoot $item
74
+ if (Test-Path -LiteralPath $sourcePath) {
75
+ $destinationPath = Join-Path $InstallDir $item
76
+ Remove-Item -LiteralPath $destinationPath -Recurse -Force -ErrorAction SilentlyContinue
77
+ Copy-Item -LiteralPath $sourcePath -Destination $InstallDir -Recurse -Force
78
+ }
79
+ }
80
+ foreach ($item in @("requirements.txt", "pyproject.toml", "package.json", "package-lock.json")) {
81
+ $sourcePath = Join-Path $PackageRoot $item
82
+ if (Test-Path -LiteralPath $sourcePath) {
83
+ Copy-Item -LiteralPath $sourcePath -Destination $InstallDir -Force
84
+ }
85
+ }
86
+
87
+ $InstalledExe = Join-Path $InstallDir "BuildCorpusEditor.exe"
88
+ $UninstallScript = Join-Path $InstallDir "uninstall-regen-mde.ps1"
89
+
90
+ if (-not (Get-Command node -ErrorAction SilentlyContinue)) {
91
+ throw "Node.js is required on PATH for DOCX/Markdown conversion."
92
+ }
93
+ $NodeExe = (Get-Command node -ErrorAction Stop).Source
94
+
95
+ $requirements = Join-Path $InstallDir "requirements.txt"
96
+ $pythonReady = $false
97
+ foreach ($candidate in @("py", "python")) {
98
+ if (-not (Get-Command $candidate -ErrorAction SilentlyContinue)) { continue }
99
+ if ($candidate -eq "py") {
100
+ & py -3 -c "import omml2latex, boto3, PIL, docx" 2>$null
101
+ } else {
102
+ & python -c "import omml2latex, boto3, PIL, docx" 2>$null
103
+ }
104
+ if ($LASTEXITCODE -eq 0) {
105
+ $pythonReady = $true
106
+ break
107
+ }
108
+ }
109
+
110
+ if (-not $pythonReady) {
111
+ Write-Warning "Python conversion dependencies are not already installed. Install them later with: py -3 -m pip install -r `"$requirements`""
112
+ }
113
+
114
+ New-Item -ItemType Directory -Force -Path $StartMenuDir | Out-Null
115
+ $shell = New-Object -ComObject WScript.Shell
116
+ $shortcut = $shell.CreateShortcut($ShortcutPath)
117
+ $shortcut.TargetPath = $InstalledExe
118
+ $shortcut.WorkingDirectory = $InstallDir
119
+ $shortcut.IconLocation = "$InstalledExe,0"
120
+ $shortcut.Description = "$ProductName Word and Markdown editor"
121
+ $shortcut.Save()
122
+
123
+ function Set-FileVerb {
124
+ param(
125
+ [string]$Extension,
126
+ [string]$Verb,
127
+ [string]$Label,
128
+ [string]$Command
129
+ )
130
+ $key = "Registry::HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\$Extension\shell\$Verb"
131
+ $commandKey = Join-Path $key "command"
132
+ New-Item -Path $commandKey -Force | Out-Null
133
+ New-ItemProperty -Path $key -Name "MUIVerb" -Value $Label -PropertyType String -Force | Out-Null
134
+ New-ItemProperty -Path $key -Name "Icon" -Value $InstalledExe -PropertyType ExpandString -Force | Out-Null
135
+ [Microsoft.Win32.Registry]::SetValue(
136
+ "HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\$Extension\shell\$Verb\command",
137
+ "",
138
+ $Command,
139
+ [Microsoft.Win32.RegistryValueKind]::String)
140
+ }
141
+
142
+ function Set-FolderVerb {
143
+ param(
144
+ [string]$Verb,
145
+ [string]$Label,
146
+ [string]$Command
147
+ )
148
+ $key = "Registry::HKEY_CURRENT_USER\Software\Classes\Directory\shell\$Verb"
149
+ $commandKey = Join-Path $key "command"
150
+ New-Item -Path $commandKey -Force | Out-Null
151
+ New-ItemProperty -Path $key -Name "MUIVerb" -Value $Label -PropertyType String -Force | Out-Null
152
+ New-ItemProperty -Path $key -Name "Icon" -Value $InstalledExe -PropertyType ExpandString -Force | Out-Null
153
+ [Microsoft.Win32.Registry]::SetValue(
154
+ "HKEY_CURRENT_USER\Software\Classes\Directory\shell\$Verb\command",
155
+ "",
156
+ $Command,
157
+ [Microsoft.Win32.RegistryValueKind]::String)
158
+ }
159
+
160
+ Set-FileVerb -Extension ".md" -Verb "RegenMDEditorOpen" -Label "Open in regen-mde" -Command "`"$InstalledExe`" `"%1`""
161
+ Set-FileVerb -Extension ".docx" -Verb "RegenMDEditorOpen" -Label "Open in regen-mde" -Command "`"$InstalledExe`" `"%1`""
162
+ Set-FileVerb -Extension ".docx" -Verb "BuildCorpusToMarkdown" -Label "Convert to Markdown" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --out-same-dir"
163
+ Set-FileVerb -Extension ".pptx" -Verb "BuildCorpusToMarkdown" -Label "Convert to Markdown" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --out-same-dir"
164
+ Set-FileVerb -Extension ".ppt" -Verb "BuildCorpusToMarkdown" -Label "Convert to Markdown" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --out-same-dir"
165
+ Set-FileVerb -Extension ".md" -Verb "BuildCorpusToWord" -Label "Convert to Word" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --to word --out-same-dir"
166
+ Set-FileVerb -Extension ".md" -Verb "BuildCorpusInlineImages" -Label "Inline Markdown Images" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%1`" --inline-images"
167
+ Set-FolderVerb -Verb "BuildCorpusFolderToMarkdown" -Label "Convert Documents to Markdown" -Command "`"$NodeExe`" `"$InstallDir\bin\build-corpus.js`" `"%V`" --out-same-dir"
168
+ New-Item -Path "Registry::HKEY_CURRENT_USER\Software\Classes\.md\ShellNew" -Force | Out-Null
169
+ New-ItemProperty -Path "Registry::HKEY_CURRENT_USER\Software\Classes\.md" -Name "Content Type" -Value "text/markdown" -PropertyType String -Force | Out-Null
170
+ New-ItemProperty -Path "Registry::HKEY_CURRENT_USER\Software\Classes\.md\ShellNew" -Name "NullFile" -Value "" -PropertyType String -Force | Out-Null
171
+
172
+ $uninstall = @"
173
+ `$ErrorActionPreference = "Stop"
174
+ `$ProductName = "regen-mde"
175
+ `$InstallDir = Split-Path -Parent `$MyInvocation.MyCommand.Path
176
+ `$StartMenuDir = Join-Path `$env:APPDATA "Microsoft\Windows\Start Menu\Programs\LIFE AI"
177
+ Get-Process BuildCorpusEditor -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
178
+ Remove-Item -LiteralPath (Join-Path `$StartMenuDir "`$ProductName.lnk") -Force -ErrorAction SilentlyContinue
179
+ Remove-Item -LiteralPath (Join-Path `$StartMenuDir "Uninstall `$ProductName.lnk") -Force -ErrorAction SilentlyContinue
180
+ Remove-Item -LiteralPath (Join-Path `$StartMenuDir "Regen.MDeditor.lnk") -Force -ErrorAction SilentlyContinue
181
+ Remove-Item -LiteralPath (Join-Path `$StartMenuDir "Manuscript Forge.lnk") -Force -ErrorAction SilentlyContinue
182
+ Remove-Item -LiteralPath (Join-Path `$StartMenuDir "Uninstall Regen.MDeditor.lnk") -Force -ErrorAction SilentlyContinue
183
+ foreach (`$ext in @(".md", ".docx", ".pptx", ".ppt")) {
184
+ foreach (`$verb in @("RegenMDEditorOpen", "BuildCorpusToMarkdown", "BuildCorpusToWord", "BuildCorpusInlineImages", "ManuscriptForgeOpen", "BuildCorpusOpenEditor")) {
185
+ Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\`$ext\shell\`$verb" -Recurse -Force -ErrorAction SilentlyContinue
186
+ }
187
+ }
188
+ Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\Directory\shell\BuildCorpusFolderToMarkdown" -Recurse -Force -ErrorAction SilentlyContinue
189
+ Remove-Item -LiteralPath "Registry::HKEY_CURRENT_USER\Software\Classes\.md\ShellNew" -Recurse -Force -ErrorAction SilentlyContinue
190
+ for (`$i = 0; `$i -lt 10; `$i++) {
191
+ Start-Sleep -Milliseconds 250
192
+ try {
193
+ Remove-Item -LiteralPath `$InstallDir -Recurse -Force
194
+ break
195
+ } catch {
196
+ if (`$i -eq 9) { throw }
197
+ }
198
+ }
199
+ Write-Host "`$ProductName removed."
200
+ "@
201
+ Set-Content -LiteralPath $UninstallScript -Value $uninstall -Encoding UTF8
202
+
203
+ $uninstallShortcut = $shell.CreateShortcut($UninstallShortcutPath)
204
+ $uninstallShortcut.TargetPath = "powershell.exe"
205
+ $uninstallShortcut.Arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$UninstallScript`""
206
+ $uninstallShortcut.WorkingDirectory = $InstallDir
207
+ $uninstallShortcut.IconLocation = "$InstalledExe,0"
208
+ $uninstallShortcut.Description = "Uninstall $ProductName"
209
+ $uninstallShortcut.Save()
210
+
211
+ Write-Host "$ProductName installed."
212
+ Write-Host "InstallDir=$InstallDir"
213
+ Write-Host "Shortcut=$ShortcutPath"
214
+ Write-Host "Executable=$InstalledExe"