两步设置notion客户端悬浮目录

notion客户端设置悬浮目录

此方法针对notion-enhancer插件修改得来,后期notion-enhancer可能会完善,但目前无法显示悬浮目录。

设置后目录可以显示在右侧侧边栏

 还可以自动隐藏在右侧,当鼠标滑到最右侧时出现(通过点击<<实现)

一、安装notion-enhancer插件并打开side panel和outliner

插件地址https://github.com/notion-enhancer/desktophttps://github.com/notion-enhancer/desktop

二、打开notion-enhancer插件地址

路径一般为:系统盘\用户(或user)\当前电脑账户名\AppData\Roaming\npm\node_modules\notion-enhancer

1. 找到\mods\side-panel下的app.css,打开app.css文件,将以下代码覆盖源代码

/*
 * side panel
 * (c) 2020 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 * (c) 2020 CloudHill
 * under the MIT license
 */

.notion-frame {
  transition: padding-right 300ms ease-in-out;
}
.enhancer-panel--container {
  flex-grow: 0;
  flex-shrink: 0;
  position: absolute;
  top: 40px;
  bottom: 0;
  right: 0;
  z-index: 99;
  height: 100vh;
  background: var(--theme--sidebar);
  color: var(--theme--text_ui);
  font-weight: 500;
  cursor: default;
  transition: box-shadow 300ms ease-in, width 300ms ease-in-out;
}

#enhancer-panel {
  display: flex;
  flex-direction: column;
  position: relative;
  pointer-events: auto;
  background: var(--theme--sidebar);
  cursor: auto;
  max-height: 100%;
  transition: transform 300ms ease-in-out, 
    opacity 300ms ease-in-out,
    right 300ms ease-in-out;
}
#enhancer-panel[data-locked="false"] {
  max-height: calc(100vh - 120px);
  box-shadow: var(--theme--box-shadow_strong) !important;
}
#enhancer-panel[data-full-height="true"] {
  height: 100%;
}
#enhancer-panel[data-locked="false"][data-full-height="true"] {
  height: calc(100vh - 120px);
}

.enhancer-panel--header {
  flex-grow: 0;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  height: 45px;
  width: 100%;
  color: var(--theme--text);
  font-size: 14px;
  padding: 2px 14px;
  overflow: hidden;
  user-select: none;
  cursor: pointer;
  transition: color 0.4s ease, background 0.4s ease, box-shadow 0.4s ease;
}
.enhancer-panel--header:hover {
  background: var(--theme--interactive_hover);
}

.enhancer-panel--icon {
  flex-grow: 0;
  flex-shrink: 0;
  border-radius: 3px;
  width: 22px;
  height: 22px;
  margin-right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.enhancer-panel--icon svg {
  width: 100%;
  height: 100%;
}

.enhancer-panel--title {
  margin-right: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.enhancer-panel--reload-button {
  flex-grow: 0;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 6px;
  margin-right: 6px;
  border-radius: 3px;
  transition: background 20ms ease-in;
}
.enhancer-panel--reload-button:hover {
  background: var(--theme--main)
}

.enhancer-panel--switcher-icon {
  flex-grow: 0;
  flex-shrink: 0;
  width: 12px;
  height: 12px;
  fill: var(--theme--text_ui);
}
.enhancer-panel--reload-button svg,
.enhancer-panel--switcher-icon svg {
  width: 100%;
  height: 100%;
  display: block;
  fill: var(--theme--text_ui_info);
}

.enhancer-panel--toggle {
  flex-grow: 0;
  flex-shrink: 0;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
  height: 24px;
  width: 24px;
  border-radius: 3px;
  cursor: pointer;
  opacity: 0;
  transition: background 20ms ease-in, opacity 300ms ease-in;
}
#enhancer-panel:hover .enhancer-panel--toggle {
  opacity: 1;
}
.enhancer-panel--toggle:hover {
  background: var(--theme--interactive_hover);
}
.enhancer-panel--toggle svg {
  width: 14px;
  height: 14px;
  fill: var(--theme--text_ui);
  transition: transform 400ms ease-in;
  fill: var(--theme--text_ui_info);
}
#enhancer-panel[data-locked="false"] .enhancer-panel--toggle svg {
  transform: rotateZ(-180deg);
}

#enhancer-panel--content {
  flex: 1;
  width: 100%;
  color: var(--theme--text);
  font-size: var(--theme--font_body-size);
  display: flex;
  flex-direction: column;
  position: relative;
  min-height: 0;
}

.enhancer-panel--resize {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100vh;
  width: 0px;
  z-index: 1;
}
#enhancer-panel[data-locked="false"] .enhancer-panel--resize {
  height: 100%;
}
.enhancer-panel--resize div {
  height: 100%;
  width: 6px;
}

.enhancer-panel--overlay-container {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 999;
  overflow: hidden;
}

.enhancer-panel--switcher {
  max-width: 320px;
  position: relative;
  right: 14px;
  border-radius: 3px;
  padding: 8px 0;
  box-shadow: var(--theme--box-shadow_strong);
  background: var(--theme--card);
  overflow: hidden;
}

.enhancer-panel--switcher-item {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 8px 14px;
  color: var(--theme--text);
  font-size: 14px;
  user-select: none;
  cursor: pointer;
  overflow: hidden;
  transition: background 300ms ease;
}
.enhancer-panel--switcher-item:hover {
  background: var(--theme--interactive_hover);
}

 2. 找到\mods\outliner下的panel.js,打开panel.js文件,将以下代码覆盖源代码

/*
 * outliner
 * (c) 2020 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 * (c) 2020 CloudHill
 * under the MIT license
 */

"use strict";

const { createElement } = require("../../pkg/helpers");

module.exports = (store, __exports) => {
  let lastSearch;

  // Observe for page changes
  const pageObserver = new MutationObserver((list, observer) => {
    for (let { addedNodes } of list) {
      if (addedNodes[0]) {
        // replace
        // if (addedNodes[0].className === 'notion-page-content') {
        if (addedNodes[0].className === "notion-scroller vertical horizontal") {
          startContentObserver();
        }
        // Clear outline on database pages
        else if (addedNodes[0].className === "notion-scroller") {
          contentObserver.disconnect();
          const outline = document.querySelector(".outliner");
          if (outline) outline.textContent = "";
        }
      }
    }
  });

  // Observe for header changes
  const contentObserver = new MutationObserver((list, observer) => {
    list.forEach((m) => {
      let header;
      if (
        (m.type === "childList" &&
          (m.target.hasAttribute("placeholder") ||
            m.target.className?.includes("header-block")) &&
          ((header = getHeaderBlock(m.target)) ||
            (header = getHeaderBlock(m.addedNodes[0])))) ||
        (m.type === "characterData" &&
          (header = getHeaderBlock(m.target.parentElement)))
      )
        updateOutlineHeader(header);
      else if (
        m.type === "childList" &&
        m.removedNodes[0] &&
        (isHeaderElement(m.removedNodes[0]) ||
          m.removedNodes[0].querySelector?.('[class*="header-block"]'))
      )
        findHeaders();
    });
  });

  function startContentObserver() {
    findHeaders();
    contentObserver.disconnect();
    contentObserver.observe(
      // replace
      document.querySelector(".notion-scroller.vertical.horizontal"),
      // document.querySelector('.notion-page-content'),
      {
        childList: true,
        subtree: true,
        characterData: true,
      }
    );
  }

  function findHeaders() {
    // Add cooldown to prevent the function being run twice at the 'same' time
    if (lastSearch >= Date.now() - 10) return;
    lastSearch = Date.now();

    const outline = document.querySelector(".outliner");
    if (!outline) return;
    outline.textContent = "";
    // replace
    const pageContent = document.querySelector(
        ".notion-scroller.vertical.horizontal"
      ),
      headerBlocks = pageContent.querySelectorAll('[class*="header-block"]'),
      fragment = new DocumentFragment();

    headerBlocks.forEach((header) => {
      const blockId = header.dataset.blockId.replace(/-/g, ""),
        headerEl = header.querySelector("[placeholder]"),
        placeholder = headerEl.getAttribute("placeholder");

      const outlineHeader = createElement(`
        <div class="outline-header" header-level="${placeholder.slice(-1)}">
          <a href="${window.location.pathname}#${blockId}" class="outline-link"
            outline-placeholder="${placeholder}"></a>
        </div>
      `);
      header.outline = outlineHeader;
      outlineHeader.firstElementChild.innerHTML = headerEl.innerHTML;

      fragment.appendChild(outlineHeader);
    });

    outline.appendChild(fragment);
  }

  function updateOutlineHeader(header) {
    const headerEl = header.querySelector("[placeholder]");
    if (!(headerEl && header.outline?.parentElement)) return findHeaders();
    const outlineHeader = header.outline;
    outlineHeader.firstElementChild.innerHTML = headerEl.innerHTML;
    setOutlineLevel(
      outlineHeader,
      headerEl.getAttribute("placeholder").slice(-1)
    );
  }

  function setOutlineLevel(outlineHeader, level) {
    outlineHeader.setAttribute("header-level", level);
    outlineHeader.firstElementChild.setAttribute(
      "outline-placeholder",
      `Header ${level}`
    );
  }

  function getHeaderBlock(el) {
    return el?.closest?.('[class*="header-block"]');
  }

  function isHeaderElement(el) {
    let placeholder;
    if (el) {
      placeholder =
        el.getAttribute?.("placeholder") ||
        el.querySelector?.("[placeholder]")?.getAttribute("placeholder");
    }
    if (!placeholder) placeholder = "";
    return placeholder.includes("Heading");
  }

  return {
    onLoad() {
      if (store().lined) {
        const outline = document.querySelector(".outliner");
        outline?.setAttribute("lined", "");
      }

      if (document.querySelector(".notion-scroller.vertical.horizontal")) {
        startContentObserver();
      }
      pageObserver.observe(document.body, {
        childList: true,
        subtree: true,
      });
    },
    onSwitch() {
      pageObserver.disconnect();
      contentObserver.disconnect();
    },
  };
};

设置完成,快打开你的notion体验悬浮目录吧!

卡顿

如果感觉有些卡顿,删除不要的功能,notion-enhancer这个插件的功能特别的多,并且是模块化的。

对于我,我只需要悬浮目录的功能,所以就只留了这些:

 其中core、outliner、side-panel是不能删的,删除后你的目录功能会受到影响,你也可以选择性的保留你需要的功能。(建议将不要的功能放到其他位置,以便需要时加入)

                                                                                                                              期待你的评论!

附图1:

 附图2:

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MriJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值