templateTransformSrcset.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.transformSrcset = exports.createSrcsetTransformWithOptions = void 0;
  7. const path_1 = __importDefault(require("path"));
  8. const compiler_core_1 = require("@vue/compiler-core");
  9. const templateUtils_1 = require("./templateUtils");
  10. const templateTransformAssetUrl_1 = require("./templateTransformAssetUrl");
  11. const srcsetTags = ['img', 'source'];
  12. // http://w3c.github.io/html/semantics-embedded-content.html#ref-for-image-candidate-string-5
  13. const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g;
  14. const createSrcsetTransformWithOptions = (options) => {
  15. return (node, context) => exports.transformSrcset(node, context, options);
  16. };
  17. exports.createSrcsetTransformWithOptions = createSrcsetTransformWithOptions;
  18. const transformSrcset = (node, context, options = templateTransformAssetUrl_1.defaultAssetUrlOptions) => {
  19. if (node.type === 1 /* NodeTypes.ELEMENT */) {
  20. if (srcsetTags.includes(node.tag) && node.props.length) {
  21. node.props.forEach((attr, index) => {
  22. if (attr.name === 'srcset' && attr.type === 6 /* NodeTypes.ATTRIBUTE */) {
  23. if (!attr.value)
  24. return;
  25. const value = attr.value.content;
  26. if (!value)
  27. return;
  28. const imageCandidates = value
  29. .split(',')
  30. .map((s) => {
  31. // The attribute value arrives here with all whitespace, except
  32. // normal spaces, represented by escape sequences
  33. const [url, descriptor] = s
  34. .replace(escapedSpaceCharacters, ' ')
  35. .trim()
  36. .split(' ', 2);
  37. return { url, descriptor };
  38. });
  39. // data urls contains comma after the ecoding so we need to re-merge
  40. // them
  41. for (let i = 0; i < imageCandidates.length; i++) {
  42. const { url } = imageCandidates[i];
  43. if ((0, templateUtils_1.isDataUrl)(url)) {
  44. imageCandidates[i + 1].url =
  45. url + ',' + imageCandidates[i + 1].url;
  46. imageCandidates.splice(i, 1);
  47. }
  48. }
  49. const hasQualifiedUrl = imageCandidates.some(({ url }) => {
  50. return (!(0, templateUtils_1.isExternalUrl)(url) &&
  51. !(0, templateUtils_1.isDataUrl)(url) &&
  52. (options.includeAbsolute || (0, templateUtils_1.isRelativeUrl)(url)));
  53. });
  54. // When srcset does not contain any qualified URLs, skip transforming
  55. if (!hasQualifiedUrl) {
  56. return;
  57. }
  58. if (options.base) {
  59. const base = options.base;
  60. const set = [];
  61. imageCandidates.forEach(({ url, descriptor }) => {
  62. descriptor = descriptor ? ` ${descriptor}` : ``;
  63. if ((0, templateUtils_1.isRelativeUrl)(url)) {
  64. set.push((path_1.default.posix || path_1.default).join(base, url) + descriptor);
  65. }
  66. else {
  67. set.push(url + descriptor);
  68. }
  69. });
  70. attr.value.content = set.join(', ');
  71. return;
  72. }
  73. const compoundExpression = (0, compiler_core_1.createCompoundExpression)([], attr.loc);
  74. imageCandidates.forEach(({ url, descriptor }, index) => {
  75. if (!(0, templateUtils_1.isExternalUrl)(url) &&
  76. !(0, templateUtils_1.isDataUrl)(url) &&
  77. (options.includeAbsolute || (0, templateUtils_1.isRelativeUrl)(url))) {
  78. const { path } = (0, templateUtils_1.parseUrl)(url);
  79. let exp;
  80. if (path) {
  81. const existingImportsIndex = context.imports.findIndex((i) => i.path === path);
  82. if (existingImportsIndex > -1) {
  83. exp = (0, compiler_core_1.createSimpleExpression)(`_imports_${existingImportsIndex}`, false, attr.loc, 2 /* ConstantTypes.CAN_HOIST */);
  84. }
  85. else {
  86. exp = (0, compiler_core_1.createSimpleExpression)(`_imports_${context.imports.length}`, false, attr.loc, 2 /* ConstantTypes.CAN_HOIST */);
  87. context.imports.push({ exp, path });
  88. }
  89. compoundExpression.children.push(exp);
  90. }
  91. }
  92. else {
  93. const exp = (0, compiler_core_1.createSimpleExpression)(`"${url}"`, false, attr.loc, 2 /* ConstantTypes.CAN_HOIST */);
  94. compoundExpression.children.push(exp);
  95. }
  96. const isNotLast = imageCandidates.length - 1 > index;
  97. if (descriptor && isNotLast) {
  98. compoundExpression.children.push(` + ' ${descriptor}, ' + `);
  99. }
  100. else if (descriptor) {
  101. compoundExpression.children.push(` + ' ${descriptor}'`);
  102. }
  103. else if (isNotLast) {
  104. compoundExpression.children.push(` + ', ' + `);
  105. }
  106. });
  107. const hoisted = context.hoist(compoundExpression);
  108. hoisted.constType = 2 /* ConstantTypes.CAN_HOIST */;
  109. node.props[index] = {
  110. type: 7 /* NodeTypes.DIRECTIVE */,
  111. name: 'bind',
  112. arg: (0, compiler_core_1.createSimpleExpression)('srcset', true, attr.loc),
  113. exp: hoisted,
  114. modifiers: [],
  115. loc: attr.loc,
  116. };
  117. }
  118. });
  119. }
  120. }
  121. };
  122. exports.transformSrcset = transformSrcset;