@@ -15,6 +15,7 @@ import {
15
15
StyleCompileResult ,
16
16
DescriptorCompileResult
17
17
} from '@vue/component-compiler'
18
+ import MagicString from 'magic-string'
18
19
import { Plugin , RawSourceMap } from 'rollup'
19
20
import * as path from 'path'
20
21
import { parse , SFCDescriptor , SFCBlock } from '@vue/component-compiler-utils'
@@ -33,6 +34,15 @@ const dR = debug('rollup-plugin-vue:resolve')
33
34
const dL = debug ( 'rollup-plugin-vue:load' )
34
35
const dT = debug ( 'rollup-plugin-vue:transform' )
35
36
37
+ export interface VuePluginOptionsData {
38
+ css : string | ( ( ) => string )
39
+ less : string | ( ( ) => string )
40
+ postcss : string | ( ( ) => string )
41
+ sass : string | ( ( ) => string )
42
+ scss : string | ( ( ) => string )
43
+ stylus : string | ( ( ) => string )
44
+ }
45
+
36
46
export interface VuePluginOptions {
37
47
/**
38
48
* Include files or directories.
@@ -65,6 +75,17 @@ export interface VuePluginOptions {
65
75
* ```
66
76
*/
67
77
customBlocks ?: string [ ] | ( ( tag : string ) => boolean )
78
+
79
+ /**
80
+ * Prepend CSS.
81
+ * @default `undefined`
82
+ * @example
83
+ * ```js
84
+ * VuePlugin({ data: { scss: '$color: red;' } }) // to extract css
85
+ * ```
86
+ */
87
+ data ?: Partial < VuePluginOptionsData >
88
+
68
89
/**
69
90
* Inject CSS in JavaScript.
70
91
* @default `true`
@@ -153,6 +174,9 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
153
174
const exposeFilename =
154
175
typeof opts . exposeFilename === 'boolean' ? opts . exposeFilename : false
155
176
177
+ const data : VuePluginOptionsData = ( opts . data || { } ) as any
178
+
179
+ delete opts . data
156
180
delete opts . beforeAssemble
157
181
delete opts . css
158
182
delete opts . exposeFilename
@@ -180,6 +204,26 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
180
204
181
205
if ( opts . css === false ) d ( 'Running in CSS extract mode' )
182
206
207
+ function prependStyle (
208
+ id : string ,
209
+ lang : string ,
210
+ code : string ,
211
+ map : any
212
+ ) : { code : string } {
213
+ if ( ! ( lang in data ) ) return { code }
214
+ const ms = new MagicString ( code , {
215
+ filename : id ,
216
+ indentExclusionRanges : [ ]
217
+ } )
218
+
219
+ const value : string | ( ( ) => string ) = ( data as any ) [ lang ]
220
+ const fn = typeof value === 'function' ? value : ( ) => value
221
+
222
+ ms . prepend ( fn ( ) )
223
+
224
+ return { code : ms . toString ( ) }
225
+ }
226
+
183
227
return {
184
228
name : 'VuePlugin' ,
185
229
@@ -193,6 +237,7 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
193
237
if ( ! isVuePartRequest ( id ) ) return
194
238
id = path . resolve ( path . dirname ( importer ) , id )
195
239
const ref = parseVuePartRequest ( id )
240
+
196
241
if ( ref ) {
197
242
const element = resolveVuePart ( descriptors , ref )
198
243
const src = ( element as SFCBlock ) . src
@@ -217,11 +262,15 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
217
262
if ( ! request ) return null
218
263
219
264
const element = resolveVuePart ( descriptors , request )
220
- const code =
265
+ let code =
221
266
'code' in element
222
267
? ( ( element as any ) . code as string ) // .code is set when extract styles is used. { css: false }
223
268
: element . content
224
- const map = element . map as RawSourceMap
269
+ let map = element . map as RawSourceMap
270
+
271
+ if ( request . meta . type === 'styles' ) {
272
+ code = prependStyle ( id , request . meta . lang , code , map ) . code
273
+ }
225
274
226
275
dL ( `id: ${ id } \ncode: \n${ code } \nmap: ${ JSON . stringify ( map , null , 2 ) } \n\n` )
227
276
@@ -254,6 +303,15 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
254
303
255
304
const styles = await Promise . all (
256
305
descriptor . styles . map ( async style => {
306
+ if ( style . content ) {
307
+ style . content = prependStyle (
308
+ filename ,
309
+ style . lang || 'css' ,
310
+ style . content ,
311
+ style . map
312
+ ) . code
313
+ }
314
+
257
315
const compiled = await compiler . compileStyleAsync (
258
316
filename ,
259
317
scopeId ,
@@ -382,7 +440,10 @@ function createCustomBlockFilter(
382
440
customBlocks . filter ( tag => tag . startsWith ( '!' ) ) . map ( tag => tag . substr ( 1 ) )
383
441
)
384
442
385
- return tag =>
386
- ( allowed . has ( '*' ) || allowed . has ( tag ) ) &&
387
- ! ( notAllowed . has ( '*' ) || notAllowed . has ( tag ) )
443
+ return tag => {
444
+ if ( allowed . has ( tag ) ) return true
445
+ if ( notAllowed . has ( tag ) ) return false
446
+ if ( notAllowed . has ( '*' ) ) return false
447
+ return allowed . has ( '*' )
448
+ }
388
449
}
0 commit comments