regen.mde 0.8.0 → 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/README.md +2 -1
- 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 +48 -0
- 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.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/assets/{index-C_VxJk4k.js → index-BB0sbZaD.js} +107 -107
- package/dist/windows-editor/wwwroot/assets/index-CtOv7qsC.css +1 -0
- package/dist/windows-editor/wwwroot/index.html +22 -22
- package/editor-web/index.html +21 -21
- package/editor-web/src/main.jsx +91 -53
- package/editor-web/src/styles.css +65 -1
- 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
- package/dist/windows-editor/wwwroot/assets/index-Wt9zSjIw.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{color-scheme:light;font-family:Segoe UI,Inter,system-ui,sans-serif;background:#fbf8f0;color:#192028;--ink: oklch(24% .018 250);--muted: oklch(47% .022 250);--paper: oklch(98% .011 92);--panel: oklch(95% .014 92);--line: oklch(82% .018 92);--soft: oklch(91% .022 92);--accent: oklch(56% .135 176);--accent-dark: oklch(36% .09 176);--warning: oklch(52% .12 23);--violet: oklch(60% .11 284);--source: oklch(99% .005 92);--source-ink: oklch(27% .018 250);--shadow: 0 24px 70px rgba(34, 38, 46, .18);--button-bg: oklch(99% .006 92);--button-hover: oklch(94% .034 176);--topbar-bg: rgba(252, 249, 240, .94);--panel-bg: rgba(248, 245, 236, .96);--card-bg: oklch(99% .006 92);--page-bg: oklch(99% .005 92);--page-ink: oklch(27% .018 250);--rail-bg: oklch(28% .026 250);--rail-item-bg: oklch(37% .04 250);--grid-line-strong: rgba(41, 143, 132, .08);--grid-line-soft: rgba(41, 143, 132, .05);--warning-bg: oklch(93% .044 72);--warning-border: oklch(74% .075 72);--warning-ink: oklch(35% .075 72);--bubble-bg: oklch(24% .022 250);--bubble-line: oklch(35% .025 250);--bubble-ink: oklch(94% .01 92);--table-head: oklch(92% .025 92)}[data-theme=dark]{color-scheme:dark;--ink: oklch(91% .014 250);--muted: oklch(68% .018 250);--paper: oklch(20% .018 250);--panel: oklch(26% .018 250);--line: oklch(38% .022 250);--soft: oklch(16% .018 250);--accent: oklch(65% .13 176);--accent-dark: oklch(88% .058 176);--warning: oklch(71% .14 68);--violet: oklch(71% .1 284);--source: oklch(96% .008 92);--source-ink: oklch(25% .018 250);--shadow: 0 24px 80px rgba(0, 0, 0, .46);--button-bg: oklch(27% .018 250);--button-hover: oklch(32% .038 176);--topbar-bg: rgba(25, 29, 36, .96);--panel-bg: rgba(29, 33, 40, .96);--card-bg: oklch(24% .018 250);--page-bg: oklch(96% .008 92);--page-ink: oklch(25% .018 250);--rail-bg: oklch(13% .02 250);--rail-item-bg: oklch(24% .03 250);--grid-line-strong: rgba(86, 205, 190, .08);--grid-line-soft: rgba(86, 205, 190, .045);--warning-bg: oklch(25% .044 68);--warning-border: oklch(48% .11 68);--warning-ink: oklch(84% .09 68);--bubble-bg: oklch(91% .012 92);--bubble-line: oklch(72% .02 92);--bubble-ink: oklch(20% .022 250);--table-head: oklch(90% .018 92)}*{box-sizing:border-box}body{margin:0;min-width:920px}button{min-height:28px;border:1px solid var(--line);border-radius:5px;padding:4px 9px;background:var(--button-bg);color:var(--ink);font:600 12px/1 Segoe UI,system-ui,sans-serif;letter-spacing:0;cursor:pointer}button:hover:not(:disabled),button.active{border-color:var(--accent);background:var(--button-hover);color:var(--accent-dark)}button:disabled{cursor:default;opacity:.42}button.primary{background:var(--accent);border-color:#006453;border-color:oklch(45% .11 176);color:#f2fbf8}button.ghost{background:transparent}main.app-shell{width:100vw;height:100vh;min-height:720px;display:grid;grid-template-columns:58px 260px minmax(560px,1fr) 320px;grid-template-rows:48px 1fr 30px;overflow:hidden;background:linear-gradient(90deg,var(--grid-line-strong) 0 1px,transparent 1px 72px),linear-gradient(var(--grid-line-soft) 0 1px,transparent 1px 72px),var(--paper)}main.app-shell.left-collapsed{grid-template-columns:58px 44px minmax(560px,1fr) 320px}main.app-shell.right-collapsed{grid-template-columns:58px 260px minmax(560px,1fr) 44px}main.app-shell.left-collapsed.right-collapsed{grid-template-columns:58px 44px minmax(560px,1fr) 44px}.brand-rail{grid-row:1 / 4;border-right:1px solid var(--line);background:var(--rail-bg);color:#e7e4dc;display:grid;grid-template-rows:64px repeat(5,42px) 1fr 42px;place-items:center}.mark{width:32px;height:32px;border-radius:8px;display:grid;place-items:center;background:var(--accent);color:#f2fbf8;font-weight:800}.rail-item{width:34px;height:34px;border-radius:7px;display:grid;place-items:center;color:#c7c4bc;font-size:12px;font-weight:700}.rail-item.active{background:var(--rail-item-bg);color:#fbf8f1}.topbar{grid-column:2 / 5;border-bottom:1px solid var(--line);background:var(--topbar-bg);display:flex;align-items:center;justify-content:space-between;gap:16px;padding:0 14px}.file-title{min-width:0;display:flex;align-items:baseline;gap:10px}.file-title strong{font-size:15px}.file-title span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted);font:12px/1.2 Consolas,Cascadia Mono,monospace}.actions{display:flex;align-items:center;gap:6px}.side-panel{border-color:var(--line);background:var(--panel-bg);padding:14px;overflow:auto}.side-panel.collapsed{overflow:hidden;padding:8px 5px}.left-panel{grid-row:2 / 3;grid-column:2 / 3;border-right:1px solid var(--line)}.right-panel{grid-row:2 / 3;grid-column:4 / 5;border-left:1px solid var(--line)}.panel-chrome{min-height:28px;display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}.left-panel .panel-chrome{flex-direction:row-reverse}.panel-toggle{width:28px;min-width:28px;height:28px;min-height:28px;display:grid;place-items:center;padding:0;font-size:17px;line-height:1}.side-panel.collapsed .panel-chrome{height:100%;min-height:0;flex-direction:column;justify-content:flex-start;margin:0}.side-panel.collapsed .panel-title{writing-mode:vertical-rl;transform:rotate(180deg);white-space:nowrap;margin:10px 0 0;max-height:calc(100vh - 150px);overflow:hidden;text-overflow:ellipsis}.side-panel.collapsed .panel-body{display:none}.panel-title{margin:0 0 10px;color:var(--muted);font-size:11px;font-weight:800;text-transform:uppercase}.source-card,.check{border:1px solid var(--line);border-radius:7px;background:var(--card-bg)}.source-card{padding:12px;margin-bottom:12px}.source-card strong{display:block;font-size:13px;margin-bottom:5px}.source-card p{margin:0;color:var(--muted);font-size:12px;line-height:1.4}.batch-option{display:flex;align-items:center;gap:8px;margin-top:10px;color:var(--text);font-size:12px;line-height:1.35}.format-flow,.checklist{display:grid;gap:8px;margin:14px 0}.flow-step{display:grid;grid-template-columns:32px 1fr auto;align-items:center;gap:9px;min-height:42px;padding:7px;border:1px solid var(--line);border-radius:7px;background:var(--panel)}.badge{height:26px;border-radius:5px;display:grid;place-items:center;background:#c0dfd6;color:#003d32;color:oklch(32% .07 176);font-weight:800;font-size:10px}.flow-step small{display:block;color:var(--muted);font-size:11px}.insert-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.insert-tile{min-height:58px;border:1px solid var(--line);border-radius:7px;padding:9px;background:var(--card-bg);font-size:12px;text-align:left}.insert-tile b{display:block;margin-bottom:5px}.workspace{grid-row:2 / 3;grid-column:3 / 4;min-width:0;min-height:0;display:grid;grid-template-rows:42px 1fr;overflow:hidden;background:var(--soft)}.mode-strip{display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line);padding:0 14px}.segmented{display:inline-flex;gap:2px;padding:3px;border:1px solid var(--line);border-radius:7px;background:var(--card-bg)}.segmented button{border:0;min-height:24px;background:transparent}.segmented button.active{background:var(--ink);color:#fbf8f1}.canvas-wrap{min-height:0;height:100%;display:grid;grid-template-columns:minmax(360px,1fr) minmax(300px,.72fr);overflow:hidden}.workspace.markdown .canvas-wrap,.workspace.markdown.large .canvas-wrap{grid-template-columns:1fr}.workspace.split .canvas-wrap{grid-template-columns:minmax(360px,1fr) minmax(300px,.72fr)}.workspace.raw .canvas-wrap{grid-template-columns:1fr}.workspace.markdown .markdown-pane,.workspace.raw .page-area{display:none}.page-area{min-width:0;min-height:0;height:100%;overflow:auto;padding:26px 38px 60px}.page{position:relative;width:min(760px,100%);min-height:900px;margin:0 auto;padding:58px 64px;border:1px solid oklch(84% .014 92);border-radius:6px;background:var(--page-bg);box-shadow:var(--shadow)}.page-label{margin:0 0 18px;color:var(--warning);font-size:11px;font-weight:800;text-transform:uppercase}.rich .ProseMirror{min-height:720px;outline:none;color:var(--page-ink);line-height:1.62}.rich .ProseMirror h1,.rendered-markdown h1{margin:0 0 18px;max-width:14ch;font-size:42px;line-height:.98}.rich .ProseMirror h2,.rendered-markdown h2{margin-top:32px;font-size:25px}.rich .ProseMirror p,.rich .ProseMirror li,.rendered-markdown p,.rendered-markdown li{font-size:15px}.rich .ProseMirror blockquote,.rendered-markdown blockquote{margin:24px 0;padding:15px;border:1px solid oklch(78% .055 176);border-radius:7px;background:color-mix(in oklch,var(--accent) 14%,var(--page-bg))}.rich .ProseMirror table,.rendered-markdown table{width:100%;margin:22px 0;border-collapse:collapse;font-size:13px}.rich .ProseMirror th,.rich .ProseMirror td,.rendered-markdown th,.rendered-markdown td{border:1px solid oklch(78% .016 92);padding:8px;text-align:left}.rich .ProseMirror th,.rendered-markdown th{background:var(--table-head)}.rich img,.rendered-markdown img{max-width:100%;height:auto;border-radius:5px}.readonly-preview{color:var(--page-ink);line-height:1.62}.rendered-markdown{min-height:720px}.rendered-markdown pre{overflow:auto;padding:12px;border-radius:6px;background:color-mix(in oklch,var(--page-ink) 8%,var(--page-bg))}.rendered-markdown code{font-family:Consolas,Cascadia Mono,monospace}.markdown-pane{min-width:0;min-height:0;height:100%;overflow:auto;padding:18px;background:var(--source);color:var(--source-ink);border-left:1px solid var(--line)}.editable-markdown{display:flex;flex-direction:column;gap:10px}.markdown-toolbar{display:flex;flex-wrap:wrap;gap:4px;padding-bottom:8px;border-bottom:1px solid var(--line)}.markdown-toolbar button{min-width:30px;min-height:26px;border-color:var(--line);background:color-mix(in oklch,var(--page-ink) 4%,var(--source));color:var(--source-ink)}.source{width:100%;min-height:0;flex:1;border:0;outline:none;background:transparent;color:inherit;font:13px/1.55 Consolas,Cascadia Mono,monospace}.code-source,.code-source>div,.code-source [class*=cm-theme],.code-source .cm-editor,.code-source .cm-scroller{min-height:0;height:100%}.code-source .cm-editor{border-radius:6px;border:1px solid oklch(84% .014 92);background:var(--source);color:var(--source-ink)}.code-source .cm-scroller{background:var(--source);color:var(--source-ink);font-family:Consolas,Cascadia Mono,monospace;font-size:13px;line-height:1.55}.code-source .cm-content{color:var(--source-ink)}.code-source .cm-gutters{border-right:1px solid var(--line);background:var(--source);color:var(--muted)}.code-source .cm-lineNumbers .cm-gutterElement{min-width:26px;padding:0 6px 0 2px;color:var(--muted);font-size:10px;opacity:.52}.code-source .cm-activeLine,.code-source .cm-activeLineGutter{background:color-mix(in oklch,var(--accent) 8%,transparent)}.bubble-menu,.floating-menu{display:flex;align-items:center;gap:3px;padding:5px;border:1px solid var(--bubble-line);border-radius:8px;background:var(--bubble-bg);box-shadow:0 16px 32px #181c2438}.floating-menu{background:var(--card-bg);border-color:var(--line)}.bubble-menu button{min-width:28px;border-color:#3e4c5a;background:transparent;color:var(--bubble-ink)}.floating-menu button{min-width:28px;min-height:26px}.meter{height:8px;overflow:hidden;border-radius:999px;background:#d8d4c7;margin-top:10px}.meter span{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--violet))}.check{display:grid;grid-template-columns:24px 1fr;gap:8px;align-items:start;padding:8px;font-size:12px}.dot{width:16px;height:16px;margin-top:1px;border-radius:999px;background:var(--accent)}.dot.warn{background:var(--warning)}.tool-group{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-bottom:12px}.tool-group button{min-width:0}.statusbar{grid-column:2 / 5;border-top:1px solid var(--line);background:#f5f2e9;color:var(--muted);display:flex;align-items:center;justify-content:space-between;gap:20px;padding:0 12px;font-size:12px}.statusbar span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:840px){body{min-width:760px}main.app-shell{grid-template-columns:52px 1fr;grid-template-rows:48px 1fr 30px}.topbar,.statusbar{grid-column:2 / 3}.left-panel,.right-panel{display:none}.workspace{grid-column:2 / 3}.canvas-wrap{grid-template-columns:1fr}.workspace.split .canvas-wrap{grid-template-columns:minmax(340px,1fr) minmax(280px,.78fr)}}.compose-shell{display:grid;grid-template-rows:auto 1fr auto;height:100vh;width:100vw;background:#101214;color:#eef1f4;font-family:Segoe UI,Inter,system-ui,sans-serif}.compose-topbar,.compose-statusbar{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 16px;background:#181b1f;border-bottom:1px solid #353b44}.compose-statusbar{border-bottom:0;border-top:1px solid #353b44;color:#9ca8b4;font-size:12.5px;gap:14px}.compose-statusbar span:first-child{flex:1 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compose-title{display:flex;flex-direction:column;gap:2px;min-width:0}.compose-title strong{font-size:16px}.compose-title span{font-size:12px;color:#9ca8b4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compose-actions{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end}.compose-actions button{min-height:34px;border:1px solid #353b44;background:#20242a;color:#eef1f4;border-radius:6px;padding:0 12px;font:inherit;font-size:13px;cursor:pointer}.compose-actions button:hover{border-color:#9cc7ff}.compose-actions button.active{border-color:#65d0a4;color:#65d0a4}.compose-actions button.primary{background:#65d0a4;color:#06120d;border-color:#65d0a4;font-weight:650}.compose-actions button.primary:disabled{opacity:.6;cursor:default}.compose-editor-wrap{padding:14px;min-height:0;display:flex}.compose-editor-wrap.dragging{outline:3px solid #9cc7ff;outline-offset:-10px}.compose-editor{width:100%;height:100%;resize:none;border:1px solid #353b44;border-radius:8px;background:#0c0e10;color:#eef1f4;padding:16px;font:15px/1.55 Cascadia Code,Consolas,monospace;outline:none}.compose-editor:focus{border-color:#9cc7ff}
|
|
@@ -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>
|
|
16
|
-
<script type="module" crossorigin src="./assets/index-
|
|
17
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
18
|
-
</head>
|
|
19
|
-
<body>
|
|
20
|
-
<div id="root"></div>
|
|
21
|
-
</body>
|
|
22
|
-
</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
|
+
<script type="module" crossorigin src="./assets/index-BB0sbZaD.js"></script>
|
|
17
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CtOv7qsC.css">
|
|
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
|
@@ -164,6 +164,8 @@ function App() {
|
|
|
164
164
|
const [dirty, setDirty] = React.useState(false);
|
|
165
165
|
const [largeFile, setLargeFile] = React.useState(false);
|
|
166
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");
|
|
167
169
|
const sourceViewRef = React.useRef(null);
|
|
168
170
|
const pageAreaRef = React.useRef(null);
|
|
169
171
|
const scrollSyncRef = React.useRef(false);
|
|
@@ -225,6 +227,14 @@ function App() {
|
|
|
225
227
|
window.localStorage?.setItem("build-corpus-editor-theme", theme);
|
|
226
228
|
}, [theme]);
|
|
227
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
|
+
|
|
228
238
|
async function chooseOpen() {
|
|
229
239
|
try {
|
|
230
240
|
const result = await bridge.call("chooseOpen");
|
|
@@ -527,7 +537,7 @@ function App() {
|
|
|
527
537
|
const codeMirrorTheme = "light";
|
|
528
538
|
|
|
529
539
|
return (
|
|
530
|
-
<main className=
|
|
540
|
+
<main className={`app-shell${leftPanelCollapsed ? " left-collapsed" : ""}${rightPanelCollapsed ? " right-collapsed" : ""}`} data-theme={theme}>
|
|
531
541
|
<aside className="brand-rail" aria-label="Primary tools">
|
|
532
542
|
<div className="mark">BC</div>
|
|
533
543
|
<div className="rail-item active">Ed</div>
|
|
@@ -556,37 +566,51 @@ function App() {
|
|
|
556
566
|
</div>
|
|
557
567
|
</header>
|
|
558
568
|
|
|
559
|
-
<section className=
|
|
560
|
-
<
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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>
|
|
565
582
|
</div>
|
|
566
|
-
<div className="
|
|
567
|
-
<div className="
|
|
568
|
-
<
|
|
569
|
-
<
|
|
570
|
-
<
|
|
571
|
-
</div>
|
|
572
|
-
<div className="flow-step">
|
|
573
|
-
<div className="badge">MD</div>
|
|
574
|
-
<div><b>Working draft</b><small>{draftText}</small></div>
|
|
575
|
-
<small>{dirty ? "dirty" : "saved"}</small>
|
|
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>
|
|
576
588
|
</div>
|
|
577
|
-
<div className="flow
|
|
578
|
-
<div className="
|
|
579
|
-
|
|
580
|
-
|
|
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>
|
|
581
605
|
</div>
|
|
582
|
-
</div>
|
|
583
606
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
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>
|
|
590
614
|
</div>
|
|
591
615
|
</section>
|
|
592
616
|
|
|
@@ -676,35 +700,49 @@ function App() {
|
|
|
676
700
|
</div>
|
|
677
701
|
</section>
|
|
678
702
|
|
|
679
|
-
<aside className=
|
|
680
|
-
<
|
|
681
|
-
|
|
682
|
-
<
|
|
683
|
-
|
|
684
|
-
|
|
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>
|
|
685
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>
|
|
686
723
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
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>
|
|
696
733
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
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>
|
|
702
739
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
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>
|
|
708
746
|
</div>
|
|
709
747
|
</aside>
|
|
710
748
|
|
|
@@ -127,6 +127,18 @@ main.app-shell {
|
|
|
127
127
|
var(--paper);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
main.app-shell.left-collapsed {
|
|
131
|
+
grid-template-columns: 58px 44px minmax(560px, 1fr) 320px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
main.app-shell.right-collapsed {
|
|
135
|
+
grid-template-columns: 58px 260px minmax(560px, 1fr) 44px;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
main.app-shell.left-collapsed.right-collapsed {
|
|
139
|
+
grid-template-columns: 58px 44px minmax(560px, 1fr) 44px;
|
|
140
|
+
}
|
|
141
|
+
|
|
130
142
|
.brand-rail {
|
|
131
143
|
grid-row: 1 / 4;
|
|
132
144
|
border-right: 1px solid var(--line);
|
|
@@ -208,6 +220,11 @@ main.app-shell {
|
|
|
208
220
|
overflow: auto;
|
|
209
221
|
}
|
|
210
222
|
|
|
223
|
+
.side-panel.collapsed {
|
|
224
|
+
overflow: hidden;
|
|
225
|
+
padding: 8px 5px;
|
|
226
|
+
}
|
|
227
|
+
|
|
211
228
|
.left-panel {
|
|
212
229
|
grid-row: 2 / 3;
|
|
213
230
|
grid-column: 2 / 3;
|
|
@@ -220,6 +237,53 @@ main.app-shell {
|
|
|
220
237
|
border-left: 1px solid var(--line);
|
|
221
238
|
}
|
|
222
239
|
|
|
240
|
+
.panel-chrome {
|
|
241
|
+
min-height: 28px;
|
|
242
|
+
display: flex;
|
|
243
|
+
align-items: center;
|
|
244
|
+
justify-content: space-between;
|
|
245
|
+
gap: 8px;
|
|
246
|
+
margin-bottom: 10px;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.left-panel .panel-chrome {
|
|
250
|
+
flex-direction: row-reverse;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.panel-toggle {
|
|
254
|
+
width: 28px;
|
|
255
|
+
min-width: 28px;
|
|
256
|
+
height: 28px;
|
|
257
|
+
min-height: 28px;
|
|
258
|
+
display: grid;
|
|
259
|
+
place-items: center;
|
|
260
|
+
padding: 0;
|
|
261
|
+
font-size: 17px;
|
|
262
|
+
line-height: 1;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.side-panel.collapsed .panel-chrome {
|
|
266
|
+
height: 100%;
|
|
267
|
+
min-height: 0;
|
|
268
|
+
flex-direction: column;
|
|
269
|
+
justify-content: flex-start;
|
|
270
|
+
margin: 0;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.side-panel.collapsed .panel-title {
|
|
274
|
+
writing-mode: vertical-rl;
|
|
275
|
+
transform: rotate(180deg);
|
|
276
|
+
white-space: nowrap;
|
|
277
|
+
margin: 10px 0 0;
|
|
278
|
+
max-height: calc(100vh - 150px);
|
|
279
|
+
overflow: hidden;
|
|
280
|
+
text-overflow: ellipsis;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.side-panel.collapsed .panel-body {
|
|
284
|
+
display: none;
|
|
285
|
+
}
|
|
286
|
+
|
|
223
287
|
.panel-title {
|
|
224
288
|
margin: 0 0 10px;
|
|
225
289
|
color: var(--muted);
|
|
@@ -685,7 +749,7 @@ main.app-shell {
|
|
|
685
749
|
white-space: nowrap;
|
|
686
750
|
}
|
|
687
751
|
|
|
688
|
-
@media (max-width:
|
|
752
|
+
@media (max-width: 840px) {
|
|
689
753
|
body {
|
|
690
754
|
min-width: 760px;
|
|
691
755
|
}
|
|
@@ -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
|
+
}
|