mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-06 21:49:03 +00:00
extension: global block links
This commit is contained in:
parent
b1ced4fac8
commit
dbb94bc29b
70
repo/global-block-links/client.css
Normal file
70
repo/global-block-links/client.css
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* notion-enhancer: global block links
|
||||
* (c) 2021 admiraldus (https://github.com/admiraldus)
|
||||
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||
* (https://notion-enhancer.github.io/) under the MIT license
|
||||
*/
|
||||
|
||||
.global_block_links--topbar_copy {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border-radius: 3px;
|
||||
height: 28px;
|
||||
min-width: 0px;
|
||||
padding-right: 8px;
|
||||
padding-left: 6px;
|
||||
font-size: 14px;
|
||||
line-height: 1.2;
|
||||
color: var(--theme--text);
|
||||
cursor: pointer;
|
||||
transition: background 20ms ease-in 0s;
|
||||
user-select: none;
|
||||
}
|
||||
.global_block_links--topbar_copy > svg {
|
||||
display: block;
|
||||
margin-right: 6px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
fill: var(--theme--icon_secondary);
|
||||
}
|
||||
.global_block_links--topbar_copy > span {
|
||||
opacity: 1;
|
||||
transition: opacity 0.4s ease;
|
||||
}
|
||||
|
||||
.global_block_links--block_copy {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 28px;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
line-height: 1.2;
|
||||
cursor: pointer;
|
||||
transition: background 20ms ease-in 0s;
|
||||
user-select: none;
|
||||
}
|
||||
.global_block_links--block_copy > svg {
|
||||
display: block;
|
||||
margin-left: 14px;
|
||||
height: 17px;
|
||||
width: 17px;
|
||||
color: var(--theme--icon);
|
||||
}
|
||||
.global_block_links--block_copy > span {
|
||||
margin-right: 14px;
|
||||
margin-left: 8px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.global_block_links--topbar_copy:hover,
|
||||
.global_block_links--block_copy:hover {
|
||||
background: var(--theme--ui_interactive-hover);
|
||||
}
|
||||
|
||||
.global_block_links--hidden {
|
||||
position: absolute;
|
||||
top: -9999px;
|
||||
opacity: 0 !important;
|
||||
}
|
96
repo/global-block-links/client.mjs
Normal file
96
repo/global-block-links/client.mjs
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* notion-enhancer: global block links
|
||||
* (c) 2021 admiraldus (https://github.com/admiraldus)
|
||||
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||
* (https://notion-enhancer.github.io/) under the MIT license
|
||||
*/
|
||||
|
||||
export default async function ({ web, components, notion }, db) {
|
||||
const topbarShareSelector = '.notion-topbar-share-menu',
|
||||
blockActionSelector =
|
||||
'.notion-overlay-container .notion-scroller.vertical .notion-focusable > div > div > [style*="text-overflow: ellipsis;"]',
|
||||
hoveredActionSelector =
|
||||
'.notion-overlay-container .notion-scroller.vertical .notion-focusable[style*="background:"]',
|
||||
topbarCopyClass = 'global_block_links--topbar_copy',
|
||||
blockCopyClass = 'global_block_links--block_copy',
|
||||
hiddenClass = 'global_block_links--hidden';
|
||||
|
||||
if (await db.get(['topbar_copy'])) {
|
||||
const $topbarCopyTemplate = web.html`
|
||||
<div class="${topbarCopyClass}" role="button" tabindex="0">
|
||||
<svg viewBox="0 0 30 30">
|
||||
<path d="M2,12c0-3.309,2.691-6,6-6h8c3.309,0,6,2.691,6,6s-2.691,6-6,6h-6c0,0.736,
|
||||
0.223,1.41,0.574,2H16c4.418,0,8-3.582,8-8 c0-4.418-3.582-8-8-8H8c-4.418,0-8,3.582-8,
|
||||
8c0,2.98,1.634,5.575,4.051,6.951C4.021,18.638,4,18.321,4,18 c0-0.488,0.046-0.967,
|
||||
0.115-1.436C2.823,15.462,2,13.827,2,12z M25.953,11.051C25.984,11.363,26,11.68,26,12
|
||||
c0,0.489-0.047,0.965-0.117,1.434C27.176,14.536,28,16.172,28,18c0,3.309-2.691,6-6,6h-8c-3.309,
|
||||
0-6-2.691-6-6s2.691-6,6-6h6 c0-0.731-0.199-1.413-0.545-2H14c-4.418,0-8,3.582-8,8c0,4.418,3.582,8,8,
|
||||
8h8c4.418,0,8-3.582,8-8 C30,15.021,28.368,12.428,25.953,11.051z"></path>
|
||||
</svg>
|
||||
<span>Copy link</span>
|
||||
<span class="${hiddenClass}">Link copied!</span>
|
||||
</div>`;
|
||||
|
||||
const insertTopbarCopy = () => {
|
||||
const $btns = document.querySelectorAll(topbarShareSelector);
|
||||
$btns.forEach(($btn) => {
|
||||
if (!$btn.previousElementSibling?.classList?.contains?.(topbarCopyClass)) {
|
||||
const $copy = $topbarCopyTemplate.cloneNode(true);
|
||||
$btn.before($copy);
|
||||
|
||||
let resetButtonDelay;
|
||||
$copy.addEventListener('click', () => {
|
||||
$copy.children[1].classList.add(hiddenClass);
|
||||
$copy.lastElementChild.classList.remove(hiddenClass);
|
||||
clearTimeout(resetButtonDelay);
|
||||
resetButtonDelay = setTimeout(() => {
|
||||
$copy.children[1].classList.remove(hiddenClass);
|
||||
$copy.lastElementChild.classList.add(hiddenClass);
|
||||
}, 1250);
|
||||
|
||||
web.copyToClipboard(`https://notion.so/${notion.getPageID().replace(/-/g, '')}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
insertTopbarCopy();
|
||||
web.addDocumentObserver(insertTopbarCopy, [topbarShareSelector]);
|
||||
}
|
||||
|
||||
const $blockCopyTemplate = web.html`
|
||||
<div class="${blockCopyClass}" role="button" tabindex="0">
|
||||
${await components.feather('globe')}
|
||||
<span>Global link</span>
|
||||
</div>`;
|
||||
|
||||
const getLinkButtons = () =>
|
||||
[...document.querySelectorAll(blockActionSelector)]
|
||||
.filter(($action) =>
|
||||
['Copy link', '링크 복사', 'リンクをコピー'].includes($action.textContent)
|
||||
)
|
||||
.map(($action) => $action.closest('.notion-focusable')),
|
||||
insertBlockCopy = () => {
|
||||
const $btns = getLinkButtons();
|
||||
$btns.forEach(($btn) => {
|
||||
if (!$btn.previousElementSibling?.classList?.contains?.(blockCopyClass)) {
|
||||
const $copy = $blockCopyTemplate.cloneNode(true);
|
||||
$btn.before($copy);
|
||||
|
||||
$copy.addEventListener('mouseover', () => {
|
||||
document.querySelectorAll(hoveredActionSelector).forEach(($action) => {
|
||||
$action.style.background = '';
|
||||
});
|
||||
});
|
||||
|
||||
$copy.addEventListener('click', async () => {
|
||||
$btn.click();
|
||||
const link = await web.readFromClipboard(),
|
||||
id = link.replace(/.+#(?=\w+)/, '');
|
||||
web.copyToClipboard(id.length === 32 ? `https://notion.so/${id}` : link);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
insertBlockCopy();
|
||||
web.addDocumentObserver(insertBlockCopy, [blockActionSelector]);
|
||||
}
|
28
repo/global-block-links/mod.json
Normal file
28
repo/global-block-links/mod.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "global block links",
|
||||
"id": "74856af4-6970-455d-bd86-0a385a402dd1",
|
||||
"version": "0.1.0",
|
||||
"description": "easily copy the global link of a page or block.",
|
||||
"tags": ["extension", "shortcut"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "admiraldus",
|
||||
"homepage": "https://github.com/admiraldus",
|
||||
"avatar": "https://raw.githubusercontent.com/admiraldus/admiraldus/main/module.gif"
|
||||
}
|
||||
],
|
||||
"js": {
|
||||
"client": ["client.mjs"]
|
||||
},
|
||||
"css": {
|
||||
"client": ["client.css"]
|
||||
},
|
||||
"options": [
|
||||
{
|
||||
"key": "topbar_copy",
|
||||
"label": "copy page links from the topbar",
|
||||
"type": "toggle",
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
}
|
@ -31,5 +31,6 @@
|
||||
"weekly-view",
|
||||
"collapse-properties",
|
||||
"truncated-titles",
|
||||
"focus-mode"
|
||||
"focus-mode",
|
||||
"global-block-links"
|
||||
]
|
||||
|
@ -219,7 +219,7 @@ body,
|
||||
}
|
||||
|
||||
.notion-body.dark [style*='background: rgb(71, 76, 80);'],
|
||||
.notion-body:not(.dark) [style*='background: rgba(55, 53, 47, 0.08)'],
|
||||
.notion-body:not(.dark) [style*='background: rgba(255, 255, 255, 0.1)'],
|
||||
.notion-focusable[style*='z-index:'][style*='box-shadow: '][style*='font-size: 12px;'][style*='min-height: 24px; overflow: hidden; pointer-events:']:hover,
|
||||
:not(.notion-login)
|
||||
> .notion-focusable[role='button'][tabindex='0'][style*='box-shadow:'][style*='background:'][style*='transition: background 20ms ease-in 0s; cursor: pointer;']:not([style*='rgb(46, 170, 220);']):not([style*='rgb(6, 156, 205);']):not([style*='rgb(0, 141, 190);']):not([style*='flex: 1 1 0%; white-space: nowrap; height: 26px; border-radius: 3px 0px 0px 3px;']):not([style*='rgb(225, 98, 89)']):hover,
|
||||
|
@ -205,7 +205,7 @@
|
||||
|
||||
--theme--ui_shadow: rgba(15, 15, 15, 0.15);
|
||||
--theme--ui_divider: rgb(255, 255, 255, 0.07);
|
||||
--theme--ui_interactive-hover: rgb(71, 76, 80);
|
||||
--theme--ui_interactive-hover: rgba(255, 255, 255, 0.1);
|
||||
--theme--ui_interactive-active: rgb(63, 68, 71);
|
||||
--theme--ui_toggle-on: var(--theme--accent_blue);
|
||||
--theme--ui_toggle-off: rgba(202, 204, 206, 0.3);
|
||||
|
@ -23,9 +23,7 @@ export default async function ({ web, components }, db) {
|
||||
if ($btn.innerHTML !== innerHTML) $btn.innerHTML = innerHTML;
|
||||
});
|
||||
};
|
||||
web.addDocumentObserver(() => {
|
||||
updateButton();
|
||||
}, [selector]);
|
||||
web.addDocumentObserver(updateButton, [selector]);
|
||||
updateButton();
|
||||
};
|
||||
|
||||
|
@ -4,35 +4,20 @@
|
||||
* (https://notion-enhancer.github.io/) under the MIT license
|
||||
*/
|
||||
|
||||
const copyToClipboard = async (str) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(str);
|
||||
} catch {
|
||||
const el = document.createElement('textarea');
|
||||
el.value = str;
|
||||
el.setAttribute('readonly', '');
|
||||
el.style.position = 'absolute';
|
||||
el.style.left = '-9999px';
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
}
|
||||
},
|
||||
humanTime = (mins) => {
|
||||
let readable = '';
|
||||
if (1 <= mins) {
|
||||
readable += `${Math.floor(mins)} min`;
|
||||
if (2 <= mins) readable += 's';
|
||||
}
|
||||
const secs = Math.round((mins % 1) * 60);
|
||||
if (1 <= secs) {
|
||||
if (1 <= mins) readable += ' ';
|
||||
readable += `${secs} sec`;
|
||||
if (2 <= secs) readable += 's';
|
||||
}
|
||||
return readable;
|
||||
};
|
||||
const humanTime = (mins) => {
|
||||
let readable = '';
|
||||
if (1 <= mins) {
|
||||
readable += `${Math.floor(mins)} min`;
|
||||
if (2 <= mins) readable += 's';
|
||||
}
|
||||
const secs = Math.round((mins % 1) * 60);
|
||||
if (1 <= secs) {
|
||||
if (1 <= mins) readable += ' ';
|
||||
readable += `${secs} sec`;
|
||||
if (2 <= secs) readable += 's';
|
||||
}
|
||||
return readable;
|
||||
};
|
||||
|
||||
export default async function ({ web, components }, db) {
|
||||
const dbNoticeText = 'Open a page to see its word count.',
|
||||
@ -67,7 +52,7 @@ export default async function ({ web, components }, db) {
|
||||
)
|
||||
);
|
||||
$statList.querySelectorAll('.word-counter--stat').forEach(($stat) => {
|
||||
$stat.addEventListener('click', () => copyToClipboard($stat.innerText));
|
||||
$stat.addEventListener('click', () => web.copyToClipboard($stat.innerText));
|
||||
});
|
||||
components.setTooltip($readingTooltip, '**~ 275 wpm**');
|
||||
components.setTooltip($speakingTooltip, '**~ 180 wpm**');
|
||||
|
Loading…
Reference in New Issue
Block a user