InnerHTML logger

Logs usage of innerHTML and outerHTML

  1. // ==UserScript==
  2. // @name InnerHTML logger
  3. // @namespace https://lafkpages.tech
  4. // @version 0.2
  5. // @description Logs usage of innerHTML and outerHTML
  6. // @author LuisAFK
  7. // @match *://*/*
  8. // @icon https://i.imgur.com/1p0A8XP.png
  9. // @icon64 https://i.imgur.com/jbvkyHD.png
  10. // @run-at document-start
  11. // @grant none
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15. (() => {
  16. const proto = Element.prototype;
  17. const props = ['innerHTML', 'outerHTML'];
  18. const injectInto = document.head || document.body || document.currentScript?.parentElement || document.documentElement;
  19. const flashClass = 'innerhtml-logger-flash';
  20. const flashProp = '__innerhtml_logger_flash_timeout';
  21. const timesUsedProp = '__innerhtml_logger_times_used';
  22.  
  23. window[timesUsedProp] = 0;
  24.  
  25. const originalProps = Object.fromEntries(
  26. props.map(prop => [
  27. prop,
  28. Object.getOwnPropertyDescriptor(proto, prop)
  29. ])
  30. );
  31.  
  32. function log(prop, elm, value) {
  33. window[timesUsedProp]++;
  34.  
  35. elm.classList.remove(flashClass);
  36. clearTimeout(elm[flashProp] || 0);
  37. setTimeout(() => {
  38. elm.classList.add(flashClass);
  39. elm[flashProp] = setTimeout(() => {
  40. elm?.classList.remove(flashClass);
  41. }, 1000);
  42. }, 10);
  43. }
  44.  
  45. function makeLoggerProp(prop) {
  46. return {
  47. get: function () {
  48. // log
  49. log(prop, this);
  50.  
  51. // call
  52. return originalProps[prop].get.call(this, ...arguments);
  53. },
  54. set: function (value) {
  55. // log
  56. log(prop, this, value);
  57.  
  58. // call
  59. return originalProps[prop].set.call(this, ...arguments);
  60. }
  61. };
  62. }
  63.  
  64. Object.defineProperties(proto, Object.fromEntries(
  65. props.map(prop => [
  66. prop,
  67. makeLoggerProp(prop)
  68. ])
  69. ));
  70.  
  71. const styles = document.createElement('style');
  72. styles.textContent = `
  73. .${flashClass} {
  74. background-image: none;
  75. animation: 1s linear 0s 1 normal forwards running ${flashClass} !important;
  76. }
  77.  
  78. @keyframes ${flashClass} {
  79. from {
  80. background-color: yellow;
  81. }
  82.  
  83. to {
  84. background-color: transparent;
  85. }
  86. };
  87. `;
  88. styles.type = 'text/css';
  89. injectInto.appendChild(styles);
  90. })();