Skip to content
This repository was archived by the owner on Jan 18, 2022. It is now read-only.

Commit a5711f6

Browse files
committed
feat: Add data option to allow prepending style block content
Related #93
1 parent c61e6d6 commit a5711f6

File tree

5 files changed

+141
-15
lines changed

5 files changed

+141
-15
lines changed

docs/options.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,26 @@ e.g.: `defaultLang: { script: 'ts' }` would set default `<script>` block languag
2929
`defaultLang` does not set default language in templates for your editor/IDE.
3030
:::
3131

32-
## `blackListCustomBlocks`
3332

34-
- type: `string[]`
35-
- default: `['*']`
33+
## `customBlocks`
3634

37-
Exclude custom block from final bundle.
35+
- type: `string[] | ((tag: string) => boolean)`
36+
- default: `() => false`
3837

39-
## `whiteListCustomBlocks`
38+
Include/exclude custom block in final bundle.
39+
e.g.
4040

41-
- type: `string[]`
42-
- default: `[]`
43-
44-
Include custom block in final bundle.
41+
``` js
42+
...
43+
VuePlugin({
44+
customBlocks: [
45+
'!docs', // exclude <docs>
46+
'gql', // include <gql>
47+
'!*', // exclude everything else
48+
]
49+
})
50+
...
51+
```
4552

4653
## `css`
4754

@@ -50,6 +57,13 @@ Include custom block in final bundle.
5057

5158
Inject CSS in JavaScript. Setting `css: false` would extract styles in a `.css` file.
5259

60+
## `data`
61+
62+
- type: `{ [lang: string]: string | (() => string)}`
63+
- default: `{}`
64+
65+
Prepend content to `<style>` blocks in `.vue` files.
66+
5367
## `compiler`
5468

5569
- type: [VueTemplateCompiler](https://github.com/vuejs/component-compiler-utils#parseparseoptions-sfcdescriptor)

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@vue/component-compiler-utils": "^2.1.0",
5050
"debug": "^4.1.1",
5151
"hash-sum": "^1.0.2",
52+
"magic-string": "^0.25.2",
5253
"querystring": "^0.2.0",
5354
"rollup-pluginutils": "^2.0.1",
5455
"source-map": "0.7.3",

src/index.ts

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
StyleCompileResult,
1616
DescriptorCompileResult
1717
} from '@vue/component-compiler'
18+
import MagicString from 'magic-string'
1819
import { Plugin, RawSourceMap } from 'rollup'
1920
import * as path from 'path'
2021
import { parse, SFCDescriptor, SFCBlock } from '@vue/component-compiler-utils'
@@ -33,6 +34,15 @@ const dR = debug('rollup-plugin-vue:resolve')
3334
const dL = debug('rollup-plugin-vue:load')
3435
const dT = debug('rollup-plugin-vue:transform')
3536

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+
3646
export interface VuePluginOptions {
3747
/**
3848
* Include files or directories.
@@ -65,6 +75,17 @@ export interface VuePluginOptions {
6575
* ```
6676
*/
6777
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+
6889
/**
6990
* Inject CSS in JavaScript.
7091
* @default `true`
@@ -153,6 +174,9 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
153174
const exposeFilename =
154175
typeof opts.exposeFilename === 'boolean' ? opts.exposeFilename : false
155176

177+
const data: VuePluginOptionsData = (opts.data || {}) as any
178+
179+
delete opts.data
156180
delete opts.beforeAssemble
157181
delete opts.css
158182
delete opts.exposeFilename
@@ -180,6 +204,26 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
180204

181205
if (opts.css === false) d('Running in CSS extract mode')
182206

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+
183227
return {
184228
name: 'VuePlugin',
185229

@@ -193,6 +237,7 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
193237
if (!isVuePartRequest(id)) return
194238
id = path.resolve(path.dirname(importer), id)
195239
const ref = parseVuePartRequest(id)
240+
196241
if (ref) {
197242
const element = resolveVuePart(descriptors, ref)
198243
const src = (element as SFCBlock).src
@@ -217,11 +262,15 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
217262
if (!request) return null
218263

219264
const element = resolveVuePart(descriptors, request)
220-
const code =
265+
let code =
221266
'code' in element
222267
? ((element as any).code as string) // .code is set when extract styles is used. { css: false }
223268
: 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+
}
225274

226275
dL(`id: ${id}\ncode: \n${code}\nmap: ${JSON.stringify(map, null, 2)}\n\n`)
227276

@@ -254,6 +303,15 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
254303

255304
const styles = await Promise.all(
256305
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+
257315
const compiled = await compiler.compileStyleAsync(
258316
filename,
259317
scopeId,
@@ -382,7 +440,10 @@ function createCustomBlockFilter(
382440
customBlocks.filter(tag => tag.startsWith('!')).map(tag => tag.substr(1))
383441
)
384442

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+
}
388449
}

test/options/data.spec.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import vue, { VuePluginOptions } from '../../src'
2+
import { pluginInline } from '../setup/plugins'
3+
import { rollup } from 'rollup'
4+
5+
describe('data', () => {
6+
async function setup(options?: Partial<VuePluginOptions>) {
7+
return rollup({
8+
input: '/entry.vue',
9+
plugins: [
10+
pluginInline(
11+
'/entry.vue',
12+
`
13+
<template>
14+
<div>Hello, world</div>
15+
</template>
16+
<style scoped>
17+
div {
18+
color: red;
19+
}
20+
</style>
21+
`
22+
),
23+
vue({
24+
...options,
25+
normalizer: 'vue-runtime-helpers/dist/normalize-component.mjs',
26+
styleInjector: 'vue-runtime-helpers/dist/inject-style/browser.mjs',
27+
})
28+
]
29+
})
30+
.then(bundle => bundle.generate({ format: 'es' }))
31+
.then(generated => generated.output[0])
32+
}
33+
34+
it('prefix', async () => {
35+
const { code } = await setup({
36+
data: {
37+
css: '/*! © 2019 Jane Doe */\n'
38+
}
39+
})
40+
41+
expect(code).toEqual(expect.stringContaining('© 2019 Jane Doe'))
42+
})
43+
})

yarn.lock

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6604,6 +6604,13 @@ magic-string@^0.25.1:
66046604
dependencies:
66056605
sourcemap-codec "^1.4.1"
66066606

6607+
magic-string@^0.25.2:
6608+
version "0.25.2"
6609+
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9"
6610+
integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==
6611+
dependencies:
6612+
sourcemap-codec "^1.4.4"
6613+
66076614
make-dir@^1.0.0:
66086615
version "1.3.0"
66096616
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
@@ -9330,7 +9337,7 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, sour
93309337
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
93319338
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
93329339

9333-
sourcemap-codec@^1.4.1:
9340+
sourcemap-codec@^1.4.1, sourcemap-codec@^1.4.4:
93349341
version "1.4.4"
93359342
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f"
93369343
integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy