import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { inlineTemplatePlugin } from '../inline-template-plugin.ts';
// Helper: run the plugin's transform on a code string.
function transform(code: string): string {
const plugin = inlineTemplatePlugin({ minify: true });
const result = plugin.transform?.(code, 'test.ts');
return result?.code ?? code;
}
// Helper: extract the minified template body (between the backticks).
function minifyHTML(template: string): string {
const code = `/*html*/ \`${template}\``;
const result = transform(code);
const match = result.match(/`([\s\S]*)`/);
return match?.[1] ?? '';
}
// ---------------------------------------------------------------------------
// HTML minification
// ---------------------------------------------------------------------------
describe('minifyHtmlQuasis', () => {
// ------- whitespace -------
it('collapses whitespace-only text content between tags', () => {
// Whitespace-only text between > and < is removed entirely
// (step 2 collapses to single space, step 3 removes inter-tag space).
assert.equal(minifyHTML('
'), '');
});
it('removes whitespace between tags', () => {
assert.equal(minifyHTML(' '), '');
});
it('trims leading whitespace from the template', () => {
assert.equal(minifyHTML(' '), '');
});
it('trims trailing whitespace from the template', () => {
assert.equal(minifyHTML(' '), '');
});
it('collapses newlines and indentation between tags', () => {
const input = `
`;
assert.equal(minifyHTML(input), '
');
});
// ------- HTML comments -------
it('strips HTML comments', () => {
assert.equal(minifyHTML(''), '');
});
it('strips multiline HTML comments', () => {
const input = `
`;
assert.equal(minifyHTML(input), '');
});
it('strips comments between elements', () => {
assert.equal(minifyHTML(''), '');
});
// ------- empty elements -------
it('preserves empty elements', () => {
assert.equal(minifyHTML(''), '');
});
it('preserves empty elements with attributes', () => {
assert.equal(minifyHTML(''), '');
});
it('preserves adjacent empty slot elements', () => {
const input = `
`;
assert.equal(minifyHTML(input), '');
});
it('preserves the default slot between named slots', () => {
const input = `
`;
assert.equal(minifyHTML(input), '');
});
it('preserves empty void-like elements', () => {
assert.equal(minifyHTML(''), '');
});
// ------- attribute values with special characters -------
it('does not corrupt attribute values containing > <', () => {
assert.equal(minifyHTML(''), '');
});
it('does not corrupt single-quoted attribute values containing > <', () => {
assert.equal(minifyHTML(""), "");
});
it('handles attribute values with > followed by space and <', () => {
assert.equal(minifyHTML(''), '');
});
// ------- text content -------
it('preserves text content inside elements', () => {
assert.equal(minifyHTML('hello world'), 'hello world');
});
it('preserves single space in text content between tags', () => {
// Text-only whitespace after > that is NOT followed by < should be kept.
assert.equal(minifyHTML('hello world'), 'hello world');
});
// ------- realistic skin template -------
it('correctly minifies a skin-like template', () => {
const input = `
`;
assert.equal(
minifyHTML(input),
'' +
'' +
'' +
'' +
''
);
});
});
// ---------------------------------------------------------------------------
// Template expressions
// ---------------------------------------------------------------------------
describe('processTemplates (expressions)', () => {
it('preserves template expressions', () => {
const code = 'const html = /*html*/ `${expr}
`;';
const result = transform(code);
assert.equal(result, 'const html = /*html*/ `${expr}
`;');
});
it('handles multiple expressions', () => {
const code = 'const html = /*html*/ `${a}
${b}`;';
const result = transform(code);
assert.equal(result, 'const html = /*html*/ `${a}
${b}`;');
});
it('handles expressions with nested braces', () => {
const code = "const html = /*html*/ `${fn({ class: 'icon' })}
`;";
const result = transform(code);
assert.equal(result, "const html = /*html*/ `${fn({ class: 'icon' })}
`;");
});
it('handles expressions with nested template literals', () => {
const code = 'const html = /*html*/ `${`nested ${value}`}
`;';
const result = transform(code);
assert.equal(result, 'const html = /*html*/ `${`nested ${value}`}
`;');
});
it('collapses whitespace around expressions', () => {
const code = `const html = /*html*/ \`
\${expr}
\`;`;
const result = transform(code);
assert.equal(result, 'const html = /*html*/ ` ${expr}
`;');
});
it('removes inter-tag whitespace around expressions', () => {
const code = `const html = /*html*/ \`
\${expr}
\`;`;
const result = transform(code);
assert.equal(result, 'const html = /*html*/ ` ${expr}
`;');
});
});
// ---------------------------------------------------------------------------
// CSS minification
// ---------------------------------------------------------------------------
describe('minifyCssQuasis', () => {
it('minifies simple CSS', () => {
const code = 'const css = /* css */ ` .foo { color: red; } `;';
const result = transform(code);
assert.match(result, /\.foo\s*\{/);
assert.match(result, /color:\s*red/);
});
it('preserves CSS expressions', () => {
const code = 'const css = /* css */ `.foo { color: ${color}; }`;';
const result = transform(code);
assert.match(result, /\$\{color\}/);
});
});
// ---------------------------------------------------------------------------
// Edge cases
// ---------------------------------------------------------------------------
describe('edge cases', () => {
it('returns null when minify is disabled', () => {
const plugin = inlineTemplatePlugin({ minify: false });
assert.equal(plugin.transform?.('/*html*/ ``', 'test.ts'), null);
});
it('returns null when code contains no markers', () => {
const plugin = inlineTemplatePlugin({ minify: true });
assert.equal(plugin.transform?.('const x = 1;', 'test.ts'), null);
});
it('returns null when marker is not followed by a template literal', () => {
const code = 'const marker = "/*html*/"; const x = 1;';
const result = transform(code);
assert.equal(result, code);
});
it('handles multiple HTML templates in one file', () => {
const code = ['const a = /*html*/ `
`;', 'const b = /*html*/ ` `;'].join('\n');
const result = transform(code);
assert.match(result, /`<\/div>`/);
assert.match(result, /`<\/span>`/);
});
});