import { html } from './util/run' import { defaultExtractor } from '../src/lib/defaultExtractor' const jsExamples = ` document.body.classList.add(["pl-1.5"].join(" ")); document.body.classList.add(['pl-2.5'].join(" ")); ` const jsxExamples = `
` const htmlExamples = html`
` const includes = [ `font-['some_font',sans-serif]`, `font-["some_font",sans-serif]`, `bg-[url('...')]`, `bg-[url("...")]`, `bg-[url('...'),url('...')]`, `bg-[url("..."),url("...")]`, `content-['hello']`, `content-["hello"]`, `[content:'hello']`, `[content:"hello"]`, `[content:"hello"]`, `[content:'hello']`, `fill-[#bada55]`, `fill-[#bada55]/50`, `px-1.5`, `pl-1.5`, `pl-2.5`, `pr-1.5`, `pr-2.5`, `pr-3.5`, `pr-4.5`, `pr-5.5`, `pr-6.5`, `ml-0.5`, `h-[100px]`, `h-[101px]`, `h-[102px]`, `h-[103px]`, `h-[104px]`, `h-[105px]`, `h-[106px]`, `h-[107px]`, `h-[108px]`, `h-[109px]`, `uppercase`, `lowercase`, `normal-case`, `hover:font-bold`, `text-sm`, `text-[10px]`, `text-[11px]`, `text-blue-500`, `text-[21px]`, `text-[22px]`, `text-[31px]`, `text-[32px]`, `text-[41px]`, `text-[42px]`, `text-[51px]`, `text-[52px]`, `text-[61px]`, `text-[62px]`, `text-[71px]`, `text-[72px]`, `lg:text-[4px]`, `lg:text-[24px]`, `content-['>']`, `hover:test`, `overflow-scroll`, `[--y:theme(colors.blue.500)]`, `w-[calc(100%-theme('spacing.1'))]`, `w-[calc(100%-theme("spacing.2"))]`, ] const excludes = [ `uppercase:`, 'hover:', "hover:'abc", `font-bold`, `
`, `test`, ] test('The default extractor works as expected', async () => { const extractions = defaultExtractor([jsExamples, jsxExamples, htmlExamples].join('\n').trim()) for (const str of includes) { expect(extractions).toContain(str) } for (const str of excludes) { expect(extractions).not.toContain(str) } }) // Scenarios: // - In double quoted class attribute // - In single quoted class attribute // - Single-quoted as a variable // - Double-quoted as a variable // - Single-quoted as first array item // - Double-quoted as first array item // - Single-quoted as middle array item // - Double-quoted as middle array item // - Single-quoted as last array item // - Double-quoted as last array item // - Bare as an object key (with trailing `:`) // - Quoted as an object key (with trailing `:`) // - Within a template literal // - Within a template literal directly before interpolation // - Within a template literal directly after interpolation // - JS: ${...} // - PHP: {$...} // - Ruby: #{...} // - Within a string of HTML wrapped in escaped quotes test('basic utility classes', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('text-center') expect(extractions).toContain('font-bold') expect(extractions).toContain('px-4') expect(extractions).toContain('pointer-events-none') }) test('modifiers with basic utilites', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('hover:text-center') expect(extractions).toContain('hover:focus:font-bold') }) test('utilities with dot characters', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('px-1.5') expect(extractions).toContain('active:px-2.5') expect(extractions).toContain('hover:focus:px-3.5') }) test('basic utilities with color opacity modifier', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('text-red-500/25') expect(extractions).toContain('hover:text-red-500/50') expect(extractions).toContain('hover:active:text-red-500/75') }) test('basic arbitrary values', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('px-[25px]') expect(extractions).toContain('hover:px-[40rem]') expect(extractions).toContain('hover:focus:px-[23vh]') }) test('arbitrary values with color opacity modifier', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('text-[#bada55]/25') expect(extractions).toContain('hover:text-[#bada55]/50') expect(extractions).toContain('hover:active:text-[#bada55]/75') }) test('arbitrary values with spaces', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('grid-cols-[1fr_200px_3fr]') expect(extractions).toContain('md:grid-cols-[2fr_100px_1fr]') expect(extractions).toContain('open:lg:grid-cols-[3fr_300px_1fr]') }) test('arbitrary values with css variables', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('fill-[var(--my-color)]') expect(extractions).toContain('hover:fill-[var(--my-color-2)]') expect(extractions).toContain('hover:focus:fill-[var(--my-color-3)]') }) test('arbitrary values with type hints', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('text-[color:var(--my-color)]') expect(extractions).toContain('hover:text-[color:var(--my-color-2)]') expect(extractions).toContain('hover:focus:text-[color:var(--my-color-3)]') }) test('arbitrary values with single quotes', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain(`content-['hello_world']`) expect(extractions).toContain(`hover:content-['hello_world_2']`) expect(extractions).toContain(`hover:focus:content-['hello_world_3']`) }) test('arbitrary values with double quotes', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain(`content-["hello_world"]`) expect(extractions).toContain(`hover:content-["hello_world_2"]`) expect(extractions).toContain(`hover:focus:content-["hello_world_3"]`) }) test('arbitrary values with some single quoted values', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain(`font-['Open_Sans',_system-ui,_sans-serif]`) expect(extractions).toContain(`hover:font-['Proxima_Nova',_system-ui,_sans-serif]`) expect(extractions).toContain(`hover:focus:font-['Inter_var',_system-ui,_sans-serif]`) }) test('arbitrary values with some double quoted values', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain(`font-["Open_Sans",_system-ui,_sans-serif]`) expect(extractions).toContain(`hover:font-["Proxima_Nova",_system-ui,_sans-serif]`) expect(extractions).toContain(`hover:focus:font-["Inter_var",_system-ui,_sans-serif]`) }) test('arbitrary values with escaped underscores', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain(`content-['hello\\_world']`) expect(extractions).toContain(`hover:content-['hello\\_world\\_2']`) expect(extractions).toContain(`hover:focus:content-['hello\\_world\\_3']`) }) test('basic utilities with arbitrary color opacity modifier', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('text-red-500/[.25]') expect(extractions).toContain('hover:text-red-500/[.5]') expect(extractions).toContain('hover:active:text-red-500/[.75]') }) test('arbitrary values with arbitrary color opacity modifier', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('text-[#bada55]/[.25]') expect(extractions).toContain('hover:text-[#bada55]/[.5]') expect(extractions).toContain('hover:active:text-[#bada55]/[.75]') }) test('arbitrary values with angle brackets', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain(`content-[>]`) expect(extractions).toContain(`hover:content-[<]`) expect(extractions).toContain(`hover:focus:content-[>]`) }) test('arbitrary values with angle brackets in single quotes', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain(`content-['>']`) expect(extractions).toContain(`hover:content-['<']`) expect(extractions).toContain(`hover:focus:content-['>']`) }) test('arbitrary values with angle brackets in double quotes', async () => { const extractions = defaultExtractor(`
"] hover:content-["<"] hover:focus:content-[">"]">
`) expect(extractions).toContain(`content-[">"]`) expect(extractions).toContain(`hover:content-["<"]`) expect(extractions).toContain(`hover:focus:content-[">"]`) }) test('arbitrary values with theme lookup using quotes', () => { const extractions = defaultExtractor(`

`) expect(extractions).toContain(`[--y:theme('colors.blue.500')]`) expect(extractions).toContain(`[color:var(--y)]`) }) test('special characters', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain(`:font-bold`) }) test('with single quotes array within template literal', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('pr-1.5') expect(extractions).toContain('pr-1') }) test('with double quotes array within template literal', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('pr-1.5') expect(extractions).toContain('pr-1') }) test('with single quotes array within function', async () => { const extractions = defaultExtractor(`document.body.classList.add(['pl-1.5'].join(" "));`) expect(extractions).toContain('pl-1.5') expect(extractions).toContain('pl-1') }) test('with double quotes array within function', async () => { const extractions = defaultExtractor(`document.body.classList.add(["pl-1.5"].join(" "));`) expect(extractions).toContain('pl-1.5') expect(extractions).toContain('pl-1') })