chushihua
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
<!-- Before creating an issue please make sure you are using the latest version of style-loader. -->
|
||||
|
||||
**Do you want to request a *feature* or report a *bug*?**
|
||||
<!-- Please ask questions on StackOverflow or the webpack Gitter (https://gitter.im/webpack/webpack). Questions will be closed. -->
|
||||
|
||||
**What is the current behavior?**
|
||||
|
||||
**If the current behavior is a bug, please provide the steps to reproduce.**
|
||||
<!-- A great way to do this is to provide your configuration via a GitHub gist. -->
|
||||
|
||||
**What is the expected behavior?**
|
||||
|
||||
**If this is a feature request, what is motivation or use case for changing the behavior?**
|
||||
|
||||
**Please mention other relevant information such as your webpack version, Node.js version and Operating System.**
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->
|
||||
|
||||
**What kind of change does this PR introduce?**
|
||||
<!-- E.g. a bugfix, feature, refactoring, build related change, etc… -->
|
||||
|
||||
**Did you add tests for your changes?**
|
||||
|
||||
**If relevant, did you update the README?**
|
||||
|
||||
**Summary**
|
||||
|
||||
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->
|
||||
<!-- Try to link to an open issue for more information. -->
|
||||
|
||||
**Does this PR introduce a breaking change?**
|
||||
<!-- If this PR introduces a breaking change, please describe the impact and a migration path for existing applications. -->
|
||||
|
||||
**Other information**
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
Copyright JS Foundation and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# vue-style-loader [](https://circleci.com/gh/vuejs/vue-loader/tree/master) [](https://www.npmjs.com/package/vue-style-loader)
|
||||
|
||||
This is a fork based on [style-loader](https://github.com/webpack/style-loader). Similar to `style-loader`, you can chain it after `css-loader` to dynamically inject CSS into the document as style tags. However, since this is included as a dependency and used by default in `vue-loader`, in most cases you don't need to configure this loader yourself.
|
||||
|
||||
## Options
|
||||
|
||||
- **manualInject** (3.1.0+):
|
||||
|
||||
Type: `boolean`. When importing the style from a non-vue-file, by default the style is injected as a side effect of the import. When `manualInject` is true, the imported style object exposes a `__inject__` method, which can then be called manually at appropriate timing. If called on the server, the method expects one argument which is the `ssrContext` to attach styles to.
|
||||
|
||||
``` js
|
||||
import styles from 'styles.scss'
|
||||
|
||||
export default {
|
||||
beforeCreate() { // or create a mixin for this purpose
|
||||
if(styles.__inject__) {
|
||||
styles.__inject__(this.$ssrContext)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div class={styles.heading}>Hello World</div>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note this behavior is enabled automatically when `vue-style-loader` is used on styles imported within a `*.vue` file. The option is only exposed for advanced usage.
|
||||
|
||||
- **ssrId** (3.1.0+):
|
||||
|
||||
Type: `boolean`. Add `data-vue-ssr-id` attribute to injected `<style>` tags even when not in Node.js. This can be used with pre-rendering (instead of SSR) to avoid duplicate style injection on hydration.
|
||||
|
||||
## Differences from `style-loader`
|
||||
|
||||
### Server-Side Rendering Support
|
||||
|
||||
When bundling with `target: 'node'`, the styles in all rendered components are collected and exposed on the Vue render context object as `context.styles`, which you can simply inline into your markup's `<head>`. If you are building a Vue SSR app, you probably should use this loader for CSS imported from JavaScript files too.
|
||||
|
||||
### Misc
|
||||
|
||||
- Does not support url mode and reference counting mode. Also removed `singleton` and `insertAt` query options. It always automatically pick the style insertion mechanism that makes most sense. If you need these capabilities you should probably use the original `style-loader` instead.
|
||||
|
||||
- Fixed the issue that root-relative URLs are interpreted against chrome:// urls and make source map URLs work for injected `<style>` tags in Chrome.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
Modified by Evan You @yyx990803
|
||||
*/
|
||||
var loaderUtils = require('loader-utils')
|
||||
var path = require('path')
|
||||
var hash = require('hash-sum')
|
||||
|
||||
module.exports = function () {}
|
||||
|
||||
module.exports.pitch = function (remainingRequest) {
|
||||
if (this.cacheable) this.cacheable()
|
||||
|
||||
var isServer = this.target === 'node'
|
||||
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 request = loaderUtils.stringifyRequest(this, '!!' + remainingRequest)
|
||||
var id = JSON.stringify(hash(request + path.relative(__dirname, this.resourcePath)))
|
||||
var options = loaderUtils.getOptions(this) || {}
|
||||
|
||||
// direct css import from js --> direct, or manually call `styles.__inject__(ssrContext)` with `manualInject` option
|
||||
// css import from vue file --> component lifecycle linked
|
||||
// style embedded in vue file --> component lifecycle linked
|
||||
var isVue = /"vue":true/.test(remainingRequest) || options.manualInject
|
||||
|
||||
var shared = [
|
||||
'// style-loader: Adds some css to the DOM by adding a <style> tag',
|
||||
'',
|
||||
'// load the styles',
|
||||
'var content = require(' + request + ');',
|
||||
// content list format is [id, css, media, sourceMap]
|
||||
"if(typeof content === 'string') content = [[module.id, content, '']];",
|
||||
'if(content.locals) module.exports = content.locals;'
|
||||
]
|
||||
|
||||
if (!isServer) {
|
||||
// on the client: dynamic inject + hot-reload
|
||||
var code = [
|
||||
'// add the styles to the DOM',
|
||||
'var update = require(' + addStylesClientPath + ')(' + id + ', content, ' + isProduction + ', ' + JSON.stringify(options) + ');'
|
||||
]
|
||||
if (!isProduction) {
|
||||
code = code.concat([
|
||||
'// Hot Module Replacement',
|
||||
'if(module.hot) {',
|
||||
' // When the styles change, update the <style> tags',
|
||||
' if(!content.locals) {',
|
||||
' module.hot.accept(' + request + ', function() {',
|
||||
' var newContent = require(' + request + ');',
|
||||
" if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];",
|
||||
' update(newContent);',
|
||||
' });',
|
||||
' }',
|
||||
' // When the module is disposed, remove the <style> tags',
|
||||
' module.hot.dispose(function() { update(); });',
|
||||
'}'
|
||||
])
|
||||
}
|
||||
return shared.concat(code).join('\n')
|
||||
} else {
|
||||
// on the server: attach to Vue SSR context
|
||||
if (isVue) {
|
||||
// inside *.vue file: expose a function so it can be called in
|
||||
// component's lifecycle hooks
|
||||
return shared.concat([
|
||||
'// add CSS to SSR context',
|
||||
'var add = require(' + addStylesServerPath + ')',
|
||||
'module.exports.__inject__ = function (context) {',
|
||||
' add(' + id + ', content, ' + isProduction + ', context)',
|
||||
'};'
|
||||
]).join('\n')
|
||||
} else {
|
||||
// normal import
|
||||
return shared.concat([
|
||||
'require(' + addStylesServerPath + ')(' + id + ', content, ' + isProduction + ')'
|
||||
]).join('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
Modified by Evan You @yyx990803
|
||||
*/
|
||||
|
||||
var hasDocument = typeof document !== 'undefined'
|
||||
|
||||
if (typeof DEBUG !== 'undefined' && DEBUG) {
|
||||
if (!hasDocument) {
|
||||
throw new Error(
|
||||
'vue-style-loader cannot be used in a non-browser environment. ' +
|
||||
"Use { target: 'node' } in your Webpack config to indicate a server-rendering environment."
|
||||
) }
|
||||
}
|
||||
|
||||
var listToStyles = require('./listToStyles')
|
||||
|
||||
/*
|
||||
type StyleObject = {
|
||||
id: number;
|
||||
parts: Array<StyleObjectPart>
|
||||
}
|
||||
|
||||
type StyleObjectPart = {
|
||||
css: string;
|
||||
media: string;
|
||||
sourceMap: ?string
|
||||
}
|
||||
*/
|
||||
|
||||
var stylesInDom = {/*
|
||||
[id: number]: {
|
||||
id: number,
|
||||
refs: number,
|
||||
parts: Array<(obj?: StyleObjectPart) => void>
|
||||
}
|
||||
*/}
|
||||
|
||||
var head = hasDocument && (document.head || document.getElementsByTagName('head')[0])
|
||||
var singletonElement = null
|
||||
var singletonCounter = 0
|
||||
var isProduction = false
|
||||
var noop = function () {}
|
||||
var options = null
|
||||
var ssrIdKey = 'data-vue-ssr-id'
|
||||
|
||||
// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
|
||||
// tags it will allow on a page
|
||||
var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\b/.test(navigator.userAgent.toLowerCase())
|
||||
|
||||
module.exports = function (parentId, list, _isProduction, _options) {
|
||||
isProduction = _isProduction
|
||||
|
||||
options = _options || {}
|
||||
|
||||
var styles = listToStyles(parentId, list)
|
||||
addStylesToDom(styles)
|
||||
|
||||
return function update (newList) {
|
||||
var mayRemove = []
|
||||
for (var i = 0; i < styles.length; i++) {
|
||||
var item = styles[i]
|
||||
var domStyle = stylesInDom[item.id]
|
||||
domStyle.refs--
|
||||
mayRemove.push(domStyle)
|
||||
}
|
||||
if (newList) {
|
||||
styles = listToStyles(parentId, newList)
|
||||
addStylesToDom(styles)
|
||||
} else {
|
||||
styles = []
|
||||
}
|
||||
for (var i = 0; i < mayRemove.length; i++) {
|
||||
var domStyle = mayRemove[i]
|
||||
if (domStyle.refs === 0) {
|
||||
for (var j = 0; j < domStyle.parts.length; j++) {
|
||||
domStyle.parts[j]()
|
||||
}
|
||||
delete stylesInDom[domStyle.id]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addStylesToDom (styles /* Array<StyleObject> */) {
|
||||
for (var i = 0; i < styles.length; i++) {
|
||||
var item = styles[i]
|
||||
var domStyle = stylesInDom[item.id]
|
||||
if (domStyle) {
|
||||
domStyle.refs++
|
||||
for (var j = 0; j < domStyle.parts.length; j++) {
|
||||
domStyle.parts[j](item.parts[j])
|
||||
}
|
||||
for (; j < item.parts.length; j++) {
|
||||
domStyle.parts.push(addStyle(item.parts[j]))
|
||||
}
|
||||
if (domStyle.parts.length > item.parts.length) {
|
||||
domStyle.parts.length = item.parts.length
|
||||
}
|
||||
} else {
|
||||
var parts = []
|
||||
for (var j = 0; j < item.parts.length; j++) {
|
||||
parts.push(addStyle(item.parts[j]))
|
||||
}
|
||||
stylesInDom[item.id] = { id: item.id, refs: 1, parts: parts }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createStyleElement () {
|
||||
var styleElement = document.createElement('style')
|
||||
styleElement.type = 'text/css'
|
||||
head.appendChild(styleElement)
|
||||
return styleElement
|
||||
}
|
||||
|
||||
function addStyle (obj /* StyleObjectPart */) {
|
||||
var update, remove
|
||||
var styleElement = document.querySelector('style[' + ssrIdKey + '~="' + obj.id + '"]')
|
||||
|
||||
if (styleElement) {
|
||||
if (isProduction) {
|
||||
// has SSR styles and in production mode.
|
||||
// simply do nothing.
|
||||
return noop
|
||||
} else {
|
||||
// has SSR styles but in dev mode.
|
||||
// for some reason Chrome can't handle source map in server-rendered
|
||||
// style tags - source maps in <style> only works if the style tag is
|
||||
// created and inserted dynamically. So we remove the server rendered
|
||||
// styles and inject new ones.
|
||||
styleElement.parentNode.removeChild(styleElement)
|
||||
}
|
||||
}
|
||||
|
||||
if (isOldIE) {
|
||||
// use singleton mode for IE9.
|
||||
var styleIndex = singletonCounter++
|
||||
styleElement = singletonElement || (singletonElement = createStyleElement())
|
||||
update = applyToSingletonTag.bind(null, styleElement, styleIndex, false)
|
||||
remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true)
|
||||
} else {
|
||||
// use multi-style-tag mode in all other cases
|
||||
styleElement = createStyleElement()
|
||||
update = applyToTag.bind(null, styleElement)
|
||||
remove = function () {
|
||||
styleElement.parentNode.removeChild(styleElement)
|
||||
}
|
||||
}
|
||||
|
||||
update(obj)
|
||||
|
||||
return function updateStyle (newObj /* StyleObjectPart */) {
|
||||
if (newObj) {
|
||||
if (newObj.css === obj.css &&
|
||||
newObj.media === obj.media &&
|
||||
newObj.sourceMap === obj.sourceMap) {
|
||||
return
|
||||
}
|
||||
update(obj = newObj)
|
||||
} else {
|
||||
remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var replaceText = (function () {
|
||||
var textStore = []
|
||||
|
||||
return function (index, replacement) {
|
||||
textStore[index] = replacement
|
||||
return textStore.filter(Boolean).join('\n')
|
||||
}
|
||||
})()
|
||||
|
||||
function applyToSingletonTag (styleElement, index, remove, obj) {
|
||||
var css = remove ? '' : obj.css
|
||||
|
||||
if (styleElement.styleSheet) {
|
||||
styleElement.styleSheet.cssText = replaceText(index, css)
|
||||
} else {
|
||||
var cssNode = document.createTextNode(css)
|
||||
var childNodes = styleElement.childNodes
|
||||
if (childNodes[index]) styleElement.removeChild(childNodes[index])
|
||||
if (childNodes.length) {
|
||||
styleElement.insertBefore(cssNode, childNodes[index])
|
||||
} else {
|
||||
styleElement.appendChild(cssNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyToTag (styleElement, obj) {
|
||||
var css = obj.css
|
||||
var media = obj.media
|
||||
var sourceMap = obj.sourceMap
|
||||
|
||||
if (media) {
|
||||
styleElement.setAttribute('media', media)
|
||||
}
|
||||
if (options.ssrId) {
|
||||
styleElement.setAttribute(ssrIdKey, obj.id)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
var listToStyles = require('./listToStyles')
|
||||
|
||||
module.exports = function (parentId, list, isProduction, context) {
|
||||
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
|
||||
context = __VUE_SSR_CONTEXT__
|
||||
}
|
||||
if (context) {
|
||||
if (!context.hasOwnProperty('styles')) {
|
||||
Object.defineProperty(context, 'styles', {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return renderStyles(context._styles)
|
||||
}
|
||||
})
|
||||
// expose renderStyles for vue-server-renderer (vuejs/#6353)
|
||||
context._renderStyles = renderStyles
|
||||
}
|
||||
|
||||
var styles = context._styles || (context._styles = {})
|
||||
list = listToStyles(parentId, list)
|
||||
if (isProduction) {
|
||||
addStyleProd(styles, list)
|
||||
} else {
|
||||
addStyleDev(styles, list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In production, render as few style tags as possible.
|
||||
// (mostly because IE9 has a limit on number of style tags)
|
||||
function addStyleProd (styles, list) {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var parts = list[i].parts
|
||||
for (var j = 0; j < parts.length; j++) {
|
||||
var part = parts[j]
|
||||
// group style tags by media types.
|
||||
var id = part.media || 'default'
|
||||
var style = styles[id]
|
||||
if (style) {
|
||||
if (style.ids.indexOf(part.id) < 0) {
|
||||
style.ids.push(part.id)
|
||||
style.css += '\n' + part.css
|
||||
}
|
||||
} else {
|
||||
styles[id] = {
|
||||
ids: [part.id],
|
||||
css: part.css,
|
||||
media: part.media
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In dev we use individual style tag for each module for hot-reload
|
||||
// and source maps.
|
||||
function addStyleDev (styles, list) {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var parts = list[i].parts
|
||||
for (var j = 0; j < parts.length; j++) {
|
||||
var part = parts[j]
|
||||
styles[part.id] = {
|
||||
ids: [part.id],
|
||||
css: part.css,
|
||||
media: part.media
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderStyles (styles) {
|
||||
var css = ''
|
||||
for (var key in styles) {
|
||||
var style = styles[key]
|
||||
css += '<style data-vue-ssr-id="' + style.ids.join(' ') + '"' +
|
||||
(style.media ? ( ' media="' + style.media + '"' ) : '') + '>' +
|
||||
style.css + '</style>'
|
||||
}
|
||||
return css
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Translates the list format produced by css-loader into something
|
||||
* easier to manipulate.
|
||||
*/
|
||||
module.exports = function listToStyles (parentId, list) {
|
||||
var styles = []
|
||||
var newStyles = {}
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var item = list[i]
|
||||
var id = item[0]
|
||||
var css = item[1]
|
||||
var media = item[2]
|
||||
var sourceMap = item[3]
|
||||
var part = {
|
||||
id: parentId + ':' + i,
|
||||
css: css,
|
||||
media: media,
|
||||
sourceMap: sourceMap
|
||||
}
|
||||
if (!newStyles[id]) {
|
||||
styles.push(newStyles[id] = { id: id, parts: [part] })
|
||||
} else {
|
||||
newStyles[id].parts.push(part)
|
||||
}
|
||||
}
|
||||
return styles
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "vue-style-loader",
|
||||
"version": "3.1.2",
|
||||
"author": "Evan You",
|
||||
"description": "Vue.js style loader module for webpack",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:vuejs/vue-style-loader.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"hash-sum": "^1.0.2",
|
||||
"loader-utils": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^18.1.0"
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
const addStylesClient = require('../lib/addStylesClient')
|
||||
const addStylesServer = require('../lib/addStylesServer')
|
||||
|
||||
const mockedList = [
|
||||
[1, 'h1 { color: red; }', ''],
|
||||
[1, 'p { color: green; }', ''],
|
||||
[2, 'span { color: blue; }', ''],
|
||||
[2, 'span { color: blue; }', 'print']
|
||||
]
|
||||
|
||||
test('addStylesClient (dev)', () => {
|
||||
const update = addStylesClient('foo', mockedList, false)
|
||||
assertStylesMatch(mockedList)
|
||||
const mockedList2 = mockedList.slice(1, 3)
|
||||
update(mockedList2)
|
||||
assertStylesMatch(mockedList2)
|
||||
update()
|
||||
expect(document.querySelectorAll('style').length).toBe(0)
|
||||
})
|
||||
|
||||
test('addStylesClient (prod)', () => {
|
||||
const update = addStylesClient('foo', mockedList, true)
|
||||
assertStylesMatch(mockedList)
|
||||
const mockedList2 = mockedList.slice(2)
|
||||
update(mockedList2)
|
||||
assertStylesMatch(mockedList2)
|
||||
update()
|
||||
expect(document.querySelectorAll('style').length).toBe(0)
|
||||
})
|
||||
|
||||
test('addStylesClient (dev + ssr)', () => {
|
||||
mockSSRTags(mockedList, 'foo')
|
||||
const update = addStylesClient('foo', mockedList, false)
|
||||
assertStylesMatch(mockedList)
|
||||
update()
|
||||
expect(document.querySelectorAll('style').length).toBe(0)
|
||||
})
|
||||
|
||||
test('addStylesClient (prod + ssr)', () => {
|
||||
mockProdSSRTags(mockedList, 'foo')
|
||||
const update = addStylesClient('foo', mockedList, true)
|
||||
expect(document.querySelectorAll('style').length).toBe(1)
|
||||
})
|
||||
|
||||
test('addStylesServer (dev)', () => {
|
||||
const context = global.__VUE_SSR_CONTEXT__ = {}
|
||||
addStylesServer('foo', mockedList, false)
|
||||
expect(context.styles).toBe(
|
||||
`<style data-vue-ssr-id="foo:0">h1 { color: red; }</style>` +
|
||||
`<style data-vue-ssr-id="foo:1">p { color: green; }</style>` +
|
||||
`<style data-vue-ssr-id="foo:2">span { color: blue; }</style>` +
|
||||
`<style data-vue-ssr-id="foo:3" media="print">span { color: blue; }</style>`
|
||||
)
|
||||
})
|
||||
|
||||
test('addStylesServer (prod)', () => {
|
||||
const context = global.__VUE_SSR_CONTEXT__ = {}
|
||||
addStylesServer('foo', mockedList, true)
|
||||
expect(context.styles).toBe(
|
||||
`<style data-vue-ssr-id="foo:0 foo:1 foo:2">` +
|
||||
`h1 { color: red; }\np { color: green; }\nspan { color: blue; }` +
|
||||
`</style>` +
|
||||
`<style data-vue-ssr-id="foo:3" media="print">span { color: blue; }</style>`
|
||||
)
|
||||
})
|
||||
|
||||
// --- helpers ---
|
||||
|
||||
function assertStylesMatch (list) {
|
||||
const styles = document.querySelectorAll('style')
|
||||
expect(styles.length).toBe(list.length)
|
||||
;[].forEach.call(styles, (style, i) => {
|
||||
expect(style.textContent.indexOf(list[i][1]) > -1).toBe(true)
|
||||
})
|
||||
}
|
||||
|
||||
function mockSSRTags (list, parentId) {
|
||||
list.forEach((item, i) => {
|
||||
const style = document.createElement('style')
|
||||
style.setAttribute('data-vue-ssr-id', `${parentId}:${i}`)
|
||||
style.textContent = item[1]
|
||||
if (item[2]) {
|
||||
style.setAttribute('media', item[2])
|
||||
}
|
||||
document.head.appendChild(style)
|
||||
})
|
||||
}
|
||||
|
||||
function mockProdSSRTags (list, parentId) {
|
||||
const style = document.createElement('style')
|
||||
style.setAttribute('data-vue-ssr-id', list.map((item, i) => `${parentId}:${i}`).join(' '))
|
||||
style.textContent = list.map(item => item[1]).join('\n')
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
Reference in New Issue
Block a user