Commit cda1ec35 authored by Evan You's avatar Evan You

feat: expose all block attrs via query

parent 6b73b74d
...@@ -128,7 +128,7 @@ The good news is that you can now configure `localIdentName` in one place: ...@@ -128,7 +128,7 @@ The good news is that you can now configure `localIdentName` in one place:
} }
``` ```
If you only want to use CSS Modules in some of your Vue components, you can use a `oneOf` rule and check for the `cssModules` string in resourceQuery: If you only want to use CSS Modules in some of your Vue components, you can use a `oneOf` rule and check for the `module` string in resourceQuery:
``` js ``` js
{ {
...@@ -136,7 +136,7 @@ If you only want to use CSS Modules in some of your Vue components, you can use ...@@ -136,7 +136,7 @@ If you only want to use CSS Modules in some of your Vue components, you can use
oneOf: [ oneOf: [
// this matches <style module> // this matches <style module>
{ {
resourceQuery: /cssModules/, resourceQuery: /module/,
use: [ use: [
'vue-style-loader', 'vue-style-loader',
{ {
......
module.exports = function genCustomBlocksCode () { // const { attrsToQuery } = require('./utils')
module.exports = function genCustomBlocksCode (
blocks,
resourcePath
) {
// blocks.map((block, i) => {
// const src = block.src || resourcePath
// const langQuery = getLangQuery(block)
// })
} }
...@@ -5,8 +5,10 @@ const qs = require('querystring') ...@@ -5,8 +5,10 @@ const qs = require('querystring')
const plugin = require('./plugin') const plugin = require('./plugin')
const selectBlock = require('./select') const selectBlock = require('./select')
const loaderUtils = require('loader-utils') const loaderUtils = require('loader-utils')
const { attrsToQuery } = require('./utils')
const genStylesCode = require('./styles')
const { genHotReloadCode } = require('./hotReload') const { genHotReloadCode } = require('./hotReload')
const genStyleInjectionCode = require('./styleInjection') const genCustomBlocksCode = require('./customBlocks')
const componentNormalizerPath = require.resolve('./runtime/componentNormalizer') const componentNormalizerPath = require.resolve('./runtime/componentNormalizer')
module.exports = function (source) { module.exports = function (source) {
...@@ -59,9 +61,7 @@ module.exports = function (source) { ...@@ -59,9 +61,7 @@ module.exports = function (source) {
// feature information // feature information
const hasScoped = descriptor.styles.some(s => s.scoped) const hasScoped = descriptor.styles.some(s => s.scoped)
const templateAttrs = (descriptor.template && descriptor.template.attrs) || {} const hasFunctional = descriptor.template && descriptor.template.attrs.functional
const hasFunctional = templateAttrs.functional
const hasComment = templateAttrs.comments
const needsHotReload = ( const needsHotReload = (
!isServer && !isServer &&
!isProduction && !isProduction &&
...@@ -73,12 +73,10 @@ module.exports = function (source) { ...@@ -73,12 +73,10 @@ module.exports = function (source) {
let templateImport = `var render, staticRenderFns` let templateImport = `var render, staticRenderFns`
if (descriptor.template) { if (descriptor.template) {
const src = descriptor.template.src || resourcePath const src = descriptor.template.src || resourcePath
const langQuery = getLangQuery(descriptor.template)
const idQuery = `&id=${id}` const idQuery = `&id=${id}`
const scopedQuery = hasScoped ? `&scoped` : `` const scopedQuery = hasScoped ? `&scoped=true` : ``
const fnQuery = hasFunctional ? `&functional` : `` const attrsQuery = attrsToQuery(descriptor.template.attrs)
const commentQuery = hasComment ? `&comment` : `` const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}`
const query = `?vue&type=template${scopedQuery}${idQuery}${langQuery}${fnQuery}${commentQuery}`
const request = stringifyRequest(src + query) const request = stringifyRequest(src + query)
templateImport = `import { render, staticRenderFns } from ${request}` templateImport = `import { render, staticRenderFns } from ${request}`
} }
...@@ -87,8 +85,8 @@ module.exports = function (source) { ...@@ -87,8 +85,8 @@ module.exports = function (source) {
let scriptImport = `var script = {}` let scriptImport = `var script = {}`
if (descriptor.script) { if (descriptor.script) {
const src = descriptor.script.src || resourcePath const src = descriptor.script.src || resourcePath
const langQuery = getLangQuery(descriptor.script, 'js') const attrsQuery = attrsToQuery(descriptor.script.attrs, 'js')
const query = `?vue&type=script${langQuery}` const query = `?vue&type=script${attrsQuery}`
const request = stringifyRequest(src + query) const request = stringifyRequest(src + query)
scriptImport = ( scriptImport = (
`import script from ${request}\n` + `import script from ${request}\n` +
...@@ -97,15 +95,14 @@ module.exports = function (source) { ...@@ -97,15 +95,14 @@ module.exports = function (source) {
} }
// styles // styles
let styleInjectionCode = `` let stylesCode = ``
if (descriptor.styles.length) { if (descriptor.styles.length) {
styleInjectionCode = genStyleInjectionCode( stylesCode = genStylesCode(
loaderContext, loaderContext,
descriptor.styles, descriptor.styles,
id, id,
resourcePath, resourcePath,
stringifyRequest, stringifyRequest,
getLangQuery,
needsHotReload, needsHotReload,
isServer || isShadow // needs explicit injection? isServer || isShadow // needs explicit injection?
) )
...@@ -114,14 +111,14 @@ module.exports = function (source) { ...@@ -114,14 +111,14 @@ module.exports = function (source) {
let code = ` let code = `
${templateImport} ${templateImport}
${scriptImport} ${scriptImport}
${styleInjectionCode} ${stylesCode}
import normalizer from ${stringifyRequest(`!${componentNormalizerPath}`)} import normalizer from ${stringifyRequest(`!${componentNormalizerPath}`)}
var component = normalizer( var component = normalizer(
script, script,
render, render,
staticRenderFns, staticRenderFns,
${hasFunctional ? `true` : `false`}, ${hasFunctional ? `true` : `false`},
${/injectStyles/.test(styleInjectionCode) ? `injectStyles` : `null`}, ${/injectStyles/.test(stylesCode) ? `injectStyles` : `null`},
${hasScoped ? JSON.stringify(id) : `null`}, ${hasScoped ? JSON.stringify(id) : `null`},
${isServer ? JSON.stringify(hash(request)) : `null`} ${isServer ? JSON.stringify(hash(request)) : `null`}
${isShadow ? `,true` : ``} ${isShadow ? `,true` : ``}
...@@ -129,7 +126,7 @@ var component = normalizer( ...@@ -129,7 +126,7 @@ var component = normalizer(
`.trim() `.trim()
if (descriptor.customBlocks && descriptor.customBlocks.length) { if (descriptor.customBlocks && descriptor.customBlocks.length) {
// TODO custom blocks code += genCustomBlocksCode(descriptor.customBlocks)
} }
// Expose filename. This is used by the devtools and vue runtime warnings. // Expose filename. This is used by the devtools and vue runtime warnings.
...@@ -146,9 +143,4 @@ var component = normalizer( ...@@ -146,9 +143,4 @@ var component = normalizer(
return code return code
} }
function getLangQuery (block, fallback) {
const lang = block.lang || fallback
return lang ? `&lang=${lang}` : ``
}
module.exports.VueLoaderPlugin = plugin module.exports.VueLoaderPlugin = plugin
...@@ -13,7 +13,7 @@ module.exports = function (source, map) { ...@@ -13,7 +13,7 @@ module.exports = function (source, map) {
const id = `data-v-${query.id}` const id = `data-v-${query.id}`
const plugins = [trim()] const plugins = [trim()]
if (query.scoped != null) { if (query.scoped) {
plugins.push(scoped({ id })) plugins.push(scoped({ id }))
} }
......
const { attrsToQuery } = require('./utils')
const hotReloadAPIPath = require.resolve('vue-hot-reload-api') const hotReloadAPIPath = require.resolve('vue-hot-reload-api')
module.exports = function genStyleInjectionCode ( module.exports = function genStyleInjectionCode (
...@@ -6,7 +7,6 @@ module.exports = function genStyleInjectionCode ( ...@@ -6,7 +7,6 @@ module.exports = function genStyleInjectionCode (
id, id,
resourcePath, resourcePath,
stringifyRequest, stringifyRequest,
getLangQuery,
needsHotReload, needsHotReload,
needsExplicitInjection needsExplicitInjection
) { ) {
...@@ -19,12 +19,11 @@ module.exports = function genStyleInjectionCode ( ...@@ -19,12 +19,11 @@ module.exports = function genStyleInjectionCode (
function genStyleRequest (style, i) { function genStyleRequest (style, i) {
const src = style.src || resourcePath const src = style.src || resourcePath
const langQuery = getLangQuery(style, 'css') const attrsQuery = attrsToQuery(style.attrs, 'css')
// make sure to only pass id when necessary so that we don't inject // make sure to only pass id when necessary so that we don't inject
// duplicate tags when multiple components import the same css file // duplicate tags when multiple components import the same css file
const scopedQuery = style.scoped ? `&scoped&id=${id}` : `` const idQuery = style.scoped ? `&id=${id}` : ``
const moduleQuery = style.module ? `&cssModules` : `` const query = `?vue&type=style&index=${i}${idQuery}${attrsQuery}`
const query = `?vue&type=style&index=${i}${langQuery}${scopedQuery}${moduleQuery}`
return stringifyRequest(src + query) return stringifyRequest(src + query)
} }
......
...@@ -64,15 +64,14 @@ function actuallyCompile (sourceTemplate, options, loaderContext, query) { ...@@ -64,15 +64,14 @@ function actuallyCompile (sourceTemplate, options, loaderContext, query) {
const isProduction = loaderContext.minimize || process.env.NODE_ENV === 'production' const isProduction = loaderContext.minimize || process.env.NODE_ENV === 'production'
const needsHotReload = !isServer && !isProduction && options.hotReload !== false const needsHotReload = !isServer && !isProduction && options.hotReload !== false
const defaultModules = [transformAssetUrl(options.transformAssetUrl), transformSrcset()] const defaultModules = [transformAssetUrl(options.transformAssetUrl), transformSrcset()]
const hasComment = query.comment != null const hasFunctionalTemplate = query.functional
const hasFunctionalTemplate = query.functional != null
const userCompilerOptions = options.compilerOptions || {} const userCompilerOptions = options.compilerOptions || {}
const compilerOptions = Object.assign({}, userCompilerOptions, { const compilerOptions = Object.assign({}, userCompilerOptions, {
scopeId: query.scoped != null ? `data-v-${id}` : null, scopeId: query.scoped ? `data-v-${id}` : null,
modules: defaultModules.concat(userCompilerOptions.modules || []), modules: defaultModules.concat(userCompilerOptions.modules || []),
comments: hasComment comments: query.comments
}) })
// support user compiler // support user compiler
......
const qs = require('querystring')
exports.attrsToQuery = (attrs, langFallback) => {
let query = ``
for (const name in attrs) {
const value = attrs[name]
if (name !== 'src') {
query += `&${qs.escape(name)}=${value ? qs.escape(value) : ``}`
}
}
if (langFallback && !(`lang` in attrs)) {
query += `&lang=${langFallback}`
}
return query
}
...@@ -117,7 +117,7 @@ test('support rules with oneOf', async () => { ...@@ -117,7 +117,7 @@ test('support rules with oneOf', async () => {
use: 'vue-style-loader', use: 'vue-style-loader',
oneOf: [ oneOf: [
{ {
resourceQuery: /cssModules/, resourceQuery: /module/,
use: [ use: [
{ {
loader: 'css-loader', loader: 'css-loader',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment