您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Replaces dollar amounts with $**.** on app.monarchmoney.com
// ==UserScript== // @name Mask Money on MonarchMoney // @namespace http://tampermonkey.net/ // @version 1.5 // @description Replaces dollar amounts with $**.** on app.monarchmoney.com // @author JtMotoX // @match https://app.monarchmoney.com/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; const moneyRegex = /\$\d{1,3}(,\d{3})*(\.\d*)?(M|K)?/g; const maskText = '$**.**'; // Function to replace money references in text and input fields const replaceMoneyReferences = (node) => { if (node.nodeType === Node.TEXT_NODE) { if (moneyRegex.test(node.nodeValue)) { node.nodeValue = node.nodeValue.replace(moneyRegex, maskText); } } else if (node.nodeType === Node.ELEMENT_NODE) { if (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA') { if (moneyRegex.test(node.value)) { node.value = node.value.replace(moneyRegex, maskText); } } node.childNodes.forEach((child) => replaceMoneyReferences(child)); } }; // Function to process shadow roots const processShadowRoot = (root) => { const elements = root.querySelectorAll('span.number span.number__inner'); elements.forEach((el) => { if (el.textContent !== '**.**') { el.textContent = '**.**'; } }); root.childNodes.forEach((child) => replaceMoneyReferences(child)); }; // Recursive function to handle all shadow roots const traverseShadowRoots = (node, callback) => { if (!node) return; if (node.shadowRoot) { callback(node.shadowRoot); traverseShadowRoots(node.shadowRoot, callback); } node.childNodes.forEach((child) => traverseShadowRoots(child, callback)); }; // Unified function to mask all elements const maskAllElements = () => { replaceMoneyReferences(document.body); traverseShadowRoots(document.body, processShadowRoot); }; // Hide all shadow DOMs initially const preHideShadowDOMs = () => { document.querySelectorAll('*').forEach((el) => { if (el.shadowRoot) { el.shadowRoot.host.style.visibility = 'hidden'; } }); }; // Reveal shadow DOMs after masking const revealShadowDOMs = () => { document.querySelectorAll('*').forEach((el) => { if (el.shadowRoot) { el.shadowRoot.host.style.visibility = 'visible'; } }); }; // Observe for DOM and shadow DOM changes const observeDOMChanges = () => { const observer = new MutationObserver(() => { maskAllElements(); revealShadowDOMs(); // Ensure visibility is restored }); observer.observe(document.body, { childList: true, subtree: true, }); // Initial masking maskAllElements(); revealShadowDOMs(); }; const init = () => { preHideShadowDOMs(); // Mask content maskAllElements(); // Restore visibility document.body.style.visibility = 'visible'; revealShadowDOMs(); // Start observing for changes observeDOMChanges(); }; // Hide the page until all replacements have been performed document.body.style.visibility = 'hidden'; // Initialize after the page loads window.addEventListener('load', init); })();