html-images-alt-minifier.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * Copyright 2010-2019 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. this.imagesAltMinifier = this.imagesAltMinifier || (() => {
  21. const EMPTY_IMAGE = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
  22. return {
  23. process(doc) {
  24. doc.querySelectorAll("picture").forEach(pictureElement => {
  25. const imgElement = pictureElement.querySelector("img");
  26. if (imgElement) {
  27. let srcData = getImgSrcData(imgElement);
  28. let { src, srcset } = srcData;
  29. if (!src) {
  30. const sources = Array.from(pictureElement.querySelectorAll("source")).reverse();
  31. const data = getSourceSrcData(Array.from(sources));
  32. src = data.src;
  33. if (!srcset) {
  34. srcset = data.srcset;
  35. }
  36. }
  37. setSrc({ src, srcset }, imgElement, pictureElement);
  38. }
  39. });
  40. doc.querySelectorAll(":not(picture) > img[srcset]").forEach(imgElement => setSrc(getImgSrcData(imgElement), imgElement));
  41. }
  42. };
  43. function getImgSrcData(imgElement) {
  44. let src = imgElement.getAttribute("src");
  45. if (src == EMPTY_IMAGE) {
  46. src = null;
  47. }
  48. let srcset = getSourceSrc(imgElement.getAttribute("srcset"));
  49. if (srcset == EMPTY_IMAGE) {
  50. srcset = null;
  51. }
  52. return { src, srcset };
  53. }
  54. function getSourceSrcData(sources) {
  55. let source = sources.find(source => source.src);
  56. let src = source && source.src;
  57. let srcset = source && source.srcset;
  58. if (!src) {
  59. source = sources.find(source => getSourceSrc(source.src));
  60. src = source && source.src;
  61. if (src == EMPTY_IMAGE) {
  62. src = null;
  63. }
  64. }
  65. if (!srcset) {
  66. source = sources.find(source => getSourceSrc(source.srcset));
  67. srcset = source && source.srcset;
  68. if (srcset == EMPTY_IMAGE) {
  69. srcset = null;
  70. }
  71. }
  72. return { src, srcset };
  73. }
  74. function setSrc(srcData, imgElement, pictureElement) {
  75. if (srcData.src) {
  76. imgElement.setAttribute("src", srcData.src);
  77. imgElement.setAttribute("srcset", "");
  78. imgElement.setAttribute("sizes", "");
  79. } else {
  80. imgElement.setAttribute("src", EMPTY_IMAGE);
  81. if (srcData.srcset) {
  82. imgElement.setAttribute("srcset", srcData.srcset);
  83. } else {
  84. imgElement.setAttribute("srcset", "");
  85. imgElement.setAttribute("sizes", "");
  86. }
  87. }
  88. if (pictureElement) {
  89. pictureElement.querySelectorAll("source").forEach(sourceElement => sourceElement.remove());
  90. }
  91. }
  92. function getSourceSrc(sourceSrcSet) {
  93. if (sourceSrcSet) {
  94. const srcset = this.imagesAltMinifier.srcsetParser.process(sourceSrcSet);
  95. return (srcset.find(srcset => srcset.url)).url;
  96. }
  97. }
  98. })();