regen.mde 0.8.1 → 0.8.2
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/LICENSE +16 -16
- package/bin/build-corpus-editor.js +83 -83
- package/bin/build-corpus.js +41 -41
- package/bin/regen-mdeditor-install.js +27 -27
- package/bin/regen-mdeditor-uninstall.js +19 -19
- package/bin/validate-katex.js +93 -93
- package/desktop/BuildCorpusEditor/BuildCorpusEditor.csproj +22 -22
- package/desktop/BuildCorpusEditor/EditorForm.cs +58 -58
- package/desktop/BuildCorpusEditor/app.manifest +16 -16
- package/dist/release/{regen-mde-0.8.0-win-x64.zip → regen-mde-0.6.1-win-x64.zip} +0 -0
- package/dist/release/{regen-mde-0.8.1-win-x64.zip → regen-mde-0.8.2-win-x64.zip} +0 -0
- package/dist/windows-editor/BuildCorpusEditor.dll +0 -0
- package/dist/windows-editor/BuildCorpusEditor.exe +0 -0
- package/dist/windows-editor/BuildCorpusEditor.pdb +0 -0
- package/dist/windows-editor/wwwroot/index.html +20 -20
- package/editor-web/index.html +21 -21
- package/editor-web/src/main.jsx +107 -107
- package/editor-web/src/styles.css +99 -99
- package/editor-web/vite.config.js +13 -13
- package/examples/build-corpus.config.example.json +21 -21
- package/installer/install-regen-mde.ps1 +214 -214
- package/installer/regen-mde.nsi +81 -81
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/scripts/build-windows-editor.ps1 +47 -47
- package/scripts/package-windows-editor.ps1 +90 -90
- package/scripts/run-corpus.ps1 +28 -28
- package/scripts/run-editor-implementation-plane.ps1 +226 -226
- package/scripts/run-required-tests.ps1 +98 -98
- package/scripts/run-smoke.ps1 +28 -28
- package/src/build_corpus/__init__.py +3 -3
- package/src/build_corpus/docx_exporter.py +10 -4
- package/src/build_corpus/equations.py +1345 -1345
- package/src/build_corpus/templates/__init__.py +1 -1
- package/src/build_corpus/validate_assets.py +46 -46
- package/tools/audit_corpus.py +203 -203
- package/tools/collect_microsoft_word_templates.py +228 -228
- package/tools/collect_online_docx_corpus.py +272 -272
- package/tools/collect_online_pptx_corpus.py +252 -252
- package/tools/compare_pptx_inputs_outputs.py +87 -87
- package/tools/roundtrip_docx_corpus.py +171 -171
|
@@ -634,69 +634,69 @@ console.log("style fixture");
|
|
|
634
634
|
await ClickButtonAsync("Run Check");
|
|
635
635
|
await WaitForBodyTextAsync("Checked ", "Run Check did not update status.");
|
|
636
636
|
|
|
637
|
-
await AssertControlStepAsync("layout still usable", """
|
|
638
|
-
(() => {
|
|
639
|
-
const modeStrip = document.querySelector(".mode-strip");
|
|
640
|
-
if (!modeStrip) throw new Error("Mode strip missing.");
|
|
637
|
+
await AssertControlStepAsync("layout still usable", """
|
|
638
|
+
(() => {
|
|
639
|
+
const modeStrip = document.querySelector(".mode-strip");
|
|
640
|
+
if (!modeStrip) throw new Error("Mode strip missing.");
|
|
641
641
|
const canvas = document.querySelector(".canvas-wrap");
|
|
642
642
|
if (!canvas || canvas.getBoundingClientRect().width < 300) {
|
|
643
643
|
throw new Error("Editor canvas did not render with usable width.");
|
|
644
644
|
}
|
|
645
645
|
return [...document.querySelectorAll(".statusbar span")].map((node) => node.textContent).join(" | ");
|
|
646
|
-
})()
|
|
647
|
-
""");
|
|
648
|
-
|
|
649
|
-
await AssertControlStepAsync("side panels collapse clicks", """
|
|
650
|
-
(() => {
|
|
651
|
-
const canvas = document.querySelector(".canvas-wrap");
|
|
652
|
-
const left = document.querySelector(".left-panel");
|
|
653
|
-
const right = document.querySelector(".right-panel");
|
|
654
|
-
if (!canvas || !left || !right) throw new Error("Panel collapse elements missing.");
|
|
655
|
-
const before = canvas.getBoundingClientRect().width;
|
|
656
|
-
document.querySelector('button[aria-label="Collapse Document Flow panel"]')?.click();
|
|
657
|
-
document.querySelector('button[aria-label="Collapse Output Health panel"]')?.click();
|
|
658
|
-
window.__REGEN_PANEL_BEFORE = before;
|
|
659
|
-
return `collapse clicks scheduled from ${before}`;
|
|
660
|
-
})()
|
|
661
|
-
""");
|
|
662
|
-
await Task.Delay(250);
|
|
663
|
-
await AssertControlStepAsync("side panels collapse without focus", """
|
|
664
|
-
(() => {
|
|
665
|
-
const shell = document.querySelector(".app-shell");
|
|
666
|
-
const canvas = document.querySelector(".canvas-wrap");
|
|
667
|
-
const left = document.querySelector(".left-panel");
|
|
668
|
-
const right = document.querySelector(".right-panel");
|
|
669
|
-
if (!shell || !canvas || !left || !right) throw new Error("Panel collapse elements missing.");
|
|
670
|
-
const before = Number(window.__REGEN_PANEL_BEFORE || 0);
|
|
671
|
-
if (!shell.classList.contains("left-collapsed") || !shell.classList.contains("right-collapsed")) {
|
|
672
|
-
throw new Error("Panel collapse classes were not applied.");
|
|
673
|
-
}
|
|
674
|
-
if (!left.classList.contains("collapsed") || !right.classList.contains("collapsed")) {
|
|
675
|
-
throw new Error("Panel elements were not marked collapsed.");
|
|
676
|
-
}
|
|
677
|
-
const after = canvas.getBoundingClientRect().width;
|
|
678
|
-
if (after <= before + 120) throw new Error(`Editor canvas did not reclaim enough width: ${before} -> ${after}`);
|
|
679
|
-
document.querySelector('button[aria-label="Expand Document Flow panel"]')?.click();
|
|
680
|
-
document.querySelector('button[aria-label="Expand Output Health panel"]')?.click();
|
|
681
|
-
window.__REGEN_PANEL_AFTER = after;
|
|
682
|
-
return `panels collapsed: ${before} -> ${after}`;
|
|
683
|
-
})()
|
|
684
|
-
""");
|
|
685
|
-
await Task.Delay(250);
|
|
686
|
-
await AssertControlStepAsync("side panels expand without focus", """
|
|
687
|
-
(() => {
|
|
688
|
-
const shell = document.querySelector(".app-shell");
|
|
689
|
-
if (!shell) throw new Error("Panel collapse shell missing.");
|
|
690
|
-
if (shell.classList.contains("left-collapsed") || shell.classList.contains("right-collapsed")) {
|
|
691
|
-
throw new Error("Panel expand did not restore the app shell.");
|
|
692
|
-
}
|
|
693
|
-
return `panels expanded after ${window.__REGEN_PANEL_AFTER}`;
|
|
694
|
-
})()
|
|
695
|
-
""");
|
|
696
|
-
|
|
697
|
-
if (!File.Exists(markdownOutput) || !File.ReadAllText(markdownOutput).Contains("UI save-as edit marker", StringComparison.Ordinal))
|
|
698
|
-
{
|
|
699
|
-
throw new InvalidOperationException("Save MD As did not write the smoke Markdown output.");
|
|
646
|
+
})()
|
|
647
|
+
""");
|
|
648
|
+
|
|
649
|
+
await AssertControlStepAsync("side panels collapse clicks", """
|
|
650
|
+
(() => {
|
|
651
|
+
const canvas = document.querySelector(".canvas-wrap");
|
|
652
|
+
const left = document.querySelector(".left-panel");
|
|
653
|
+
const right = document.querySelector(".right-panel");
|
|
654
|
+
if (!canvas || !left || !right) throw new Error("Panel collapse elements missing.");
|
|
655
|
+
const before = canvas.getBoundingClientRect().width;
|
|
656
|
+
document.querySelector('button[aria-label="Collapse Document Flow panel"]')?.click();
|
|
657
|
+
document.querySelector('button[aria-label="Collapse Output Health panel"]')?.click();
|
|
658
|
+
window.__REGEN_PANEL_BEFORE = before;
|
|
659
|
+
return `collapse clicks scheduled from ${before}`;
|
|
660
|
+
})()
|
|
661
|
+
""");
|
|
662
|
+
await Task.Delay(250);
|
|
663
|
+
await AssertControlStepAsync("side panels collapse without focus", """
|
|
664
|
+
(() => {
|
|
665
|
+
const shell = document.querySelector(".app-shell");
|
|
666
|
+
const canvas = document.querySelector(".canvas-wrap");
|
|
667
|
+
const left = document.querySelector(".left-panel");
|
|
668
|
+
const right = document.querySelector(".right-panel");
|
|
669
|
+
if (!shell || !canvas || !left || !right) throw new Error("Panel collapse elements missing.");
|
|
670
|
+
const before = Number(window.__REGEN_PANEL_BEFORE || 0);
|
|
671
|
+
if (!shell.classList.contains("left-collapsed") || !shell.classList.contains("right-collapsed")) {
|
|
672
|
+
throw new Error("Panel collapse classes were not applied.");
|
|
673
|
+
}
|
|
674
|
+
if (!left.classList.contains("collapsed") || !right.classList.contains("collapsed")) {
|
|
675
|
+
throw new Error("Panel elements were not marked collapsed.");
|
|
676
|
+
}
|
|
677
|
+
const after = canvas.getBoundingClientRect().width;
|
|
678
|
+
if (after <= before + 120) throw new Error(`Editor canvas did not reclaim enough width: ${before} -> ${after}`);
|
|
679
|
+
document.querySelector('button[aria-label="Expand Document Flow panel"]')?.click();
|
|
680
|
+
document.querySelector('button[aria-label="Expand Output Health panel"]')?.click();
|
|
681
|
+
window.__REGEN_PANEL_AFTER = after;
|
|
682
|
+
return `panels collapsed: ${before} -> ${after}`;
|
|
683
|
+
})()
|
|
684
|
+
""");
|
|
685
|
+
await Task.Delay(250);
|
|
686
|
+
await AssertControlStepAsync("side panels expand without focus", """
|
|
687
|
+
(() => {
|
|
688
|
+
const shell = document.querySelector(".app-shell");
|
|
689
|
+
if (!shell) throw new Error("Panel collapse shell missing.");
|
|
690
|
+
if (shell.classList.contains("left-collapsed") || shell.classList.contains("right-collapsed")) {
|
|
691
|
+
throw new Error("Panel expand did not restore the app shell.");
|
|
692
|
+
}
|
|
693
|
+
return `panels expanded after ${window.__REGEN_PANEL_AFTER}`;
|
|
694
|
+
})()
|
|
695
|
+
""");
|
|
696
|
+
|
|
697
|
+
if (!File.Exists(markdownOutput) || !File.ReadAllText(markdownOutput).Contains("UI save-as edit marker", StringComparison.Ordinal))
|
|
698
|
+
{
|
|
699
|
+
throw new InvalidOperationException("Save MD As did not write the smoke Markdown output.");
|
|
700
700
|
}
|
|
701
701
|
if (!largeSmokeDocument && (!File.Exists(wordOutput) || new FileInfo(wordOutput).Length == 0))
|
|
702
702
|
{
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
3
|
-
<assemblyIdentity version="1.0.0.0" name="LifeAI.BuildCorpusEditor.app"/>
|
|
4
|
-
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
|
5
|
-
<security>
|
|
6
|
-
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
7
|
-
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
|
8
|
-
</requestedPrivileges>
|
|
9
|
-
</security>
|
|
10
|
-
</trustInfo>
|
|
11
|
-
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
|
12
|
-
<application>
|
|
13
|
-
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
|
14
|
-
</application>
|
|
15
|
-
</compatibility>
|
|
16
|
-
</assembly>
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
3
|
+
<assemblyIdentity version="1.0.0.0" name="LifeAI.BuildCorpusEditor.app"/>
|
|
4
|
+
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
|
5
|
+
<security>
|
|
6
|
+
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
7
|
+
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
|
8
|
+
</requestedPrivileges>
|
|
9
|
+
</security>
|
|
10
|
+
</trustInfo>
|
|
11
|
+
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
|
12
|
+
<application>
|
|
13
|
+
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
|
14
|
+
</application>
|
|
15
|
+
</compatibility>
|
|
16
|
+
</assembly>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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-BB0sbZaD.js"></script>
|
|
17
17
|
<link rel="stylesheet" crossorigin href="./assets/index-CtOv7qsC.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>
|
package/editor-web/index.html
CHANGED
|
@@ -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>
|
package/editor-web/src/main.jsx
CHANGED
|
@@ -163,9 +163,9 @@ function App() {
|
|
|
163
163
|
});
|
|
164
164
|
const [dirty, setDirty] = React.useState(false);
|
|
165
165
|
const [largeFile, setLargeFile] = React.useState(false);
|
|
166
|
-
const [moveSources, setMoveSources] = React.useState(false);
|
|
167
|
-
const [leftPanelCollapsed, setLeftPanelCollapsed] = React.useState(() => window.localStorage?.getItem("build-corpus-editor-left-panel") === "collapsed");
|
|
168
|
-
const [rightPanelCollapsed, setRightPanelCollapsed] = React.useState(() => window.localStorage?.getItem("build-corpus-editor-right-panel") === "collapsed");
|
|
166
|
+
const [moveSources, setMoveSources] = React.useState(false);
|
|
167
|
+
const [leftPanelCollapsed, setLeftPanelCollapsed] = React.useState(() => window.localStorage?.getItem("build-corpus-editor-left-panel") === "collapsed");
|
|
168
|
+
const [rightPanelCollapsed, setRightPanelCollapsed] = React.useState(() => window.localStorage?.getItem("build-corpus-editor-right-panel") === "collapsed");
|
|
169
169
|
const sourceViewRef = React.useRef(null);
|
|
170
170
|
const pageAreaRef = React.useRef(null);
|
|
171
171
|
const scrollSyncRef = React.useRef(false);
|
|
@@ -223,17 +223,17 @@ function App() {
|
|
|
223
223
|
if (editor && !dirty && markdown.length <= RICH_EDITOR_LIMIT) editor.commands.setContent(markdownToHtml(markdown));
|
|
224
224
|
}, [editor, markdown, dirty]);
|
|
225
225
|
|
|
226
|
-
React.useEffect(() => {
|
|
227
|
-
window.localStorage?.setItem("build-corpus-editor-theme", theme);
|
|
228
|
-
}, [theme]);
|
|
229
|
-
|
|
230
|
-
React.useEffect(() => {
|
|
231
|
-
window.localStorage?.setItem("build-corpus-editor-left-panel", leftPanelCollapsed ? "collapsed" : "open");
|
|
232
|
-
}, [leftPanelCollapsed]);
|
|
233
|
-
|
|
234
|
-
React.useEffect(() => {
|
|
235
|
-
window.localStorage?.setItem("build-corpus-editor-right-panel", rightPanelCollapsed ? "collapsed" : "open");
|
|
236
|
-
}, [rightPanelCollapsed]);
|
|
226
|
+
React.useEffect(() => {
|
|
227
|
+
window.localStorage?.setItem("build-corpus-editor-theme", theme);
|
|
228
|
+
}, [theme]);
|
|
229
|
+
|
|
230
|
+
React.useEffect(() => {
|
|
231
|
+
window.localStorage?.setItem("build-corpus-editor-left-panel", leftPanelCollapsed ? "collapsed" : "open");
|
|
232
|
+
}, [leftPanelCollapsed]);
|
|
233
|
+
|
|
234
|
+
React.useEffect(() => {
|
|
235
|
+
window.localStorage?.setItem("build-corpus-editor-right-panel", rightPanelCollapsed ? "collapsed" : "open");
|
|
236
|
+
}, [rightPanelCollapsed]);
|
|
237
237
|
|
|
238
238
|
async function chooseOpen() {
|
|
239
239
|
try {
|
|
@@ -537,7 +537,7 @@ function App() {
|
|
|
537
537
|
const codeMirrorTheme = "light";
|
|
538
538
|
|
|
539
539
|
return (
|
|
540
|
-
<main className={`app-shell${leftPanelCollapsed ? " left-collapsed" : ""}${rightPanelCollapsed ? " right-collapsed" : ""}`} data-theme={theme}>
|
|
540
|
+
<main className={`app-shell${leftPanelCollapsed ? " left-collapsed" : ""}${rightPanelCollapsed ? " right-collapsed" : ""}`} data-theme={theme}>
|
|
541
541
|
<aside className="brand-rail" aria-label="Primary tools">
|
|
542
542
|
<div className="mark">BC</div>
|
|
543
543
|
<div className="rail-item active">Ed</div>
|
|
@@ -566,53 +566,53 @@ function App() {
|
|
|
566
566
|
</div>
|
|
567
567
|
</header>
|
|
568
568
|
|
|
569
|
-
<section className={`side-panel left-panel${leftPanelCollapsed ? " collapsed" : ""}`}>
|
|
570
|
-
<div className="panel-chrome">
|
|
571
|
-
<button
|
|
572
|
-
type="button"
|
|
573
|
-
className="panel-toggle"
|
|
574
|
-
aria-label={leftPanelCollapsed ? "Expand Document Flow panel" : "Collapse Document Flow panel"}
|
|
575
|
-
aria-expanded={!leftPanelCollapsed}
|
|
576
|
-
onClick={() => setLeftPanelCollapsed((collapsed) => !collapsed)}
|
|
577
|
-
title={leftPanelCollapsed ? "Expand Document Flow" : "Collapse Document Flow"}
|
|
578
|
-
>
|
|
579
|
-
<span aria-hidden="true">≡</span>
|
|
580
|
-
</button>
|
|
581
|
-
<h2 className="panel-title">Document Flow</h2>
|
|
582
|
-
</div>
|
|
583
|
-
<div className="panel-body">
|
|
584
|
-
<div className="source-card">
|
|
585
|
-
<strong>{sourceText}</strong>
|
|
586
|
-
<p>{dirty ? "The Markdown draft has unsaved changes." : "The Markdown draft is in sync with its save target."}</p>
|
|
587
|
-
<label className="batch-option"><input type="checkbox" checked={moveSources} onChange={(event) => setMoveSources(event.target.checked)} /> Move processed files to sources</label>
|
|
588
|
-
</div>
|
|
589
|
-
<div className="format-flow">
|
|
590
|
-
<div className="flow-step">
|
|
591
|
-
<div className="badge">{sourceBadge}</div>
|
|
592
|
-
<div><b>Original</b><small>{sourcePath || "Choose a file to begin"}</small></div>
|
|
593
|
-
<small>{sourcePath ? "loaded" : "empty"}</small>
|
|
594
|
-
</div>
|
|
595
|
-
<div className="flow-step">
|
|
596
|
-
<div className="badge">MD</div>
|
|
597
|
-
<div><b>Working draft</b><small>{draftText}</small></div>
|
|
598
|
-
<small>{dirty ? "dirty" : "saved"}</small>
|
|
599
|
-
</div>
|
|
600
|
-
<div className="flow-step">
|
|
601
|
-
<div className="badge">DOCX</div>
|
|
602
|
-
<div><b>Word export</b><small>{exportText}</small></div>
|
|
603
|
-
<small>{exportPath ? "done" : "ready"}</small>
|
|
604
|
-
</div>
|
|
605
|
-
</div>
|
|
606
|
-
|
|
607
|
-
<h2 className="panel-title">Insert</h2>
|
|
608
|
-
<div className="insert-grid">
|
|
609
|
-
<button className="insert-tile" disabled={!canUseRich} onClick={() => editor?.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}><b>Table</b>Rows, columns, headers</button>
|
|
610
|
-
<button className="insert-tile" disabled={!canUseRich} onClick={insertImageFile}><b>Image</b>File with alt text</button>
|
|
611
|
-
<button className="insert-tile" disabled={!canUseRich} onClick={() => editor?.chain().focus().toggleBlockquote().run()}><b>Callout</b>Note or quotation</button>
|
|
612
|
-
<button className="insert-tile" disabled={!canUseRich} onClick={() => editor?.chain().focus().toggleTaskList().run()}><b>Task</b>Checklist block</button>
|
|
613
|
-
</div>
|
|
614
|
-
</div>
|
|
615
|
-
</section>
|
|
569
|
+
<section className={`side-panel left-panel${leftPanelCollapsed ? " collapsed" : ""}`}>
|
|
570
|
+
<div className="panel-chrome">
|
|
571
|
+
<button
|
|
572
|
+
type="button"
|
|
573
|
+
className="panel-toggle"
|
|
574
|
+
aria-label={leftPanelCollapsed ? "Expand Document Flow panel" : "Collapse Document Flow panel"}
|
|
575
|
+
aria-expanded={!leftPanelCollapsed}
|
|
576
|
+
onClick={() => setLeftPanelCollapsed((collapsed) => !collapsed)}
|
|
577
|
+
title={leftPanelCollapsed ? "Expand Document Flow" : "Collapse Document Flow"}
|
|
578
|
+
>
|
|
579
|
+
<span aria-hidden="true">≡</span>
|
|
580
|
+
</button>
|
|
581
|
+
<h2 className="panel-title">Document Flow</h2>
|
|
582
|
+
</div>
|
|
583
|
+
<div className="panel-body">
|
|
584
|
+
<div className="source-card">
|
|
585
|
+
<strong>{sourceText}</strong>
|
|
586
|
+
<p>{dirty ? "The Markdown draft has unsaved changes." : "The Markdown draft is in sync with its save target."}</p>
|
|
587
|
+
<label className="batch-option"><input type="checkbox" checked={moveSources} onChange={(event) => setMoveSources(event.target.checked)} /> Move processed files to sources</label>
|
|
588
|
+
</div>
|
|
589
|
+
<div className="format-flow">
|
|
590
|
+
<div className="flow-step">
|
|
591
|
+
<div className="badge">{sourceBadge}</div>
|
|
592
|
+
<div><b>Original</b><small>{sourcePath || "Choose a file to begin"}</small></div>
|
|
593
|
+
<small>{sourcePath ? "loaded" : "empty"}</small>
|
|
594
|
+
</div>
|
|
595
|
+
<div className="flow-step">
|
|
596
|
+
<div className="badge">MD</div>
|
|
597
|
+
<div><b>Working draft</b><small>{draftText}</small></div>
|
|
598
|
+
<small>{dirty ? "dirty" : "saved"}</small>
|
|
599
|
+
</div>
|
|
600
|
+
<div className="flow-step">
|
|
601
|
+
<div className="badge">DOCX</div>
|
|
602
|
+
<div><b>Word export</b><small>{exportText}</small></div>
|
|
603
|
+
<small>{exportPath ? "done" : "ready"}</small>
|
|
604
|
+
</div>
|
|
605
|
+
</div>
|
|
606
|
+
|
|
607
|
+
<h2 className="panel-title">Insert</h2>
|
|
608
|
+
<div className="insert-grid">
|
|
609
|
+
<button className="insert-tile" disabled={!canUseRich} onClick={() => editor?.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}><b>Table</b>Rows, columns, headers</button>
|
|
610
|
+
<button className="insert-tile" disabled={!canUseRich} onClick={insertImageFile}><b>Image</b>File with alt text</button>
|
|
611
|
+
<button className="insert-tile" disabled={!canUseRich} onClick={() => editor?.chain().focus().toggleBlockquote().run()}><b>Callout</b>Note or quotation</button>
|
|
612
|
+
<button className="insert-tile" disabled={!canUseRich} onClick={() => editor?.chain().focus().toggleTaskList().run()}><b>Task</b>Checklist block</button>
|
|
613
|
+
</div>
|
|
614
|
+
</div>
|
|
615
|
+
</section>
|
|
616
616
|
|
|
617
617
|
<section className={`workspace ${mode} ${largeFile ? "large" : ""}`}>
|
|
618
618
|
<div className="mode-strip">
|
|
@@ -700,51 +700,51 @@ function App() {
|
|
|
700
700
|
</div>
|
|
701
701
|
</section>
|
|
702
702
|
|
|
703
|
-
<aside className={`side-panel right-panel${rightPanelCollapsed ? " collapsed" : ""}`}>
|
|
704
|
-
<div className="panel-chrome">
|
|
705
|
-
<h2 className="panel-title">Output Health</h2>
|
|
706
|
-
<button
|
|
707
|
-
type="button"
|
|
708
|
-
className="panel-toggle"
|
|
709
|
-
aria-label={rightPanelCollapsed ? "Expand Output Health panel" : "Collapse Output Health panel"}
|
|
710
|
-
aria-expanded={!rightPanelCollapsed}
|
|
711
|
-
onClick={() => setRightPanelCollapsed((collapsed) => !collapsed)}
|
|
712
|
-
title={rightPanelCollapsed ? "Expand Output Health" : "Collapse Output Health"}
|
|
713
|
-
>
|
|
714
|
-
<span aria-hidden="true">≡</span>
|
|
715
|
-
</button>
|
|
716
|
-
</div>
|
|
717
|
-
<div className="panel-body">
|
|
718
|
-
<div className="source-card">
|
|
719
|
-
<strong>Round-trip confidence</strong>
|
|
720
|
-
<p>Tables, images, links, and headings are tracked as conversion risks.</p>
|
|
721
|
-
<div className="meter" aria-label="Round-trip confidence"><span style={{ width: `${confidence}%` }} /></div>
|
|
722
|
-
</div>
|
|
723
|
-
|
|
724
|
-
<h2 className="panel-title">Table Tools</h2>
|
|
725
|
-
<div className="tool-group">
|
|
726
|
-
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().addRowAfter().run()}>Row +</button>
|
|
727
|
-
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().addColumnAfter().run()}>Col +</button>
|
|
728
|
-
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().deleteRow().run()}>Row -</button>
|
|
729
|
-
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().deleteColumn().run()}>Col -</button>
|
|
730
|
-
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().toggleHeaderRow().run()}>Header</button>
|
|
731
|
-
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().deleteTable().run()}>Delete</button>
|
|
732
|
-
</div>
|
|
733
|
-
|
|
734
|
-
<h2 className="panel-title">Image Tools</h2>
|
|
735
|
-
<div className="tool-group">
|
|
736
|
-
<button disabled={!canUseRich} onClick={insertImageFile}>File</button>
|
|
737
|
-
<button disabled={!canUseRich} onClick={insertImageUrl}>URL</button>
|
|
738
|
-
</div>
|
|
739
|
-
|
|
740
|
-
<div className="checklist">
|
|
741
|
-
<div className="check"><span className="dot" /><div><b>Markdown target</b><br />{markdownPath || "Choose Save MD As..."}</div></div>
|
|
742
|
-
<div className="check"><span className="dot" /><div><b>Word export</b><br />{exportPath || "Ready to export with template hook."}</div></div>
|
|
743
|
-
<div className="check"><span className={imageCount ? "dot warn" : "dot"} /><div><b>Images</b><br />{imageCount} detected. Asset folder policy still needs final pass.</div></div>
|
|
744
|
-
<div className="check"><span className={tableCount ? "dot warn" : "dot"} /><div><b>Tables</b><br />{tableCount} detected. Advanced cell controls are surfaced here.</div></div>
|
|
745
|
-
</div>
|
|
746
|
-
</div>
|
|
747
|
-
</aside>
|
|
703
|
+
<aside className={`side-panel right-panel${rightPanelCollapsed ? " collapsed" : ""}`}>
|
|
704
|
+
<div className="panel-chrome">
|
|
705
|
+
<h2 className="panel-title">Output Health</h2>
|
|
706
|
+
<button
|
|
707
|
+
type="button"
|
|
708
|
+
className="panel-toggle"
|
|
709
|
+
aria-label={rightPanelCollapsed ? "Expand Output Health panel" : "Collapse Output Health panel"}
|
|
710
|
+
aria-expanded={!rightPanelCollapsed}
|
|
711
|
+
onClick={() => setRightPanelCollapsed((collapsed) => !collapsed)}
|
|
712
|
+
title={rightPanelCollapsed ? "Expand Output Health" : "Collapse Output Health"}
|
|
713
|
+
>
|
|
714
|
+
<span aria-hidden="true">≡</span>
|
|
715
|
+
</button>
|
|
716
|
+
</div>
|
|
717
|
+
<div className="panel-body">
|
|
718
|
+
<div className="source-card">
|
|
719
|
+
<strong>Round-trip confidence</strong>
|
|
720
|
+
<p>Tables, images, links, and headings are tracked as conversion risks.</p>
|
|
721
|
+
<div className="meter" aria-label="Round-trip confidence"><span style={{ width: `${confidence}%` }} /></div>
|
|
722
|
+
</div>
|
|
723
|
+
|
|
724
|
+
<h2 className="panel-title">Table Tools</h2>
|
|
725
|
+
<div className="tool-group">
|
|
726
|
+
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().addRowAfter().run()}>Row +</button>
|
|
727
|
+
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().addColumnAfter().run()}>Col +</button>
|
|
728
|
+
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().deleteRow().run()}>Row -</button>
|
|
729
|
+
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().deleteColumn().run()}>Col -</button>
|
|
730
|
+
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().toggleHeaderRow().run()}>Header</button>
|
|
731
|
+
<button disabled={!canUseRich || !editor?.isActive("table")} onClick={() => editor?.chain().focus().deleteTable().run()}>Delete</button>
|
|
732
|
+
</div>
|
|
733
|
+
|
|
734
|
+
<h2 className="panel-title">Image Tools</h2>
|
|
735
|
+
<div className="tool-group">
|
|
736
|
+
<button disabled={!canUseRich} onClick={insertImageFile}>File</button>
|
|
737
|
+
<button disabled={!canUseRich} onClick={insertImageUrl}>URL</button>
|
|
738
|
+
</div>
|
|
739
|
+
|
|
740
|
+
<div className="checklist">
|
|
741
|
+
<div className="check"><span className="dot" /><div><b>Markdown target</b><br />{markdownPath || "Choose Save MD As..."}</div></div>
|
|
742
|
+
<div className="check"><span className="dot" /><div><b>Word export</b><br />{exportPath || "Ready to export with template hook."}</div></div>
|
|
743
|
+
<div className="check"><span className={imageCount ? "dot warn" : "dot"} /><div><b>Images</b><br />{imageCount} detected. Asset folder policy still needs final pass.</div></div>
|
|
744
|
+
<div className="check"><span className={tableCount ? "dot warn" : "dot"} /><div><b>Tables</b><br />{tableCount} detected. Advanced cell controls are surfaced here.</div></div>
|
|
745
|
+
</div>
|
|
746
|
+
</div>
|
|
747
|
+
</aside>
|
|
748
748
|
|
|
749
749
|
<footer className="statusbar">
|
|
750
750
|
<span>{status}{exportPath ? ` - Last Word export: ${exportPath}` : ""}</span>
|