1
1
import { PluginContext } from 'rollup' ;
2
2
import path from 'path' ;
3
- import CleanCSS from 'clean-css' ;
3
+ import { transform } from 'lightningcss' ;
4
+ import fs from 'fs' ;
4
5
5
6
import { InputAsset , InputData } from '../input/InputData' ;
6
7
import { RollupPluginHTMLOptions , TransformAssetFunction } from '../RollupPluginHTMLOptions' ;
@@ -10,6 +11,16 @@ export interface EmittedAssets {
10
11
hashed : Map < string , string > ;
11
12
}
12
13
14
+ function shouldHandleFontFile ( url : string ) {
15
+ return (
16
+ ( url . endsWith ( '.woff2' ) || url . endsWith ( '.woff' ) ) &&
17
+ ! url . startsWith ( 'http' ) &&
18
+ ! url . startsWith ( 'data' ) &&
19
+ ! url . startsWith ( '#' ) &&
20
+ ! url . startsWith ( '/' )
21
+ ) ;
22
+ }
23
+
13
24
export async function emitAssets (
14
25
this : PluginContext ,
15
26
inputs : InputData [ ] ,
@@ -44,18 +55,6 @@ export async function emitAssets(
44
55
const allAssets = [ ...hashedAssets , ...staticAssets ] ;
45
56
46
57
for ( const asset of allAssets ) {
47
- if ( asset . filePath . endsWith ( '.css' ) ) {
48
- // TODO: try css bundlers like https://lightningcss.dev/bundling.html or esbuild
49
- // TODO: question: do we need to recursively analyze all assets that are referenced inside the first css file?
50
- // TODO: make a flag to enable this behavior, "false" by default
51
- const { styles } = await new CleanCSS ( {
52
- rebaseTo : path . dirname ( asset . filePath ) ,
53
- returnPromise : true ,
54
- } ) . minify ( [ asset . filePath ] ) ;
55
- console . log ( 'emitEsset.ts styles' , styles ) ;
56
- asset . content = Buffer . from ( styles , 'utf-8' ) ;
57
- }
58
-
59
58
const map = asset . hashed ? emittedHashedAssets : emittedStaticAssets ;
60
59
if ( ! map . has ( asset . filePath ) ) {
61
60
let source : Buffer = asset . content ;
@@ -70,7 +69,46 @@ export async function emitAssets(
70
69
71
70
let ref : string ;
72
71
let basename = path . basename ( asset . filePath ) ;
72
+ const emittedFonts = new Map ( ) ;
73
73
if ( asset . hashed ) {
74
+ if ( basename . endsWith ( '.css' ) ) {
75
+ let updatedCssSource = false ;
76
+ const { code } = await transform ( {
77
+ filename : basename ,
78
+ code : asset . content ,
79
+ minify : false ,
80
+ visitor : {
81
+ Url : url => {
82
+ if ( shouldHandleFontFile ( url . url ) ) {
83
+ // Read the font file, get the font from the source location on the FS using asset.filePath
84
+ const fontLocation = path . resolve ( path . dirname ( asset . filePath ) , url . url ) ;
85
+ const fontContent = fs . readFileSync ( fontLocation ) ;
86
+
87
+ // Avoid duplicates
88
+ if ( ! emittedFonts . has ( fontLocation ) ) {
89
+ const fontFileRef = this . emitFile ( {
90
+ type : 'asset' ,
91
+ name : path . basename ( url . url ) ,
92
+ source : fontContent ,
93
+ } ) ;
94
+ const emittedFontFilePath = path . basename ( this . getFileName ( fontFileRef ) ) ;
95
+ emittedFonts . set ( fontLocation , emittedFontFilePath ) ;
96
+ // Update the URL in the original CSS file to point to the emitted font file
97
+ url . url = emittedFontFilePath ;
98
+ } else {
99
+ url . url = emittedFonts . get ( fontLocation ) ;
100
+ }
101
+ }
102
+ updatedCssSource = true ;
103
+ return url ;
104
+ } ,
105
+ } ,
106
+ } ) ;
107
+ if ( updatedCssSource ) {
108
+ source = Buffer . from ( code ) ;
109
+ }
110
+ }
111
+
74
112
ref = this . emitFile ( { type : 'asset' , name : basename , source } ) ;
75
113
} else {
76
114
// ensure the output filename is unique
0 commit comments