mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-06 05:29:02 +00:00
242 lines
7.7 KiB
JavaScript
242 lines
7.7 KiB
JavaScript
/*
|
|
* global linking blocks
|
|
* (c) 2020 admiraldus (https://github.com/admiraldus)
|
|
* under the MIT license
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const {x$} = require('./helper.js');
|
|
|
|
module.exports = {
|
|
id: '74856af4-6970-455d-bd86-0a385a402dd1',
|
|
name: 'global linking blocks',
|
|
tags: ['extension'],
|
|
desc: 'easily copy the global link of the page or the desired block.',
|
|
version: '0.1.0',
|
|
author: {
|
|
name: 'admiraldus',
|
|
link: 'https://github.com/admiraldus',
|
|
avatar: 'https://raw.githubusercontent.com/admiraldus/admiraldus/main/module.gif',
|
|
},
|
|
options: [
|
|
{
|
|
key: 'hidePageButton',
|
|
label: 'show the page link button',
|
|
type: 'toggle',
|
|
value: true,
|
|
},
|
|
],
|
|
hacks: {
|
|
'renderer/preload.js'(store, __exports) {
|
|
document.addEventListener('readystatechange', () => {
|
|
if (document.readyState !== 'complete') return false;
|
|
|
|
/**
|
|
* Prevent selectors from failing.
|
|
*
|
|
* @return {Function} Returns "wait()" until "main()" returns.
|
|
*/
|
|
const wait = !function wait() {
|
|
const els = [x$.sel('.notion-frame'), x$.sel('.notion-topbar')];
|
|
if (els.some((el) => el !== null)) return main();
|
|
setTimeout(() => wait(), 500);
|
|
}();
|
|
|
|
/**
|
|
* Everything happens here. ¯\_(ツ)_/¯
|
|
*/
|
|
async function main() {
|
|
const icons = {
|
|
globe: await x$.svg('/icons/globe.svg'),
|
|
chain: await x$.svg('/icons/chain.svg'),
|
|
};
|
|
const pageClass = 'admiraldus-glb-page-button';
|
|
const blockClass = 'admiraldus-glb-block-button';
|
|
const spanClass = 'admiraldus-glb-span-hide';
|
|
|
|
if (store().hidePageButton) {
|
|
/**
|
|
* Create the page link button and append it to the topbar.
|
|
*
|
|
* @return {create} Returns "create()" if not appended.
|
|
*/
|
|
const pageButton = function create() {
|
|
const target = x$.sel('.notion-topbar-share-menu');
|
|
if (target === null) return;
|
|
|
|
const attr = [
|
|
`class="${pageClass}" role="button" tabindex="0"`,
|
|
`class="${spanClass}"`,
|
|
];
|
|
const html = x$.el(
|
|
`<div ${attr[0]}>
|
|
${icons.chain}
|
|
<span>Copy link</span>
|
|
<span ${attr[1]}>Link copied!</span
|
|
</div>`);
|
|
|
|
target.before(html);
|
|
if (html === null) return create();
|
|
};
|
|
pageButton();
|
|
|
|
/**
|
|
* Observer for the topbar.
|
|
*/
|
|
x$.obs(() => {
|
|
if (x$.sel(`.${pageClass}`) !== null) return;
|
|
pageButton();
|
|
}, x$.sel('.notion-topbar'), {
|
|
subtree: true, childList: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Create the block link button and append it to the block menu.
|
|
*
|
|
* @param {HTMLDivElement} el The copy link button.
|
|
*
|
|
* @return {create} Returns "create()" if not appended.
|
|
*/
|
|
const blockButton = function create(el) {
|
|
const target = el;
|
|
const attr = `class="${blockClass}" role="button" tabindex="0"`;
|
|
const html = x$.el(
|
|
`<div ${attr}>
|
|
${icons.globe}
|
|
<span>Global link</span>
|
|
</div>`);
|
|
|
|
target.before(html);
|
|
if (html === null) return create();
|
|
};
|
|
|
|
let buttonDelay;
|
|
let link;
|
|
/**
|
|
* Copy the link to the clipboard.
|
|
*
|
|
* @param {boolean} page If the link is the link of the page.
|
|
*/
|
|
function copyLink(page) {
|
|
/**
|
|
* Change the button text to provide the copied feedback.
|
|
*/
|
|
const changeButtonText = function create() {
|
|
const span = x$.sel('span', true, x$.sel(`.${pageClass}`));
|
|
/**
|
|
* Set the classes of the button's div elements.
|
|
*
|
|
* @param {number} first A specific array items.
|
|
* @param {number} second A specific array items.
|
|
*/
|
|
function setClasses(first, second) {
|
|
x$.cls.a(span[first], spanClass);
|
|
x$.cls.r(span[second], spanClass);
|
|
}
|
|
|
|
clearTimeout(buttonDelay);
|
|
setClasses(0, 1);
|
|
buttonDelay = setTimeout(() => {
|
|
setClasses(1, 0);
|
|
}, 700);
|
|
};
|
|
|
|
switch (page) {
|
|
case true:
|
|
link = `https://${window.location.href}/`.replace(/notion:\/\//, '');
|
|
changeButtonText();
|
|
x$.clp(false, link);
|
|
break;
|
|
case false:
|
|
const events = ['mousedown', 'mouseup', 'click'];
|
|
x$.sim(events, x$.sel(`.${blockClass}`).nextSibling);
|
|
x$.clp().then((text) => {
|
|
x$.clp(false, `${text.replace(/(?<=so[\/]).*#/, '')}/`);
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Observer for the overlay container.
|
|
*/
|
|
x$.obs(() => {
|
|
/**
|
|
* Get the copy link button.
|
|
*
|
|
* @return {HTMLDivElement} Returns the copy link button.
|
|
*/
|
|
function getLinkButton() {
|
|
const lang = ['Copy link', '링크 복사'];
|
|
const overlay = x$.sel('.notion-overlay-container');
|
|
const record = x$.sel(
|
|
'[style*="text-overflow: ellipsis;"]', true, overlay);
|
|
|
|
return Array.from(record).find(
|
|
(div) => lang.some((text) => div.textContent === text));
|
|
}
|
|
if (x$.sel(`.${blockClass}`) !== null ||
|
|
x$.sel('.notion-selectable-halo') === null ||
|
|
getLinkButton() === undefined) return;
|
|
blockButton(getLinkButton().closest('[role="button"]'));
|
|
}, x$.sel('.notion-overlay-container'), {
|
|
subtree: true, childList: true,
|
|
});
|
|
|
|
/**
|
|
* Listen for click events to call "copyLink()"".
|
|
*
|
|
* @type {HTMLElement}
|
|
* @listens document.body#click
|
|
*/
|
|
x$.on(document.body, 'click', (event) => {
|
|
const target = event.target;
|
|
|
|
if (x$.cls.c(target, pageClass) ||
|
|
target.closest(`.${pageClass}`)) {
|
|
copyLink(/* page= */ true);
|
|
} else if (x$.cls.c(target, blockClass) ||
|
|
target.closest(`.${blockClass}`)) {
|
|
copyLink(/* page= */ false);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Listen for mouseenter events to add class.
|
|
*
|
|
* @type {HTMLElement}
|
|
* @listens document.body#mouseenter
|
|
*/
|
|
x$.on(document.body, 'mouseenter', (event) => {
|
|
const target = event.target;
|
|
|
|
if (x$.cls.c(target, 'admiraldus-glb-block-button')) {
|
|
const menu = target.closest('.notion-scroller.vertical');
|
|
|
|
x$.cls.a(menu, '--on-hover');
|
|
}
|
|
}, true);
|
|
|
|
/**
|
|
* Listen for mouseleave events to remove class.
|
|
*
|
|
* @type {HTMLElement}
|
|
* @listens document.body#mouseleave
|
|
*/
|
|
x$.on(document.body, 'mouseleave', (event) => {
|
|
const target = event.target;
|
|
|
|
if (x$.cls.c(target, 'admiraldus-glb-block-button')) {
|
|
const menu = target.closest('.notion-scroller.vertical');
|
|
|
|
x$.cls.r(menu, '--on-hover');
|
|
}
|
|
}, true);
|
|
}
|
|
});
|
|
},
|
|
},
|
|
};
|