diff --git a/packages/opencode/src/util/bom.ts b/packages/opencode/src/util/bom.ts index f015651e97fd..16b578eeccaf 100644 --- a/packages/opencode/src/util/bom.ts +++ b/packages/opencode/src/util/bom.ts @@ -5,8 +5,8 @@ const BOM_CODE = 0xfeff const BOM = String.fromCharCode(BOM_CODE) export function split(text: string) { - if (text.charCodeAt(0) !== BOM_CODE) return { bom: false, text } - return { bom: true, text: text.slice(1) } + const stripped = text.replace(/^\uFEFF+/, "") + return { bom: stripped.length !== text.length, text: stripped } } export function join(text: string, bom: boolean) { diff --git a/packages/opencode/test/util/bom.test.ts b/packages/opencode/test/util/bom.test.ts new file mode 100644 index 000000000000..7fffb6beb19f --- /dev/null +++ b/packages/opencode/test/util/bom.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, test } from "bun:test" +import * as Bom from "../../src/util/bom" + +const BOM = "\uFEFF" + +describe("Bom.split", () => { + test("returns text unchanged when there is no BOM", () => { + expect(Bom.split("hello")).toEqual({ bom: false, text: "hello" }) + }) + + test("strips a single leading BOM", () => { + expect(Bom.split(BOM + "hello")).toEqual({ bom: true, text: "hello" }) + }) + + test("strips all consecutive leading BOMs", () => { + expect(Bom.split(BOM.repeat(4) + "hello")).toEqual({ bom: true, text: "hello" }) + }) + + test("does not strip a BOM that is not at the start", () => { + expect(Bom.split("hello" + BOM)).toEqual({ bom: false, text: "hello" + BOM }) + }) + + test("handles an empty string", () => { + expect(Bom.split("")).toEqual({ bom: false, text: "" }) + }) +}) + +describe("Bom.join", () => { + test("adds a BOM when requested", () => { + expect(Bom.join("hello", true)).toBe(BOM + "hello") + }) + + test("omits the BOM when not requested", () => { + expect(Bom.join("hello", false)).toBe("hello") + }) + + test("normalizes multiple existing leading BOMs to exactly one", () => { + expect(Bom.join(BOM.repeat(4) + "hello", true)).toBe(BOM + "hello") + }) + + test("strips all existing leading BOMs when none is requested", () => { + expect(Bom.join(BOM.repeat(3) + "hello", false)).toBe("hello") + }) +})