-
-
Notifications
You must be signed in to change notification settings - Fork 239
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New extensions: side panel and outliner (#284)
* upload side panel core * upload outliner extension * add onLoad, onSwitch, and onResize functions to panel extensions * Update panel.js * Add onLock and onUnlock functions to panel extensions * Reordered side panel content loading * change panel switcher font color * fix loading last opened panel * use svg icon files instead of defining them inline * outliner: add full height option
- Loading branch information
Showing
10 changed files
with
805 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* outliner | ||
* (c) 2020 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) | ||
* (c) 2020 CloudHill | ||
* under the MIT license | ||
*/ | ||
|
||
.outliner { | ||
max-height: 100%; | ||
overflow: hidden auto; | ||
} | ||
|
||
.outline-header { | ||
display: flex; | ||
align-items: center; | ||
height: 2.2em; | ||
cursor: pointer; | ||
user-select: none; | ||
transition: background 20ms ease-in; | ||
} | ||
.outline-header:hover { | ||
background: var(--theme--interactive_hover); | ||
} | ||
|
||
.outline-header a { | ||
width: 100%; | ||
height: 100%; | ||
padding: 0 14px; | ||
line-height: 2.2; | ||
color: inherit; | ||
text-decoration: none; | ||
|
||
white-space: nowrap; | ||
overflow: hidden; | ||
text-overflow: ellipsis; | ||
} | ||
|
||
.outline-header a:empty:before { | ||
color: var(--theme--text_ui_info); | ||
content: attr(placeholder); | ||
display: block; | ||
} | ||
.outline-header.notion-header-block a { | ||
text-indent: 0; | ||
} | ||
.outline-header.notion-sub_header-block a { | ||
text-indent: 18px; | ||
} | ||
.outline-header.notion-sub_sub_header-block a { | ||
text-indent: 36px; | ||
} |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* outliner | ||
* (c) 2020 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) | ||
* (c) 2020 CloudHill | ||
* under the MIT license | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const store = require("../../pkg/store"); | ||
|
||
module.exports = { | ||
id: '87e077cc-5402-451c-ac70-27cc4ae65546', | ||
tags: ['extension', 'panel'], | ||
name: 'outliner', | ||
desc: 'table of contents.', | ||
version: '1.0.0', | ||
author: 'CloudHill', | ||
options: [ | ||
{ | ||
key: 'fullHeight', | ||
label: 'full height', | ||
type: 'toggle', | ||
value: false | ||
} | ||
], | ||
panel: { | ||
html: "panel.html", | ||
name: "Outline", | ||
icon: "icon.svg", | ||
js: "panel.js", | ||
fullHeight: store('87e077cc-5402-451c-ac70-27cc4ae65546').fullHeight | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<div class="outliner"></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* 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) => { | ||
// Observe for page changes | ||
const pageObserver = new MutationObserver((list, observer) => { | ||
for ( let { addedNodes } of list) { | ||
if (addedNodes[0]) { | ||
if (addedNodes[0].className === 'notion-page-content') { | ||
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 => { | ||
if ( | ||
( | ||
m.type === 'childList' && | ||
( | ||
isHeaderElement(m.target) || | ||
isHeaderElement(m.addedNodes[0]) || | ||
isHeaderElement(m.removedNodes[0]) | ||
) | ||
) || | ||
( | ||
m.type === 'characterData' && | ||
isHeaderElement(m.target.parentElement) | ||
) | ||
) findHeaders(); | ||
}) | ||
}); | ||
|
||
function startContentObserver() { | ||
findHeaders(); | ||
contentObserver.disconnect(); | ||
contentObserver.observe( | ||
document.querySelector('.notion-page-content'), | ||
{ | ||
childList: true, | ||
subtree: true, | ||
characterData: true, | ||
} | ||
); | ||
} | ||
|
||
function findHeaders() { | ||
const outline = document.querySelector('.outliner'); | ||
if (!outline) return; | ||
outline.textContent = ''; | ||
|
||
const pageContent = document.querySelector('.notion-page-content'); | ||
const headerBlocks = pageContent.querySelectorAll('[class*="header-block"]'); | ||
|
||
headerBlocks.forEach(block => { | ||
const blockId = block.dataset.blockId.replace(/-/g, ''); | ||
const placeholder = block.querySelector('[placeholder]').getAttribute('placeholder'); | ||
const header = createElement(` | ||
<div class="outline-header ${block.classList[1]}"> | ||
<a href="${window.location.pathname}#${blockId}" | ||
placeholder="${placeholder}">${block.innerText}</a> | ||
</div> | ||
`); | ||
|
||
outline.append(header); | ||
}) | ||
} | ||
|
||
function isHeaderElement(el) { | ||
let placeholder; | ||
if (el) { | ||
if ( | ||
el.querySelector && | ||
el.querySelector('[placeholder]') | ||
) { | ||
placeholder = el.querySelector('[placeholder]').getAttribute('placeholder') | ||
} else if (el.getAttribute) { | ||
placeholder = el.getAttribute('placeholder'); | ||
} | ||
} | ||
if (!placeholder) placeholder = ''; | ||
return placeholder.includes('Heading'); | ||
} | ||
|
||
return { | ||
onLoad() { | ||
// Find headers when switching panels | ||
if (document.querySelector('.notion-page-content')) { | ||
startContentObserver(); | ||
}; | ||
pageObserver.observe(document.body, { | ||
childList: true, | ||
subtree: true, | ||
}); | ||
}, | ||
onSwitch() { | ||
pageObserver.disconnect(); | ||
contentObserver.disconnect(); | ||
} | ||
} | ||
} |
Oops, something went wrong.