diff --git a/packages/@d-zero/builder/src/compiler/css.spec.ts b/packages/@d-zero/builder/src/compiler/css.spec.ts index c2815de4..8c4e22e4 100644 --- a/packages/@d-zero/builder/src/compiler/css.spec.ts +++ b/packages/@d-zero/builder/src/compiler/css.spec.ts @@ -21,12 +21,12 @@ describe('compileCss', () => { }); // Verify cssnano minification - expect(result).not.toContain('\n'); - expect(result).not.toContain(' '); - expect(result).toContain('.button'); - expect(result).toContain('color:red'); - expect(result).toContain('background-color:blue'); - expect(result).toContain('margin:10px 20px'); + expect(result.css).not.toContain('\n'); + expect(result.css).not.toContain(' '); + expect(result.css).toContain('.button'); + expect(result.css).toContain('color:red'); + expect(result.css).toContain('background-color:blue'); + expect(result.css).toContain('margin:10px 20px'); }); it('should handle CSS comments properly', async () => { @@ -41,8 +41,8 @@ describe('compileCss', () => { alias: {}, }); - expect(result).not.toContain('Regular comment'); - expect(result).toContain('Important comment'); + expect(result.css).not.toContain('Regular comment'); + expect(result.css).toContain('Important comment'); }); it('should process complex CSS selectors and values', async () => { @@ -66,10 +66,10 @@ describe('compileCss', () => { alias: {}, }); - expect(result).toContain('.card>.header:before'); // ::before gets minified to :before - expect(result).toContain('content:""'); - expect(result).toContain('linear-gradient(90deg,red,#00f)'); // Actual minification result - expect(result).toContain('@media (min-width:768px)'); + expect(result.css).toContain('.card>.header:before'); // ::before gets minified to :before + expect(result.css).toContain('content:""'); + expect(result.css).toContain('linear-gradient(90deg,red,#00f)'); // Actual minification result + expect(result.css).toContain('@media (min-width:768px)'); }); it('should handle empty CSS', async () => { @@ -79,7 +79,7 @@ describe('compileCss', () => { alias: {}, }); - expect(result).toBe(''); + expect(result.css).toBe(''); }); it('should handle CSS with only comments', async () => { @@ -92,7 +92,7 @@ describe('compileCss', () => { alias: {}, }); - expect(result).toBe(''); + expect(result.css).toBe(''); }); it('should preserve only important comments', async () => { @@ -106,9 +106,9 @@ describe('compileCss', () => { alias: {}, }); - expect(result).toContain('License information'); - expect(result).toContain('Copyright information'); - expect(result).not.toContain('Regular comment'); + expect(result.css).toContain('License information'); + expect(result.css).toContain('Copyright information'); + expect(result.css).not.toContain('Regular comment'); }); }); @@ -120,7 +120,7 @@ describe('compileCss', () => { alias: {}, }); - expect(result).toBe(''); + expect(result.css).toBe(''); }); it('should throw error for unclosed block syntax', async () => { @@ -149,8 +149,8 @@ describe('compileCss', () => { }, }); - expect(result).toContain('.component'); - expect(result).toContain('color:green'); + expect(result.css).toContain('.component'); + expect(result.css).toContain('color:green'); }); }); }); @@ -182,8 +182,8 @@ describe('compileCss - File import functionality', () => { }, }); - expect(result).toContain('.button'); - expect(result).toContain('padding:1rem'); + expect(result.css).toContain('.button'); + expect(result.css).toContain('padding:1rem'); }); it('should throw error when importing non-existent file', async () => { diff --git a/packages/@d-zero/builder/src/compiler/css.ts b/packages/@d-zero/builder/src/compiler/css.ts index 95c7fffe..4ea1a210 100644 --- a/packages/@d-zero/builder/src/compiler/css.ts +++ b/packages/@d-zero/builder/src/compiler/css.ts @@ -89,5 +89,11 @@ export async function compileCss( to: undefined, }); - return result.css; + const dependencies = result.messages + .filter( + (message) => message.type === 'dependency' && typeof message.file === 'string', + ) + .map((message) => message.file); + + return { css: result.css, dependencies }; } diff --git a/packages/@d-zero/builder/src/eleventy-plugins/script.ts b/packages/@d-zero/builder/src/eleventy-plugins/script.ts index 71c9c164..5c8c2b2d 100644 --- a/packages/@d-zero/builder/src/eleventy-plugins/script.ts +++ b/packages/@d-zero/builder/src/eleventy-plugins/script.ts @@ -25,19 +25,36 @@ export const scriptPlugin: EleventyPlugin { const tmpPath = path.join(pluginConfig.tmpDir, inputPath); + const addDependencies = this.addDependencies; - await esbuild.build({ + const result = await esbuild.build({ entryPoints: [inputPath], bundle: true, alias: eleventyConfig.globalData.alias, outfile: tmpPath, minify: !!(eleventyConfig.globalData.minifier?.minifyJS ?? true), charset: 'utf8', + metafile: true, banner: { js: pluginConfig.banner, }, }); + const dependencies = result.metafile + ? Object.keys(result.metafile.inputs) + .filter( + (key) => + typeof key === 'string' && + !key.startsWith('<') && + !key.startsWith('node:'), + ) + .map((key) => path.resolve(key)) + : []; + + if (addDependencies && dependencies.length > 0) { + addDependencies(inputPath, dependencies); + } + const content = await fs.readFile(tmpPath, 'utf8'); return content; }; diff --git a/packages/@d-zero/builder/src/eleventy-plugins/style.ts b/packages/@d-zero/builder/src/eleventy-plugins/style.ts index b4004083..e8cff42c 100644 --- a/packages/@d-zero/builder/src/eleventy-plugins/style.ts +++ b/packages/@d-zero/builder/src/eleventy-plugins/style.ts @@ -28,16 +28,22 @@ export const stylePlugin: EleventyPlugin return async () => { const absInputPath = path.resolve(inputPath); const cssMinify = !!(pluginConfig.minify ?? true); + const addDependencies = this.addDependencies; - let content = await compileCss(css, absInputPath, { + const { css: compiledCss, dependencies } = await compileCss(css, absInputPath, { alias: pluginConfig.alias, }); + let content = compiledCss; if (!cssMinify) { const prettierOptions = pluginConfig.prettier ?? false; content = await prettifyCss(content, inputPath, prettierOptions); } + if (addDependencies && dependencies.length > 0) { + addDependencies(inputPath, dependencies); + } + return `${pluginConfig.banner}\n${content}`; }; }, diff --git a/packages/@d-zero/builder/src/eleventy.types.ts b/packages/@d-zero/builder/src/eleventy.types.ts index ad4fa1d9..576228d0 100644 --- a/packages/@d-zero/builder/src/eleventy.types.ts +++ b/packages/@d-zero/builder/src/eleventy.types.ts @@ -43,6 +43,7 @@ export type EleventyTransformContext = { export type EleventyExtensionCompiler = { outputFileExtension?: string; + addDependencies?: (inputPath: string, dependencies: string[]) => void; compile: ( content: string, inputPath: string, diff --git a/packages/@d-zero/scaffold/package.json b/packages/@d-zero/scaffold/package.json index 5a032932..a5a1093e 100644 --- a/packages/@d-zero/scaffold/package.json +++ b/packages/@d-zero/scaffold/package.json @@ -19,7 +19,7 @@ "build:only": "npx @d-zero/builder", "build:clear": "yarn lint && npx @d-zero/builder --clear-cache", "build:only:clear": "npx @d-zero/builder --clear-cache", - "dev": "npx eleventy --serve --watch", + "dev": "npx eleventy --serve --watch --incremental", "d": "yarn dev", "lint": "run-s \"lint:*\"", "lint:html": "npx markuplint \"./__assets/**/*.{pug,html}\"",