aboutsummaryrefslogtreecommitdiff
path: root/node_modules/@vue/component-compiler-utils/lib
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@vue/component-compiler-utils/lib')
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/compileStyle.ts143
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/compileTemplate.ts176
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/index.ts28
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/parse.ts112
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/stylePlugins/scoped.ts98
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/stylePlugins/trim.ts10
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/styleProcessors/index.ts133
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/assetUrl.ts51
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/srcset.ts66
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/utils.ts54
-rw-r--r--node_modules/@vue/component-compiler-utils/lib/types.ts47
11 files changed, 918 insertions, 0 deletions
diff --git a/node_modules/@vue/component-compiler-utils/lib/compileStyle.ts b/node_modules/@vue/component-compiler-utils/lib/compileStyle.ts
new file mode 100644
index 00000000..bbd39c3f
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/compileStyle.ts
@@ -0,0 +1,143 @@
+const postcss = require('postcss')
+import { ProcessOptions, LazyResult } from 'postcss'
+import trimPlugin from './stylePlugins/trim'
+import scopedPlugin from './stylePlugins/scoped'
+import {
+ processors,
+ StylePreprocessor,
+ StylePreprocessorResults
+} from './styleProcessors'
+
+export interface StyleCompileOptions {
+ source: string
+ filename: string
+ id: string
+ map?: any
+ scoped?: boolean
+ trim?: boolean
+ preprocessLang?: string
+ preprocessOptions?: any
+ postcssOptions?: any
+ postcssPlugins?: any[]
+}
+
+export interface AsyncStyleCompileOptions extends StyleCompileOptions {
+ isAsync?: boolean
+}
+
+export interface StyleCompileResults {
+ code: string
+ map: any | void
+ rawResult: LazyResult | void
+ errors: string[]
+}
+
+export function compileStyle(
+ options: StyleCompileOptions
+): StyleCompileResults {
+ return doCompileStyle({ ...options, isAsync: false })
+}
+
+export function compileStyleAsync(
+ options: StyleCompileOptions
+): Promise<StyleCompileResults> {
+ return Promise.resolve(doCompileStyle({ ...options, isAsync: true }))
+}
+
+export function doCompileStyle(
+ options: AsyncStyleCompileOptions
+): StyleCompileResults {
+ const {
+ filename,
+ id,
+ scoped = true,
+ trim = true,
+ preprocessLang,
+ postcssOptions,
+ postcssPlugins
+ } = options
+ const preprocessor = preprocessLang && processors[preprocessLang]
+ const preProcessedSource = preprocessor && preprocess(options, preprocessor)
+ const map = preProcessedSource ? preProcessedSource.map : options.map
+ const source = preProcessedSource ? preProcessedSource.code : options.source
+
+ const plugins = (postcssPlugins || []).slice()
+ if (trim) {
+ plugins.push(trimPlugin())
+ }
+ if (scoped) {
+ plugins.push(scopedPlugin(id))
+ }
+
+ const postCSSOptions: ProcessOptions = {
+ ...postcssOptions,
+ to: filename,
+ from: filename
+ }
+ if (map) {
+ postCSSOptions.map = {
+ inline: false,
+ annotation: false,
+ prev: map
+ }
+ }
+
+ let result, code, outMap
+ const errors: any[] = []
+ if (preProcessedSource && preProcessedSource.errors.length) {
+ errors.push(...preProcessedSource.errors)
+ }
+ try {
+ result = postcss(plugins).process(source, postCSSOptions)
+
+ // In async mode, return a promise.
+ if (options.isAsync) {
+ return result
+ .then(
+ (result: LazyResult): StyleCompileResults => ({
+ code: result.css || '',
+ map: result.map && result.map.toJSON(),
+ errors,
+ rawResult: result
+ })
+ )
+ .catch(
+ (error: Error): StyleCompileResults => ({
+ code: '',
+ map: undefined,
+ errors: [...errors, error.message],
+ rawResult: undefined
+ })
+ )
+ }
+
+ // force synchronous transform (we know we only have sync plugins)
+ code = result.css
+ outMap = result.map
+ } catch (e) {
+ errors.push(e)
+ }
+
+ return {
+ code: code || ``,
+ map: outMap && outMap.toJSON(),
+ errors,
+ rawResult: result
+ }
+}
+
+function preprocess(
+ options: StyleCompileOptions,
+ preprocessor: StylePreprocessor
+): StylePreprocessorResults {
+ return preprocessor.render(
+ options.source,
+ options.map,
+ Object.assign(
+ {
+ filename: options.filename
+ },
+ options.preprocessOptions
+ )
+ )
+}
diff --git a/node_modules/@vue/component-compiler-utils/lib/compileTemplate.ts b/node_modules/@vue/component-compiler-utils/lib/compileTemplate.ts
new file mode 100644
index 00000000..13bb3c80
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/compileTemplate.ts
@@ -0,0 +1,176 @@
+import { VueTemplateCompiler, VueTemplateCompilerOptions } from './types'
+
+import assetUrlsModule, {
+ AssetURLOptions
+} from './templateCompilerModules/assetUrl'
+import srcsetModule from './templateCompilerModules/srcset'
+
+const prettier = require('prettier')
+const consolidate = require('consolidate')
+const transpile = require('vue-template-es2015-compiler')
+
+export interface TemplateCompileOptions {
+ source: string
+ filename: string
+ compiler: VueTemplateCompiler
+ compilerOptions?: VueTemplateCompilerOptions
+ transformAssetUrls?: AssetURLOptions | boolean
+ preprocessLang?: string
+ preprocessOptions?: any
+ transpileOptions?: any
+ isProduction?: boolean
+ isFunctional?: boolean
+ optimizeSSR?: boolean
+}
+
+export interface TemplateCompileResult {
+ code: string
+ source: string
+ tips: string[]
+ errors: string[]
+}
+
+export function compileTemplate(
+ options: TemplateCompileOptions
+): TemplateCompileResult {
+ const { preprocessLang } = options
+ const preprocessor = preprocessLang && consolidate[preprocessLang]
+ if (preprocessor) {
+ return actuallyCompile(
+ Object.assign({}, options, {
+ source: preprocess(options, preprocessor)
+ })
+ )
+ } else if (preprocessLang) {
+ return {
+ code: `var render = function () {}\n` + `var staticRenderFns = []\n`,
+ source: options.source,
+ tips: [
+ `Component ${
+ options.filename
+ } uses lang ${preprocessLang} for template. Please install the language preprocessor.`
+ ],
+ errors: [
+ `Component ${
+ options.filename
+ } uses lang ${preprocessLang} for template, however it is not installed.`
+ ]
+ }
+ } else {
+ return actuallyCompile(options)
+ }
+}
+
+function preprocess(
+ options: TemplateCompileOptions,
+ preprocessor: any
+): string {
+ const { source, filename, preprocessOptions } = options
+
+ const finalPreprocessOptions = Object.assign(
+ {
+ filename
+ },
+ preprocessOptions
+ )
+
+ // Consolidate exposes a callback based API, but the callback is in fact
+ // called synchronously for most templating engines. In our case, we have to
+ // expose a synchronous API so that it is usable in Jest transforms (which
+ // have to be sync because they are applied via Node.js require hooks)
+ let res: any, err
+ preprocessor.render(
+ source,
+ finalPreprocessOptions,
+ (_err: Error | null, _res: string) => {
+ if (_err) err = _err
+ res = _res
+ }
+ )
+
+ if (err) throw err
+ return res
+}
+
+function actuallyCompile(
+ options: TemplateCompileOptions
+): TemplateCompileResult {
+ const {
+ source,
+ compiler,
+ compilerOptions = {},
+ transpileOptions = {},
+ transformAssetUrls,
+ isProduction = process.env.NODE_ENV === 'production',
+ isFunctional = false,
+ optimizeSSR = false
+ } = options
+
+ const compile =
+ optimizeSSR && compiler.ssrCompile ? compiler.ssrCompile : compiler.compile
+
+ let finalCompilerOptions = compilerOptions
+ if (transformAssetUrls) {
+ const builtInModules = [
+ transformAssetUrls === true
+ ? assetUrlsModule()
+ : assetUrlsModule(transformAssetUrls),
+ srcsetModule()
+ ]
+ finalCompilerOptions = Object.assign({}, compilerOptions, {
+ modules: [...builtInModules, ...(compilerOptions.modules || [])]
+ })
+ }
+
+ const { render, staticRenderFns, tips, errors } = compile(
+ source,
+ finalCompilerOptions
+ )
+
+ if (errors && errors.length) {
+ return {
+ code: `var render = function () {}\n` + `var staticRenderFns = []\n`,
+ source,
+ tips,
+ errors
+ }
+ } else {
+ const finalTranspileOptions = Object.assign({}, transpileOptions, {
+ transforms: Object.assign({}, transpileOptions.transforms, {
+ stripWithFunctional: isFunctional
+ })
+ })
+
+ const toFunction = (code: string): string => {
+ return `function (${isFunctional ? `_h,_vm` : ``}) {${code}}`
+ }
+
+ // transpile code with vue-template-es2015-compiler, which is a forked
+ // version of Buble that applies ES2015 transforms + stripping `with` usage
+ let code =
+ transpile(
+ `var __render__ = ${toFunction(render)}\n` +
+ `var __staticRenderFns__ = [${staticRenderFns.map(toFunction)}]`,
+ finalTranspileOptions
+ ) + `\n`
+
+ // #23 we use __render__ to avoid `render` not being prefixed by the
+ // transpiler when stripping with, but revert it back to `render` to
+ // maintain backwards compat
+ code = code.replace(/\s__(render|staticRenderFns)__\s/g, ' $1 ')
+
+ if (!isProduction) {
+ // mark with stripped (this enables Vue to use correct runtime proxy
+ // detection)
+ code += `render._withStripped = true`
+ code = prettier.format(code, { semi: false, parser: 'babylon' })
+ }
+
+ return {
+ code,
+ source,
+ tips,
+ errors
+ }
+ }
+}
diff --git a/node_modules/@vue/component-compiler-utils/lib/index.ts b/node_modules/@vue/component-compiler-utils/lib/index.ts
new file mode 100644
index 00000000..79d22ece
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/index.ts
@@ -0,0 +1,28 @@
+import { parse, SFCBlock, SFCCustomBlock, SFCDescriptor } from './parse'
+
+import {
+ compileTemplate,
+ TemplateCompileOptions,
+ TemplateCompileResult
+} from './compileTemplate'
+
+import {
+ compileStyle,
+ compileStyleAsync,
+ StyleCompileOptions,
+ StyleCompileResults
+} from './compileStyle'
+
+// API
+export { parse, compileTemplate, compileStyle, compileStyleAsync }
+
+// types
+export {
+ SFCBlock,
+ SFCCustomBlock,
+ SFCDescriptor,
+ TemplateCompileOptions,
+ TemplateCompileResult,
+ StyleCompileOptions,
+ StyleCompileResults
+}
diff --git a/node_modules/@vue/component-compiler-utils/lib/parse.ts b/node_modules/@vue/component-compiler-utils/lib/parse.ts
new file mode 100644
index 00000000..8fbd70ee
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/parse.ts
@@ -0,0 +1,112 @@
+import {
+ RawSourceMap,
+ VueTemplateCompiler,
+ VueTemplateCompilerParseOptions
+} from './types'
+
+const hash = require('hash-sum')
+const cache = require('lru-cache')(100)
+const { SourceMapGenerator } = require('source-map')
+
+const splitRE = /\r?\n/g
+const emptyRE = /^(?:\/\/)?\s*$/
+
+export interface ParseOptions {
+ source: string
+ filename?: string
+ compiler: VueTemplateCompiler
+ compilerParseOptions?: VueTemplateCompilerParseOptions
+ sourceRoot?: string
+ needMap?: boolean
+}
+
+export interface SFCCustomBlock {
+ type: string
+ content: string
+ attrs: { [key: string]: string | true }
+ start: number
+ end: number
+ map?: RawSourceMap
+}
+
+export interface SFCBlock extends SFCCustomBlock {
+ lang?: string
+ src?: string
+ scoped?: boolean
+ module?: string | boolean
+}
+
+export interface SFCDescriptor {
+ template: SFCBlock | null
+ script: SFCBlock | null
+ styles: SFCBlock[]
+ customBlocks: SFCCustomBlock[]
+}
+
+export function parse(options: ParseOptions): SFCDescriptor {
+ const {
+ source,
+ filename = '',
+ compiler,
+ compilerParseOptions = { pad: 'line' },
+ sourceRoot = process.cwd(),
+ needMap = true
+ } = options
+ const cacheKey = hash(filename + source)
+ let output: SFCDescriptor = cache.get(cacheKey)
+ if (output) return output
+ output = compiler.parseComponent(source, compilerParseOptions)
+ if (needMap) {
+ if (output.script && !output.script.src) {
+ output.script.map = generateSourceMap(
+ filename,
+ source,
+ output.script.content,
+ sourceRoot
+ )
+ }
+ if (output.styles) {
+ output.styles.forEach(style => {
+ if (!style.src) {
+ style.map = generateSourceMap(
+ filename,
+ source,
+ style.content,
+ sourceRoot
+ )
+ }
+ })
+ }
+ }
+ cache.set(cacheKey, output)
+ return output
+}
+
+function generateSourceMap(
+ filename: string,
+ source: string,
+ generated: string,
+ sourceRoot: string
+): RawSourceMap {
+ const map = new SourceMapGenerator({
+ file: filename,
+ sourceRoot
+ })
+ 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()
+}
diff --git a/node_modules/@vue/component-compiler-utils/lib/stylePlugins/scoped.ts b/node_modules/@vue/component-compiler-utils/lib/stylePlugins/scoped.ts
new file mode 100644
index 00000000..c0ce6c2a
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/stylePlugins/scoped.ts
@@ -0,0 +1,98 @@
+import { Root } from 'postcss'
+import * as postcss from 'postcss'
+// postcss-selector-parser does have typings but it's problematic to work with.
+const selectorParser = require('postcss-selector-parser')
+
+export default postcss.plugin('add-id', (options: any) => (root: Root) => {
+ const id: string = options
+ const keyframes = Object.create(null)
+
+ root.each(function rewriteSelector(node: any) {
+ if (!node.selector) {
+ // handle media queries
+ if (node.type === 'atrule') {
+ if (node.name === 'media' || node.name === 'supports') {
+ node.each(rewriteSelector)
+ } else if (/-?keyframes$/.test(node.name)) {
+ // register keyframes
+ keyframes[node.params] = node.params = node.params + '-' + id
+ }
+ }
+ return
+ }
+ node.selector = selectorParser((selectors: any) => {
+ selectors.each((selector: any) => {
+ let node: any = null
+
+ selector.each((n: any) => {
+ // ">>>" combinator
+ if (n.type === 'combinator' && n.value === '>>>') {
+ n.value = ' '
+ n.spaces.before = n.spaces.after = ''
+ return false
+ }
+ // /deep/ alias for >>>, since >>> doesn't work in SASS
+ if (n.type === 'tag' && n.value === '/deep/') {
+ const prev = n.prev()
+ if (prev && prev.type === 'combinator' && prev.value === ' ') {
+ prev.remove()
+ }
+ n.remove()
+ return false
+ }
+ if (n.type !== 'pseudo' && n.type !== 'combinator') {
+ node = n
+ }
+ })
+
+ if (node) {
+ node.spaces.after = ''
+ } else {
+ // For deep selectors & standalone pseudo selectors,
+ // the attribute selectors are prepended rather than appended.
+ // So all leading spaces must be eliminated to avoid problems.
+ selector.first.spaces.before = ''
+ }
+
+ selector.insertAfter(
+ node,
+ selectorParser.attribute({
+ attribute: id
+ })
+ )
+ })
+ }).processSync(node.selector)
+ })
+
+ // If keyframes are found in this <style>, find and rewrite animation names
+ // in declarations.
+ // Caveat: this only works for keyframes and animation rules in the same
+ // <style> element.
+ if (Object.keys(keyframes).length) {
+ root.walkDecls(decl => {
+ // individual animation-name declaration
+ if (/^(-\w+-)?animation-name$/.test(decl.prop)) {
+ decl.value = decl.value
+ .split(',')
+ .map(v => keyframes[v.trim()] || v.trim())
+ .join(',')
+ }
+ // shorthand
+ if (/^(-\w+-)?animation$/.test(decl.prop)) {
+ decl.value = decl.value
+ .split(',')
+ .map(v => {
+ const vals = v.trim().split(/\s+/)
+ const i = vals.findIndex(val => keyframes[val])
+ if (i !== -1) {
+ vals.splice(i, 1, keyframes[vals[i]])
+ return vals.join(' ')
+ } else {
+ return v
+ }
+ })
+ .join(',')
+ }
+ })
+ }
+})
diff --git a/node_modules/@vue/component-compiler-utils/lib/stylePlugins/trim.ts b/node_modules/@vue/component-compiler-utils/lib/stylePlugins/trim.ts
new file mode 100644
index 00000000..a7e9a0db
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/stylePlugins/trim.ts
@@ -0,0 +1,10 @@
+import { Root } from 'postcss'
+import * as postcss from 'postcss'
+
+export default postcss.plugin('trim', () => (css: Root) => {
+ css.walk(({ type, raws }) => {
+ if (type === 'rule' || type === 'atrule') {
+ raws.before = raws.after = '\n'
+ }
+ })
+})
diff --git a/node_modules/@vue/component-compiler-utils/lib/styleProcessors/index.ts b/node_modules/@vue/component-compiler-utils/lib/styleProcessors/index.ts
new file mode 100644
index 00000000..b458c52e
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/styleProcessors/index.ts
@@ -0,0 +1,133 @@
+const merge = require('merge-source-map')
+
+export interface StylePreprocessor {
+ render(
+ source: string,
+ map: any | null,
+ options: any
+ ): StylePreprocessorResults
+}
+
+export interface StylePreprocessorResults {
+ code: string
+ map?: any
+ errors: Array<Error>
+}
+
+// .scss/.sass processor
+const scss: StylePreprocessor = {
+ render(
+ source: string,
+ map: any | null,
+ options: any
+ ): StylePreprocessorResults {
+ const nodeSass = require('node-sass')
+ const finalOptions = Object.assign({}, options, {
+ data: source,
+ file: options.filename,
+ outFile: options.filename,
+ sourceMap: !!map
+ })
+
+ try {
+ const result = nodeSass.renderSync(finalOptions)
+
+ if (map) {
+ return {
+ code: result.css.toString(),
+ map: merge(map, JSON.parse(result.map.toString())),
+ errors: []
+ }
+ }
+
+ return { code: result.css.toString(), errors: [] }
+ } catch (e) {
+ return { code: '', errors: [e] }
+ }
+ }
+}
+
+const sass = {
+ render(
+ source: string,
+ map: any | null,
+ options: any
+ ): StylePreprocessorResults {
+ return scss.render(
+ source,
+ map,
+ Object.assign({}, options, { indentedSyntax: true })
+ )
+ }
+}
+
+// .less
+const less = {
+ render(
+ source: string,
+ map: any | null,
+ options: any
+ ): StylePreprocessorResults {
+ const nodeLess = require('less')
+
+ let result: any
+ let error: Error | null = null
+ nodeLess.render(
+ source,
+ Object.assign({}, options, { syncImport: true }),
+ (err: Error | null, output: any) => {
+ error = err
+ result = output
+ }
+ )
+
+ if (error) return { code: '', errors: [error] }
+
+ if (map) {
+ return {
+ code: result.css.toString(),
+ map: merge(map, result.map),
+ errors: []
+ }
+ }
+
+ return { code: result.css.toString(), errors: [] }
+ }
+}
+
+// .styl
+const styl = {
+ render(
+ source: string,
+ map: any | null,
+ options: any
+ ): StylePreprocessorResults {
+ const nodeStylus = require('stylus')
+ try {
+ const ref = nodeStylus(source)
+ Object.keys(options).forEach(key => ref.set(key, options[key]))
+ if (map) ref.set('sourcemap', { inline: false, comment: false })
+
+ const result = ref.render()
+ if (map) {
+ return {
+ code: result,
+ map: merge(map, ref.sourcemap),
+ errors: []
+ }
+ }
+
+ return { code: result, errors: [] }
+ } catch (e) {
+ return { code: '', errors: [e] }
+ }
+ }
+}
+
+export const processors: { [key: string]: StylePreprocessor } = {
+ less,
+ sass,
+ scss,
+ styl,
+ stylus: styl
+}
diff --git a/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/assetUrl.ts b/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/assetUrl.ts
new file mode 100644
index 00000000..b74b0596
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/assetUrl.ts
@@ -0,0 +1,51 @@
+// vue compiler module for transforming `<tag>:<attribute>` to `require`
+
+import { urlToRequire, ASTNode, Attr } from './utils'
+
+export interface AssetURLOptions {
+ [name: string]: string | string[]
+}
+
+const defaultOptions: AssetURLOptions = {
+ video: ['src', 'poster'],
+ source: 'src',
+ img: 'src',
+ image: ['xlink:href', 'href']
+}
+
+export default (userOptions?: AssetURLOptions) => {
+ const options = userOptions
+ ? Object.assign({}, defaultOptions, userOptions)
+ : defaultOptions
+
+ return {
+ postTransformNode: (node: ASTNode) => {
+ transform(node, options)
+ }
+ }
+}
+
+function transform(node: ASTNode, options: AssetURLOptions) {
+ for (const tag in options) {
+ if ((tag === '*' || node.tag === tag) && node.attrs) {
+ const 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: Attr, name: string) {
+ if (attr.name === name) {
+ const value = attr.value
+ // only transform static URLs
+ if (value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
+ attr.value = urlToRequire(value.slice(1, -1))
+ return true
+ }
+ }
+ return false
+}
diff --git a/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/srcset.ts b/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/srcset.ts
new file mode 100644
index 00000000..7cb7544e
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/srcset.ts
@@ -0,0 +1,66 @@
+// vue compiler module for transforming `img:srcset` to a number of `require`s
+
+import { urlToRequire, ASTNode } from './utils'
+
+interface ImageCandidate {
+ require: string
+ descriptor: string
+}
+
+export default () => ({
+ postTransformNode: (node: ASTNode) => {
+ transform(node)
+ }
+})
+
+// http://w3c.github.io/html/semantics-embedded-content.html#ref-for-image-candidate-string-5
+const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g
+
+function transform(node: ASTNode) {
+ const tags = ['img', 'source']
+
+ if (tags.indexOf(node.tag) !== -1 && node.attrs) {
+ node.attrs.forEach(attr => {
+ if (attr.name === 'srcset') {
+ // same logic as in transform-require.js
+ const value = attr.value
+ const isStatic =
+ value.charAt(0) === '"' && value.charAt(value.length - 1) === '"'
+ if (!isStatic) {
+ return
+ }
+
+ const imageCandidates: ImageCandidate[] = value
+ .substr(1, value.length - 2)
+ .split(',')
+ .map(s => {
+ // The attribute value arrives here with all whitespace, except
+ // normal spaces, represented by escape sequences
+ const [url, descriptor] = s
+ .replace(escapedSpaceCharacters, ' ')
+ .trim()
+ .split(' ', 2)
+ return { require: urlToRequire(url), descriptor }
+ })
+
+ // "require(url1)"
+ // "require(url1) 1x"
+ // "require(url1), require(url2)"
+ // "require(url1), require(url2) 2x"
+ // "require(url1) 1x, require(url2)"
+ // "require(url1) 1x, require(url2) 2x"
+ const code = imageCandidates
+ .map(
+ ({ require, descriptor }) =>
+ `${require} + "${descriptor ? ' ' + descriptor : ''}, " + `
+ )
+ .join('')
+ .slice(0, -6)
+ .concat('"')
+ .replace(/ \+ ""$/, '')
+
+ attr.value = code
+ }
+ })
+ }
+}
diff --git a/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/utils.ts b/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/utils.ts
new file mode 100644
index 00000000..893d8a41
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/templateCompilerModules/utils.ts
@@ -0,0 +1,54 @@
+export interface Attr {
+ name: string
+ value: string
+}
+
+export interface ASTNode {
+ tag: string
+ attrs: Attr[]
+}
+
+import { UrlWithStringQuery, parse as uriParse } from 'url'
+
+export function urlToRequire(url: string): string {
+ const returnValue = `"${url}"`
+ // same logic as in transform-require.js
+ const firstChar = url.charAt(0)
+ if (firstChar === '.' || firstChar === '~' || firstChar === '@') {
+ if (firstChar === '~') {
+ const secondChar = url.charAt(1)
+ url = url.slice(secondChar === '/' ? 2 : 1)
+ }
+
+ const uriParts = parseUriParts(url)
+
+ if (!uriParts.hash) {
+ return `require("${url}")`
+ } else {
+ // support uri fragment case by excluding it from
+ // the require and instead appending it as string;
+ // assuming that the path part is sufficient according to
+ // the above caseing(t.i. no protocol-auth-host parts expected)
+ return `require("${uriParts.path}") + "${uriParts.hash}"`
+ }
+ }
+ return returnValue
+}
+
+/**
+ * vuejs/component-compiler-utils#22 Support uri fragment in transformed require
+ * @param urlString an url as a string
+ */
+function parseUriParts(urlString: string): UrlWithStringQuery {
+ // initialize return value
+ const returnValue: UrlWithStringQuery = uriParse('')
+ if (urlString) {
+ // A TypeError is thrown if urlString is not a string
+ // @see https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost
+ if ('string' === typeof urlString) {
+ // check is an uri
+ return uriParse(urlString) // take apart the uri
+ }
+ }
+ return returnValue
+}
diff --git a/node_modules/@vue/component-compiler-utils/lib/types.ts b/node_modules/@vue/component-compiler-utils/lib/types.ts
new file mode 100644
index 00000000..b5305201
--- /dev/null
+++ b/node_modules/@vue/component-compiler-utils/lib/types.ts
@@ -0,0 +1,47 @@
+import { SFCDescriptor } from './parse'
+
+export interface StartOfSourceMap {
+ file?: string
+ sourceRoot?: string
+}
+
+export interface RawSourceMap extends StartOfSourceMap {
+ version: string
+ sources: string[]
+ names: string[]
+ sourcesContent?: string[]
+ mappings: string
+}
+
+export interface VueTemplateCompiler {
+ parseComponent(source: string, options?: any): SFCDescriptor
+
+ compile(
+ template: string,
+ options: VueTemplateCompilerOptions
+ ): VueTemplateCompilerResults
+
+ ssrCompile(
+ template: string,
+ options: VueTemplateCompilerOptions
+ ): VueTemplateCompilerResults
+}
+
+// we'll just shim this much for now - in the future these types
+// should come from vue-template-compiler directly, or this package should be
+// part of the vue monorepo.
+export interface VueTemplateCompilerOptions {
+ modules?: Object[]
+}
+
+export interface VueTemplateCompilerParseOptions {
+ pad?: 'line' | 'space'
+}
+
+export interface VueTemplateCompilerResults {
+ ast: Object | void
+ render: string
+ staticRenderFns: string[]
+ errors: string[]
+ tips: string[]
+}