获取光标所在元素的上级标题,当不存在时显示文档标题
获取光标所在元素的上级标题,当不存在时显示文档标题
// 获取光标所在元素的上级标题,当不存在时显示文档标题
// 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;
}
})();