您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a "Download VSIX" button next to Install, copying its style exactly.
// ==UserScript== // @name VS Marketplace: Download VSIX // @namespace https://brandonhenness.dev/tm/vsix-download // @version 1.8.1 // @description Adds a "Download VSIX" button next to Install, copying its style exactly. // @match https://marketplace.visualstudio.com/items* // @run-at document-idle // @grant none // @license GPL-3.0-only; https://www.gnu.org/licenses/gpl-3.0.txt // @author Brandon Henness // ==/UserScript== (function () { "use strict"; const BTN_ID = "bh-vsix-dl"; const getItem = () => { try { const u = new URL(location.href); const q = u.searchParams.get("itemName"); if (q && q.includes(".")) return q; const m = u.pathname.match(/items\/([^/?#]+)/i); if (m && m[1] && m[1].includes(".")) return m[1]; } catch {} return null; }; function findInstallButton() { return document.querySelector(".ux-oneclick-install-button-container .install"); } function createDownloadButton() { const installBtn = findInstallButton(); if (!installBtn) return null; // Clone Install button for identical style const clone = installBtn.cloneNode(true); clone.id = BTN_ID; // Add spacing so the buttons are not touching clone.style.marginLeft = "8px"; // Change label const labelDiv = clone.querySelector(".ms-Button-label"); if (labelDiv) labelDiv.textContent = "Download VSIX"; // Wire up latest VSIX URL const key = getItem(); if (key) { const [publisher, extension] = key.split("."); clone.href = `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${extension}/latest/vspackage`; clone.setAttribute("download", `${publisher}.${extension}_latest.vsix`); clone.removeAttribute("aria-disabled"); } return clone; } function ensureButton() { if (document.getElementById(BTN_ID)) return; const installBtn = findInstallButton(); if (installBtn && installBtn.parentElement) { const dlBtn = createDownloadButton(); if (dlBtn) installBtn.parentElement.appendChild(dlBtn); } } // Keep the button present across SPA re-renders const observer = new MutationObserver(() => ensureButton()); observer.observe(document.documentElement, { childList: true, subtree: true }); if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", ensureButton); } else { ensureButton(); } })();