export * as Bom from "./bom.js" import { Effect } from "effect" import { FSUtil } from "./fs-util.js" const code = 0xfeff const value = String.fromCharCode(code) export function split(text: string) { const stripped = text.replace(/^\uFEFF+/, "") return { bom: stripped.length !== text.length, text: stripped } } export function join(text: string, bom: boolean) { const stripped = split(text).text return bom ? value + stripped : stripped } export function has(content: Uint8Array) { return content[0] === 0xef && content[1] === 0xbb && content[2] === 0xbf } export const readFile = Effect.fn("Bom.readFile")(function* (fs: FSUtil.Interface, filepath: string) { return split(decode(yield* fs.readFile(filepath))) }) export const syncFile = Effect.fn("Bom.syncFile")(function* (fs: FSUtil.Interface, filepath: string, bom: boolean) { const decoded = decode(yield* fs.readFile(filepath)) const current = split(decoded) const canonical = join(current.text, bom) if (decoded === canonical) return current.text yield* fs.writeWithDirs(filepath, canonical) return current.text }) function decode(content: Uint8Array) { return new TextDecoder("utf-8", { ignoreBOM: true }).decode(content) }