jialh
2025-01-07 bb59b053247ef82969b64979260e2478bd732e1f
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
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformSrcset = exports.createSrcsetTransformWithOptions = void 0;
const path_1 = __importDefault(require("path"));
const compiler_core_1 = require("@vue/compiler-core");
const templateUtils_1 = require("./templateUtils");
const templateTransformAssetUrl_1 = require("./templateTransformAssetUrl");
const srcsetTags = ['img', 'source'];
// http://w3c.github.io/html/semantics-embedded-content.html#ref-for-image-candidate-string-5
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g;
const createSrcsetTransformWithOptions = (options) => {
    return (node, context) => exports.transformSrcset(node, context, options);
};
exports.createSrcsetTransformWithOptions = createSrcsetTransformWithOptions;
const transformSrcset = (node, context, options = templateTransformAssetUrl_1.defaultAssetUrlOptions) => {
    if (node.type === 1 /* NodeTypes.ELEMENT */) {
        if (srcsetTags.includes(node.tag) && node.props.length) {
            node.props.forEach((attr, index) => {
                if (attr.name === 'srcset' && attr.type === 6 /* NodeTypes.ATTRIBUTE */) {
                    if (!attr.value)
                        return;
                    const value = attr.value.content;
                    if (!value)
                        return;
                    const imageCandidates = 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 ecoding so we need to re-merge
                    // them
                    for (let i = 0; i < imageCandidates.length; i++) {
                        const { url } = imageCandidates[i];
                        if ((0, templateUtils_1.isDataUrl)(url)) {
                            imageCandidates[i + 1].url =
                                url + ',' + imageCandidates[i + 1].url;
                            imageCandidates.splice(i, 1);
                        }
                    }
                    const hasQualifiedUrl = imageCandidates.some(({ url }) => {
                        return (!(0, templateUtils_1.isExternalUrl)(url) &&
                            !(0, templateUtils_1.isDataUrl)(url) &&
                            (options.includeAbsolute || (0, templateUtils_1.isRelativeUrl)(url)));
                    });
                    // When srcset does not contain any qualified URLs, skip transforming
                    if (!hasQualifiedUrl) {
                        return;
                    }
                    if (options.base) {
                        const base = options.base;
                        const set = [];
                        imageCandidates.forEach(({ url, descriptor }) => {
                            descriptor = descriptor ? ` ${descriptor}` : ``;
                            if ((0, templateUtils_1.isRelativeUrl)(url)) {
                                set.push((path_1.default.posix || path_1.default).join(base, url) + descriptor);
                            }
                            else {
                                set.push(url + descriptor);
                            }
                        });
                        attr.value.content = set.join(', ');
                        return;
                    }
                    const compoundExpression = (0, compiler_core_1.createCompoundExpression)([], attr.loc);
                    imageCandidates.forEach(({ url, descriptor }, index) => {
                        if (!(0, templateUtils_1.isExternalUrl)(url) &&
                            !(0, templateUtils_1.isDataUrl)(url) &&
                            (options.includeAbsolute || (0, templateUtils_1.isRelativeUrl)(url))) {
                            const { path } = (0, templateUtils_1.parseUrl)(url);
                            let exp;
                            if (path) {
                                const existingImportsIndex = context.imports.findIndex((i) => i.path === path);
                                if (existingImportsIndex > -1) {
                                    exp = (0, compiler_core_1.createSimpleExpression)(`_imports_${existingImportsIndex}`, false, attr.loc, 2 /* ConstantTypes.CAN_HOIST */);
                                }
                                else {
                                    exp = (0, compiler_core_1.createSimpleExpression)(`_imports_${context.imports.length}`, false, attr.loc, 2 /* ConstantTypes.CAN_HOIST */);
                                    context.imports.push({ exp, path });
                                }
                                compoundExpression.children.push(exp);
                            }
                        }
                        else {
                            const exp = (0, compiler_core_1.createSimpleExpression)(`"${url}"`, false, attr.loc, 2 /* ConstantTypes.CAN_HOIST */);
                            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(` + ', ' + `);
                        }
                    });
                    const hoisted = context.hoist(compoundExpression);
                    hoisted.constType = 2 /* ConstantTypes.CAN_HOIST */;
                    node.props[index] = {
                        type: 7 /* NodeTypes.DIRECTIVE */,
                        name: 'bind',
                        arg: (0, compiler_core_1.createSimpleExpression)('srcset', true, attr.loc),
                        exp: hoisted,
                        modifiers: [],
                        loc: attr.loc,
                    };
                }
            });
        }
    }
};
exports.transformSrcset = transformSrcset;