38 lines
1.2 KiB
TypeScript
38 lines
1.2 KiB
TypeScript
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)
|
|
}
|