下载 VS Code 扩展插件 VSIX 包

在 VS Code 官方市场上下载任何扩展插件的当前版本和旧版本的 .vsix 包文件

// ==UserScript==
// @name         Download VS Code Extension VSIX Packages
// @name:zh-CN   下载 VS Code 扩展插件 VSIX 包
// @name:zh-TW   下載 VS Code 擴充插件 VSIX 包
// @name:fr      Télécharger packages VSIX d'extension VS Code
// @name:fr-CA   Télécharger packages VSIX d'extension VS Code
// @namespace    https://tomchen.org/
// @version      1.0.0
// @description  Download .vsix packages of current and old versions of any extension on VS Code Marketplace
// @description:zh-CN 在 VS Code 官方市场上下载任何扩展插件的当前版本和旧版本的 .vsix 包文件
// @description:zh-TW 在 VS Code 官方市場上下載任何擴充插件外掛程式的當前版本和舊版本的 .vsix 包檔案
// @description:fr Télécharger les packages .vsix des versions actuelles et anciennes d'une extension sur la Marketplace VS Code
// @description:fr-CA Télécharger les packages .vsix des versions actuelles et anciennes d'une extension sur la Marketplace VS Code
// @author       Tom Chen (tomchen.org)
// @license      MIT
// @compatible   chrome
// @compatible   firefox
// @compatible   edge
// @compatible   opera
// @compatible   brave
// @icon         https://www.google.com/s2/favicons?sz=64&domain=code.visualstudio.com
// @match        https://marketplace.visualstudio.com/items*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {

    function getPublisherAndExtensionName(url) {
        const params = new URL(url).searchParams
        const itemName = params.get("itemName")
        if (!itemName) {
            return null
        }
        const obj = itemName.split(".")
        return {
            publisher: obj[0],
            extensionName: obj[1]
        }
    }

    const obj = getPublisherAndExtensionName(window.location.href)
    if (!obj) {
        return
    }
    const { publisher, extensionName } = obj

    function getUrl(publisher, extensionName, version) {
        return `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${extensionName}/${version}/vspackage/`
    }

    const currentVersionLinkclassName = "version-current-vspackage-link"
    let isCurrentVersionLinkAdded = false
    function findCurrentVersionAndAddLink() {
        const versionTd = document.querySelector("table.ux-table-metadata td[aria-labelledby='Version'], table.ux-table-metadata td[aria-labelledby='version']")
        if (versionTd && !versionTd.querySelector(`.${currentVersionLinkclassName}`)) {
            const currentVersion = versionTd.textContent.trim()
            const a = document.createElement("a")
            a.href = getUrl(publisher, extensionName, currentVersion)
            a.textContent = currentVersion
            a.className = currentVersionLinkclassName
            a.title= "Download .vsix package"
            versionTd.removeChild(versionTd.firstChild)
            versionTd.appendChild(a)
        }
    }

    const historyVersionLinkclassName = "version-history-vspackage-link"
    let isHistoryLinksAdded = false
    function findTableAndAddLinks() {
        const table = document.querySelector(".version-history-table")
        if (table && !table.querySelector(`.${historyVersionLinkclassName}`)) {
            const trs = table.querySelectorAll("tbody tr.version-history-container-row")
            trs.forEach(tr => {
                const td = tr.querySelector("td.version-history-container-column")
                const version = td.textContent.trim()
                const a = document.createElement("a")
                a.href = getUrl(publisher, extensionName, version)
                a.textContent = "download"
                a.className = historyVersionLinkclassName
                a.title= "Download .vsix package"
                const text1 = document.createTextNode(' (')
                const text2 = document.createTextNode(')')
                td.appendChild(text1)
                td.appendChild(a)
                td.appendChild(text2)
            })
        }
    }

    const observer = new MutationObserver((mutationsList) => {
        for (const mutation of mutationsList) {
            if (mutation.type === "childList") {
                findTableAndAddLinks()
                findCurrentVersionAndAddLink()
                // can't disconnect observer because switching tab will erase added links
            }
        }
    });

    observer.observe(document, { childList: true, subtree: true })

})()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址