Created
December 17, 2025 10:44
-
-
Save malys/793a5ec62e7d49df1b5c8836e2facae2 to your computer and use it in GitHub Desktop.
[Outline] minimal view #userscript #violentmonkey
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Outline Minimal View | |
| // @namespace http://tampermonkey.net/ | |
| // @version 3.1 | |
| // @description Show minimal view of Outline documents - title and body only | |
| // @author You | |
| // @match https://*/doc/* | |
| // @grant none | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| function toRemove(elements, level = 1) { | |
| elements.forEach(function(element) { | |
| let parentElement = element.parentElement; | |
| let currentLevel = 0; | |
| // Loop to traverse up the DOM tree up to the specified level | |
| while (parentElement && currentLevel < level) { | |
| let nextElement = parentElement.parentElement; // Store the parent before removal | |
| parentElement.remove(); // Remove the current parent | |
| parentElement = nextElement; // Move to the next level up | |
| currentLevel++; | |
| } | |
| }); | |
| } | |
| // Check if minimal=true is in URL parameters | |
| const urlParams = new URLSearchParams(window.location.search); | |
| if (urlParams.get('minimal') !== 'true') { | |
| return; | |
| } | |
| let isMinimalMode = false; | |
| let originalStyles = new Map(); | |
| function enableMinimalMode() { | |
| if (isMinimalMode) return; | |
| isMinimalMode = true; | |
| // Store original styles before hiding | |
| const elementsToHide = [ | |
| '#sidebar', | |
| 'header', | |
| 'nav', | |
| 'footer', | |
| 'button:not([contenteditable])', | |
| '[role="toolbar"]', | |
| '[aria-label*="Afficher"]', | |
| '[aria-label*="Partager"]', | |
| '[aria-label*="Nouveau"]', | |
| '[aria-label*="Options"]', | |
| '[aria-label*="Compte"]', | |
| '[aria-label*="Notifications"]' , | |
| '[aria-label*="Titre du document"]' , | |
| 'a[href="/#backlinks"]', | |
| ]; | |
| elementsToHide.forEach(selector => { | |
| try { | |
| document.querySelectorAll(selector).forEach(el => { | |
| if (!originalStyles.has(el)) { | |
| originalStyles.set(el, { | |
| display: el.style.display, | |
| visibility: el.style.visibility, | |
| opacity: el.style.opacity | |
| }); | |
| } | |
| el.style.display = 'none'; | |
| el.style.visibility = 'hidden'; | |
| el.style.opacity = '0'; | |
| }); | |
| } catch (e) { | |
| // Skip invalid selectors | |
| } | |
| }); | |
| // Apply full-screen styles | |
| const root = document.getElementById('root'); | |
| if (root) { | |
| if (!originalStyles.has(root)) { | |
| originalStyles.set(root, { | |
| maxWidth: root.style.maxWidth, | |
| margin: root.style.margin, | |
| padding: root.style.padding, | |
| marginLeft: root.style.marginLeft, | |
| background: root.style.background | |
| }); | |
| } | |
| root.style.maxWidth = 'none'; | |
| root.style.margin = '0'; | |
| root.style.padding = '20px'; | |
| root.style.marginLeft = '0'; | |
| root.style.background = 'transparent'; | |
| } | |
| // Margin left | |
| // Select all elements on the page (or a specific set of elements) | |
| var elements = document.querySelectorAll('*'); // Or use a specific selector, like '.my-class' | |
| elements.forEach(function(element) { | |
| // Get the current margin-left value | |
| var marginLeft = window.getComputedStyle(element).marginLeft; | |
| // Convert the margin-left value from string (e.g., "60px") to a number (e.g., 60) | |
| var marginLeftValue = parseInt(marginLeft, 10); | |
| // If the margin-left is greater than 50px, force it to 50px | |
| if (marginLeftValue > 50) { | |
| element.style.marginLeft = '50px'; | |
| } | |
| }); | |
| //History | |
| toRemove(document.querySelectorAll('a[href^="/doc"][href$="/history"]',2)); | |
| toRemove(document.querySelectorAll('a[href^="/collection"]',2)); | |
| toRemove(document.querySelectorAll('a[href^="/doc"]',2)); | |
| // Style title and content | |
| const title = document.querySelector('[contenteditable]'); | |
| if (title) { | |
| if (!originalStyles.has(title)) { | |
| originalStyles.set(title, { | |
| fontSize: title.style.fontSize, | |
| fontWeight: title.style.fontWeight, | |
| marginTop: title.style.marginTop | |
| }); | |
| } | |
| title.style.fontSize = '2.5em'; | |
| title.style.fontWeight = '600'; | |
| title.style.marginTop = '40px'; | |
| } | |
| const content = document.querySelector('.ProseMirror'); | |
| if (content) { | |
| if (!originalStyles.has(content)) { | |
| originalStyles.set(content, { | |
| fontSize: content.style.fontSize, | |
| lineHeight: content.style.lineHeight, | |
| padding: content.style.padding | |
| }); | |
| } | |
| content.style.fontSize = '1.1em'; | |
| content.style.lineHeight = '1.6'; | |
| content.style.padding = '0'; | |
| } | |
| // Reset body | |
| document.body.style.margin = '0'; | |
| document.body.style.padding = '0'; | |
| document.body.style.background = 'transparent'; | |
| } | |
| function disableMinimalMode() { | |
| if (!isMinimalMode) return; | |
| isMinimalMode = false; | |
| // Restore original styles | |
| originalStyles.forEach((styles, element) => { | |
| Object.assign(element.style, styles); | |
| }); | |
| originalStyles.clear(); | |
| } | |
| // Wait for page to be ready | |
| function waitForReady() { | |
| const root = document.getElementById('root'); | |
| const content = document.querySelector('.ProseMirror'); | |
| if (root && content && root.children.length > 0) { | |
| setTimeout(enableMinimalMode, 500); | |
| } else { | |
| setTimeout(waitForReady, 100); | |
| } | |
| } | |
| // Persistent observer to maintain minimal mode | |
| const observer = new MutationObserver(() => { | |
| if (isMinimalMode) { | |
| setTimeout(enableMinimalMode, 50); | |
| } | |
| }); | |
| // Start after page loads | |
| if (document.readyState === 'loading') { | |
| document.addEventListener('DOMContentLoaded', waitForReady); | |
| } else { | |
| waitForReady(); | |
| } | |
| // Observer to catch React re-renders | |
| observer.observe(document.body, { | |
| childList: true, | |
| subtree: true, | |
| attributes: true, | |
| attributeFilter: ['style', 'class'] | |
| }); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment