hasApplicableFix 重写为对象入参类型谓词 patch is ApplicablePatch,谓词命中后 applyConflictFix 里 original/replacement 自动收窄为 string,删两处 as string;补收窄单测。
55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
// 一键采纳改法:把审稿提议的补丁(original→replacement)应用到终稿。
|
||
// 纯逻辑(可单测,不依赖 DOM)。粒度=最小句段;找不到原文则不动正文(作者手改)。
|
||
|
||
export type FixOutcome =
|
||
| { status: "applied"; text: string } // 命中原文并替换:text=改后终稿
|
||
| { status: "not-found"; text: string } // 有补丁但终稿里找不到原文(作者已改稿/漂移):text 原样
|
||
| { status: "no-patch"; text: string }; // 该冲突无可自动应用的补丁:text 原样
|
||
|
||
// 已确认可应用的补丁(original/replacement 均为 string)。
|
||
export interface ApplicablePatch {
|
||
original: string;
|
||
replacement: string;
|
||
}
|
||
|
||
// 松散补丁入参:original/replacement 可能缺失/为 null(审稿可局部修复时才带上)。
|
||
interface LoosePatch {
|
||
original: string | null | undefined;
|
||
replacement: string | null | undefined;
|
||
}
|
||
|
||
// 是否带可应用补丁:original 非空 + replacement 为字符串(容许空串=删除)。
|
||
// 类型谓词:命中即把 original/replacement 收窄为 string,调用方无需强转。
|
||
export function hasApplicableFix(patch: LoosePatch): patch is ApplicablePatch {
|
||
return (
|
||
typeof patch.original === "string" &&
|
||
patch.original.length > 0 &&
|
||
typeof patch.replacement === "string"
|
||
);
|
||
}
|
||
|
||
// 把首个匹配的 original 替换为 replacement(不可变:返回新串,不改入参)。
|
||
// 无补丁 → no-patch;有补丁但未命中 → not-found(终稿不变);命中 → applied。
|
||
export function applyConflictFix(
|
||
text: string,
|
||
original: string | null | undefined,
|
||
replacement: string | null | undefined,
|
||
): FixOutcome {
|
||
const patch: LoosePatch = { original, replacement };
|
||
if (!hasApplicableFix(patch)) {
|
||
return { status: "no-patch", text };
|
||
}
|
||
// 谓词已把 patch 收窄为 ApplicablePatch,original/replacement 皆为 string。
|
||
const idx = text.indexOf(patch.original);
|
||
if (idx === -1) {
|
||
return { status: "not-found", text };
|
||
}
|
||
return {
|
||
status: "applied",
|
||
text:
|
||
text.slice(0, idx) +
|
||
patch.replacement +
|
||
text.slice(idx + patch.original.length),
|
||
};
|
||
}
|