html-alt-images.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright 2018 Gildas Lormeau
  3. * contact : gildas.lormeau <at> gmail.com
  4. *
  5. * This file is part of SingleFile.
  6. *
  7. * SingleFile is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * SingleFile is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with SingleFile. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. /* global docHelper, parseSrcset */
  21. this.altImages = this.altImages || (() => {
  22. const EMPTY_IMAGE = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
  23. return {
  24. process(doc, options) {
  25. const dataAttributeName = docHelper.responsiveImagesAttributeName(options.sessionId);
  26. doc.querySelectorAll("picture").forEach(pictureElement => {
  27. const imgElement = pictureElement.querySelector("img");
  28. if (imgElement) {
  29. let srcData = getImgSrcData(pictureElement, imgElement, options);
  30. let { src, srcset } = srcData;
  31. if (!src) {
  32. const sources = Array.from(pictureElement.querySelectorAll("source")).reverse();
  33. const data = getSourceSrcData(Array.from(sources));
  34. src = data.src;
  35. srcset = srcset || data.srcset;
  36. }
  37. if (!src && options.responsiveImageData) {
  38. const responsiveImageData = options.responsiveImageData[Number(pictureElement.getAttribute(dataAttributeName))];
  39. if (responsiveImageData.src) {
  40. src = responsiveImageData.src;
  41. } else if (responsiveImageData.sources) {
  42. const sources = responsiveImageData.sources.reverse();
  43. const data = getSourceSrcData(sources);
  44. src = data.src;
  45. srcset = srcset || data.srcset;
  46. }
  47. }
  48. setSrc({ src, srcset }, pictureElement.querySelector("img"), pictureElement);
  49. }
  50. });
  51. doc.querySelectorAll(":not(picture) > img[srcset]").forEach(imgElement => setSrc(getImgSrcData(imgElement, imgElement, options), imgElement));
  52. }
  53. };
  54. function getImgSrcData(pictureElement, imgElement, options) {
  55. const dataAttributeName = docHelper.responsiveImagesAttributeName(options.sessionId);
  56. let src = imgElement.getAttribute("src");
  57. let srcset = getSourceSrc(imgElement.getAttribute("srcset"));
  58. if (options.responsiveImageData) {
  59. const responsiveImageData = options.responsiveImageData[Number(pictureElement.getAttribute(dataAttributeName))];
  60. if (!src && responsiveImageData.src) {
  61. src = responsiveImageData.src;
  62. }
  63. if (srcset && responsiveImageData.srcset) {
  64. srcset = getSourceSrc(responsiveImageData.srcset);
  65. }
  66. }
  67. return { src, srcset };
  68. }
  69. function getSourceSrcData(sources) {
  70. let source = sources.find(source => source.src);
  71. let src = source && source.src;
  72. let srcset = source && source.srcset;
  73. if (!src) {
  74. source = sources.find(source => getSourceSrc(source.src));
  75. src = source && source.src;
  76. }
  77. if (!srcset) {
  78. source = sources.find(source => getSourceSrc(source.srcset));
  79. srcset = source && source.srcset;
  80. }
  81. return { src, srcset };
  82. }
  83. function setSrc(srcData, imgElement, pictureElement) {
  84. imgElement.src = EMPTY_IMAGE;
  85. imgElement.setAttribute("srcset", "");
  86. if (srcData.src) {
  87. imgElement.src = srcData.src;
  88. } else {
  89. if (imgElement.getAttribute("srcset")) {
  90. imgElement.setAttribute("srcset", srcData.srcset || "");
  91. if (!srcData.srcset) {
  92. imgElement.setAttribute("sizes", "");
  93. }
  94. }
  95. }
  96. if (pictureElement) {
  97. pictureElement.querySelectorAll("source").forEach(sourceElement => sourceElement.remove());
  98. }
  99. }
  100. function getSourceSrc(sourceSrcSet) {
  101. if (sourceSrcSet) {
  102. const srcset = parseSrcset.process(sourceSrcSet);
  103. return (srcset.find(srcset => srcset.url)).url;
  104. }
  105. }
  106. })();