Files
writer-work-flow/apps/web/lib/review/applyFix.ts
Yaojia Wang 9cf4915d49 refactor(web): hasApplicableFix 改类型谓词,消除 applyConflictFix 强转
hasApplicableFix 重写为对象入参类型谓词 patch is ApplicablePatch,谓词命中后 applyConflictFix 里 original/replacement 自动收窄为 string,删两处 as string;补收窄单测。
2026-07-08 13:27:45 +02:00

55 lines
2.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 一键采纳改法把审稿提议的补丁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 收窄为 ApplicablePatchoriginal/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),
};
}