mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-06 21:49:03 +00:00
refactor twind to classes + support notion.site + bugfixes
This commit is contained in:
parent
ea30d01296
commit
8c1b5c0835
@ -10,14 +10,15 @@
|
|||||||
|
|
||||||
/** environment-specific methods and constants */
|
/** environment-specific methods and constants */
|
||||||
export * as env from './env.mjs';
|
export * as env from './env.mjs';
|
||||||
|
/** environment-specific data persistence */
|
||||||
|
export * as storage from './storage.mjs';
|
||||||
|
|
||||||
/** helpers for formatting or parsing text */
|
/** helpers for formatting or parsing text */
|
||||||
export * as fmt from './fmt.mjs';
|
export * as fmt from './fmt.mjs';
|
||||||
/** environment-specific filesystem reading */
|
/** environment-specific filesystem reading */
|
||||||
export * as fs from './fs.mjs';
|
export * as fs from './fs.mjs';
|
||||||
/** interactions with the enhancer's repository of mods */
|
/** interactions with the enhancer's repository of mods */
|
||||||
export * as registry from './registry.mjs';
|
export * as registry from './registry.mjs';
|
||||||
/** environment-specific data persistence */
|
|
||||||
export * as storage from './storage.mjs';
|
|
||||||
/** pattern and type validators */
|
/** pattern and type validators */
|
||||||
export * as validation from './validation.mjs';
|
export * as validation from './validation.mjs';
|
||||||
/** helpers for manipulation of a webpage */
|
/** helpers for manipulation of a webpage */
|
||||||
|
@ -30,8 +30,7 @@ export const supported = ['linux', 'win32', 'darwin', 'extension'];
|
|||||||
export const version = chrome.runtime.getManifest().version;
|
export const version = chrome.runtime.getManifest().version;
|
||||||
|
|
||||||
/** open the enhancer's menu */
|
/** open the enhancer's menu */
|
||||||
export const openEnhancerMenu = () =>
|
export const focusMenu = () => chrome.runtime.sendMessage({ action: 'focusMenu' });
|
||||||
chrome.runtime.sendMessage({ action: 'openEnhancerMenu' });
|
|
||||||
|
|
||||||
/** focus an active notion tab */
|
/** focus an active notion tab */
|
||||||
export const focusNotion = () => chrome.runtime.sendMessage({ action: 'focusNotion' });
|
export const focusNotion = () => chrome.runtime.sendMessage({ action: 'focusNotion' });
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
* @module notion-enhancer/api/fmt
|
* @module notion-enhancer/api/fmt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import * as web from './web.mjs';
|
||||||
|
|
||||||
import '../dep/prism.min.js';
|
import '../dep/prism.min.js';
|
||||||
/** syntax highlighting using https://prismjs.com/ */
|
/** syntax highlighting using https://prismjs.com/ */
|
||||||
export const prism = Prism;
|
export const prism = Prism;
|
||||||
@ -19,7 +21,7 @@ Prism.hooks.add('complete', async (event) => {
|
|||||||
event.element.parentElement.removeAttribute('tabindex');
|
event.element.parentElement.removeAttribute('tabindex');
|
||||||
event.element.parentElement.parentElement
|
event.element.parentElement.parentElement
|
||||||
.querySelector('.copy-to-clipboard-button')
|
.querySelector('.copy-to-clipboard-button')
|
||||||
.prepend(web.createElement(await web.getIcon('fa/regular/copy')));
|
.prepend(web.html`${await web.icon('clipboard')}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
import '../dep/markdown-it.min.js';
|
import '../dep/markdown-it.min.js';
|
||||||
@ -27,7 +29,7 @@ import '../dep/markdown-it.min.js';
|
|||||||
export const md = new markdownit({
|
export const md = new markdownit({
|
||||||
linkify: true,
|
linkify: true,
|
||||||
highlight: (str, lang) =>
|
highlight: (str, lang) =>
|
||||||
web.html`<pre class="language-${lang || 'plaintext'} match-braces"><code>${web.escapeHtml(
|
web.html`<pre class="language-${lang || 'plaintext'} match-braces"><code>${web.escape(
|
||||||
str
|
str
|
||||||
)}</code></pre>`,
|
)}</code></pre>`,
|
||||||
});
|
});
|
||||||
@ -36,7 +38,7 @@ md.renderer.rules.code_block = (tokens, idx, options, env, slf) => {
|
|||||||
if (attrIdx === -1) {
|
if (attrIdx === -1) {
|
||||||
tokens[idx].attrPush(['class', 'match-braces language-plaintext']);
|
tokens[idx].attrPush(['class', 'match-braces language-plaintext']);
|
||||||
} else tokens[idx].attrs[attrIdx][1] = 'match-braces language-plaintext';
|
} else tokens[idx].attrs[attrIdx][1] = 'match-braces language-plaintext';
|
||||||
return web.html`<pre${slf.renderAttrs(tokens[idx])}><code>${web.escapeHtml(
|
return web.html`<pre${slf.renderAttrs(tokens[idx])}><code>${web.escape(
|
||||||
tokens[idx].content
|
tokens[idx].content
|
||||||
)}</code></pre>\n`;
|
)}</code></pre>\n`;
|
||||||
};
|
};
|
||||||
@ -47,7 +49,7 @@ md.core.ruler.push(
|
|||||||
state.tokens.forEach(function (token, i) {
|
state.tokens.forEach(function (token, i) {
|
||||||
if (token.type === 'heading_open') {
|
if (token.type === 'heading_open') {
|
||||||
const text = md.renderer.render(state.tokens[i + 1].children, md.options),
|
const text = md.renderer.render(state.tokens[i + 1].children, md.options),
|
||||||
slug = fmt.slugger(text, slugs);
|
slug = slugger(text, slugs);
|
||||||
slugs.add(slug);
|
slugs.add(slug);
|
||||||
const attrIdx = token.attrIndex('id');
|
const attrIdx = token.attrIndex('id');
|
||||||
if (attrIdx === -1) {
|
if (attrIdx === -1) {
|
||||||
|
@ -242,8 +242,7 @@ export const list = async (filter = (mod) => true) => {
|
|||||||
const mod = await getJSON(`repo/${dir}/mod.json`);
|
const mod = await getJSON(`repo/${dir}/mod.json`);
|
||||||
mod._dir = dir;
|
mod._dir = dir;
|
||||||
if (await validate(mod)) _cache.push(mod);
|
if (await validate(mod)) _cache.push(mod);
|
||||||
} catch (e) {
|
} catch {
|
||||||
console.log(e);
|
|
||||||
_errors.push({ source: dir, message: 'invalid mod.json' });
|
_errors.push({ source: dir, message: 'invalid mod.json' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ const _hotkeyEventListeners = [],
|
|||||||
_documentObserverListeners = [],
|
_documentObserverListeners = [],
|
||||||
_documentObserverEvents = [];
|
_documentObserverEvents = [];
|
||||||
|
|
||||||
let _$featherStylesheet, _$tooltip, _$tooltipStylesheet, _hotkeyEvent, _documentObserver;
|
let _$tooltip, _$tooltipStylesheet, _hotkeyEvent, _documentObserver;
|
||||||
|
|
||||||
import '../dep/jscolor.min.js';
|
import '../dep/jscolor.min.js';
|
||||||
/** color picker with alpha channel using https://jscolor.com/ */
|
/** color picker with alpha channel using https://jscolor.com/ */
|
||||||
@ -152,22 +152,13 @@ export const loadStylesheet = (path) => {
|
|||||||
* @returns {string} an svg string
|
* @returns {string} an svg string
|
||||||
*/
|
*/
|
||||||
export const icon = (name, attrs = {}) => {
|
export const icon = (name, attrs = {}) => {
|
||||||
if (!_$featherStylesheet) {
|
attrs.style = (
|
||||||
_$featherStylesheet = html`<style data-enhancer-api-style="feather">
|
(attrs.style || '') +
|
||||||
.enhancer--feather {
|
';stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;fill:none;'
|
||||||
stroke: currentColor;
|
).trim();
|
||||||
stroke-width: 2;
|
return `<svg ${Object.entries(attrs)
|
||||||
stroke-linecap: round;
|
.map(([key, val]) => `${escape(key)}="${escape(val)}"`)
|
||||||
stroke-linejoin: round;
|
.join(' ')}><use xlink:href="${localPath('dep/feather-sprite.svg')}#${name}" /></svg>`;
|
||||||
fill: none;
|
|
||||||
}
|
|
||||||
</style>`;
|
|
||||||
render(document.head, _$featherStylesheet);
|
|
||||||
}
|
|
||||||
attrs.class = ((attrs.class || '') + ' enhancer--feather').trim();
|
|
||||||
return `<svg ${Object.entries(attrs).map(
|
|
||||||
([key, val]) => `${escape(key)}="${escape(val)}"`
|
|
||||||
)}><use xlink:href="${localPath('dep/feather-sprite.svg')}#${name}" /></svg>`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -177,9 +168,9 @@ export const icon = (name, attrs = {}) => {
|
|||||||
*/
|
*/
|
||||||
export const tooltip = ($ref, text) => {
|
export const tooltip = ($ref, text) => {
|
||||||
if (!_$tooltip) {
|
if (!_$tooltip) {
|
||||||
_$tooltip = html`<div class="enhancer--tooltip"></div>`;
|
_$tooltip = html`<div id="enhancer--tooltip"></div>`;
|
||||||
_$tooltipStylesheet = html`<style data-enhancer-api-style="tooltip">
|
_$tooltipStylesheet = html`<style>
|
||||||
.enhancer--tooltip {
|
#enhancer--tooltip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: var(--theme--ui_tooltip);
|
background: var(--theme--ui_tooltip);
|
||||||
font-size: 11.5px;
|
font-size: 11.5px;
|
||||||
@ -189,13 +180,13 @@ export const tooltip = ($ref, text) => {
|
|||||||
max-width: 20rem;
|
max-width: 20rem;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.enhancer--tooltip p {
|
#enhancer--tooltip p {
|
||||||
margin: 0.25rem 0;
|
margin: 0.25rem 0;
|
||||||
}
|
}
|
||||||
.enhancer--tooltip p:first-child {
|
#enhancer--tooltip p:first-child {
|
||||||
color: var(--theme--ui_tooltip-title);
|
color: var(--theme--ui_tooltip-title);
|
||||||
}
|
}
|
||||||
.enhancer--tooltip p:not(:first-child) {
|
#enhancer--tooltip p:not(:first-child) {
|
||||||
color: var(--theme--ui_tooltip-description);
|
color: var(--theme--ui_tooltip-description);
|
||||||
}
|
}
|
||||||
</style>`;
|
</style>`;
|
||||||
|
@ -6,11 +6,12 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// only load if user is logged into notion and viewing a page
|
const site = location.host.endsWith('.notion.site'),
|
||||||
if (
|
loggedIn = localStorage['LRU:KeyValueStore2:current-user-id'],
|
||||||
localStorage['LRU:KeyValueStore2:current-user-id'] &&
|
page = location.pathname.split(/[/-]/g).reverse()[0].length === 32,
|
||||||
location.pathname.split(/[/-]/g).reverse()[0].length === 32
|
home = location.pathname === '/';
|
||||||
) {
|
|
||||||
|
if (site || (loggedIn && (page || home))) {
|
||||||
import(chrome.runtime.getURL('api/_.mjs')).then(async (api) => {
|
import(chrome.runtime.getURL('api/_.mjs')).then(async (api) => {
|
||||||
const { registry, web } = api;
|
const { registry, web } = api;
|
||||||
for (const mod of await registry.list((mod) => registry.enabled(mod.id))) {
|
for (const mod of await registry.list((mod) => registry.enabled(mod.id))) {
|
||||||
|
@ -19,15 +19,15 @@
|
|||||||
"web_accessible_resources": [
|
"web_accessible_resources": [
|
||||||
{
|
{
|
||||||
"resources": ["api/*", "dep/*", "icon/*", "repo/*"],
|
"resources": ["api/*", "dep/*", "icon/*", "repo/*"],
|
||||||
"matches": ["https://*.notion.so/*"]
|
"matches": ["https://*.notion.so/*", "https://*.notion.site/*"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": ["https://*.notion.so/*"],
|
"matches": ["https://*.notion.so/*", "https://*.notion.site/*"],
|
||||||
"js": ["launcher.js"]
|
"js": ["launcher.js"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"permissions": ["tabs", "storage", "unlimitedStorage"],
|
"permissions": ["tabs", "storage", "unlimitedStorage"],
|
||||||
"host_permissions": ["https://*.notion.so/*", "<all_urls>"]
|
"host_permissions": ["https://*.notion.so/*", "https://*.notion.site/*", "<all_urls>"]
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "calendar-scroll",
|
"name": "calendar-scroll",
|
||||||
"id": "b1c7db33-dfee-489a-a76c-0dd66f7ed29a",
|
"id": "b1c7db33-dfee-489a-a76c-0dd66f7ed29a",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"description": "add a button to scroll down to the current week in fullpage/infinite-scroll calendars.",
|
"description": "add a button to jump down to the current week in fullpage/infinite-scroll calendars.",
|
||||||
"tags": ["extension", "shortcut"],
|
"tags": ["extension", "shortcut"],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@ -7,8 +7,18 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
export default async function (api, db) {
|
export default async function (api, db) {
|
||||||
const { env, fs, registry, web } = api,
|
const { env, fs, registry, web } = api;
|
||||||
sidebarSelector = '.notion-sidebar-container .notion-sidebar > div:nth-child(4)';
|
|
||||||
|
web.addHotkeyListener(await db.get(['hotkey']), env.focusMenu);
|
||||||
|
|
||||||
|
const updateTheme = () =>
|
||||||
|
db.set(['theme'], document.querySelector('.notion-dark-theme') ? 'dark' : 'light');
|
||||||
|
web.addDocumentObserver((mutation) => {
|
||||||
|
if (mutation.target === document.body) updateTheme();
|
||||||
|
});
|
||||||
|
updateTheme();
|
||||||
|
|
||||||
|
const sidebarSelector = '.notion-sidebar-container .notion-sidebar > div:nth-child(4)';
|
||||||
await web.whenReady([sidebarSelector]);
|
await web.whenReady([sidebarSelector]);
|
||||||
|
|
||||||
const $sidebarLink = web.html`<div class="enhancer--sidebarMenuLink" role="button" tabindex="0">
|
const $sidebarLink = web.html`<div class="enhancer--sidebarMenuLink" role="button" tabindex="0">
|
||||||
@ -17,15 +27,7 @@ export default async function (api, db) {
|
|||||||
<div><div>notion-enhancer</div></div>
|
<div><div>notion-enhancer</div></div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
$sidebarLink.addEventListener('click', env.openEnhancerMenu);
|
$sidebarLink.addEventListener('click', env.focusMenu);
|
||||||
web.addHotkeyListener(await db.get(['hotkey']), env.openEnhancerMenu);
|
|
||||||
|
|
||||||
const updateTheme = () =>
|
|
||||||
db.set(['theme'], document.querySelector('.notion-dark-theme') ? 'dark' : 'light');
|
|
||||||
web.addDocumentObserver((mutation) => {
|
|
||||||
if (mutation.target === document.body) updateTheme();
|
|
||||||
});
|
|
||||||
updateTheme();
|
|
||||||
|
|
||||||
const notifications = {
|
const notifications = {
|
||||||
cache: await db.get(['notifications'], []),
|
cache: await db.get(['notifications'], []),
|
||||||
|
@ -4,64 +4,65 @@
|
|||||||
* (https://notion-enhancer.github.io/) under the MIT license
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.enhancer--markdown table {
|
.markdown table {
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
border: 1px solid var(--theme--ui_divider);
|
border: 1px solid var(--theme--ui_divider);
|
||||||
}
|
}
|
||||||
.enhancer--markdown table th {
|
.markdown table th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
.enhancer--markdown table th,
|
.markdown table th,
|
||||||
.enhancer--markdown table td {
|
.markdown table td {
|
||||||
padding: 5px 8px 6px;
|
padding: 5px 8px 6px;
|
||||||
border: 1px solid var(--theme--ui_divider);
|
border: 1px solid var(--theme--ui_divider);
|
||||||
}
|
}
|
||||||
.enhancer--markdown h1 {
|
.markdown h1 {
|
||||||
font-size: 1.875rem;
|
font-size: 1.875rem;
|
||||||
margin: 1rem 0 0.5rem 0;
|
margin: 1rem 0 0.5rem 0;
|
||||||
}
|
}
|
||||||
.enhancer--markdown h2 {
|
.markdown h2 {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin: 1rem 0 0.5rem 0;
|
margin: 1rem 0 0.5rem 0;
|
||||||
}
|
}
|
||||||
.enhancer--markdown h3 {
|
.markdown h3 {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
margin: 1rem 0 0.5rem 0;
|
margin: 1rem 0 0.5rem 0;
|
||||||
}
|
}
|
||||||
.enhancer--markdown ul,
|
.markdown ul,
|
||||||
.enhancer--markdown ol {
|
.markdown ol {
|
||||||
padding-left: 1.25rem;
|
padding-left: 1.25rem;
|
||||||
}
|
}
|
||||||
.enhancer--markdown li {
|
.markdown li {
|
||||||
margin: 0.4rem 0;
|
margin: 0.4rem 0;
|
||||||
}
|
}
|
||||||
.enhancer--markdown ol li {
|
.markdown ol li {
|
||||||
padding-left: 0.25rem;
|
padding-left: 0.25rem;
|
||||||
}
|
}
|
||||||
.enhancer--markdown blockquote {
|
.markdown blockquote {
|
||||||
border-left: 2px solid currentColor;
|
border-left: 2px solid currentColor;
|
||||||
padding-left: 0.75rem;
|
padding-left: 0.75rem;
|
||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
}
|
}
|
||||||
.enhancer--markdown hr {
|
.markdown hr {
|
||||||
border: 0.5px solid var(--theme--ui_divider);
|
border: 0.5px solid var(--theme--ui_divider);
|
||||||
}
|
}
|
||||||
.enhancer--markdown a {
|
.markdown.markdown-inline a {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: 0.05em solid var(--theme--text_ui);
|
border-bottom: 0.05em solid var(--theme--text_ui);
|
||||||
}
|
}
|
||||||
.enhancer--markdown a:hover {
|
.markdown.markdown-inline a:hover {
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.enhancer--markdown :not(pre) > code {
|
.markdown :not(pre) > code,
|
||||||
|
.markdown-inline code {
|
||||||
padding: 0.2em 0.4em;
|
padding: 0.2em 0.4em;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: var(--theme--code_inline);
|
background: var(--theme--code_inline);
|
||||||
color: var(--theme--code_inline-text);
|
color: var(--theme--code_inline-text);
|
||||||
}
|
}
|
||||||
.enhancer--markdown pre {
|
.markdown pre {
|
||||||
padding: 2em 1.25em;
|
padding: 2em 1.25em;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
tab-size: 2;
|
tab-size: 2;
|
||||||
@ -70,8 +71,8 @@
|
|||||||
background: var(--theme--code);
|
background: var(--theme--code);
|
||||||
color: var(--theme--code_plain);
|
color: var(--theme--code_plain);
|
||||||
}
|
}
|
||||||
.enhancer--markdown pre,
|
.markdown pre,
|
||||||
.enhancer--markdown code {
|
.markdown.markdown-inline code {
|
||||||
font-family: var(--theme--font_code);
|
font-family: var(--theme--font_code);
|
||||||
font-size: 0.796875rem;
|
font-size: 0.796875rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -85,7 +86,7 @@
|
|||||||
/*
|
/*
|
||||||
* https://prismjs.com/plugins/inline-color/
|
* https://prismjs.com/plugins/inline-color/
|
||||||
*/
|
*/
|
||||||
.enhancer--markdown .inline-color-wrapper {
|
.markdown .inline-color-wrapper {
|
||||||
/*
|
/*
|
||||||
* base64 svg (https://stackoverflow.com/a/21626701/7595472 - prevents visual glitches)
|
* base64 svg (https://stackoverflow.com/a/21626701/7595472 - prevents visual glitches)
|
||||||
* <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2">
|
* <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2">
|
||||||
@ -104,7 +105,7 @@
|
|||||||
border: 0.5px solid var(--theme--code_plain);
|
border: 0.5px solid var(--theme--code_plain);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.enhancer--markdown .inline-color {
|
.markdown .inline-color {
|
||||||
display: block;
|
display: block;
|
||||||
height: 120%;
|
height: 120%;
|
||||||
width: 120%;
|
width: 120%;
|
||||||
@ -113,8 +114,8 @@
|
|||||||
/*
|
/*
|
||||||
* https://prismjs.com/plugins/match-braces/
|
* https://prismjs.com/plugins/match-braces/
|
||||||
*/
|
*/
|
||||||
.enhancer--markdown .token.punctuation.brace-hover,
|
.markdown .token.punctuation.brace-hover,
|
||||||
.enhancer--markdown .token.punctuation.brace-selected {
|
.markdown .token.punctuation.brace-selected {
|
||||||
outline: solid 1px;
|
outline: solid 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,43 +123,43 @@
|
|||||||
* https://prismjs.com/plugins/show-language/
|
* https://prismjs.com/plugins/show-language/
|
||||||
* https://prismjs.com/plugins/copy-to-clipboard/
|
* https://prismjs.com/plugins/copy-to-clipboard/
|
||||||
*/
|
*/
|
||||||
.enhancer--markdown .code-toolbar {
|
.markdown .code-toolbar {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.enhancer--markdown .code-toolbar .toolbar-item {
|
.markdown .code-toolbar .toolbar-item {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.35rem;
|
top: 0.35rem;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
transition: opacity 200ms ease-in-out;
|
transition: opacity 200ms ease-in-out;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
.enhancer--markdown .code-toolbar .toolbar-item:first-child {
|
.markdown .code-toolbar .toolbar-item:first-child {
|
||||||
left: 0.8rem;
|
left: 0.8rem;
|
||||||
}
|
}
|
||||||
.enhancer--markdown .code-toolbar .toolbar-item:last-child {
|
.markdown .code-toolbar .toolbar-item:last-child {
|
||||||
right: 0.8rem;
|
right: 0.8rem;
|
||||||
}
|
}
|
||||||
.enhancer--markdown .code-toolbar:hover .toolbar-item,
|
.markdown .code-toolbar:hover .toolbar-item,
|
||||||
.enhancer--markdown .code-toolbar:focus-within .toolbar-item {
|
.markdown .code-toolbar:focus-within .toolbar-item {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.enhancer--markdown .code-toolbar .toolbar-item > * {
|
.markdown .code-toolbar .toolbar-item > * {
|
||||||
padding: 0.25rem 0.35rem;
|
padding: 0.25rem 0.35rem;
|
||||||
color: var(--theme--text_ui);
|
color: var(--theme--text_ui);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
.enhancer--markdown .code-toolbar .toolbar-item .copy-to-clipboard-button {
|
.markdown .code-toolbar .toolbar-item .copy-to-clipboard-button {
|
||||||
border: none;
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
transition: background 100ms ease-in-out;
|
transition: background 100ms ease-in-out;
|
||||||
}
|
}
|
||||||
.enhancer--markdown .code-toolbar .toolbar-item .copy-to-clipboard-button:hover {
|
.markdown .code-toolbar .toolbar-item .copy-to-clipboard-button:hover {
|
||||||
background: var(--theme--button-hover);
|
background: var(--theme--button-hover);
|
||||||
}
|
}
|
||||||
.enhancer--markdown .code-toolbar .toolbar-item .copy-to-clipboard-button svg {
|
.markdown .code-toolbar .toolbar-item .copy-to-clipboard-button svg {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
@ -6,94 +6,14 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// css-in-js for better component generation
|
|
||||||
|
|
||||||
import { tw, apply, setup } from '../../dep/twind.mjs';
|
|
||||||
import { content } from '../../dep/twind-content.mjs';
|
|
||||||
const pseudoContent = content('""');
|
|
||||||
|
|
||||||
const mapColorVariables = (color) => ({
|
|
||||||
'text': `var(--theme--text_${color})`,
|
|
||||||
'highlight': `var(--theme--highlight_${color})`,
|
|
||||||
'highlight-text': `var(--theme--highlight_${color}-text)`,
|
|
||||||
'block': `var(--theme--block_${color})`,
|
|
||||||
'block-text': `var(--theme--block_${color}-text)`,
|
|
||||||
'tag': `var(--theme--tag_${color})`,
|
|
||||||
'tag-text': `var(--theme--tag_${color}-text)`,
|
|
||||||
'callout': `var(--theme--callout_${color})`,
|
|
||||||
'callout-text': `var(--theme--callout_${color}-text)`,
|
|
||||||
});
|
|
||||||
|
|
||||||
setup({
|
|
||||||
preflight: {
|
|
||||||
html: apply`w-full h-full`,
|
|
||||||
body: apply`w-full h-full bg-notion-bg font-sans text-foreground`,
|
|
||||||
},
|
|
||||||
theme: {
|
|
||||||
fontFamily: {
|
|
||||||
sans: ['var(--theme--font_sans)'],
|
|
||||||
mono: ['var(--theme--font_mono)'],
|
|
||||||
},
|
|
||||||
colors: {
|
|
||||||
'notion': {
|
|
||||||
'bg': 'var(--theme--bg)',
|
|
||||||
'secondary': 'var(--theme--bg_secondary)',
|
|
||||||
'popup': 'var(--theme--bg_popup)',
|
|
||||||
'divider': 'var(--theme--ui_divider)',
|
|
||||||
'input': 'var(--theme--ui_input)',
|
|
||||||
},
|
|
||||||
'icon': 'var(--theme--icon)',
|
|
||||||
'icon-ui': 'var(--theme--icon_ui)',
|
|
||||||
'foreground': 'var(--theme--text)',
|
|
||||||
'foreground-ui': 'var(--theme--text_ui)',
|
|
||||||
'interactive': 'var(--theme--ui_interactive)',
|
|
||||||
'interactive-hover': 'var(--theme--ui_interactive-hover)',
|
|
||||||
'tag': 'var(--theme--tag_default)',
|
|
||||||
'tag-text': 'var(--theme--tag_default-text)',
|
|
||||||
'toggle': {
|
|
||||||
'on': 'var(--theme--ui_toggle-on)',
|
|
||||||
'off': 'var(--theme--ui_toggle-off)',
|
|
||||||
'feature': 'var(--theme--ui_toggle-feature)',
|
|
||||||
},
|
|
||||||
'accent': {
|
|
||||||
'blue': 'var(--theme--accent_blue)',
|
|
||||||
'blue-hover': 'var(--theme--accent_blue-hover)',
|
|
||||||
'blue-active': 'var(--theme--accent_blue-active)',
|
|
||||||
'blue-text': 'var(--theme--accent_blue-text)',
|
|
||||||
'red': 'var(--theme--accent_red)',
|
|
||||||
'red-hover': 'var(--theme--accent_red-hover)',
|
|
||||||
'red-text': 'var(--theme--accent_red-text)',
|
|
||||||
},
|
|
||||||
'grey': mapColorVariables('grey'),
|
|
||||||
'brown': mapColorVariables('brown'),
|
|
||||||
'orange': mapColorVariables('orange'),
|
|
||||||
'yellow': mapColorVariables('yellow'),
|
|
||||||
'green': mapColorVariables('green'),
|
|
||||||
'blue': mapColorVariables('blue'),
|
|
||||||
'purple': mapColorVariables('purple'),
|
|
||||||
'pink': mapColorVariables('pink'),
|
|
||||||
'red': mapColorVariables('red'),
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
width: {
|
|
||||||
'full-96': 'calc(100% - 24rem)',
|
|
||||||
},
|
|
||||||
maxHeight: {
|
|
||||||
'full-16': 'calc(100% - 4rem)',
|
|
||||||
'full-32': 'calc(100% - 8rem)',
|
|
||||||
'full-48': 'calc(100% - 12rem)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// initialisation and external interactions
|
// initialisation and external interactions
|
||||||
|
|
||||||
import * as api from '../../api/_.mjs';
|
import * as api from '../../api/_.mjs';
|
||||||
import { render } from '../../api/web.mjs';
|
const { env, fmt, fs, registry, web } = api,
|
||||||
const { env, fmt, fs, registry, storage, web } = api,
|
|
||||||
db = await registry.db('a6621988-551d-495a-97d8-3c568bca2e9e');
|
db = await registry.db('a6621988-551d-495a-97d8-3c568bca2e9e');
|
||||||
|
|
||||||
|
import { tw } from './styles.mjs';
|
||||||
|
|
||||||
web.addHotkeyListener(await db.get(['hotkey']), env.focusNotion);
|
web.addHotkeyListener(await db.get(['hotkey']), env.focusNotion);
|
||||||
|
|
||||||
for (const mod of await registry.list((mod) => registry.enabled(mod.id))) {
|
for (const mod of await registry.list((mod) => registry.enabled(mod.id))) {
|
||||||
@ -110,29 +30,25 @@ document.addEventListener('visibilitychange', loadTheme);
|
|||||||
loadTheme();
|
loadTheme();
|
||||||
|
|
||||||
const notifications = {
|
const notifications = {
|
||||||
$container: web.html`<div class="${tw`absolute bottom-0 right-0 px-4 py-3 max-w-full w-96`}"></div>`,
|
$container: web.html`<div class="notifications-container"></div>`,
|
||||||
cache: await db.get(['notifications'], []),
|
cache: await db.get(['notifications'], []),
|
||||||
provider: [
|
provider: [
|
||||||
env.welcomeNotification,
|
env.welcomeNotification,
|
||||||
...(await fs.getJSON('https://notion-enhancer.github.io/notifications.json')),
|
...(await fs.getJSON('https://notion-enhancer.github.io/notifications.json')),
|
||||||
],
|
],
|
||||||
add({ icon, message, id = undefined, color = undefined, link = undefined }) {
|
add({ icon, message, id = undefined, color = undefined, link = undefined }) {
|
||||||
const style = tw`p-2 ${
|
const $notification = link
|
||||||
color
|
? web.html`<a
|
||||||
? `bg-${color}-tag text-${color}-tag-text border border-${color}-text hover:bg-${color}-text`
|
href="${web.escape(link)}"
|
||||||
: 'bg-tag text-tag-text hover:bg-interactive-hover border border-notion-divider'
|
class="${tw`notification-${color || 'default'}`}"
|
||||||
} flex items-center rounded-full mt-3 shadow-md cursor-pointer`,
|
role="alert"
|
||||||
$notification = web.render(
|
target="_blank"
|
||||||
link
|
></a>`
|
||||||
? web.html`<a href="${web.escape(
|
: web.html`<p
|
||||||
link
|
class="${tw`notification-${color || 'default'}`}"
|
||||||
)}" class="${style}" role="alert" target="_blank"></a>`
|
role="alert"
|
||||||
: web.html`<p class="${style}" role="alert" tabindex="0"></p>`,
|
tabindex="0"
|
||||||
web.html`<span class="${tw`font-semibold mx-2 flex-auto`}">
|
></p>`,
|
||||||
${message}
|
|
||||||
</span>`,
|
|
||||||
web.html`${web.icon(icon, { class: tw`fill-current opacity-75 h-4 w-4 mx-2` })}`
|
|
||||||
),
|
|
||||||
resolve = async () => {
|
resolve = async () => {
|
||||||
if (id !== undefined) {
|
if (id !== undefined) {
|
||||||
notifications.cache.push(id);
|
notifications.cache.push(id);
|
||||||
@ -144,7 +60,16 @@ const notifications = {
|
|||||||
$notification.addEventListener('keyup', (event) => {
|
$notification.addEventListener('keyup', (event) => {
|
||||||
if (['Enter', ' '].includes(event.key)) resolve();
|
if (['Enter', ' '].includes(event.key)) resolve();
|
||||||
});
|
});
|
||||||
web.render(notifications.$container, $notification);
|
web.render(
|
||||||
|
notifications.$container,
|
||||||
|
web.render(
|
||||||
|
$notification,
|
||||||
|
web.html`<span class="notification-text markdown-inline">
|
||||||
|
${fmt.md.renderInline(message)}
|
||||||
|
</span>`,
|
||||||
|
web.html`${web.icon(icon, { class: 'notification-icon' })}`
|
||||||
|
)
|
||||||
|
);
|
||||||
return $notification;
|
return $notification;
|
||||||
},
|
},
|
||||||
_changes: false,
|
_changes: false,
|
||||||
@ -158,7 +83,7 @@ const notifications = {
|
|||||||
$notification.addEventListener('click', env.reload);
|
$notification.addEventListener('click', env.reload);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
render(document.body, notifications.$container);
|
web.render(document.body, notifications.$container);
|
||||||
for (const notification of notifications.provider) {
|
for (const notification of notifications.provider) {
|
||||||
if (
|
if (
|
||||||
!notifications.cache.includes(notification.id) &&
|
!notifications.cache.includes(notification.id) &&
|
||||||
@ -182,135 +107,59 @@ if (errors.length) {
|
|||||||
|
|
||||||
// mod config
|
// mod config
|
||||||
|
|
||||||
const $container = web.html`<div class="${tw`flex w-full h-full overflow-hidden`}"></div>`,
|
|
||||||
$nav = web.html`<nav class="${tw`px-4 py-3 flex flex-wrap items-center border-b border-notion-divider h-48 sm:h-32 lg:h-16`}"></nav>`,
|
|
||||||
$main = web.html`<main class="${tw`transition px-4 py-3 overflow-y-auto max-h-full-48 sm:max-h-full-32 lg:max-h-full-16`}">abc</main>`,
|
|
||||||
// $footer = web.html`<footer></footer>`,
|
|
||||||
$sidebar = web.html`<article class="${tw`h-full w-96 bg-notion-secondary border-l border-notion-divider`}"></article>`;
|
|
||||||
|
|
||||||
const notionNavStyle = tw`flex items-center font-semibold text-xl cursor-pointer select-none mr-4
|
|
||||||
ml-4 sm:mb-4 md:w-full lg:(w-auto ml-0 mb-0)`,
|
|
||||||
$notion = web.html`<h1 class="${notionNavStyle}">
|
|
||||||
${(await fs.getText('icon/colour.svg')).replace(
|
|
||||||
/width="\d+" height="\d+"/,
|
|
||||||
`class="${tw`h-12 w-12 mr-5 sm:(h-6 w-6 mr-3)`}"`
|
|
||||||
)}
|
|
||||||
<a href="https://notion-enhancer.github.io/" target="_blank">notion-enhancer</a>
|
|
||||||
</h1>`;
|
|
||||||
$notion.children[0].addEventListener('click', env.focusNotion);
|
|
||||||
|
|
||||||
const navItemStyle = tw`ml-4 px-3 py-2 rounded-md text-sm font-medium bg-interactive hover:bg-interactive-hover`,
|
|
||||||
selectedNavItemStyle = tw`ml-4 px-3 py-2 rounded-md text-sm font-medium ring-1 ring-notion-divider bg-notion-secondary`;
|
|
||||||
|
|
||||||
const $coreNavItem = web.html`<a href="?view=core" class="${navItemStyle}">core</a>`,
|
|
||||||
$extensionsNavItem = web.html`<a href="?view=extensions" class="${navItemStyle}">extensions</a>`,
|
|
||||||
$themesNavItem = web.html`<a href="?view=themes" class="${navItemStyle}">themes</a>`,
|
|
||||||
$supportNavItem = web.html`<a href="https://discord.gg/sFWPXtA" class="${navItemStyle}">support</a>`;
|
|
||||||
|
|
||||||
web.render(
|
|
||||||
document.body,
|
|
||||||
web.render(
|
|
||||||
$container,
|
|
||||||
web.render(
|
|
||||||
web.html`<div class="${tw`h-full w-full-96`}"></div>`,
|
|
||||||
web.render(
|
|
||||||
$nav,
|
|
||||||
$notion,
|
|
||||||
$coreNavItem,
|
|
||||||
$extensionsNavItem,
|
|
||||||
$themesNavItem,
|
|
||||||
$supportNavItem
|
|
||||||
),
|
|
||||||
$main
|
|
||||||
// $footer
|
|
||||||
),
|
|
||||||
$sidebar
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const components = {
|
const components = {
|
||||||
preview: (url) => web.html`<img
|
preview: (url) => web.html`<img
|
||||||
class="${tw`object-cover w-full h-32`}"
|
class="mod-preview"
|
||||||
src="${web.escape(url)}"
|
src="${web.escape(url)}"
|
||||||
alt=""
|
alt=""
|
||||||
/>`,
|
/>`,
|
||||||
title: (title) => {
|
title: (title) => web.html`<h4 class="mod-title"><span>${web.escape(title)}</span></h4>`,
|
||||||
const style = tw`mb-2 text-xl font-semibold tracking-tight flex items-center`;
|
version: (version) => web.html`<span class="mod-version">v${web.escape(version)}</span>`,
|
||||||
return web.html`<h4 class="${style}"><span>${web.escape(title)}</span></h4>`;
|
|
||||||
},
|
|
||||||
version: (version) => {
|
|
||||||
const style = tw`mt-px ml-3 p-1 font-normal text-xs leading-none bg-tag text-tag-text rounded`;
|
|
||||||
return web.html`<span class="${style}">v${web.escape(version)}</span>`;
|
|
||||||
},
|
|
||||||
tags: (tags) => {
|
tags: (tags) => {
|
||||||
if (!tags.length) return '';
|
if (!tags.length) return '';
|
||||||
return web.render(
|
return web.render(
|
||||||
web.html`<p class="${tw`text-foreground-ui mb-2 text-xs`}"></p>`,
|
web.html`<p class="mod-tags"></p>`,
|
||||||
tags.map((tag) => `#${web.escape(tag)}`).join(' ')
|
tags.map((tag) => `#${web.escape(tag)}`).join(' ')
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
description: (description) => {
|
description: (description) => web.html`<p class="mod-description markdown-inline">
|
||||||
return web.html`<p class="${tw`mb-2 text-sm`} enhancer--markdown">
|
${fmt.md.renderInline(description)}
|
||||||
${fmt.md.renderInline(description)}
|
</p>`,
|
||||||
</p>`;
|
|
||||||
},
|
|
||||||
authors: (authors) => {
|
authors: (authors) => {
|
||||||
const author = (author) => web.html`<a class="${tw`flex items-center mb-2`}"
|
const author = (author) => web.html`<a class="mod-author" href="${web.escape(
|
||||||
href="${web.escape(author.homepage)}"
|
author.homepage
|
||||||
>
|
)}">
|
||||||
<img class="${tw`inline object-cover w-5 h-5 rounded-full mr-2`}"
|
<img class="mod-author-avatar"
|
||||||
src="${web.escape(author.avatar)}" alt="${web.escape(author.name)}'s avatar"
|
src="${web.escape(author.avatar)}" alt="${web.escape(author.name)}'s avatar"
|
||||||
/> <span>${web.escape(author.name)}</span>
|
/> <span>${web.escape(author.name)}</span>
|
||||||
</a>`;
|
</a>`;
|
||||||
return web.render(
|
return web.render(web.html`<p class="mod-authors-container"></p>`, ...authors.map(author));
|
||||||
web.html`<p class="${tw`text-sm font-medium`}"></p>`,
|
|
||||||
...authors.map(author)
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
toggle: (
|
toggle: (checked) => {
|
||||||
checked,
|
const $label = web.html`<label tabindex="0" class="toggle-label-full"></label>`,
|
||||||
{
|
$input = web.html`<input tabindex="-1" type="checkbox" class="toggle-check-right"
|
||||||
customLabelStyle = '',
|
${checked ? 'checked' : ''}/>`;
|
||||||
customCheckStyle = '',
|
|
||||||
customBoxStyle = '',
|
|
||||||
customFeatureStyle = '',
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
const checkStyle = tw`appearance-none checked:sibling:(bg-toggle-on after::translate-x-4) ${customCheckStyle}`,
|
|
||||||
boxStyle = tw`w-9 h-5 p-0.5 flex items-center bg-toggle-off rounded-full duration-300 ease-in-out ${customBoxStyle}`,
|
|
||||||
featureStyle = tw`after::(${pseudoContent} w-4 h-4 bg-toggle-feature rounded-full duration-300) ${customFeatureStyle}`,
|
|
||||||
$label = web.html`<label tabindex="0" class="${tw`relative text-sm ${customLabelStyle}`}"></label>`,
|
|
||||||
$input = web.html`<input tabindex="-1" type="checkbox" class="${checkStyle}" ${
|
|
||||||
checked ? 'checked' : ''
|
|
||||||
}/>`;
|
|
||||||
$label.addEventListener('keyup', (event) => {
|
$label.addEventListener('keyup', (event) => {
|
||||||
if (['Enter', ' '].includes(event.key)) {
|
if (['Enter', ' '].includes(event.key)) $input.checked = !$input.checked;
|
||||||
$input.checked = !$input.checked;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return web.render(
|
return web.render(
|
||||||
$label,
|
$label,
|
||||||
$input,
|
$input,
|
||||||
web.html`<span class="${boxStyle} ${featureStyle}"></span>`
|
web.html`<span class="toggle-box toggle-feature"></span>`
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
components.mod = async (mod) => {
|
components.mod = async (mod) => {
|
||||||
const $toggle = components.toggle(await registry.enabled(mod.id), {
|
const $toggle = components.toggle(await registry.enabled(mod.id));
|
||||||
customLabelStyle: 'flex w-full mt-auto',
|
|
||||||
customCheckStyle: 'ml-auto',
|
|
||||||
});
|
|
||||||
$toggle.addEventListener('change', (event) => {
|
$toggle.addEventListener('change', (event) => {
|
||||||
registry.profile.set(['_mods', mod.id], event.target.checked);
|
registry.profile.set(['_mods', mod.id], event.target.checked);
|
||||||
notifications.changes();
|
notifications.changes();
|
||||||
});
|
});
|
||||||
const style = tw`relative h-full w-full flex flex-col overflow-hidden rounded-lg shadow-lg
|
|
||||||
bg-notion-secondary border border-notion-divider`;
|
|
||||||
return web.render(
|
return web.render(
|
||||||
web.html`<article class="${tw`w-full md:w-1/2 lg:w-1/3 xl:w-1/4 2xl:w-1/5 px-2.5 py-2.5 box-border`}"></article>`,
|
web.html`<article class="mod-container"></article>`,
|
||||||
web.render(
|
web.render(
|
||||||
web.html`<div class="${style}"></div>`,
|
web.html`<div class="mod"></div>`,
|
||||||
mod.preview
|
mod.preview
|
||||||
? components.preview(
|
? components.preview(
|
||||||
mod.preview.startsWith('http')
|
mod.preview.startsWith('http')
|
||||||
@ -319,7 +168,7 @@ components.mod = async (mod) => {
|
|||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
web.render(
|
web.render(
|
||||||
web.html`<div class="${tw`px-4 py-3 flex flex-col flex-auto`}"></div>`,
|
web.html`<div class="mod-body"></div>`,
|
||||||
web.render(components.title(mod.name), components.version(mod.version)),
|
web.render(components.title(mod.name), components.version(mod.version)),
|
||||||
components.tags(mod.tags),
|
components.tags(mod.tags),
|
||||||
components.description(mod.description),
|
components.description(mod.description),
|
||||||
@ -331,21 +180,18 @@ components.mod = async (mod) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
components.modList = async (category) => {
|
components.modList = async (category) => {
|
||||||
const $search = web.html`<input type="search" class="${tw`transition block w-full px-3 py-2 text-sm rounded-md flex
|
const $search = web.html`<input type="search" class="search"
|
||||||
bg-notion-input text-foreground
|
|
||||||
hover:(ring ring-accent-blue-hover) focus:(outline-none ring ring-accent-blue-active)`}"
|
|
||||||
placeholder="Search ('/' to focus)">`,
|
placeholder="Search ('/' to focus)">`,
|
||||||
$list = web.html`<div class="${tw`flex flex-wrap`}"></div>`,
|
$list = web.html`<div class="mods-list"></div>`,
|
||||||
mods = await registry.list(
|
mods = await registry.list(
|
||||||
(mod) => mod.environments.includes(env.name) && mod.tags.includes(category)
|
(mod) => mod.environments.includes(env.name) && mod.tags.includes(category)
|
||||||
);
|
);
|
||||||
web.addHotkeyListener(['/'], () => $search.focus());
|
web.addHotkeyListener(['/'], () => $search.focus());
|
||||||
$search.addEventListener('input', (event) => {
|
$search.addEventListener('input', (event) => {
|
||||||
const query = $search.value.toLowerCase(),
|
const query = $search.value.toLowerCase();
|
||||||
hiddenStyle = tw`hidden`;
|
|
||||||
for (const $mod of $list.children) {
|
for (const $mod of $list.children) {
|
||||||
const matches = !query || $mod.innerText.toLowerCase().includes(query);
|
const matches = !query || $mod.innerText.toLowerCase().includes(query);
|
||||||
$mod.classList[matches ? 'remove' : 'add'](hiddenStyle);
|
$mod.classList[matches ? 'remove' : 'add']('hidden');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (const mod of mods) {
|
for (const mod of mods) {
|
||||||
@ -355,34 +201,72 @@ components.modList = async (category) => {
|
|||||||
}
|
}
|
||||||
return web.render(
|
return web.render(
|
||||||
web.html`<div></div>`,
|
web.html`<div></div>`,
|
||||||
web.render(web.html`<div class="${tw`mx-2.5 my-2.5`}"></div>`, $search),
|
web.render(web.html`<div class="search-container"></div>`, $search),
|
||||||
$list
|
$list
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const $main = web.html`<main class="main"></main>`,
|
||||||
|
$sidebar = web.html`<article class="sidebar"></article>`;
|
||||||
|
|
||||||
|
const $notionNavItem = web.html`<h1 class="nav-notion">
|
||||||
|
${(await fs.getText('icon/colour.svg')).replace(
|
||||||
|
/width="\d+" height="\d+"/,
|
||||||
|
`class="nav-notion-icon"`
|
||||||
|
)}
|
||||||
|
<a href="https://notion-enhancer.github.io/" target="_blank">notion-enhancer</a>
|
||||||
|
</h1>`;
|
||||||
|
$notionNavItem.children[0].addEventListener('click', env.focusNotion);
|
||||||
|
|
||||||
|
const $coreNavItem = web.html`<a href="?view=core" class="nav-item">core</a>`,
|
||||||
|
$extensionsNavItem = web.html`<a href="?view=extensions" class="nav-item">extensions</a>`,
|
||||||
|
$themesNavItem = web.html`<a href="?view=themes" class="nav-item">themes</a>`,
|
||||||
|
$supportNavItem = web.html`<a href="https://discord.gg/sFWPXtA" class="nav-item">support</a>`;
|
||||||
|
|
||||||
|
web.render(
|
||||||
|
document.body,
|
||||||
|
web.render(
|
||||||
|
web.html`<div class="body-container"></div>`,
|
||||||
|
web.render(
|
||||||
|
web.html`<div class="content-container"></div>`,
|
||||||
|
web.render(
|
||||||
|
web.html`<nav class="nav"></nav>`,
|
||||||
|
$notionNavItem,
|
||||||
|
$coreNavItem,
|
||||||
|
$extensionsNavItem,
|
||||||
|
$themesNavItem,
|
||||||
|
$supportNavItem
|
||||||
|
),
|
||||||
|
$main
|
||||||
|
),
|
||||||
|
$sidebar
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
function selectNavItem($item) {
|
||||||
|
for (const $selected of document.querySelectorAll('.nav-item-selected')) {
|
||||||
|
$selected.className = 'nav-item';
|
||||||
|
}
|
||||||
|
$item.className = 'nav-item-selected';
|
||||||
|
}
|
||||||
|
|
||||||
import * as router from './router.mjs';
|
import * as router from './router.mjs';
|
||||||
|
|
||||||
router.addView('core', async () => {
|
router.addView('core', async () => {
|
||||||
$extensionsNavItem.className = navItemStyle;
|
|
||||||
$themesNavItem.className = navItemStyle;
|
|
||||||
$coreNavItem.className = selectedNavItemStyle;
|
|
||||||
web.empty($main);
|
web.empty($main);
|
||||||
|
selectNavItem($coreNavItem);
|
||||||
return web.render($main, await components.modList('core'));
|
return web.render($main, await components.modList('core'));
|
||||||
});
|
});
|
||||||
|
|
||||||
router.addView('extensions', async () => {
|
router.addView('extensions', async () => {
|
||||||
$coreNavItem.className = navItemStyle;
|
|
||||||
$themesNavItem.className = navItemStyle;
|
|
||||||
$extensionsNavItem.className = selectedNavItemStyle;
|
|
||||||
web.empty($main);
|
web.empty($main);
|
||||||
|
selectNavItem($extensionsNavItem);
|
||||||
return web.render($main, await components.modList('extension'));
|
return web.render($main, await components.modList('extension'));
|
||||||
});
|
});
|
||||||
|
|
||||||
router.addView('themes', async () => {
|
router.addView('themes', async () => {
|
||||||
$coreNavItem.className = navItemStyle;
|
|
||||||
$extensionsNavItem.className = navItemStyle;
|
|
||||||
$themesNavItem.className = selectedNavItemStyle;
|
|
||||||
web.empty($main);
|
web.empty($main);
|
||||||
|
selectNavItem($themesNavItem);
|
||||||
return web.render($main, await components.modList('theme'));
|
return web.render($main, await components.modList('theme'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* notion-enhancer core: menu
|
||||||
|
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// css-in-js for better component generation
|
||||||
|
|
||||||
|
import { tw, apply, setup } from '../../dep/twind.mjs';
|
||||||
|
import { content } from '../../dep/twind-content.mjs';
|
||||||
|
const pseudoContent = content('""');
|
||||||
|
|
||||||
|
const mapColorVariables = (color) => ({
|
||||||
|
'text': `var(--theme--text_${color})`,
|
||||||
|
'highlight': `var(--theme--highlight_${color})`,
|
||||||
|
'highlight-text': `var(--theme--highlight_${color}-text)`,
|
||||||
|
'block': `var(--theme--block_${color})`,
|
||||||
|
'block-text': `var(--theme--block_${color}-text)`,
|
||||||
|
'tag': `var(--theme--tag_${color})`,
|
||||||
|
'tag-text': `var(--theme--tag_${color}-text)`,
|
||||||
|
'callout': `var(--theme--callout_${color})`,
|
||||||
|
'callout-text': `var(--theme--callout_${color}-text)`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const customClasses = {
|
||||||
|
'notifications-container': apply`absolute bottom-0 right-0 px-4 py-3 max-w-full w-96`,
|
||||||
|
'notification': ([color = 'default']) =>
|
||||||
|
apply`p-2 ${
|
||||||
|
color === 'default'
|
||||||
|
? 'bg-tag text-tag-text hover:bg-interactive-hover border border-notion-divider'
|
||||||
|
: `bg-${color}-tag text-${color}-tag-text border border-${color}-text hover:bg-${color}-text`
|
||||||
|
} flex items-center rounded-full mt-3 shadow-md cursor-pointer`,
|
||||||
|
'notification-text': apply`font-semibold mx-2 flex-auto`,
|
||||||
|
'notification-icon': apply`fill-current opacity-75 h-4 w-4 mx-2`,
|
||||||
|
'body-container': apply`flex w-full h-full overflow-hidden`,
|
||||||
|
'content-container': apply`h-full w-full-96`,
|
||||||
|
'nav': apply`px-4 py-3 flex flex-wrap items-center border-b border-notion-divider h-48 sm:h-32 lg:h-16`,
|
||||||
|
'nav-notion': apply`flex items-center font-semibold text-xl cursor-pointer select-none mr-4
|
||||||
|
ml-4 sm:mb-4 md:w-full lg:(w-auto ml-0 mb-0)`,
|
||||||
|
'nav-notion-icon': apply`h-12 w-12 mr-5 sm:(h-6 w-6 mr-3)`,
|
||||||
|
'nav-item': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium bg-interactive hover:bg-interactive-hover`,
|
||||||
|
'nav-item-selected': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium ring-1 ring-notion-divider bg-notion-secondary`,
|
||||||
|
'main': apply`transition px-4 py-3 overflow-y-auto max-h-full-48 sm:max-h-full-32 lg:max-h-full-16`,
|
||||||
|
'sidebar': apply`h-full w-96 bg-notion-secondary border-l border-notion-divider`,
|
||||||
|
'mods-list': apply`flex flex-wrap`,
|
||||||
|
'mod-container': apply`w-full md:w-1/2 lg:w-1/3 xl:w-1/4 2xl:w-1/5 px-2.5 py-2.5 box-border`,
|
||||||
|
'mod': apply`relative h-full w-full flex flex-col overflow-hidden rounded-lg shadow-lg
|
||||||
|
bg-notion-secondary border border-notion-divider`,
|
||||||
|
'mod-body': apply`px-4 py-3 flex flex-col flex-auto`,
|
||||||
|
'mod-preview': apply`object-cover w-full h-32`,
|
||||||
|
'mod-title': apply`mb-2 text-xl font-semibold tracking-tight flex items-center`,
|
||||||
|
'mod-version': apply`mt-px ml-3 p-1 font-normal text-xs leading-none bg-tag text-tag-text rounded`,
|
||||||
|
'mod-tags': apply`text-foreground-ui mb-2 text-xs`,
|
||||||
|
'mod-description': apply`mb-2 text-sm`,
|
||||||
|
'mod-authors-container': apply`text-sm font-medium`,
|
||||||
|
'mod-author': apply`flex items-center mb-2`,
|
||||||
|
'mod-author-avatar': apply`inline object-cover w-5 h-5 rounded-full mr-2`,
|
||||||
|
'toggle-box': apply`w-9 h-5 p-0.5 flex items-center bg-toggle-off rounded-full duration-300 ease-in-out`,
|
||||||
|
'toggle-label': apply`relative text-sm`,
|
||||||
|
'toggle-label-full': apply`relative text-sm flex w-full mt-auto`,
|
||||||
|
'toggle-check': apply`appearance-none checked:sibling:(bg-toggle-on after::translate-x-4)`,
|
||||||
|
'toggle-check-right': apply`appearance-none ml-auto checked:sibling:(bg-toggle-on after::translate-x-4)`,
|
||||||
|
'toggle-feature': apply`after::(${pseudoContent} w-4 h-4 bg-toggle-feature rounded-full duration-300)`,
|
||||||
|
'search-container': apply`mx-2.5 my-2.5`,
|
||||||
|
'search': apply`transition block w-full px-3 py-2 text-sm rounded-md flex bg-notion-input text-foreground
|
||||||
|
hover:(ring ring-accent-blue-hover) focus:(outline-none ring ring-accent-blue-active)`,
|
||||||
|
};
|
||||||
|
|
||||||
|
setup({
|
||||||
|
preflight: {
|
||||||
|
html: apply`w-full h-full`,
|
||||||
|
body: apply`w-full h-full bg-notion-bg font-sans text-foreground`,
|
||||||
|
},
|
||||||
|
theme: {
|
||||||
|
fontFamily: {
|
||||||
|
sans: ['var(--theme--font_sans)'],
|
||||||
|
mono: ['var(--theme--font_mono)'],
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
'notion': {
|
||||||
|
'bg': 'var(--theme--bg)',
|
||||||
|
'secondary': 'var(--theme--bg_secondary)',
|
||||||
|
'popup': 'var(--theme--bg_popup)',
|
||||||
|
'divider': 'var(--theme--ui_divider)',
|
||||||
|
'input': 'var(--theme--ui_input)',
|
||||||
|
},
|
||||||
|
'icon': 'var(--theme--icon)',
|
||||||
|
'icon-ui': 'var(--theme--icon_ui)',
|
||||||
|
'foreground': 'var(--theme--text)',
|
||||||
|
'foreground-ui': 'var(--theme--text_ui)',
|
||||||
|
'interactive': 'var(--theme--ui_interactive)',
|
||||||
|
'interactive-hover': 'var(--theme--ui_interactive-hover)',
|
||||||
|
'tag': 'var(--theme--tag_default)',
|
||||||
|
'tag-text': 'var(--theme--tag_default-text)',
|
||||||
|
'toggle': {
|
||||||
|
'on': 'var(--theme--ui_toggle-on)',
|
||||||
|
'off': 'var(--theme--ui_toggle-off)',
|
||||||
|
'feature': 'var(--theme--ui_toggle-feature)',
|
||||||
|
},
|
||||||
|
'accent': {
|
||||||
|
'blue': 'var(--theme--accent_blue)',
|
||||||
|
'blue-hover': 'var(--theme--accent_blue-hover)',
|
||||||
|
'blue-active': 'var(--theme--accent_blue-active)',
|
||||||
|
'blue-text': 'var(--theme--accent_blue-text)',
|
||||||
|
'red': 'var(--theme--accent_red)',
|
||||||
|
'red-hover': 'var(--theme--accent_red-hover)',
|
||||||
|
'red-text': 'var(--theme--accent_red-text)',
|
||||||
|
},
|
||||||
|
'grey': mapColorVariables('grey'),
|
||||||
|
'brown': mapColorVariables('brown'),
|
||||||
|
'orange': mapColorVariables('orange'),
|
||||||
|
'yellow': mapColorVariables('yellow'),
|
||||||
|
'green': mapColorVariables('green'),
|
||||||
|
'blue': mapColorVariables('blue'),
|
||||||
|
'purple': mapColorVariables('purple'),
|
||||||
|
'pink': mapColorVariables('pink'),
|
||||||
|
'red': mapColorVariables('red'),
|
||||||
|
},
|
||||||
|
extend: {
|
||||||
|
width: {
|
||||||
|
'full-96': 'calc(100% - 24rem)',
|
||||||
|
},
|
||||||
|
maxHeight: {
|
||||||
|
'full-16': 'calc(100% - 4rem)',
|
||||||
|
'full-32': 'calc(100% - 8rem)',
|
||||||
|
'full-48': 'calc(100% - 12rem)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: customClasses,
|
||||||
|
});
|
||||||
|
|
||||||
|
tw`hidden ${Object.keys(customClasses).join(' ')}`;
|
||||||
|
|
||||||
|
export { tw };
|
@ -2,7 +2,7 @@
|
|||||||
"name": "tweaks",
|
"name": "tweaks",
|
||||||
"id": "5174a483-c88d-4bf8-a95f-35cd330b76e2",
|
"id": "5174a483-c88d-4bf8-a95f-35cd330b76e2",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"description": "common style/layout changes and custom inserts.",
|
"description": "common style/layout changes and custom CSS insertion.",
|
||||||
"tags": ["extension", "customisation"],
|
"tags": ["extension", "customisation"],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@ -6,47 +6,45 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function openEnhancerMenu() {
|
async function focusMenu() {
|
||||||
chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => {
|
const tabs = await chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }),
|
||||||
const enhancerMenuURL = chrome.runtime.getURL(
|
url = chrome.runtime.getURL('repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.html'),
|
||||||
'repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.html'
|
menu = tabs.find((tab) => tab.url.startsWith(url));
|
||||||
),
|
if (menu) {
|
||||||
enhancerMenuTab = tabs.find((tab) => tab.url.startsWith(enhancerMenuURL));
|
chrome.tabs.highlight({ 'tabs': menu.index });
|
||||||
if (enhancerMenuTab) {
|
} else chrome.tabs.create({ url });
|
||||||
chrome.tabs.highlight({ 'tabs': enhancerMenuTab.index });
|
|
||||||
} else chrome.tabs.create({ url: enhancerMenuURL });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
chrome.action.onClicked.addListener(openEnhancerMenu);
|
chrome.action.onClicked.addListener(focusMenu);
|
||||||
|
|
||||||
function focusNotion() {
|
async function focusNotion() {
|
||||||
chrome.tabs.query(
|
const tabs = await chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }),
|
||||||
{ url: 'https://*.notion.so/*', windowId: chrome.windows.WINDOW_ID_CURRENT },
|
notion = tabs.find(
|
||||||
(tabs) => {
|
(tab) =>
|
||||||
if (tabs.length) {
|
new URL(tab.url).host.endsWith('.notion.so') ||
|
||||||
chrome.tabs.highlight({ 'tabs': tabs[0].index });
|
new URL(tab.url).host.endsWith('.notion.site')
|
||||||
} else chrome.tabs.create({ url: 'https://notion.so/' });
|
);
|
||||||
}
|
if (notion) {
|
||||||
);
|
chrome.tabs.highlight({ 'tabs': notion.index });
|
||||||
|
} else chrome.tabs.create({ url: 'https://notion.so/' });
|
||||||
}
|
}
|
||||||
|
|
||||||
function reload() {
|
async function reload() {
|
||||||
chrome.tabs.query({ url: 'https://*.notion.so/*' }, (tabs) => {
|
const tabs = await chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }),
|
||||||
(tabs || []).forEach((tab) => chrome.tabs.reload(tab.id));
|
menu = chrome.runtime.getURL('repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.html');
|
||||||
});
|
tabs.forEach((tab) => {
|
||||||
chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => {
|
const url = new URL(tab.url),
|
||||||
const enhancerMenuURL = chrome.runtime.getURL(
|
matches =
|
||||||
'repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.html'
|
url.host.endsWith('.notion.so') ||
|
||||||
),
|
url.host.endsWith('.notion.site') ||
|
||||||
enhancerMenuTabs = (tabs || []).filter((tab) => tab.url.startsWith(enhancerMenuURL));
|
tab.url.startsWith(menu);
|
||||||
enhancerMenuTabs.forEach((tab) => chrome.tabs.reload(tab.id));
|
if (matches) chrome.tabs.reload(tab.id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||||
switch (request.action) {
|
switch (request.action) {
|
||||||
case 'openEnhancerMenu':
|
case 'focusMenu':
|
||||||
openEnhancerMenu();
|
focusMenu();
|
||||||
break;
|
break;
|
||||||
case 'focusNotion':
|
case 'focusNotion':
|
||||||
focusNotion();
|
focusNotion();
|
||||||
|
Loading…
Reference in New Issue
Block a user