aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue-loader/lib/plugin.js
diff options
context:
space:
mode:
authorruki <waruqi@gmail.com>2018-11-08 00:38:48 +0800
committerruki <waruqi@gmail.com>2018-11-07 21:53:09 +0800
commit26105034da4fcce7ac883c899d781f016559310d (patch)
treec459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/vue-loader/lib/plugin.js
parent2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff)
downloadxmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz
xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip
switch to vuepress
Diffstat (limited to 'node_modules/vue-loader/lib/plugin.js')
-rw-r--r--node_modules/vue-loader/lib/plugin.js156
1 files changed, 156 insertions, 0 deletions
diff --git a/node_modules/vue-loader/lib/plugin.js b/node_modules/vue-loader/lib/plugin.js
new file mode 100644
index 00000000..be2019ee
--- /dev/null
+++ b/node_modules/vue-loader/lib/plugin.js
@@ -0,0 +1,156 @@
+const qs = require('querystring')
+const RuleSet = require('webpack/lib/RuleSet')
+
+const id = 'vue-loader-plugin'
+const NS = 'vue-loader'
+
+class VueLoaderPlugin {
+ apply (compiler) {
+ // add NS marker so that the loader can detect and report missing plugin
+ if (compiler.hooks) {
+ // webpack 4
+ compiler.hooks.compilation.tap(id, compilation => {
+ compilation.hooks.normalModuleLoader.tap(id, loaderContext => {
+ loaderContext[NS] = true
+ })
+ })
+ } else {
+ // webpack < 4
+ compiler.plugin('compilation', compilation => {
+ compilation.plugin('normal-module-loader', loaderContext => {
+ loaderContext[NS] = true
+ })
+ })
+ }
+
+ // use webpack's RuleSet utility to normalize user rules
+ const rawRules = compiler.options.module.rules
+ const { rules } = new RuleSet(rawRules)
+
+ // find the rule that applies to vue files
+ let vueRuleIndex = rawRules.findIndex(createMatcher(`foo.vue`))
+ if (vueRuleIndex < 0) {
+ vueRuleIndex = rawRules.findIndex(createMatcher(`foo.vue.html`))
+ }
+ const vueRule = rules[vueRuleIndex]
+
+ if (!vueRule) {
+ throw new Error(
+ `[VueLoaderPlugin Error] No matching rule for .vue files found.\n` +
+ `Make sure there is at least one root-level rule that matches .vue or .vue.html files.`
+ )
+ }
+
+ if (vueRule.oneOf) {
+ throw new Error(
+ `[VueLoaderPlugin Error] vue-loader 15 currently does not support vue rules with oneOf.`
+ )
+ }
+
+ // get the normlized "use" for vue files
+ const vueUse = vueRule.use
+ // get vue-loader options
+ const vueLoaderUseIndex = vueUse.findIndex(u => {
+ return /^vue-loader|(\/|\\|@)vue-loader/.test(u.loader)
+ })
+
+ if (vueLoaderUseIndex < 0) {
+ throw new Error(
+ `[VueLoaderPlugin Error] No matching use for vue-loader is found.\n` +
+ `Make sure the rule matching .vue files include vue-loader in its use.`
+ )
+ }
+
+ // make sure vue-loader options has a known ident so that we can share
+ // options by reference in the template-loader by using a ref query like
+ // template-loader??vue-loader-options
+ const vueLoaderUse = vueUse[vueLoaderUseIndex]
+ vueLoaderUse.ident = 'vue-loader-options'
+ vueLoaderUse.options = vueLoaderUse.options || {}
+
+ // for each user rule (expect the vue rule), create a cloned rule
+ // that targets the corresponding language blocks in *.vue files.
+ const clonedRules = rules
+ .filter(r => r !== vueRule)
+ .map(cloneRule)
+
+ // global pitcher (responsible for injecting template compiler loader & CSS
+ // post loader)
+ const pitcher = {
+ loader: require.resolve('./loaders/pitcher'),
+ resourceQuery: query => {
+ const parsed = qs.parse(query.slice(1))
+ return parsed.vue != null
+ },
+ options: {
+ cacheDirectory: vueLoaderUse.options.cacheDirectory,
+ cacheIdentifier: vueLoaderUse.options.cacheIdentifier
+ }
+ }
+
+ // replace original rules
+ compiler.options.module.rules = [
+ pitcher,
+ ...clonedRules,
+ ...rules
+ ]
+ }
+}
+
+function createMatcher (fakeFile) {
+ return (rule, i) => {
+ // #1201 we need to skip the `include` check when locating the vue rule
+ const clone = Object.assign({}, rule)
+ delete clone.include
+ const normalized = RuleSet.normalizeRule(clone, {}, '')
+ return (
+ !rule.enforce &&
+ normalized.resource &&
+ normalized.resource(fakeFile)
+ )
+ }
+}
+
+function cloneRule (rule) {
+ const { resource, resourceQuery } = rule
+ // 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
+ // it in `resourceQuery`. This ensures when we use the normalized rule's
+ // resource check, include/exclude are matched correctly.
+ let currentResource
+ const res = Object.assign({}, rule, {
+ resource: {
+ test: resource => {
+ currentResource = resource
+ return true
+ }
+ },
+ resourceQuery: query => {
+ const parsed = qs.parse(query.slice(1))
+ if (parsed.vue == null) {
+ return false
+ }
+ if (resource && parsed.lang == null) {
+ return false
+ }
+ const fakeResourcePath = `${currentResource}.${parsed.lang}`
+ if (resource && !resource(fakeResourcePath)) {
+ return false
+ }
+ if (resourceQuery && !resourceQuery(query)) {
+ return false
+ }
+ return true
+ }
+ })
+
+ if (rule.oneOf) {
+ res.oneOf = rule.oneOf.map(cloneRule)
+ }
+
+ return res
+}
+
+VueLoaderPlugin.NS = NS
+module.exports = VueLoaderPlugin