aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue-loader/lib/loaders
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/vue-loader/lib/loaders')
-rw-r--r--node_modules/vue-loader/lib/loaders/pitcher.js144
-rw-r--r--node_modules/vue-loader/lib/loaders/stylePostLoader.js23
-rw-r--r--node_modules/vue-loader/lib/loaders/templateLoader.js71
3 files changed, 238 insertions, 0 deletions
diff --git a/node_modules/vue-loader/lib/loaders/pitcher.js b/node_modules/vue-loader/lib/loaders/pitcher.js
new file mode 100644
index 00000000..0bc77046
--- /dev/null
+++ b/node_modules/vue-loader/lib/loaders/pitcher.js
@@ -0,0 +1,144 @@
+const qs = require('querystring')
+const loaderUtils = require('loader-utils')
+const hash = require('hash-sum')
+const selfPath = require.resolve('../index')
+const templateLoaderPath = require.resolve('./templateLoader')
+const stylePostLoaderPath = require.resolve('./stylePostLoader')
+
+const isESLintLoader = l => /(\/|\\|@)eslint-loader/.test(l.path)
+const isNullLoader = l => /(\/|\\|@)null-loader/.test(l.path)
+const isCSSLoader = l => /(\/|\\|@)css-loader/.test(l.path)
+const isPitcher = l => l.path !== __filename
+
+const dedupeESLintLoader = loaders => {
+ const res = []
+ let seen = false
+ loaders.forEach(l => {
+ if (!isESLintLoader(l)) {
+ res.push(l)
+ } else if (!seen) {
+ seen = true
+ res.push(l)
+ }
+ })
+ return res
+}
+
+module.exports = code => code
+
+// This pitching loader is responsible for intercepting all vue block requests
+// and transform it into appropriate requests.
+module.exports.pitch = function (remainingRequest) {
+ const options = loaderUtils.getOptions(this)
+ const { cacheDirectory, cacheIdentifier } = options
+ const query = qs.parse(this.resourceQuery.slice(1))
+
+ let loaders = this.loaders
+
+ // if this is a language block request, eslint-loader may get matched
+ // multiple times
+ if (query.type) {
+ // if this is an inline block, since the whole file itself is being linted,
+ // remove eslint-loader to avoid duplicate linting.
+ if (/\.vue$/.test(this.resourcePath)) {
+ loaders = loaders.filter(l => !isESLintLoader(l))
+ } else {
+ // This is a src import. Just make sure there's not more than 1 instance
+ // of eslint present.
+ loaders = dedupeESLintLoader(loaders)
+ }
+ }
+
+ // remove self
+ loaders = loaders.filter(isPitcher)
+
+ // do not inject if user uses null-loader to void the type (#1239)
+ if (loaders.some(isNullLoader)) {
+ return
+ }
+
+ const genRequest = loaders => {
+ // Important: dedupe since both the original rule
+ // and the cloned rule would match a source import request.
+ // also make sure to dedupe based on loader path.
+ // assumes you'd probably never want to apply the same loader on the same
+ // file twice.
+ // Exception: in Vue CLI we do need two instances of postcss-loader
+ // for user config and inline minification. So we need to dedupe baesd on
+ // path AND query to be safe.
+ const seen = new Map()
+ const loaderStrings = []
+
+ loaders.forEach(loader => {
+ const identifier = typeof loader === 'string'
+ ? loader
+ : (loader.path + loader.query)
+ const request = typeof loader === 'string' ? loader : loader.request
+ if (!seen.has(identifier)) {
+ seen.set(identifier, true)
+ // loader.request contains both the resolved loader path and its options
+ // query (e.g. ??ref-0)
+ loaderStrings.push(request)
+ }
+ })
+
+ return loaderUtils.stringifyRequest(this, '-!' + [
+ ...loaderStrings,
+ this.resourcePath + this.resourceQuery
+ ].join('!'))
+ }
+
+ // Inject style-post-loader before css-loader for scoped CSS and trimming
+ if (query.type === `style`) {
+ const cssLoaderIndex = loaders.findIndex(isCSSLoader)
+ if (cssLoaderIndex > -1) {
+ const afterLoaders = loaders.slice(0, cssLoaderIndex + 1)
+ const beforeLoaders = loaders.slice(cssLoaderIndex + 1)
+ const request = genRequest([
+ ...afterLoaders,
+ stylePostLoaderPath,
+ ...beforeLoaders
+ ])
+ // console.log(request)
+ return `import mod from ${request}; export default mod; export * from ${request}`
+ }
+ }
+
+ // for templates: inject the template compiler & optional cache
+ if (query.type === `template`) {
+ const path = require('path')
+ const cacheLoader = cacheDirectory && cacheIdentifier
+ ? [`cache-loader?${JSON.stringify({
+ // For some reason, webpack fails to generate consistent hash if we
+ // use absolute paths here, even though the path is only used in a
+ // comment. For now we have to ensure cacheDirectory is a relative path.
+ cacheDirectory: path.isAbsolute(cacheDirectory)
+ ? path.relative(process.cwd(), cacheDirectory)
+ : cacheDirectory,
+ cacheIdentifier: hash(cacheIdentifier) + '-vue-loader-template'
+ })}`]
+ : []
+ const request = genRequest([
+ ...cacheLoader,
+ templateLoaderPath + `??vue-loader-options`,
+ ...loaders
+ ])
+ // console.log(request)
+ // the template compiler uses esm exports
+ return `export * from ${request}`
+ }
+
+ // if a custom block has no other matching loader other than vue-loader itself,
+ // we should ignore it
+ if (query.type === `custom` &&
+ loaders.length === 1 &&
+ loaders[0].path === selfPath) {
+ return ``
+ }
+
+ // When the user defines a rule that has only resourceQuery but no test,
+ // both that rule and the cloned rule will match, resulting in duplicated
+ // loaders. Therefore it is necessary to perform a dedupe here.
+ const request = genRequest(loaders)
+ return `import mod from ${request}; export default mod; export * from ${request}`
+}
diff --git a/node_modules/vue-loader/lib/loaders/stylePostLoader.js b/node_modules/vue-loader/lib/loaders/stylePostLoader.js
new file mode 100644
index 00000000..de8d09eb
--- /dev/null
+++ b/node_modules/vue-loader/lib/loaders/stylePostLoader.js
@@ -0,0 +1,23 @@
+const qs = require('querystring')
+const { compileStyle } = require('@vue/component-compiler-utils')
+
+// This is a post loader that handles scoped CSS transforms.
+// Injected right before css-loader by the global pitcher (../pitch.js)
+// for any <style scoped> selection requests initiated from within vue files.
+module.exports = function (source, inMap) {
+ const query = qs.parse(this.resourceQuery.slice(1))
+ const { code, map, errors } = compileStyle({
+ source,
+ filename: this.resourcePath,
+ id: `data-v-${query.id}`,
+ map: inMap,
+ scoped: !!query.scoped,
+ trim: true
+ })
+
+ if (errors.length) {
+ this.callback(errors[0])
+ } else {
+ this.callback(null, code, map)
+ }
+}
diff --git a/node_modules/vue-loader/lib/loaders/templateLoader.js b/node_modules/vue-loader/lib/loaders/templateLoader.js
new file mode 100644
index 00000000..d5b18741
--- /dev/null
+++ b/node_modules/vue-loader/lib/loaders/templateLoader.js
@@ -0,0 +1,71 @@
+const qs = require('querystring')
+const loaderUtils = require('loader-utils')
+const { compileTemplate } = require('@vue/component-compiler-utils')
+
+// Loader that compiles raw template into JavaScript functions.
+// This is injected by the global pitcher (../pitch) for template
+// selection requests initiated from vue files.
+module.exports = function (source) {
+ const loaderContext = this
+ const query = qs.parse(this.resourceQuery.slice(1))
+
+ // although this is not the main vue-loader, we can get access to the same
+ // vue-loader options because we've set an ident in the plugin and used that
+ // ident to create the request for this loader in the pitcher.
+ const options = loaderUtils.getOptions(loaderContext) || {}
+ const { id } = query
+ const isServer = loaderContext.target === 'node'
+ const isProduction = loaderContext.minimize || process.env.NODE_ENV === 'production'
+ const isFunctional = query.functional
+
+ // allow using custom compiler via options
+ const compiler = options.compiler || require('vue-template-compiler')
+ const compilerOptions = Object.assign({}, options.compilerOptions, {
+ scopeId: query.scoped ? `data-v-${id}` : null,
+ comments: query.comments
+ })
+
+ // for vue-component-compiler
+ const finalOptions = {
+ source,
+ filename: this.resourcePath,
+ compiler,
+ compilerOptions,
+ // allow customizing behavior of vue-template-es2015-compiler
+ transpileOptions: options.transpileOptions,
+ transformAssetUrls: options.transformAssetUrls || true,
+ isProduction,
+ isFunctional,
+ optimizeSSR: isServer && options.optimizeSSR !== false
+ }
+
+ const compiled = compileTemplate(finalOptions)
+
+ // tips
+ if (compiled.tips && compiled.tips.length) {
+ compiled.tips.forEach(tip => {
+ loaderContext.emitWarning(tip)
+ })
+ }
+
+ // errors
+ if (compiled.errors && compiled.errors.length) {
+ loaderContext.emitError(
+ `\n Error compiling template:\n${pad(compiled.source)}\n` +
+ compiled.errors.map(e => ` - ${e}`).join('\n') +
+ '\n'
+ )
+ }
+
+ const { code } = compiled
+
+ // finish with ESM exports
+ return code + `\nexport { render, staticRenderFns }`
+}
+
+function pad (source) {
+ return source
+ .split(/\r?\n/)
+ .map(line => ` ${line}`)
+ .join('\n')
+}