This commit is contained in:
chrosey
2017-09-13 07:52:34 +02:00
parent a1f16c37f4
commit 2340b0226b
24621 changed files with 2912161 additions and 149 deletions
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015-present Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+23
View File
@@ -0,0 +1,23 @@
# vue-loader [![Build Status](https://circleci.com/gh/vuejs/vue-loader/tree/master.svg?style=shield)](https://circleci.com/gh/vuejs/vue-loader/tree/master) [![Windows Build status](https://ci.appveyor.com/api/projects/status/8cdonrkbg6m4k1tm/branch/master?svg=true)](https://ci.appveyor.com/project/yyx990803/vue-loader/branch/master) [![npm package](https://img.shields.io/npm/v/vue-loader.svg?maxAge=2592000)](https://www.npmjs.com/package/vue-loader)
> Vue.js component loader for [Webpack](http://webpack.github.io).
**NOTE: the master branch (9.0+) only works with Vue 2.x. For usage with Vue 1.x, see the [8.x branch](https://github.com/vuejs/vue-loader/tree/8.x).**
It allows you to write your components in this format:
![screenshot](http://blog.evanyou.me/images/vue-component.png)
The best way to get started is with [vue-cli](https://github.com/vuejs/vue-cli):
``` js
npm install -g vue-cli
vue init webpack-simple hello
cd hello
npm install
npm run dev
```
This will setup a basic Webpack + `vue-loader` project for you, with `*.vue` files and hot-reloading working out of the box!
For advanced `vue-loader` configuration, checkout the [documentation](http://vuejs.github.io/vue-loader/index.html).
+1
View File
@@ -0,0 +1 @@
module.exports = require('./lib/loader')
+51
View File
@@ -0,0 +1,51 @@
// this module is a runtime utility for cleaner component module output and will
// be included in the final webpack user bundle
module.exports = function normalizeComponent (
rawScriptExports,
compiledTemplate,
scopeId,
cssModules
) {
var esModule
var scriptExports = rawScriptExports = rawScriptExports || {}
// ES6 modules interop
var type = typeof rawScriptExports.default
if (type === 'object' || type === 'function') {
esModule = rawScriptExports
scriptExports = rawScriptExports.default
}
// Vue.extend constructor export interop
var options = typeof scriptExports === 'function'
? scriptExports.options
: scriptExports
// render functions
if (compiledTemplate) {
options.render = compiledTemplate.render
options.staticRenderFns = compiledTemplate.staticRenderFns
}
// scopedId
if (scopeId) {
options._scopeId = scopeId
}
// inject cssModules
if (cssModules) {
var computed = Object.create(options.computed || null)
Object.keys(cssModules).forEach(function (key) {
var module = cssModules[key]
computed[key] = function () { return module }
})
options.computed = computed
}
return {
esModule: esModule,
exports: scriptExports,
options: options
}
}
+488
View File
@@ -0,0 +1,488 @@
var path = require('path')
var parse = require('./parser')
var genId = require('./utils/gen-id')
var normalize = require('./utils/normalize')
var loaderUtils = require('loader-utils')
var querystring = require('querystring')
// internal lib loaders
var selectorPath = normalize.lib('selector')
var styleCompilerPath = normalize.lib('style-compiler/index')
var templateCompilerPath = normalize.lib('template-compiler/index')
var templatePreprocessorPath = normalize.lib('template-compiler/preprocessor')
var componentNormalizerPath = normalize.lib('component-normalizer')
// dep loaders
var styleLoaderPath = normalize.dep('vue-style-loader')
var hotReloadAPIPath = normalize.dep('vue-hot-reload-api')
var hasBabel = false
try {
hasBabel = !!require('babel-loader')
} catch (e) {}
var hasBuble = false
try {
hasBuble = !!require('buble-loader')
} catch (e) {}
var rewriterInjectRE = /\b(css(?:-loader)?(?:\?[^!]+)?)(?:!|$)/
var defaultLang = {
template: 'html',
styles: 'css',
script: 'js'
}
// When extracting parts from the source vue file, we want to apply the
// loaders chained before vue-loader, but exclude some loaders that simply
// produces side effects such as linting.
function getRawRequest (context, excludedPreLoaders) {
excludedPreLoaders = excludedPreLoaders || /eslint-loader/
return loaderUtils.getRemainingRequest({
resource: context.resource,
loaderIndex: context.loaderIndex,
loaders: context.loaders.filter(loader => !excludedPreLoaders.test(loader.path))
})
}
module.exports = function (content) {
this.cacheable()
var isServer = this.target === 'node'
var isProduction = this.minimize || process.env.NODE_ENV === 'production'
var loaderContext = this
var query = loaderUtils.getOptions(this) || {}
var options = this.options.__vueOptions__ = Object.assign({}, this.options.vue, this.vue, query)
var rawRequest = getRawRequest(this, options.excludedPreLoaders)
var filePath = this.resourcePath
var fileName = path.basename(filePath)
var context = (this._compiler && this._compiler.context) || this.options.context || process.cwd()
var moduleId = 'data-v-' + genId(filePath, context, options.hashKey)
var cssLoaderOptions = ''
if (!isProduction && this.sourceMap && options.cssSourceMap !== false) {
cssLoaderOptions += '?sourceMap'
}
if (isProduction) {
cssLoaderOptions += (cssLoaderOptions ? '&' : '?') + 'minimize'
}
var bubleOptions = hasBuble && options.buble
? '?' + JSON.stringify(options.buble)
: ''
var templateCompilerOptions = '?' + JSON.stringify({
id: moduleId,
transformToRequire: options.transformToRequire,
preserveWhitespace: options.preserveWhitespace,
buble: options.buble,
// only pass compilerModules if it's a path string
compilerModules: typeof options.compilerModules === 'string'
? options.compilerModules
: undefined
})
var defaultLoaders = {
html: templateCompilerPath + templateCompilerOptions,
css: styleLoaderPath + '!' + 'css-loader' + cssLoaderOptions,
js: hasBuble ? ('buble-loader' + bubleOptions) : hasBabel ? 'babel-loader' : ''
}
// check if there are custom loaders specified via
// webpack config, otherwise use defaults
var loaders = Object.assign({}, defaultLoaders, options.loaders)
var preLoaders = options.preLoaders || {}
var postLoaders = options.postLoaders || {}
function getRequire (type, part, index, scoped) {
return 'require(' +
getRequireString(type, part, index, scoped) +
')'
}
function getRequireString (type, part, index, scoped) {
return loaderUtils.stringifyRequest(loaderContext,
// disable all configuration loaders
'!!' +
// get loader string for pre-processors
getLoaderString(type, part, index, scoped) +
// select the corresponding part from the vue file
getSelectorString(type, index || 0) +
// the url to the actual vue file, including remaining requests
rawRequest
)
}
function getRequireForImport (type, impt, scoped) {
return 'require(' +
getRequireForImportString(type, impt, scoped) +
')'
}
function getRequireForImportString (type, impt, scoped) {
return loaderUtils.stringifyRequest(loaderContext,
'!!' +
getLoaderString(type, impt, -1, scoped) +
impt.src
)
}
function addCssModulesToLoader (loader, part, index) {
if (!part.module) return loader
var option = options.cssModules || {}
var DEFAULT_OPTIONS = {
modules: true,
importLoaders: true
}
var OPTIONS = {
localIdentName: '[hash:base64]'
}
return loader.replace(/((?:^|!)css(?:-loader)?)(\?[^!]*)?/, function (m, $1, $2) {
// $1: !css-loader
// $2: ?a=b
var query = loaderUtils.parseQuery($2 || '?')
Object.assign(query, OPTIONS, option, DEFAULT_OPTIONS)
if (index !== -1) {
// Note:
// Class name is generated according to its filename.
// Different <style> tags in the same .vue file may generate same names.
// Append `_[index]` to class name to avoid this.
query.localIdentName += '_' + index
}
return $1 + '?' + JSON.stringify(query)
})
}
function buildCustomBlockLoaderString (attrs) {
var noSrcAttrs = Object.assign({}, attrs)
delete noSrcAttrs.src
var qs = querystring.stringify(noSrcAttrs)
return qs ? '?' + qs : qs
}
// stringify an Array of loader objects
function stringifyLoaders (loaders) {
return loaders.map(function (obj) {
return obj && typeof obj === 'object' && typeof obj.loader === 'string'
? obj.loader + (obj.options ? '?' + JSON.stringify(obj.options) : '')
: obj
}).join('!')
}
function getLoaderString (type, part, index, scoped) {
var loader = getRawLoaderString(type, part, index, scoped)
var lang = getLangString(type, part)
if (preLoaders[lang]) {
loader = loader + ensureBang(preLoaders[lang])
}
if (postLoaders[lang]) {
loader = ensureBang(postLoaders[lang]) + loader
}
return loader
}
function getLangString (type, part) {
if (type === 'script' || type === 'template' || type === 'styles') {
return part.lang || defaultLang[type]
} else {
return type
}
}
function getRawLoaderString (type, part, index, scoped) {
var lang = part.lang || defaultLang[type]
var loader = loaders[lang]
var styleCompiler = ''
if (type === 'styles') {
styleCompiler = styleCompilerPath + '?' + JSON.stringify({
id: moduleId,
scoped: !!scoped,
hasInlineConfig: !!query.postcss
}) + '!'
}
var injectString = (type === 'script' && query.inject)
? 'inject-loader!'
: ''
if (loader != null) {
if (Array.isArray(loader)) {
loader = stringifyLoaders(loader)
} else if (typeof loader === 'object') {
loader = stringifyLoaders([loader])
}
if (type === 'styles') {
// add css modules
loader = addCssModulesToLoader(loader, part, index)
// inject rewriter before css loader for extractTextPlugin use cases
if (rewriterInjectRE.test(loader)) {
loader = loader.replace(rewriterInjectRE, function (m, $1) {
return ensureBang($1) + styleCompiler
})
} else {
loader = ensureBang(loader) + styleCompiler
}
}
// if user defines custom loaders for html, add template compiler to it
if (type === 'template' && loader.indexOf(defaultLoaders.html) < 0) {
loader = defaultLoaders.html + '!' + loader
}
return injectString + ensureBang(loader)
} else {
// unknown lang, infer the loader to be used
switch (type) {
case 'template':
return defaultLoaders.html + '!' + templatePreprocessorPath + '?raw&engine=' + lang + '!'
case 'styles':
loader = addCssModulesToLoader(defaultLoaders.css, part, index)
return loader + '!' + styleCompiler + ensureBang(ensureLoader(lang))
case 'script':
return injectString + ensureBang(ensureLoader(lang))
default:
loader = loaders[type]
if (Array.isArray(loader)) {
loader = stringifyLoaders(loader)
}
return ensureBang(loader + buildCustomBlockLoaderString(part.attrs))
}
}
}
// sass => sass-loader
// sass-loader => sass-loader
// sass?indentedsyntax!css => sass-loader?indentedSyntax!css-loader
function ensureLoader (lang) {
return lang.split('!').map(function (loader) {
return loader.replace(/^([\w-]+)(\?.*)?/, function (_, name, query) {
return (/-loader$/.test(name) ? name : (name + '-loader')) + (query || '')
})
}).join('!')
}
function getSelectorString (type, index) {
return selectorPath +
'?type=' + ((type === 'script' || type === 'template' || type === 'styles') ? type : 'customBlocks') +
'&index=' + index + '!'
}
function ensureBang (loader) {
if (loader.charAt(loader.length - 1) !== '!') {
return loader + '!'
} else {
return loader
}
}
var output = ''
var parts = parse(content, fileName, this.sourceMap)
var hasScoped = parts.styles.some(function (s) { return s.scoped })
// css modules
var cssModules
// add requires for styles
if (parts.styles.length) {
output += '\n/* styles */\n'
var hasModules = false
parts.styles.forEach(function (style, i) {
// require style
var requireString = style.src
? getRequireForImport('styles', style, style.scoped)
: getRequire('styles', style, i, style.scoped)
var moduleName = (style.module === true) ? '$style' : style.module
// setCssModule
if (moduleName) {
if (!cssModules) {
cssModules = {}
}
if (!hasModules) {
hasModules = true
output += 'var cssModules = {}\n'
}
if (moduleName in cssModules) {
loaderContext.emitError('CSS module name "' + moduleName + '" is not unique!')
output += requireString
} else {
cssModules[moduleName] = true
// `(vue-)style-loader` exposes the name-to-hash map directly
// `css-loader` exposes it in `.locals`
// add `.locals` if the user configured to not use style-loader.
if (requireString.indexOf('style-loader') < 0) {
requireString += '.locals'
}
output += 'cssModules["' + moduleName + '"] = ' + requireString + '\n'
}
} else {
output += requireString + '\n'
}
})
output += '\n'
}
// we require the component normalizer function, and call it like so:
// normalizeComponent(
// scriptExports,
// compiledTemplate,
// scopeId,
// cssModules
// )
output += 'var Component = require(' +
loaderUtils.stringifyRequest(loaderContext, '!' + componentNormalizerPath) +
')(\n'
// <script>
output += ' /* script */\n '
var script = parts.script
if (script) {
output += script.src
? getRequireForImport('script', script)
: getRequire('script', script)
// inject loader interop
if (query.inject) {
output += '(injections)'
}
} else {
output += 'null'
}
output += ',\n'
// <template>
output += ' /* template */\n '
var template = parts.template
if (template) {
output += template.src
? getRequireForImport('template', template)
: getRequire('template', template)
} else {
output += 'null'
}
output += ',\n'
// scopeId
output += ' /* scopeId */\n '
output += (hasScoped ? JSON.stringify(moduleId) : 'null') + ',\n'
// cssModules
output += ' /* cssModules */\n '
if (cssModules) {
// inject style modules as computed properties
output += 'cssModules'
} else {
output += 'null'
}
output += '\n'
// close normalizeComponent call
output += ')\n'
// development-only code
if (!isProduction) {
// add filename in dev
output += 'Component.options.__file = ' + JSON.stringify(filePath) + '\n'
// check named exports
output +=
'if (Component.esModule && Object.keys(Component.esModule).some(function (key) {' +
'return key !== "default" && key !== "__esModule"' +
'})) {' +
'console.error("named exports are not supported in *.vue files.")' +
'}\n'
// check functional components used with templates
if (template) {
output +=
'if (Component.options.functional) {' +
'console.error("' +
'[vue-loader] ' + fileName + ': functional components are not ' +
'supported with templates, they should use render functions.' +
'")}\n'
}
}
// add requires for customBlocks
if (parts.customBlocks && parts.customBlocks.length) {
var addedPrefix = false
parts.customBlocks.forEach(function (customBlock, i) {
if (loaders[customBlock.type]) {
// require customBlock
customBlock.src = customBlock.attrs.src
var requireString = customBlock.src
? getRequireForImport(customBlock.type, customBlock)
: getRequire(customBlock.type, customBlock, i)
if (!addedPrefix) {
output += '\n/* customBlocks */\n'
addedPrefix = true
}
output +=
'var customBlock = ' + requireString + '\n' +
'if (typeof customBlock === "function") {' +
'customBlock(Component)' +
'}\n'
}
})
output += '\n'
}
if (!query.inject) {
// hot reload
if (
!isServer &&
!isProduction &&
(parts.script || parts.template)
) {
output +=
'\n/* hot reload */\n' +
'if (module.hot) {(function () {\n' +
' var hotAPI = require("' + hotReloadAPIPath + '")\n' +
' hotAPI.install(require("vue"), false)\n' +
' if (!hotAPI.compatible) return\n' +
' module.hot.accept()\n' +
' if (!module.hot.data) {\n' +
// initial insert
' hotAPI.createRecord("' + moduleId + '", Component.options)\n' +
' } else {\n'
// update
if (cssModules) {
output +=
' if (module.hot.data.cssModules && JSON.stringify(module.hot.data.cssModules) !== JSON.stringify(cssModules)) {\n' +
' delete Component.options._Ctor\n' +
' }\n'
}
output +=
' hotAPI.reload("' + moduleId + '", Component.options)\n' +
' }\n'
if (cssModules) {
// save cssModules
output +=
' module.hot.dispose(function (data) {\n' +
' data.cssModules = cssModules\n' +
' })\n'
}
output += '})()}\n'
}
// final export
if (options.esModule) {
output += '\nexports.__esModule = true;\nexports["default"] = Component.exports\n'
} else {
output += '\nmodule.exports = Component.exports\n'
}
} else {
// inject-loader support
output =
'\n/* dependency injection */\n' +
'module.exports = function (injections) {\n' + output + '\n' +
'\nreturn Component.exports\n}'
}
// done
return output
}
+59
View File
@@ -0,0 +1,59 @@
var compiler = require('vue-template-compiler')
var cache = require('lru-cache')(100)
var hash = require('hash-sum')
var SourceMapGenerator = require('source-map').SourceMapGenerator
var splitRE = /\r?\n/g
var emptyRE = /^(?:\/\/)?\s*$/
module.exports = function (content, filename, needMap) {
var cacheKey = hash(filename + content)
// source-map cache busting for hot-reloadded modules
var filenameWithHash = filename + '?' + cacheKey
var output = cache.get(cacheKey)
if (output) return output
output = compiler.parseComponent(content, { pad: 'line' })
if (needMap) {
if (output.script && !output.script.src) {
output.script.map = generateSourceMap(
filenameWithHash,
content,
output.script.content
)
}
if (output.styles) {
output.styles.forEach(style => {
if (!style.src) {
style.map = generateSourceMap(
filenameWithHash,
content,
style.content
)
}
})
}
}
cache.set(cacheKey, output)
return output
}
function generateSourceMap (filename, source, generated) {
var map = new SourceMapGenerator()
map.setSourceContent(filename, source)
generated.split(splitRE).forEach((line, index) => {
if (!emptyRE.test(line)) {
map.addMapping({
source: filename,
original: {
line: index + 1,
column: 0
},
generated: {
line: index + 1,
column: 0
}
})
}
})
return map.toJSON()
}
+19
View File
@@ -0,0 +1,19 @@
// this is a utility loader that takes a *.vue file, parses it and returns
// the requested language block, e.g. the content inside <template>, for
// further processing.
var path = require('path')
var parse = require('./parser')
var loaderUtils = require('loader-utils')
module.exports = function (content) {
this.cacheable()
var query = loaderUtils.getOptions(this) || {}
var filename = path.basename(this.resourcePath)
var parts = parse(content, filename, this.sourceMap)
var part = parts[query.type]
if (Array.isArray(part)) {
part = part[query.index]
}
this.callback(null, part.content, part.map)
}
+68
View File
@@ -0,0 +1,68 @@
var postcss = require('postcss')
var loaderUtils = require('loader-utils')
var loadPostcssConfig = require('./load-postcss-config')
var trim = require('./plugins/trim')
var scopeId = require('./plugins/scope-id')
module.exports = function (css, map) {
this.cacheable()
var cb = this.async()
var query = loaderUtils.getOptions(this) || {}
var vueOptions = this.options.__vueOptions__
if (!vueOptions) {
if (query.hasInlineConfig) {
this.emitError(
`\n [vue-loader] It seems you are using HappyPack with inline postcss ` +
`options for vue-loader. This is not supported because loaders running ` +
`in different threads cannot share non-serializable options. ` +
`It is recommended to use a postcss config file instead.\n` +
`\n See http://vue-loader.vuejs.org/en/features/postcss.html#using-a-config-file for more details.\n`
)
}
vueOptions = Object.assign({}, this.options.vue, this.vue)
}
// use the same config loading interface as postcss-loader
loadPostcssConfig(vueOptions.postcss).then(config => {
var plugins = [trim].concat(config.plugins)
var options = Object.assign({
to: this.resourcePath,
from: this.resourcePath,
map: false
}, config.options)
// add plugin for vue-loader scoped css rewrite
if (query.scoped) {
plugins.push(scopeId({ id: query.id }))
}
// source map
if (
this.sourceMap &&
!this.minimize &&
vueOptions.cssSourceMap !== false &&
process.env.NODE_ENV !== 'production' &&
!options.map
) {
options.map = {
inline: false,
annotation: false,
prev: map
}
}
return postcss(plugins)
.process(css, options)
.then(function (result) {
var map = result.map && result.map.toJSON()
cb(null, result.css, map)
return null // silence bluebird warning
})
}).catch(e => {
console.log(e)
cb(e)
})
}
+45
View File
@@ -0,0 +1,45 @@
var load = require('postcss-load-config')
var loaded
function isObject (val) {
return val && typeof val === 'object'
}
module.exports = function loadPostcssConfig (inlineConfig) {
if (process.env.VUE_LOADER_TEST || !loaded) {
loaded = load({}, null, { argv: false }).catch(() => {
// postcss-load-config throws error when no config file is found,
// but for us it's optional.
})
}
return loaded.then(config => {
var plugins = []
var options = {}
// inline postcss options for vue-loader
if (typeof inlineConfig === 'function') {
inlineConfig = inlineConfig.call(this, this)
}
if (Array.isArray(inlineConfig)) {
plugins = inlineConfig
} else if (isObject(inlineConfig)) {
plugins = inlineConfig.plugins || []
options = inlineConfig.options || {}
}
// merge postcss config file
if (config && config.plugins) {
plugins = plugins.concat(config.plugins)
}
if (config && config.options) {
options = Object.assign({}, config.options, options)
}
return {
plugins,
options
}
})
}
+27
View File
@@ -0,0 +1,27 @@
var postcss = require('postcss')
var selectorParser = require('postcss-selector-parser')
module.exports = postcss.plugin('add-id', function (opts) {
return function (root) {
root.each(function rewriteSelector (node) {
if (!node.selector) {
// handle media queries
if (node.type === 'atrule' && node.name === 'media') {
node.each(rewriteSelector)
}
return
}
node.selector = selectorParser(function (selectors) {
selectors.each(function (selector) {
var node = null
selector.each(function (n) {
if (n.type !== 'pseudo') node = n
})
selector.insertAfter(node, selectorParser.attribute({
attribute: opts.id
}))
})
}).process(node.selector).result
})
}
})
+11
View File
@@ -0,0 +1,11 @@
var postcss = require('postcss')
module.exports = postcss.plugin('trim', function (opts) {
return function (css) {
css.walk(function (node) {
if (node.type === 'rule' || node.type === 'atrule') {
node.raws.before = node.raws.after = '\n'
}
})
}
})
+81
View File
@@ -0,0 +1,81 @@
var loaderUtils = require('loader-utils')
var normalize = require('../utils/normalize')
var compiler = require('vue-template-compiler')
var beautify = require('js-beautify').js_beautify
var transpile = require('vue-template-es2015-compiler')
var hotReloadAPIPath = normalize.dep('vue-hot-reload-api')
var transformRequire = require('./modules/transform-require')
module.exports = function (html) {
this.cacheable()
var isServer = this.target === 'node'
var isProduction = this.minimize || process.env.NODE_ENV === 'production'
var vueOptions = this.options.__vueOptions__ || {}
var options = loaderUtils.getOptions(this) || {}
var defaultModules = [transformRequire(options.transformToRequire)]
var userModules = vueOptions.compilerModules || options.compilerModules
// for HappyPack cross-process use cases
if (typeof userModules === 'string') {
userModules = require(userModules)
}
var compilerOptions = {
preserveWhitespace: options.preserveWhitespace,
modules: defaultModules.concat(userModules || [])
}
var compiled = compiler.compile(html, compilerOptions)
// tips
if (compiled.tips && compiled.tips.length) {
compiled.tips.forEach(tip => {
this.emitWarning(tip)
})
}
var code
if (compiled.errors && compiled.errors.length) {
this.emitError(
`\n Error compiling template:\n${pad(html)}\n` +
compiled.errors.map(e => ` - ${e}`).join('\n') + '\n'
)
code = 'module.exports={render:function(){},staticRenderFns:[]}'
} else {
var bubleOptions = options.buble
code = transpile('module.exports={' +
'render:' + toFunction(compiled.render) + ',' +
'staticRenderFns: [' + compiled.staticRenderFns.map(toFunction).join(',') + ']' +
'}', bubleOptions)
// mark with stripped (this enables Vue to use correct runtime proxy detection)
if (!isProduction && (
!bubleOptions ||
!bubleOptions.transforms ||
bubleOptions.transforms.stripWith !== false
)) {
code += `\nmodule.exports.render._withStripped = true`
}
}
// hot-reload
if (!isServer && !isProduction) {
code +=
'\nif (module.hot) {\n' +
' module.hot.accept()\n' +
' if (module.hot.data) {\n' +
' require("' + hotReloadAPIPath + '").rerender("' + options.id + '", module.exports)\n' +
' }\n' +
'}'
}
return code
}
function toFunction (code) {
return 'function (){' + beautify(code, {
indent_size: 2 // eslint-disable-line camelcase
}) + '}'
}
function pad (html) {
return html.split(/\r?\n/).map(line => ` ${line}`).join('\n')
}
@@ -0,0 +1,49 @@
// vue compiler module for transforming `<tag>:<attribute>` to `require`
var defaultOptions = {
img: 'src',
image: 'xlink:href'
}
module.exports = userOptions => {
var options = userOptions
? Object.assign({}, defaultOptions, userOptions)
: defaultOptions
return {
postTransformNode: node => {
transform(node, options)
}
}
}
function transform (node, options) {
for (var tag in options) {
if (node.tag === tag && node.attrs) {
var attributes = options[tag]
if (typeof attributes === 'string') {
node.attrs.some(attr => rewrite(attr, attributes))
} else if (Array.isArray(attributes)) {
attributes.forEach(item => node.attrs.some(attr => rewrite(attr, item)))
}
}
}
}
function rewrite (attr, name) {
if (attr.name === name) {
var value = attr.value
var isStatic = value.charAt(0) === '"' && value.charAt(value.length - 1) === '"'
if (!isStatic) {
return
}
var firstChar = value.charAt(1)
if (firstChar === '.' || firstChar === '~') {
if (firstChar === '~') {
value = '"' + value.slice(2)
}
attr.value = `require(${value})`
}
return true
}
}
+50
View File
@@ -0,0 +1,50 @@
// loader for pre-processing templates with e.g. pug
var cons = require('consolidate')
var loaderUtils = require('loader-utils')
var extname = require('path').extname
module.exports = function (content) {
this.cacheable && this.cacheable()
var callback = this.async()
var opt = loaderUtils.getOptions(this) || {}
// this is never documented and should be deprecated
// but we'll keep it so we don't break stuff
var vue = this.options.__vueOptions__
if (vue && vue.template) {
for (var key in vue.template) {
opt[key] = vue.template[key]
}
}
function exportContent (content) {
if (opt.raw) {
callback(null, content)
} else {
callback(null, 'module.exports = ' + JSON.stringify(content))
}
}
// with no engine given, use the file extension as engine
if (!opt.engine) {
opt.engine = extname(this.request).substr(1).toLowerCase()
}
if (!cons[opt.engine]) {
return callback(new Error(
'Template engine \'' + opt.engine + '\' ' +
'isn\'t available in Consolidate.js'
))
}
// for relative includes
opt.filename = this.resourcePath
cons[opt.engine].render(content, opt, function (err, html) {
if (err) {
return callback(err)
}
exportContent(html)
})
}
+13
View File
@@ -0,0 +1,13 @@
// utility for generating a uid for each component file
// used in scoped CSS rewriting
var path = require('path')
var hash = require('hash-sum')
var cache = Object.create(null)
var sepRE = new RegExp(path.sep.replace('\\', '\\\\'), 'g')
module.exports = function genId (file, context, key) {
var contextPath = context.split(path.sep)
var rootId = contextPath[contextPath.length - 1]
file = rootId + '/' + path.relative(context, file).replace(sepRE, '/') + (key || '')
return cache[file] || (cache[file] = hash(file))
}
+19
View File
@@ -0,0 +1,19 @@
var IS_TEST = !!process.env.VUE_LOADER_TEST
var fs = require('fs')
var path = require('path')
exports.lib = function (file) {
return path.resolve(__dirname, '../', file)
}
exports.dep = function (dep) {
if (IS_TEST) {
return dep
} else if (fs.existsSync(path.resolve(__dirname, '../../node_modules', dep))) {
// npm 2 or npm linked
return 'vue-loader/node_modules/' + dep
} else {
// npm 3
return dep
}
}
+18
View File
@@ -0,0 +1,18 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="1.1.0"></a>
# [1.1.0](https://github.com/webpack/loader-utils/compare/v1.0.4...v1.1.0) (2017-03-16)
### Features
* **automatic-release:** Generation of automatic release ([7484d13](https://github.com/webpack/loader-utils/commit/7484d13))
* **parseQuery:** export parseQuery ([ddf64e4](https://github.com/webpack/loader-utils/commit/ddf64e4))
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+20
View File
@@ -0,0 +1,20 @@
Copyright JS Foundation and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+229
View File
@@ -0,0 +1,229 @@
# loader-utils
## Methods
### `getOptions`
Recommended way to retrieve the options of a loader invocation:
```javascript
// inside your loader
const options = loaderUtils.getOptions(this);
```
1. If `this.query` is a string:
- Tries to parse the query string and returns a new object
- Throws if it's not a valid query string
2. If `this.query` is object-like, it just returns `this.query`
3. In any other case, it just returns `null`
**Please note:** The returned `options` object is *read-only*. It may be re-used across multiple invocations.
If you pass it on to another library, make sure to make a *deep copy* of it:
```javascript
const options = Object.assign(
{},
loaderUtils.getOptions(this), // it is safe to pass null to Object.assign()
defaultOptions
);
// don't forget nested objects or arrays
options.obj = Object.assign({}, options.obj);
options.arr = options.arr.slice();
someLibrary(options);
```
[clone-deep](https://www.npmjs.com/package/clone-deep) is a good library to make a deep copy of the options.
#### Options as query strings
If the loader options have been passed as loader query string (`loader?some&params`), the string is parsed by using [`parseQuery`](#parsequery).
### `parseQuery`
Parses a passed string (e.g. `loaderContext.resourceQuery`) as a query string, and returns an object.
``` javascript
const params = loaderUtils.parseQuery(this.resourceQuery); // resource: `file?param1=foo`
if (params.param1 === "foo") {
// do something
}
```
The string is parsed like this:
``` text
-> Error
? -> {}
?flag -> { flag: true }
?+flag -> { flag: true }
?-flag -> { flag: false }
?xyz=test -> { xyz: "test" }
?xyz=1 -> { xyz: "1" } // numbers are NOT parsed
?xyz[]=a -> { xyz: ["a"] }
?flag1&flag2 -> { flag1: true, flag2: true }
?+flag1,-flag2 -> { flag1: true, flag2: false }
?xyz[]=a,xyz[]=b -> { xyz: ["a", "b"] }
?a%2C%26b=c%2C%26d -> { "a,&b": "c,&d" }
?{data:{a:1},isJSON5:true} -> { data: { a: 1 }, isJSON5: true }
```
### `stringifyRequest`
Turns a request into a string that can be used inside `require()` or `import` while avoiding absolute paths.
Use it instead of `JSON.stringify(...)` if you're generating code inside a loader.
**Why is this necessary?** Since webpack calculates the hash before module paths are translated into module ids, we must avoid absolute paths to ensure
consistent hashes across different compilations.
This function:
- resolves absolute requests into relative requests if the request and the module are on the same hard drive
- replaces `\` with `/` if the request and the module are on the same hard drive
- won't change the path at all if the request and the module are on different hard drives
- applies `JSON.stringify` to the result
```javascript
loaderUtils.stringifyRequest(this, "./test.js");
// "\"./test.js\""
loaderUtils.stringifyRequest(this, ".\\test.js");
// "\"./test.js\""
loaderUtils.stringifyRequest(this, "test");
// "\"test\""
loaderUtils.stringifyRequest(this, "test/lib/index.js");
// "\"test/lib/index.js\""
loaderUtils.stringifyRequest(this, "otherLoader?andConfig!test?someConfig");
// "\"otherLoader?andConfig!test?someConfig\""
loaderUtils.stringifyRequest(this, require.resolve("test"));
// "\"../node_modules/some-loader/lib/test.js\""
loaderUtils.stringifyRequest(this, "C:\\module\\test.js");
// "\"../../test.js\"" (on Windows, in case the module and the request are on the same drive)
loaderUtils.stringifyRequest(this, "C:\\module\\test.js");
// "\"C:\\module\\test.js\"" (on Windows, in case the module and the request are on different drives)
loaderUtils.stringifyRequest(this, "\\\\network-drive\\test.js");
// "\"\\\\network-drive\\\\test.js\"" (on Windows, in case the module and the request are on different drives)
```
### `urlToRequest`
Converts some resource URL to a webpack module request.
```javascript
const url = "path/to/module.js";
const request = loaderUtils.urlToRequest(url); // "./path/to/module.js"
```
#### Module URLs
Any URL containing a `~` will be interpreted as a module request. Anything after the `~` will be considered the request path.
```javascript
const url = "~path/to/module.js";
const request = loaderUtils.urlToRequest(url); // "path/to/module.js"
```
#### Root-relative URLs
URLs that are root-relative (start with `/`) can be resolved relative to some arbitrary path by using the `root` parameter:
```javascript
const url = "/path/to/module.js";
const root = "./root";
const request = loaderUtils.urlToRequest(url, root); // "./root/path/to/module.js"
```
To convert a root-relative URL into a module URL, specify a `root` value that starts with `~`:
```javascript
const url = "/path/to/module.js";
const root = "~";
const request = loaderUtils.urlToRequest(url, root); // "path/to/module.js"
```
### `interpolateName`
Interpolates a filename template using multiple placeholders and/or a regular expression.
The template and regular expression are set as query params called `name` and `regExp` on the current loader's context.
```javascript
const interpolatedName = loaderUtils.interpolateName(loaderContext, name, options);
```
The following tokens are replaced in the `name` parameter:
* `[ext]` the extension of the resource
* `[name]` the basename of the resource
* `[path]` the path of the resource relative to the `context` query parameter or option.
* `[folder]` the folder of the resource is in.
* `[emoji]` a random emoji representation of `options.content`
* `[emoji:<length>]` same as above, but with a customizable number of emojis
* `[hash]` the hash of `options.content` (Buffer) (by default it's the hex digest of the md5 hash)
* `[<hashType>:hash:<digestType>:<length>]` optionally one can configure
* other `hashType`s, i. e. `sha1`, `md5`, `sha256`, `sha512`
* other `digestType`s, i. e. `hex`, `base26`, `base32`, `base36`, `base49`, `base52`, `base58`, `base62`, `base64`
* and `length` the length in chars
* `[N]` the N-th match obtained from matching the current file name against `options.regExp`
Examples
``` javascript
// loaderContext.resourcePath = "/app/js/javascript.js"
loaderUtils.interpolateName(loaderContext, "js/[hash].script.[ext]", { content: ... });
// => js/9473fdd0d880a43c21b7778d34872157.script.js
// loaderContext.resourcePath = "/app/page.html"
loaderUtils.interpolateName(loaderContext, "html-[hash:6].html", { content: ... });
// => html-9473fd.html
// loaderContext.resourcePath = "/app/flash.txt"
loaderUtils.interpolateName(loaderContext, "[hash]", { content: ... });
// => c31e9820c001c9c4a86bce33ce43b679
// loaderContext.resourcePath = "/app/img/image.gif"
loaderUtils.interpolateName(loaderContext, "[emoji]", { content: ... });
// => 👍
// loaderContext.resourcePath = "/app/img/image.gif"
loaderUtils.interpolateName(loaderContext, "[emoji:4]", { content: ... });
// => 🙍🏢📤🐝
// loaderContext.resourcePath = "/app/img/image.png"
loaderUtils.interpolateName(loaderContext, "[sha512:hash:base64:7].[ext]", { content: ... });
// => 2BKDTjl.png
// use sha512 hash instead of md5 and with only 7 chars of base64
// loaderContext.resourcePath = "/app/img/myself.png"
// loaderContext.query.name =
loaderUtils.interpolateName(loaderContext, "picture.png");
// => picture.png
// loaderContext.resourcePath = "/app/dir/file.png"
loaderUtils.interpolateName(loaderContext, "[path][name].[ext]?[hash]", { content: ... });
// => /app/dir/file.png?9473fdd0d880a43c21b7778d34872157
// loaderContext.resourcePath = "/app/js/page-home.js"
loaderUtils.interpolateName(loaderContext, "script-[1].[ext]", { regExp: "page-(.*)\\.js", content: ... });
// => script-home.js
```
### `getHashDigest`
``` javascript
const digestString = loaderUtils.getHashDigest(buffer, hashType, digestType, maxLength);
```
* `buffer` the content that should be hashed
* `hashType` one of `sha1`, `md5`, `sha256`, `sha512` or any other node.js supported hash type
* `digestType` one of `hex`, `base26`, `base32`, `base36`, `base49`, `base52`, `base58`, `base62`, `base64`
* `maxLength` the maximum length in chars
## License
MIT (http://www.opensource.org/licenses/mit-license.php)
@@ -0,0 +1,13 @@
"use strict";
function getCurrentRequest(loaderContext) {
if(loaderContext.currentRequest)
return loaderContext.currentRequest;
const request = loaderContext.loaders
.slice(loaderContext.loaderIndex)
.map(obj => obj.request)
.concat([loaderContext.resource]);
return request.join("!");
}
module.exports = getCurrentRequest;
+53
View File
@@ -0,0 +1,53 @@
"use strict";
const baseEncodeTables = {
26: "abcdefghijklmnopqrstuvwxyz",
32: "123456789abcdefghjkmnpqrstuvwxyz", // no 0lio
36: "0123456789abcdefghijklmnopqrstuvwxyz",
49: "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ", // no lIO
52: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
58: "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ", // no 0lIO
62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
64: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
};
function encodeBufferToBase(buffer, base) {
const encodeTable = baseEncodeTables[base];
if(!encodeTable) throw new Error("Unknown encoding base" + base);
const readLength = buffer.length;
const Big = require("big.js");
Big.RM = Big.DP = 0;
let b = new Big(0);
for(let i = readLength - 1; i >= 0; i--) {
b = b.times(256).plus(buffer[i]);
}
let output = "";
while(b.gt(0)) {
output = encodeTable[b.mod(base)] + output;
b = b.div(base);
}
Big.DP = 20;
Big.RM = 1;
return output;
}
function getHashDigest(buffer, hashType, digestType, maxLength) {
hashType = hashType || "md5";
maxLength = maxLength || 9999;
const hash = require("crypto").createHash(hashType);
hash.update(buffer);
if(digestType === "base26" || digestType === "base32" || digestType === "base36" ||
digestType === "base49" || digestType === "base52" || digestType === "base58" ||
digestType === "base62" || digestType === "base64") {
return encodeBufferToBase(hash.digest(), digestType.substr(4)).substr(0, maxLength);
} else {
return hash.digest(digestType || "hex").substr(0, maxLength);
}
}
module.exports = getHashDigest;
+17
View File
@@ -0,0 +1,17 @@
"use strict";
const parseQuery = require("./parseQuery");
function getOptions(loaderContext) {
const query = loaderContext.query;
if(typeof query === "string" && query !== "") {
return parseQuery(loaderContext.query);
}
if(!query || typeof query !== "object") {
// Not object-like queries are not supported.
return null;
}
return query;
}
module.exports = getOptions;
@@ -0,0 +1,13 @@
"use strict";
function getRemainingRequest(loaderContext) {
if(loaderContext.remainingRequest)
return loaderContext.remainingRequest;
const request = loaderContext.loaders
.slice(loaderContext.loaderIndex + 1)
.map(obj => obj.request)
.concat([loaderContext.resource]);
return request.join("!");
}
module.exports = getRemainingRequest;
+23
View File
@@ -0,0 +1,23 @@
"use strict";
const getOptions = require("./getOptions");
const parseQuery = require("./parseQuery");
const stringifyRequest = require("./stringifyRequest");
const getRemainingRequest = require("./getRemainingRequest");
const getCurrentRequest = require("./getCurrentRequest");
const isUrlRequest = require("./isUrlRequest");
const urlToRequest = require("./urlToRequest");
const parseString = require("./parseString");
const getHashDigest = require("./getHashDigest");
const interpolateName = require("./interpolateName");
exports.getOptions = getOptions;
exports.parseQuery = parseQuery;
exports.stringifyRequest = stringifyRequest;
exports.getRemainingRequest = getRemainingRequest;
exports.getCurrentRequest = getCurrentRequest;
exports.isUrlRequest = isUrlRequest;
exports.urlToRequest = urlToRequest;
exports.parseString = parseString;
exports.getHashDigest = getHashDigest;
exports.interpolateName = interpolateName;
@@ -0,0 +1,95 @@
"use strict";
const path = require("path");
const emojisList = require("emojis-list");
const getHashDigest = require("./getHashDigest");
const emojiRegex = /[\uD800-\uDFFF]./;
const emojiList = emojisList.filter(emoji => emojiRegex.test(emoji));
const emojiCache = {};
function encodeStringToEmoji(content, length) {
if(emojiCache[content]) return emojiCache[content];
length = length || 1;
const emojis = [];
do {
const index = Math.floor(Math.random() * emojiList.length);
emojis.push(emojiList[index]);
emojiList.splice(index, 1);
} while(--length > 0);
const emojiEncoding = emojis.join("");
emojiCache[content] = emojiEncoding;
return emojiEncoding;
}
function interpolateName(loaderContext, name, options) {
let filename;
if(typeof name === "function") {
filename = name(loaderContext.resourcePath);
} else {
filename = name || "[hash].[ext]";
}
const context = options.context;
const content = options.content;
const regExp = options.regExp;
let ext = "bin";
let basename = "file";
let directory = "";
let folder = "";
if(loaderContext.resourcePath) {
const parsed = path.parse(loaderContext.resourcePath);
let resourcePath = loaderContext.resourcePath;
if(parsed.ext) {
ext = parsed.ext.substr(1);
}
if(parsed.dir) {
basename = parsed.name;
resourcePath = parsed.dir + path.sep;
}
if(typeof context !== "undefined") {
directory = path.relative(context, resourcePath + "_").replace(/\\/g, "/").replace(/\.\.(\/)?/g, "_$1");
directory = directory.substr(0, directory.length - 1);
} else {
directory = resourcePath.replace(/\\/g, "/").replace(/\.\.(\/)?/g, "_$1");
}
if(directory.length === 1) {
directory = "";
} else if(directory.length > 1) {
folder = path.basename(directory);
}
}
let url = filename;
if(content) {
// Match hash template
url = url
.replace(
/\[(?:(\w+):)?hash(?::([a-z]+\d*))?(?::(\d+))?\]/ig,
(all, hashType, digestType, maxLength) => getHashDigest(content, hashType, digestType, parseInt(maxLength, 10))
)
.replace(
/\[emoji(?::(\d+))?\]/ig,
(all, length) => encodeStringToEmoji(content, length)
);
}
url = url
.replace(/\[ext\]/ig, () => ext)
.replace(/\[name\]/ig, () => basename)
.replace(/\[path\]/ig, () => directory)
.replace(/\[folder\]/ig, () => folder);
if(regExp && loaderContext.resourcePath) {
const match = loaderContext.resourcePath.match(new RegExp(regExp));
match && match.forEach((matched, i) => {
url = url.replace(
new RegExp("\\[" + i + "\\]", "ig"),
matched
);
});
}
if(typeof loaderContext.options === "object" && typeof loaderContext.options.customInterpolateName === "function") {
url = loaderContext.options.customInterpolateName.call(loaderContext, url, name, options);
}
return url;
}
module.exports = interpolateName;
+14
View File
@@ -0,0 +1,14 @@
"use strict";
function isUrlRequest(url, root) {
// An URL is not an request if
// 1. it's a Data Url
// 2. it's an absolute url or and protocol-relative
// 3. it's some kind of url for a template
if(/^data:|^chrome-extension:|^(https?:)?\/\/|^[\{\}\[\]#*;,'§\$%&\(=?`´\^°<>]/.test(url)) return false;
// 4. It's also not an request if root isn't set and it's a root-relative url
if((root === undefined || root === false) && /^\//.test(url)) return false;
return true;
}
module.exports = isUrlRequest;
+54
View File
@@ -0,0 +1,54 @@
"use strict";
const JSON5 = require("json5");
const specialValues = {
"null": null,
"true": true,
"false": false
};
function parseQuery(query) {
if(query.substr(0, 1) !== "?") {
throw new Error("A valid query string passed to parseQuery should begin with '?'");
}
query = query.substr(1);
if(!query) {
return {};
}
if(query.substr(0, 1) === "{" && query.substr(-1) === "}") {
return JSON5.parse(query);
}
const queryArgs = query.split(/[,&]/g);
const result = {};
queryArgs.forEach(arg => {
const idx = arg.indexOf("=");
if(idx >= 0) {
let name = arg.substr(0, idx);
let value = decodeURIComponent(arg.substr(idx + 1));
if(specialValues.hasOwnProperty(value)) {
value = specialValues[value];
}
if(name.substr(-2) === "[]") {
name = decodeURIComponent(name.substr(0, name.length - 2));
if(!Array.isArray(result[name]))
result[name] = [];
result[name].push(value);
} else {
name = decodeURIComponent(name);
result[name] = value;
}
} else {
if(arg.substr(0, 1) === "-") {
result[decodeURIComponent(arg.substr(1))] = false;
} else if(arg.substr(0, 1) === "+") {
result[decodeURIComponent(arg.substr(1))] = true;
} else {
result[decodeURIComponent(arg)] = true;
}
}
});
return result;
}
module.exports = parseQuery;
+19
View File
@@ -0,0 +1,19 @@
"use strict";
function parseString(str) {
try {
if(str[0] === "\"") return JSON.parse(str);
if(str[0] === "'" && str.substr(str.length - 1) === "'") {
return parseString(
str
.replace(/\\.|"/g, x => x === "\"" ? "\\\"" : x)
.replace(/^'|'$/g, "\"")
);
}
return JSON.parse("\"" + str + "\"");
} catch(e) {
return str;
}
}
module.exports = parseString;
@@ -0,0 +1,40 @@
"use strict";
const path = require("path");
const matchRelativePath = /^\.\.?[/\\]/;
function isAbsolutePath(str) {
return path.posix.isAbsolute(str) || path.win32.isAbsolute(str);
}
function isRelativePath(str) {
return matchRelativePath.test(str);
}
function stringifyRequest(loaderContext, request) {
const splitted = request.split("!");
const context = loaderContext.context || (loaderContext.options && loaderContext.options.context);
return JSON.stringify(splitted.map(part => {
// First, separate singlePath from query, because the query might contain paths again
const splittedPart = part.match(/^(.*?)(\?.*)/);
let singlePath = splittedPart ? splittedPart[1] : part;
const query = splittedPart ? splittedPart[2] : "";
if(isAbsolutePath(singlePath) && context) {
singlePath = path.relative(context, singlePath);
if(isAbsolutePath(singlePath)) {
// If singlePath still matches an absolute path, singlePath was on a different drive than context.
// In this case, we leave the path platform-specific without replacing any separators.
// @see https://github.com/webpack/loader-utils/pull/14
return singlePath + query;
}
if(isRelativePath(singlePath) === false) {
// Ensure that the relative path starts at least with ./ otherwise it would be a request into the modules directory (like node_modules).
singlePath = "./" + singlePath;
}
}
return singlePath.replace(/\\/g, "/") + query;
}).join("!"));
}
module.exports = stringifyRequest;
+49
View File
@@ -0,0 +1,49 @@
"use strict";
// we can't use path.win32.isAbsolute because it also matches paths starting with a forward slash
const matchNativeWin32Path = /^[A-Z]:[/\\]|^\\\\/i;
function urlToRequest(url, root) {
const moduleRequestRegex = /^[^?]*~/;
let request;
if(matchNativeWin32Path.test(url)) {
// absolute windows path, keep it
request = url;
} else if(root !== undefined && root !== false && /^\//.test(url)) {
// if root is set and the url is root-relative
switch(typeof root) {
// 1. root is a string: root is prefixed to the url
case "string":
// special case: `~` roots convert to module request
if(moduleRequestRegex.test(root)) {
request = root.replace(/([^~\/])$/, "$1/") + url.slice(1);
} else {
request = root + url;
}
break;
// 2. root is `true`: absolute paths are allowed
// *nix only, windows-style absolute paths are always allowed as they doesn't start with a `/`
case "boolean":
request = url;
break;
default:
throw new Error("Unexpected parameters to loader-utils 'urlToRequest': url = " + url + ", root = " + root + ".");
}
} else if(/^\.\.?\//.test(url)) {
// A relative url stays
request = url;
} else {
// every other url is threaded like a relative url
request = "./" + url;
}
// A `~` makes the url an module
if(moduleRequestRegex.test(request)) {
request = request.replace(moduleRequestRegex, "");
}
return request;
}
module.exports = urlToRequest;
+109
View File
@@ -0,0 +1,109 @@
{
"_args": [
[
{
"raw": "loader-utils@^1.1.0",
"scope": null,
"escapedName": "loader-utils",
"name": "loader-utils",
"rawSpec": "^1.1.0",
"spec": ">=1.1.0 <2.0.0",
"type": "range"
},
"c:\\xampp\\htdocs\\laravel\\node_modules\\vue-loader"
]
],
"_from": "loader-utils@>=1.1.0 <2.0.0",
"_id": "loader-utils@1.1.0",
"_inCache": true,
"_location": "/vue-loader/loader-utils",
"_nodeVersion": "7.7.3",
"_npmOperationalInternal": {
"host": "packages-12-west.internal.npmjs.com",
"tmp": "tmp/loader-utils-1.1.0.tgz_1489673126296_0.2887681087013334"
},
"_npmUser": {
"name": "jhnns",
"email": "mail@johannesewald.de"
},
"_npmVersion": "4.1.2",
"_phantomChildren": {},
"_requested": {
"raw": "loader-utils@^1.1.0",
"scope": null,
"escapedName": "loader-utils",
"name": "loader-utils",
"rawSpec": "^1.1.0",
"spec": ">=1.1.0 <2.0.0",
"type": "range"
},
"_requiredBy": [
"/vue-loader"
],
"_resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
"_shasum": "c98aef488bcceda2ffb5e2de646d6a754429f5cd",
"_shrinkwrap": null,
"_spec": "loader-utils@^1.1.0",
"_where": "c:\\xampp\\htdocs\\laravel\\node_modules\\vue-loader",
"author": {
"name": "Tobias Koppers @sokra"
},
"bugs": {
"url": "https://github.com/webpack/loader-utils/issues"
},
"dependencies": {
"big.js": "^3.1.3",
"emojis-list": "^2.0.0",
"json5": "^0.5.0"
},
"description": "utils for webpack loaders",
"devDependencies": {
"coveralls": "^2.11.2",
"eslint": "^3.15.0",
"eslint-plugin-node": "^4.0.1",
"istanbul": "^0.3.14",
"mocha": "^1.21.4",
"standard-version": "^4.0.0"
},
"directories": {},
"dist": {
"shasum": "c98aef488bcceda2ffb5e2de646d6a754429f5cd",
"tarball": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz"
},
"engines": {
"node": ">=4.0.0"
},
"files": [
"lib"
],
"gitHead": "a5602addda0c5e98e70d067b8dd050d5e4153f1d",
"homepage": "https://github.com/webpack/loader-utils#readme",
"license": "MIT",
"main": "lib/index.js",
"maintainers": [
{
"name": "jhnns",
"email": "mail@johannesewald.de"
},
{
"name": "sokra",
"email": "tobias.koppers@googlemail.com"
}
],
"name": "loader-utils",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/webpack/loader-utils.git"
},
"scripts": {
"cover": "istanbul cover -x *.runtime.js node_modules/mocha/bin/_mocha",
"lint": "eslint lib test",
"posttest": "npm run lint",
"release": "npm test && standard-version",
"test": "mocha",
"travis": "npm run cover -- --report lcovonly"
},
"version": "1.1.0"
}
+151
View File
@@ -0,0 +1,151 @@
{
"_args": [
[
{
"raw": "vue-loader@^11.1.3",
"scope": null,
"escapedName": "vue-loader",
"name": "vue-loader",
"rawSpec": "^11.1.3",
"spec": ">=11.1.3 <12.0.0",
"type": "range"
},
"c:\\xampp\\htdocs\\laravel\\node_modules\\laravel-mix"
]
],
"_from": "vue-loader@>=11.1.3 <12.0.0",
"_id": "vue-loader@11.3.4",
"_inCache": true,
"_location": "/vue-loader",
"_nodeVersion": "7.4.0",
"_npmOperationalInternal": {
"host": "packages-18-east.internal.npmjs.com",
"tmp": "tmp/vue-loader-11.3.4.tgz_1490773059829_0.01661223010160029"
},
"_npmUser": {
"name": "yyx990803",
"email": "yyx990803@gmail.com"
},
"_npmVersion": "4.0.5",
"_phantomChildren": {
"big.js": "3.1.3",
"emojis-list": "2.1.0",
"json5": "0.5.1"
},
"_requested": {
"raw": "vue-loader@^11.1.3",
"scope": null,
"escapedName": "vue-loader",
"name": "vue-loader",
"rawSpec": "^11.1.3",
"spec": ">=11.1.3 <12.0.0",
"type": "range"
},
"_requiredBy": [
"/laravel-mix"
],
"_resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-11.3.4.tgz",
"_shasum": "65e10a44ce092d906e14bbc72981dec99eb090d2",
"_shrinkwrap": null,
"_spec": "vue-loader@^11.1.3",
"_where": "c:\\xampp\\htdocs\\laravel\\node_modules\\laravel-mix",
"author": {
"name": "Evan You"
},
"bugs": {
"url": "https://github.com/vuejs/vue-loader/issues"
},
"dependencies": {
"consolidate": "^0.14.0",
"hash-sum": "^1.0.2",
"js-beautify": "^1.6.3",
"loader-utils": "^1.1.0",
"lru-cache": "^4.0.1",
"postcss": "^5.0.21",
"postcss-load-config": "^1.1.0",
"postcss-selector-parser": "^2.0.0",
"source-map": "^0.5.6",
"vue-hot-reload-api": "^2.0.11",
"vue-style-loader": "^2.0.0",
"vue-template-es2015-compiler": "^1.2.2"
},
"description": "Vue single-file component loader for Webpack",
"devDependencies": {
"babel-core": "^6.8.0",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.6.0",
"chai": "^3.0.0",
"coffee-loader": "^0.7.2",
"coffee-script": "^1.10.0",
"css-loader": "^0.26.0",
"eslint": "^3.14.1",
"eslint-config-vue": "^2.0.2",
"eslint-plugin-vue": "^2.0.0",
"expose-loader": "^0.7.1",
"extract-text-webpack-plugin": "^2.0.0-rc.0",
"file-loader": "^0.10.0",
"inject-loader": "^2.0.0",
"js-yaml": "^3.8.2",
"jsdom": "^9.2.1",
"marked": "^0.3.6",
"memory-fs": "^0.4.1",
"mkdirp": "^0.5.1",
"mocha": "^3.2.0",
"node-libs-browser": "^2.0.0",
"normalize-newline": "^3.0.0",
"null-loader": "^0.1.1",
"pug": "^2.0.0-beta6",
"raw-loader": "^0.5.1",
"skeleton-loader": "0.0.5",
"stylus": "^0.54.5",
"stylus-loader": "^2.0.0",
"sugarss": "^0.2.0",
"url-loader": "^0.5.7",
"vue": "^2.1.0",
"vue-server-renderer": "^2.1.10",
"vue-template-compiler": "^2.1.0",
"webpack": "^2.2.0"
},
"directories": {},
"dist": {
"shasum": "65e10a44ce092d906e14bbc72981dec99eb090d2",
"tarball": "https://registry.npmjs.org/vue-loader/-/vue-loader-11.3.4.tgz"
},
"files": [
"index.js",
"lib"
],
"gitHead": "5af00e58bb58329ac353c0e4048a62a33f8dac15",
"homepage": "https://github.com/vuejs/vue-loader",
"keywords": [
"vue",
"webpack",
"loader"
],
"license": "MIT",
"main": "index.js",
"maintainers": [
{
"name": "yyx990803",
"email": "yyx990803@gmail.com"
}
],
"name": "vue-loader",
"optionalDependencies": {},
"peerDependencies": {
"css-loader": "*",
"vue-template-compiler": "^2.0.0"
},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vue-loader.git"
},
"scripts": {
"docs": "cd docs && gitbook serve",
"docs:deploy": "bash ./docs/deploy.sh",
"lint": "eslint lib",
"test": "eslint lib && mocha --slow 5000 --timeout 10000"
},
"version": "11.3.4"
}