import { expect, it } from "vitest";
import {
HTML_INLINE_SCRIPT_LOCATION_LIMIT,
htmlArtifactReferences,
} from "./htmlArtifactReferences.js";
it.each([
['', []],
['', []],
[``, []],
["", ["actual.js"]],
['', ["actual.js"]],
['', ["actual.js"]],
["", ["actual.js"]],
['', ["actual.js"]],
['', ["actual.js"]],
['', []],
['', ["actual.js"]],
['', []],
['', []],
['', []],
[``, []],
[
'',
[],
],
['', []],
[
'',
["actual.js"],
],
['', ["actual.js"]],
['', ["actual.js"]],
['', ["actual.js"]],
['', ["actual.js"]],
['', ["actual.js"]],
['', ["actual.js"]],
['', ["actual.js"]],
])("extracts document references from %s", (text, expected) => {
expect(
htmlArtifactReferences(text).scripts.map(({ scriptPath }) => scriptPath),
).toEqual(expected);
});
it("retains exact opening-tag coordinates rather than the script body", () => {
const opening = '`;
expect(htmlArtifactReferences(text)).toEqual({
baseHref: null,
inlineScripts: [],
inlineScriptCount: 0,
scripts: [
{
scriptPath: "actual.js",
scriptType: "classic",
location: {
start: { line: 3, column: 0 },
end: { line: 4, column: ' title=">" src=actual.js>'.length },
},
},
],
});
});
it.each([
['', "actual/"],
['', "actual/"],
['', ""],
['', "actual/"],
['', "actual/"],
])("selects the first real base href from %s", (text, expected) => {
expect(htmlArtifactReferences(text).baseHref).toBe(expected);
});
it("traverses deep valid document content without recursive stack growth", () => {
const depth = 12_000;
const text = `${"
".repeat(depth)}${"
".repeat(depth)}`;
expect(
htmlArtifactReferences(text).scripts.map(({ scriptPath }) => scriptPath),
).toEqual(["actual.js"]);
});
it.each([
["", ["classic"]],
['', ["classic"]],
['', ["classic"]],
['', ["classic"]],
['', ["classic"]],
['', ["classic"]],
['', ["module"]],
// Only the JavaScript MIME check strips whitespace; `module` must match.
['', []],
['', []],
["", ["classic"]],
// A src attribute, even an empty one, means the browser ignores the body.
['', []],
['', []],
["", []],
['', []],
['', []],
['', []],
['', []],
['', []],
['', []],
["", []],
["", []],
["", []],
])("classifies inline JavaScript in %s", (text, expected) => {
expect(
htmlArtifactReferences(text).inlineScripts.map(
({ scriptType }) => scriptType,
),
).toEqual(expected);
});
it("retains exact inline script body coordinates, including unclosed scripts", () => {
const prefix = "\nafter
`;
expect(htmlArtifactReferences(closed).inlineScripts).toEqual([
{
scriptType: "classic",
location: { start: { line: 2, column: 8 }, end: { line: 4, column: 0 } },
},
]);
const unclosed = `${prefix}${body}`;
expect(htmlArtifactReferences(unclosed).inlineScripts).toEqual([
{
scriptType: "classic",
location: { start: { line: 2, column: 8 }, end: { line: 4, column: 0 } },
},
]);
});
it("counts every inline body but retains bounded locations", () => {
const count = 150_000;
const text = "".repeat(count);
const { inlineScripts, inlineScriptCount } = htmlArtifactReferences(text);
expect(inlineScriptCount).toBe(count);
expect(inlineScripts).toHaveLength(HTML_INLINE_SCRIPT_LOCATION_LIMIT);
const column = 18 * (HTML_INLINE_SCRIPT_LOCATION_LIMIT - 1) + 8;
expect(inlineScripts.at(-1)).toEqual({
scriptType: "classic",
location: {
start: { line: 1, column },
end: { line: 1, column: column + 1 },
},
});
});
it.each([
['type=" Text/JavaScript "', "classic"],
['type="MODULE"', "module"],
['type="application/json"', null],
['type="importmap"', null],
['type="speculationrules"', null],
['language="vbscript"', null],
['type=" module "', null],
])(
"retains external src with parsed JavaScript type for %s",
(attributes, scriptType) => {
expect(
htmlArtifactReferences(``)
.scripts,
).toMatchObject([{ scriptPath: "source.js", scriptType }]);
},
);