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

Commit

Permalink
feat: Add support for shadow DOM style injection
Browse files Browse the repository at this point in the history
  • Loading branch information
znck committed Oct 26, 2019
1 parent 7344a1f commit 9a0e7cf
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 102 deletions.
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -45,15 +45,15 @@
"dist/"
],
"dependencies": {
"@vue/component-compiler": "^4.0.0",
"@vue/component-compiler": "^4.1.0",
"@vue/component-compiler-utils": "^3.0.0",
"debug": "^4.1.1",
"hash-sum": "^1.0.2",
"magic-string": "^0.25.2",
"querystring": "^0.2.0",
"rollup-pluginutils": "^2.4.1",
"source-map": "0.7.3",
"vue-runtime-helpers": "1.0.1"
"vue-runtime-helpers": "^1.1.1"
},
"devDependencies": {
"@babel/core": "^7.0.0-beta.46",
Expand Down
127 changes: 35 additions & 92 deletions src/index.ts
Expand Up @@ -4,7 +4,7 @@ import {
parseVuePartRequest,
resolveVuePart,
isVuePartRequest,
transformRequireToImport
transformRequireToImport,
} from './utils'
import {
createDefaultCompiler,
Expand All @@ -13,17 +13,14 @@ import {
StyleOptions,
TemplateOptions,
StyleCompileResult,
DescriptorCompileResult
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'
import debug from 'debug'
import {
VueTemplateCompiler,
VueTemplateCompilerParseOptions
} from '@vue/component-compiler-utils/dist/types'
import { VueTemplateCompiler, VueTemplateCompilerParseOptions } from '@vue/component-compiler-utils/dist/types'

const templateCompiler = require('vue-template-compiler')
const hash = require('hash-sum')
Expand Down Expand Up @@ -153,6 +150,10 @@ export interface VuePluginOptions {
*/
styleInjectorSSR?: string

styleInjectorShadow?: string

isWebComponent?: boolean

beforeAssemble?(descriptor: DescriptorCompileResult): DescriptorCompileResult
}
/**
Expand All @@ -163,25 +164,20 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
const isProduction =
opts.template && typeof opts.template.isProduction === 'boolean'
? opts.template.isProduction
: process.env.NODE_ENV === 'production' ||
process.env.BUILD === 'production'
: process.env.NODE_ENV === 'production' || process.env.BUILD === 'production'

d('Version ' + version)
d(`Build environment: ${isProduction ? 'production' : 'development'}`)
d(`Build target: ${process.env.VUE_ENV || 'browser'}`)

if (!opts.normalizer)
opts.normalizer = '~' + 'vue-runtime-helpers/dist/normalize-component.js'
if (!opts.styleInjector)
opts.styleInjector =
'~' + 'vue-runtime-helpers/dist/inject-style/browser.js'
if (!opts.styleInjectorSSR)
opts.styleInjectorSSR =
'~' + 'vue-runtime-helpers/dist/inject-style/server.js'
if (!opts.normalizer) opts.normalizer = '~' + 'vue-runtime-helpers/dist/normalize-component.mjs'
if (!opts.styleInjector) opts.styleInjector = '~' + 'vue-runtime-helpers/dist/inject-style/browser.mjs'
if (!opts.styleInjectorSSR) opts.styleInjectorSSR = '~' + 'vue-runtime-helpers/dist/inject-style/server.mjs'
if (!opts.styleInjectorSSR) opts.styleInjectorShadow = '~' + 'vue-runtime-helpers/dist/inject-style/shadow.mjs'

createVuePartRequest.defaultLang = {
...createVuePartRequest.defaultLang,
...opts.defaultLang
...opts.defaultLang,
}

const shouldExtractCss = opts.css === false
Expand All @@ -201,12 +197,9 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
}
const isAllowed = createCustomBlockFilter(opts.customBlocks || customBlocks)

const beforeAssemble =
opts.beforeAssemble ||
((d: DescriptorCompileResult): DescriptorCompileResult => d)
const beforeAssemble = opts.beforeAssemble || ((d: DescriptorCompileResult): DescriptorCompileResult => d)

const exposeFilename =
typeof opts.exposeFilename === 'boolean' ? opts.exposeFilename : false
const exposeFilename = typeof opts.exposeFilename === 'boolean' ? opts.exposeFilename : false

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

Expand All @@ -226,9 +219,9 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
image: 'xlink:href',
},
...opts.template
...opts.template,
} as any

if (opts.template && typeof opts.template.isProduction === 'undefined') {
Expand All @@ -240,16 +233,11 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {

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

function prependStyle(
id: string,
lang: string,
code: string,
map: any
): { code: string } {
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: []
indentExclusionRanges: [],
})

const value: string | (() => string) = (data as any)[lang]
Expand Down Expand Up @@ -282,7 +270,7 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
return path.resolve(path.dirname(ref.filename), src as string)
} else {
return require.resolve(src, {
paths: [path.dirname(ref.filename)]
paths: [path.dirname(ref.filename)],
})
}
}
Expand Down Expand Up @@ -324,35 +312,22 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
compiler: opts.compiler || templateCompiler,
compilerParseOptions: opts.compilerParseOptions,
sourceRoot: opts.sourceRoot,
needMap: 'needMap' in opts ? (opts as any).needMap : true
needMap: 'needMap' in opts ? (opts as any).needMap : true,
})
)
)

descriptors.set(filename, descriptor)

const scopeId =
'data-v-' +
(isProduction
? hash(path.basename(filename) + source)
: hash(filename + source))
const scopeId = 'data-v-' + (isProduction ? hash(path.basename(filename) + source) : hash(filename + source))

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
style.content = prependStyle(filename, style.lang || 'css', style.content, style.map).code
}

const compiled = await compiler.compileStyleAsync(
filename,
scopeId,
style
)
const compiled = await compiler.compileStyleAsync(filename, scopeId, style)
if (compiled.errors.length > 0) throw Error(compiled.errors[0])
return compiled
})
Expand All @@ -361,14 +336,11 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
const input: any = {
scopeId,
styles,
customBlocks: []
customBlocks: [],
}

if (descriptor.template) {
input.template = compiler.compileTemplate(
filename,
descriptor.template
)
input.template = compiler.compileTemplate(filename, descriptor.template)

input.template.code = transformRequireToImport(input.template.code)

Expand All @@ -384,29 +356,17 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
input.script = descriptor.script
? {
code: `
export * from '${createVuePartRequest(
filename,
descriptor.script.lang || 'js',
'script'
)}'
import script from '${createVuePartRequest(
filename,
descriptor.script.lang || 'js',
'script'
)}'
export * from '${createVuePartRequest(filename, descriptor.script.lang || 'js', 'script')}'
import script from '${createVuePartRequest(filename, descriptor.script.lang || 'js', 'script')}'
export default script
${
exposeFilename
? `
// For security concerns, we use only base name in production mode. See https://github.com/vuejs/rollup-plugin-vue/issues/258
script.__file = ${
isProduction
? JSON.stringify(path.basename(filename))
: JSON.stringify(filename)
}`
script.__file = ${isProduction ? JSON.stringify(path.basename(filename)) : JSON.stringify(filename)}`
: ''
}
`
`,
}
: { code: '' }

Expand All @@ -415,14 +375,7 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
.map((style: StyleCompileResult, index: number) => {
;(descriptor.styles[index] as any).code = style.code

input.script.code +=
'\n' +
`import '${createVuePartRequest(
filename,
'css',
'styles',
index
)}'`
input.script.code += '\n' + `import '${createVuePartRequest(filename, 'css', 'styles', index)}'`

if (style.module || descriptor.styles[index].scoped) {
return { ...style, code: '', map: undefined }
Expand All @@ -449,32 +402,22 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
)}'`
})

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

result.map = result.map || { mappings: '' }

return result
}
}
},
}
}

function createCustomBlockFilter(
customBlocks?: string[] | ((tag: string) => boolean)
): (tag: string) => boolean {
function createCustomBlockFilter(customBlocks?: string[] | ((tag: string) => boolean)): (tag: string) => boolean {
if (typeof customBlocks === 'function') return customBlocks
if (!Array.isArray(customBlocks)) return () => false

const allowed = new Set(customBlocks.filter(tag => !tag.startsWith('!')))
const notAllowed = new Set(
customBlocks.filter(tag => tag.startsWith('!')).map(tag => tag.substr(1))
)
const notAllowed = new Set(customBlocks.filter(tag => tag.startsWith('!')).map(tag => tag.substr(1)))

return tag => {
if (allowed.has(tag)) return true
Expand Down
16 changes: 8 additions & 8 deletions yarn.lock
Expand Up @@ -1435,10 +1435,10 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"

"@vue/component-compiler@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler/-/component-compiler-4.0.0.tgz#916d57d546d38cc9179fe841c1f7f93d35a255a0"
integrity sha512-XZkpbE1B16g7RqM8AL/LP/wr3qkOLDwiO9yF2k/2O5BwGcqPyQOYHtD67sjMso6/703ztykFsbZsJbD/7xFWDQ==
"@vue/component-compiler@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler/-/component-compiler-4.1.0.tgz#92ccb90e425aa7e61d58bf092a5cfcdd6d0f9315"
integrity sha512-20S7mm7CYP94m2Morw2ftz1tqoBu1nX7KYiqo5rlgKPZ0dlY7VZX7wAL/etN3s4HD0PBeenr1pUUCBIgGSaB2g==
dependencies:
"@vue/component-compiler-utils" "^3.0.0"
clean-css "^4.1.11"
Expand Down Expand Up @@ -10264,10 +10264,10 @@ vue-router@^3.0.1:
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be"
integrity sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg==

vue-runtime-helpers@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vue-runtime-helpers/-/vue-runtime-helpers-1.0.1.tgz#9a7f527d43fdecf83638188fb0e5bae699c2b5bb"
integrity sha512-yodqdAWt/QrUkb51jN2DS4dtF4vQWg5YejYdBAcHIOi6kBoGLRVEDz5NYGdh5IhzLrElgi+eKX1DQJmj3bCuJw==
vue-runtime-helpers@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/vue-runtime-helpers/-/vue-runtime-helpers-1.1.1.tgz#5f9422d4e958478060800afe738df40de7c9f653"
integrity sha512-L20UdZnvY9Tmvf7yWJmN2kzlK/KyCFLAXOIUbm7yyRfjDqub6vC1CUrkLH7XGM+GRO8MnBap6uUYvgQTJ1yOOQ==

vue-server-renderer@^2.5.16:
version "2.5.22"
Expand Down

0 comments on commit 9a0e7cf

Please sign in to comment.