Twitter Image Expander

Prevents images in the twitter feed from having the top and bottom cropped off

  1. // ==UserScript==
  2. // @name Twitter Image Expander
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Prevents images in the twitter feed from having the top and bottom cropped off
  6. // @author Ambit
  7. // @match https://twitter.com/*
  8. // @icon https://www.google.com/s2/favicons?domain=twitter.com
  9. // @grant none
  10. // @licnse ISC; https://opensource.org/licenses/ISC
  11. // ==/UserScript==
  12.  
  13. // Copyright 2021 Ambit
  14. //
  15. // Permission to use, copy, modify, and/or distribute this software for any
  16. // purpose with or without fee is hereby granted, provided that the above
  17. // copyright notice and this permission notice appear in all copies.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  20. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  21. // FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  22. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  23. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  24. // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  25. // PERFORMANCE OF THIS SOFTWARE.
  26.  
  27. (function() {
  28. 'use strict';
  29. const enableDebugLogging = false;
  30. // Width to use for resizing when the container has no computed size yet
  31. const defaultWidth = 505;
  32.  
  33. console.info("Twitter Image Expander loaded");
  34.  
  35. function logat(level, ...args) {
  36. if (level == "debug" && !enableDebugLogging) return;
  37. console[level]("twimg-expand:", ...args);
  38. }
  39.  
  40. function debug(...args) { logat("debug", ...args); }
  41. function warn(...args) { logat("warn", ...args); }
  42.  
  43. var globalStyle = document.createElement("style");
  44. globalStyle.type = "text/css";
  45. document.head.appendChild(globalStyle);
  46. globalStyle.sheet.insertRule(`
  47. [data-testid="tweetPhoto"] {
  48. margin: 0px !important;
  49. }`);
  50. globalStyle.sheet.insertRule(`
  51. [data-testid="tweetPhoto"] >div {
  52. background-size: contain !important;
  53. }`);
  54.  
  55. function fixImageContainer(container, image) {
  56. debug(`h: ${image.naturalHeight}, w: ${image.naturalWidth}, container:`, container);
  57. if (image.naturalHeight == 0 || image.naturalWidth == 0) return;
  58. var child = container.querySelector(".r-1adg3ll.r-13qz1uu");
  59. if (!child) {
  60. warn("image viewport controlling container not found, skipping");
  61. return;
  62. }
  63. var ratio = (container.clientWidth || defaultWidth) / image.naturalWidth
  64. var height = image.naturalHeight * ratio;
  65. debug(`setting height to ${height}px based on ratio ${ratio} for element`, child);
  66. child.style.paddingBottom = `${height}px`;
  67. }
  68.  
  69. function isPhotoDiv(node) {
  70. return node && node.localName == "div" && node.getAttribute("data-testid") == "tweetPhoto";
  71. }
  72.  
  73. function fixNode(node) {
  74. if (node.localName == "img"
  75. && isPhotoDiv(node.parentElement)
  76. && node.parentElement.parentElement
  77. && node.parentElement.parentElement.parentElement) {
  78. var container = node.parentElement.parentElement.parentElement;
  79.  
  80. debug("attaching image fixer");
  81. node.addEventListener("load", function(event) {
  82. fixImageContainer(container, node);
  83. });
  84.  
  85. if (node.complete) {
  86. fixImageContainer(container, node);
  87. }
  88. }
  89. }
  90.  
  91. debug("fixing initial nodes");
  92. var nodes = document.body.getElementsByTagName("img");
  93. for (var i = 0; i < nodes.length; i++) {
  94. fixNode(nodes[i]);
  95. }
  96.  
  97. var observer = new MutationObserver(mutationList => {
  98. mutationList.forEach(mutation => {
  99. mutation.addedNodes.forEach(fixNode);
  100. });
  101. });
  102.  
  103. debug("watching for new image posts");
  104. observer.observe(document.body, {childList: true, subtree: true});
  105. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址