### Install Multi with Homebrew Source: https://github.com/kofigumbs/multi/blob/main/README.md Use this command to install the Multi application via Homebrew Cask. ```bash brew install --cask multi ``` -------------------------------- ### Advanced Multi App JSON Configuration Source: https://github.com/kofigumbs/multi/blob/main/README.md An example of a comprehensive JSON configuration for a Multi app, demonstrating various optional fields for tabs and window settings. This includes authentication, custom user agents, JavaScript, CSS, cookies, and window behavior. ```json { "tabs": [ { "title": "Dancing", "url": "https://rc.kofi.sexy/bathroom-floss", "basicAuthUser": "user", "basicAuthPassword": "password", "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15" }, { "title": "Walking", "url": "https://kofi.sexy/cel-shading", "customJs": [ "file:///Users/kofi/Documents/dotfiles/main/example.js" ], "customCss": [ "https://example.com/custom.css" ], "customCookies": [ { "name": "login_token_tab", "value": "eyJoZWxsbyI6ICJ3b3JsZCJ9", "domain": ".example.com", "path": "/" } ] } ], "windowed": true, "alwaysNotify": true, "alwaysOnTop": true, "terminateWithLastWindow": true, "openNewWindowsInBackground": true, "openNewWindowsWith": "com.apple.Safari" } ``` -------------------------------- ### Create and Open Multi App Source: https://github.com/kofigumbs/multi/blob/main/Docs/TESTING.md Use this command to create a new macOS application bundle with a JSON configuration and then open the created application. ```bash MULTI_APP_NAME='Test' MULTI_JSON_CONFIG='{ "windowed": true, "openNewWindowsWith": "com.mozilla.firefox", "openNewWindowsInBackground": true, "tabs": [ { "title": "Alert", "url": "https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_alert" }, { "title": "Confirm", "url": "https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_confirm" }, { "title": "Prompt", "url": "https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_prompt" }, { "title": "File", "url": "https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_type_file" }, { "title": "External Links", "url": "https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_a_target" }, { "title": "Notifications", "url": "https://www.bennish.net/web-notifications.html" }, { "title": "Popup", "url": "https://javascript.info/popup-windows#example-a-minimalistic-window" }, { "title": "Basic Auth", "basicAuthUser": "guest", "basicAuthPassword": "guest", "url": "https://jigsaw.w3.org/HTTP/Basic/" } ] }' ./Multi.app/Contents/Resources/create-mac-app open ./Multi/Test.app ``` -------------------------------- ### Create a Bare-Minimum Multi App with CLI Source: https://github.com/kofigumbs/multi/blob/main/README.md Use the `create-mac-app` script with the `MULTI_APP_NAME` environment variable to quickly generate a new Multi application. The app will open with its preferences window for further configuration. ```bash MULTI_APP_NAME='Test' /Applications/Multi.app/Contents/Resources/create-mac-app ``` -------------------------------- ### JavaScript for Multi App Configuration Source: https://github.com/kofigumbs/multi/blob/main/Multi.app/Contents/Resources/settings.html Handles user input for app name, icon selection, and JSON configuration. Updates the UI based on input and validation. ```javascript let iconPath = "" let jsonError = "" const name = document.getElementById("name") const icon = document.getElementById("icon") const path = document.getElementById("path") const json = document.getElementById("json") const save = document.getElementById("save") const error = document.getElementById("error") name.addEventListener("input", () => { update() }) icon.addEventListener("click", () => { webkit.messageHandlers.icon.postMessage({}) .then((x) => iconPath = x, (e) => console.error(e)) .then(update) }) json.addEventListener("input", () => { webkit.messageHandlers.json.postMessage(json.value) .then(() => jsonError = "", (e) => jsonError = e.toString()) .then(update) }) save.addEventListener("click", () => { webkit.messageHandlers.save.postMessage({ name: name.value, icon: iconPath, json: json.value }) .catch((e) => error.innerText = e.toString()) }) function update() { path.innerText = iconPath error.innerText = jsonError save.disabled = !name.value || !!jsonError } ``` -------------------------------- ### Basic Multi App JSON Configuration Source: https://github.com/kofigumbs/multi/blob/main/README.md A minimal JSON configuration to set up a single tab for a Multi app. This is the simplest valid configuration. ```json { "tabs": [{ "url": "https://app.slack.com/client" }] } ``` -------------------------------- ### Implement Find in Page with Custom JS Source: https://github.com/kofigumbs/multi/blob/main/README.md This script adds a command-palette-like search functionality (Cmd-F) to your Multi app. It highlights search results and allows closing the search bar. The `document.designMode` trick is used for highlighting. ```javascript window.addEventListener("DOMContentLoaded", () => { const highlightResults = (text, color) => { document.designMode = "on"; // https://stackoverflow.com/a/5887719 var selection = window.getSelection(); selection.collapse(document.body, 0); while (window.find(text)) { document.execCommand("HiliteColor", false, color); selection.collapseToEnd(); } document.designMode = "off"; }; let mostRecentSearchText = ""; const search = text => { highlightResults(mostRecentSearchText, "transparent"); highlightResults(text, "rgb(255 255 1 / 50%)"); mostRecentSearchText = text; }; const input = document.createElement("input"); input.placeholder = "Search..."; input.style.padding = "10px 15px"; input.style.fontSize = "15px"; input.style.borderRadius = "3px"; input.style.border = "solid 1px lightgray"; const form = document.createElement("form"); form.style.display = "none"; form.style.position = "fixed"; form.style.top = "15px"; form.style.right = "15px"; form.style.zIndex = "2147483647"; // https://stackoverflow.com/a/856569 form.addEventListener("submit", e => { e.preventDefault(); search(input.value); }); const close = document.createElement("a"); close.innerText = "тип"; close.href = "javascript:void(0)"; close.style.fontSize = "30px"; close.style.padding = "15px"; close.style.textDecoration = "none"; close.addEventListener("click", e => { e.preventDefault(); search(""); form.style.display = "none"; }); form.appendChild(input); form.appendChild(close); document.body.appendChild(form); document.addEventListener("keydown", event => { if (event.metaKey && event.key === "f") { event.preventDefault(); form.style.display = "block"; input.focus(); } }); }); ``` -------------------------------- ### Preview Link Targets with CSS in Multi Source: https://github.com/kofigumbs/multi/blob/main/README.md This CSS solution adds a hover effect to display the URL of a link. It requires no JavaScript and is purely for visual feedback. ```css a:hover::after { content: attr(href); position: fixed; left: 4px; bottom: 4px; padding: 4px; font-size: 12px; font-family: -apple-system, BlinkMacSystemFont; font-weight: normal; color: black; background: ghostwhite; border: solid 1px black; border-radius: 1px; } ``` -------------------------------- ### Enable Drag and Drop for URLs in Multi Source: https://github.com/kofigumbs/multi/blob/main/README.md Add this JavaScript event listener to allow dragging URLs into the Multi application. It prevents the default browser behavior for dragover events. ```javascript document.addEventListener("dragover", e => e.preventDefault()); ``` -------------------------------- ### Fix Links in Gmail/Google Calendar with Custom JS Source: https://github.com/kofigumbs/multi/blob/main/README.md Inject this JavaScript to prevent Google's URL tracking by stopping event propagation on links with `target=_blank`. It uses `setInterval` to continuously monitor and attach the listener to new links. ```javascript window.addEventListener("DOMContentLoaded", () => { const listener = e => e.stopPropagation(); const query = () => document.querySelectorAll("a[target=_blank]").forEach(a => { a.removeEventListener("click", listener); a.addEventListener("click", listener, true); }); setInterval(query, 400); // wait time between DOM queries, in milliseconds }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.