Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
import { describe, expect, it } from "@suaveplan/testing/runner";
import { sniffBom } from "./sniff-bom.js";
import { sniffHtmlMeta } from "./sniff-html-meta.js";
import { sniffXmlDecl } from "./sniff-xml-decl.js";
describe("sniffBom", () => {
it("detects UTF-8 BOM (EF BB BF)", { timeout: 5000 }, () => {
const bytes = new Uint8Array([0xef, 0xbb, 0xbf, 0x68, 0x65]);
const result = sniffBom(bytes);
expect(result?.charset).toBe("utf-8");
expect(result?.bomLength).toBe(3);
});
it("detects UTF-16 LE BOM (FF FE)", { timeout: 5000 }, () => {
const bytes = new Uint8Array([0xff, 0xfe, 0x68, 0x00]);
const result = sniffBom(bytes);
expect(result?.charset).toBe("utf-16le");
expect(result?.bomLength).toBe(2);
});
it("detects UTF-16 BE BOM (FE FF)", { timeout: 5000 }, () => {
const bytes = new Uint8Array([0xfe, 0xff, 0x00, 0x68]);
const result = sniffBom(bytes);
expect(result?.charset).toBe("utf-16be");
expect(result?.bomLength).toBe(2);
});
it("detects UTF-32 LE BOM (FF FE 00 00)", { timeout: 5000 }, () => {
const bytes = new Uint8Array([0xff, 0xfe, 0x00, 0x00, 0x68]);
const result = sniffBom(bytes);
expect(result?.charset).toBe("utf-32le");
expect(result?.bomLength).toBe(4);
});
it("detects UTF-32 BE BOM (00 00 FE FF)", { timeout: 5000 }, () => {
const bytes = new Uint8Array([0x00, 0x00, 0xfe, 0xff, 0x68]);
const result = sniffBom(bytes);
expect(result?.charset).toBe("utf-32be");
expect(result?.bomLength).toBe(4);
});
it("returns null for no BOM", { timeout: 5000 }, () => {
const bytes = new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f]);
expect(sniffBom(bytes)).toBeNull();
});
it("returns null for empty buffer", { timeout: 5000 }, () => {
expect(sniffBom(new Uint8Array(0))).toBeNull();
});
it("accepts ArrayBuffer", { timeout: 5000 }, () => {
const buf = new Uint8Array([0xef, 0xbb, 0xbf, 0x41]).buffer;
expect(sniffBom(buf)?.charset).toBe("utf-8");
});
it("UTF-32 LE takes priority over UTF-16 LE when first 4 bytes are FF FE 00 00", {
timeout: 5000,
}, () => {
const bytes = new Uint8Array([0xff, 0xfe, 0x00, 0x00]);
expect(sniffBom(bytes)?.charset).toBe("utf-32le");
});
});
describe("sniffHtmlMeta", () => {
it("detects charset from <meta charset>", { timeout: 5000 }, () => {
const html = '<html><head><meta charset="UTF-8"></head></html>';
expect(sniffHtmlMeta(html)).toBe("utf-8");
});
it("detects charset from <meta charset> without quotes", {
timeout: 5000,
}, () => {
const html = "<meta charset=UTF-8>";
expect(sniffHtmlMeta(html)).toBe("utf-8");
});
it("detects charset from http-equiv content-type", {
timeout: 5000,
}, () => {
const html =
'<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">';
expect(sniffHtmlMeta(html)).toBe("iso-8859-1");
});
it("returns null when no charset found", { timeout: 5000 }, () => {
expect(
sniffHtmlMeta("<html><head><title>Hello</title></head></html>")
).toBeNull();
});
it("only scans first 1024 characters", { timeout: 5000 }, () => {
const prefix = "x".repeat(1100);
const html = `${prefix}<meta charset="UTF-8">`;
expect(sniffHtmlMeta(html)).toBeNull();
});
it("returns lowercase charset", { timeout: 5000 }, () => {
expect(sniffHtmlMeta('<meta charset="ISO-8859-1">')).toBe("iso-8859-1");
});
});
describe("sniffXmlDecl", () => {
it("detects encoding from XML declaration", { timeout: 5000 }, () => {
const xml = '<?xml version="1.0" encoding="UTF-8"?><root/>';
expect(sniffXmlDecl(xml)).toBe("utf-8");
});
it("detects encoding with single quotes", { timeout: 5000 }, () => {
const xml = "<?xml version='1.0' encoding='ISO-8859-1'?><root/>";
expect(sniffXmlDecl(xml)).toBe("iso-8859-1");
});
it("returns null when no encoding attribute", { timeout: 5000 }, () => {
const xml = '<?xml version="1.0"?><root/>';
expect(sniffXmlDecl(xml)).toBeNull();
});
it("returns null for non-XML content", { timeout: 5000 }, () => {
expect(sniffXmlDecl("<html>not xml</html>")).toBeNull();
});
it("only scans first 256 characters", { timeout: 5000 }, () => {
const prefix = "x".repeat(300);
const xml = `${prefix}<?xml version="1.0" encoding="UTF-8"?>`;
expect(sniffXmlDecl(xml)).toBeNull();
});
it("returns lowercase encoding", { timeout: 5000 }, () => {
const xml = '<?xml version="1.0" encoding="UTF-16"?>';
expect(sniffXmlDecl(xml)).toBe("utf-16");
});
});