notion plugin

add notion outline view

Устаревшая версия за 01.11.2022. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         notion plugin
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  add notion outline view
// @author       fengxxc
// @match        https://www.notion.so/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=notion.so
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    /**
	 * 一、二、三 级标题的className分别为
	 * notion-header-block
	 * notion-sub_header-block
	 * notion-sub_sub_header-block
	 */
	function getOutlineTokens() {
		const headerBlock = document.querySelectorAll('.notion-header-block,.notion-sub_header-block,.notion-sub_sub_header-block')
		const tokens = []
		for (var i = 0; i < headerBlock.length; i++) {
			const id = headerBlock[i].getAttribute('data-block-id').replaceAll('-', '')
			// const notranslate = headerBlock[i].querySelector('.notranslate')
			const level = headerBlock[i].className.split('sub').length
			const header = headerBlock[i].innerText
			tokens.push({id, level, header})
		}
		return tokens
	}

	function getOutlineHTMLs(outlineTokens) {
		const pathname = window.location.pathname
		return outlineTokens.map(token => (`
			<a href="${pathname}#${token.id}" rel="noopener noreferrer" style="display: block; color: inherit; text-decoration: none;">
				<div class="notion-focusable" role="button" tabindex="0" style="user-select: none; transition: background 20ms ease-in 0s; cursor: pointer; width: 100%;">
					<div style="padding: 6px 2px; font-size: 14px; line-height: 1.3; display: flex; align-items: center; margin-left: ${(token.level-1) * 24}px;">
						<div class="notranslate" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; background-image: linear-gradient(to right, rgba(55, 53, 47, 0.16) 0%, rgba(55, 53, 47, 0.16) 100%); background-repeat: repeat-x; background-position: 0px 100%; background-size: 100% 1px;">
							${token.header}
						</div>
					</div>
				</div>
			</a>
		`))
	}

	function getOutlineBox(outlineHTMLs) {
		return `
			<div id="outline_view" style="position: fixed; top: 47px; right: 16px; z-index: 2; background-color: #f0f8ffcc; padding: 9px; height: calc(100% - 47px); overflow-y: auto; max-width: 33%;">
				${outlineHTMLs.join('')}
			</div>
		`
	}

	let notionFrame = null
	let existBox = false
	let lastTokenStr = ''
	const initInterval = setInterval(() => {
		notionFrame = notionFrame || document.querySelector('.notion-frame')
		if (notionFrame) {
			// init completed
			// clearInterval(initInterval)
			const tokens = getOutlineTokens()
			const tokenStr = JSON.stringify(tokens)
			if (!existBox) {
				notionFrame.insertAdjacentHTML('afterend', getOutlineBox(getOutlineHTMLs(tokens)))
				existBox = true
				lastTokenStr = tokenStr
			} else {
				if (lastTokenStr != tokenStr) {
					document.querySelector('#outline_view').innerHTML = getOutlineHTMLs(tokens).join('')
					lastTokenStr = tokenStr
				}
			}
		}
	}, 1000)

})();