Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | 17x 17x 17x 7x 49x 17x 254x 149x 65x 113x 59x 59x 59x 55x 101x 101x 55x 93x 93x 8x 8x 55x 129x 67x 11x 44x 10x 10x 10x 10x 18x 18x 18x 14x 14x 4x 3x 1x 10x 8x 8x 36x 36x 58x 56x 56x 56x 56x 56x 53x 56x 44x 12x 12x 56x 2x 56x 2x 2x 58x 58x 10x 48x 25x 23x 12x 36x 36x 33x 33x 36x | import path from 'path'
import {
ConstantTypes,
type ExpressionNode,
type NodeTransform,
NodeTypes,
type SimpleExpressionNode,
createCompoundExpression,
createSimpleExpression,
} from '@vue/compiler-core'
import {
isDataUrl,
isExternalUrl,
isRelativeUrl,
normalizeDecodedImportPath,
parseUrl,
} from './templateUtils'
import {
type AssetURLOptions,
defaultAssetUrlOptions,
} from './transformAssetUrl'
const srcsetTags = ['img', 'source']
interface ImageCandidate {
url: string
descriptor: string
}
// http://w3c.github.io/html/semantics-embedded-content.html#ref-for-image-candidate-string-5
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g
export const createSrcsetTransformWithOptions = (
options: Required<AssetURLOptions>,
): NodeTransform => {
return (node, context) =>
(transformSrcset as Function)(node, context, options)
}
export const transformSrcset: NodeTransform = (
node,
context,
options: Required<AssetURLOptions> = defaultAssetUrlOptions,
) => {
if (node.type === NodeTypes.ELEMENT) {
if (srcsetTags.includes(node.tag) && node.props.length) {
node.props.forEach((attr, index) => {
if (attr.name === 'srcset' && attr.type === NodeTypes.ATTRIBUTE) {
Iif (!attr.value) return
const value = attr.value.content
if (!value) return
const imageCandidates: ImageCandidate[] = value.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 { url, descriptor }
})
// data urls contains comma after the encoding so we need to re-merge
// them
for (let i = 0; i < imageCandidates.length; i++) {
const { url } = imageCandidates[i]
if (isDataUrl(url)) {
imageCandidates[i + 1].url =
url + ',' + imageCandidates[i + 1].url
imageCandidates.splice(i, 1)
}
}
const shouldProcessUrl = (url: string) => {
return (
url &&
!isExternalUrl(url) &&
!isDataUrl(url) &&
(options.includeAbsolute || isRelativeUrl(url))
)
}
// When srcset does not contain any qualified URLs, skip transforming
if (!imageCandidates.some(({ url }) => shouldProcessUrl(url))) {
return
}
if (options.base) {
const base = options.base
const set: string[] = []
let needImportTransform = false
imageCandidates.forEach(candidate => {
let { url, descriptor } = candidate
descriptor = descriptor ? ` ${descriptor}` : ``
if (url[0] === '.') {
candidate.url = (path.posix || path).join(base, url)
set.push(candidate.url + descriptor)
} else if (shouldProcessUrl(url)) {
needImportTransform = true
} else {
set.push(url + descriptor)
}
})
if (!needImportTransform) {
attr.value.content = set.join(', ')
return
}
}
const compoundExpression = createCompoundExpression([], attr.loc)
imageCandidates.forEach(({ url, descriptor }, index) => {
if (shouldProcessUrl(url)) {
const { path, hash } = parseUrl(url)
const source = path ? path : hash
Eif (source) {
const normalizedSource = normalizeDecodedImportPath(source)
const existingImportsIndex = context.imports.findIndex(
i => i.path === normalizedSource,
)
let exp: SimpleExpressionNode
if (existingImportsIndex > -1) {
exp = createSimpleExpression(
`_imports_${existingImportsIndex}`,
false,
attr.loc,
ConstantTypes.CAN_STRINGIFY,
)
} else {
exp = createSimpleExpression(
`_imports_${context.imports.length}`,
false,
attr.loc,
ConstantTypes.CAN_STRINGIFY,
)
context.imports.push({ exp, path: normalizedSource })
}
if (path && hash) {
exp = createSimpleExpression(
`${exp.content} + '${hash}'`,
false,
attr.loc,
ConstantTypes.CAN_STRINGIFY,
)
}
compoundExpression.children.push(exp)
}
} else {
const exp = createSimpleExpression(
`"${url}"`,
false,
attr.loc,
ConstantTypes.CAN_STRINGIFY,
)
compoundExpression.children.push(exp)
}
const isNotLast = imageCandidates.length - 1 > index
if (descriptor && isNotLast) {
compoundExpression.children.push(` + ' ${descriptor}, ' + `)
} else if (descriptor) {
compoundExpression.children.push(` + ' ${descriptor}'`)
} else if (isNotLast) {
compoundExpression.children.push(` + ', ' + `)
}
})
let exp: ExpressionNode = compoundExpression
if (context.hoistStatic) {
exp = context.hoist(compoundExpression)
exp.constType = ConstantTypes.CAN_STRINGIFY
}
node.props[index] = {
type: NodeTypes.DIRECTIVE,
name: 'bind',
arg: createSimpleExpression('srcset', true, attr.loc),
exp,
modifiers: [],
loc: attr.loc,
}
}
})
}
}
}
|