From 1e9adc51df94752c4f343f1da1f2eab1504e09e0 Mon Sep 17 00:00:00 2001 From: Alexa B Date: Sat, 17 Oct 2020 20:55:17 -0400 Subject: [PATCH 1/5] docs: Fixed link to dev build instructions (#167) --- DOCUMENTATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 95f0667..ed22a83 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -20,7 +20,7 @@ _for examples of the stuff described below in action._ _at the moment, for ease of development and use (and security assurance), there's no way for users_ _to install their own modules. this means that testing modules requires_ -_[running a dev build of the enhancer](DOCUMENTATION.md#testing). a better system is in the works._ +_[running a dev build of the enhancer](https://github.com/dragonwocky/notion-enhancer/blob/master/CONTRIBUTING.md#testing). a better system is in the works._ _once your mod is working, open a pull request to add it to the enhancer!_ From cf4d8e63eeb650d8209f0316266edbad59641c78 Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Sun, 18 Oct 2020 22:35:56 +1100 Subject: [PATCH 2/5] cherry cola adjustments + tab button hover fixes + closing tabs shouldn't create weird broken things anymore --- mods/cherrycola/styles.css | 21 +++--- mods/core/buttons.js | 6 +- mods/core/css/buttons.css | 6 +- mods/core/css/tabs.css | 13 +++- mods/core/render.js | 130 +++++++++++++++++++++---------------- 5 files changed, 98 insertions(+), 78 deletions(-) diff --git a/mods/cherrycola/styles.css b/mods/cherrycola/styles.css index 9975044..893e96a 100644 --- a/mods/cherrycola/styles.css +++ b/mods/cherrycola/styles.css @@ -1,14 +1,15 @@ /* * cherry cola * (c) 2020 Alexa Baldon (https://github.com/runargs) + * (c) 2020 dragonwocky (https://dragonwocky.me/) * under the MIT license */ - :root { - +:root { --cola-main: #180915; --cola-sec: #1d0919; --cola-tet: #492341; + --cola-info: #9b6890; --cola-accent: #bf799b; --cola-gray: #8a8a8a; --cola-brown: #755241; @@ -24,11 +25,11 @@ --theme_dark--main: var(--cola-main); --theme_dark--sidebar: var(--cola-sec); --theme_dark--overlay: var(--cola-sec); - --theme_dark--dragarea: var(--cola-tet); + --theme_dark--dragarea: #210a1c; --theme_dark--box-shadow: rgba(20, 0, 16, 0.2) 0px 0px 0px 1px, - rgba(20, 0, 16, 0.2) 0px 2px 4px; + rgba(20, 0, 16, 0.2) 0px 2px 4px; --theme_dark--box-shadow_strong: rgba(20, 0, 16, 0.1) 0px 0px 0px 1px, - rgba(20, 0, 16, 0.2) 0px 3px 6px, rgba(20, 0, 16, 0.4) 0px 9px 24px; + rgba(20, 0, 16, 0.2) 0px 3px 6px, rgba(20, 0, 16, 0.4) 0px 9px 24px; /* Scrollbar */ --theme_dark--scrollbar: var(--cola-sec); @@ -59,8 +60,8 @@ /* Default text colors */ --theme_dark--text: #ffffff; - --theme_dark--text_ui: var(--cola-gray); - --theme_dark--text_ui_info: var(--cola-gray); + --theme_dark--text_ui: var(--cola-info); + --theme_dark--text_ui_info: var(--cola-info); /* Text color options */ --theme_dark--text_gray: var(--cola-gray); @@ -140,12 +141,10 @@ --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); - } /* Quotations as serif */ -.notion-dark-theme - .notion-quote-block{ +.notion-dark-theme .notion-quote-block { font-family: Georgia, 'Times New Roman', Times, serif; background-color: var(--cola-sec); -} \ No newline at end of file +} diff --git a/mods/core/buttons.js b/mods/core/buttons.js index bae94cd..d132722 100644 --- a/mods/core/buttons.js +++ b/mods/core/buttons.js @@ -83,19 +83,19 @@ module.exports = (store) => { (async () => { for (let btn of buttons.insert) { - buttons.element.innerHTML += ``; } for (let btn of buttons.insert) { - buttons.element.querySelector(`.window-button#btn-${btn}`).onclick = + buttons.element.querySelector(`.window-button.btn-${btn}`).onclick = buttons.actions[btn]; } if (store().frameless && !store().tiling_mode && !is_mac) { window.addEventListener('resize', (event) => { Promise.resolve(buttons.icons.maximize()).then((icon) => { icon = icon.toString(); - const el = buttons.element.querySelector('#btn-maximize'); + const el = buttons.element.querySelector('.btn-maximize'); if (el.innerHTML != icon) el.innerHTML = icon; }); }); diff --git a/mods/core/css/buttons.css b/mods/core/css/buttons.css index ac3cacc..70b8465 100644 --- a/mods/core/css/buttons.css +++ b/mods/core/css/buttons.css @@ -37,9 +37,7 @@ background: var(--theme--interactive_hover); box-shadow: 0 0 0 0.5px var(--theme--interactive_hover-border); } -.window-button#btn-close:hover { +.window-button.btn-close:hover { background: var(--theme--button_close); -} -.window-button#btn-close:hover svg line { - stroke: var(--theme--button_close-fill); + color: var(--theme--button_close-fill); } diff --git a/mods/core/css/tabs.css b/mods/core/css/tabs.css index 2e9aed3..1e38668 100644 --- a/mods/core/css/tabs.css +++ b/mods/core/css/tabs.css @@ -95,7 +95,7 @@ body, color: var(--theme--text); -webkit-app-region: no-drag; border: none; - background-color: transparent; + background: transparent; } #titlebar .window-buttons-area { margin: 0.5em 0.55em 0.5em auto; @@ -132,6 +132,7 @@ body, } #tabs .tab:not(.new) span:not(.close) { width: 8.5em; + margin-right: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -166,9 +167,15 @@ body, opacity: 1; } #tabs .tab .close:hover, -#tabs .tab.new span:hover { +#tabs .tab.new span:hover, +#titlebar .window-button:hover { + border-radius: 4px; background: var(--theme--table-border); - border-radius: 5px; + box-shadow: 0 0 0 0.5px var(--theme--interactive_hover-border); +} +#titlebar .window-button.btn-close:hover { + background: var(--theme--button_close); + color: var(--theme--button_close-fill); } #tabs .tab.dragged-over { box-shadow: inset 4px 0 0 0 var(--theme--selected); diff --git a/mods/core/render.js b/mods/core/render.js index 12cf0b5..6016dbf 100644 --- a/mods/core/render.js +++ b/mods/core/render.js @@ -223,7 +223,7 @@ module.exports = (store, __exports) => { const list = new Map(this.state.tabs); while (this.state.tabs.get(id) && this.state.tabs.get(id).open) id++; list.delete(id); - this.openTab(id, { state: list, load: url || true }); + return this.openTab(id, { state: list, load: url || true }); } openTab( id, @@ -237,64 +237,80 @@ module.exports = (store, __exports) => { load: false, } ) { - if (!id && id !== 0) { - if (state.get(this.views.current.id).open) return; - const currentIndex = [...state].findIndex( - ([id, { title, open }]) => id === this.views.current.id - ); - id = ( - [...state].find( + return new Promise((res, rej) => { + if (!id && id !== 0) { + if (state.get(this.views.current.id).open) return res(true); + const currentIndex = [...state].findIndex( + ([id, { title, open }]) => id === this.views.current.id + ); + id = ([...state].find( ([id, { title, open }], tabIndex) => open && tabIndex > currentIndex - ) || [...state].find(([id, { title, open }]) => open) - ).title; - } - const current_src = this.views.current.$el().src; - this.views.current.id = id; - this.setState( - { - tabs: state.set(id, { - title: state.get(id) ? state.get(id).title : 'notion.so', - open: true, - }), - slideIn: load ? this.state.slideIn.add(id) : this.state.slideIn, - slideOut: slideOut, - }, - async () => { - this.focusTab(); - if (load) { - await new Promise((res, rej) => { - let attempt; - attempt = setInterval(() => { - if (!document.body.contains(this.views.html[id])) return; - clearInterval(attempt); - res(); - }, 50); - }); - this.views.html[id].style.opacity = '0'; - let unhide; - unhide = () => { - this.views.html[id].style.opacity = ''; - this.views.html[id].removeEventListener( - 'did-stop-loading', - unhide - ); - }; - this.views.html[id].addEventListener('did-stop-loading', unhide); - this.views.html[id].loadURL( - typeof load === 'string' - ? load - : store().default_page - ? idToNotionURL(store().default_page) - : current_src - ); - // this.views.html[id].getWebContents().openDevTools(); - } - setTimeout(() => { - this.setState({ slideIn: new Set(), slideOut: new Set() }); - }, 150); + ) || [...state].find(([id, { title, open }]) => open))[0]; } - ); + const current_src = this.views.current.$el().src; + this.views.current.id = id; + this.setState( + { + tabs: state.set(id, { + title: state.get(id) ? state.get(id).title : 'notion.so', + open: true, + }), + slideIn: load ? this.state.slideIn.add(id) : this.state.slideIn, + slideOut: slideOut, + }, + async () => { + this.focusTab(); + new Promise((resolve, reject) => { + let attempt, + clear = () => { + clearInterval(attempt); + return true; + }; + attempt = setInterval(() => { + if (this.views.current.id !== id) return clear() && reject(); + if (document.body.contains(this.views.html[id])) + return clear() && resolve(); + }, 50); + }) + .then(() => { + if (load) { + this.views.html[id].style.opacity = '0'; + let unhide; + unhide = () => { + this.views.html[id].style.opacity = ''; + this.views.html[id].removeEventListener( + 'did-stop-loading', + unhide + ); + }; + this.views.html[id].addEventListener( + 'did-stop-loading', + unhide + ); + this.views.html[id].loadURL( + typeof load === 'string' + ? load + : store().default_page + ? idToNotionURL(store().default_page) + : current_src + ); + } + }) + .catch(() => { + // nothing + }) + .finally(() => { + setTimeout(() => { + this.setState( + { slideIn: new Set(), slideOut: new Set() }, + () => res(true) + ); + }, 150); + }); + } + ); + }); } closeTab(id) { if ((!id && id !== 0) || !this.state.tabs.get(id)) return; @@ -302,7 +318,7 @@ module.exports = (store, __exports) => { list.set(id, { ...list.get(id), open: false }); if (![...list].filter(([id, { title, open }]) => open).length) return electron.remote.getCurrentWindow().close(); - this.openTab( + return this.openTab( this.views.current.id === id ? null : this.views.current.id, { state: list, slideOut: this.state.slideOut.add(id) } ); From 1d1503c826a0ac0c802f34c8ae7881763cc1c5b2 Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Mon, 19 Oct 2020 09:33:08 +1100 Subject: [PATCH 3/5] cross-window draggable tabs --- mods/core/render.js | 69 +++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/mods/core/render.js b/mods/core/render.js index 6016dbf..f7a54fc 100644 --- a/mods/core/render.js +++ b/mods/core/render.js @@ -87,11 +87,22 @@ module.exports = (store, __exports) => { document.addEventListener('dragstart', (event) => { if (!this.$titlebar) return; this.$dragging = getTab(event.target)[0]; + event.dataTransfer.setData( + 'text', + document.getElementById(getTab(event.target)[0]).src + ); event.target.style.opacity = 0.5; }); document.addEventListener('dragend', (event) => { if (!this.$titlebar) return; event.target.style.opacity = ''; + document + .querySelectorAll('.dragged-over') + .forEach((el) => el.classList.remove('dragged-over')); + if (this.$dragging !== null) { + this.closeTab(this.$dragging); + this.$dragging = null; + } }); document.addEventListener('dragover', (event) => { if (!this.$titlebar) return; @@ -103,36 +114,40 @@ module.exports = (store, __exports) => { if (tab[1]) tab[1].classList.add('dragged-over'); }); document.addEventListener('drop', (event) => { - if (!this.$titlebar || this.$dragging === null) return; event.preventDefault(); - document - .querySelectorAll('.dragged-over') - .forEach((el) => el.classList.remove('dragged-over')); - const from = getTab(this.views.tabs[+this.$dragging]), - to = getTab(event.target); - if (from[0] !== to[0]) { - if (to[1].classList.contains('new')) { - const list = new Map(this.state.tabs); - list.delete(from[0]); - list.set(from[0], this.state.tabs.get(from[0])); - this.setState({ tabs: list }); - } else { - const list = [...this.state.tabs], - fromIndex = list.findIndex( - ([id, { title, open }]) => id === from[0] - ), - toIndex = list.findIndex( - ([id, { title, open }]) => id === to[0] - ); - list.splice( - toIndex > fromIndex ? toIndex - 1 : toIndex, - 0, - list.splice(fromIndex, 1)[0] - ); - this.setState({ tabs: new Map(list) }); + if (this.$dragging === null) { + console.log(event.dataTransfer.getData('text')); + if (event.dataTransfer.getData('text').startsWith('notion://')) + this.newTab(event.dataTransfer.getData('text')); + } else { + if (this.$titlebar) { + const from = getTab(this.views.tabs[+this.$dragging]), + to = getTab(event.target); + if (from[0] !== to[0]) { + if (to[1].classList.contains('new')) { + const list = new Map(this.state.tabs); + list.delete(from[0]); + list.set(from[0], this.state.tabs.get(from[0])); + this.setState({ tabs: list }); + } else { + const list = [...this.state.tabs], + fromIndex = list.findIndex( + ([id, { title, open }]) => id === from[0] + ), + toIndex = list.findIndex( + ([id, { title, open }]) => id === to[0] + ); + list.splice( + toIndex > fromIndex ? toIndex - 1 : toIndex, + 0, + list.splice(fromIndex, 1)[0] + ); + this.setState({ tabs: new Map(list) }); + } + } } + this.$dragging = null; } - this.$dragging = null; }); document.addEventListener('keyup', (event) => { if (!electron.remote.getCurrentWindow().isFocused()) return; From b2491a0a090b4493db07ed10f31fd6cac478a379 Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Mon, 19 Oct 2020 22:03:54 +1100 Subject: [PATCH 4/5] use event communication instead of variable checking for cross-window dragging = less-buggy --- mods/core/render.js | 119 +++++++++++++++++++++++++++----------------- mods/core/tray.js | 5 ++ 2 files changed, 79 insertions(+), 45 deletions(-) diff --git a/mods/core/render.js b/mods/core/render.js index f7a54fc..c2e731e 100644 --- a/mods/core/render.js +++ b/mods/core/render.js @@ -86,10 +86,16 @@ module.exports = (store, __exports) => { }; document.addEventListener('dragstart', (event) => { if (!this.$titlebar) return; - this.$dragging = getTab(event.target)[0]; + const tab = getTab(event.target); + this.$dragging = tab[0]; event.dataTransfer.setData( 'text', - document.getElementById(getTab(event.target)[0]).src + JSON.stringify({ + target: electron.remote.getCurrentWindow().webContents.id, + tab: tab[0], + title: tab[1].children[0].innerText, + url: document.getElementById(getTab(event.target)[0]).src, + }) ); event.target.style.opacity = 0.5; }); @@ -99,10 +105,6 @@ module.exports = (store, __exports) => { document .querySelectorAll('.dragged-over') .forEach((el) => el.classList.remove('dragged-over')); - if (this.$dragging !== null) { - this.closeTab(this.$dragging); - this.$dragging = null; - } }); document.addEventListener('dragover', (event) => { if (!this.$titlebar) return; @@ -110,40 +112,50 @@ module.exports = (store, __exports) => { document .querySelectorAll('.dragged-over') .forEach((el) => el.classList.remove('dragged-over')); - const tab = getTab(event.target); - if (tab[1]) tab[1].classList.add('dragged-over'); + const tab = getTab(event.target)[1]; + if (tab) tab.classList.add('dragged-over'); }); - document.addEventListener('drop', (event) => { + document.addEventListener('drop', async (event) => { event.preventDefault(); - if (this.$dragging === null) { - console.log(event.dataTransfer.getData('text')); - if (event.dataTransfer.getData('text').startsWith('notion://')) - this.newTab(event.dataTransfer.getData('text')); - } else { - if (this.$titlebar) { - const from = getTab(this.views.tabs[+this.$dragging]), - to = getTab(event.target); - if (from[0] !== to[0]) { - if (to[1].classList.contains('new')) { - const list = new Map(this.state.tabs); - list.delete(from[0]); - list.set(from[0], this.state.tabs.get(from[0])); - this.setState({ tabs: list }); - } else { - const list = [...this.state.tabs], - fromIndex = list.findIndex( - ([id, { title, open }]) => id === from[0] - ), - toIndex = list.findIndex( - ([id, { title, open }]) => id === to[0] - ); - list.splice( - toIndex > fromIndex ? toIndex - 1 : toIndex, - 0, - list.splice(fromIndex, 1)[0] + const eventData = JSON.parse(event.dataTransfer.getData('text')); + if ( + eventData.target !== + electron.remote.getCurrentWindow().webContents.id + ) { + electron.ipcRenderer.send( + 'enhancer:close-tab', + eventData.target, + eventData.tab + ); + this.$dragging = await this.newTab( + eventData.url, + eventData.title, + false + ); + } + if (this.$titlebar) { + const from = getTab(this.views.tabs[+this.$dragging]), + to = getTab(event.target); + if (from[0] !== to[0]) { + if (to[1].classList.contains('new')) { + const list = new Map(this.state.tabs); + list.delete(from[0]); + list.set(from[0], this.state.tabs.get(from[0])); + this.setState({ tabs: list }); + } else { + const list = [...this.state.tabs], + fromIndex = list.findIndex( + ([id, { title, open }]) => id === from[0] + ), + toIndex = list.findIndex( + ([id, { title, open }]) => id === to[0] ); - this.setState({ tabs: new Map(list) }); - } + list.splice( + toIndex > fromIndex ? toIndex - 1 : toIndex, + 0, + list.splice(fromIndex, 1)[0] + ); + this.setState({ tabs: new Map(list) }); } } this.$dragging = null; @@ -192,6 +204,9 @@ module.exports = (store, __exports) => { if (triggered && document.querySelector('.tab.current .close')) document.querySelector('.tab.current .close').click(); }); + electron.ipcRenderer.on('enhancer:close-tab', (event, tab) => { + this.closeTab(tab); + }); } componentDidMount() { @@ -233,12 +248,17 @@ module.exports = (store, __exports) => { }); } - newTab(url = '') { + newTab(url = '', title = 'notion.so', animate = true) { let id = 0; const list = new Map(this.state.tabs); while (this.state.tabs.get(id) && this.state.tabs.get(id).open) id++; list.delete(id); - return this.openTab(id, { state: list, load: url || true }); + return this.openTab(id, { + state: list, + load: url || true, + title, + animate, + }); } openTab( id, @@ -246,15 +266,19 @@ module.exports = (store, __exports) => { state = new Map(this.state.tabs), slideOut = new Set(this.state.slideOut), load, + animate, + title = 'notion.so', } = { state: new Map(this.state.tabs), slideOut: new Set(this.state.slideOut), load: false, + title: 'notion.so', + animate: false, } ) { return new Promise((res, rej) => { if (!id && id !== 0) { - if (state.get(this.views.current.id).open) return res(true); + if (state.get(this.views.current.id).open) return res(id); const currentIndex = [...state].findIndex( ([id, { title, open }]) => id === this.views.current.id ); @@ -268,10 +292,12 @@ module.exports = (store, __exports) => { this.setState( { tabs: state.set(id, { - title: state.get(id) ? state.get(id).title : 'notion.so', + title: state.get(id) ? state.get(id).title : title, open: true, }), - slideIn: load ? this.state.slideIn.add(id) : this.state.slideIn, + slideIn: animate + ? this.state.slideIn.add(id) + : this.state.slideIn, slideOut: slideOut, }, async () => { @@ -319,7 +345,7 @@ module.exports = (store, __exports) => { setTimeout(() => { this.setState( { slideIn: new Set(), slideOut: new Set() }, - () => res(true) + () => res(id) ); }, 150); }); @@ -421,8 +447,11 @@ module.exports = (store, __exports) => { this.newTab(event.args[0]); break; case 'enhancer:close-tab': - if (document.querySelector('.tab.current .close')) - document.querySelector('.tab.current .close').click(); + this.closeTab( + event.args[0] || event.args[0] === 0 + ? event.args[0] + : this.views.current.id + ); break; } } diff --git a/mods/core/tray.js b/mods/core/tray.js index db9942e..59e292a 100644 --- a/mods/core/tray.js +++ b/mods/core/tray.js @@ -46,6 +46,11 @@ module.exports = (store, __exports) => { webContents.send('enhancer:get-menu-theme', arg) ); }); + electron.ipcMain.on('enhancer:close-tab', (event, target, tab) => { + electron.webContents + .fromId(target) + .webContents.send('enhancer:close-tab', tab); + }); function calculateWindowPos(width, height) { const screen = electron.screen.getDisplayNearestPoint({ From 84ef0d9440edea460c2a175a3d6779fed1f1f568 Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Mon, 19 Oct 2020 22:49:22 +1100 Subject: [PATCH 5/5] fix theming primary-colour text + right-to-left text in columns --- CHANGELOG.md | 2 ++ README.md | 5 +++-- mods/core/css/theme.css | 3 ++- mods/right-to-left/mod.js | 6 ++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9433cb3..72b963d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,8 @@ a flexibility update. `box-shadow`, `box-shadow_strong`, `select_input`, and `ui-border` - bugfix: font sizing applied to overlays/previews. - bugfix: removed typo in variable name for brown text. +- bugfix: primary-colour text (mainly in "add a \_" popups) is now properly themed. +- bugfix: right-to-left extension applies to text in columns. - tweak: sticky table/list rows. - theme: "material ocean" = an oceanic colour palette. - theme: "dracula" = a theme based on the popular dracula color palette diff --git a/README.md b/README.md index 91c4019..1f1f702 100644 --- a/README.md +++ b/README.md @@ -375,8 +375,9 @@ the font you would like to use, or leave it blank to not change anything. a couple months after I ([@dragonwocky](https://github.com/dragonwocky/)) picked the project up, at first extending upon the original base and later moving to the javascript module system. -since then, various community members have helped out heaps - some listed as +the enhancer wouldn't be anything near to what it is now though without +interested community members testing, coding and ideating features - some are listed as [contributors](https://github.com/dragonwocky/notion-enhancer/graphs/contributors) here on github, -but many helping with code, feedback and testing on discord and in emails. +but many more have been helping out on discord and in emails. individual modules have their original authors attributed. diff --git a/mods/core/css/theme.css b/mods/core/css/theme.css index 3ea2b56..dc1bb30 100644 --- a/mods/core/css/theme.css +++ b/mods/core/css/theme.css @@ -403,7 +403,8 @@ background: var(--theme--selected) !important; } -[style*=' color: rgb(46, 170, 220)'] { +[style*=' color: rgb(46, 170, 220)'], +[style^='color: rgb(46, 170, 220)'] { color: var(--theme--primary) !important; } [style*='fill: rgb(46, 170, 220)'] { diff --git a/mods/right-to-left/mod.js b/mods/right-to-left/mod.js index 270669a..3f1fb80 100644 --- a/mods/right-to-left/mod.js +++ b/mods/right-to-left/mod.js @@ -12,7 +12,7 @@ module.exports = { tags: ['extension'], name: 'right-to-left', desc: 'enables auto rtl/ltr text direction detection.', - version: '1.4.0', + version: '1.4.1', author: 'obahareth', hacks: { 'renderer/preload.js'(store, __exports) { @@ -48,7 +48,9 @@ module.exports = { function autoAlignPageContent() { document .querySelectorAll( - '.notion-page-content > div[data-block-id]:not([dir]), [placeholder="Untitled"]:not([dir])' + `.notion-page-content > div[data-block-id]:not([dir]):not(.notion-column_list-block), + [placeholder="Untitled"]:not([dir]), + .notion-column-block > div[data-block-id]:not([dir])` ) .forEach((block) => block.setAttribute('dir', 'auto')); document