From 26105034da4fcce7ac883c899d781f016559310d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Nov 2018 00:38:48 +0800 Subject: switch to vuepress --- .../vue-loader/lib/codegen/customBlocks.js | 21 +++ node_modules/vue-loader/lib/codegen/hotReload.js | 31 ++++ .../vue-loader/lib/codegen/styleInjection.js | 114 ++++++++++++ node_modules/vue-loader/lib/codegen/utils.js | 25 +++ node_modules/vue-loader/lib/index.d.ts | 7 + node_modules/vue-loader/lib/index.js | 193 +++++++++++++++++++++ node_modules/vue-loader/lib/loaders/pitcher.js | 144 +++++++++++++++ .../vue-loader/lib/loaders/stylePostLoader.js | 23 +++ .../vue-loader/lib/loaders/templateLoader.js | 71 ++++++++ node_modules/vue-loader/lib/plugin.js | 156 +++++++++++++++++ .../vue-loader/lib/runtime/componentNormalizer.js | 93 ++++++++++ node_modules/vue-loader/lib/select.js | 57 ++++++ 12 files changed, 935 insertions(+) create mode 100644 node_modules/vue-loader/lib/codegen/customBlocks.js create mode 100644 node_modules/vue-loader/lib/codegen/hotReload.js create mode 100644 node_modules/vue-loader/lib/codegen/styleInjection.js create mode 100644 node_modules/vue-loader/lib/codegen/utils.js create mode 100644 node_modules/vue-loader/lib/index.d.ts create mode 100644 node_modules/vue-loader/lib/index.js create mode 100644 node_modules/vue-loader/lib/loaders/pitcher.js create mode 100644 node_modules/vue-loader/lib/loaders/stylePostLoader.js create mode 100644 node_modules/vue-loader/lib/loaders/templateLoader.js create mode 100644 node_modules/vue-loader/lib/plugin.js create mode 100644 node_modules/vue-loader/lib/runtime/componentNormalizer.js create mode 100644 node_modules/vue-loader/lib/select.js (limited to 'node_modules/vue-loader/lib') diff --git a/node_modules/vue-loader/lib/codegen/customBlocks.js b/node_modules/vue-loader/lib/codegen/customBlocks.js new file mode 100644 index 00000000..64e78a16 --- /dev/null +++ b/node_modules/vue-loader/lib/codegen/customBlocks.js @@ -0,0 +1,21 @@ +const qs = require('querystring') +const { attrsToQuery } = require('./utils') + +module.exports = function genCustomBlocksCode ( + blocks, + resourcePath, + resourceQuery, + stringifyRequest +) { + return `\n/* custom blocks */\n` + blocks.map((block, i) => { + const src = block.attrs.src || resourcePath + const attrsQuery = attrsToQuery(block.attrs) + const issuerQuery = block.attrs.src ? `&issuerPath=${qs.escape(resourcePath)}` : '' + const inheritQuery = resourceQuery ? `&${resourceQuery.slice(1)}` : '' + const query = `?vue&type=custom&index=${i}&blockType=${qs.escape(block.type)}${issuerQuery}${attrsQuery}${inheritQuery}` + return ( + `import block${i} from ${stringifyRequest(src + query)}\n` + + `if (typeof block${i} === 'function') block${i}(component)` + ) + }).join(`\n`) + `\n` +} diff --git a/node_modules/vue-loader/lib/codegen/hotReload.js b/node_modules/vue-loader/lib/codegen/hotReload.js new file mode 100644 index 00000000..4f426b4d --- /dev/null +++ b/node_modules/vue-loader/lib/codegen/hotReload.js @@ -0,0 +1,31 @@ +const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api')) + +const genTemplateHotReloadCode = (id, request) => { + return ` + module.hot.accept(${request}, function () { + api.rerender('${id}', { + render: render, + staticRenderFns: staticRenderFns + }) + }) + `.trim() +} + +exports.genHotReloadCode = (id, functional, templateRequest) => { + return ` +/* hot reload */ +if (module.hot) { + var api = require(${hotReloadAPIPath}) + api.install(require('vue')) + if (api.compatible) { + module.hot.accept() + if (!module.hot.data) { + api.createRecord('${id}', component.options) + } else { + api.${functional ? 'rerender' : 'reload'}('${id}', component.options) + } + ${templateRequest ? genTemplateHotReloadCode(id, templateRequest) : ''} + } +} + `.trim() +} diff --git a/node_modules/vue-loader/lib/codegen/styleInjection.js b/node_modules/vue-loader/lib/codegen/styleInjection.js new file mode 100644 index 00000000..b11e488a --- /dev/null +++ b/node_modules/vue-loader/lib/codegen/styleInjection.js @@ -0,0 +1,114 @@ +const { attrsToQuery } = require('./utils') +const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api')) + +module.exports = function genStyleInjectionCode ( + loaderContext, + styles, + id, + resourcePath, + stringifyRequest, + needsHotReload, + needsExplicitInjection +) { + let styleImportsCode = `` + let styleInjectionCode = `` + let cssModulesHotReloadCode = `` + + let hasCSSModules = false + const cssModuleNames = new Map() + + function genStyleRequest (style, i) { + const src = style.src || resourcePath + const attrsQuery = attrsToQuery(style.attrs, 'css') + const inheritQuery = `&${loaderContext.resourceQuery.slice(1)}` + // 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 idQuery = style.scoped ? `&id=${id}` : `` + const query = `?vue&type=style&index=${i}${idQuery}${attrsQuery}${inheritQuery}` + return stringifyRequest(src + query) + } + + function genCSSModulesCode (style, request, i) { + hasCSSModules = true + + const moduleName = style.module === true ? '$style' : style.module + if (cssModuleNames.has(moduleName)) { + loaderContext.emitError(`CSS module name ${moduleName} is not unique!`) + } + cssModuleNames.set(moduleName, true) + + // `(vue-)style-loader` exports the name-to-hash map directly + // `css-loader` exports it in `.locals` + const locals = `(style${i}.locals || style${i})` + const name = JSON.stringify(moduleName) + + if (!needsHotReload) { + styleInjectionCode += `this[${name}] = ${locals}\n` + } else { + styleInjectionCode += ` + cssModules[${name}] = ${locals} + Object.defineProperty(this, ${name}, { + get: function () { + return cssModules[${name}] + } + }) + ` + cssModulesHotReloadCode += ` + module.hot && module.hot.accept([${request}], function () { + var oldLocals = cssModules[${name}] + if (oldLocals) { + var newLocals = require(${request}) + if (JSON.stringify(newLocals) !== JSON.stringify(oldLocals)) { + cssModules[${name}] = newLocals + require(${hotReloadAPIPath}).rerender("${id}") + } + } + }) + ` + } + } + + // explicit injection is needed in SSR (for critical CSS collection) + // or in Shadow Mode (for injection into shadow root) + // In these modes, vue-style-loader exports objects with the __inject__ + // method; otherwise we simply import the styles. + if (!needsExplicitInjection) { + styles.forEach((style, i) => { + const request = genStyleRequest(style, i) + styleImportsCode += `import style${i} from ${request}\n` + if (style.module) genCSSModulesCode(style, request, i) + }) + } else { + styles.forEach((style, i) => { + const request = genStyleRequest(style, i) + styleInjectionCode += ( + `var style${i} = require(${request})\n` + + `if (style${i}.__inject__) style${i}.__inject__(context)\n` + ) + if (style.module) genCSSModulesCode(style, request, i) + }) + } + + if (!needsExplicitInjection && !hasCSSModules) { + return styleImportsCode + } + + return ` +${styleImportsCode} +${hasCSSModules && needsHotReload ? `var cssModules = {}` : ``} +${needsHotReload ? `var disposed = false` : ``} + +function injectStyles (context) { + ${needsHotReload ? `if (disposed) return` : ``} + ${styleInjectionCode} +} + +${needsHotReload ? ` + module.hot && module.hot.dispose(function (data) { + disposed = true + }) +` : ``} + +${cssModulesHotReloadCode} + `.trim() +} diff --git a/node_modules/vue-loader/lib/codegen/utils.js b/node_modules/vue-loader/lib/codegen/utils.js new file mode 100644 index 00000000..054f9a9c --- /dev/null +++ b/node_modules/vue-loader/lib/codegen/utils.js @@ -0,0 +1,25 @@ +const qs = require('querystring') + +// these are built-in query parameters so should be ignored +// if the user happen to add them as attrs +const ignoreList = [ + 'id', + 'index', + 'src', + 'type' +] + +// transform the attrs on a SFC block descriptor into a resourceQuery string +exports.attrsToQuery = (attrs, langFallback) => { + let query = `` + for (const name in attrs) { + const value = attrs[name] + if (!ignoreList.includes(name)) { + query += `&${qs.escape(name)}=${value ? qs.escape(value) : ``}` + } + } + if (langFallback && !(`lang` in attrs)) { + query += `&lang=${langFallback}` + } + return query +} diff --git a/node_modules/vue-loader/lib/index.d.ts b/node_modules/vue-loader/lib/index.d.ts new file mode 100644 index 00000000..a2755dbb --- /dev/null +++ b/node_modules/vue-loader/lib/index.d.ts @@ -0,0 +1,7 @@ +import { Plugin } from 'webpack' + +declare namespace VueLoader { + class VueLoaderPlugin extends Plugin {} +} + +export = VueLoader diff --git a/node_modules/vue-loader/lib/index.js b/node_modules/vue-loader/lib/index.js new file mode 100644 index 00000000..752f9854 --- /dev/null +++ b/node_modules/vue-loader/lib/index.js @@ -0,0 +1,193 @@ +const path = require('path') +const hash = require('hash-sum') +const qs = require('querystring') +const plugin = require('./plugin') +const selectBlock = require('./select') +const loaderUtils = require('loader-utils') +const { attrsToQuery } = require('./codegen/utils') +const { parse } = require('@vue/component-compiler-utils') +const genStylesCode = require('./codegen/styleInjection') +const { genHotReloadCode } = require('./codegen/hotReload') +const genCustomBlocksCode = require('./codegen/customBlocks') +const componentNormalizerPath = require.resolve('./runtime/componentNormalizer') +const { NS } = require('./plugin') + +let errorEmitted = false + +function loadTemplateCompiler () { + try { + return require('vue-template-compiler') + } catch (e) { + throw new Error( + `[vue-loader] vue-template-compiler must be installed as a peer dependency, ` + + `or a compatible compiler implementation must be passed via options.` + ) + } +} + +module.exports = function (source) { + const loaderContext = this + + if (!errorEmitted && !loaderContext['thread-loader'] && !loaderContext[NS]) { + loaderContext.emitError(new Error( + `vue-loader was used without the corresponding plugin. ` + + `Make sure to include VueLoaderPlugin in your webpack config.` + )) + errorEmitted = true + } + + const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r) + + const { + target, + request, + minimize, + sourceMap, + rootContext, + resourcePath, + resourceQuery + } = loaderContext + + const rawQuery = resourceQuery.slice(1) + const inheritQuery = `&${rawQuery}` + const incomingQuery = qs.parse(rawQuery) + const options = loaderUtils.getOptions(loaderContext) || {} + + const isServer = target === 'node' + const isShadow = !!options.shadowMode + const isProduction = options.productionMode || minimize || process.env.NODE_ENV === 'production' + const filename = path.basename(resourcePath) + const context = rootContext || process.cwd() + const sourceRoot = path.dirname(path.relative(context, resourcePath)) + + const descriptor = parse({ + source, + compiler: options.compiler || loadTemplateCompiler(), + filename, + sourceRoot, + needMap: sourceMap + }) + + // if the query has a type field, this is a language block request + // e.g. foo.vue?type=template&id=xxxxx + // and we will return early + if (incomingQuery.type) { + return selectBlock( + descriptor, + loaderContext, + incomingQuery, + !!options.appendExtension + ) + } + + // module id for scoped CSS & hot-reload + const rawShortFilePath = path + .relative(context, resourcePath) + .replace(/^(\.\.[\/\\])+/, '') + + const shortFilePath = rawShortFilePath.replace(/\\/g, '/') + resourceQuery + + const id = hash( + isProduction + ? (shortFilePath + '\n' + source) + : shortFilePath + ) + + // feature information + const hasScoped = descriptor.styles.some(s => s.scoped) + const hasFunctional = descriptor.template && descriptor.template.attrs.functional + const needsHotReload = ( + !isServer && + !isProduction && + (descriptor.script || descriptor.template) && + options.hotReload !== false + ) + + // template + let templateImport = `var render, staticRenderFns` + let templateRequest + if (descriptor.template) { + const src = descriptor.template.src || resourcePath + const idQuery = `&id=${id}` + const scopedQuery = hasScoped ? `&scoped=true` : `` + const attrsQuery = attrsToQuery(descriptor.template.attrs) + const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${inheritQuery}` + const request = templateRequest = stringifyRequest(src + query) + templateImport = `import { render, staticRenderFns } from ${request}` + } + + // script + let scriptImport = `var script = {}` + if (descriptor.script) { + const src = descriptor.script.src || resourcePath + const attrsQuery = attrsToQuery(descriptor.script.attrs, 'js') + const query = `?vue&type=script${attrsQuery}${inheritQuery}` + const request = stringifyRequest(src + query) + scriptImport = ( + `import script from ${request}\n` + + `export * from ${request}` // support named exports + ) + } + + // styles + let stylesCode = `` + if (descriptor.styles.length) { + stylesCode = genStylesCode( + loaderContext, + descriptor.styles, + id, + resourcePath, + stringifyRequest, + needsHotReload, + isServer || isShadow // needs explicit injection? + ) + } + + let code = ` +${templateImport} +${scriptImport} +${stylesCode} + +/* normalize component */ +import normalizer from ${stringifyRequest(`!${componentNormalizerPath}`)} +var component = normalizer( + script, + render, + staticRenderFns, + ${hasFunctional ? `true` : `false`}, + ${/injectStyles/.test(stylesCode) ? `injectStyles` : `null`}, + ${hasScoped ? JSON.stringify(id) : `null`}, + ${isServer ? JSON.stringify(hash(request)) : `null`} + ${isShadow ? `,true` : ``} +) + `.trim() + `\n` + + if (descriptor.customBlocks && descriptor.customBlocks.length) { + code += genCustomBlocksCode( + descriptor.customBlocks, + resourcePath, + resourceQuery, + stringifyRequest + ) + } + + if (needsHotReload) { + code += `\n` + genHotReloadCode(id, hasFunctional, templateRequest) + } + + // Expose filename. This is used by the devtools and Vue runtime warnings. + code += `\ncomponent.options.__file = ${ + isProduction + // For security reasons, only expose the file's basename in production. + ? JSON.stringify(filename) + // Expose the file's full path in development, so that it can be opened + // from the devtools. + : JSON.stringify(rawShortFilePath.replace(/\\/g, '/')) + }` + + code += `\nexport default component.exports` + // console.log(code) + return code +} + +module.exports.VueLoaderPlugin = plugin 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