下載 VS Code 擴充插件 VSIX 包

在 VS Code 官方市場上下載任何擴充插件外掛程式的當前版本和舊版本的 .vsix 包檔案

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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 })

})()