新增能力:内置 4 套红头、3 套正式文档和 3 套标书主题,支持主题推荐页边距、页面装饰、页眉页脚和页码;增加结构化公文、项目报告及标书 Front Matter,内置 Fandol 中文字体、两份教程和 14 份主题示例。 桌面工作流:重组更多菜单,增加新建、保存、另存为快捷键和未保存确认;另存为后跟随新路径,主题示例自动切换主题,Desktop 发行包完整携带教程、示例与字体。 问题修复:修正红头标题居中与正式文档字体;围栏代码按正文宽度自动换行,长内容安全断行,至少两行即可在当前页分页,并统一保留 8px 左侧内容留白;Docker Web 镜像正确打包 samples。 兼容与部署:未声明主题推荐设置时继续使用 16mm 默认页边距;Web 隐藏不适用的另存为。正式镜像 yixiong/md-to-pdf:v0.5.1 内容 ID 为 sha256:72f519a69bfd6cb2f6df30c2be938e58ceb6f20e4748a32551874de3d436b276,Compose 健康运行。 验证结果:最终修复前 65 个测试文件、286 项测试通过,最终代码块与主题定向测试 27 项通过;全项目类型检查、生产构建和 git diff --check 通过。容器检出 14 套主题、17 份 Markdown,代码块回归 PDF 为 2 页且无越界。NSIS SHA-256 为 676CCE73D782B0B15AC6BC68F253CFBC4740383583E4DAA98F746EDF9999C5CC,ZIP SHA-256 为 82BF6ADF1200604F145CC86FA3ED193955CF6741EBEE3DF8953483515CFF621F。
103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
import { useEffect } from "react";
|
|
|
|
type DocumentActionDialogProps =
|
|
| {
|
|
type: "new-location";
|
|
busy?: false;
|
|
onCurrentWindow: () => void;
|
|
onNewWindow: () => void;
|
|
onCancel: () => void;
|
|
}
|
|
| {
|
|
type: "unsaved";
|
|
busy: boolean;
|
|
onSave: () => void;
|
|
onDiscard: () => void;
|
|
onCancel: () => void;
|
|
};
|
|
|
|
export function DocumentActionDialog(
|
|
props: DocumentActionDialogProps
|
|
) {
|
|
useEffect(() => {
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
if (event.key === "Escape" && !props.busy) {
|
|
event.preventDefault();
|
|
props.onCancel();
|
|
}
|
|
};
|
|
window.addEventListener("keydown", handleKeyDown);
|
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
}, [props]);
|
|
|
|
const isNewLocation = props.type === "new-location";
|
|
return (
|
|
<div className="document-dialog-layer">
|
|
<div className="document-dialog-backdrop" />
|
|
<section
|
|
className="document-dialog"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="document-dialog-title"
|
|
aria-describedby="document-dialog-description"
|
|
>
|
|
<span className="panel-kicker">文档操作</span>
|
|
<h2 id="document-dialog-title">
|
|
{isNewLocation ? "新建 Markdown" : "保存当前修改?"}
|
|
</h2>
|
|
<p id="document-dialog-description">
|
|
{isNewLocation
|
|
? "请选择在当前窗口新建,或者保留当前文档并打开一个新窗口。"
|
|
: "当前文档包含尚未保存的修改。继续操作前,可以先保存这些内容。"}
|
|
</p>
|
|
<div className="document-dialog-actions">
|
|
<button
|
|
type="button"
|
|
disabled={props.busy}
|
|
onClick={props.onCancel}
|
|
>
|
|
取消
|
|
</button>
|
|
{isNewLocation ? (
|
|
<>
|
|
<button
|
|
type="button"
|
|
onClick={props.onNewWindow}
|
|
>
|
|
新窗口新建
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="is-primary"
|
|
autoFocus
|
|
onClick={props.onCurrentWindow}
|
|
>
|
|
当前窗口新建
|
|
</button>
|
|
</>
|
|
) : (
|
|
<>
|
|
<button
|
|
type="button"
|
|
disabled={props.busy}
|
|
onClick={props.onDiscard}
|
|
>
|
|
不保存
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="is-primary"
|
|
disabled={props.busy}
|
|
autoFocus
|
|
onClick={props.onSave}
|
|
>
|
|
{props.busy ? "正在保存…" : "保存"}
|
|
</button>
|
|
</>
|
|
)}
|
|
</div>
|
|
</section>
|
|
</div>
|
|
);
|
|
}
|