regen.mde 0.2.2 → 0.7.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 (37) hide show
  1. package/README.md +409 -295
  2. package/bin/build-corpus-editor.js +5 -3
  3. package/bin/postinstall.js +259 -187
  4. package/bin/regen-mdeditor-install.js +1 -1
  5. package/bin/regen-mdeditor-uninstall.js +1 -1
  6. package/desktop/BuildCorpusEditor/BuildCorpusBridge.cs +493 -270
  7. package/desktop/BuildCorpusEditor/EditorForm.cs +853 -540
  8. package/desktop/BuildCorpusEditor/Program.cs +85 -81
  9. package/dist/release/regen-mde-0.3.0-win-x64-setup.exe +0 -0
  10. package/dist/release/{regen.mde-0.2.2-win-x64.zip → regen-mde-0.3.0-win-x64.zip} +0 -0
  11. package/dist/release/regen-mde-0.7.0-win-x64-setup.exe +0 -0
  12. package/dist/release/regen-mde-0.7.0-win-x64.zip +0 -0
  13. package/dist/windows-editor/BuildCorpusEditor.dll +0 -0
  14. package/dist/windows-editor/BuildCorpusEditor.exe +0 -0
  15. package/dist/windows-editor/BuildCorpusEditor.pdb +0 -0
  16. package/dist/windows-editor/wwwroot/assets/index-C_VxJk4k.js +375 -0
  17. package/dist/windows-editor/wwwroot/assets/index-Wt9zSjIw.css +1 -0
  18. package/dist/windows-editor/wwwroot/index.html +3 -3
  19. package/editor-web/index.html +1 -1
  20. package/editor-web/src/main.jsx +1044 -399
  21. package/editor-web/src/styles.css +846 -602
  22. package/installer/install-regen-mde.ps1 +49 -10
  23. package/installer/regen-mde.nsi +16 -16
  24. package/package.json +90 -86
  25. package/pyproject.toml +35 -33
  26. package/requirements.txt +6 -4
  27. package/scripts/package-windows-editor.ps1 +8 -8
  28. package/scripts/release-dual.mjs +105 -0
  29. package/scripts/run-editor-implementation-plane.ps1 +29 -6
  30. package/src/build_corpus/docx_exporter.py +1055 -798
  31. package/src/build_corpus/equations.py +80 -0
  32. package/src/build_corpus/exporter.py +1488 -1195
  33. package/src/build_corpus/frontmatter.py +302 -0
  34. package/src/build_corpus/ppt_exporter.py +543 -532
  35. package/dist/release/regen.mde-0.2.2-win-x64-setup.exe +0 -0
  36. package/dist/windows-editor/wwwroot/assets/index-DjJ6xmhy.js +0 -326
  37. package/dist/windows-editor/wwwroot/assets/index-_dwMNNsm.css +0 -1
@@ -0,0 +1,80 @@
1
+ """LaTeX -> OMML (Office Math) conversion for Markdown -> Word export.
2
+
3
+ Word renders equations from OMML (`<m:oMath>`), not from raw text. The previous
4
+ exporter only set the font to "Cambria Math" and emitted the LaTeX source as
5
+ literal characters, so anything with real commands (\\sum, \\Delta, \\rightarrow,
6
+ \\leq) showed up as raw text. This module performs a genuine conversion:
7
+
8
+ LaTeX --(latex2mathml)--> presentation MathML --(mathml2omml)--> OMML
9
+
10
+ and returns a parsed `<m:oMath>` / `<m:oMathPara>` element ready to splice into a
11
+ python-docx paragraph. On any failure it returns ``None`` so callers can fall
12
+ back to plain text rather than crash.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from docx.oxml import parse_xml
18
+ from docx.oxml.ns import nsdecls
19
+
20
+ _MATH_NS = "http://schemas.openxmlformats.org/officeDocument/2006/math"
21
+
22
+
23
+ def _latex_to_omml_string(latex: str) -> str | None:
24
+ """Convert a LaTeX fragment to an OMML `<m:oMath>` XML string, or None."""
25
+ latex = latex.strip()
26
+ if not latex:
27
+ return None
28
+ try:
29
+ # Imported lazily so a missing optional dependency degrades to plain
30
+ # text instead of breaking the whole export.
31
+ import latex2mathml.converter as _l2m
32
+ from mathml2omml import convert as _mml2omml
33
+ except Exception:
34
+ return None
35
+ try:
36
+ mathml = _l2m.convert(latex)
37
+ omml = _mml2omml(mathml)
38
+ except Exception:
39
+ return None
40
+ if not omml or "oMath" not in omml:
41
+ return None
42
+ return omml
43
+
44
+
45
+ def _parse_with_namespaces(omml: str):
46
+ """Parse an OMML fragment, injecting the math/word namespace decls."""
47
+ decls = nsdecls("m", "w")
48
+ for tag in ("<m:oMath>", "<m:oMathPara>"):
49
+ if omml.startswith(tag):
50
+ opener = tag[:-1] + f" {decls}>"
51
+ omml = opener + omml[len(tag):]
52
+ break
53
+ else:
54
+ return None
55
+ try:
56
+ return parse_xml(omml)
57
+ except Exception:
58
+ return None
59
+
60
+
61
+ def latex_to_omath(latex: str):
62
+ """Return an inline `<m:oMath>` element for ``latex``, or None on failure."""
63
+ omml = _latex_to_omml_string(latex)
64
+ if omml is None:
65
+ return None
66
+ return _parse_with_namespaces(omml)
67
+
68
+
69
+ def latex_to_omath_para(latex: str):
70
+ """Return a display `<m:oMathPara>` element for ``latex``, or None.
71
+
72
+ Wraps the inline `<m:oMath>` in `<m:oMathPara>` so Word treats it as a
73
+ centered display equation on its own line.
74
+ """
75
+ omml = _latex_to_omml_string(latex)
76
+ if omml is None:
77
+ return None
78
+ if omml.startswith("<m:oMath>"):
79
+ omml = "<m:oMathPara>" + omml + "</m:oMathPara>"
80
+ return _parse_with_namespaces(omml)