[js][css] 仿 Obsidian Callout 样式

一、效果

(1)风格 1

PixPin20250621224349.png

(2)风格 2

PixPin20250621224417.png

二、操作

PixPin20250622101725.gif

三、代码

(1)JavaScript

(function() {
    'use strict';

    console.log('=== Optimized SiYuan BlockQuote Enhanced Script ===');

    // ==================== 自定义样式检测 ====================
  
    // 检查是否为自定义样式的 BlockQuote
    function hasCustomStyle(blockQuote) {
        if (!blockQuote) return false;
      
        // 检查 custom-b 属性
        const customB = blockQuote.getAttribute('custom-b');
        if (customB) {
            const customBTypes = ['info', 'light', 'bell', 'check', 'question', 'warn', 'wrong', 'bug', 'note', 'pen'];
            if (customBTypes.includes(customB)) {
                return true;
            }
        }
      
        // 检查 custom-callout 属性
        const customCallout = blockQuote.getAttribute('custom-callout');
        if (customCallout === '书签') {
            return true;
        }
      
        return false;
    }

    // ==================== 命令菜单部分 ====================
  
    // 命令定义(菜单用)
    const menuCommands = [
        {
            command: '@info',
            displayName: '信息补充',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" overflow="visible"><circle cx="12" cy="12" r="10" stroke="#4493f8" stroke-width="1.7" fill="white"/><rect x="11" y="7" width="2" height="7" rx="1" fill="#4493f8"/><circle cx="12" cy="17" r="1.2" fill="#4493f8"/></svg>`,
            color: '#4493f8'
        },
        {
            command: '@note',
            displayName: '笔记',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" overflow="visible"><path d="M21.17 6.81a1 1 0 0 0-3.99-3.99L3.84 16.17a2 2 0 0 0-.5.83l-1.32 4.35a.5.5 0 0 0 .62.62l4.35-1.32a2 2 0 0 0 .83-.5z" stroke="#4493f8" stroke-width="2" fill="white"/><path d="m15 5 4 4" stroke="#4493f8" stroke-width="2"/></svg>`,
            color: '#4493f8'
        },
        {
            command: '@comment',
            displayName: '批注',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" overflow="visible"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" stroke="#4493f8" stroke-width="2" fill="white"/><path d="M8 10h.01M12 10h.01M16 10h.01" stroke="#4493f8" stroke-width="2"/></svg>`,
            color: '#4493f8'
        },
        {
            command: '@tip',
            displayName: '提示',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" overflow="visible"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5" stroke="#238636" stroke-width="1.7" fill="none"/><path d="M9 18h6M10 22h4" stroke="#238636" stroke-width="1.7"/></svg>`,
            color: '#238636'
        },
        {
            command: '@warning',
            displayName: '警告',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" overflow="visible"><path d="M12 4L21 20H3L12 4Z" stroke="#e3b341" stroke-width="1.7" fill="white"/><rect x="11" y="9" width="2" height="6" rx="1" fill="#e3b341"/><circle cx="12" cy="18" r="1.2" fill="#e3b341"/></svg>`,
            color: '#e3b341'
        },
        {
            command: '@important',
            displayName: '重要',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" overflow="visible"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" stroke="#e3b341" stroke-width="1.7" fill="white"/><rect x="11" y="9" width="2" height="6" rx="1" fill="#e3b341"/><path d="M12 7v2M12 13h.01" stroke="#e3b341" stroke-width="1.7"/></svg>`,
            color: '#e3b341'
        },
        {
            command: '@caution',
            displayName: '小心',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" overflow="visible"><path d="M12 8v4" stroke="#e3b341" stroke-width="2" stroke-linecap="round"/><path d="M12 16h.01" stroke="#e3b341" stroke-width="2" stroke-linecap="round"/><path d="M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688A2 2 0 0 1 15.312 22H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z" stroke="#e3b341" stroke-width="1.7" fill="none"/></svg>`,
            color: '#e3b341'
        },
        {
            command: '@question',
            displayName: '问题',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" overflow="visible"><circle cx="12" cy="12" r="10" stroke="#d1242f" stroke-width="2" fill="none"/><path d="M12 8a2 2 0 0 1 2 2c0 1.5-2 2-2 4" stroke="#d1242f" stroke-width="2" stroke-linecap="round" fill="none"/><circle cx="12" cy="17" r="1" fill="#d1242f"/></svg>`,
            color: '#d1242f'
        },
        {
            command: '@error',
            displayName: '错误',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" overflow="visible"><circle cx="12" cy="12" r="10" stroke="#d1242f" stroke-width="2" fill="white"/><path d="M14.5 9.5l-5 5M9.5 9.5l5 5" stroke="#d1242f" stroke-width="2"/></svg>`,
            color: '#d1242f'
        },
        {
            command: '@example',
            displayName: '示例',
            icon: `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" overflow="visible"><path d="M3 12h.01M3 18h.01M3 6h.01M8 12h13M8 18h13M8 6h13" stroke="#8957e5" stroke-width="2" fill="none"/></svg>`,
            color: '#8957e5'
        }
    ];

    // 菜单状态管理
    let commandMenu = null;
    let isMenuVisible = false;
    let isProcessingEvent = false;
    let trackedBlockQuotes = new Set();
    let recentlyCreatedBlockQuotes = new Set();
    let currentTargetBlockQuote = null;

    // ==================== Callout 处理部分 ====================
  
    // Callout 类型定义(处理器用)
    const calloutTypes = {
        '@info': { type: 'info', displayName: '信息补充' },
        '@信息': { type: 'info', displayName: '信息补充' },
        '@note': { type: 'note', displayName: '笔记' },
        '@笔记': { type: 'note', displayName: '笔记' },
        '@comment': { type: 'comment', displayName: '批注' },
        '@批注': { type: 'comment', displayName: '批注' },
        '@tip': { type: 'tip', displayName: '提示' },
        '@提示': { type: 'tip', displayName: '提示' },
        '@warning': { type: 'warning', displayName: '警告' },
        '@警告': { type: 'warning', displayName: '警告' },
        '@important': { type: 'important', displayName: '重要' },
        '@重要': { type: 'important', displayName: '重要' },
        '@caution': { type: 'caution', displayName: '小心' },
        '@小心': { type: 'caution', displayName: '小心' },
        '@error': { type: 'error', displayName: '错误' },
        '@错误': { type: 'error', displayName: '错误' },
        '@question': { type: 'question', displayName: '问题' },
        '@问题': { type: 'question', displayName: '问题' },
        '@example': { type: 'example', displayName: '示例' },
        '@示例': { type: 'example', displayName: '示例' },
        '@default': { type: 'default', displayName: '默认' },
        '@默认': { type: 'default', displayName: '默认' }
    };

    // ==================== 命令菜单功能 ====================

    // 创建命令菜单
    function createCommandMenu(targetBlockQuote) {
        if (commandMenu) return commandMenu;

        currentTargetBlockQuote = targetBlockQuote;
        commandMenu = document.createElement('div');
        commandMenu.style.cssText = `
            position: fixed;
            background: white;
            border: 1px solid #d1d5db;
            border-radius: 8px;
            box-shadow: 0 10px 25px rgba(0,0,0,0.15);
            max-height: 400px;
            overflow-y: auto;
            z-index: 10000;
            font-size: 14px;
            min-width: 250px;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            opacity: 0;
            transform: translateY(-10px);
            transition: opacity 0.2s ease, transform 0.2s ease;
            pointer-events: none;
        `;

        // 关闭按钮
        const closeButton = document.createElement('div');
        closeButton.style.cssText = `
            position: absolute;
            top: 8px;
            right: 8px;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            background: #f3f4f6;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            font-size: 14px;
            color: #6b7280;
            transition: all 0.15s ease;
            z-index: 1;
        `;
        closeButton.innerHTML = '×';
        closeButton.addEventListener('mouseenter', () => {
            closeButton.style.background = '#ef4444';
            closeButton.style.color = 'white';
        });
        closeButton.addEventListener('mouseleave', () => {
            closeButton.style.background = '#f3f4f6';
            closeButton.style.color = '#6b7280';
        });
        closeButton.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            hideCommandMenu(true);
        });
        commandMenu.appendChild(closeButton);

        // 标题
        const header = document.createElement('div');
        header.style.cssText = `
            padding: 12px 40px 12px 16px;
            background: #f9fafb;
            border-bottom: 1px solid #e5e7eb;
            font-size: 13px;
            color: #6b7280;
            font-weight: 600;
        `;
        header.innerHTML = '<div>Callout 命令菜单</div>';
        commandMenu.appendChild(header);

        // 命令选项
        menuCommands.forEach((cmd, index) => {
            const item = document.createElement('div');
            item.style.cssText = `
                padding: 12px 16px;
                cursor: pointer;
                border-bottom: 1px solid #f3f4f6;
                display: flex;
                align-items: center;
                gap: 12px;
                transition: all 0.15s ease;
            `;
          
            if (index === menuCommands.length - 1) {
                item.style.borderBottom = 'none';
            }
          
            item.innerHTML = `
                <span style="width:24px;height:24px;display:flex;align-items:center;justify-content:center;flex-shrink:0;">${cmd.icon}</span>
                <div style="flex: 1;">
                    <div style="font-weight: 500; color: #374151; margin-bottom: 2px;">${cmd.command}</div>
                    <div style="color: #6b7280; font-size: 12px;">${cmd.displayName}</div>
                </div>
            `;
          
            item.addEventListener('mouseenter', () => {
                item.style.backgroundColor = '#f3f4f6';
                item.style.transform = 'translateX(2px)';
            });
          
            item.addEventListener('mouseleave', () => {
                item.style.backgroundColor = '';
                item.style.transform = 'translateX(0)';
            });
          
            item.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                item.style.backgroundColor = '#dbeafe';
                item.style.color = '#1e40af';
                insertCommandToBlockQuote(cmd.command, currentTargetBlockQuote);
                setTimeout(() => hideCommandMenu(true), 300);
            });
          
            commandMenu.appendChild(item);
        });

        // 底部提示
        const footer = document.createElement('div');
        footer.style.cssText = `
            padding: 8px 16px;
            background: #f9fafb;
            border-top: 1px solid #e5e7eb;
            font-size: 11px;
            color: #9ca3af;
            text-align: center;
        `;
        footer.innerHTML = '点击选择 Callout 类型 • ESC 关闭';
        commandMenu.appendChild(footer);

        document.body.appendChild(commandMenu);
        return commandMenu;
    }

    // 插入命令并自动换行
    function insertCommandToBlockQuote(command, blockQuoteElement) {
        if (!blockQuoteElement) return false;

        const editableDiv = blockQuoteElement.querySelector('[contenteditable="true"]');
        if (!editableDiv) return false;

        try {
            editableDiv.textContent = command;
          
            // 触发事件,让 Callout 处理器知道内容已更改
            editableDiv.dispatchEvent(new Event('input', { bubbles: true }));
            editableDiv.dispatchEvent(new Event('change', { bubbles: true }));

            // 设置光标并自动换行
            setTimeout(() => {
                editableDiv.focus();
              
                const range = document.createRange();
                const selection = window.getSelection();
              
                if (editableDiv.childNodes.length > 0) {
                    const lastNode = editableDiv.childNodes[editableDiv.childNodes.length - 1];
                    if (lastNode.nodeType === Node.TEXT_NODE) {
                        range.setStart(lastNode, lastNode.textContent.length);
                        range.setEnd(lastNode, lastNode.textContent.length);
                    } else {
                        range.setStartAfter(lastNode);
                        range.setEndAfter(lastNode);
                    }
                } else {
                    range.selectNodeContents(editableDiv);
                    range.collapse(false);
                }
              
                selection.removeAllRanges();
                selection.addRange(range);
              
                // 自动换行
                setTimeout(() => {
                    editableDiv.dispatchEvent(new KeyboardEvent('keydown', {
                        key: 'Enter', code: 'Enter', keyCode: 13, bubbles: true
                    }));
                    editableDiv.dispatchEvent(new KeyboardEvent('keyup', {
                        key: 'Enter', code: 'Enter', keyCode: 13, bubbles: true
                    }));
                  
                    // 延迟处理 Callout,确保内容已更新
                    setTimeout(() => {
                        processBlockquote(blockQuoteElement);
                    }, 200);
                }, 100);
            }, 150);

            return true;
        } catch (error) {
            if (navigator.clipboard) {
                navigator.clipboard.writeText(command);
            }
            return false;
        }
    }

    // 显示菜单
    function showCommandMenu(x, y, blockQuoteElement) {
        if (isProcessingEvent || isMenuVisible) return;
      
        // 检查是否为自定义样式的 BlockQuote
        if (hasCustomStyle(blockQuoteElement)) {
            console.log('Skipping custom styled blockquote:', blockQuoteElement);
            return;
        }
      
        isProcessingEvent = true;
        const menu = createCommandMenu(blockQuoteElement);

        // 获取菜单尺寸
        menu.style.left = '0px';
        menu.style.top = '0px';
        menu.style.visibility = 'hidden';
        menu.style.opacity = '1';
        menu.style.pointerEvents = 'auto';

        requestAnimationFrame(() => {
            const menuRect = menu.getBoundingClientRect();
            const menuHeight = menuRect.height;
            const menuWidth = menuRect.width;
          
            let menuX = x;
            let menuY = y;
          
            if (blockQuoteElement) {
                const blockRect = blockQuoteElement.getBoundingClientRect();
                menuX = blockRect.left;
                menuY = blockRect.top - menuHeight - 10;
            }

            // 边界检查
            if (menuY < 10 && blockQuoteElement) {
                const blockRect = blockQuoteElement.getBoundingClientRect();
                menuY = blockRect.bottom + 10;
            }
            if (menuX + menuWidth > window.innerWidth) {
                menuX = window.innerWidth - menuWidth - 10;
            }
            if (menuY + menuHeight > window.innerHeight) {
                menuY = window.innerHeight - menuHeight - 10;
            }
            if (menuX < 10) menuX = 10;
            if (menuY < 10) menuY = 10;
          
            // 设置位置并显示
            menu.style.left = menuX + 'px';
            menu.style.top = menuY + 'px';
            menu.style.visibility = 'visible';
            menu.style.opacity = '0';
            menu.style.transform = 'translateY(-10px)';
          
            setTimeout(() => {
                menu.style.opacity = '1';
                menu.style.transform = 'translateY(0)';
            }, 10);
          
            isMenuVisible = true;
            isProcessingEvent = false;
          
            // 标记已显示
            if (blockQuoteElement) {
                const nodeId = blockQuoteElement.getAttribute('data-node-id');
                if (nodeId) {
                    recentlyCreatedBlockQuotes.add(nodeId);
                    setTimeout(() => recentlyCreatedBlockQuotes.delete(nodeId), 3000);
                }
            }
        });
    }

    // 隐藏菜单
    function hideCommandMenu(immediate = false) {
        if (!commandMenu || !isMenuVisible) return;
      
        currentTargetBlockQuote = null;
      
        if (immediate) {
            commandMenu.remove();
            commandMenu = null;
            isMenuVisible = false;
            return;
        }
      
        commandMenu.style.opacity = '0';
        commandMenu.style.transform = 'translateY(-10px)';
        commandMenu.style.pointerEvents = 'none';
      
        setTimeout(() => {
            if (commandMenu) {
                commandMenu.remove();
                commandMenu = null;
            }
            isMenuVisible = false;
        }, 200);
    }

    // ==================== Callout 处理功能 ====================

    // 处理单个引用块的函数
    function processBlockquote(blockquote) {
        console.log('Processing blockquote:', blockquote);
      
        // 跳过自定义样式的 BlockQuote
        if (hasCustomStyle(blockquote)) {
            console.log('Skipping custom styled blockquote for callout processing');
            return;
        }
      
        const firstParagraph = blockquote.querySelector('div[data-type="NodeParagraph"]:first-of-type');
        if (!firstParagraph) {
            console.log('No first paragraph found');
            return;
        }

        const titleDiv = firstParagraph.querySelector('div[contenteditable="true"]');
        if (!titleDiv) {
            console.log('No contenteditable div found');
            return;
        }

        const text = titleDiv.textContent.trim();
        console.log('Current text:', text);
      
        // 检查是否匹配任何 callout 类型
        for (const [trigger, config] of Object.entries(calloutTypes)) {
            if (text.startsWith(trigger)) {
                console.log(`Match found: ${trigger} -> ${config.type}`);
              
                // 设置 callout 类型
                blockquote.setAttribute('data-callout-type', config.type);
              
                // 标记标题并设置显示名称
                titleDiv.setAttribute('data-callout-title', 'true');
                titleDiv.setAttribute('data-callout-display-name', config.displayName);
              
                console.log('Callout attributes set');
                return;
            }
        }
      
        // 如果不匹配任何 callout 类型,清除相关属性
        if (blockquote.hasAttribute('data-callout-type')) {
            console.log('Clearing callout attributes');
            blockquote.removeAttribute('data-callout-type');
            titleDiv.removeAttribute('data-callout-title');
            titleDiv.removeAttribute('data-callout-display-name');
        }
    }

    // 处理所有引用块
    function processAllBlockquotes() {
        console.log('=== Processing all blockquotes ===');
        const blockquotes = document.querySelectorAll('.bq');
        console.log('Found blockquotes:', blockquotes.length);
      
        blockquotes.forEach((bq, index) => {
            if (!hasCustomStyle(bq)) {
                console.log(`Processing blockquote ${index + 1}`);
                processBlockquote(bq);
            } else {
                console.log(`Skipping custom blockquote ${index + 1}`);
            }
        });
    }

    // ==================== 共用功能 ====================

    // 查找 BlockQuote 元素
    function findSiYuanBlockQuotes() {
        const selectors = ['[data-type="NodeBlockquote"]', '.bq'];
        let allBlockQuotes = [];
      
        selectors.forEach(selector => {
            allBlockQuotes = allBlockQuotes.concat(Array.from(document.querySelectorAll(selector)));
        });
      
        return [...new Set(allBlockQuotes)];
    }

    // 检查是否为空
    function isBlockQuoteEmpty(blockQuote) {
        const contentDiv = blockQuote.querySelector('[contenteditable="true"]');
        if (!contentDiv) return false;
      
        const text = contentDiv.textContent.trim();
        return text === '' || text.length < 3 || /^[\s\n\r]*$/.test(text);
    }

    // 检查是否新创建
    function isBlockQuoteNewlyCreated(blockQuote) {
        const nodeId = blockQuote.getAttribute('data-node-id');
        if (!nodeId) return false;
      
        // 跳过自定义样式的 BlockQuote
        if (hasCustomStyle(blockQuote)) {
            return false;
        }
      
        const wasTracked = trackedBlockQuotes.has(nodeId);
        const isEmpty = isBlockQuoteEmpty(blockQuote);
      
        return !wasTracked && isEmpty;
    }

    // ==================== 优化的事件监听系统 ====================

    // 优化的MutationObserver
    function setupOptimizedObserver() {
        const observer = new MutationObserver(function(mutations) {
            const relevantMutations = mutations.filter(mutation => {
                // 只关注添加节点的变化
                return mutation.type === 'childList' && mutation.addedNodes.length > 0;
            });

            if (relevantMutations.length === 0) return;

            let newBlockquotes = [];
          
            relevantMutations.forEach(mutation => {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        // 直接检查是否是blockquote
                        if (node.getAttribute?.('data-type') === 'NodeBlockquote' || 
                            node.classList?.contains('bq')) {
                            newBlockquotes.push(node);
                        }
                        // 检查子元素中的blockquote
                        const childBlockquotes = node.querySelectorAll?.('[data-type="NodeBlockquote"], .bq');
                        if (childBlockquotes?.length > 0) {
                            newBlockquotes.push(...Array.from(childBlockquotes));
                        }
                    }
                });
            });

            // 批量处理新的blockquote
            if (newBlockquotes.length > 0) {
                // 去重
                const uniqueBlockquotes = [...new Set(newBlockquotes)];
              
                setTimeout(() => {
                    uniqueBlockquotes.forEach(bq => {
                        if (!hasCustomStyle(bq)) {
                            const nodeId = bq.getAttribute('data-node-id');
                          
                            // 标记为已跟踪
                            if (nodeId) {
                                trackedBlockQuotes.add(nodeId);
                            }
                          
                            // 检查是否为新建的空blockquote
                            if (isBlockQuoteEmpty(bq)) {
                                const rect = bq.getBoundingClientRect();
                                if (rect.width > 0 && rect.height > 0) {
                                    showCommandMenu(rect.left, rect.top, bq);
                                }
                            }
                            // 处理callout
                            processBlockquote(bq);
                        }
                    });
                }, 50);
            }
        });

        // 更精确的观察配置
        observer.observe(document.body, { 
            childList: true, 
            subtree: true,
            attributes: false, // 不观察属性变化
            characterData: false // 不观察文本变化
        });

        return observer;
    }

    // 基于焦点的检测
    function setupFocusBasedDetection() {
        let lastFocusedElement = null;
      
        document.addEventListener('focusin', (e) => {
            const target = e.target;
          
            // 检查是否聚焦到blockquote内的可编辑元素
            if (target.contentEditable === 'true') {
                const blockquote = target.closest('[data-type="NodeBlockquote"], .bq');
                if (blockquote && !hasCustomStyle(blockquote)) {
                    // 如果是新的空blockquote,显示菜单
                    if (isBlockQuoteEmpty(blockquote) && lastFocusedElement !== target) {
                        const nodeId = blockquote.getAttribute('data-node-id');
                        if (nodeId && !recentlyCreatedBlockQuotes.has(nodeId)) {
                            const rect = blockquote.getBoundingClientRect();
                            showCommandMenu(rect.left, rect.top, blockquote);
                        }
                    }
                    lastFocusedElement = target;
                }
            }
        });
    }

    // 事件驱动的callout处理
    function setupEventDrivenSystem() {
        // 使用防抖的输入监听
        let inputTimeout;
      
        ['input', 'keyup', 'paste'].forEach(eventType => {
            document.addEventListener(eventType, function(e) {
                // 检查是否在可编辑元素中
                if (e.target.contentEditable === 'true') {
                    clearTimeout(inputTimeout);
                    inputTimeout = setTimeout(() => {
                        // 查找最近的引用块父元素
                        const blockquote = e.target.closest('[data-type="NodeBlockquote"], .bq');
                        if (blockquote && !hasCustomStyle(blockquote)) {
                            processBlockquote(blockquote);
                        }
                    }, eventType === 'paste' ? 100 : 300); // 防抖300ms,粘贴100ms
                }
            }, true);
        });
    }

    // 🔥 修复:思源API监听(安全版本)
    function setupSiYuanAPIListener() {
        try {
            // 检查思源API是否可用
            if (typeof window.siyuan === 'object' && window.siyuan !== null) {
                console.log('SiYuan API detected');
              
                // 尝试不同的API监听方式
                if (window.siyuan.ws && typeof window.siyuan.ws.onmessage !== 'undefined') {
                    // 方式1:使用 onmessage 属性
                    const originalOnMessage = window.siyuan.ws.onmessage;
                    window.siyuan.ws.onmessage = function(event) {
                        // 调用原始处理器
                        if (originalOnMessage) {
                            originalOnMessage.call(this, event);
                        }
                      
                        // 我们的处理逻辑
                        try {
                            const data = JSON.parse(event.data);
                            if (data.cmd === 'transactions' && data.data) {
                                data.data.forEach(transaction => {
                                    transaction.doOperations?.forEach(op => {
                                        if (op.action === 'insert' && op.data?.includes('NodeBlockquote')) {
                                            setTimeout(() => {
                                                const newBlockquote = document.querySelector(`[data-node-id="${op.id}"]`);
                                                if (newBlockquote && !hasCustomStyle(newBlockquote) && isBlockQuoteEmpty(newBlockquote)) {
                                                    const rect = newBlockquote.getBoundingClientRect();
                                                    showCommandMenu(rect.left, rect.top, newBlockquote);
                                                }
                                            }, 100);
                                        }
                                    });
                                });
                            }
                        } catch (error) {
                            // 忽略JSON解析错误
                        }
                    };
                    console.log('SiYuan WebSocket listener attached via onmessage');
                } else if (window.siyuan.eventBus && typeof window.siyuan.eventBus.on === 'function') {
                    // 方式2:使用事件总线
                    window.siyuan.eventBus.on('ws-main', (data) => {
                        try {
                            if (data.cmd === 'transactions' && data.data) {
                                data.data.forEach(transaction => {
                                    transaction.doOperations?.forEach(op => {
                                        if (op.action === 'insert' && op.data?.includes('NodeBlockquote')) {
                                            setTimeout(() => {
                                                const newBlockquote = document.querySelector(`[data-node-id="${op.id}"]`);
                                                if (newBlockquote && !hasCustomStyle(newBlockquote) && isBlockQuoteEmpty(newBlockquote)) {
                                                    const rect = newBlockquote.getBoundingClientRect();
                                                    showCommandMenu(rect.left, rect.top, newBlockquote);
                                                }
                                            }, 100);
                                        }
                                    });
                                });
                            }
                        } catch (error) {
                            // 忽略处理错误
                        }
                    });
                    console.log('SiYuan event bus listener attached');
                } else {
                    console.log('SiYuan API available but no suitable WebSocket interface found');
                }
            } else {
                console.log('SiYuan API not detected, using DOM-based detection only');
            }
        } catch (error) {
            console.log('Error setting up SiYuan API listener:', error.message);
            console.log('Falling back to DOM-based detection only');
        }
    }

    // 优化的事件监听设置
    function setupOptimizedEventListeners() {
        console.log('Setting up optimized event listeners');
      
        // 初始化已知的 BlockQuote
        const initialBlockQuotes = findSiYuanBlockQuotes();
        initialBlockQuotes.forEach(bq => {
            const nodeId = bq.getAttribute('data-node-id');
            if (nodeId) trackedBlockQuotes.add(nodeId);
        });
      
        // 1. 优化的MutationObserver
        setupOptimizedObserver();
      
        // 2. 基于焦点的检测
        setupFocusBasedDetection();
      
        // 3. 事件驱动的callout处理
        setupEventDrivenSystem();
      
        // 4. 键盘事件(ESC关闭菜单)
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Escape' && isMenuVisible) {
                e.preventDefault();
                hideCommandMenu(true);
                return;
            }
        });
      
        // 5. 点击外部关闭菜单
        document.addEventListener('click', function(e) {
            if (commandMenu && !commandMenu.contains(e.target) && isMenuVisible) {
                setTimeout(() => {
                    if (isMenuVisible) hideCommandMenu(true);
                }, 100);
            }
        });

        // 6. 🔥 修复:安全的思源API监听
        setupSiYuanAPIListener();
    }

    // ==================== 初始化 ====================

    function initOptimized() {
        console.log('Initializing optimized BlockQuote script');
      
        // 初始处理现有的blockquote(只执行一次)
        processAllBlockquotes();
      
        // 设置优化的事件监听
        setupOptimizedEventListeners();
    }

    // 启动优化版本
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initOptimized);
    } else {
        initOptimized();
    }

    // 页面卸载清理
    window.addEventListener('beforeunload', () => hideCommandMenu(true));

    // 调试功能
    window.debugEnhancedBlockQuote = {
        // 菜单相关
        showMenu: () => {
            const blockQuotes = findSiYuanBlockQuotes();
            if (blockQuotes.length > 0) {
                const lastBlockQuote = blockQuotes[blockQuotes.length - 1];
                const rect = lastBlockQuote.getBoundingClientRect();
                showCommandMenu(rect.left, rect.top, lastBlockQuote);
            }
        },
        hideMenu: () => hideCommandMenu(true),
      
        // Callout 相关
        processAll: processAllBlockquotes,
        checkBlockquotes: () => {
            const bqs = document.querySelectorAll('.bq');
            console.log('=== Current blockquotes ===');
            bqs.forEach((bq, i) => {
                const text = bq.textContent.trim();
                const type = bq.getAttribute('data-callout-type');
                const customStyle = hasCustomStyle(bq);
                console.log(`BQ ${i + 1}: "${text}" - Type: ${type || 'none'} - Custom: ${customStyle}`);
            });
        },
      
        // 检查自定义样式
        checkCustomStyles: () => {
            const bqs = document.querySelectorAll('.bq');
            console.log('=== Custom styled blockquotes ===');
            bqs.forEach((bq, i) => {
                if (hasCustomStyle(bq)) {
                    const customB = bq.getAttribute('custom-b');
                    const customCallout = bq.getAttribute('custom-callout');
                    console.log(`Custom BQ ${i + 1}: custom-b="${customB}" custom-callout="${customCallout}"`);
                }
            });
        },
      
        // 状态查看
        status: () => ({
            menuVisible: isMenuVisible,
            trackedCount: trackedBlockQuotes.size,
            recentCount: recentlyCreatedBlockQuotes.size
        }),

        // 性能测试
        performanceTest: () => {
            const start = performance.now();
            processAllBlockquotes();
            const end = performance.now();
            console.log(`Processing all blockquotes took ${end - start} milliseconds`);
        }
    };

    console.log('=== Optimized Enhanced BlockQuote Script Loaded ===');
})();

(2-1)CSS(风格 1)

/* === 普通引用块样式 === */
.bq:not([custom-b]):not([custom-callout]) {
    background: #f8f8f8;
    border-radius: 0;
    margin: 8px 0;
    padding: 10px 16px;
    border-left: 0.25em solid #7d8590 !important;
}

/* === 隐藏普通引用块的黑色伪元素 === */
.bq:not([data-callout-type]):not([custom-b]):not([custom-callout])::before {
    display: none !important;
}

/* === 基础 callout 样式(排除自定义属性)=== */
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) {
    border-left: none !important;
    box-shadow: none !important;
    border-radius: 0;
    padding: 10px !important;
    color: var(--b3-theme-on-background);
    position: relative;
}

.bq[data-callout-type]:not([custom-b]):not([custom-callout])::before,
.bq[data-callout-type]:not([custom-b]):not([custom-callout])::after,
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) .bq-line {
    display: none !important;
    content: none !important;
}

/* === 标题行样式 === */
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type {
    margin-bottom: 0.5em;
}
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    display: inline-flex;
    align-items: center;
    font-weight: bold;
    margin-bottom: 0;
}

/* === 只有当元素具有 data-callout-title 和 data-callout-display-name 时才隐藏触发词 === */
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"][data-callout-title="true"][data-callout-display-name] {
    font-size: 0;
}

.bq[data-callout-type]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"][data-callout-title="true"][data-callout-display-name]::after {
    content: attr(data-callout-display-name);
    font-size: 1rem;
    margin-left: 0;
}

/* === 蓝色系——info === */
.bq[data-callout-type="info"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #1f6feb !important;
    background-color: #1f71eb16 !important;
}
.bq[data-callout-type="info"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #4493f8;
}
.bq[data-callout-type="info"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtY2lyY2xlLWFsZXJ0Ij48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxsaW5lIHgxPSIxMiIgeDI9IjEyIiB5MT0iOCIgeTI9IjEyIi8+PGxpbmUgeDE9IjEyIiB4Mj0iMTIuMDEiIHkxPSIxNiIgeTI9IjE2Ii8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}


/* === 蓝色系——Note === */
.bq[data-callout-type="note"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #1f6feb !important;
    background-color: #1f71eb16 !important;
}
.bq[data-callout-type="note"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #4493f8;
}
.bq[data-callout-type="note"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXBlbmNpbC1pY29uIGx1Y2lkZS1wZW5jaWwiPjxwYXRoIGQ9Ik0yMS4xNzQgNi44MTJhMSAxIDAgMCAwLTMuOTg2LTMuOTg3TDMuODQyIDE2LjE3NGEyIDIgMCAwIDAtLjUuODNsLTEuMzIxIDQuMzUyYS41LjUgMCAwIDAgLjYyMy42MjJsNC4zNTMtMS4zMmEyIDIgMCAwIDAgLjgzLS40OTd6Ii8+PHBhdGggZD0ibTE1IDUgNCA0Ii8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 蓝色系——Comment === */
.bq[data-callout-type="comment"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #1f6feb !important;
    background-color: #1f71eb16 !important;
}
.bq[data-callout-type="comment"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #4493f8;
}
.bq[data-callout-type="comment"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLW1lc3NhZ2Utc3F1YXJlLW1vcmUtaWNvbiBsdWNpZGUtbWVzc2FnZS1zcXVhcmUtbW9yZSI+PHBhdGggZD0iTTIxIDE1YTIgMiAwIDAgMS0yIDJIN2wtNCA0VjVhMiAyIDAgMCAxIDItMmgxNGEyIDIgMCAwIDEgMiAyeiIvPjxwYXRoIGQ9Ik04IDEwaC4wMSIvPjxwYXRoIGQ9Ik0xMiAxMGguMDEiLz48cGF0aCBkPSJNMTYgMTBoLjAxIi8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 绿色系——Tip === */
.bq[data-callout-type="tip"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #238636 !important;
    background-color: #23863615 !important;
}
.bq[data-callout-type="tip"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #238636;
}
.bq[data-callout-type="tip"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtbGlnaHRidWxiIj48cGF0aCBkPSJNMTUgMTRjLjItMSAuNy0xLjcgMS41LTIuNSAxLS45IDEuNS0yLjIgMS41LTMuNUE2IDYgMCAwIDAgNiA4YzAgMSAuMiAyLjIgMS41IDMuNS43LjcgMS4zIDEuNSAxLjUgMi41Ii8+PHBhdGggZD0iTTkgMThoNiIvPjxwYXRoIGQ9Ik0xMCAyMmg0Ii8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 黄色系——Important === */
.bq[data-callout-type="important"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #e3b341 !important;
    background-color: #e3b34115 !important;
}
.bq[data-callout-type="important"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #e3b341;
}
.bq[data-callout-type="important"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtbWVzc2FnZS1zcXVhcmUtd2FybmluZyI+PHBhdGggZD0iTTIxIDE1YTIgMiAwIDAgMS0yIDJIN2wtNCA0VjVhMiAyIDAgMCAxIDItMmgxNGEyIDIgMCAwIDEgMiAyeiIvPjxwYXRoIGQ9Ik0xMiA3djIiLz48cGF0aCBkPSJNMTIgMTNoLjAxIi8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 黄色系——Warning === */
.bq[data-callout-type="warning"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #e3b341 !important;
    background-color: #e3b34115 !important;
}
.bq[data-callout-type="warning"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #e3b341;
}
.bq[data-callout-type="warning"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtdHJpYW5nbGUtYWxlcnQiPjxwYXRoIGQ9Im0yMS43MyAxOC04LTE0YTIgMiAwIDAgMC0zLjQ4IDBsLTggMTRBMiAyIDAgMCAwIDQgMjFoMTZhMiAyIDAgMCAwIDEuNzMtMyIvPjxwYXRoIGQ9Ik0xMiA5djQiLz48cGF0aCBkPSJNMTIgMTdoLjAxIi8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 黄色系——Caution === */
.bq[data-callout-type="caution"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #e3b341 !important;
    background-color: #e3b34115 !important;
}
.bq[data-callout-type="caution"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #e3b341;
}
.bq[data-callout-type="caution"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtb2N0YWdvbi1hbGVydCI+PHBhdGggZD0iTTEyIDE2aC4wMSIvPjxwYXRoIGQ9Ik0xMiA4djQiLz48cGF0aCBkPSJNMTUuMzEyIDJhMiAyIDAgMCAxIDEuNDE0LjU4Nmw0LjY4OCA0LjY4OEEyIDIgMCAwIDEgMjIgOC42ODh2Ni42MjRhMiAyIDAgMCAxLS41ODYgMS40MTRsLTQuNjg4IDQuNjg4YTIgMiAwIDAgMS0xLjQxNC41ODZIOC42ODhhMiAyIDAgMCAxLTEuNDE0LS41ODZsLTQuNjg4LTQuNjg4QTIgMiAwIDAgMSAyIDE1LjMxMlY4LjY4OGEyIDIgMCAwIDEgLjU4Ni0xLjQxNGw0LjY4OC00LjY4OEEyIDIgMCAwIDEgOC42ODggMnoiLz48L3N2Zz4=");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 紫色系——example === */
.bq[data-callout-type="example"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #8957e5 !important;
    background-color: #8957e515 !important;
}
.bq[data-callout-type="example"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #8957e5;
}
.bq[data-callout-type="example"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWxpc3QtaWNvbiBsdWNpZGUtbGlzdCI+PHBhdGggZD0iTTMgMTJoLjAxIi8+PHBhdGggZD0iTTMgMThoLjAxIi8+PHBhdGggZD0iTTMgNmguMDEiLz48cGF0aCBkPSJNOCAxMmgxMyIvPjxwYXRoIGQ9Ik04IDE4aDEzIi8+PHBhdGggZD0iTTggNmgxMyIvPjwvc3ZnPg==");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}


/* === 红色系——error === */
.bq[data-callout-type="error"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #d1242f !important;
    background-color: #d1242f15 !important;
}
.bq[data-callout-type="error"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #d1242f;
}
.bq[data-callout-type="error"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXNoaWVsZC14LWljb24gbHVjaWRlLXNoaWVsZC14Ij48cGF0aCBkPSJNMjAgMTNjMCA1LTMuNSA3LjUtNy42NiA4Ljk1YTEgMSAwIDAgMS0uNjctLjAxQzcuNSAyMC41IDQgMTggNCAxM1Y2YTEgMSAwIDAgMSAxLTFjMiAwIDQuNS0xLjIgNi4yNC0yLjcyYTEuMTcgMS4xNyAwIDAgMSAxLjUyIDBDMTQuNTEgMy44MSAxNyA1IDE5IDVhMSAxIDAgMCAxIDEgMXoiLz48cGF0aCBkPSJtMTQuNSA5LjUtNSA1Ii8+PHBhdGggZD0ibTkuNSA5LjUgNSA1Ii8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 红色系——question === */
.bq[data-callout-type="question"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #d1242f !important;
    background-color: #d1242f15 !important;
}
.bq[data-callout-type="question"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #d1242f;
}
.bq[data-callout-type="question"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWNpcmNsZS1xdWVzdGlvbi1tYXJrLWljb24gbHVjaWRlLWNpcmNsZS1xdWVzdGlvbi1tYXJrIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxwYXRoIGQ9Ik05LjA5IDlhMyAzIDAgMCAxIDUuODMgMWMwIDItMyAzLTMgMyIvPjxwYXRoIGQ9Ik0xMiAxN2guMDEiLz48L3N2Zz4=");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 默认 callout 样式 === */
.bq[data-callout-type="default"]:not([custom-b]):not([custom-callout]) {
    border-left: 0.25em solid #7d8590 !important;
    background-color: #7d859015 !important;
}
.bq[data-callout-type="default"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #7d8590;
}
.bq[data-callout-type="default"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    display: none;
}

(2-2)CSS(风格 2)

/* === 普通引用块样式 === */
.bq:not([custom-b]):not([custom-callout]) {
    background: #f8f8f8;
    border-radius: 6px;
    padding: 10px 16px;
    margin: 8px 0;
    border-left: 0.25em solid #7d8590 !important;
}

/* === 隐藏普通引用块的黑色伪元素 === */
.bq:not([data-callout-type]):not([custom-b]):not([custom-callout])::before {
    display: none !important;
}

/* === 基础 callout 样式(排除自定义属性)=== */
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) {
    border-left: none !important;
    box-shadow: none !important;
    border-radius: 6px;
    padding: 10px 16px;
    color: var(--b3-theme-on-background);
    position: relative;
}

.bq[data-callout-type]:not([custom-b]):not([custom-callout])::before,
.bq[data-callout-type]:not([custom-b]):not([custom-callout])::after,
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) .bq-line {
    display: none !important;
    content: none !important;
}

/* === 标题行样式 === */
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type {
    margin-bottom: 0.5em;
}
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    display: inline-flex;
    align-items: center;
    font-weight: bold;
    margin-bottom: 0;
}

/* === 只有当元素具有 data-callout-title 和 data-callout-display-name 时才隐藏触发词 === */
.bq[data-callout-type]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"][data-callout-title="true"][data-callout-display-name] {
    font-size: 0;
}

.bq[data-callout-type]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"][data-callout-title="true"][data-callout-display-name]::after {
    content: attr(data-callout-display-name);
    font-size: 1rem;
    margin-left: 0;
}

/* === 蓝色系——info === */
.bq[data-callout-type="info"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #1f6feb !important;
    background-color: #1f71eb16 !important;
}
.bq[data-callout-type="info"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #4493f8;
}
.bq[data-callout-type="info"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtY2lyY2xlLWFsZXJ0Ij48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxsaW5lIHgxPSIxMiIgeDI9IjEyIiB5MT0iOCIgeTI9IjEyIi8+PGxpbmUgeDE9IjEyIiB4Mj0iMTIuMDEiIHkxPSIxNiIgeTI9IjE2Ii8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}


/* === 蓝色系——Note === */
.bq[data-callout-type="note"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #1f6feb !important;
    background-color: #1f71eb16 !important;
}
.bq[data-callout-type="note"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #4493f8;
}
.bq[data-callout-type="note"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXBlbmNpbC1pY29uIGx1Y2lkZS1wZW5jaWwiPjxwYXRoIGQ9Ik0yMS4xNzQgNi44MTJhMSAxIDAgMCAwLTMuOTg2LTMuOTg3TDMuODQyIDE2LjE3NGEyIDIgMCAwIDAtLjUuODNsLTEuMzIxIDQuMzUyYS41LjUgMCAwIDAgLjYyMy42MjJsNC4zNTMtMS4zMmEyIDIgMCAwIDAgLjgzLS40OTd6Ii8+PHBhdGggZD0ibTE1IDUgNCA0Ii8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 蓝色系——Comment === */
.bq[data-callout-type="comment"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #1f6feb !important;
    background-color: #1f71eb16 !important;
}
.bq[data-callout-type="comment"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #4493f8;
}
.bq[data-callout-type="comment"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLW1lc3NhZ2Utc3F1YXJlLW1vcmUtaWNvbiBsdWNpZGUtbWVzc2FnZS1zcXVhcmUtbW9yZSI+PHBhdGggZD0iTTIxIDE1YTIgMiAwIDAgMS0yIDJIN2wtNCA0VjVhMiAyIDAgMCAxIDItMmgxNGEyIDIgMCAwIDEgMiAyeiIvPjxwYXRoIGQ9Ik04IDEwaC4wMSIvPjxwYXRoIGQ9Ik0xMiAxMGguMDEiLz48cGF0aCBkPSJNMTYgMTBoLjAxIi8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 绿色系——Tip === */
.bq[data-callout-type="tip"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #238636 !important;
    background-color: #23863615 !important;
}
.bq[data-callout-type="tip"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #238636;
}
.bq[data-callout-type="tip"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtbGlnaHRidWxiIj48cGF0aCBkPSJNMTUgMTRjLjItMSAuNy0xLjcgMS41LTIuNSAxLS45IDEuNS0yLjIgMS41LTMuNUE2IDYgMCAwIDAgNiA4YzAgMSAuMiAyLjIgMS41IDMuNS43LjcgMS4zIDEuNSAxLjUgMi41Ii8+PHBhdGggZD0iTTkgMThoNiIvPjxwYXRoIGQ9Ik0xMCAyMmg0Ii8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 黄色系——Important === */
.bq[data-callout-type="important"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #e3b341 !important;
    background-color: #e3b34115 !important;
}
.bq[data-callout-type="important"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #e3b341;
}
.bq[data-callout-type="important"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtbWVzc2FnZS1zcXVhcmUtd2FybmluZyI+PHBhdGggZD0iTTIxIDE1YTIgMiAwIDAgMS0yIDJIN2wtNCA0VjVhMiAyIDAgMCAxIDItMmgxNGEyIDIgMCAwIDEgMiAyeiIvPjxwYXRoIGQ9Ik0xMiA3djIiLz48cGF0aCBkPSJNMTIgMTNoLjAxIi8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 黄色系——Warning === */
.bq[data-callout-type="warning"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #e3b341 !important;
    background-color: #e3b34115 !important;
}
.bq[data-callout-type="warning"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #e3b341;
}
.bq[data-callout-type="warning"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtdHJpYW5nbGUtYWxlcnQiPjxwYXRoIGQ9Im0yMS43MyAxOC04LTE0YTIgMiAwIDAgMC0zLjQ4IDBsLTggMTRBMiAyIDAgMCAwIDQgMjFoMTZhMiAyIDAgMCAwIDEuNzMtMyIvPjxwYXRoIGQ9Ik0xMiA5djQiLz48cGF0aCBkPSJNMTIgMTdoLjAxIi8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 黄色系——Caution === */
.bq[data-callout-type="caution"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #e3b341 !important;
    background-color: #e3b34115 !important;
}
.bq[data-callout-type="caution"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #e3b341;
}
.bq[data-callout-type="caution"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjcxNDI4NTcxNDI4NTcxNDIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtb2N0YWdvbi1hbGVydCI+PHBhdGggZD0iTTEyIDE2aC4wMSIvPjxwYXRoIGQ9Ik0xMiA4djQiLz48cGF0aCBkPSJNMTUuMzEyIDJhMiAyIDAgMCAxIDEuNDE0LjU4Nmw0LjY4OCA0LjY4OEEyIDIgMCAwIDEgMjIgOC42ODh2Ni42MjRhMiAyIDAgMCAxLS41ODYgMS40MTRsLTQuNjg4IDQuNjg4YTIgMiAwIDAgMS0xLjQxNC41ODZIOC42ODhhMiAyIDAgMCAxLTEuNDE0LS41ODZsLTQuNjg4LTQuNjg4QTIgMiAwIDAgMSAyIDE1LjMxMlY4LjY4OGEyIDIgMCAwIDEgLjU4Ni0xLjQxNGw0LjY4OC00LjY4OEEyIDIgMCAwIDEgOC42ODggMnoiLz48L3N2Zz4=");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 紫色系——example === */
.bq[data-callout-type="example"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #8957e5 !important;
    background-color: #8957e515 !important;
}
.bq[data-callout-type="example"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #8957e5;
}
.bq[data-callout-type="example"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWxpc3QtaWNvbiBsdWNpZGUtbGlzdCI+PHBhdGggZD0iTTMgMTJoLjAxIi8+PHBhdGggZD0iTTMgMThoLjAxIi8+PHBhdGggZD0iTTMgNmguMDEiLz48cGF0aCBkPSJNOCAxMmgxMyIvPjxwYXRoIGQ9Ik04IDE4aDEzIi8+PHBhdGggZD0iTTggNmgxMyIvPjwvc3ZnPg==");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}


/* === 红色系——error === */
.bq[data-callout-type="error"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #d1242f !important;
    background-color: #d1242f15 !important;
}
.bq[data-callout-type="error"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #d1242f;
}
.bq[data-callout-type="error"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXNoaWVsZC14LWljb24gbHVjaWRlLXNoaWVsZC14Ij48cGF0aCBkPSJNMjAgMTNjMCA1LTMuNSA3LjUtNy42NiA4Ljk1YTEgMSAwIDAgMS0uNjctLjAxQzcuNSAyMC41IDQgMTggNCAxM1Y2YTEgMSAwIDAgMSAxLTFjMiAwIDQuNS0xLjIgNi4yNC0yLjcyYTEuMTcgMS4xNyAwIDAgMSAxLjUyIDBDMTQuNTEgMy44MSAxNyA1IDE5IDVhMSAxIDAgMCAxIDEgMXoiLz48cGF0aCBkPSJtMTQuNSA5LjUtNSA1Ii8+PHBhdGggZD0ibTkuNSA5LjUgNSA1Ii8+PC9zdmc+");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 红色系——question === */
.bq[data-callout-type="question"]:not([custom-b]):not([custom-callout]) {
    border-left: .25em solid #d1242f !important;
    background-color: #d1242f15 !important;
}
.bq[data-callout-type="question"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #d1242f;
}
.bq[data-callout-type="question"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 24px;
    height: 24px;
    margin-right: 10px;
    mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWNpcmNsZS1xdWVzdGlvbi1tYXJrLWljb24gbHVjaWRlLWNpcmNsZS1xdWVzdGlvbi1tYXJrIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxwYXRoIGQ9Ik05LjA5IDlhMyAzIDAgMCAxIDUuODMgMWMwIDItMyAzLTMgMyIvPjxwYXRoIGQ9Ik0xMiAxN2guMDEiLz48L3N2Zz4=");
    mask-size: cover;
    background-color: currentColor;
    mask-repeat: no-repeat;
    overflow: visible !important;
}

/* === 默认 callout 样式 === */
.bq[data-callout-type="default"]:not([custom-b]):not([custom-callout]) {
    border-left: 0.25em solid #7d8590 !important;
    background-color: #7d859015 !important;
}
.bq[data-callout-type="default"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"] {
    color: #7d8590;
}
.bq[data-callout-type="default"]:not([custom-b]):not([custom-callout]) > div[data-type="NodeParagraph"]:first-of-type > div[contenteditable="true"]::before {
    display: none;
}

四、参考

  1. [css][js] 识别开头内容,应用风格样式
  2. [js] 适配任何主题的 Callout
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    26351 引用 • 109582 回帖
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    203 引用 • 1473 回帖
2 操作
shangzw 在 2025-06-22 10:18:23 更新了该帖
JeffreyChen 在 2025-06-22 00:59:18 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • funnybow

    导出图片或者 PDF 的时候有效果吗

    2 回复
  • shangzw

    无效

  • 大佬有办法把 callout 菜单添加到斜杠菜单中或者是右键菜单中吗?或者有办法手动触发 callout 菜单吗?不然调整现有 callout 不方便。

    1 回复
  • shangzw

    就是普通用户,想加到斜杠菜单的话直接用 Savor Callout 插件就行

  • GloR

    请问这个 callout 菜单是怎么调出来的 😂?

    谢谢!

    1 回复
  • jingtu

    打开设置-> 外观-> 代码片段-> 设置,复制粘贴即可

  • shangzw 1

    思源自带的导出图片和 PDF 没办法带上效果,但是用浏览器打开思源笔记调用浏览器的打印到 PDF 可以带上效果,有些麻烦

    1 回复
  • 感谢答复 🙏

  • xjtcnj

    带折叠符就好了。

    1 操作
    xjtcnj 在 2025-06-29 10:19:39 更新了该回帖
请输入回帖内容 ...