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>`/); }); });