regen.mde 0.2.2 → 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 (56) hide show
  1. package/LICENSE +16 -16
  2. package/README.md +409 -295
  3. package/bin/build-corpus-editor.js +83 -81
  4. package/bin/build-corpus.js +41 -41
  5. package/bin/postinstall.js +259 -187
  6. package/bin/regen-mdeditor-install.js +27 -27
  7. package/bin/regen-mdeditor-uninstall.js +19 -19
  8. package/bin/validate-katex.js +93 -93
  9. package/desktop/BuildCorpusEditor/BuildCorpusBridge.cs +493 -270
  10. package/desktop/BuildCorpusEditor/BuildCorpusEditor.csproj +22 -22
  11. package/desktop/BuildCorpusEditor/EditorForm.cs +853 -540
  12. package/desktop/BuildCorpusEditor/Program.cs +85 -81
  13. package/desktop/BuildCorpusEditor/app.manifest +16 -16
  14. package/dist/release/regen-mde-0.8.0-win-x64.zip +0 -0
  15. package/dist/windows-editor/BuildCorpusEditor.dll +0 -0
  16. package/dist/windows-editor/BuildCorpusEditor.exe +0 -0
  17. package/dist/windows-editor/BuildCorpusEditor.pdb +0 -0
  18. package/dist/windows-editor/BuildCorpusEditor.runtimeconfig.json +1 -1
  19. package/dist/windows-editor/wwwroot/assets/index-C_VxJk4k.js +375 -0
  20. package/dist/windows-editor/wwwroot/assets/index-Wt9zSjIw.css +1 -0
  21. package/dist/windows-editor/wwwroot/index.html +22 -22
  22. package/editor-web/index.html +21 -21
  23. package/editor-web/src/main.jsx +1044 -399
  24. package/editor-web/src/styles.css +846 -602
  25. package/editor-web/vite.config.js +13 -13
  26. package/examples/build-corpus.config.example.json +21 -21
  27. package/installer/install-regen-mde.ps1 +214 -175
  28. package/installer/regen-mde.nsi +81 -81
  29. package/package.json +10 -6
  30. package/pyproject.toml +4 -3
  31. package/requirements.txt +5 -4
  32. package/scripts/build-windows-editor.ps1 +47 -47
  33. package/scripts/package-windows-editor.ps1 +90 -90
  34. package/scripts/release-dual.mjs +105 -0
  35. package/scripts/run-corpus.ps1 +28 -28
  36. package/scripts/run-editor-implementation-plane.ps1 +226 -203
  37. package/scripts/run-required-tests.ps1 +98 -98
  38. package/scripts/run-smoke.ps1 +28 -28
  39. package/src/build_corpus/__init__.py +1 -1
  40. package/src/build_corpus/docx_exporter.py +1055 -798
  41. package/src/build_corpus/equations.py +1345 -0
  42. package/src/build_corpus/exporter.py +1488 -1195
  43. package/src/build_corpus/frontmatter.py +302 -0
  44. package/src/build_corpus/ppt_exporter.py +543 -532
  45. package/src/build_corpus/templates/__init__.py +1 -1
  46. package/src/build_corpus/validate_assets.py +46 -46
  47. package/tools/audit_corpus.py +203 -203
  48. package/tools/collect_microsoft_word_templates.py +228 -228
  49. package/tools/collect_online_docx_corpus.py +272 -272
  50. package/tools/collect_online_pptx_corpus.py +252 -252
  51. package/tools/compare_pptx_inputs_outputs.py +87 -87
  52. package/tools/roundtrip_docx_corpus.py +171 -171
  53. package/dist/release/regen.mde-0.2.2-win-x64-setup.exe +0 -0
  54. package/dist/release/regen.mde-0.2.2-win-x64.zip +0 -0
  55. package/dist/windows-editor/wwwroot/assets/index-DjJ6xmhy.js +0 -326
  56. package/dist/windows-editor/wwwroot/assets/index-_dwMNNsm.css +0 -1
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "regen.mde",
3
- "version": "0.2.2",
4
- "description": "Convert DOCX to Markdown with tables, images, and KaTeX-readable Word equations.",
3
+ "version": "0.8.0",
4
+ "description": "Convert between DOCX/PPTX and Markdown Word OMML equations to KaTeX TeX on the way in, LaTeX to native OMML on the way out.",
5
5
  "bin": {
6
6
  "build-corpus": "bin/build-corpus.js",
7
7
  "build-corpus-editor": "bin/build-corpus-editor.js",
8
- "regen.mde": "bin/build-corpus-editor.js",
9
- "regen.mdeditor": "bin/build-corpus-editor.js",
8
+ "mdeditor": "bin/build-corpus-editor.js",
9
+ "regen-mde": "bin/build-corpus-editor.js",
10
10
  "regen-mdeditor": "bin/build-corpus-editor.js",
11
11
  "regen-mdeditor-install": "bin/regen-mdeditor-install.js",
12
12
  "regen-mdeditor-uninstall": "bin/regen-mdeditor-uninstall.js",
@@ -17,8 +17,8 @@
17
17
  "desktop/BuildCorpusEditor/*.cs",
18
18
  "desktop/BuildCorpusEditor/*.csproj",
19
19
  "desktop/BuildCorpusEditor/*.manifest",
20
- "dist/release/regen.mde-*-win-x64-setup.exe",
21
- "dist/release/regen.mde-*-win-x64.zip",
20
+ "dist/release/regen-mde-*-win-x64-setup.exe",
21
+ "dist/release/regen-mde-*-win-x64.zip",
22
22
  "dist/windows-editor/",
23
23
  "editor-web/",
24
24
  "installer/",
@@ -41,12 +41,15 @@
41
41
  "test:editor": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/run-required-tests.ps1 -Suite Editor",
42
42
  "test:required": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/run-required-tests.ps1 -Suite Auto",
43
43
  "test:all": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/run-required-tests.ps1 -Suite All",
44
+ "release": "node scripts/release-dual.mjs",
44
45
  "prepack": "npm run editor:windows && npm run editor:package",
45
46
  "postinstall": "node bin/postinstall.js",
46
47
  "preuninstall": "node bin/postinstall.js --uninstall",
47
48
  "test": "node bin/build-corpus.js --help && node bin/validate-katex.js README.md"
48
49
  },
49
50
  "dependencies": {
51
+ "@codemirror/lang-markdown": "^6.5.0",
52
+ "@codemirror/theme-one-dark": "^6.1.3",
50
53
  "@tiptap/extension-bubble-menu": "^3.23.1",
51
54
  "@tiptap/extension-floating-menu": "^3.23.1",
52
55
  "@tiptap/extension-image": "^3.23.1",
@@ -60,6 +63,7 @@
60
63
  "@tiptap/extension-task-list": "^3.23.1",
61
64
  "@tiptap/react": "^3.23.1",
62
65
  "@tiptap/starter-kit": "^3.23.1",
66
+ "@uiw/react-codemirror": "^4.25.9",
63
67
  "katex": "^0.16.22",
64
68
  "marked": "^15.0.12",
65
69
  "react": "^19.2.6",
package/pyproject.toml CHANGED
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "build-corpus"
7
- version = "0.2.0"
8
- description = "Convert DOCX to Markdown with tables, images, and KaTeX-readable Word equations."
7
+ version = "0.8.0"
8
+ description = "Convert between DOCX/PPTX and Markdown Word OMML equations to KaTeX TeX inbound, LaTeX to native OMML outbound."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  license = "Apache-2.0"
@@ -16,7 +16,8 @@ keywords = ["docx", "markdown", "omml", "katex", "word", "converter"]
16
16
  dependencies = [
17
17
  "omml2latex>=0.1.1",
18
18
  "Pillow>=10.0.0",
19
- "python-docx>=1.1.2"
19
+ "python-docx>=1.1.2",
20
+ "latex2mathml>=3.77"
20
21
  ]
21
22
 
22
23
  [project.optional-dependencies]
package/requirements.txt CHANGED
@@ -1,4 +1,5 @@
1
- omml2latex>=0.1.1
2
- boto3>=1.34
3
- Pillow>=10.0.0
4
- python-docx>=1.1.2
1
+ omml2latex>=0.1.1
2
+ boto3>=1.34
3
+ Pillow>=10.0.0
4
+ python-docx>=1.1.2
5
+ latex2mathml>=3.77
@@ -1,47 +1,47 @@
1
- [CmdletBinding()]
2
- param(
3
- [string]$Root = ""
4
- )
5
-
6
- $ErrorActionPreference = "Stop"
7
-
8
- if ([string]::IsNullOrWhiteSpace($Root)) {
9
- $Root = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
10
- }
11
-
12
- function Invoke-Checked {
13
- param([string]$FilePath, [string[]]$Arguments)
14
- Write-Host "+ $FilePath $($Arguments -join ' ')" -ForegroundColor DarkGray
15
- Push-Location $Root
16
- try {
17
- & $FilePath @Arguments
18
- $exitCode = if ($LASTEXITCODE -is [int]) { $LASTEXITCODE } else { 0 }
19
- } finally {
20
- Pop-Location
21
- }
22
- if ($exitCode -ne 0) {
23
- throw "Command failed with exit code ${exitCode}: $FilePath $($Arguments -join ' ')"
24
- }
25
- }
26
-
27
- Invoke-Checked "npm" @("run", "editor:build")
28
-
29
- Get-Process BuildCorpusEditor -ErrorAction SilentlyContinue | Stop-Process -Force
30
-
31
- Invoke-Checked "dotnet" @(
32
- "publish",
33
- "desktop\BuildCorpusEditor\BuildCorpusEditor.csproj",
34
- "-c", "Release",
35
- "-r", "win-x64",
36
- "--self-contained", "false",
37
- "-o", "dist\windows-editor"
38
- )
39
-
40
- $exe = Join-Path $Root "dist\windows-editor\BuildCorpusEditor.exe"
41
- if (-not (Test-Path -LiteralPath $exe)) {
42
- throw "Expected executable missing: $exe"
43
- }
44
-
45
- Remove-Item -LiteralPath (Join-Path $Root "dist\windows-editor\BuildCorpusEditor.exe.WebView2") -Recurse -Force -ErrorAction SilentlyContinue
46
-
47
- Write-Host "Built $exe" -ForegroundColor Green
1
+ [CmdletBinding()]
2
+ param(
3
+ [string]$Root = ""
4
+ )
5
+
6
+ $ErrorActionPreference = "Stop"
7
+
8
+ if ([string]::IsNullOrWhiteSpace($Root)) {
9
+ $Root = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
10
+ }
11
+
12
+ function Invoke-Checked {
13
+ param([string]$FilePath, [string[]]$Arguments)
14
+ Write-Host "+ $FilePath $($Arguments -join ' ')" -ForegroundColor DarkGray
15
+ Push-Location $Root
16
+ try {
17
+ & $FilePath @Arguments
18
+ $exitCode = if ($LASTEXITCODE -is [int]) { $LASTEXITCODE } else { 0 }
19
+ } finally {
20
+ Pop-Location
21
+ }
22
+ if ($exitCode -ne 0) {
23
+ throw "Command failed with exit code ${exitCode}: $FilePath $($Arguments -join ' ')"
24
+ }
25
+ }
26
+
27
+ Invoke-Checked "npm" @("run", "editor:build")
28
+
29
+ Get-Process BuildCorpusEditor -ErrorAction SilentlyContinue | Stop-Process -Force
30
+
31
+ Invoke-Checked "dotnet" @(
32
+ "publish",
33
+ "desktop\BuildCorpusEditor\BuildCorpusEditor.csproj",
34
+ "-c", "Release",
35
+ "-r", "win-x64",
36
+ "--self-contained", "false",
37
+ "-o", "dist\windows-editor"
38
+ )
39
+
40
+ $exe = Join-Path $Root "dist\windows-editor\BuildCorpusEditor.exe"
41
+ if (-not (Test-Path -LiteralPath $exe)) {
42
+ throw "Expected executable missing: $exe"
43
+ }
44
+
45
+ Remove-Item -LiteralPath (Join-Path $Root "dist\windows-editor\BuildCorpusEditor.exe.WebView2") -Recurse -Force -ErrorAction SilentlyContinue
46
+
47
+ Write-Host "Built $exe" -ForegroundColor Green
@@ -1,90 +1,90 @@
1
- [CmdletBinding()]
2
- param(
3
- [string]$Root = "",
4
- [string]$Version = ""
5
- )
6
-
7
- $ErrorActionPreference = "Stop"
8
-
9
- if ([string]::IsNullOrWhiteSpace($Root)) {
10
- $Root = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
11
- }
12
-
13
- if ([string]::IsNullOrWhiteSpace($Version)) {
14
- $pkg = Get-Content -Raw -LiteralPath (Join-Path $Root "package.json") | ConvertFrom-Json
15
- $Version = $pkg.version
16
- }
17
-
18
- $releaseRoot = Join-Path $Root "dist\release"
19
- $stage = Join-Path $releaseRoot "regen.mde-$Version-win-x64"
20
- $app = Join-Path $stage "app"
21
- $zip = Join-Path $releaseRoot "regen.mde-$Version-win-x64.zip"
22
- $setupExe = Join-Path $releaseRoot "regen.mde-$Version-win-x64-setup.exe"
23
-
24
- Remove-Item -LiteralPath $stage -Recurse -Force -ErrorAction SilentlyContinue
25
- Remove-Item -LiteralPath $zip -Force -ErrorAction SilentlyContinue
26
- Remove-Item -LiteralPath $setupExe -Force -ErrorAction SilentlyContinue
27
- New-Item -ItemType Directory -Force -Path $app | Out-Null
28
-
29
- Copy-Item -Path (Join-Path $Root "dist\windows-editor\*") -Destination $app -Recurse -Force
30
- Remove-Item -LiteralPath (Join-Path $app "BuildCorpusEditor.exe.WebView2") -Recurse -Force -ErrorAction SilentlyContinue
31
- Copy-Item -LiteralPath (Join-Path $Root "bin") -Destination $app -Recurse -Force
32
- Copy-Item -LiteralPath (Join-Path $Root "src") -Destination $app -Recurse -Force
33
- Copy-Item -LiteralPath (Join-Path $Root "requirements.txt") -Destination $app -Force
34
- Copy-Item -LiteralPath (Join-Path $Root "pyproject.toml") -Destination $app -Force
35
- Copy-Item -LiteralPath (Join-Path $Root "package.json") -Destination $app -Force
36
- Copy-Item -LiteralPath (Join-Path $Root "package-lock.json") -Destination $app -Force
37
-
38
- Copy-Item -LiteralPath (Join-Path $Root "installer\install-regen-mde.ps1") -Destination $stage -Force
39
-
40
- $readme = @"
41
- regen.mde for Windows
42
- =====================
43
-
44
- Install:
45
- Right-click install-regen-mde.ps1 and choose "Run with PowerShell"
46
-
47
- After install:
48
- Open the Windows Start menu and search for "regen.mde".
49
- Right-click .md or .docx files and choose "Open in regen.mde".
50
- Use "Uninstall regen.mde" from the Start menu to remove the app and shell verbs.
51
-
52
- Requirements:
53
- Windows with Microsoft Edge WebView2 runtime
54
- Node.js on PATH
55
- Python 3 on PATH with the Build Corpus Python requirements installed
56
-
57
- The installer copies the app to:
58
- %LOCALAPPDATA%\Programs\regen.mde
59
- "@
60
- Set-Content -LiteralPath (Join-Path $stage "README-INSTALL.txt") -Value $readme -Encoding UTF8
61
-
62
- Compress-Archive -Path (Join-Path $stage "*") -DestinationPath $zip -Force
63
-
64
- if (-not (Test-Path -LiteralPath $zip)) {
65
- throw "Package zip was not created: $zip"
66
- }
67
-
68
- $makensis = @(
69
- "C:\Program Files (x86)\NSIS\makensis.exe",
70
- "C:\Program Files (x86)\NSIS\Bin\makensis.exe"
71
- ) | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1
72
-
73
- if ($makensis) {
74
- & $makensis `
75
- "/DVERSION=$Version" `
76
- "/DAPP_SOURCE=$app" `
77
- "/DOUT_FILE=$setupExe" `
78
- (Join-Path $Root "installer\regen-mde.nsi")
79
- if ($LASTEXITCODE -ne 0) {
80
- throw "NSIS installer build failed with exit code $LASTEXITCODE"
81
- }
82
- if (-not (Test-Path -LiteralPath $setupExe)) {
83
- throw "Installer exe was not created: $setupExe"
84
- }
85
- Write-Host "Packaged $setupExe"
86
- } else {
87
- Write-Warning "NSIS makensis.exe was not found; skipped setup EXE package."
88
- }
89
-
90
- Write-Host "Packaged $zip"
1
+ [CmdletBinding()]
2
+ param(
3
+ [string]$Root = "",
4
+ [string]$Version = ""
5
+ )
6
+
7
+ $ErrorActionPreference = "Stop"
8
+
9
+ if ([string]::IsNullOrWhiteSpace($Root)) {
10
+ $Root = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
11
+ }
12
+
13
+ if ([string]::IsNullOrWhiteSpace($Version)) {
14
+ $pkg = Get-Content -Raw -LiteralPath (Join-Path $Root "package.json") | ConvertFrom-Json
15
+ $Version = $pkg.version
16
+ }
17
+
18
+ $releaseRoot = Join-Path $Root "dist\release"
19
+ $stage = Join-Path $releaseRoot "regen-mde-$Version-win-x64"
20
+ $app = Join-Path $stage "app"
21
+ $zip = Join-Path $releaseRoot "regen-mde-$Version-win-x64.zip"
22
+ $setupExe = Join-Path $releaseRoot "regen-mde-$Version-win-x64-setup.exe"
23
+
24
+ Remove-Item -LiteralPath $stage -Recurse -Force -ErrorAction SilentlyContinue
25
+ Remove-Item -LiteralPath $zip -Force -ErrorAction SilentlyContinue
26
+ Remove-Item -LiteralPath $setupExe -Force -ErrorAction SilentlyContinue
27
+ New-Item -ItemType Directory -Force -Path $app | Out-Null
28
+
29
+ Copy-Item -Path (Join-Path $Root "dist\windows-editor\*") -Destination $app -Recurse -Force
30
+ Remove-Item -LiteralPath (Join-Path $app "BuildCorpusEditor.exe.WebView2") -Recurse -Force -ErrorAction SilentlyContinue
31
+ Copy-Item -LiteralPath (Join-Path $Root "bin") -Destination $app -Recurse -Force
32
+ Copy-Item -LiteralPath (Join-Path $Root "src") -Destination $app -Recurse -Force
33
+ Copy-Item -LiteralPath (Join-Path $Root "requirements.txt") -Destination $app -Force
34
+ Copy-Item -LiteralPath (Join-Path $Root "pyproject.toml") -Destination $app -Force
35
+ Copy-Item -LiteralPath (Join-Path $Root "package.json") -Destination $app -Force
36
+ Copy-Item -LiteralPath (Join-Path $Root "package-lock.json") -Destination $app -Force
37
+
38
+ Copy-Item -LiteralPath (Join-Path $Root "installer\install-regen-mde.ps1") -Destination $stage -Force
39
+
40
+ $readme = @"
41
+ regen-mde for Windows
42
+ =====================
43
+
44
+ Install:
45
+ Right-click install-regen-mde.ps1 and choose "Run with PowerShell"
46
+
47
+ After install:
48
+ Open the Windows Start menu and search for "regen-mde".
49
+ Right-click .md or .docx files and choose "Open in regen-mde".
50
+ Use "Uninstall regen-mde" from the Start menu to remove the app and shell verbs.
51
+
52
+ Requirements:
53
+ Windows with Microsoft Edge WebView2 runtime
54
+ Node.js on PATH
55
+ Python 3 on PATH with the Build Corpus Python requirements installed
56
+
57
+ The installer copies the app to:
58
+ %LOCALAPPDATA%\Programs\regen-mde
59
+ "@
60
+ Set-Content -LiteralPath (Join-Path $stage "README-INSTALL.txt") -Value $readme -Encoding UTF8
61
+
62
+ Compress-Archive -Path (Join-Path $stage "*") -DestinationPath $zip -Force
63
+
64
+ if (-not (Test-Path -LiteralPath $zip)) {
65
+ throw "Package zip was not created: $zip"
66
+ }
67
+
68
+ $makensis = @(
69
+ "C:\Program Files (x86)\NSIS\makensis.exe",
70
+ "C:\Program Files (x86)\NSIS\Bin\makensis.exe"
71
+ ) | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1
72
+
73
+ if ($makensis) {
74
+ & $makensis `
75
+ "/DVERSION=$Version" `
76
+ "/DAPP_SOURCE=$app" `
77
+ "/DOUT_FILE=$setupExe" `
78
+ (Join-Path $Root "installer\regen-mde.nsi")
79
+ if ($LASTEXITCODE -ne 0) {
80
+ throw "NSIS installer build failed with exit code $LASTEXITCODE"
81
+ }
82
+ if (-not (Test-Path -LiteralPath $setupExe)) {
83
+ throw "Installer exe was not created: $setupExe"
84
+ }
85
+ Write-Host "Packaged $setupExe"
86
+ } else {
87
+ Write-Warning "NSIS makensis.exe was not found; skipped setup EXE package."
88
+ }
89
+
90
+ Write-Host "Packaged $zip"
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ // Dual-channel release for build-corpus: keep the npm package (package.json)
3
+ // and the PyPI package (pyproject.toml) on the SAME version, then optionally
4
+ // publish both and tag once.
5
+ //
6
+ // Usage:
7
+ // node scripts/release-dual.mjs <version|--patch|--minor|--major> [--publish] [--dry-run]
8
+ //
9
+ // node scripts/release-dual.mjs 0.3.1 # set both manifests to 0.3.1 (no publish)
10
+ // node scripts/release-dual.mjs --patch # bump patch in both
11
+ // node scripts/release-dual.mjs --minor --publish# bump, build, publish npm + PyPI, tag
12
+ // node scripts/release-dual.mjs --patch --dry-run# show what would change, touch nothing
13
+ //
14
+ // Publishing requires credentials in the environment / config:
15
+ // - npm: a logged-in npm (npm whoami) or NPM_TOKEN in ~/.npmrc
16
+ // - PyPI: TWINE_USERNAME=__token__ and TWINE_PASSWORD=<pypi-token>, or ~/.pypirc
17
+ // The script never reads secrets itself — it defers to npm/twine.
18
+
19
+ import { readFileSync, writeFileSync } from "node:fs";
20
+ import { spawnSync } from "node:child_process";
21
+ import { fileURLToPath } from "node:url";
22
+ import path from "node:path";
23
+
24
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
25
+ const pkgPath = path.join(root, "package.json");
26
+ const pyPath = path.join(root, "pyproject.toml");
27
+
28
+ const args = process.argv.slice(2);
29
+ const dryRun = args.includes("--dry-run");
30
+ const publish = args.includes("--publish");
31
+ const versionArg = args.find((a) => !a.startsWith("--"));
32
+ const bumpFlag = ["--patch", "--minor", "--major"].find((f) => args.includes(f));
33
+
34
+ function die(message) {
35
+ console.error(`release-dual: ${message}`);
36
+ process.exit(1);
37
+ }
38
+
39
+ function run(command, commandArgs, opts = {}) {
40
+ console.log(`$ ${command} ${commandArgs.join(" ")}`);
41
+ if (dryRun) return 0;
42
+ const result = spawnSync(command, commandArgs, { stdio: "inherit", cwd: root, shell: false, ...opts });
43
+ if (result.error) die(`${command} failed: ${result.error.message}`);
44
+ if ((result.status ?? 1) !== 0) die(`${command} exited ${result.status}`);
45
+ return 0;
46
+ }
47
+
48
+ function bumpSemver(current, kind) {
49
+ const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(current);
50
+ if (!match) die(`current version "${current}" is not plain semver`);
51
+ let [major, minor, patch] = match.slice(1).map(Number);
52
+ if (kind === "--major") { major += 1; minor = 0; patch = 0; }
53
+ else if (kind === "--minor") { minor += 1; patch = 0; }
54
+ else { patch += 1; }
55
+ return `${major}.${minor}.${patch}`;
56
+ }
57
+
58
+ // --- resolve target version ---
59
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
60
+ const currentVersion = pkg.version;
61
+
62
+ let nextVersion;
63
+ if (versionArg) {
64
+ if (!/^\d+\.\d+\.\d+$/.test(versionArg)) die(`"${versionArg}" is not a valid semver`);
65
+ nextVersion = versionArg;
66
+ } else if (bumpFlag) {
67
+ nextVersion = bumpSemver(currentVersion, bumpFlag);
68
+ } else {
69
+ die("provide a version (e.g. 0.3.1) or a bump flag (--patch/--minor/--major)");
70
+ }
71
+
72
+ console.log(`build-corpus: ${currentVersion} -> ${nextVersion}${dryRun ? " (dry-run)" : ""}`);
73
+
74
+ // --- write package.json ---
75
+ pkg.version = nextVersion;
76
+ if (!dryRun) writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
77
+ console.log(` package.json version = ${nextVersion}`);
78
+
79
+ // --- write pyproject.toml (only the [project] version line) ---
80
+ const pyText = readFileSync(pyPath, "utf8");
81
+ const pyNext = pyText.replace(/^(version\s*=\s*)"[^"]+"/m, `$1"${nextVersion}"`);
82
+ if (pyNext === pyText) die("could not find a version line in pyproject.toml");
83
+ if (!dryRun) writeFileSync(pyPath, pyNext);
84
+ console.log(` pyproject.toml version = ${nextVersion}`);
85
+
86
+ if (!publish) {
87
+ console.log("\nVersions synced. Re-run with --publish to build, publish, and tag.");
88
+ process.exit(0);
89
+ }
90
+
91
+ // --- publish PyPI: build sdist+wheel, upload with twine ---
92
+ console.log("\n== PyPI ==");
93
+ run("python3", ["-m", "build"]);
94
+ run("python3", ["-m", "twine", "upload", "dist/*.whl", "dist/*.tar.gz"]);
95
+
96
+ // --- publish npm ---
97
+ console.log("\n== npm ==");
98
+ run("npm", ["publish"]);
99
+
100
+ // --- tag once ---
101
+ console.log("\n== git ==");
102
+ run("git", ["add", "package.json", "pyproject.toml"]);
103
+ run("git", ["commit", "-m", `release: v${nextVersion} (npm + PyPI)`]);
104
+ run("git", ["tag", `v${nextVersion}`]);
105
+ console.log(`\nDone. Push with: git push && git push origin v${nextVersion}`);
@@ -1,28 +1,28 @@
1
- param(
2
- [Parameter(Mandatory=$true)]
3
- [string]$Source,
4
-
5
- [string]$Out = ".tmp\corpus",
6
-
7
- [ValidateSet("assets", "base64", "s3")]
8
- [string]$Images = "assets",
9
-
10
- [string]$Config = ""
11
- )
12
-
13
- $ErrorActionPreference = "Stop"
14
- $root = Split-Path -Parent $PSScriptRoot
15
- $buildCorpus = Join-Path $root "bin\build-corpus.js"
16
- $katex = Join-Path $root "bin\validate-katex.js"
17
- $assetValidator = Join-Path $root "src\build_corpus\validate_assets.py"
18
-
19
- $args = @($buildCorpus, $Source, "--out", $Out, "--images", $Images)
20
- if ($Config) {
21
- $args += @("--config", $Config)
22
- }
23
-
24
- node @args
25
- node $katex $Out | Set-Content -Path (Join-Path $Out "katex-report.json") -Encoding UTF8
26
- py -3 $assetValidator $Out | Set-Content -Path (Join-Path $Out "asset-report.json") -Encoding UTF8
27
-
28
- Write-Host "Corpus test passed: $Out"
1
+ param(
2
+ [Parameter(Mandatory=$true)]
3
+ [string]$Source,
4
+
5
+ [string]$Out = ".tmp\corpus",
6
+
7
+ [ValidateSet("assets", "base64", "s3")]
8
+ [string]$Images = "assets",
9
+
10
+ [string]$Config = ""
11
+ )
12
+
13
+ $ErrorActionPreference = "Stop"
14
+ $root = Split-Path -Parent $PSScriptRoot
15
+ $buildCorpus = Join-Path $root "bin\build-corpus.js"
16
+ $katex = Join-Path $root "bin\validate-katex.js"
17
+ $assetValidator = Join-Path $root "src\build_corpus\validate_assets.py"
18
+
19
+ $args = @($buildCorpus, $Source, "--out", $Out, "--images", $Images)
20
+ if ($Config) {
21
+ $args += @("--config", $Config)
22
+ }
23
+
24
+ node @args
25
+ node $katex $Out | Set-Content -Path (Join-Path $Out "katex-report.json") -Encoding UTF8
26
+ py -3 $assetValidator $Out | Set-Content -Path (Join-Path $Out "asset-report.json") -Encoding UTF8
27
+
28
+ Write-Host "Corpus test passed: $Out"