Skip to content

Commit

Permalink
feat: support rules with oneOf
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Mar 20, 2018
1 parent 58239f6 commit c3b379d
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 10 deletions.
23 changes: 15 additions & 8 deletions lib/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,6 @@ module.exports = class VueLoaderPlugin {
}

function cloneRule (rule, normalizedRule, vueUse) {
if (rule.oneOf) {
return Object.assign({}, rule, {
oneOf: rule.oneOf.map((r, i) => cloneRule(r, normalizedRule.oneOf[i]))
})
}

// Assuming `test` and `resourceQuery` tests are executed in series and
// synchronously (which is true based on RuleSet's implementation), we can
// save the current resource being matched from `test` so that we can access
Expand All @@ -114,18 +108,31 @@ function cloneRule (rule, normalizedRule, vueUse) {
if (parsed.lang == null) {
return false
}
return normalizedRule.resource(`${currentResource}.${parsed.lang}`)
const { resource, resourceQuery } = normalizedRule
if (resource && !resource(`${currentResource}.${parsed.lang}`)) {
return false
}
if (resourceQuery && !resourceQuery(query)) {
return false
}
return true
},
use: [
...(normalizedRule.use || []).map(cleanUse),
...vueUse
...rule.oneOf ? [] : vueUse
]
})

// delete shorthand since we have normalized use
delete res.loader
delete res.options

if (rule.oneOf) {
res.oneOf = rule.oneOf.map((r, i) => {
return cloneRule(r, normalizedRule.oneOf[i], vueUse)
})
}

return res
}

Expand Down
3 changes: 2 additions & 1 deletion lib/styleInjection.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ module.exports = function genStyleInjectionCode (
// make sure to only pass id when necessary so that we don't inject
// duplicate tags when multiple components import the same css file
const scopedQuery = style.scoped ? `&scoped&id=${id}` : ``
const query = `?vue&type=style&index=${i}${langQuery}${scopedQuery}`
const moduleQuery = style.module ? `&cssModules` : ``
const query = `?vue&type=style&index=${i}${langQuery}${scopedQuery}${moduleQuery}`
return stringifyRequest(src + query)
}

Expand Down
54 changes: 54 additions & 0 deletions test/advanced.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,60 @@ test('extract CSS', done => {
})
})

test('support rules with oneOf', async () => {
const run = (entry, assert) => new Promise((resolve, reject) => {
mockBundleAndRun({
entry,
modify: config => {
config.module.rules = [
{ test: /\.vue$/, loader: 'vue-loader' },
{
test: /\.css$/,
use: 'vue-style-loader',
oneOf: [
{
resourceQuery: /cssModules/,
use: [
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[local]_[hash:base64:5]'
}
}
]
},
{
use: ['css-loader']
}
]
}
]
}
}, res => {
const { jsdomError, bundleError } = res
if (jsdomError) return reject(jsdomError)
if (bundleError) return reject(bundleError)
assert(res)
resolve()
})
})

await run('basic.vue', ({ window }) => {
let style = window.document.querySelector('style').textContent
style = normalizeNewline(style)
expect(style).toContain('comp-a h2 {\n color: #f00;\n}')
})

await run('css-modules-simple.vue', ({ window, instance }) => {
const className = instance.$style.red
expect(className).toMatch(/^red_\w{5}/)
let style = window.document.querySelector('style').textContent
style = normalizeNewline(style)
expect(style).toContain('.' + className + ' {\n color: red;\n}')
})
})

// TODO
// test('multiple rule definitions', done => {
// mockBundleAndRun({
Expand Down
9 changes: 9 additions & 0 deletions test/fixtures/css-modules-simple.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<style module>
.red {
color: red;
}
</style>

<script>
export default {}
</script>
2 changes: 1 addition & 1 deletion test/style.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ test('postcss', done => {
})
})

test('css-modules', async () => {
test('CSS Modules', async () => {
function testWithIdent (localIdentName, regexToMatch) {
return new Promise((resolve, reject) => {
const baseLoaders = [
Expand Down

0 comments on commit c3b379d

Please sign in to comment.