Files
oh-my-openagent/src/tools/hashline-edit/file-text-canonicalization.ts
YeonGyu-Kim e6868e9112 fix(hashline-edit): align autocorrect, BOM/CRLF, and tool description with oh-my-pi
- Rewrite restoreOldWrappedLines to use oh-my-pi's span-scanning algorithm
- Add stripTrailingContinuationTokens and stripMergeOperatorChars helpers
- Fix detectLineEnding to use first-occurrence logic instead of any-match
- Fix applyAppend/applyPrepend to replace empty-line placeholder in empty files
- Enhance tool description with 7 critical rules, tag guidance, and anti-patterns
2026-02-22 14:40:18 +09:00

45 lines
1.3 KiB
TypeScript

export interface FileTextEnvelope {
content: string
hadBom: boolean
lineEnding: "\n" | "\r\n"
}
function detectLineEnding(content: string): "\n" | "\r\n" {
const crlfIndex = content.indexOf("\r\n")
const lfIndex = content.indexOf("\n")
if (lfIndex === -1) return "\n"
if (crlfIndex === -1) return "\n"
return crlfIndex < lfIndex ? "\r\n" : "\n"
}
function stripBom(content: string): { content: string; hadBom: boolean } {
if (!content.startsWith("\uFEFF")) {
return { content, hadBom: false }
}
return { content: content.slice(1), hadBom: true }
}
function normalizeToLf(content: string): string {
return content.replace(/\r\n/g, "\n").replace(/\r/g, "\n")
}
function restoreLineEndings(content: string, lineEnding: "\n" | "\r\n"): string {
if (lineEnding === "\n") return content
return content.replace(/\n/g, "\r\n")
}
export function canonicalizeFileText(content: string): FileTextEnvelope {
const stripped = stripBom(content)
return {
content: normalizeToLf(stripped.content),
hadBom: stripped.hadBom,
lineEnding: detectLineEnding(stripped.content),
}
}
export function restoreFileText(content: string, envelope: FileTextEnvelope): string {
const withLineEnding = restoreLineEndings(content, envelope.lineEnding)
if (!envelope.hadBom) return withLineEnding
return `\uFEFF${withLineEnding}`
}