InnerHTML logger

Logs usage of innerHTML and outerHTML

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

You will need to install an extension such as Tampermonkey to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name         InnerHTML logger
// @namespace    https://lafkpages.tech
// @version      0.2
// @description  Logs usage of innerHTML and outerHTML
// @author       LuisAFK
// @match        *://*/*
// @icon         https://i.imgur.com/1p0A8XP.png
// @icon64       https://i.imgur.com/jbvkyHD.png
// @run-at       document-start
// @grant        none
// @license      MIT
// ==/UserScript==

(() => {
  const proto = Element.prototype;
  const props = ['innerHTML', 'outerHTML'];
  const injectInto = document.head || document.body || document.currentScript?.parentElement || document.documentElement;
  const flashClass = 'innerhtml-logger-flash';
  const flashProp = '__innerhtml_logger_flash_timeout';
  const timesUsedProp = '__innerhtml_logger_times_used';

  window[timesUsedProp] = 0;

  const originalProps = Object.fromEntries(
    props.map(prop => [
      prop,
      Object.getOwnPropertyDescriptor(proto, prop)
    ])
  );

  function log(prop, elm, value) {
    window[timesUsedProp]++;

    elm.classList.remove(flashClass);
    clearTimeout(elm[flashProp] || 0);
    setTimeout(() => {
      elm.classList.add(flashClass);
      elm[flashProp] = setTimeout(() => {
        elm?.classList.remove(flashClass);
      }, 1000);
    }, 10);
  }

  function makeLoggerProp(prop) {
    return {
      get: function () {
        // log
        log(prop, this);

        // call
        return originalProps[prop].get.call(this, ...arguments);
      },
      set: function (value) {
        // log
        log(prop, this, value);

        // call
        return originalProps[prop].set.call(this, ...arguments);
      }
    };
  }

  Object.defineProperties(proto, Object.fromEntries(
    props.map(prop => [
      prop,
      makeLoggerProp(prop)
    ])
  ));

  const styles = document.createElement('style');
  styles.textContent = `
    .${flashClass} {
      background-image: none;
      animation: 1s linear 0s 1 normal forwards running ${flashClass} !important;
    }

    @keyframes ${flashClass} {
      from {
        background-color: yellow;
      }

      to {
        background-color: transparent;
      }
    };
  `;
  styles.type = 'text/css';
  injectInto.appendChild(styles);
})();