获取光标所在元素的上级标题,当不存在时显示文档标题

获取光标所在元素的上级标题,当不存在时显示文档标题

// 获取光标所在元素的上级标题,当不存在时显示文档标题
// see https://ld246.com/article/1734576044332
// see https://ld246.com/article/1729605574188
// see 
(()=>{
    // 添加样式
    addStyle(`
        .fn__flex-1.dock__item--space {
        	display: flex;
        	justify-content: center; /* 水平居中 */
        	align-items: center; /* 垂直居中 */
        	font-size: 20px; /* 字体大小 */
        	writing-mode: vertical-rl; /* 竖向排列 */
        	text-align: center; /* 文字居中对齐 */
        }
    `);
  
    // 光标被位置变动事件
    document.addEventListener("selectionchange", () => {
        const el = getCursorElement();
        const parentHead = getParentHead(el);
        if(!parentHead) return;
        const text = parentHead.querySelector('div[contenteditable="true"]')?.textContent;
        setDockSpace(text);
    }, false);
  
    // 添加样式
    function addStyle(css) {
        // 创建一个 <style> 元素
        const styleElement = document.createElement('style');
        // 设置样式内容
        styleElement.type = 'text/css';
        styleElement.appendChild(document.createTextNode(css));
        // 将 <style> 元素添加到 <head> 中
        document.head.appendChild(styleElement);
    }
    // 设置左侧dock空白文字
    function setDockSpace(html) {
        const dockSpace = document.querySelector('#dockLeft .fn__flex-1.dock__item--space');
        dockSpace.innerHTML = html;
    }
    // 获取上级标题
    function getParentHead(el) {
        let parentHead = null;
        //获取是否在head中
        const head = isInHeading(el);
        if(head) {
            // 光标在head中
            parentHead = findPreviousNodeHeading(head);
            if(head && parentHead) {
                // 获取错误则抛弃
                const headSubtype = parseInt(head.dataset.subtype.replace(/h/i, ''));
                const parentHeadSubtype = parseInt(parentHead.dataset.subtype.replace(/h/i, ''));
                if(parentHeadSubtype > headSubtype) parentHead = null;
            }
        } else {
            // 光标不在head中
            const Sibling = el?.closest('[data-node-index]');
            parentHead = findPreviousNodeHeading(Sibling);
        }
        // 不在head中显示文档标题
        if(!parentHead) {
            const protyle = el.closest('.protyle');
            const title = protyle.querySelector('.protyle-title');
            return title;
        }
        return parentHead;
    }
    // 判断光标是发在标题中
    function isInHeading(el) {
        let heading = el?.closest('[data-type="NodeHeading"]');
        if(heading) {
            return heading;
        }
        return null;
    }
    // 递归查找上一个标题
    function findPreviousNodeHeading(el) {
        // 从当前元素开始向前查找兄弟节点
        let sibling = el?.previousElementSibling;
  
        while (sibling) {
            // 检查是否具有 data-type="NodeHeading" 的属性
            if (sibling.getAttribute('data-type') === 'NodeHeading') {
                return sibling; // 找到了,返回这个节点
            }
            // 继续向前查找
            sibling = sibling.previousElementSibling;
        }
  
        // 如果没有找到符合条件的兄弟节点,返回null
        return null;
    }
    // 获取光标所在的元素
    function getCursorElement() {
        const selection = window.getSelection();
        if (selection.rangeCount > 0) {
            const range = selection.getRangeAt(0);
            // 获取选择范围的起始位置所在的节点
            const startContainer = range.startContainer;
            // 如果起始位置是文本节点,返回其父元素节点
            const cursorElement = startContainer.nodeType === Node.TEXT_NODE
                ? startContainer.parentElement
                : startContainer;
  
            return cursorElement;
        }
        return null;
    }
})();
image.png

留下你的脚步
推荐阅读