@@ -3,6 +3,7 @@ import path from 'path';
3
3
import relative from 'require-relative' ;
4
4
import { compile , preprocess } from 'svelte' ;
5
5
import { createFilter } from 'rollup-pluginutils' ;
6
+ import { encode , decode } from 'sourcemap-codec' ;
6
7
7
8
function sanitize ( input ) {
8
9
return path
@@ -52,6 +53,59 @@ function exists(file) {
52
53
}
53
54
}
54
55
56
+ function mkdirp ( dir ) {
57
+ const parent = path . dirname ( dir ) ;
58
+ if ( parent === dir ) return ;
59
+
60
+ mkdirp ( parent ) ;
61
+
62
+ try {
63
+ fs . mkdirSync ( dir ) ;
64
+ } catch ( err ) {
65
+ if ( err . code !== 'EEXIST' ) throw err ;
66
+ }
67
+ }
68
+
69
+ class CssWriter {
70
+ constructor ( code , map ) {
71
+ this . code = code ;
72
+ this . map = {
73
+ version : 3 ,
74
+ file : null ,
75
+ sources : map . sources ,
76
+ sourcesContent : map . sourcesContent ,
77
+ names : [ ] ,
78
+ mappings : map . mappings
79
+ } ;
80
+ }
81
+
82
+ write ( dest , map ) {
83
+ dest = path . resolve ( dest ) ;
84
+ mkdirp ( path . dirname ( dest ) ) ;
85
+
86
+ const basename = path . basename ( dest ) ;
87
+
88
+ if ( map !== false ) {
89
+ fs . writeFileSync ( dest , `${ this . code } \n/*# sourceMappingURL=${ basename } .map */` ) ;
90
+ fs . writeFileSync ( `${ dest } .map` , JSON . stringify ( {
91
+ version : 3 ,
92
+ file : basename ,
93
+ sources : this . map . sources . map ( source => path . relative ( path . dirname ( dest ) , source ) ) ,
94
+ sourcesContent : this . map . sourcesContent ,
95
+ names : [ ] ,
96
+ mappings : this . map . mappings
97
+ } , null , ' ' ) ) ;
98
+ } else {
99
+ fs . writeFileSync ( dest , this . code ) ;
100
+ }
101
+ }
102
+
103
+ toString ( ) {
104
+ console . log ( '[DEPRECATION] As of rollup-plugin-svelte@3, the argument to the `css` function is an object, not a string — use `css.write(file)`. Consult the documentation for more information: https://github.com/rollup/rollup-plugin-svelte' ) ; // eslint-disable-line no-console
105
+ return this . code ;
106
+ }
107
+ }
108
+
55
109
export default function svelte ( options = { } ) {
56
110
const filter = createFilter ( options . include , options . exclude ) ;
57
111
@@ -69,12 +123,21 @@ export default function svelte(options = {}) {
69
123
fixedOptions . shared = require . resolve ( options . shared || 'svelte/shared.js' ) ;
70
124
71
125
// handle CSS extraction
72
- if ( 'emitCss ' in options ) {
73
- if ( typeof options . emitCss !== 'boolean' ) {
74
- throw new Error ( 'options.emitCss must be a boolean' ) ;
126
+ if ( 'css ' in options ) {
127
+ if ( typeof options . css !== 'function' && typeof options . css !== 'boolean' ) {
128
+ throw new Error ( 'options.css must be a boolean or a function ' ) ;
75
129
}
76
130
}
77
- let cssBuffer = new Map ( ) ;
131
+
132
+ let css = options . css && typeof options . css === 'function'
133
+ ? options . css
134
+ : null ;
135
+
136
+ const cssLookup = new Map ( ) ;
137
+
138
+ if ( css || options . emitCss ) {
139
+ fixedOptions . css = false ;
140
+ }
78
141
79
142
if ( options . onwarn ) {
80
143
fixedOptions . onwarn = options . onwarn ;
@@ -84,12 +147,12 @@ export default function svelte(options = {}) {
84
147
name : 'svelte' ,
85
148
86
149
load ( id ) {
87
- if ( ! cssBuffer . has ( id ) ) return null ;
88
- return cssBuffer . get ( id ) ;
150
+ if ( ! cssLookup . has ( id ) ) return null ;
151
+ return cssLookup . get ( id ) ;
89
152
} ,
90
153
91
154
resolveId ( importee , importer ) {
92
- if ( cssBuffer . has ( importee ) ) { return importee ; }
155
+ if ( cssLookup . has ( importee ) ) { return importee ; }
93
156
if ( ! importer || importee [ 0 ] === '.' || importee [ 0 ] === '\0' || path . isAbsolute ( importee ) )
94
157
return null ;
95
158
@@ -130,7 +193,7 @@ export default function svelte(options = {}) {
130
193
code . toString ( ) ,
131
194
Object . assign ( { } , {
132
195
onwarn : warning => {
133
- if ( ! options . emitCss && warning . code === 'css-unused-selector' ) return ;
196
+ if ( ( options . css || ! options . emitCss ) && warning . code === 'css-unused-selector' ) return ;
134
197
this . warn ( warning ) ;
135
198
} ,
136
199
onerror : error => this . error ( error )
@@ -145,18 +208,63 @@ export default function svelte(options = {}) {
145
208
map : compiled . js ? compiled . js . map : compiled . map
146
209
} ;
147
210
148
- if ( options . emitCss ) {
211
+ if ( css || options . emitCss ) {
149
212
// handle pre- and post-1.60 signature
150
- const css_code = typeof compiled . css === 'string' ? compiled . css : compiled . css && compiled . css . code ;
151
- const css_map = compiled . css && compiled . css . map || compiled . cssMap ;
213
+ let code = typeof compiled . css === 'string' ? compiled . css : compiled . css && compiled . css . code ;
214
+ let map = compiled . css && compiled . css . map || compiled . cssMap ;
152
215
153
216
let fname = id . replace ( '.html' , '.scss' ) ;
154
- cssBuffer . set ( fname , { code : css_code , map : css_map } ) ;
155
- bundle . code += `\nimport '${ fname } ';\n` ;
217
+ cssLookup . set ( fname , { code, map } ) ;
218
+ if ( options . emitCss ) {
219
+ bundle . code += `\nimport '${ fname } ';\n` ;
220
+ }
221
+
156
222
}
157
223
158
224
return bundle ;
159
225
} ) ;
226
+ } ,
227
+ ongenerate ( ) {
228
+ if ( css ) {
229
+ // write out CSS file. TODO would be nice if there was a
230
+ // a more idiomatic way to do this in Rollup
231
+ let result = '' ;
232
+
233
+ const mappings = [ ] ;
234
+ const sources = [ ] ;
235
+ const sourcesContent = [ ] ;
236
+
237
+ for ( let chunk of cssLookup . values ( ) ) {
238
+ if ( ! chunk . code ) continue ;
239
+ result += chunk . code + '\n' ;
240
+
241
+ if ( chunk . map ) {
242
+ const i = sources . length ;
243
+ sources . push ( chunk . map . sources [ 0 ] ) ;
244
+ sourcesContent . push ( chunk . map . sourcesContent [ 0 ] ) ;
245
+
246
+ const decoded = decode ( chunk . map . mappings ) ;
247
+
248
+ if ( i > 0 ) {
249
+ decoded . forEach ( line => {
250
+ line . forEach ( segment => {
251
+ segment [ 1 ] = i ;
252
+ } ) ;
253
+ } ) ;
254
+ }
255
+
256
+ mappings . push ( ...decoded ) ;
257
+ }
258
+ }
259
+
260
+ const writer = new CssWriter ( result , {
261
+ sources,
262
+ sourcesContent,
263
+ mappings : encode ( mappings )
264
+ } ) ;
265
+
266
+ css ( writer ) ;
267
+ }
160
268
}
161
269
} ;
162
270
}
0 commit comments