From 67b396e5110c80d653afd3d316460db45c9dd9b8 Mon Sep 17 00:00:00 2001 From: CloudHill Date: Mon, 7 Dec 2020 16:26:40 +0700 Subject: [PATCH 1/5] outliner now follows the headers' inline styling --- mods/outliner/mod.js | 2 +- mods/outliner/panel.js | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/mods/outliner/mod.js b/mods/outliner/mod.js index 56efa89..0dd85cf 100644 --- a/mods/outliner/mod.js +++ b/mods/outliner/mod.js @@ -14,7 +14,7 @@ module.exports = { tags: ['extension', 'panel'], name: 'outliner', desc: 'table of contents.', - version: '1.0.0', + version: '1.1.0', author: 'CloudHill', options: [ { diff --git a/mods/outliner/panel.js b/mods/outliner/panel.js index 044c8d7..428c8b6 100644 --- a/mods/outliner/panel.js +++ b/mods/outliner/panel.js @@ -69,16 +69,18 @@ module.exports = (store, __exports) => { 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(` + headerBlocks.forEach(header => { + const blockId = header.dataset.blockId.replace(/-/g, ''); + const headerEl = header.querySelector('[placeholder]'); + const placeholder = headerEl.getAttribute('placeholder'); + + const outlineHeader = createElement(`
${block.innerText} + outline-placeholder="${placeholder}">${headerEl.innerHTML}
`); - outline.append(header); + outline.append(outlineHeader); }) } From 6a8006823f386f53e2f3fcc97377e637906259d2 Mon Sep 17 00:00:00 2001 From: CloudHill Date: Mon, 7 Dec 2020 16:52:14 +0700 Subject: [PATCH 2/5] outliner fix inline page links not rendering right --- mods/outliner/app.css | 8 ++++---- mods/outliner/mod.js | 2 +- mods/outliner/panel.js | 8 ++++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/mods/outliner/app.css b/mods/outliner/app.css index 7095dc4..03af8f5 100644 --- a/mods/outliner/app.css +++ b/mods/outliner/app.css @@ -23,7 +23,7 @@ background: var(--theme--interactive_hover); } -.outline-header a { +.outline-header .outline-link { width: 100%; height: 100%; padding: 0 14px; @@ -36,16 +36,16 @@ text-overflow: ellipsis; } -.outline-header a:empty:before { +.outline-header .outline-link:empty:before { color: var(--theme--text_ui_info); content: attr(outline-placeholder); display: block; } -.outline-header[header-level="2"] a { +.outline-header[header-level="2"] .outline-link { text-indent: 18px; } -.outline-header[header-level="3"] a { +.outline-header[header-level="3"] .outline-link { text-indent: 36px; } diff --git a/mods/outliner/mod.js b/mods/outliner/mod.js index 0dd85cf..185b25d 100644 --- a/mods/outliner/mod.js +++ b/mods/outliner/mod.js @@ -14,7 +14,7 @@ module.exports = { tags: ['extension', 'panel'], name: 'outliner', desc: 'table of contents.', - version: '1.1.0', + version: '1.1.1', author: 'CloudHill', options: [ { diff --git a/mods/outliner/panel.js b/mods/outliner/panel.js index 428c8b6..d53a14e 100644 --- a/mods/outliner/panel.js +++ b/mods/outliner/panel.js @@ -76,10 +76,11 @@ module.exports = (store, __exports) => { const outlineHeader = createElement(` `); + outlineHeader.firstElementChild.innerHTML = headerEl.innerHTML; outline.append(outlineHeader); }) } @@ -117,3 +118,6 @@ module.exports = (store, __exports) => { } } } + + + From 07d0836e975beb8166536a3ab3e33f410dfa9060 Mon Sep 17 00:00:00 2001 From: CloudHill Date: Tue, 8 Dec 2020 00:24:01 +0700 Subject: [PATCH 3/5] side-panel: detect keyboard events to navigate the panel switcher (tab, arrows, enter, space, escape) --- mods/side-panel/app.css | 3 ++- mods/side-panel/mod.js | 45 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/mods/side-panel/app.css b/mods/side-panel/app.css index a489931..901147c 100644 --- a/mods/side-panel/app.css +++ b/mods/side-panel/app.css @@ -213,6 +213,7 @@ overflow: hidden; transition: background 300ms ease; } -.enhancer-panel--switcher-item:hover { +.enhancer-panel--switcher-item:hover, +.enhancer-panel--switcher-item:focus { background: var(--theme--interactive_hover); } diff --git a/mods/side-panel/mod.js b/mods/side-panel/mod.js index 3e35589..c830516 100644 --- a/mods/side-panel/mod.js +++ b/mods/side-panel/mod.js @@ -16,7 +16,7 @@ module.exports = { tags: ['extension', 'panel'], name: 'side panel', desc: 'adds a side panel to notion.', - version: '1.0.0', + version: '1.1.0', author: 'CloudHill', hacks: { 'renderer/preload.js'(store, __exports) { @@ -224,7 +224,7 @@ module.exports = { function renderSwitcherItem(mod) { if (mod.panel) { const item = createElement( - `
+ `
${mod.panel.icon}
${mod.panel.name || mod.name}
` @@ -235,7 +235,7 @@ module.exports = { } function renderSwitcher() { - if (panel.querySelector('.enhancer-panel--overlay-container')) return; + if (document.querySelector('.enhancer-panel--overlay-container')) return; // Layer to close switcher const overlayContainer = createElement( @@ -261,10 +261,12 @@ module.exports = { panelMods.forEach(mod => switcher.append(renderSwitcherItem(mod)) ); - + overlayContainer.appendChild(div); div.firstElementChild.appendChild(switcher); + switcher.firstElementChild.focus(); + // Fade in switcher.animate( [ {opacity: 0}, {opacity: 1} ], @@ -273,12 +275,16 @@ module.exports = { // Prevent panel from closing if unlocked panel.removeEventListener('mouseleave', hidePanel); + + // Escape key listener + document.addEventListener('keydown', switcherKeyEvent); } function hideSwitcher() { const overlayContainer = document.querySelector('.enhancer-panel--overlay-container'); overlayContainer.removeEventListener('click', hideSwitcher); - + document.removeEventListener('keydown', switcherKeyEvent); + // Fade out document.querySelector('.enhancer-panel--switcher').animate( [ {opacity: 1}, {opacity: 0} ], @@ -363,6 +369,35 @@ module.exports = { if (panel.dataset.locked === 'true') return true; else return false; } + + function switcherKeyEvent(e) { + e.stopPropagation(); + + if (e.key === 'Escape') return hideSwitcher(); + + const currentFocus = document.activeElement; + if ([' ', 'Enter'].includes(e.key)) return currentFocus.click(); + + const focusNext = () => { + const nextEl = currentFocus.nextElementSibling; + if (nextEl) nextEl.focus(); + else currentFocus.parentElement.firstElementChild.focus(); + } + const focusPrevious = () => { + const prevEl = currentFocus.previousElementSibling; + if (prevEl) prevEl.focus(); + else currentFocus.parentElement.lastElementChild.focus(); + } + + if (e.key === 'ArrowUp') focusPrevious(); + else if (e.key === 'ArrowDown') focusNext(); + else if (e.key === 'Tab') { + if (e.shiftKey) focusPrevious(); + else focusNext(); + + e.preventDefault(); + } + } } }); From 2d43b7973543bf0ad09a585e9a15240223d5eadb Mon Sep 17 00:00:00 2001 From: CloudHill Date: Wed, 9 Dec 2020 01:34:59 +0700 Subject: [PATCH 4/5] outliner: refactor to increase performance reduced the number of times the outliner has to refresh in response to issue #333 --- mods/outliner/mod.js | 2 +- mods/outliner/panel.js | 60 +++++++++++++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/mods/outliner/mod.js b/mods/outliner/mod.js index 185b25d..87b28af 100644 --- a/mods/outliner/mod.js +++ b/mods/outliner/mod.js @@ -14,7 +14,7 @@ module.exports = { tags: ['extension', 'panel'], name: 'outliner', desc: 'table of contents.', - version: '1.1.1', + version: '1.2.0', author: 'CloudHill', options: [ { diff --git a/mods/outliner/panel.js b/mods/outliner/panel.js index d53a14e..a6e1d66 100644 --- a/mods/outliner/panel.js +++ b/mods/outliner/panel.js @@ -9,7 +9,9 @@ const { createElement } = require("../../pkg/helpers"); -module.exports = (store, __exports) => { +module.exports = (store, __exports) => { + let lastSearch; + // Observe for page changes const pageObserver = new MutationObserver((list, observer) => { for ( let { addedNodes } of list) { @@ -30,18 +32,30 @@ module.exports = (store, __exports) => { // Observe for header changes const contentObserver = new MutationObserver((list, observer) => { list.forEach(m => { + let header; if ( ( m.type === 'childList' && ( - isHeaderElement(m.target) || - isHeaderElement(m.addedNodes[0]) || - isHeaderElement(m.removedNodes[0]) + m.target.hasAttribute('placeholder') || + m.target.className?.includes('header-block') + ) && + ( + (header = getHeaderBlock(m.target)) || + (header = getHeaderBlock(m.addedNodes[0])) ) ) || ( m.type === 'characterData' && - isHeaderElement(m.target.parentElement) + (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(); }) @@ -61,6 +75,10 @@ module.exports = (store, __exports) => { } 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 = ''; @@ -80,22 +98,38 @@ module.exports = (store, __exports) => { outline-placeholder="${placeholder}">
`); + header.outline = outlineHeader; outlineHeader.firstElementChild.innerHTML = headerEl.innerHTML; outline.append(outlineHeader); }) } + function updateOutlineHeader(header) { + const headerEl = header.querySelector('[placeholder]') || header; + if (!( + headerEl && + header.outline && + header.outline.parentElement + )) return findHeaders(); + const outlineHeader = header.outline; + outlineHeader.firstElementChild.innerHTML = headerEl.innerHTML; + updateOutlineLevel(outlineHeader, headerEl.getAttribute('placeholder').slice(-1)); + } + + function updateOutlineLevel(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) { - if ( - el.querySelector && - el.querySelector('[placeholder]') - ) { - placeholder = el.querySelector('[placeholder]').getAttribute('placeholder') - } else if (el.getAttribute) { - placeholder = el.getAttribute('placeholder'); - } + placeholder = el.getAttribute?.('placeholder') || + el.querySelector?.('[placeholder]')?.getAttribute('placeholder'); } if (!placeholder) placeholder = ''; return placeholder.includes('Heading'); From b48efb2f39f979cac8d40cf8e7fa567b7d884d50 Mon Sep 17 00:00:00 2001 From: MANNEN <35939149+MANNNNEN@users.noreply.github.com> Date: Wed, 9 Dec 2020 01:18:20 +0100 Subject: [PATCH 5/5] Add files via upload (#335) --- mods/nord/app.css | 8 ++ mods/nord/mod.js | 17 ++++ mods/nord/variables.css | 186 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 mods/nord/app.css create mode 100644 mods/nord/mod.js create mode 100644 mods/nord/variables.css diff --git a/mods/nord/app.css b/mods/nord/app.css new file mode 100644 index 0000000..4730fb4 --- /dev/null +++ b/mods/nord/app.css @@ -0,0 +1,8 @@ +/* + * nord v0.1.0 + * (c) 2020 MANNEN + * dunno what to do here + * under the MIT license, probably? + */ + +/* diff --git a/mods/nord/mod.js b/mods/nord/mod.js new file mode 100644 index 0000000..31fe791 --- /dev/null +++ b/mods/nord/mod.js @@ -0,0 +1,17 @@ +/* + * nord v0.1.0 + * (c) 2020 MANNEN + * dunno what to do here + * under the MIT license, probably? + */ + +'use strict'; + +module.exports = { + id: 'ff87ff66-4910-436f-a843-7598edde2a7f', + tags: ['theme', 'dark'], + name: 'nord', + desc: 'An arctic, north-bluish color palette.', + version: '0.1.0', + author: 'MANNEN', +}; diff --git a/mods/nord/variables.css b/mods/nord/variables.css new file mode 100644 index 0000000..08c165f --- /dev/null +++ b/mods/nord/variables.css @@ -0,0 +1,186 @@ +/* + * nord v0.1.0 + * (c) 2020 MANNEN + * dunno what to do here + * under the MIT license, probably? + */ + +@import 'https://rsms.me/inter/inter.css'; +@import url('https://fonts.googleapis.com/css2?family=Fira+Code&display=swap'); + +:root { + /** dark **/ + + --nord0: #2e3440; /*dark1*/ + --nord1: #3b4252; /*dark2*/ + --nord2: #434c5e; /*dark3*/ + --nord3: #4c566a; /*dark4*/ + --nord4: #d8dee9; /*light1*/ + --nord5: #e5e9f0; /*light2*/ + --nord6: #eceff4; /*light3*/ + --nord7: #8fbcbb; /*frost1*/ + --nord8: #88c0d0; /*frost2*/ + --nord9: #81a1c1; /*frost3*/ + --nord10: #5e81ac; /*frost4*/ + --nord11: #bf616a; /*red*/ + --nord12: #d08770; /*orange*/ + --nord13: #ebcb8b; /*yellow*/ + --nord14: #a3be8c; /*green*/ + --nord15: #b48ead; /*purple*/ + + --theme_dark--main: var(--nord0); + --theme_dark--sidebar: var(--nord1); + --theme_dark--overlay: rgb(41 37 37 / 60%); + --theme_dark--dragarea: var(--nord0); + --theme_dark--box-shadow: rgba(15, 15, 15, 0.2) 0px 0px 0px 1px, + rgba(15, 15, 15, 0.2) 0px 2px 4px; + --theme_dark--box-shadow_strong: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, + rgba(15, 15, 15, 0.2) 0px 3px 6px, rgba(15, 15, 15, 0.4) 0px 9px 24px; + + --theme_dark--font_sans: 'Inter', -apple-system, BlinkMacSystemFont, + 'Segoe UI', Helvetica, 'Apple Color Emoji', Arial, sans-serif, + 'Segoe UI Emoji', 'Segoe UI Symbol'; + --theme_dark--font_code: 'Fira Code', monospace; + + --theme_dark--scrollbar: var(--nord2); + --theme_dark--scrollbar-border: transparent; + --theme_dark--scrollbar_hover: var(--nord3); + + --theme_dark--card: var(--nord1); + --theme_dark--gallery: var(--nord2); + --theme_dark--select_input: rgb(55, 60, 63); + --theme_dark--table-border: rgba(255, 255, 255, 0.1); + --theme_dark--ui-border: rgba(255, 255, 255, 0.07); + --theme_dark--interactive_hover: var(--nord3); + --theme_dark--interactive_hover-border: transparent; + --theme_dark--button_close: var(--nord11); + --theme_dark--button_close-fill: var(--nord6); + + --theme_dark--selected: rgb(136 192 208 / 50%); + --theme_dark--primary: var(--nord8); + --theme_dark--primary_hover: var(--nord8); + --theme_dark--primary_click: var(--nord8); + --theme_dark--primary_indicator: var(--nord11); + + --theme_dark--option-color: var(--nord4); + --theme_dark--option-background: transparent; + --theme_dark--option_active-color: var(--nord4); + --theme_dark--option_active-background: var(--theme_dark--primary); + --theme_dark--option_hover-color: var(--nord4); + --theme_dark--option_hover-background: var(--nord4); + + --theme_dark--danger_text: var(--nord11); + --theme_dark--danger_border: rgba(235, 87, 87, 0.5); + + --theme_dark--text: var(--nord4); + --theme_dark--text_ui: var(--nord4); + --theme_dark--text_ui_info: var(--nord4); + + --theme_dark--text_gray: rgba(151, 154, 155, 0.95); + --theme_dark--text_brown: rgb(147, 114, 100); + --theme_dark--text_orange: var(--nord12); + --theme_dark--text_yellow: var(--nord13); + --theme_dark--text_green: var(--nord14); + --theme_dark--text_blue: var(--nord9); + --theme_dark--text_purple: var(--nord15); + --theme_dark--text_pink: rgb(193 106 153); + --theme_dark--text_red: var(--nord11); + + --theme_dark--bg-text: var(--theme_dark--text); + --theme_dark--bg_gray: rgb(69, 75, 78); + --theme_dark--bg_gray-text: var(--theme_dark--bg-text); + --theme_dark--bg_brown: rgb(67, 64, 64); + --theme_dark--bg_brown-text: var(--theme_dark--bg-text); + --theme_dark--bg_orange: var(--nord12); + --theme_dark--bg_orange-text: var(--theme_light--bg-text); + --theme_dark--bg_yellow: var(--nord13); + --theme_dark--bg_yellow-text: var(--theme_light--bg-text); + --theme_dark--bg_green: var(--nord14); + --theme_dark--bg_green-text: var(--theme_dark--bg-text); + --theme_dark--bg_blue: var(--nord9); + --theme_dark--bg_blue-text: var(--theme_dark--bg-text); + --theme_dark--bg_purple: var(--nord15); + --theme_dark--bg_purple-text: var(--theme_dark--bg-text); + --theme_dark--bg_pink: rgb(193 106 153); + --theme_dark--bg_pink-text: var(--theme_dark--bg-text); + --theme_dark--bg_red: var(--nord11); + --theme_dark--bg_red-text: var(--theme_dark--bg-text); + + --theme_dark--line-text: var(--theme_dark--text); + --theme_dark--line_gray: rgb(69, 75, 78); + --theme_dark--line_gray-text: var(--theme_dark--line-text); + --theme_dark--line_brown: rgb(67, 64, 64); + --theme_dark--line_brown-text: var(--theme_dark--line-text); + --theme_dark--line_orange: var(--nord12); + --theme_dark--line_orange-text: var(--theme_light--line-text); + --theme_dark--line_yellow: var(--nord13); + --theme_dark--line_yellow-text: var(--theme_light--line-text); + --theme_dark--line_green: var(--nord14); + --theme_dark--line_green-text: var(--theme_dark--line-text); + --theme_dark--line_blue: var(--nord9); + --theme_dark--line_blue-text: var(--theme_dark--line-text); + --theme_dark--line_purple: var(--nord15); + --theme_dark--line_purple-text: var(--theme_dark--line-text); + --theme_dark--line_pink: rgb(193 106 153); + --theme_dark--line_pink-text: var(--theme_dark--line-text); + --theme_dark--line_red: var(--nord11); + --theme_dark--line_red-text: var(--theme_dark--line-text); + + --theme_dark--select-text: var(--theme_dark--text); + --theme_dark--select_gray: rgba(151, 154, 155, 0.5); + --theme_dark--select_gray-text: var(--theme_dark--select-text); + --theme_dark--select_brown: rgba(147, 114, 100, 0.5); + --theme_dark--select_brown-text: var(--theme_dark--select-text); + --theme_dark--select_orange: rgba(255, 163, 68, 0.5); + --theme_dark--select_orange-text: var(--theme_dark--select-text); + --theme_dark--select_yellow: rgba(255, 220, 73, 0.5); + --theme_dark--select_yellow-text: var(--theme_dark--select-text); + --theme_dark--select_green: rgba(77, 171, 154, 0.5); + --theme_dark--select_green-text: var(--theme_dark--select-text); + --theme_dark--select_blue: rgba(82, 156, 202, 0.5); + --theme_dark--select_blue-text: var(--theme_dark--select-text); + --theme_dark--select_purple: rgba(154, 109, 215, 0.5); + --theme_dark--select_purple-text: var(--theme_dark--select-text); + --theme_dark--select_pink: rgba(226, 85, 161, 0.5); + --theme_dark--select_pink-text: var(--theme_dark--select-text); + --theme_dark--select_red: rgba(255, 115, 105, 0.5); + --theme_dark--select_red-text: var(--theme_dark--select-text); + + --theme_dark--callout-text: var(--theme_dark--text); + --theme_dark--callout_gray: rgba(69, 75, 78, 0.3); + --theme_dark--callout_gray-text: var(--theme_dark--callout-text); + --theme_dark--callout_brown: rgba(67, 64, 64, 0.3); + --theme_dark--callout_brown-text: var(--theme_dark--callout-text); + --theme_dark--callout_orange: rgba(89, 74, 58, 0.3); + --theme_dark--callout_orange-text: var(--theme_dark--callout-text); + --theme_dark--callout_yellow: rgba(89, 86, 59, 0.3); + --theme_dark--callout_yellow-text: var(--theme_dark--callout-text); + --theme_dark--callout_green: rgba(53, 76, 75, 0.3); + --theme_dark--callout_green-text: var(--theme_dark--callout-text); + --theme_dark--callout_blue: rgba(54, 73, 84, 0.3); + --theme_dark--callout_blue-text: var(--theme_dark--callout-text); + --theme_dark--callout_purple: rgba(68, 63, 87, 0.3); + --theme_dark--callout_purple-text: var(--theme_dark--callout-text); + --theme_dark--callout_pink: rgba(83, 59, 76, 0.3); + --theme_dark--callout_pink-text: var(--theme_dark--callout-text); + --theme_dark--callout_red: rgba(89, 65, 65, 0.3); + --theme_dark--callout_red-text: var(--theme_dark--callout-text); + + --theme_dark--code_inline-text: var(--nord11); + --theme_dark--code_inline-background: rgba(135, 131, 120, 0.15); + --theme_dark--code-text: var(--theme_dark--text); + --theme_dark--code-background: var(--theme_dark--card); + --theme_dark--code_function: var(--theme_dark--text_blue); + --theme_dark--code_keyword: var(--theme_dark--text_pink); + --theme_dark--code_tag: var(--theme_dark--text_pink); + --theme_dark--code_operator: var(--theme_dark--text_yellow); + --theme_dark--code_important: var(--theme_dark--text_yellow); + --theme_dark--code_property: var(--theme_dark--text_pink); + --theme_dark--code_builtin: var(--theme_dark--text_yellow); + --theme_dark--code_attr-name: var(--theme_dark--text_yellow); + --theme_dark--code_comment: var(--theme_dark--text_gray); + --theme_dark--code_punctuation: var(--theme_dark--text_gray); + --theme_dark--code_doctype: var(--theme_dark--text_gray); + --theme_dark--code_number: var(--theme_dark--text_purple); + --theme_dark--code_string: var(--theme_dark--text_orange); + --theme_dark--code_attr-value: var(--theme_dark--text_orange);