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

Commit

Permalink
Browse files Browse the repository at this point in the history
feat: Add data option to allow prepending style block content
Related #93
  • Loading branch information
znck committed Feb 5, 2019
1 parent c61e6d6 commit a5711f6
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 15 deletions.
32 changes: 23 additions & 9 deletions docs/options.md
Expand Up @@ -29,19 +29,26 @@ e.g.: `defaultLang: { script: 'ts' }` would set default `<script>` block languag
`defaultLang` does not set default language in templates for your editor/IDE.
:::

## `blackListCustomBlocks`

- type: `string[]`
- default: `['*']`
## `customBlocks`

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

## `whiteListCustomBlocks`
Include/exclude custom block in final bundle.
e.g.

- type: `string[]`
- default: `[]`

Include custom block in final bundle.
``` js
...
VuePlugin({
customBlocks: [
'!docs', // exclude <docs>
'gql', // include <gql>
'!*', // exclude everything else
]
})
...
```

## `css`

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

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

## `data`

- type: `{ [lang: string]: string | (() => string)}`
- default: `{}`

Prepend content to `<style>` blocks in `.vue` files.

## `compiler`

- type: [VueTemplateCompiler](https://github.com/vuejs/component-compiler-utils#parseparseoptions-sfcdescriptor)
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -49,6 +49,7 @@
"@vue/component-compiler-utils": "^2.1.0",
"debug": "^4.1.1",
"hash-sum": "^1.0.2",
"magic-string": "^0.25.2",
"querystring": "^0.2.0",
"rollup-pluginutils": "^2.0.1",
"source-map": "0.7.3",
Expand Down
71 changes: 66 additions & 5 deletions src/index.ts
Expand Up @@ -15,6 +15,7 @@ import {
StyleCompileResult,
DescriptorCompileResult
} from '@vue/component-compiler'
import MagicString from 'magic-string'
import { Plugin, RawSourceMap } from 'rollup'
import * as path from 'path'
import { parse, SFCDescriptor, SFCBlock } from '@vue/component-compiler-utils'
Expand All @@ -33,6 +34,15 @@ const dR = debug('rollup-plugin-vue:resolve')
const dL = debug('rollup-plugin-vue:load')
const dT = debug('rollup-plugin-vue:transform')

export interface VuePluginOptionsData {
css: string | (() => string)
less: string | (() => string)
postcss: string | (() => string)
sass: string | (() => string)
scss: string | (() => string)
stylus: string | (() => string)
}

export interface VuePluginOptions {
/**
* Include files or directories.
Expand Down Expand Up @@ -65,6 +75,17 @@ export interface VuePluginOptions {
* ```
*/
customBlocks?: string[] | ((tag: string) => boolean)

/**
* Prepend CSS.
* @default `undefined`
* @example
* ```js
* VuePlugin({ data: { scss: '$color: red;' } }) // to extract css
* ```
*/
data?: Partial<VuePluginOptionsData>

/**
* Inject CSS in JavaScript.
* @default `true`
Expand Down Expand Up @@ -153,6 +174,9 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
const exposeFilename =
typeof opts.exposeFilename === 'boolean' ? opts.exposeFilename : false

const data: VuePluginOptionsData = (opts.data || {}) as any

delete opts.data
delete opts.beforeAssemble
delete opts.css
delete opts.exposeFilename
Expand Down Expand Up @@ -180,6 +204,26 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {

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

function prependStyle(
id: string,
lang: string,
code: string,
map: any
): { code: string } {
if (!(lang in data)) return { code }
const ms = new MagicString(code, {
filename: id,
indentExclusionRanges: []
})

const value: string | (() => string) = (data as any)[lang]
const fn = typeof value === 'function' ? value : () => value

ms.prepend(fn())

return { code: ms.toString() }
}

return {
name: 'VuePlugin',

Expand All @@ -193,6 +237,7 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
if (!isVuePartRequest(id)) return
id = path.resolve(path.dirname(importer), id)
const ref = parseVuePartRequest(id)

if (ref) {
const element = resolveVuePart(descriptors, ref)
const src = (element as SFCBlock).src
Expand All @@ -217,11 +262,15 @@ export default function vue(opts: VuePluginOptions = {}): Plugin {
if (!request) return null

const element = resolveVuePart(descriptors, request)
const code =
let code =
'code' in element
? ((element as any).code as string) // .code is set when extract styles is used. { css: false }
: element.content
const map = element.map as RawSourceMap
let map = element.map as RawSourceMap

if (request.meta.type === 'styles') {
code = prependStyle(id, request.meta.lang, code, map).code
}

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

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

const styles = await Promise.all(
descriptor.styles.map(async style => {
if (style.content) {
style.content = prependStyle(
filename,
style.lang || 'css',
style.content,
style.map
).code
}

const compiled = await compiler.compileStyleAsync(
filename,
scopeId,
Expand Down Expand Up @@ -382,7 +440,10 @@ function createCustomBlockFilter(
customBlocks.filter(tag => tag.startsWith('!')).map(tag => tag.substr(1))
)

return tag =>
(allowed.has('*') || allowed.has(tag)) &&
!(notAllowed.has('*') || notAllowed.has(tag))
return tag => {
if (allowed.has(tag)) return true
if (notAllowed.has(tag)) return false
if (notAllowed.has('*')) return false
return allowed.has('*')
}
}
43 changes: 43 additions & 0 deletions test/options/data.spec.ts
@@ -0,0 +1,43 @@
import vue, { VuePluginOptions } from '../../src'
import { pluginInline } from '../setup/plugins'
import { rollup } from 'rollup'

describe('data', () => {
async function setup(options?: Partial<VuePluginOptions>) {
return rollup({
input: '/entry.vue',
plugins: [
pluginInline(
'/entry.vue',
`
<template>
<div>Hello, world</div>
</template>
<style scoped>
div {
color: red;
}
</style>
`
),
vue({
...options,
normalizer: 'vue-runtime-helpers/dist/normalize-component.mjs',
styleInjector: 'vue-runtime-helpers/dist/inject-style/browser.mjs',
})
]
})
.then(bundle => bundle.generate({ format: 'es' }))
.then(generated => generated.output[0])
}

it('prefix', async () => {
const { code } = await setup({
data: {
css: '/*! © 2019 Jane Doe */\n'
}
})

expect(code).toEqual(expect.stringContaining('© 2019 Jane Doe'))
})
})
9 changes: 8 additions & 1 deletion yarn.lock
Expand Up @@ -6604,6 +6604,13 @@ magic-string@^0.25.1:
dependencies:
sourcemap-codec "^1.4.1"

magic-string@^0.25.2:
version "0.25.2"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9"
integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==
dependencies:
sourcemap-codec "^1.4.4"

make-dir@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
Expand Down Expand Up @@ -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
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=

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

0 comments on commit a5711f6

Please sign in to comment.