/* * notion-enhancer core: menu * (c) 2021 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ 'use strict'; const _id = 'a6621988-551d-495a-97d8-3c568bca2e9e'; import { env, storage, web, fmt, fs, registry } from '../../helpers.js'; for (let mod of await registry.get()) { for (let sheet of mod.css?.menu || []) { web.loadStyleset(`repo/${mod._dir}/${sheet}`); } } document.querySelector('img[data-target="notion"]').addEventListener('click', env.focusNotion); web.hotkeyListener(['Ctrl', 'Alt', 'E'], env.focusNotion); const components = {}; components.card = { preview: ({ preview = '' }) => web.createElement(web.html``), name: ({ name, id, version }) => web.createElement(web.html``), tags: ({ tags = [] }) => web.createElement(web.html``), description: ({ description }) => web.createElement( web.html`

${fmt.md.renderInline( description )}

` ), authors: ({ authors }) => web.createElement(web.html``), expand: async ({ id }) => web.createElement( web.html`

${await fs.getText('icons/fontawesome/long-arrow-alt-right.svg')} settings & documentation

` ), async _generate(mod) { const card = web.createElement(web.html`
`), body = web.createElement(web.html`
`); card.append(this.preview(mod)); body.append(this.name(mod)); body.append(this.tags(mod)); body.append(this.description(mod)); body.append(this.authors(mod)); body.append(await this.expand(mod)); card.append(body); return card; }, }; components.options = { toggle: (id, { key, label, value }) => web.createElement(web.html``), select: async (id, { key, label, values }) => web.createElement(web.html``), text(id, { key, label, value }) { const opt = web.createElement(web.html``); opt.querySelector('textarea').addEventListener('input', (ev) => { ev.target.style.removeProperty('--txt--scroll-height'); ev.target.style.setProperty('--txt--scroll-height', ev.target.scrollHeight + 'px'); }); return opt; }, number: (id, { key, label, value }) => web.createElement(web.html``), async file(id, { key, label, extensions }) { const opt = web.createElement(web.html``); opt.querySelector('input').addEventListener('change', (ev) => { opt.querySelector('.library--file_path').innerText = ev.target.files[0].name; }); return opt; }, async _generate(mod) { const card = await components.card._generate(mod); card.querySelector('.library--expand').remove(); if (mod.options && mod.options.length) { const options = web.createElement(web.html`
`), inputs = await Promise.all(mod.options.map((opt) => this[opt.type](mod.id, opt))); inputs.forEach((opt) => options.append(opt)); card.append(options); } return card; }, }; components.documentation = { buttons: async ({ _dir }) => web.createElement(web.html`

${await fs.getText('icons/fontawesome/long-arrow-alt-left.svg')} back to library ${await fs.getText('icons/fontawesome/code.svg')} view source code

`), readme: async (mod) => { const readme = web.createElement(web.html`
${ (await fs.isFile(`repo/${mod._dir}/README.md`)) ? fmt.md.render(await fs.getText(`repo/${mod._dir}/README.md`)) : '' }
`); fmt.Prism.highlightAllUnder(readme); return readme; }, }; const views = { $container: document.querySelector('[data-container]'), _router(event) { event.preventDefault(); let anchor, i = 0; do { anchor = event.path[i]; i++; } while (anchor.nodeName !== 'A'); if (location.search !== anchor.getAttribute('href')) { window.history.pushState( { search: anchor.getAttribute('href'), hash: '' }, '', anchor.href ); this._load(); } }, _navigator(event) { event.preventDefault(); const hash = event.target.getAttribute('href').slice(1); document.getElementById(hash).scrollIntoView(true); document.documentElement.scrollTop = 0; history.replaceState({ search: location.search, hash }, null, `#${hash}`); }, _reset() { document .querySelectorAll('a[href^="?"]') .forEach((a) => a.removeEventListener('click', this._router)); document .querySelectorAll('a[href^="#"]') .forEach((a) => a.removeEventListener('click', this._navigator)); this.$container.style.opacity = 0; return new Promise((res, rej) => { setTimeout(() => { this.$container.innerHTML = ''; this.$container.style.opacity = ''; this.$container.dataset.container = ''; document.querySelector('[data-target][data-active]')?.removeAttribute('data-active'); res(); }, 200); }); }, async _load() { await this._reset(); const search = new Map( location.search .slice(1) .split('&') .map((query) => query.split('=')) ); switch (search.get('view')) { case 'alerts': await this.alerts(); break; case 'mod': const mod = (await registry.get()).find((mod) => mod.id === search.get('id')); if (mod) { await this.mod(mod); break; } case 'library': await this.library(); break; default: window.history.replaceState( { search: '?view=library', hash: '' }, null, '?view=library' ); return this._load(); } setTimeout(() => { document.getElementById(location.hash.slice(1))?.scrollIntoView(true); document.documentElement.scrollTop = 0; }, 50); document .querySelectorAll('img') .forEach((img) => (img.onerror = (ev) => ev.target.remove())); document .querySelectorAll('a[href^="?"]') .forEach((a) => a.addEventListener('click', this._router)); document .querySelectorAll('a[href^="#"]') .forEach((a) => a.addEventListener('click', this._navigator)); }, async alerts() { this.$container.dataset.container = 'alerts'; document.querySelector('header [data-target="alerts"]').dataset.active = true; for (let mod of await registry.get()) this.$container.append(await components.card._generate(mod)); }, async mod(mod) { this.$container.dataset.container = 'mod'; document.querySelector('header [data-target="library"]').dataset.active = true; this.$container.append(await components.documentation.buttons(mod)); this.$container.append(await components.options._generate(mod)); this.$container.append(await components.documentation.readme(mod)); }, async library() { this.$container.dataset.container = 'library'; document.querySelector('header [data-target="library"]').dataset.active = true; for (let mod of await registry.get()) this.$container.append(await components.card._generate(mod)); }, }; views._router = views._router.bind(views); views._navigator = views._navigator.bind(views); views._load(); window.addEventListener('popstate', (ev) => { if (ev.state) views._load(); }); async function theme() { document.documentElement.className = `notion-${ (await storage.get(_id, 'theme')) || 'dark' }-theme`; } window.addEventListener('focus', theme); theme(); // registry.errors().then((err) => { // document.querySelector('[data-section="alerts"]').innerHTML = JSON.stringify(err); // });