把移动菜单移动到文档导航条

把移动菜单移动到文档导航条

我习惯先写文章,再命名标题,最后想分类和标签。

那么鉴于此,我通常先点标签页的+按钮创建一篇文档,然后写好后再移动文档到指定目录。

所以,有了这个功能在移动时更方便,虽然标题菜单里也有,还是这个更方便些。

// 把移动菜单移动到文档导航条
// 通过模拟点击菜单按钮实现
{
    const main = (protyle)=>{
        // 发布服务下不显示
        if(window.siyuan.config.readonly) return;

        if(protyle?.querySelector('.protyle-breadcrumb [data-type="move"]')) return;
        const exitFocusBtn = protyle.querySelector('.protyle-breadcrumb [data-type="exit-focus"]');
        if(!exitFocusBtn) return;
        const moveHtml = `<button class="block__icon fn__flex-center ariaLabel" aria-label="移动" data-type="move"><svg><use xlink:href="#iconMove"></use></svg></button>`;
        exitFocusBtn.insertAdjacentHTML('afterend', moveHtml);
        const moveBtn = protyle.querySelector('.protyle-breadcrumb [data-type="move"]');
        if(!moveBtn) return;
        moveBtn.addEventListener('click', async () => {
            // 锁定状态下不可修改
            const icon = protyle?.querySelector('button[data-type="readonly"] use')?.getAttributeNS('http://www.w3.org/1999/xlink', 'href');
            if(icon === '#iconLock') {
                showMessage('锁定状态不可用');
                return
            }

            const docBtn = protyle.querySelector('.protyle-breadcrumb [data-type="doc"]');
            docBtn.click();
            menuMoveBtn = await whenElementExist('#commonMenu[data-name="titleMenu"] button[data-id="move"]');
            menuMoveBtn.click();
        });
    };

    // 监听protyle加载
    whenElementExist('.protyle:not(.fn__none)').then(main);
    observeProtyleLoad(main);

    function showMessage(message, isError = false, delay = 7000) {
        return fetch('/api/notification/' + (isError ? 'pushErrMsg' : 'pushMsg'), {
            "method": "POST",
            "body": JSON.stringify({"msg": message, "timeout": delay})
        });
    }
    async function requestApi(url, data, method = 'POST') {
        return await (await fetch(url, {method: method, body: JSON.stringify(data||{})})).json();
    }
    function whenElementExist(selector, node) {
        return new Promise(resolve => {
            const check = () => {
                const el = typeof selector==='function'?selector():(node||document).querySelector(selector);
                if (el) resolve(el); else requestAnimationFrame(check);
            };
            check();
        });
    }
    function observeProtyleLoad(callback, parentElement) {
        // 如果 parentElement 是字符串,则将其转换为 DOM 元素
        if (typeof parentElement === 'string') {
            parentElement = document.querySelector(parentElement);
        }
        // 创建一个 MutationObserver 实例
        const observer = new MutationObserver((mutationsList) => {
            mutationsList.forEach((mutation) => {
                // 检查是否是属性变化并且变化的属性是 class
                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                    const targetElement = mutation.target; // 发生变化的目标元素
  
                    // 判断目标元素是否匹配指定选择器 .protyle:not(.fn__none)
                    if (targetElement.matches('.protyle:not(.fn__none)')) {
                        // 触发回调
                        callback(targetElement);
                    }
                }
            });
        });
        // 配置观察选项
        const config = {
            attributes: true, // 监听属性变化
            attributeFilter: ['class'], // 仅监听 class 属性
            subtree: true, // 监听父容器及其所有后代元素
        };
        // 启动观察,默认监听 document.body 或指定的父容器
        observer.observe(parentElement || document.body, config);
    }
}

类似的有 把优化排版按钮移动到外层

see https://ld246.com/article/1744685676889

其核心代码是调用api即可

// 优化排版
// see https://github.com/siyuan-note/siyuan/blob/a01523dc98799590396ffcabdc90b2dc6efe8474/app/src/protyle/breadcrumb/index.ts#L415
requestApi("/api/format/autoSpace", {
    id: protyle?.querySelector('.protyle-title')?.dataset?.nodeId
});

image.png

留下你的脚步
推荐阅读