Skip to content

Commit

Permalink
feat: shadowMode
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Jan 31, 2018
1 parent 18d0ae4 commit 94737e5
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
13 changes: 12 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports.pitch = function (remainingRequest) {
var isProduction = this.minimize || process.env.NODE_ENV === 'production'
var addStylesClientPath = loaderUtils.stringifyRequest(this, '!' + path.join(__dirname, 'lib/addStylesClient.js'))
var addStylesServerPath = loaderUtils.stringifyRequest(this, '!' + path.join(__dirname, 'lib/addStylesServer.js'))
var addStylesShadowPath = loaderUtils.stringifyRequest(this, '!' + path.join(__dirname, 'lib/addStylesShadow.js'))

var request = loaderUtils.stringifyRequest(this, '!!' + remainingRequest)
var id = JSON.stringify(hash(request + path.relative(__dirname, this.resourcePath)))
Expand All @@ -36,7 +37,17 @@ module.exports.pitch = function (remainingRequest) {
'if(content.locals) module.exports = content.locals;'
]

if (!isServer) {
// shadowMode is enabled in vue-cli with vue build --target web-component.
// exposes the same __inject__ method like SSR
if (options.shadowMode) {
return shared.concat([
'// add CSS to Shadow Root',
'var add = require(' + addStylesShadowPath + ').default',
'module.exports.__inject__ = function (shadowRoot) {',
' add(' + id + ', content, shadowRoot)',
'};'
]).join('\n')
} else if (!isServer) {
// on the client: dynamic inject + hot-reload
var code = [
'// add the styles to the DOM',
Expand Down
82 changes: 82 additions & 0 deletions lib/addStylesShadow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import listToStyles from './listToStyles'

export default function addStylesToShadowDOM (parentId, list, shadowRoot) {
var styles = listToStyles(parentId, list)
addStyles(styles, shadowRoot)
}

/*
type StyleObject = {
id: number;
parts: Array<StyleObjectPart>
}
type StyleObjectPart = {
css: string;
media: string;
sourceMap: ?string
}
*/

function addStyles (styles /* Array<StyleObject> */, shadowRoot) {
const injectedStyles =
shadowRoot._injectedStyles ||
(shadowRoot._injectedStyles = {})
for (var i = 0; i < styles.length; i++) {
var item = styles[i]
var style = injectedStyles[item.id]
if (style) {
style.refs++
for (var j = 0; j < style.parts.length; j++) {
style.parts[j](item.parts[j])
}
for (; j < item.parts.length; j++) {
style.parts.push(addStyle(item.parts[j], shadowRoot))
}
if (style.parts.length > item.parts.length) {
style.parts.length = item.parts.length
}
} else {
var parts = []
for (var j = 0; j < item.parts.length; j++) {
parts.push(addStyle(item.parts[j], shadowRoot))
}
injectedStyles[item.id] = { id: item.id, refs: 1, parts: parts }
}
}
}

function createStyleElement (shadowRoot) {
var styleElement = document.createElement('style')
styleElement.type = 'text/css'
shadowRoot.appendChild(styleElement)
return styleElement
}

function addStyle (obj /* StyleObjectPart */, shadowRoot) {
var styleElement = createStyleElement(shadowRoot)
var css = obj.css
var media = obj.media
var sourceMap = obj.sourceMap

if (media) {
styleElement.setAttribute('media', media)
}

if (sourceMap) {
// https://developer.chrome.com/devtools/docs/javascript-debugging
// this makes source maps inside style tags work properly in Chrome
css += '\n/*# sourceURL=' + sourceMap.sources[0] + ' */'
// http://stackoverflow.com/a/26603875
css += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + ' */'
}

if (styleElement.styleSheet) {
styleElement.styleSheet.cssText = css
} else {
while (styleElement.firstChild) {
styleElement.removeChild(styleElement.firstChild)
}
styleElement.appendChild(document.createTextNode(css))
}
}

0 comments on commit 94737e5

Please sign in to comment.