最新版本又取消了第三方插件图标,我弄回来了

image

首先如果你不需要图标 无视
因为我英语不好,所以我很需要图标

自己添加图标的方法
找到每一个插件的main.js
进去找到 PluginSettingTab

var GeneralSettingsTab = class extends import_obsidian9.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin); 在这个与plugin之间
this.icon = “chart-line”; 添加这一段 图标名称就是图标的外观
this.plugin = plugin;
}

Icons – Lucide 这是图标网站

在这个基础上 按照下面插件

main.js

const { Plugin, setIcon, notice } = require('obsidian');

module.exports = class IconRestorerPlugin extends Plugin {
    async onload() {
        this.iconMap = new Map();
        
        // 1. 预执行扫描
        await this.refreshIconMap();

        // 2. 注册命令以便手动刷新
        this.addCommand({
            id: 'refresh-plugin-icons',
            name: '手动刷新插件图标库',
            callback: async () => {
                await this.refreshIconMap();
                new Notice('插件图标库已更新');
            }
        });

        // 3. 核心:监控 DOM 注入图标
        this.registerEvent(
            this.app.workspace.on('layout-change', () => this.injectIcons())
        );

        // 监听全局点击(因为设置面板打开不触发 layout-change)
        this.registerDomEvent(document, 'click', (evt) => {
            if (evt.target.closest('.titlebar-button.mod-settings') || evt.target.closest('.clickable-icon')) {
                setTimeout(() => this.injectIcons(), 50);
            }
        });

        // 定时轮询(备用方案,防止某些情况漏掉)
        this.registerInterval(window.setInterval(() => this.injectIcons(), 1000));
    }

    async refreshIconMap() {
        const adapter = this.app.vault.adapter;
        const pluginsPath = `${this.app.vault.configDir}/plugins`;
        
        // 获取所有已安装插件的 ID
        const manifests = this.app.plugins.manifests;
        
        for (const id in manifests) {
            let foundIcon = null;

            // 尝试方式 A: 从内存中的插件实例获取 (如果插件已经运行)
            const activePlugin = this.app.plugins.plugins[id];
            if (activePlugin && activePlugin.icon) {
                foundIcon = activePlugin.icon;
            }

            // 尝试方式 B: 扫描文件 (针对没运行或实例没暴露 icon 的)
            if (!foundIcon) {
                const mainJsPath = `${pluginsPath}/${id}/main.js`;
                if (await adapter.exists(mainJsPath)) {
                    const content = await adapter.read(mainJsPath);
                    const match = content.match(/this\.icon\s*=\s*["']([^"']+)["']/);
                    if (match) foundIcon = match[1];
                }
            }

            if (foundIcon) {
                this.iconMap.set(manifests[id].name, foundIcon);
            }
        }
    }

    injectIcons() {
        const settingsModal = document.querySelector('.modal.mod-settings');
        if (!settingsModal) return;

        // 找到所有的侧边栏项目
        const navItems = settingsModal.querySelectorAll('.vertical-tab-nav-item');
        
        navItems.forEach(item => {
            // 如果已经注入过了,跳过
            if (item.querySelector('.restored-icon')) return;

            const pluginName = item.innerText.trim();
            const iconName = this.iconMap.get(pluginName);

            // 如果匹配到图标,或者它是第三方插件(在"Community Plugins"分组下的)
            // 我们为它们注入图标
            if (iconName) {
                this.createIconEl(item, iconName);
            } else {
                // 可选:为没有定义图标的插件设置一个默认占位图标,保持对齐
                // 如果你不需要占位图标,注释掉下面这行
                // this.createIconEl(item, 'toy-brick'); 
            }
        });
    }

    createIconEl(parentEl, iconName) {
        const iconSpan = document.createElement('span');
        iconSpan.classList.add('restored-icon');
        
        // CSS 样式确保图标小巧且对齐
        iconSpan.style.display = 'inline-flex';
        iconSpan.style.alignItems = 'center';
        iconSpan.style.justifyContent = 'center';
        iconSpan.style.marginRight = '10px';
        iconSpan.style.height = '16px';
        iconSpan.style.width = '16px';
        iconSpan.style.verticalAlign = 'middle';
        iconSpan.style.opacity = '0.8';

        setIcon(iconSpan, iconName);
        parentEl.prepend(iconSpan);
        
        // 修正父元素的布局为 flex
        parentEl.style.display = 'flex';
        parentEl.style.alignItems = 'center';
    }

    onunload() {
        document.querySelectorAll('.restored-icon').forEach(el => el.remove());
    }
};

manifest.json

{
  "id": "auto-restore-icons",
  "name": "Auto Restore Plugin Icons",
  "version": "1.0.0",
  "minAppVersion": "1.11.0",
  "description": "Automatically restores community plugin icons in settings sidebar.",
  "author": "User",
  "isDesktopOnly": true
}

更健壮的版本

这次不需要修改其他文件的main了
只需要在这个main里面 添加对应关系就行了
“Better Word Count”: “binary”,
这个就是对应关系
如果不懂发给ai ai帮你改了

const { Plugin, setIcon, Notice } = require('obsidian');

module.exports = class IconRestorerPlugin extends Plugin {
    async onload() {
        // --- 修正表:在这里添加你想修复的所有插件 ---
        this.manualMap = {
            "Canvasgrid Transit": "scan",
            "Advanced Canvas": "pencil-ruler",
            "Better Word Count": "binary",
            "Commander": "align-horizontal-justify-center",
            "Custom Font Loader": "type",        // 修复:图中这个没出来,换成 type 试试
            "Datacore": "database",
            "Enhancing Export": "book",
            "File Color": "palette",
            "GitHub Sync": "github",
            "Homepage": "home",
            "Iconize": "shapes",
            "Image Toolkit": "image",
            "Kanban": "square-kanban",               // 修复:图中这个没出来,换成 columns-3
            "MySnippets": "code-2",
            "ProZen": "eye-off",
            "QuickAdd": "zap",
            "Quiet Outline": "list-tree",
            "Short links": "link",
            "Sticky Headings": "heading-1",
            "Style Settings": "paint-bucket",
            "Various Complements": "list-plus",
            // 你以后安装了新插件发现没图标,直接在下面按格式加一行即可
            // "新插件的名字": "图标名字",
        };
        // ------------------------------------------

        this.iconMap = new Map();
        await this.refreshIconMap();

        this.addCommand({
            id: 'refresh-plugin-icons-final',
            name: '手动强制刷新所有图标',
            callback: async () => {
                await this.refreshIconMap();
                this.injectIcons();
                new Notice('图标映射已刷新');
            }
        });

        this.registerEvent(this.app.workspace.on('layout-change', () => this.injectIcons()));
        
        this.registerDomEvent(document, 'click', (evt) => {
            if (evt.target.closest('.titlebar-button.mod-settings') || evt.target.closest('.clickable-icon')) {
                setTimeout(() => this.injectIcons(), 150);
            }
        });

        this.registerInterval(window.setInterval(() => this.injectIcons(), 2000));
    }

    async refreshIconMap() {
        const manifests = this.app.plugins.manifests;
        for (const id in manifests) {
            const pluginName = manifests[id].name;
            let foundIcon = this.manualMap[pluginName] || null;

            if (!foundIcon) {
                const instance = this.app.plugins.plugins[id];
                if (instance) {
                    if (instance.icon && typeof instance.icon === 'string') foundIcon = instance.icon;
                    else {
                        for (const key in instance) {
                            if (instance[key] && instance[key].icon && typeof instance[key].icon === 'string') {
                                foundIcon = instance[key].icon;
                                break;
                            }
                        }
                    }
                }
            }
            if (foundIcon) this.iconMap.set(pluginName, foundIcon);
        }
    }

    injectIcons() {
        const settingsModal = document.querySelector('.modal.mod-settings');
        if (!settingsModal) return;

        const navItems = settingsModal.querySelectorAll('.vertical-tab-nav-item');
        navItems.forEach(item => {
            if (item.querySelector('.restored-icon')) return;

            // 关键:这里会同时匹配名字前后的空格
            const pluginName = item.innerText.trim();
            const iconName = this.iconMap.get(pluginName);

            if (iconName) {
                this.createIconEl(item, iconName);
            }
        });
    }

    createIconEl(parentEl, iconName) {
        const iconSpan = document.createElement('span');
        iconSpan.classList.add('restored-icon');
        
        iconSpan.style.display = 'inline-flex';
        iconSpan.style.alignItems = 'center';
        iconSpan.style.justifyContent = 'center';
        iconSpan.style.marginRight = '10px';
        iconSpan.style.minWidth = '16px';
        iconSpan.style.height = '16px';
        iconSpan.style.flexShrink = '0';
        iconSpan.style.opacity = '0.85';

        try {
            setIcon(iconSpan, iconName);
            parentEl.prepend(iconSpan);
            parentEl.style.display = 'flex';
            parentEl.style.alignItems = 'center';
        } catch (e) {}
    }

    onunload() {
        document.querySelectorAll('.restored-icon').forEach(el => el.remove());
    }
};