v0.11.0
							
								
								
									
										20
									
								
								extension/.github/workflows/submodules.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,20 @@ | |||||||
|  | name: 'update submodules' | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   workflow_dispatch: | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   sync: | ||||||
|  |     name: 'update submodules' | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - name: checkout repo | ||||||
|  |         uses: actions/checkout@v2 | ||||||
|  |         with: | ||||||
|  |           submodules: true | ||||||
|  |       - name: pull updates | ||||||
|  |         run: | | ||||||
|  |           git pull --recurse-submodules | ||||||
|  |           git submodule update --remote --recursive | ||||||
|  |       - name: commit changes | ||||||
|  |         uses: stefanzweifel/git-auto-commit-action@v4 | ||||||
							
								
								
									
										13
									
								
								extension/.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -1,3 +1,16 @@ | |||||||
| [submodule "api"] | [submodule "api"] | ||||||
| 	path = api | 	path = api | ||||||
| 	url = git@github.com:notion-enhancer/api.git | 	url = git@github.com:notion-enhancer/api.git | ||||||
|  | 	branch = dev | ||||||
|  | [submodule "repo"] | ||||||
|  | 	path = repo | ||||||
|  | 	url = git@github.com:notion-enhancer/repo.git | ||||||
|  | 	branch = dev | ||||||
|  | [submodule "media"] | ||||||
|  | 	path = media | ||||||
|  | 	url = git@github.com:notion-enhancer/media.git | ||||||
|  | 	branch = main | ||||||
|  | [submodule "dep"] | ||||||
|  | 	path = dep | ||||||
|  | 	url = git@github.com:notion-enhancer/dep.git | ||||||
|  | 	branch = main | ||||||
|  | |||||||
| @ -1,361 +0,0 @@ | |||||||
| # changelog |  | ||||||
| 
 |  | ||||||
| ### v0.11.0 (dev) |  | ||||||
| 
 |  | ||||||
| a complete rework of the enhancer including a port to the browser as a chrome extension. |  | ||||||
| 
 |  | ||||||
| - new: cross-environment and properly documented api to replace helpers. |  | ||||||
| - new: cross-environment mod loader structure. |  | ||||||
| - new: notifications sourced from an online endpoint for sending global user alerts. |  | ||||||
| - new: simplify user installs by depending on the chrome web store and [notion-repackaged](https://github.com/notion-enhancer/notion-repackaged). |  | ||||||
| - new: separate menu profiles for mod configurations. |  | ||||||
| - new: a hotkey option type that allows typing in/pressing a hotkey to enter it, instead of typing. |  | ||||||
| - improved: split the core mod into separate mods for specific features. |  | ||||||
| - improved: theming variables that are more specific, less laggy, and less complicated. |  | ||||||
| - improved: merged bracketed-links into tweaks. |  | ||||||
| - improved: a redesigned menu with nicer ui, separate categories for mods and a sidebar for configuration. |  | ||||||
| - removed: integrated scrollbar tweak (notion now includes by default). |  | ||||||
| - removed: js insert. css insert moved to tweaks mod. |  | ||||||
| - removed: majority of layout and font size variables - better to leave former to notion and use `ctrl +` for latter. |  | ||||||
| - bugfix: bypass csp restrictions. |  | ||||||
| 
 |  | ||||||
| **below this point the enhancer was desktop-only. in v0.11.0 it was been ported to also** |  | ||||||
| **run as a chrome extension. changes made to both are indicated above.** |  | ||||||
| 
 |  | ||||||
| ### v0.10.2 (2020-12-05) |  | ||||||
| 
 |  | ||||||
| again, an emergency release for bugfixes. |  | ||||||
| not properly documented and new features have not yet been fully reviewed/edited. |  | ||||||
| 
 |  | ||||||
| - new: side panel - adds an extra sidebar on the right for use by other mods, |  | ||||||
|   toggleable with `ctrl+shift+backslash`. |  | ||||||
| - improved: notion icons uses spritesheets for faster loading of icons. |  | ||||||
| - improved: icon sets can be hidden/toggled. |  | ||||||
| - improved: toggles in the enhancer menu follow the same style as notion's toggles. |  | ||||||
| - improved: separate quote font variable & option in the font chooser mod (`--theme_[dark|light]--font_quote`). |  | ||||||
| - improved: option to hide the "page details" text for the word counter extension. |  | ||||||
| - bugfix: notion icons tab is now visible in fullpage databases. |  | ||||||
| - bugfix: code line numbers handles wrapped code blocks. |  | ||||||
| - bugfix: file explorer no longer opens when enhancer menu is opened. |  | ||||||
| - bugfix: enable the remote module in webviews (windows/tabs) for compatibility with the |  | ||||||
|   updated version of electron used by new notion builds (>= 2.0.10). |  | ||||||
| - bugfix: add support for enhancing an `app` folder if there is no `app.asar` file present. |  | ||||||
| - extension: "outliner" = table of contents in right sidebar. |  | ||||||
| - extension: "panel sites" = embed sites on the site panel. |  | ||||||
| - extension: "indentation lines" = adds vertical relationship lines to make list trees easier to follow. |  | ||||||
| - extension: "truncated table titles" = see the full text of the truncated table titles on hover over. |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.10.2` |  | ||||||
| 
 |  | ||||||
| ### v0.10.1 (2020-11-18) |  | ||||||
| 
 |  | ||||||
| essentially a prerelease for v0.11.0: pushed out for urgent bugfixes during |  | ||||||
| exam/study weeks when there's no time to code a full release. |  | ||||||
| 
 |  | ||||||
| note that this means new features have not yet been fully documented and |  | ||||||
| may not be fully ready for ideal use yet. however, things overall will |  | ||||||
| work more reliably than v0.10.0. |  | ||||||
| 
 |  | ||||||
| - new: different css entrypoints for different components (tabs, menu, app). |  | ||||||
| - improved: use an svg for the scroll-to-top button. |  | ||||||
| - improved: use a better-matching icon and add transitions to the property layout toggle. |  | ||||||
| - improved: themes are directly applied to tabs and menu rather than sync-ed between (infinite loading). |  | ||||||
| - improved: error message "is notion running?" --> clearer "make sure notion isn't running!" |  | ||||||
| - improved: auto-shrink system for tabs (max of 15 open in a window). |  | ||||||
| - bugfix: disable fadein of selected block halo with snappy transitions. |  | ||||||
| - bugfix: increase contrast of `--theme_dark--interactive_hover` in dark+ and dracula. |  | ||||||
| - bugfix: tabs are focused properly for input. |  | ||||||
| - bugfix: keyboard shortcut listeners are stricter so they don't conflict. |  | ||||||
| - bugfix: dots indicating draggability are no longer next to the tabs mod in the menu. |  | ||||||
| - bugfix: prevent empty hotkeys from triggering every keypress. |  | ||||||
| - bugfix: don't try loading an empty default page url (infinite loading). |  | ||||||
| - bugfix: remove `* { z-index: 1}` rule so format dropdowns in table view can be opened. |  | ||||||
| - extension: "topbar icons" = replaces the topbar buttons with icons. |  | ||||||
| - extension: "code line numbers" = adds line numbers to code blocks. |  | ||||||
| - extension: "notion icons" = use custom icon sets directly in notion. |  | ||||||
| - tweak: vertical indentation/relationship lines for lists. |  | ||||||
| - tweak: scroll database toolbars horizontally if partially hidden. |  | ||||||
| - tweak: condense bullet points (decrease line spacing). |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.10.1` |  | ||||||
| 
 |  | ||||||
| ### v0.10.0 (2020-11-02) |  | ||||||
| 
 |  | ||||||
| a flexibility update. |  | ||||||
| 
 |  | ||||||
| - new: mods can be reordered in the menu to control what order styling/scripts are added/executed in. |  | ||||||
|   higher up on the list = higher priority of application = loaded last in order to override others. |  | ||||||
|   (excluding the core, which though pinned to the top of the list is always loaded first so theming |  | ||||||
|   variables can be modified.) |  | ||||||
| - new: relaunch button in tray menu. |  | ||||||
| - new: a core mod option for a default page id/url (all new windows will load it instead of the |  | ||||||
|   normal "most recent" page). |  | ||||||
| - new: css variables for increasing line spacing/paragraph margins. |  | ||||||
| - new: patch the notion:// url scheme/protocol to work on linux. |  | ||||||
| - new: menu shows theme conflicts + a core mod option to auto-resolve theme conflicts. |  | ||||||
| - new: a `-n` cli option. |  | ||||||
| - improved: menu will now respect integrated titlebar setting. |  | ||||||
| - improved: use keyup listeners instead of a globalShortcut for the enhancements menu toggle. |  | ||||||
| - improved: overwrite `app.asar.bak` if already exists (e.g. for app updates). |  | ||||||
| - improved: additional menu option descriptions on hover. |  | ||||||
| - improved: listen to prefers-color-scheme to better change theme in night shift. |  | ||||||
| - improved: platform-specific option overrides for features not required on macOS. |  | ||||||
| - improved: made extra padding at the bottom with the "focus mode" extension toggleable. |  | ||||||
| - bugfix: removed messenger emoji set as the provider no longer supports it. |  | ||||||
| - bugfix: remove shadow around light mode board headers. |  | ||||||
| - bugfix: properly detect/respond to `EACCES`/`EBUSY` errors. |  | ||||||
| - bugfix: night shift checks every interaction, |  | ||||||
|   will respond to system changes without any manual changes. |  | ||||||
| - bugfix: toc blocks can have text colours. |  | ||||||
| - bugfix: bypass preview extension works with the back/forward keyboard shortcuts. |  | ||||||
| - bugfix: (maybe) fix csp issues under proxy. |  | ||||||
| - bugfix: remove focus mode footer from neutral theme + better contrast in calendar views. |  | ||||||
| - bugfix: improvements to the colour theming, particularly to make real- and fake-light/dark |  | ||||||
|   modes (as applied by the night shift extension) look consistent. |  | ||||||
|   relevant variables (assuming all are prefixed by `--theme_[dark|light]--`): |  | ||||||
|   `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. |  | ||||||
| - bugfix: block text colour applies to text with backgrounds. |  | ||||||
| - bugfix: font applied to wrong mode with littlepig dark. |  | ||||||
| - bugfix: keep "empty" top bar visible in the menu. |  | ||||||
| - bugfix: set NSRequiresAquaSystemAppearance to false in /Applications/Notion.app/Contents/Info.plist |  | ||||||
|   so system dark/light mode can be properly detected. |  | ||||||
| - bugfix: make ctrl+f popover shadow less extreme. |  | ||||||
| - bugfix: "weekly" calendar view name made case insensitive. |  | ||||||
| - bugfix: re-show hidden windows when clicking on the dock. |  | ||||||
| - tweak: sticky table/list rows. |  | ||||||
| - theme: "material ocean" = an oceanic colour palette. |  | ||||||
| - theme: "cherry cola" = a delightfully plummy, cherry cola flavored theme. |  | ||||||
| - theme: "dracula" = a theme based on the popular dracula color palette |  | ||||||
|   originally by zeno rocha and friends. |  | ||||||
| - extension: "tabs" = have multiple notion pages open in a single window. tabs can be controlled |  | ||||||
|   with keyboard shortcuts and dragged/reordered within/between windows. |  | ||||||
| - extension: "scroll to top" = add an arrow above the help button to scroll back to the top of a page. |  | ||||||
| - extension: "tweaks" = common style/layout changes. includes: |  | ||||||
|   - new: make transitions snappy/0s. |  | ||||||
|   - new: in-page columns are disabled/wrapped and pages are wider when |  | ||||||
|     the window is narrower than 600px for improved responsiveness. |  | ||||||
|   - new: thicker bold text for better visibility. |  | ||||||
|   - new: more readable line spacing. |  | ||||||
|   - moved: smooth scrollbars. |  | ||||||
|   - moved: change dragarea height. |  | ||||||
|   - moved: hide help. |  | ||||||
| 
 |  | ||||||
| a fork of notion-deb-builder that does generate an app.asar has been created and is once again supported. |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.10.0` |  | ||||||
| 
 |  | ||||||
| ### v0.9.1 (2020-09-26) |  | ||||||
| 
 |  | ||||||
| - bugfix: font chooser will continue iterating through fonts after encountering a blank option. |  | ||||||
| - bugfix: block indents are no longer overriden. |  | ||||||
| - bugfix: neutral does not force full width pages. |  | ||||||
| - bugfix: bypass preview extension works with the back/forward arrows. |  | ||||||
| - bugfix: check all views on a page for a weekly calendar. |  | ||||||
| - bugfix: emoji sets no longer modifies the user agent = doesn't break hotkeys. |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.9.1` |  | ||||||
| 
 |  | ||||||
| ### v0.9.0 (2020-09-20) |  | ||||||
| 
 |  | ||||||
| a feature and cleanup update. |  | ||||||
| 
 |  | ||||||
| - improved: halved the number of css rules used -> much better performance. |  | ||||||
| - improved: font imports must be define in the `mod.js` so that they can also be used in |  | ||||||
|   the enhancements menu. |  | ||||||
| - improved: tiling window-manager support (can hide titlebars entirely without dragarea/buttons). |  | ||||||
| - improved: extensions menu search is now case insensitive and includes options, inputs and versions. |  | ||||||
|   the search box can also for focused with `CMD/CTRL+F`. |  | ||||||
| - improved: extensions menu filters shown either a ✓ or × to help understand the current state. |  | ||||||
| - improved: added individual text-colour rules for different background colours. |  | ||||||
| - improved: added variables for callout colouring. |  | ||||||
| - improved: replaced with `helpers.getNotion()` with the constant `helpers.__notion` to reduce |  | ||||||
|   repeated function calls. |  | ||||||
| - improved: added variables for page width. |  | ||||||
| - improved/bugfix: emoji sets extension should now work on macOS and will change user agent to use |  | ||||||
|   real emojis instead of downloading images when system default is selected. |  | ||||||
| - bugfix: enhancer settings should no longer reset on update (though this will not have |  | ||||||
|   effect until the release after this one). |  | ||||||
| - bugfix: blue select tags are no longer purple. |  | ||||||
| - bugfix: page titles now respond to small-text mode. |  | ||||||
| - bugfix: weekly calendar view height is now sized correctly according to its contents. |  | ||||||
| - bugfix: made the open enhancements menu hotkey configurable and changed the default to `ALT+E`. |  | ||||||
|   to remove conflict with the inline code highlight shortcut. |  | ||||||
| - bugfix: update property-layout to match notion changes again. |  | ||||||
| - bugfix: updated some of the tweak styling to match notion changes. |  | ||||||
| - bugfix: block-level text colours are now changed properly. |  | ||||||
| - bugfix: do not require data folder during installation, to prevent `sudo` attempting to |  | ||||||
|   create it in `/var/root/`. |  | ||||||
| - bugfix: bullet points/checkboxes will now align properly in the right-to-left extension. |  | ||||||
| - themes: "littlepig" (light + dark) = monospaced themes using emojis and colourful text. |  | ||||||
| - extension: "font chooser" = customize fonts. for each option, type in the name of the font you would like to use, |  | ||||||
|   or leave it blank to not change anything. |  | ||||||
| - extension: "always on top" = add an arrow/button to show the notion window on top of other windows |  | ||||||
|   even if it's not focused. |  | ||||||
| - extension: "calendar scroll" = add a button to scroll down to the current week in fullpage/infinite-scroll calendars. |  | ||||||
| - extension: "hide help button" = hide the help button if you don't need it. |  | ||||||
| - extension: "bypass preview" = go straight to the normal full view when opening a page. |  | ||||||
| - extension: "word counter" = add page details: word/character/sentence/block count & speaking/reading times. |  | ||||||
| 
 |  | ||||||
| notion-deb-builder has been discovered to not generate an app.asar and so is no longer supported. |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.9.0` |  | ||||||
| 
 |  | ||||||
| ### v0.8.5 (2020-08-29) |  | ||||||
| 
 |  | ||||||
| - bugfix: separate text highlight and select tag variables. |  | ||||||
| - bugfix: bypass CSP for the `enhancement://` protocol - was failing on some platforms? |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.8.5` |  | ||||||
| 
 |  | ||||||
| ### v0.8.4 (2020-08-29) |  | ||||||
| 
 |  | ||||||
| - bugfix: property-layout now works consistently with or without a banner. |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.8.4` |  | ||||||
| 
 |  | ||||||
| ### v0.8.3 (2020-08-29) |  | ||||||
| 
 |  | ||||||
| previous release was a mistake: it did as intended on linux, but broke windows. |  | ||||||
| this should achieve the same thing in a more compatible way. |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.8.3` |  | ||||||
| 
 |  | ||||||
| ### v0.8.2 (2020-08-28) |  | ||||||
| 
 |  | ||||||
| some things you just can't test until production... fixed the auto-installer |  | ||||||
| to use `./bin.js` instead of `notion-enhancer` |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.8.2` |  | ||||||
| 
 |  | ||||||
| ### v0.8.1 (2020-08-28) |  | ||||||
| 
 |  | ||||||
| a clarity and stability update. |  | ||||||
| 
 |  | ||||||
| - improved: more informative cli error messages (original ones can be accessed with the `-d/--dev` flag). |  | ||||||
| - bugfix: gallery variable didn't apply on fullpage. |  | ||||||
| - bugfix: date picker hid current date number. |  | ||||||
| - bugfix: small-text pages should now work as expected. |  | ||||||
| - bugfix: padding issues in page previews. |  | ||||||
| - bugfix: property-layout extension had been broken by internal notion changes. |  | ||||||
| - bugfix: linux installer path typo. |  | ||||||
| - bugfix: caret-color was being mistaken for color and block-level text colouring was broken. |  | ||||||
| - improved: auto-application on install. |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.8.1` |  | ||||||
| 
 |  | ||||||
| ### v0.8.0 (2020-08-27) |  | ||||||
| 
 |  | ||||||
| complete rewrite with node.js. |  | ||||||
| 
 |  | ||||||
| - new: simpler cli installation system (inc. commands: `apply`, `remove`, and `check`). |  | ||||||
| - new: mod loading system (easier to create new mods, adds to notion rather than overwriting). |  | ||||||
| - new: mod configuration menu. |  | ||||||
| - improved: more theming variable coverage - inc. light theme and sizing/spacing. |  | ||||||
| - bugfix: non-reproducable errors with python. |  | ||||||
| - bugfix: better launcher patching on linux. |  | ||||||
| - bugfix: fix frameless window issue introduced by notion desktop 2.0.9. |  | ||||||
| - extension: "custom inserts" = link files for small client-side tweaks. |  | ||||||
| - extension: "bracketed links" = render links surrounded with \[\[brackets]] instead of underlined. |  | ||||||
| - extension: "focus mode" = hide the titlebar/menubar if the sidebar is closed (will be shown on hover). |  | ||||||
| - theme: "dark+" = a vivid-colour near-black theme. |  | ||||||
| - theme: "neutral" = smoother colours and fonts, designed to be more pleasing to the eye. |  | ||||||
| - theme: "gameish" = a purple, "gamer-styled" theme with a blocky-font. |  | ||||||
| - theme: "pastel dark" = a smooth-transition true dark theme with a hint of pastel. |  | ||||||
| - extension: "emoji sets" = pick from a variety of emoji styles to use. |  | ||||||
| - extension: "night shift" = sync dark/light theme with the system (overrides normal theme setting). |  | ||||||
| - extension: "right-to-left" = enables auto rtl/ltr text direction detection. (ported from [github.com/obahareth/notion-rtl](https://github.com/obahareth/notion-rtl).) |  | ||||||
| - extension: "weekly view" = calendar views named "weekly" will show only the 7 days of this week. (ported from [github.com/adihd/notionweeklyview](https://github.com/adihd/notionweeklyview).)] |  | ||||||
| - extension: "property layout" = auto-collapse page properties that usually push down page content. (ported from [github.com/alexander-kazakov/notion-layout-extension](https://github.com/alexander-kazakov/notion-layout-extension).) |  | ||||||
| 
 |  | ||||||
| > 📥 `npm i -g notion-enhancer@0.8.0` |  | ||||||
| 
 |  | ||||||
| ### v0.7.0 (2020-07-09) |  | ||||||
| 
 |  | ||||||
| - new: tray option to use system default emojis (instead of twitter's emojiset). |  | ||||||
| - new: mac support (identical functionality to other platforms with the |  | ||||||
|   exception of the native minimise/maximise/close buttons being kept, as they integrate |  | ||||||
|   better with the OS while not being out-of-place in notion). |  | ||||||
| - new: notion-deb-builder support for linux. |  | ||||||
| - new: an alert will be shown if there is an update available for the enhancer. |  | ||||||
| - improved: replaced button symbols with svgs for multi-platform support. |  | ||||||
| - improved: window close button is now red on hover (thanks to [@torchatlas](https://github.com/torchatlas)). |  | ||||||
| - bugfix: `cleaner.py` patched for linux. |  | ||||||
| - bugfix: tray now operates as expected on linux. |  | ||||||
| - bugfix: odd mix of `\\` and `/` being used for windows filepaths. |  | ||||||
| - bugfix: app no longer crashes when sidebar is toggled. |  | ||||||
| 
 |  | ||||||
| > 📥 [notion-enhancer.v0.7.0.zip](https://github.com/notion-enhancer/notion-enhancer/archive/v0.7.0.zip) |  | ||||||
| 
 |  | ||||||
| ### v0.6.0 (2020-06-30) |  | ||||||
| 
 |  | ||||||
| - style: custom fonts. |  | ||||||
| - style: font resizing. |  | ||||||
| - style: hide discussions (thanks to [u/Roosmaryn](https://www.reddit.com/user/Roosmaryn/)). |  | ||||||
| - new: custom colour theming, demonstrated via the dark+ theme. |  | ||||||
| - new: linux support (thanks to [@Blacksuan19](https://github.com/Blacksuan19)). |  | ||||||
| - improved: if hotkey is pressed while notion is unfocused, it will bring it to the front rather than hiding it. |  | ||||||
| - improved: stop window buttons breaking at smaller widths. |  | ||||||
| - improved: more obviously visible drag area. |  | ||||||
| - bugfix: specify UTF-8 encoding to prevent multibyte/gbk codec errors (thanks to [@etnperlong](https://github.com/etnperlong)). |  | ||||||
| 
 |  | ||||||
| > 📥 [notion-enhancer.v0.6.0.zip](https://github.com/notion-enhancer/notion-enhancer/archive/v0.6.0.zip) |  | ||||||
| 
 |  | ||||||
| ### v0.5.0 (2020-05-23) |  | ||||||
| 
 |  | ||||||
| - new: running from the wsl. |  | ||||||
| - new: reload window with f5. |  | ||||||
| - improved: code has been refactored and cleaned up, |  | ||||||
|   inc. file renaming and a `customiser.py` that doesn't require |  | ||||||
|   a run of `cleaner.py` to build modifications. |  | ||||||
|   improved: scrollbar colours that fit better with notion's theming. |  | ||||||
| - bugfix: un-break having multiple notion windows open. |  | ||||||
| 
 |  | ||||||
| > 📥 [notion-enhancer.v0.5.0.zip](https://github.com/notion-enhancer/notion-enhancer/archive/v0.5.0.zip) |  | ||||||
| 
 |  | ||||||
| **development here taken over by [@dragonwocky](https://github.com/dragonwocky).** |  | ||||||
| 
 |  | ||||||
| **the ~~crossed out~~ features below are no longer features included by default,** |  | ||||||
| **but can still easily be added as [custom tweaks](https://github.com/notion-enhancer/tweaks).** |  | ||||||
| 
 |  | ||||||
| ### v0.4.1 (2020-02-13) |  | ||||||
| 
 |  | ||||||
| - bugfix: wider table & the "+" button not working in database pages. |  | ||||||
| 
 |  | ||||||
| > 📥 [notion-enhancer.v4.1.zip](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d239a3cf-d553-4ef3-ab04-8b47892d9f9a/Notion_Customization_v4.1.zip) |  | ||||||
| 
 |  | ||||||
| ### v0.4.0 |  | ||||||
| 
 |  | ||||||
| - new: tray icon. |  | ||||||
| - new: app startup options (+ saving). |  | ||||||
| - new: `Reset.py` |  | ||||||
| - improved: better output from `Customization Patcher.py`. |  | ||||||
| - bugfix: wider tables in "short page" mode. |  | ||||||
| - bugfix: unclickable buttons/draggable area (of titlebar). |  | ||||||
| 
 |  | ||||||
| ### v0.3.0 |  | ||||||
| 
 |  | ||||||
| - new: show/hide window hotkey. |  | ||||||
| - new: app startup options. |  | ||||||
| - ~~style: smaller table icons.~~ |  | ||||||
| 
 |  | ||||||
| > 📥 [notion-enhancer.v3.zip](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b01aa446-5727-476a-a25e-395472bfb1be/NotionScriptsV3.zip) |  | ||||||
| 
 |  | ||||||
| ### v0.2.0 |  | ||||||
| 
 |  | ||||||
| - new: light/dark theme support for window control buttons + scrollbars. |  | ||||||
| - new: custom styles directly linked to the enhancer resources + compatible with web version. |  | ||||||
| - ~~improved: making table column width go below 100px.~~ |  | ||||||
| 
 |  | ||||||
| ### v0.1.0 |  | ||||||
| 
 |  | ||||||
| - new: custom window control buttons. |  | ||||||
| - removed: default titlebar/menubar. |  | ||||||
| - ~~removed: huge padding of board view.~~ |  | ||||||
| - ~~removed: huge padding of table view.~~ |  | ||||||
| - ~~optional: making table column width go below 100px.~~ |  | ||||||
| - ~~style: thinner cover image + higher content block.~~ |  | ||||||
| - style: scrollbars. |  | ||||||
| @ -1,13 +1,5 @@ | |||||||
| # extension | # notion-enhancer/extension | ||||||
| 
 | 
 | ||||||
| bringing all your favourite notion-enhancer features to the browser (wip) | an enhancer/customiser for the all-in-one productivity workspace notion.so (browser) | ||||||
| 
 | 
 | ||||||
| > considering that using notion in the browser is more lightweight & probably preferred for some people since it means they have less apps open, i've always planned to eventually port the enhancer to be a chrome extension. | [read the docs online](https://notion-enhancer.github.io/) | ||||||
| > |  | ||||||
| > since the enhancer focuses on being able to manipulate notion's app files, it's not going to be a very friendly transfer to web - a few features will have to be lost (e.g. frameless mode & tabs, of course) and the extensions system will need to be completely rebuilt. |  | ||||||
| > |  | ||||||
| > to make this work better, i'm splitting things up: an mod repository, a chrome extension, and an app loader. |  | ||||||
| > |  | ||||||
| > i'll be building the enhancer chrome-first from now on, since it'll be more limited there (and it's easier to add extra features when porting than to take features out), and then releasing the app loader a little afterwards. both the app loader and the chrome extension will source the same themes & extensions from the mod repository, and updates & releases of individual mods won't require waiting for the enhancer version anymore. |  | ||||||
| 
 |  | ||||||
| -- from the #announcements channel of the [notion-enhancer discord](https://discord.gg/sFWPXtA) |  | ||||||
|  | |||||||
| @ -1 +1 @@ | |||||||
| Subproject commit 5030fe2b0fd71b397796b055934ec50f7e909a5c | Subproject commit 9815d73b9277e96864654a8d8dd48762039c9845 | ||||||
							
								
								
									
										1
									
								
								extension/dep
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
							
						
						| @ -0,0 +1 @@ | |||||||
|  | Subproject commit 1a4762550fe185706be26678f734b0475066c3e4 | ||||||
| Before Width: | Height: | Size: 59 KiB | 
							
								
								
									
										6
									
								
								extension/dep/jscolor.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
							
								
								
									
										12
									
								
								extension/dep/markdown-it.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
							
								
								
									
										13
									
								
								extension/dep/prism.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -1,58 +0,0 @@ | |||||||
| /** |  | ||||||
|  * style-vendorizer v2.0.0 |  | ||||||
|  * @license MIT |  | ||||||
|  * @source https://unpkg.com/style-vendorizer@^2.0.0?module
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| var i = new Map([ |  | ||||||
|   ['align-self', '-ms-grid-row-align'], |  | ||||||
|   ['color-adjust', '-webkit-print-color-adjust'], |  | ||||||
|   ['column-gap', 'grid-column-gap'], |  | ||||||
|   ['gap', 'grid-gap'], |  | ||||||
|   ['grid-template-columns', '-ms-grid-columns'], |  | ||||||
|   ['grid-template-rows', '-ms-grid-rows'], |  | ||||||
|   ['justify-self', '-ms-grid-column-align'], |  | ||||||
|   ['margin-inline-end', '-webkit-margin-end'], |  | ||||||
|   ['margin-inline-start', '-webkit-margin-start'], |  | ||||||
|   ['overflow-wrap', 'word-wrap'], |  | ||||||
|   ['padding-inline-end', '-webkit-padding-end'], |  | ||||||
|   ['padding-inline-start', '-webkit-padding-start'], |  | ||||||
|   ['row-gap', 'grid-row-gap'], |  | ||||||
|   ['scroll-margin-bottom', 'scroll-snap-margin-bottom'], |  | ||||||
|   ['scroll-margin-left', 'scroll-snap-margin-left'], |  | ||||||
|   ['scroll-margin-right', 'scroll-snap-margin-right'], |  | ||||||
|   ['scroll-margin-top', 'scroll-snap-margin-top'], |  | ||||||
|   ['scroll-margin', 'scroll-snap-margin'], |  | ||||||
|   ['text-combine-upright', '-ms-text-combine-horizontal'], |  | ||||||
| ]); |  | ||||||
| function r(r) { |  | ||||||
|   return i.get(r); |  | ||||||
| } |  | ||||||
| function n(i) { |  | ||||||
|   var r = |  | ||||||
|     /^(?:(text-(?:decoration$|e|or|si)|back(?:ground-cl|d|f)|box-d|(?:mask(?:$|-[ispro]|-cl)))|(tab-|column(?!-s)|text-align-l)|(ap)|(u|hy))/i.exec( |  | ||||||
|       i |  | ||||||
|     ); |  | ||||||
|   return r ? (r[1] ? 1 : r[2] ? 2 : r[3] ? 3 : 5) : 0; |  | ||||||
| } |  | ||||||
| function t(i, r) { |  | ||||||
|   var n = /^(?:(pos)|(background-i)|((?:max-|min-)?(?:block-s|inl|he|widt))|(dis))/i.exec(i); |  | ||||||
|   return n |  | ||||||
|     ? n[1] |  | ||||||
|       ? /^sti/i.test(r) |  | ||||||
|         ? 1 |  | ||||||
|         : 0 |  | ||||||
|       : n[2] |  | ||||||
|       ? /^image-/i.test(r) |  | ||||||
|         ? 1 |  | ||||||
|         : 0 |  | ||||||
|       : n[3] |  | ||||||
|       ? '-' === r[3] |  | ||||||
|         ? 2 |  | ||||||
|         : 0 |  | ||||||
|       : /^(inline-)?grid$/i.test(r) |  | ||||||
|       ? 4 |  | ||||||
|       : 0 |  | ||||||
|     : 0; |  | ||||||
| } |  | ||||||
| export { r as cssPropertyAlias, n as cssPropertyPrefixFlags, t as cssValuePrefixFlags }; |  | ||||||
| @ -1,43 +0,0 @@ | |||||||
| /** |  | ||||||
|  * Twind v0.16.16 |  | ||||||
|  * @license MIT |  | ||||||
|  * @source https://unpkg.com/@twind/content@0.1.0/content.js?module
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| import { directive as o } from './twind.mjs'; |  | ||||||
| var c = new Set([ |  | ||||||
|     'open-quote', |  | ||||||
|     'close-quote', |  | ||||||
|     'no-open-quote', |  | ||||||
|     'no-close-quote', |  | ||||||
|     'normal', |  | ||||||
|     'none', |  | ||||||
|     'inherit', |  | ||||||
|     'initial', |  | ||||||
|     'unset', |  | ||||||
|   ]), |  | ||||||
|   n = (t) => t.join('-'), |  | ||||||
|   s = (t) => { |  | ||||||
|     switch (t[0]) { |  | ||||||
|       case 'data': |  | ||||||
|         return `attr(${n(t)})`; |  | ||||||
|       case 'attr': |  | ||||||
|       case 'counter': |  | ||||||
|         return `${t[0]}(${n(t.slice(1))})`; |  | ||||||
|       case 'var': |  | ||||||
|         return `var(--${n(t)})`; |  | ||||||
|       case void 0: |  | ||||||
|         return 'attr(data-content)'; |  | ||||||
|       default: |  | ||||||
|         return JSON.stringify(n(t)); |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   i = (t, { theme: r }) => { |  | ||||||
|     let e = Array.isArray(t) ? n(t) : t; |  | ||||||
|     return { |  | ||||||
|       content: |  | ||||||
|         (e && r('content', [e], '')) || (c.has(e) && e) || (Array.isArray(t) ? s(t) : e), |  | ||||||
|     }; |  | ||||||
|   }, |  | ||||||
|   u = (t, r) => (Array.isArray(t) ? i(t, r) : o(i, t)); |  | ||||||
| export { u as content }; |  | ||||||
| @ -1,134 +0,0 @@ | |||||||
| /** |  | ||||||
|  * Twind v0.16.16 |  | ||||||
|  * @license MIT |  | ||||||
|  * @source https://unpkg.com/twind@0.16.16/css/css.js?module
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| // src/css/index.ts
 |  | ||||||
| import { apply, hash, directive } from "./twind.mjs"; |  | ||||||
| 
 |  | ||||||
| // src/internal/util.ts
 |  | ||||||
| var includes = (value, search) => !!~value.indexOf(search); |  | ||||||
| var join = (parts, separator = "-") => parts.join(separator); |  | ||||||
| var hyphenate = value => value.replace(/[A-Z]/g, "-$&").toLowerCase(); |  | ||||||
| var evalThunk = (value, context) => { |  | ||||||
|   while (typeof value == "function") { |  | ||||||
|     value = value(context); |  | ||||||
|   } |  | ||||||
|   return value; |  | ||||||
| }; |  | ||||||
| var isCSSProperty = (key, value) => !includes("@:&", key[0]) && (includes("rg", (typeof value)[5]) || Array.isArray(value)); |  | ||||||
| var merge = (target, source, context) => source ? Object.keys(source).reduce((target2, key) => { |  | ||||||
|   const value = evalThunk(source[key], context); |  | ||||||
|   if (isCSSProperty(key, value)) { |  | ||||||
|     target2[hyphenate(key)] = value; |  | ||||||
|   } else { |  | ||||||
|     target2[key] = key[0] == "@" && includes("figa", key[1]) ? (target2[key] || []).concat(value) : merge(target2[key] || {}, value, context); |  | ||||||
|   } |  | ||||||
|   return target2; |  | ||||||
| }, target) : target; |  | ||||||
| var escape = typeof CSS !== "undefined" && CSS.escape || (className => className.replace(/[!"'`*+.,;:\\/<=>?@#$%&^|~()[\]{}]/g, "\\$&").replace(/^\d/, "\\3$& ")); |  | ||||||
| var buildMediaQuery = screen2 => { |  | ||||||
|   if (!Array.isArray(screen2)) { |  | ||||||
|     screen2 = [screen2]; |  | ||||||
|   } |  | ||||||
|   return "@media " + join(screen2.map(screen3 => { |  | ||||||
|     if (typeof screen3 == "string") { |  | ||||||
|       screen3 = { min: screen3 }; |  | ||||||
|     } |  | ||||||
|     return screen3.raw || join(Object.keys(screen3).map(feature => `(${feature}-width:${screen3[feature]})`), " and "); |  | ||||||
|   }), ","); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // src/css/index.ts
 |  | ||||||
| var translate = (tokens, context) => { |  | ||||||
|   const collect = (target, token) => Array.isArray(token) ? token.reduce(collect, target) : merge(target, evalThunk(token, context), context); |  | ||||||
|   return tokens.reduce(collect, {}); |  | ||||||
| }; |  | ||||||
| var newRule = /\s*(?:([\w-%@]+)\s*:?\s*([^{;]+?)\s*(?:;|$|})|([^;}{]*?)\s*{)|(})/gi; |  | ||||||
| var ruleClean = /\/\*[\s\S]*?\*\/|\s+|\n/gm; |  | ||||||
| var decorate = (selectors, currentBlock) => selectors.reduceRight((rules, selector) => ({ [selector]: rules }), currentBlock); |  | ||||||
| var saveBlock = (rules, selectors, currentBlock) => { |  | ||||||
|   if (currentBlock) { |  | ||||||
|     rules.push(decorate(selectors, currentBlock)); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| var interleave = (strings, interpolations, context) => { |  | ||||||
|   let buffer = strings[0]; |  | ||||||
|   const result = []; |  | ||||||
|   for (let index = 0; index < interpolations.length;) { |  | ||||||
|     const interpolation = evalThunk(interpolations[index], context); |  | ||||||
|     if (interpolation && typeof interpolation == "object") { |  | ||||||
|       result.push(buffer, interpolation); |  | ||||||
|       buffer = strings[++index]; |  | ||||||
|     } else { |  | ||||||
|       buffer += (interpolation || "") + strings[++index]; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   result.push(buffer); |  | ||||||
|   return result; |  | ||||||
| }; |  | ||||||
| var astish = (values, context) => { |  | ||||||
|   const selectors = []; |  | ||||||
|   const rules = []; |  | ||||||
|   let currentBlock; |  | ||||||
|   let match; |  | ||||||
|   for (let index = 0; index < values.length; index++) { |  | ||||||
|     const value = values[index]; |  | ||||||
|     if (typeof value == "string") { |  | ||||||
|       while (match = newRule.exec(value.replace(ruleClean, " "))) { |  | ||||||
|         if (!match[0]) |  | ||||||
|         continue; |  | ||||||
|         if (match[4]) { |  | ||||||
|           currentBlock = saveBlock(rules, selectors, currentBlock); |  | ||||||
|           selectors.pop(); |  | ||||||
|         } |  | ||||||
|         if (match[3]) { |  | ||||||
|           currentBlock = saveBlock(rules, selectors, currentBlock); |  | ||||||
|           selectors.push(match[3]); |  | ||||||
|         } else if (!match[4]) { |  | ||||||
|           if (!currentBlock) |  | ||||||
|           currentBlock = {}; |  | ||||||
|           const value2 = match[2] && /\S/.test(match[2]) ? match[2] : values[++index]; |  | ||||||
|           if (value2) { |  | ||||||
|             if (match[1] == "@apply") { |  | ||||||
|               merge(currentBlock, evalThunk(apply(value2), context), context); |  | ||||||
|             } else { |  | ||||||
|               currentBlock[match[1]] = value2; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       currentBlock = saveBlock(rules, selectors, currentBlock); |  | ||||||
|       rules.push(decorate(selectors, value)); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   saveBlock(rules, selectors, currentBlock); |  | ||||||
|   return rules; |  | ||||||
| }; |  | ||||||
| var cssFactory = (tokens, context) => translate(Array.isArray(tokens[0]) && Array.isArray(tokens[0].raw) ? astish(interleave(tokens[0], tokens.slice(1), context), context) : tokens, context); |  | ||||||
| var css = (...tokens) => directive(cssFactory, tokens); |  | ||||||
| var keyframesFactory = (tokens, context) => { |  | ||||||
|   const waypoints = cssFactory(tokens, context); |  | ||||||
|   const id = hash(JSON.stringify(waypoints)); |  | ||||||
|   context.tw(() => ({ [`@keyframes ${id}`]: waypoints })); |  | ||||||
|   return id; |  | ||||||
| }; |  | ||||||
| var keyframes = (...tokens) => directive(keyframesFactory, tokens); |  | ||||||
| var animation = (value, waypoints) => waypoints === void 0 ? (...args) => animation(value, keyframes(...args)) : css({ |  | ||||||
|   ...(value && typeof value == "object" ? value : { animation: value }), |  | ||||||
|   animationName: typeof waypoints == "function" ? waypoints : keyframes(waypoints) }); |  | ||||||
| 
 |  | ||||||
| var screenFactory = ({ size, rules }, context) => { |  | ||||||
|   const media = buildMediaQuery(context.theme("screens", size)); |  | ||||||
|   return rules === void 0 ? media : { |  | ||||||
|     [media]: typeof rules == "function" ? evalThunk(rules, context) : cssFactory([rules], context) }; |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| var screen = (size, rules) => directive(screenFactory, { size, rules }); |  | ||||||
| export { |  | ||||||
| animation, |  | ||||||
| css, |  | ||||||
| keyframes, |  | ||||||
| screen }; |  | ||||||
							
								
								
									
										5
									
								
								extension/env/env.mjs
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -6,10 +6,7 @@ | |||||||
| 
 | 
 | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| /** | /** environment-specific methods and constants */ | ||||||
|  * environment-specific methods and constants |  | ||||||
|  * @module notion-enhancer/api/env |  | ||||||
|  */ |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * the environment/platform name code is currently being executed in |  * the environment/platform name code is currently being executed in | ||||||
|  | |||||||
							
								
								
									
										9
									
								
								extension/env/fs.mjs
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -6,10 +6,7 @@ | |||||||
| 
 | 
 | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| /** | /** environment-specific file reading */ | ||||||
|  * environment-specific filesystem reading |  | ||||||
|  * @module notion-enhancer/api/fs |  | ||||||
|  */ |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * transform a path relative to the enhancer root directory into an absolute path |  * transform a path relative to the enhancer root directory into an absolute path | ||||||
| @ -21,7 +18,7 @@ export const localPath = chrome.runtime.getURL; | |||||||
| /** | /** | ||||||
|  * fetch and parse a json file's contents |  * fetch and parse a json file's contents | ||||||
|  * @param {string} path - a url or within-the-enhancer filepath |  * @param {string} path - a url or within-the-enhancer filepath | ||||||
|  * @param {object} [opts] - the second argument of a fetch() request |  * @param {object=} opts - the second argument of a fetch() request | ||||||
|  * @returns {object} the json value of the requested file as a js object |  * @returns {object} the json value of the requested file as a js object | ||||||
|  */ |  */ | ||||||
| export const getJSON = (path, opts = {}) => | export const getJSON = (path, opts = {}) => | ||||||
| @ -30,7 +27,7 @@ export const getJSON = (path, opts = {}) => | |||||||
| /** | /** | ||||||
|  * fetch a text file's contents |  * fetch a text file's contents | ||||||
|  * @param {string} path - a url or within-the-enhancer filepath |  * @param {string} path - a url or within-the-enhancer filepath | ||||||
|  * @param {object} [opts] - the second argument of a fetch() request |  * @param {object=} opts - the second argument of a fetch() request | ||||||
|  * @returns {string} the text content of the requested file |  * @returns {string} the text content of the requested file | ||||||
|  */ |  */ | ||||||
| export const getText = (path, opts = {}) => | export const getText = (path, opts = {}) => | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								extension/env/storage.mjs
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -6,18 +6,15 @@ | |||||||
| 
 | 
 | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| /** | /** environment-specific data persistence */ | ||||||
|  * environment-specific data persistence |  | ||||||
|  * @module notion-enhancer/api/storage |  | ||||||
|  */ |  | ||||||
| 
 | 
 | ||||||
| const _queue = [], | const _queue = [], | ||||||
|   _onChangeListeners = []; |   _onChangeListeners = []; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * get persisted data |  * get persisted data | ||||||
|  * @param {array<string>} path - the path of keys to the value being fetched |  * @param {string[]} path - the path of keys to the value being fetched | ||||||
|  * @param {*} [fallback] - a default value if the path is not matched |  * @param {unknown=} fallback - a default value if the path is not matched | ||||||
|  * @returns {Promise} value ?? fallback |  * @returns {Promise} value ?? fallback | ||||||
|  */ |  */ | ||||||
| export const get = (path, fallback = undefined) => { | export const get = (path, fallback = undefined) => { | ||||||
| @ -39,8 +36,8 @@ export const get = (path, fallback = undefined) => { | |||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * persist data |  * persist data | ||||||
|  * @param {array<string>} path - the path of keys to the value being set |  * @param {string[]} path - the path of keys to the value being set | ||||||
|  * @param {*} value - the data to save |  * @param {unknown} value - the data to save | ||||||
|  * @returns {Promise} resolves when data has been saved |  * @returns {Promise} resolves when data has been saved | ||||||
|  */ |  */ | ||||||
| export const set = (path, value) => { | export const set = (path, value) => { | ||||||
| @ -68,7 +65,7 @@ export const set = (path, value) => { | |||||||
|         } |         } | ||||||
|         chrome.storage.local.set({ [namespace]: values[namespace] }, () => { |         chrome.storage.local.set({ [namespace]: values[namespace] }, () => { | ||||||
|           _onChangeListeners.forEach((listener) => |           _onChangeListeners.forEach((listener) => | ||||||
|             listener({ type: 'set', path: pathClone, new: value, old }) |             listener({ path: pathClone, new: value, old }) | ||||||
|           ); |           ); | ||||||
|           res(value); |           res(value); | ||||||
|         }); |         }); | ||||||
| @ -80,12 +77,13 @@ export const set = (path, value) => { | |||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * create a wrapper for accessing a partition of the storage |  * create a wrapper for accessing a partition of the storage | ||||||
|  * @param {array<string>} namespace - the path of keys to prefix all storage requests with |  * @param {string[]} namespace - the path of keys to prefix all storage requests with | ||||||
|  * @param {function} [get] - the storage get function to be wrapped |  * @param {function=} get - the storage get function to be wrapped | ||||||
|  * @param {function} [set] - the storage set function to be wrapped |  * @param {function=} set - the storage set function to be wrapped | ||||||
|  * @returns {object} an object with the wrapped get/set functions |  * @returns {object} an object with the wrapped get/set functions | ||||||
|  */ |  */ | ||||||
| export const db = (namespace, getFunc = get, setFunc = set) => { | export const db = (namespace, getFunc = get, setFunc = set) => { | ||||||
|  |   if (typeof namespace === 'string') namespace = [namespace]; | ||||||
|   return { |   return { | ||||||
|     get: (path = [], fallback = undefined) => getFunc([...namespace, ...path], fallback), |     get: (path = [], fallback = undefined) => getFunc([...namespace, ...path], fallback), | ||||||
|     set: (path, value) => setFunc([...namespace, ...path], value), |     set: (path, value) => setFunc([...namespace, ...path], value), | ||||||
| @ -112,9 +110,7 @@ export const removeChangeListener = (callback) => { | |||||||
| /** | /** | ||||||
|  * @callback onStorageChangeCallback |  * @callback onStorageChangeCallback | ||||||
|  * @param {object} event |  * @param {object} event | ||||||
|  * @param {string} event.type - 'set' or 'reset' |  * @param {string} event.path- the path of keys to the changed value | ||||||
|  * @param {string} event.namespace- the name of the store, e.g. a mod id |  * @param {string=} event.new - the new value being persisted to the store | ||||||
|  * @param {string} [event.key] - the key associated with the changed value |  * @param {string=} event.old - the previous value associated with the key | ||||||
|  * @param {string} [event.new] - the new value being persisted to the store |  | ||||||
|  * @param {string} [event.old] - the previous value associated with the key |  | ||||||
|  */ |  */ | ||||||
|  | |||||||
| Before Width: | Height: | Size: 55 KiB | 
| Before Width: | Height: | Size: 5.1 KiB | 
| Before Width: | Height: | Size: 623 B | 
| Before Width: | Height: | Size: 10 KiB | 
| Before Width: | Height: | Size: 1.3 KiB | 
| Before Width: | Height: | Size: 2.0 KiB | 
| Before Width: | Height: | Size: 21 KiB | 
| Before Width: | Height: | Size: 18 KiB | 
| Before Width: | Height: | Size: 5.3 KiB | 
| Before Width: | Height: | Size: 634 B | 
| Before Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 1.3 KiB | 
| Before Width: | Height: | Size: 2.0 KiB | 
| Before Width: | Height: | Size: 24 KiB | 
| Before Width: | Height: | Size: 24 KiB | 
							
								
								
									
										35
									
								
								extension/init.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,35 @@ | |||||||
|  | /* | ||||||
|  |  * notion-enhancer | ||||||
|  |  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 | ||||||
|  |  * (https://notion-enhancer.github.io/) under the MIT license
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | (async () => { | ||||||
|  |   const site = location.host.endsWith('.notion.site'), | ||||||
|  |     page = location.pathname.split(/[/-]/g).reverse()[0].length === 32, | ||||||
|  |     whitelisted = ['/', '/onboarding'].includes(location.pathname), | ||||||
|  |     signedIn = localStorage['LRU:KeyValueStore2:current-user-id']; | ||||||
|  | 
 | ||||||
|  |   if (site || page || (whitelisted && signedIn)) { | ||||||
|  |     const api = await import(chrome.runtime.getURL('api/index.mjs')), | ||||||
|  |       { fs, registry, web } = api; | ||||||
|  | 
 | ||||||
|  |     for (const mod of await registry.list((mod) => registry.enabled(mod.id))) { | ||||||
|  |       for (const sheet of mod.css?.client || []) { | ||||||
|  |         web.loadStylesheet(`repo/${mod._dir}/${sheet}`); | ||||||
|  |       } | ||||||
|  |       for (let script of mod.js?.client || []) { | ||||||
|  |         script = await import(fs.localPath(`repo/${mod._dir}/${script}`)); | ||||||
|  |         script.default(api, await registry.db(mod.id)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const errors = await registry.errors(); | ||||||
|  |     if (errors.length) { | ||||||
|  |       console.log('[notion-enhancer] registry errors:'); | ||||||
|  |       console.table(errors); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | })(); | ||||||
| @ -1,34 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| (async () => { |  | ||||||
|   if (location.pathname === '/') await new Promise((res, rej) => setTimeout(res, 500)); |  | ||||||
| 
 |  | ||||||
|   const site = location.host.endsWith('.notion.site'), |  | ||||||
|     page = location.pathname.split(/[/-]/g).reverse()[0].length === 32; |  | ||||||
| 
 |  | ||||||
|   if (site || page) { |  | ||||||
|     import(chrome.runtime.getURL('api/_.mjs')).then(async (api) => { |  | ||||||
|       const { fs, registry, web } = api; |  | ||||||
|       for (const mod of await registry.list((mod) => registry.enabled(mod.id))) { |  | ||||||
|         for (const sheet of mod.css?.client || []) { |  | ||||||
|           web.loadStylesheet(`repo/${mod._dir}/${sheet}`); |  | ||||||
|         } |  | ||||||
|         for (let script of mod.js?.client || []) { |  | ||||||
|           script = await import(fs.localPath(`repo/${mod._dir}/${script}`)); |  | ||||||
|           script.default(api, await registry.db(mod.id)); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       const errors = await registry.errors(); |  | ||||||
|       if (errors.length) { |  | ||||||
|         console.log('[notion-enhancer] registry errors:'); |  | ||||||
|         console.table(errors); |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| })(); |  | ||||||
| @ -6,32 +6,25 @@ | |||||||
|   "description": "an enhancer/customiser for the all-in-one productivity workspace notion.so", |   "description": "an enhancer/customiser for the all-in-one productivity workspace notion.so", | ||||||
|   "homepage_url": "https://notion-enhancer.github.io", |   "homepage_url": "https://notion-enhancer.github.io", | ||||||
|   "icons": { |   "icons": { | ||||||
|     "16": "icon/colour-x16.png", |     "16": "media/colour-x16.png", | ||||||
|     "32": "icon/colour-x32.png", |     "32": "media/colour-x32.png", | ||||||
|     "48": "icon/colour-x48.png", |     "48": "media/colour-x48.png", | ||||||
|     "128": "icon/colour-x128.png", |     "128": "media/colour-x128.png", | ||||||
|     "256": "icon/colour-x256.png", |     "256": "media/colour-x256.png", | ||||||
|     "512": "icon/colour-x512.png" |     "512": "media/colour-x512.png" | ||||||
|   }, |   }, | ||||||
|   "browser_action": {}, |   "browser_action": {}, | ||||||
|   "background": { "scripts": ["worker.js"] }, |   "background": { "scripts": ["worker.js"] }, | ||||||
|   "options_ui": { |   "options_ui": { | ||||||
|     "page": "repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.html", |     "page": "repo/menu/menu.html", | ||||||
|     "open_in_tab": true |     "open_in_tab": true | ||||||
|   }, |   }, | ||||||
|   "web_accessible_resources": ["env/*", "api/*", "dep/*", "icon/*", "repo/*"], |   "web_accessible_resources": ["env/*", "api/*", "dep/*", "media/*", "repo/*"], | ||||||
|   "content_scripts": [ |   "content_scripts": [ | ||||||
|     { |     { | ||||||
|       "matches": ["https://*.notion.so/*", "https://*.notion.site/*"], |       "matches": ["https://*.notion.so/*", "https://*.notion.site/*"], | ||||||
|       "js": ["launcher.js"] |       "js": ["init.js"] | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   "permissions": [ |   "permissions": ["tabs", "storage", "clipboardRead", "clipboardWrite", "unlimitedStorage"] | ||||||
|     "tabs", |  | ||||||
|     "storage", |  | ||||||
|     "unlimitedStorage", |  | ||||||
|     "https://*.notion.so/*", |  | ||||||
|     "https://*.notion.site/*", |  | ||||||
|     "<all_urls>" |  | ||||||
|   ] |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								extension/media
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
							
						
						| @ -0,0 +1 @@ | |||||||
|  | Subproject commit 2a0a17998385f1d86148b9213451b3a5deff6bae | ||||||
							
								
								
									
										1
									
								
								extension/repo
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
							
						
						| @ -0,0 +1 @@ | |||||||
|  | Subproject commit 76e36ab47ca2ffd354280b5c907f9ebb827c30c4 | ||||||
| @ -1,9 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer: bypass-preview |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| .notion-peek-renderer { |  | ||||||
|   display: none; |  | ||||||
| } |  | ||||||
| @ -1,33 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer: bypass-preview |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| export default async function (api, db) { |  | ||||||
|   const { web, components } = api; |  | ||||||
|   await web.whenReady(); |  | ||||||
| 
 |  | ||||||
|   let _lastPage = {}; |  | ||||||
|   function getCurrentPage() { |  | ||||||
|     if (web.queryParams().get('p')) return { type: 'preview', id: web.queryParams().get('p') }; |  | ||||||
|     return { type: 'page', id: location.pathname.split(/(-|\/)/g).reverse()[0] }; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   web.addDocumentObserver((event) => { |  | ||||||
|     const currentPage = getCurrentPage(); |  | ||||||
|     if (currentPage.id !== _lastPage.id || currentPage.type !== _lastPage.type) { |  | ||||||
|       const openAsPage = document.querySelector( |  | ||||||
|         '.notion-peek-renderer [style*="height: 45px;"] a' |  | ||||||
|       ); |  | ||||||
|       if (openAsPage) { |  | ||||||
|         if (currentPage.id === _lastPage.id && currentPage.type === 'preview') { |  | ||||||
|           history.back(); |  | ||||||
|         } else openAsPage.click(); |  | ||||||
|       } |  | ||||||
|       _lastPage = getCurrentPage(); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "bypass-preview", |  | ||||||
|   "id": "cb6fd684-f113-4a7a-9423-8f0f0cff069f", |  | ||||||
|   "version": "0.2.0", |  | ||||||
|   "description": "go straight to the normal full view when opening a page.", |  | ||||||
|   "tags": ["extension", "automation"], |  | ||||||
|   "authors": [ |  | ||||||
|     { |  | ||||||
|       "name": "dragonwocky", |  | ||||||
|       "email": "thedragonring.bod@gmail.com", |  | ||||||
|       "homepage": "https://dragonwocky.me/", |  | ||||||
|       "avatar": "https://dragonwocky.me/avatar.jpg" |  | ||||||
|     } |  | ||||||
|   ], |  | ||||||
|   "js": { |  | ||||||
|     "client": ["client.mjs"] |  | ||||||
|   }, |  | ||||||
|   "css": { |  | ||||||
|     "client": ["client.css"] |  | ||||||
|   }, |  | ||||||
|   "options": [] |  | ||||||
| } |  | ||||||
| @ -1,21 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer: calendar-scroll |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #calendar-scroll-to-week { |  | ||||||
|   background: var(--theme--button_hover); |  | ||||||
|   border: 1px solid transparent; |  | ||||||
|   font-size: var(--theme--font_label-size); |  | ||||||
|   color: var(--theme--text); |  | ||||||
|   height: 24px; |  | ||||||
|   border-radius: 3px; |  | ||||||
|   line-height: 1.2; |  | ||||||
|   padding: 0 0.5em; |  | ||||||
|   margin-right: 5px; |  | ||||||
| } |  | ||||||
| #calendar-scroll-to-week:hover { |  | ||||||
|   background: transparent; |  | ||||||
|   border: 1px solid var(--theme--button_hover); |  | ||||||
| } |  | ||||||
| @ -1,64 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer core: bypass-preview |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| import { web } from '../../api/_.mjs'; |  | ||||||
| 
 |  | ||||||
| const $button = web.createElement( |  | ||||||
|   web.html`<button id="calendar-scroll-to-week">Scroll</button>` |  | ||||||
| ); |  | ||||||
| $button.addEventListener('click', async (event) => { |  | ||||||
|   let $day = document.querySelector('.notion-calendar-view-day[style*="background:"]'); |  | ||||||
|   while (!$day) { |  | ||||||
|     const $toolbar = document.querySelector( |  | ||||||
|         '.notion-calendar-view > :first-child > :first-child > :first-child' |  | ||||||
|       ), |  | ||||||
|       year = +$toolbar.children[0].innerText.split(' ')[1], |  | ||||||
|       month = { |  | ||||||
|         'January': 0, |  | ||||||
|         'February': 1, |  | ||||||
|         'March': 2, |  | ||||||
|         'April': 3, |  | ||||||
|         'May': 4, |  | ||||||
|         'June': 5, |  | ||||||
|         'July': 6, |  | ||||||
|         'August': 7, |  | ||||||
|         'September': 8, |  | ||||||
|         'October': 9, |  | ||||||
|         'November': 10, |  | ||||||
|         'December': 11, |  | ||||||
|       }[$toolbar.children[0].innerText.split(' ')[0]], |  | ||||||
|       now = new Date(); |  | ||||||
|     switch (true) { |  | ||||||
|       case now.getFullYear() < year: |  | ||||||
|       case now.getFullYear() === year && now.getMonth() < month: |  | ||||||
|         $toolbar.children[3].click(); |  | ||||||
|         break; |  | ||||||
|       case now.getFullYear() > year: |  | ||||||
|       case now.getFullYear() === year && now.getMonth() > month: |  | ||||||
|         $toolbar.children[5].click(); |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         await new Promise((res, rej) => requestAnimationFrame(res)); |  | ||||||
|         $day = document.querySelector('.notion-calendar-view-day[style*="background:"]'); |  | ||||||
|     } |  | ||||||
|     await new Promise((res, rej) => requestAnimationFrame(res)); |  | ||||||
|   } |  | ||||||
|   const $scroller = document.querySelector('.notion-frame .notion-scroller'); |  | ||||||
|   $scroller.scroll({ |  | ||||||
|     top: $day.offsetParent.offsetParent.offsetTop + 70, |  | ||||||
|     behavior: 'auto', |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| web.addDocumentObserver((event) => { |  | ||||||
|   if (document.contains($button)) return; |  | ||||||
|   const toolbar = document.querySelector( |  | ||||||
|     '.notion-calendar-view > :first-child > :first-child > :first-child' |  | ||||||
|   ); |  | ||||||
|   if (toolbar) toolbar.insertBefore($button, toolbar.children[2]); |  | ||||||
| }); |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "calendar-scroll", |  | ||||||
|   "id": "b1c7db33-dfee-489a-a76c-0dd66f7ed29a", |  | ||||||
|   "version": "0.2.0", |  | ||||||
|   "description": "add a button to jump down to the current week in fullpage/infinite-scroll calendars.", |  | ||||||
|   "tags": ["extension", "shortcut"], |  | ||||||
|   "authors": [ |  | ||||||
|     { |  | ||||||
|       "name": "dragonwocky", |  | ||||||
|       "email": "thedragonring.bod@gmail.com", |  | ||||||
|       "homepage": "https://dragonwocky.me/", |  | ||||||
|       "avatar": "https://dragonwocky.me/avatar.jpg" |  | ||||||
|     } |  | ||||||
|   ], |  | ||||||
|   "js": { |  | ||||||
|     "client": ["client.mjs"] |  | ||||||
|   }, |  | ||||||
|   "css": { |  | ||||||
|     "client": ["client.css"] |  | ||||||
|   }, |  | ||||||
|   "options": [] |  | ||||||
| } |  | ||||||
| @ -1,33 +0,0 @@ | |||||||
| { |  | ||||||
|   "__comment": "pseudo-mod to allow configuration of API-provided components", |  | ||||||
|   "name": "components", |  | ||||||
|   "id": "36a2ffc9-27ff-480e-84a7-c7700a7d232d", |  | ||||||
|   "version": "0.2.0", |  | ||||||
|   "description": "shared notion-style elements.", |  | ||||||
|   "tags": ["core"], |  | ||||||
|   "authors": [ |  | ||||||
|     { |  | ||||||
|       "name": "dragonwocky", |  | ||||||
|       "email": "thedragonring.bod@gmail.com", |  | ||||||
|       "homepage": "https://dragonwocky.me/", |  | ||||||
|       "avatar": "https://dragonwocky.me/avatar.jpg" |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "name": "CloudHill", |  | ||||||
|       "email": "rh.cloudhill@gmail.com", |  | ||||||
|       "homepage": "https://github.com/CloudHill", |  | ||||||
|       "avatar": "https://avatars.githubusercontent.com/u/54142180" |  | ||||||
|     } |  | ||||||
|   ], |  | ||||||
|   "js": {}, |  | ||||||
|   "css": {}, |  | ||||||
|   "options": [ |  | ||||||
|     { |  | ||||||
|       "type": "hotkey", |  | ||||||
|       "key": "panel.hotkey", |  | ||||||
|       "label": "toggle panel hotkey", |  | ||||||
|       "value": "Ctrl+Alt+\\", |  | ||||||
|       "tooltip": "opens/closes the side panel in notion - will only work if a mod is making use of it." |  | ||||||
|     } |  | ||||||
|   ] |  | ||||||
| } |  | ||||||
| @ -1,237 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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'; |  | ||||||
| 
 |  | ||||||
| import { fmt, web, registry, components } from '../../api/_.mjs'; |  | ||||||
| import { notifications } from './notifications.mjs'; |  | ||||||
| const profileDB = await registry.profileDB(); |  | ||||||
| 
 |  | ||||||
| export const blocks = { |  | ||||||
|   preview: (url) => web.html`<img
 |  | ||||||
|     class="mod-preview" |  | ||||||
|     src="${web.escape(url)}" |  | ||||||
|     alt="" |  | ||||||
|   >`,
 |  | ||||||
|   title: (title) => web.html`<h4 class="mod-title"><span>${web.escape(title)}</span></h4>`, |  | ||||||
|   version: (version) => web.html`<span class="mod-version">v${web.escape(version)}</span>`, |  | ||||||
|   tags: (tags) => { |  | ||||||
|     if (!tags.length) return ''; |  | ||||||
|     return web.render( |  | ||||||
|       web.html`<p class="mod-tags"></p>`, |  | ||||||
|       tags.map((tag) => `#${web.escape(tag)}`).join(' ') |  | ||||||
|     ); |  | ||||||
|   }, |  | ||||||
|   description: (description) => web.html`<p class="mod-description markdown-inline">
 |  | ||||||
|     ${fmt.md.renderInline(description)} |  | ||||||
|   </p>`, |  | ||||||
|   authors: (authors) => { |  | ||||||
|     const author = (author) => web.html`<a
 |  | ||||||
|       class="mod-author" |  | ||||||
|       href="${web.escape(author.homepage)}" |  | ||||||
|       target="_blank" |  | ||||||
|     > |  | ||||||
|       <img class="mod-author-avatar" |  | ||||||
|         src="${web.escape(author.avatar)}" alt="${web.escape(author.name)}'s avatar" |  | ||||||
|       > <span>${web.escape(author.name)}</span> |  | ||||||
|     </a>`; |  | ||||||
|     return web.render(web.html`<p class="mod-authors-container"></p>`, ...authors.map(author)); |  | ||||||
|   }, |  | ||||||
|   toggle: (label, checked) => { |  | ||||||
|     const $label = web.html`<label tabindex="0" class="toggle-label">
 |  | ||||||
|       <span>${web.escape(label)}</span> |  | ||||||
|     </label>`, |  | ||||||
|       $input = web.html`<input tabindex="-1" type="checkbox" class="toggle-check"
 |  | ||||||
|         ${checked ? 'checked' : ''}>`,
 |  | ||||||
|       $feature = web.html`<span class="toggle-box toggle-feature"></span>`; |  | ||||||
|     $label.addEventListener('keyup', (event) => { |  | ||||||
|       if (['Enter', ' '].includes(event.key)) $input.checked = !$input.checked; |  | ||||||
|     }); |  | ||||||
|     return web.render($label, $input, $feature); |  | ||||||
|   }, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| export const options = { |  | ||||||
|   toggle: async (mod, opt) => { |  | ||||||
|     const checked = await profileDB.get([mod.id, opt.key], opt.value), |  | ||||||
|       $toggle = blocks.toggle(opt.label, checked), |  | ||||||
|       $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`, |  | ||||||
|       $label = $toggle.children[0], |  | ||||||
|       $input = $toggle.children[1]; |  | ||||||
|     if (opt.tooltip) { |  | ||||||
|       $label.prepend($tooltip); |  | ||||||
|       components.tooltip($tooltip, opt.tooltip); |  | ||||||
|     } |  | ||||||
|     $input.addEventListener('change', async (event) => { |  | ||||||
|       await profileDB.set([mod.id, opt.key], $input.checked); |  | ||||||
|       notifications.onChange(); |  | ||||||
|     }); |  | ||||||
|     return $toggle; |  | ||||||
|   }, |  | ||||||
|   select: async (mod, opt) => { |  | ||||||
|     const value = await profileDB.get([mod.id, opt.key], opt.values[0]), |  | ||||||
|       $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`, |  | ||||||
|       $label = web.render( |  | ||||||
|         web.html`<label class="input-label"></label>`, |  | ||||||
|         web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label) |  | ||||||
|       ), |  | ||||||
|       $options = opt.values.map( |  | ||||||
|         (option) => web.raw`<option
 |  | ||||||
|           class="select-option" |  | ||||||
|           value="${web.escape(option)}" |  | ||||||
|           ${option === value ? 'selected' : ''} |  | ||||||
|         >${web.escape(option)}</option>` |  | ||||||
|       ), |  | ||||||
|       $select = web.html`<select class="input">
 |  | ||||||
|         ${$options.join('')} |  | ||||||
|       </select>`, |  | ||||||
|       $icon = web.html`${await components.feather('chevron-down', { class: 'input-icon' })}`; |  | ||||||
|     if (opt.tooltip) components.tooltip($tooltip, opt.tooltip); |  | ||||||
|     $select.addEventListener('change', async (event) => { |  | ||||||
|       await profileDB.set([mod.id, opt.key], $select.value); |  | ||||||
|       notifications.onChange(); |  | ||||||
|     }); |  | ||||||
|     return web.render($label, $select, $icon); |  | ||||||
|   }, |  | ||||||
|   text: async (mod, opt) => { |  | ||||||
|     const value = await profileDB.get([mod.id, opt.key], opt.value), |  | ||||||
|       $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`, |  | ||||||
|       $label = web.render( |  | ||||||
|         web.html`<label class="input-label"></label>`, |  | ||||||
|         web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label) |  | ||||||
|       ), |  | ||||||
|       $input = web.html`<input type="text" class="input" value="${web.escape(value)}">`, |  | ||||||
|       $icon = web.html`${await components.feather('type', { class: 'input-icon' })}`; |  | ||||||
|     if (opt.tooltip) components.tooltip($tooltip, opt.tooltip); |  | ||||||
|     $input.addEventListener('change', async (event) => { |  | ||||||
|       await profileDB.set([mod.id, opt.key], $input.value); |  | ||||||
|       notifications.onChange(); |  | ||||||
|     }); |  | ||||||
|     return web.render($label, $input, $icon); |  | ||||||
|   }, |  | ||||||
|   number: async (mod, opt) => { |  | ||||||
|     const value = await profileDB.get([mod.id, opt.key], opt.value), |  | ||||||
|       $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`, |  | ||||||
|       $label = web.render( |  | ||||||
|         web.html`<label class="input-label"></label>`, |  | ||||||
|         web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label) |  | ||||||
|       ), |  | ||||||
|       $input = web.html`<input type="number" class="input" value="${value}">`, |  | ||||||
|       $icon = web.html`${await components.feather('hash', { class: 'input-icon' })}`; |  | ||||||
|     if (opt.tooltip) components.tooltip($tooltip, opt.tooltip); |  | ||||||
|     $input.addEventListener('change', async (event) => { |  | ||||||
|       await profileDB.set([mod.id, opt.key], $input.value); |  | ||||||
|       notifications.onChange(); |  | ||||||
|     }); |  | ||||||
|     return web.render($label, $input, $icon); |  | ||||||
|   }, |  | ||||||
|   color: async (mod, opt) => { |  | ||||||
|     const value = await profileDB.get([mod.id, opt.key], opt.value), |  | ||||||
|       $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`, |  | ||||||
|       $label = web.render( |  | ||||||
|         web.html`<label class="input-label"></label>`, |  | ||||||
|         web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label) |  | ||||||
|       ), |  | ||||||
|       $input = web.html`<input type="text" class="input">`, |  | ||||||
|       $icon = web.html`${await components.feather('droplet', { class: 'input-icon' })}`, |  | ||||||
|       paint = () => { |  | ||||||
|         $input.style.background = $picker.toBackground(); |  | ||||||
|         $input.style.color = $picker.isLight() ? '#000' : '#fff'; |  | ||||||
|         $input.style.padding = ''; |  | ||||||
|       }, |  | ||||||
|       $picker = new web.jscolor($input, { |  | ||||||
|         value, |  | ||||||
|         format: 'rgba', |  | ||||||
|         previewSize: 0, |  | ||||||
|         borderRadius: 3, |  | ||||||
|         borderColor: 'var(--theme--ui_divider)', |  | ||||||
|         controlBorderColor: 'var(--theme--ui_divider)', |  | ||||||
|         backgroundColor: 'var(--theme--bg)', |  | ||||||
|         onInput: paint, |  | ||||||
|         onChange: paint, |  | ||||||
|       }); |  | ||||||
|     if (opt.tooltip) components.tooltip($tooltip, opt.tooltip); |  | ||||||
|     $input.addEventListener('change', async (event) => { |  | ||||||
|       await profileDB.set([mod.id, opt.key], $input.value); |  | ||||||
|       notifications.onChange(); |  | ||||||
|     }); |  | ||||||
|     paint(); |  | ||||||
|     return web.render($label, $input, $icon); |  | ||||||
|   }, |  | ||||||
|   file: async (mod, opt) => { |  | ||||||
|     const { filename } = (await profileDB.get([mod.id, opt.key], {})) || {}, |  | ||||||
|       $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`, |  | ||||||
|       $label = web.render( |  | ||||||
|         web.html`<label class="input-label"></label>`, |  | ||||||
|         web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label) |  | ||||||
|       ), |  | ||||||
|       $pseudo = web.html`<span class="input"><span class="input-placeholder">Upload file...</span></span>`, |  | ||||||
|       $input = web.html`<input type="file" class="hidden" accept=${web.escape( |  | ||||||
|         opt.extensions.join(',') |  | ||||||
|       )}>`,
 |  | ||||||
|       $icon = web.html`${await components.feather('file', { class: 'input-icon' })}`, |  | ||||||
|       $filename = web.html`<span>${web.escape(filename || 'none')}</span>`, |  | ||||||
|       $latest = web.render(web.html`<button class="file-latest">Latest: </button>`, $filename); |  | ||||||
|     if (opt.tooltip) components.tooltip($tooltip, opt.tooltip); |  | ||||||
|     $input.addEventListener('change', (event) => { |  | ||||||
|       const file = event.target.files[0], |  | ||||||
|         reader = new FileReader(); |  | ||||||
|       reader.onload = async (progress) => { |  | ||||||
|         $filename.innerText = file.name; |  | ||||||
|         await profileDB.set([mod.id, opt.key], { |  | ||||||
|           filename: file.name, |  | ||||||
|           content: progress.currentTarget.result, |  | ||||||
|         }); |  | ||||||
|         notifications.onChange(); |  | ||||||
|       }; |  | ||||||
|       reader.readAsText(file); |  | ||||||
|     }); |  | ||||||
|     $latest.addEventListener('click', (event) => { |  | ||||||
|       $filename.innerText = 'none'; |  | ||||||
|       profileDB.set([mod.id, opt.key], {}); |  | ||||||
|     }); |  | ||||||
|     return web.render( |  | ||||||
|       web.html`<div></div>`, |  | ||||||
|       web.render($label, $input, $pseudo, $icon), |  | ||||||
|       $latest |  | ||||||
|     ); |  | ||||||
|   }, |  | ||||||
|   hotkey: async (mod, opt) => { |  | ||||||
|     const value = await profileDB.get([mod.id, opt.key], opt.value), |  | ||||||
|       $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`, |  | ||||||
|       $label = web.render( |  | ||||||
|         web.html`<label class="input-label"></label>`, |  | ||||||
|         web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label) |  | ||||||
|       ), |  | ||||||
|       $input = web.html`<input type="text" class="input" value="${web.escape(value)}">`, |  | ||||||
|       $icon = web.html`${await components.feather('command', { class: 'input-icon' })}`; |  | ||||||
|     if (opt.tooltip) components.tooltip($tooltip, opt.tooltip); |  | ||||||
|     $input.addEventListener('keydown', async (event) => { |  | ||||||
|       event.preventDefault(); |  | ||||||
|       const pressed = [], |  | ||||||
|         modifiers = { |  | ||||||
|           metaKey: 'Meta', |  | ||||||
|           ctrlKey: 'Control', |  | ||||||
|           altKey: 'Alt', |  | ||||||
|           shiftKey: 'Shift', |  | ||||||
|         }; |  | ||||||
|       for (const modifier in modifiers) { |  | ||||||
|         if (event[modifier]) pressed.push(modifiers[modifier]); |  | ||||||
|       } |  | ||||||
|       const empty = ['Backspace', 'Delete'].includes(event.key) && !pressed.length; |  | ||||||
|       if (!empty && !pressed.includes(event.key)) { |  | ||||||
|         let key = event.key; |  | ||||||
|         if (key === ' ') key = 'Space'; |  | ||||||
|         if (key.length === 1) key = event.key.toUpperCase(); |  | ||||||
|         pressed.push(key); |  | ||||||
|       } |  | ||||||
|       $input.value = pressed.join('+'); |  | ||||||
|       await profileDB.set([mod.id, opt.key], $input.value); |  | ||||||
|       notifications.onChange(); |  | ||||||
|     }); |  | ||||||
|     return web.render($label, $input, $icon); |  | ||||||
|   }, |  | ||||||
| }; |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer core: menu |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| .enhancer--sidebarMenuLink { |  | ||||||
|   user-select: none; |  | ||||||
|   -webkit-user-select: none; |  | ||||||
|   transition: background 20ms ease-in 0s; |  | ||||||
|   cursor: pointer; |  | ||||||
|   color: var(--theme--text_secondary); |  | ||||||
| } |  | ||||||
| .enhancer--sidebarMenuLink:hover { |  | ||||||
|   background: var(--theme--ui_interactive-hover); |  | ||||||
| } |  | ||||||
| .enhancer--sidebarMenuLink svg { |  | ||||||
|   width: 16px; |  | ||||||
|   height: 16px; |  | ||||||
|   margin-left: 2px; |  | ||||||
| } |  | ||||||
| .enhancer--sidebarMenuLink > div { |  | ||||||
|   display: flex; |  | ||||||
|   align-items: center; |  | ||||||
|   min-height: 27px; |  | ||||||
|   font-size: 14px; |  | ||||||
|   padding: 2px 14px; |  | ||||||
|   width: 100%; |  | ||||||
| } |  | ||||||
| .enhancer--sidebarMenuLink > div > :first-child { |  | ||||||
|   flex-shrink: 0; |  | ||||||
|   flex-grow: 0; |  | ||||||
|   border-radius: 3px; |  | ||||||
|   width: 22px; |  | ||||||
|   height: 22px; |  | ||||||
|   display: flex; |  | ||||||
|   align-items: center; |  | ||||||
|   justify-content: center; |  | ||||||
|   margin-right: 8px; |  | ||||||
| } |  | ||||||
| .enhancer--sidebarMenuLink > div > :nth-child(2) { |  | ||||||
|   flex: 1 1 auto; |  | ||||||
|   white-space: nowrap; |  | ||||||
|   overflow: hidden; |  | ||||||
|   text-overflow: ellipsis; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .enhancer--sidebarMenuLink[data-has-notifications] { |  | ||||||
|   color: var(--theme--text); |  | ||||||
| } |  | ||||||
| .enhancer--sidebarMenuLink > div > .enhancer--notificationBubble { |  | ||||||
|   display: flex; |  | ||||||
| } |  | ||||||
| .enhancer--sidebarMenuLink > div > .enhancer--notificationBubble > div { |  | ||||||
|   display: inline-flex; |  | ||||||
|   align-items: center; |  | ||||||
|   justify-content: center; |  | ||||||
|   width: 16px; |  | ||||||
|   height: 16px; |  | ||||||
|   font-size: 10px; |  | ||||||
|   font-weight: 600; |  | ||||||
|   border-radius: 3px; |  | ||||||
|   color: var(--theme--accent_red-text); |  | ||||||
|   background: var(--theme--accent_red); |  | ||||||
| } |  | ||||||
| .enhancer--sidebarMenuLink > div > .enhancer--notificationBubble > div > span { |  | ||||||
|   margin-bottom: 1px; |  | ||||||
|   margin-left: -0.5px; |  | ||||||
| } |  | ||||||
| @ -1,59 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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'; |  | ||||||
| 
 |  | ||||||
| export default async function (api, db) { |  | ||||||
|   const { env, fs, storage, registry, web } = api; |  | ||||||
| 
 |  | ||||||
|   web.addHotkeyListener(await db.get(['hotkey']), env.focusMenu); |  | ||||||
| 
 |  | ||||||
|   const updateTheme = () => |  | ||||||
|     storage.set(['theme'], document.querySelector('.notion-dark-theme') ? 'dark' : 'light'); |  | ||||||
|   web.addDocumentObserver((mutation) => { |  | ||||||
|     if (mutation.target === document.body && document.hasFocus()) updateTheme(); |  | ||||||
|   }); |  | ||||||
|   if (document.hasFocus()) updateTheme(); |  | ||||||
|   document.addEventListener('visibilitychange', updateTheme); |  | ||||||
| 
 |  | ||||||
|   const sidebarSelector = '.notion-sidebar-container .notion-sidebar > div:nth-child(4)'; |  | ||||||
|   await web.whenReady([sidebarSelector]); |  | ||||||
| 
 |  | ||||||
|   const $sidebarLink = web.html`<div class="enhancer--sidebarMenuLink" role="button" tabindex="0">
 |  | ||||||
|       <div> |  | ||||||
|         <div>${await fs.getText('icon/colour.svg')}</div> |  | ||||||
|         <div><div>notion-enhancer</div></div> |  | ||||||
|       </div> |  | ||||||
|     </div>`; |  | ||||||
|   $sidebarLink.addEventListener('click', env.focusMenu); |  | ||||||
| 
 |  | ||||||
|   const notifications = { |  | ||||||
|     cache: await storage.get(['notifications'], []), |  | ||||||
|     provider: [ |  | ||||||
|       registry.welcomeNotification, |  | ||||||
|       ...(await fs.getJSON('https://notion-enhancer.github.io/notifications.json')), |  | ||||||
|     ], |  | ||||||
|     count: (await registry.errors()).length, |  | ||||||
|   }; |  | ||||||
|   for (const notification of notifications.provider) { |  | ||||||
|     if ( |  | ||||||
|       !notifications.cache.includes(notification.id) && |  | ||||||
|       notification.version === env.version && |  | ||||||
|       (!notification.environments || notification.environments.includes(env.name)) |  | ||||||
|     ) { |  | ||||||
|       notifications.count++; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (notifications.count) { |  | ||||||
|     $sidebarLink.dataset.hasNotifications = true; |  | ||||||
|     web.render( |  | ||||||
|       $sidebarLink.children[0], |  | ||||||
|       web.html`<div class="enhancer--notificationBubble"><div><span>${notifications.count}</span></div></div>` |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   web.render(document.querySelector(sidebarSelector), $sidebarLink); |  | ||||||
| } |  | ||||||
| @ -1,165 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer core: menu |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| .markdown table { |  | ||||||
|   border-spacing: 0; |  | ||||||
|   border: 1px solid var(--theme--ui_divider); |  | ||||||
| } |  | ||||||
| .markdown table th { |  | ||||||
|   text-align: left; |  | ||||||
| } |  | ||||||
| .markdown table th, |  | ||||||
| .markdown table td { |  | ||||||
|   padding: 5px 8px 6px; |  | ||||||
|   border: 1px solid var(--theme--ui_divider); |  | ||||||
| } |  | ||||||
| .markdown h1 { |  | ||||||
|   font-size: 1.875rem; |  | ||||||
|   margin: 1rem 0 0.5rem 0; |  | ||||||
| } |  | ||||||
| .markdown h2 { |  | ||||||
|   font-size: 1.5rem; |  | ||||||
|   margin: 1rem 0 0.5rem 0; |  | ||||||
| } |  | ||||||
| .markdown h3 { |  | ||||||
|   font-size: 1.25rem; |  | ||||||
|   margin: 1rem 0 0.5rem 0; |  | ||||||
| } |  | ||||||
| .markdown ul, |  | ||||||
| .markdown ol { |  | ||||||
|   padding-left: 1.25rem; |  | ||||||
| } |  | ||||||
| .markdown li { |  | ||||||
|   margin: 0.4rem 0; |  | ||||||
| } |  | ||||||
| .markdown ol li { |  | ||||||
|   padding-left: 0.25rem; |  | ||||||
| } |  | ||||||
| .markdown blockquote { |  | ||||||
|   border-left: 2px solid currentColor; |  | ||||||
|   padding-left: 0.75rem; |  | ||||||
|   margin: 0.5rem 0; |  | ||||||
| } |  | ||||||
| .markdown hr { |  | ||||||
|   border: 0.5px solid var(--theme--ui_divider); |  | ||||||
| } |  | ||||||
| .markdown.markdown-inline a { |  | ||||||
|   opacity: 0.7; |  | ||||||
|   text-decoration: none; |  | ||||||
|   border-bottom: 0.05em solid var(--theme--text_secondary); |  | ||||||
| } |  | ||||||
| .markdown.markdown-inline a:hover { |  | ||||||
|   opacity: 0.9; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .markdown :not(pre) > code, |  | ||||||
| .markdown-inline code { |  | ||||||
|   padding: 0.2em 0.4em; |  | ||||||
|   border-radius: 3px; |  | ||||||
|   background: var(--theme--code_inline); |  | ||||||
|   color: var(--theme--code_inline-text); |  | ||||||
| } |  | ||||||
| .markdown pre { |  | ||||||
|   padding: 2em 1.25em; |  | ||||||
|   border-radius: 3px; |  | ||||||
|   tab-size: 2; |  | ||||||
|   white-space: pre; |  | ||||||
|   overflow-x: auto; |  | ||||||
|   background: var(--theme--code); |  | ||||||
|   color: var(--theme--code_plain); |  | ||||||
| } |  | ||||||
| .markdown pre, |  | ||||||
| .markdown.markdown-inline code { |  | ||||||
|   font-family: var(--theme--font_code); |  | ||||||
|   font-size: 0.796875rem; |  | ||||||
|   text-align: left; |  | ||||||
|   word-spacing: normal; |  | ||||||
|   word-break: normal; |  | ||||||
|   word-wrap: normal; |  | ||||||
|   hyphens: none; |  | ||||||
|   line-height: 1.5; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
|  * https://prismjs.com/plugins/inline-color/ |  | ||||||
|  */ |  | ||||||
| .markdown .inline-color-wrapper { |  | ||||||
|   /* |  | ||||||
| 	 * base64 svg (https://stackoverflow.com/a/21626701/7595472 - prevents visual glitches) |  | ||||||
| 	 * <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"> |  | ||||||
| 	 *   <path fill="gray" d="M0 0h2v2H0z"/> |  | ||||||
| 	 *   <path fill="white" d="M0 0h1v1H0zM1 1h1v1H1z"/> |  | ||||||
| 	 * </svg> |  | ||||||
| 	 */ |  | ||||||
|   background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyIDIiPjxwYXRoIGZpbGw9ImdyYXkiIGQ9Ik0wIDBoMnYySDB6Ii8+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0wIDBoMXYxSDB6TTEgMWgxdjFIMXoiLz48L3N2Zz4='); |  | ||||||
|   background-position: center; |  | ||||||
|   background-size: 110%; |  | ||||||
|   display: inline-block; |  | ||||||
|   height: 1.333ch; |  | ||||||
|   width: 1.333ch; |  | ||||||
|   margin: 0 0.333ch; |  | ||||||
|   box-sizing: border-box; |  | ||||||
|   border: 0.5px solid var(--theme--code_plain); |  | ||||||
|   overflow: hidden; |  | ||||||
| } |  | ||||||
| .markdown .inline-color { |  | ||||||
|   display: block; |  | ||||||
|   height: 120%; |  | ||||||
|   width: 120%; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
|  * https://prismjs.com/plugins/match-braces/ |  | ||||||
|  */ |  | ||||||
| .markdown .token.punctuation.brace-hover, |  | ||||||
| .markdown .token.punctuation.brace-selected { |  | ||||||
|   outline: solid 1px; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
|  * https://prismjs.com/plugins/show-language/ |  | ||||||
|  * https://prismjs.com/plugins/copy-to-clipboard/ |  | ||||||
|  */ |  | ||||||
| .markdown .code-toolbar { |  | ||||||
|   position: relative; |  | ||||||
| } |  | ||||||
| .markdown .code-toolbar .toolbar-item { |  | ||||||
|   position: absolute; |  | ||||||
|   top: 0.35rem; |  | ||||||
|   display: inline-block; |  | ||||||
|   transition: opacity 200ms ease-in-out; |  | ||||||
|   opacity: 0; |  | ||||||
| } |  | ||||||
| .markdown .code-toolbar .toolbar-item:first-child { |  | ||||||
|   left: 0.8rem; |  | ||||||
| } |  | ||||||
| .markdown .code-toolbar .toolbar-item:last-child { |  | ||||||
|   right: 0.8rem; |  | ||||||
| } |  | ||||||
| .markdown .code-toolbar:hover .toolbar-item, |  | ||||||
| .markdown .code-toolbar:focus-within .toolbar-item { |  | ||||||
|   opacity: 1; |  | ||||||
| } |  | ||||||
| .markdown .code-toolbar .toolbar-item > * { |  | ||||||
|   padding: 0.25rem 0.35rem; |  | ||||||
|   color: var(--theme--text_secondary); |  | ||||||
|   font-size: 11px; |  | ||||||
|   font-family: inherit; |  | ||||||
| } |  | ||||||
| .markdown .code-toolbar .toolbar-item .copy-to-clipboard-button { |  | ||||||
|   border: none; |  | ||||||
|   background: none; |  | ||||||
|   cursor: pointer; |  | ||||||
|   border-radius: 3px; |  | ||||||
|   transition: background 100ms ease-in-out; |  | ||||||
| } |  | ||||||
| .markdown .code-toolbar .toolbar-item .copy-to-clipboard-button:hover { |  | ||||||
|   background: var(--theme--button-hover); |  | ||||||
| } |  | ||||||
| .markdown .code-toolbar .toolbar-item .copy-to-clipboard-button svg { |  | ||||||
|   width: 1em; |  | ||||||
|   margin-right: 0.5em; |  | ||||||
| } |  | ||||||
| @ -1,25 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer core: menu |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| ::selection { |  | ||||||
|   background: var(--theme--accent_blue-selection); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ::-webkit-scrollbar { |  | ||||||
|   width: 10px; |  | ||||||
|   height: 10px; |  | ||||||
|   background: transparent; |  | ||||||
| } |  | ||||||
| ::-webkit-scrollbar-track, |  | ||||||
| ::-webkit-scrollbar-corner { |  | ||||||
|   background: var(--theme--scrollbar_track) !important; |  | ||||||
| } |  | ||||||
| ::-webkit-scrollbar-thumb { |  | ||||||
|   background: var(--theme--scrollbar_thumb) !important; |  | ||||||
| } |  | ||||||
| ::-webkit-scrollbar-thumb:hover { |  | ||||||
|   background: var(--theme--scrollbar_thumb-hover) !important; |  | ||||||
| } |  | ||||||
| @ -1,11 +0,0 @@ | |||||||
| <!DOCTYPE html> |  | ||||||
| <html lang="en"> |  | ||||||
|   <head> |  | ||||||
|     <meta charset="UTF-8" /> |  | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |  | ||||||
|     <title>notion-enhancer menu</title> |  | ||||||
|   </head> |  | ||||||
|   <body> |  | ||||||
|     <script src="./menu.mjs" type="module"></script> |  | ||||||
|   </body> |  | ||||||
| </html> |  | ||||||
| @ -1,370 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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'; |  | ||||||
| 
 |  | ||||||
| import { env, fs, storage, registry, web, components } from '../../api/_.mjs'; |  | ||||||
| import { notifications } from './notifications.mjs'; |  | ||||||
| import { blocks, options } from './blocks.mjs'; |  | ||||||
| import './styles.mjs'; |  | ||||||
| 
 |  | ||||||
| const db = await registry.db('a6621988-551d-495a-97d8-3c568bca2e9e'), |  | ||||||
|   profileName = await registry.profileName(), |  | ||||||
|   profileDB = await registry.profileDB(); |  | ||||||
| 
 |  | ||||||
| for (const mod of await registry.list((mod) => registry.enabled(mod.id))) { |  | ||||||
|   for (const sheet of mod.css?.menu || []) { |  | ||||||
|     web.loadStylesheet(`repo/${mod._dir}/${sheet}`); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| web.addHotkeyListener(await db.get(['hotkey']), env.focusNotion); |  | ||||||
| 
 |  | ||||||
| const loadTheme = async () => { |  | ||||||
|   document.documentElement.className = |  | ||||||
|     (await storage.get(['theme'], 'light')) === 'dark' ? 'dark' : ''; |  | ||||||
| }; |  | ||||||
| document.addEventListener('visibilitychange', loadTheme); |  | ||||||
| loadTheme(); |  | ||||||
| 
 |  | ||||||
| window.addEventListener('beforeunload', (event) => { |  | ||||||
|   // trigger input save
 |  | ||||||
|   document.activeElement.blur(); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const $main = web.html`<main class="main"></main>`, |  | ||||||
|   $sidebar = web.html`<article class="sidebar"></article>`, |  | ||||||
|   $options = web.html`<div class="options-container">
 |  | ||||||
|     <p class="options-placeholder">Select a mod to view and configure its options.</p> |  | ||||||
|   </div>`, |  | ||||||
|   $profile = web.html`<button class="profile-trigger">
 |  | ||||||
|     Profile: ${web.escape(profileName)} |  | ||||||
|   </button>`; |  | ||||||
| 
 |  | ||||||
| let _$profileConfig; |  | ||||||
| $profile.addEventListener('click', async (event) => { |  | ||||||
|   for (const $selected of document.querySelectorAll('.mod-selected')) { |  | ||||||
|     $selected.className = 'mod'; |  | ||||||
|   } |  | ||||||
|   if (!_$profileConfig) { |  | ||||||
|     const profileNames = [ |  | ||||||
|         ...new Set([ |  | ||||||
|           ...Object.keys(await storage.get(['profiles'], { default: {} })), |  | ||||||
|           profileName, |  | ||||||
|         ]), |  | ||||||
|       ], |  | ||||||
|       $options = profileNames.map( |  | ||||||
|         (profile) => web.raw`<option
 |  | ||||||
|           class="select-option" |  | ||||||
|           value="${web.escape(profile)}" |  | ||||||
|           ${profile === profileName ? 'selected' : ''} |  | ||||||
|         >${web.escape(profile)}</option>` |  | ||||||
|       ), |  | ||||||
|       $select = web.html`<select class="input">
 |  | ||||||
|         <option class="select-option" value="--">-- new --</option> |  | ||||||
|         ${$options.join('')} |  | ||||||
|       </select>`, |  | ||||||
|       $edit = web.html`<input
 |  | ||||||
|         type="text" |  | ||||||
|         class="input" |  | ||||||
|         value="${web.escape(profileName)}" |  | ||||||
|         pattern="/^[A-Za-z0-9_-]+$/" |  | ||||||
|       >`,
 |  | ||||||
|       $export = web.html`<button class="profile-export">
 |  | ||||||
|         ${await components.feather('download', { class: 'profile-icon-action' })} |  | ||||||
|       </button>`, |  | ||||||
|       $import = web.html`<label class="profile-import">
 |  | ||||||
|         <input type="file" class="hidden" accept="application/json"> |  | ||||||
|         ${await components.feather('upload', { class: 'profile-icon-action' })} |  | ||||||
|       </label>`, |  | ||||||
|       $save = web.html`<button class="profile-save">
 |  | ||||||
|         ${await components.feather('save', { class: 'profile-icon-text' })} Save |  | ||||||
|       </button>`, |  | ||||||
|       $delete = web.html`<button class="profile-delete">
 |  | ||||||
|         ${await components.feather('trash-2', { class: 'profile-icon-text' })} Delete |  | ||||||
|       </button>`, |  | ||||||
|       $error = web.html`<p class="profile-error"></p>`; |  | ||||||
|     $export.addEventListener('click', async (event) => { |  | ||||||
|       const now = new Date(), |  | ||||||
|         $a = web.html`<a
 |  | ||||||
|           class="hidden" |  | ||||||
|           download="notion-enhancer_${web.escape($select.value)}_${now.getFullYear()}-${ |  | ||||||
|           now.getMonth() + 1 |  | ||||||
|         }-${now.getDate()}.json" |  | ||||||
|           href="data:text/plain;charset=utf-8,${encodeURIComponent( |  | ||||||
|             JSON.stringify(await storage.get(['profiles', $select.value], {}), null, 2) |  | ||||||
|           )}" |  | ||||||
|         ></a>`; |  | ||||||
|       web.render(document.body, $a); |  | ||||||
|       $a.click(); |  | ||||||
|       $a.remove(); |  | ||||||
|     }); |  | ||||||
|     $import.addEventListener('change', (event) => { |  | ||||||
|       const file = event.target.files[0], |  | ||||||
|         reader = new FileReader(); |  | ||||||
|       reader.onload = async (progress) => { |  | ||||||
|         try { |  | ||||||
|           const profileUpload = JSON.parse(progress.currentTarget.result); |  | ||||||
|           if (!profileUpload) throw Error; |  | ||||||
|           await storage.set(['profiles', $select.value], profileUpload); |  | ||||||
|           env.reload(); |  | ||||||
|         } catch { |  | ||||||
|           web.render(web.empty($error), 'Invalid JSON uploaded.'); |  | ||||||
|         } |  | ||||||
|       }; |  | ||||||
|       reader.readAsText(file); |  | ||||||
|     }); |  | ||||||
|     $select.addEventListener('change', async (event) => { |  | ||||||
|       if ($select.value === '--') { |  | ||||||
|         $edit.value = ''; |  | ||||||
|       } else $edit.value = $select.value; |  | ||||||
|     }); |  | ||||||
|     $save.addEventListener('click', async (event) => { |  | ||||||
|       if (profileNames.includes($edit.value) && $select.value !== $edit.value) { |  | ||||||
|         web.render( |  | ||||||
|           web.empty($error), |  | ||||||
|           `The profile "${web.escape($edit.value)}" already exists.` |  | ||||||
|         ); |  | ||||||
|         return false; |  | ||||||
|       } |  | ||||||
|       if (!$edit.value) { |  | ||||||
|         web.render(web.empty($error), 'Profile names cannot be empty.'); |  | ||||||
|         return false; |  | ||||||
|       } |  | ||||||
|       if (!$edit.value.match(/^[A-Za-z0-9_-]+$/)) { |  | ||||||
|         web.render( |  | ||||||
|           web.empty($error), |  | ||||||
|           'Profile names can only contain letters, numbers, dashes and underscores.' |  | ||||||
|         ); |  | ||||||
|         return false; |  | ||||||
|       } |  | ||||||
|       await storage.set(['currentprofile'], $edit.value); |  | ||||||
|       if ($select.value === '--') { |  | ||||||
|         await storage.set(['profiles', $edit.value], {}); |  | ||||||
|       } else if ($select.value !== $edit.value) { |  | ||||||
|         await storage.set( |  | ||||||
|           ['profiles', $edit.value], |  | ||||||
|           await storage.get(['profiles', $select.value], {}) |  | ||||||
|         ); |  | ||||||
|         await storage.set(['profiles', $select.value], undefined); |  | ||||||
|       } |  | ||||||
|       env.reload(); |  | ||||||
|     }); |  | ||||||
|     $delete.addEventListener('click', async (event) => { |  | ||||||
|       await storage.set(['profiles', $select.value], undefined); |  | ||||||
|       await storage.set( |  | ||||||
|         ['currentprofile'], |  | ||||||
|         profileNames.find((profile) => profile !== $select.value) || 'default' |  | ||||||
|       ); |  | ||||||
|       env.reload(); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     _$profileConfig = web.render( |  | ||||||
|       web.html`<div></div>`, |  | ||||||
|       web.html`<p class="options-placeholder">
 |  | ||||||
|         Profiles are used to switch entire configurations. |  | ||||||
|         Here they can be selected, renamed or deleted. |  | ||||||
|         Profile names can only contain letters, numbers, |  | ||||||
|         dashes and underscores. <br> |  | ||||||
|         Be careful - deleting a profile deletes all configuration |  | ||||||
|         related to it.  |  | ||||||
|       </p>`, |  | ||||||
|       web.render( |  | ||||||
|         web.html`<label class="input-label"></label>`, |  | ||||||
|         $select, |  | ||||||
|         web.html`${await components.feather('chevron-down', { class: 'input-icon' })}` |  | ||||||
|       ), |  | ||||||
|       web.render( |  | ||||||
|         web.html`<label class="input-label"></label>`, |  | ||||||
|         $edit, |  | ||||||
|         web.html`${await components.feather('type', { class: 'input-icon' })}` |  | ||||||
|       ), |  | ||||||
|       web.render(web.html`<p class="profile-actions"></p>`, $export, $import, $save, $delete), |  | ||||||
|       $error |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
|   web.render(web.empty($options), _$profileConfig); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const _$modListCache = {}, |  | ||||||
|   generators = { |  | ||||||
|     options: async (mod) => { |  | ||||||
|       const $fragment = document.createDocumentFragment(); |  | ||||||
|       for (const opt of mod.options) { |  | ||||||
|         web.render($fragment, await options[opt.type](mod, opt)); |  | ||||||
|       } |  | ||||||
|       if (!mod.options.length) { |  | ||||||
|         web.render($fragment, web.html`<p class="options-placeholder">No options.</p>`); |  | ||||||
|       } |  | ||||||
|       return $fragment; |  | ||||||
|     }, |  | ||||||
|     mod: async (mod) => { |  | ||||||
|       const $mod = web.html`<div class="mod" data-id="${web.escape(mod.id)}"></div>`, |  | ||||||
|         $toggle = blocks.toggle('', await registry.enabled(mod.id)); |  | ||||||
|       $toggle.addEventListener('change', async (event) => { |  | ||||||
|         if (event.target.checked && mod.tags.includes('theme')) { |  | ||||||
|           const mode = mod.tags.includes('light') ? 'light' : 'dark', |  | ||||||
|             id = mod.id, |  | ||||||
|             mods = await registry.list( |  | ||||||
|               (mod) => |  | ||||||
|                 mod.environments.includes(env.name) && |  | ||||||
|                 mod.tags.includes('theme') && |  | ||||||
|                 mod.tags.includes(mode) && |  | ||||||
|                 mod.id !== id |  | ||||||
|             ); |  | ||||||
|           for (const mod of mods) { |  | ||||||
|             profileDB.set(['_mods', mod.id], false); |  | ||||||
|             document.querySelector( |  | ||||||
|               `[data-id="${web.escape(mod.id)}"] .toggle-check` |  | ||||||
|             ).checked = false; |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|         profileDB.set(['_mods', mod.id], event.target.checked); |  | ||||||
|         notifications.onChange(); |  | ||||||
|       }); |  | ||||||
|       $mod.addEventListener('click', async (event) => { |  | ||||||
|         if ($mod.className === 'mod-selected') return; |  | ||||||
|         for (const $selected of document.querySelectorAll('.mod-selected')) { |  | ||||||
|           $selected.className = 'mod'; |  | ||||||
|         } |  | ||||||
|         $mod.className = 'mod-selected'; |  | ||||||
|         const fragment = [ |  | ||||||
|           web.render(blocks.title(mod.name), blocks.version(mod.version)), |  | ||||||
|           blocks.tags(mod.tags), |  | ||||||
|           await generators.options(mod), |  | ||||||
|         ]; |  | ||||||
|         web.render(web.empty($options), ...fragment); |  | ||||||
|       }); |  | ||||||
|       return web.render( |  | ||||||
|         web.html`<article class="mod-container"></article>`, |  | ||||||
|         web.render( |  | ||||||
|           $mod, |  | ||||||
|           mod.preview |  | ||||||
|             ? blocks.preview( |  | ||||||
|                 mod.preview.startsWith('http') |  | ||||||
|                   ? mod.preview |  | ||||||
|                   : fs.localPath(`repo/${mod._dir}/${mod.preview}`) |  | ||||||
|               ) |  | ||||||
|             : '', |  | ||||||
|           web.render( |  | ||||||
|             web.html`<div class="mod-body"></div>`, |  | ||||||
|             web.render(blocks.title(mod.name), blocks.version(mod.version)), |  | ||||||
|             blocks.tags(mod.tags), |  | ||||||
|             blocks.description(mod.description), |  | ||||||
|             blocks.authors(mod.authors), |  | ||||||
|             mod.environments.includes(env.name) && !registry.core.includes(mod.id) |  | ||||||
|               ? $toggle |  | ||||||
|               : '' |  | ||||||
|           ) |  | ||||||
|         ) |  | ||||||
|       ); |  | ||||||
|     }, |  | ||||||
|     modList: async (category, message = '') => { |  | ||||||
|       if (!_$modListCache[category]) { |  | ||||||
|         const $search = web.html`<input type="search" class="search"
 |  | ||||||
|           placeholder="Search ('/' to focus)">`,
 |  | ||||||
|           $list = web.html`<div class="mods-list"></div>`, |  | ||||||
|           mods = await registry.list( |  | ||||||
|             (mod) => mod.environments.includes(env.name) && mod.tags.includes(category) |  | ||||||
|           ); |  | ||||||
|         web.addHotkeyListener(['/'], () => $search.focus()); |  | ||||||
|         $search.addEventListener('input', (event) => { |  | ||||||
|           const query = $search.value.toLowerCase(); |  | ||||||
|           for (const $mod of $list.children) { |  | ||||||
|             const matches = !query || $mod.innerText.toLowerCase().includes(query); |  | ||||||
|             $mod.classList[matches ? 'remove' : 'add']('hidden'); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|         for (const mod of mods) { |  | ||||||
|           mod.tags = mod.tags.filter((tag) => tag !== category); |  | ||||||
|           web.render($list, await generators.mod(mod)); |  | ||||||
|           mod.tags.unshift(category); |  | ||||||
|         } |  | ||||||
|         _$modListCache[category] = web.render( |  | ||||||
|           web.html`<div></div>`, |  | ||||||
|           web.render( |  | ||||||
|             web.html`<label class="search-container"></label>`, |  | ||||||
|             $search, |  | ||||||
|             web.html`${await components.feather('search', { class: 'input-icon' })}` |  | ||||||
|           ), |  | ||||||
|           message ? web.html`<p class="main-message">${web.escape(message)}</p>` : '', |  | ||||||
|           $list |  | ||||||
|         ); |  | ||||||
|       } |  | ||||||
|       return _$modListCache[category]; |  | ||||||
|     }, |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
| const $notionNavItem = web.html`<h1 class="nav-notion">
 |  | ||||||
|     ${(await fs.getText('icon/colour.svg')).replace( |  | ||||||
|       /width="\d+" height="\d+"/, |  | ||||||
|       `class="nav-notion-icon"` |  | ||||||
|     )} |  | ||||||
|     <span>notion-enhancer</span> |  | ||||||
|   </h1>`; |  | ||||||
| $notionNavItem.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>`; |  | ||||||
| 
 |  | ||||||
| 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, |  | ||||||
|         web.html`<a href="https://notion-enhancer.github.io" class="nav-item">docs</a>`, |  | ||||||
|         web.html`<a href="https://discord.gg/sFWPXtA" class="nav-item">community</a>` |  | ||||||
|       ), |  | ||||||
|       $main |  | ||||||
|     ), |  | ||||||
|     web.render($sidebar, $profile, $options) |  | ||||||
|   ) |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| 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'; |  | ||||||
| 
 |  | ||||||
| router.addView('core', async () => { |  | ||||||
|   web.empty($main); |  | ||||||
|   selectNavItem($coreNavItem); |  | ||||||
|   return web.render($main, await generators.modList('core')); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| router.addView('extensions', async () => { |  | ||||||
|   web.empty($main); |  | ||||||
|   selectNavItem($extensionsNavItem); |  | ||||||
|   return web.render($main, await generators.modList('extension')); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| router.addView('themes', async () => { |  | ||||||
|   web.empty($main); |  | ||||||
|   selectNavItem($themesNavItem); |  | ||||||
|   return web.render( |  | ||||||
|     $main, |  | ||||||
|     await generators.modList( |  | ||||||
|       'theme', |  | ||||||
|       `Dark themes will only work when Notion is in dark mode,
 |  | ||||||
|       and light themes will only work when Notion is in light mode. |  | ||||||
|       Only one theme of each mode can be enabled at a time.` |  | ||||||
|     ) |  | ||||||
|   ); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| router.loadView('extensions', $main); |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "menu", |  | ||||||
|   "id": "a6621988-551d-495a-97d8-3c568bca2e9e", |  | ||||||
|   "version": "0.11.0", |  | ||||||
|   "description": "the enhancer's graphical menu, related buttons and shortcuts.", |  | ||||||
|   "tags": ["core"], |  | ||||||
|   "authors": [ |  | ||||||
|     { |  | ||||||
|       "name": "dragonwocky", |  | ||||||
|       "email": "thedragonring.bod@gmail.com", |  | ||||||
|       "homepage": "https://dragonwocky.me/", |  | ||||||
|       "avatar": "https://dragonwocky.me/avatar.jpg" |  | ||||||
|     } |  | ||||||
|   ], |  | ||||||
|   "css": { |  | ||||||
|     "client": ["client.css"], |  | ||||||
|     "menu": ["menu.css", "markdown.css"] |  | ||||||
|   }, |  | ||||||
|   "js": { |  | ||||||
|     "client": ["client.mjs"] |  | ||||||
|   }, |  | ||||||
|   "options": [ |  | ||||||
|     { |  | ||||||
|       "type": "hotkey", |  | ||||||
|       "key": "hotkey", |  | ||||||
|       "label": "toggle focus hotkey", |  | ||||||
|       "value": "Ctrl+Alt+E", |  | ||||||
|       "tooltip": "switches between notion & the enhancer menu" |  | ||||||
|     } |  | ||||||
|   ] |  | ||||||
| } |  | ||||||
| @ -1,86 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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'; |  | ||||||
| 
 |  | ||||||
| import { env, fs, storage, fmt, registry, web, components } from '../../api/_.mjs'; |  | ||||||
| import { tw } from './styles.mjs'; |  | ||||||
| 
 |  | ||||||
| export const notifications = { |  | ||||||
|   $container: web.html`<div class="notifications-container"></div>`, |  | ||||||
|   cache: await storage.get(['notifications'], []), |  | ||||||
|   provider: [ |  | ||||||
|     registry.welcomeNotification, |  | ||||||
|     ...(await fs.getJSON('https://notion-enhancer.github.io/notifications.json')), |  | ||||||
|   ], |  | ||||||
|   async add({ icon, message, id = undefined, color = undefined, link = undefined }) { |  | ||||||
|     const $notification = link |  | ||||||
|         ? web.html`<a
 |  | ||||||
|           href="${web.escape(link)}" |  | ||||||
|           class="${tw`notification-${color || 'default'}`}" |  | ||||||
|           role="alert" |  | ||||||
|           target="_blank" |  | ||||||
|         ></a>` |  | ||||||
|         : web.html`<p
 |  | ||||||
|           class="${tw`notification-${color || 'default'}`}" |  | ||||||
|           role="alert" |  | ||||||
|           tabindex="0" |  | ||||||
|         ></p>`, |  | ||||||
|       resolve = async () => { |  | ||||||
|         if (id !== undefined) { |  | ||||||
|           notifications.cache.push(id); |  | ||||||
|           await storage.set(['notifications'], notifications.cache); |  | ||||||
|         } |  | ||||||
|         $notification.remove(); |  | ||||||
|       }; |  | ||||||
|     $notification.addEventListener('click', resolve); |  | ||||||
|     $notification.addEventListener('keyup', (event) => { |  | ||||||
|       if (['Enter', ' '].includes(event.key)) resolve(); |  | ||||||
|     }); |  | ||||||
|     web.render( |  | ||||||
|       notifications.$container, |  | ||||||
|       web.render( |  | ||||||
|         $notification, |  | ||||||
|         web.html`<span class="notification-text markdown-inline">
 |  | ||||||
|           ${fmt.md.renderInline(message)} |  | ||||||
|         </span>`, |  | ||||||
|         web.html`${await components.feather(icon, { class: 'notification-icon' })}` |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
|     return $notification; |  | ||||||
|   }, |  | ||||||
|   _onChange: false, |  | ||||||
|   async onChange() { |  | ||||||
|     if (this._onChange) return; |  | ||||||
|     this._onChange = true; |  | ||||||
|     const $notification = await this.add({ |  | ||||||
|       icon: 'refresh-cw', |  | ||||||
|       message: 'Reload to apply changes.', |  | ||||||
|     }); |  | ||||||
|     $notification.addEventListener('click', env.reload); |  | ||||||
|   }, |  | ||||||
| }; |  | ||||||
| web.render(document.body, notifications.$container); |  | ||||||
| for (const notification of notifications.provider) { |  | ||||||
|   if ( |  | ||||||
|     !notifications.cache.includes(notification.id) && |  | ||||||
|     notification.version === env.version && |  | ||||||
|     (!notification.environments || notification.environments.includes(env.name)) |  | ||||||
|   ) { |  | ||||||
|     notifications.add(notification); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const errors = await registry.errors(); |  | ||||||
| if (errors.length) { |  | ||||||
|   console.log('[notion-enhancer] registry errors:'); |  | ||||||
|   console.table(errors); |  | ||||||
|   notifications.add({ |  | ||||||
|     icon: 'alert-circle', |  | ||||||
|     message: 'Failed to load mods (check console).', |  | ||||||
|     color: 'red', |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| @ -1,72 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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'; |  | ||||||
| 
 |  | ||||||
| import { web } from '../../api/_.mjs'; |  | ||||||
| 
 |  | ||||||
| let _defaultView = ''; |  | ||||||
| const _views = new Map(); |  | ||||||
| 
 |  | ||||||
| export function addView(name, loadFunc) { |  | ||||||
|   _views.set(name, loadFunc); |  | ||||||
| } |  | ||||||
| export function removeView(name) { |  | ||||||
|   _views.delete(name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function router(event) { |  | ||||||
|   event.preventDefault(); |  | ||||||
|   const anchor = event.path |  | ||||||
|     ? event.path.find((anchor) => anchor.nodeName === 'A') |  | ||||||
|     : event.target; |  | ||||||
|   if (location.search !== anchor.getAttribute('href')) { |  | ||||||
|     window.history.pushState(null, null, anchor.href); |  | ||||||
|     loadView(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| function navigator(event) { |  | ||||||
|   event.preventDefault(); |  | ||||||
|   const anchor = event.path |  | ||||||
|       ? event.path.find((anchor) => anchor.nodeName === 'A') |  | ||||||
|       : event.target, |  | ||||||
|     hash = anchor.getAttribute('href').slice(1); |  | ||||||
|   document.getElementById(hash).scrollIntoView(true); |  | ||||||
|   document.documentElement.scrollTop = 0; |  | ||||||
|   history.replaceState({ search: location.search, hash }, null, `#${hash}`); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export async function loadView(defaultView = null) { |  | ||||||
|   if (defaultView) _defaultView = defaultView; |  | ||||||
|   if (!_defaultView) throw new Error('no view root set.'); |  | ||||||
| 
 |  | ||||||
|   const query = web.queryParams(), |  | ||||||
|     fallbackView = () => { |  | ||||||
|       window.history.replaceState(null, null, `?view=${_defaultView}`); |  | ||||||
|       return loadView(); |  | ||||||
|     }; |  | ||||||
|   if (!query.get('view') || document.body.dataset.view !== query.get('view')) { |  | ||||||
|     if (_views.get(query.get('view'))) { |  | ||||||
|       await _views.get(query.get('view'))(); |  | ||||||
|     } else return fallbackView(); |  | ||||||
|   } else return fallbackView(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| window.addEventListener('popstate', (event) => { |  | ||||||
|   if (event.state) loadView(); |  | ||||||
|   document.getElementById(location.hash.slice(1))?.scrollIntoView(true); |  | ||||||
|   document.documentElement.scrollTop = 0; |  | ||||||
| }); |  | ||||||
| web.addDocumentObserver((mutation) => { |  | ||||||
|   mutation.target.querySelectorAll('a[href^="?"]').forEach((a) => { |  | ||||||
|     a.removeEventListener('click', router); |  | ||||||
|     a.addEventListener('click', router); |  | ||||||
|   }); |  | ||||||
|   mutation.target.querySelectorAll('a[href^="#"]').forEach((a) => { |  | ||||||
|     a.removeEventListener('click', navigator); |  | ||||||
|     a.addEventListener('click', navigator); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @ -1,157 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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-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 text-xs 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-divider h-64 sm:h-48 md: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 hover:bg-interactive-hover focus:bg-interactive-active`, |  | ||||||
|   'nav-item-selected': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium ring-1 ring-divider bg-notion-secondary`, |  | ||||||
|   'main': apply`transition px-4 py-3 overflow-y-auto max-h-full-64 sm:max-h-full-48 md:max-h-full-32 lg:max-h-full-16`, |  | ||||||
|   'main-message': apply`mx-2.5 my-2.5 px-px text-sm text-foreground-secondary text-justify`, |  | ||||||
|   '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-divider cursor-pointer`,
 |  | ||||||
|   'mod-selected': apply`mod ring ring-accent-blue-focus`, |  | ||||||
|   'mod-body': apply`px-4 py-3 flex flex-col flex-auto children:cursor-pointer`, |  | ||||||
|   '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-secondary 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`, |  | ||||||
|   'sidebar': apply`h-full w-96 px-4 pt-3 pb-32 flex flex-col bg-notion-secondary border-l border-divider`, |  | ||||||
|   'profile-trigger': apply`block px-4 py-3 mb-2 rounded-md text-sm text-left font-semibold shadow-inner
 |  | ||||||
|     bg-accent-red-hover border border-accent-red text-accent-red focus:(outline-none ring ring-inset ring-accent-red)`,
 |  | ||||||
|   'profile-actions': apply`flex`, |  | ||||||
|   'profile-save': apply`text-sm px-3 py-2 font-medium mt-2 bg-accent-blue text-accent-blue-text rounded-md flex-grow
 |  | ||||||
|     hover:bg-accent-blue-hover focus:(bg-accent-blue-focus outline-none) text-center`,
 |  | ||||||
|   'profile-delete': apply`text-sm px-3 py-2 font-medium ml-3 mt-2 bg-red-tag text-red-tag-text rounded-md flex-grow
 |  | ||||||
|     border border-red-text hover:bg-red-text focus:(outline-none bg-red-text) text-center`,
 |  | ||||||
|   'profile-export': apply`profile-save mr-2`, |  | ||||||
|   'profile-import': apply`profile-save mr-2`, |  | ||||||
|   'profile-error': apply`text-xs mt-2 text-red-text`, |  | ||||||
|   'profile-icon-action': apply`w-4 h-4 -mt-1 inline-block`, |  | ||||||
|   'profile-icon-text': apply`w-4 h-4 -mt-1 inline-block mr-1`, |  | ||||||
|   'options-container': apply`px-4 py-3 shadow-inner rounded-lg bg-notion border border-divider space-y-3`, |  | ||||||
|   'options-placeholder': apply`text-sm text-foreground-secondary`, |  | ||||||
|   'toggle-box': apply`w-9 h-5 p-0.5 flex items-center bg-toggle-off rounded-full duration-300 ease-in-out cursor-pointer`, |  | ||||||
|   'toggle-label': apply`relative text-sm flex w-full mt-auto`, |  | ||||||
|   'toggle-check': 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) cursor-pointer`, |  | ||||||
|   'input-label': apply`block text-sm mt-2 relative`, |  | ||||||
|   'input': apply`transition block w-full mt-2 pl-3 pr-14 py-2 text-sm rounded-md flex bg-input text-foreground
 |  | ||||||
|     appearance-none placeholder-foreground-secondary ring-1 ring-divider focus:(outline-none ring ring-accent-blue-focus)`,
 |  | ||||||
|   'input-tooltip': apply`h-4 w-4 -mt-1 inline-block mr-2`, |  | ||||||
|   'input-icon': apply`absolute w-11 h-9 right-0 bottom-0 py-2 px-3 bg-notion-secondary rounded-r-md text-icon`, |  | ||||||
|   'input-placeholder': apply`text-foreground-secondary`, |  | ||||||
|   'select-option': apply`bg-notion-secondary`, |  | ||||||
|   'file-latest': apply`block w-full text-left text-foreground-secondary text-xs mt-2 hover:line-through cursor-pointer`, |  | ||||||
|   'search-container': apply`block mx-2.5 my-2.5 relative`, |  | ||||||
|   'search': apply`input pr-12`, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| setup({ |  | ||||||
|   preflight: { |  | ||||||
|     html: apply`w-full h-full`, |  | ||||||
|     body: apply`w-full h-full bg-notion font-sans text-foreground`, |  | ||||||
|   }, |  | ||||||
|   theme: { |  | ||||||
|     fontFamily: { |  | ||||||
|       sans: ['var(--theme--font_sans)'], |  | ||||||
|       mono: ['var(--theme--font_mono)'], |  | ||||||
|     }, |  | ||||||
|     colors: { |  | ||||||
|       'notion': 'var(--theme--bg)', |  | ||||||
|       'notion-secondary': 'var(--theme--bg_secondary)', |  | ||||||
|       'notion-popup': 'var(--theme--bg_popup)', |  | ||||||
|       'divider': 'var(--theme--ui_divider)', |  | ||||||
|       'input': 'var(--theme--ui_input)', |  | ||||||
|       'icon': 'var(--theme--icon)', |  | ||||||
|       'icon-secondary': 'var(--theme--icon_secondary)', |  | ||||||
|       'foreground': 'var(--theme--text)', |  | ||||||
|       'foreground-secondary': 'var(--theme--text_secondary)', |  | ||||||
|       'interactive-hover': 'var(--theme--ui_interactive-hover)', |  | ||||||
|       'interactive-active': 'var(--theme--ui_interactive-active)', |  | ||||||
|       '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-focus': 'var(--theme--accent_blue-focus)', |  | ||||||
|         '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)', |  | ||||||
|         'full-64': 'calc(100% - 16rem)', |  | ||||||
|       }, |  | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
|   plugins: customClasses, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| tw`hidden ${Object.keys(customClasses).join(' ')}`; |  | ||||||
| 
 |  | ||||||
| export { tw }; |  | ||||||
| @ -1,8 +0,0 @@ | |||||||
| [ |  | ||||||
|   "menu@a6621988-551d-495a-97d8-3c568bca2e9e", |  | ||||||
|   "theming@0f0bf8b6-eae6-4273-b307-8fc43f2ee082", |  | ||||||
|   "components@36a2ffc9-27ff-480e-84a7-c7700a7d232d", |  | ||||||
|   "tweaks@5174a483-c88d-4bf8-a95f-35cd330b76e2", |  | ||||||
|   "bypass-preview@cb6fd684-f113-4a7a-9423-8f0f0cff069f", |  | ||||||
|   "calendar-scroll@b1c7db33-dfee-489a-a76c-0dd66f7ed29a" |  | ||||||
| ] |  | ||||||
| @ -1,20 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer core: theming |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| export default function (api, db) { |  | ||||||
|   const { web } = api; |  | ||||||
| 
 |  | ||||||
|   const updateTheme = () => |  | ||||||
|     document.documentElement.classList[ |  | ||||||
|       document.body.classList.contains('dark') ? 'add' : 'remove' |  | ||||||
|     ]('dark'); |  | ||||||
|   updateTheme(); |  | ||||||
|   web.addDocumentObserver((mutation) => { |  | ||||||
|     if (mutation.target === document.body) updateTheme(); |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| @ -1,24 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "theming", |  | ||||||
|   "id": "0f0bf8b6-eae6-4273-b307-8fc43f2ee082", |  | ||||||
|   "version": "0.11.0", |  | ||||||
|   "description": "the default theme variables, required by other themes & extensions.", |  | ||||||
|   "tags": ["core"], |  | ||||||
|   "authors": [ |  | ||||||
|     { |  | ||||||
|       "name": "dragonwocky", |  | ||||||
|       "email": "thedragonring.bod@gmail.com", |  | ||||||
|       "homepage": "https://dragonwocky.me/", |  | ||||||
|       "avatar": "https://dragonwocky.me/avatar.jpg" |  | ||||||
|     } |  | ||||||
|   ], |  | ||||||
|   "css": { |  | ||||||
|     "frame": ["variables.css"], |  | ||||||
|     "client": ["variables.css", "prism.css", "theme.css"], |  | ||||||
|     "menu": ["variables.css", "prism.css"] |  | ||||||
|   }, |  | ||||||
|   "js": { |  | ||||||
|     "client": ["client.mjs"] |  | ||||||
|   }, |  | ||||||
|   "options": [] |  | ||||||
| } |  | ||||||
| @ -1,156 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer core: theming |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| .token.property { |  | ||||||
|   color: var(--theme--code_property) !important; |  | ||||||
| } |  | ||||||
| .token.tag { |  | ||||||
|   color: var(--theme--code_tag) !important; |  | ||||||
| } |  | ||||||
| .token.boolean { |  | ||||||
|   color: var(--theme--code_boolean) !important; |  | ||||||
| } |  | ||||||
| .token.number { |  | ||||||
|   color: var(--theme--code_number) !important; |  | ||||||
| } |  | ||||||
| .token.constant { |  | ||||||
|   color: var(--theme--code_constant) !important; |  | ||||||
| } |  | ||||||
| .token.symbol { |  | ||||||
|   color: var(--theme--code_symbol) !important; |  | ||||||
| } |  | ||||||
| .token.deleted { |  | ||||||
|   color: var(--theme--code_deleted) !important; |  | ||||||
| } |  | ||||||
| .token.selector { |  | ||||||
|   color: var(--theme--code_selector) !important; |  | ||||||
| } |  | ||||||
| .token.attr-name { |  | ||||||
|   color: var(--theme--code_attr-name) !important; |  | ||||||
| } |  | ||||||
| .token.string { |  | ||||||
|   color: var(--theme--code_string) !important; |  | ||||||
| } |  | ||||||
| .token.char { |  | ||||||
|   color: var(--theme--code_char) !important; |  | ||||||
| } |  | ||||||
| .token.builtin { |  | ||||||
|   color: var(--theme--code_builtin) !important; |  | ||||||
| } |  | ||||||
| .token.inserted { |  | ||||||
|   color: var(--theme--code_inserted) !important; |  | ||||||
| } |  | ||||||
| .token.operator { |  | ||||||
|   color: var(--theme--code_operator) !important; |  | ||||||
| } |  | ||||||
| .token.entity { |  | ||||||
|   color: var(--theme--code_entity) !important; |  | ||||||
| } |  | ||||||
| .token.url { |  | ||||||
|   color: var(--theme--code_url) !important; |  | ||||||
| } |  | ||||||
| .token.variable { |  | ||||||
|   color: var(--theme--code_variable) !important; |  | ||||||
| } |  | ||||||
| .token.comment { |  | ||||||
|   color: var(--theme--code_comment) !important; |  | ||||||
| } |  | ||||||
| .token.cdata { |  | ||||||
|   color: var(--theme--code_cdata) !important; |  | ||||||
| } |  | ||||||
| .token.prolog { |  | ||||||
|   color: var(--theme--code_prolog) !important; |  | ||||||
| } |  | ||||||
| .token.doctype { |  | ||||||
|   color: var(--theme--code_doctype) !important; |  | ||||||
| } |  | ||||||
| .token.atrule { |  | ||||||
|   color: var(--theme--code_atrule) !important; |  | ||||||
| } |  | ||||||
| .token.attr-value { |  | ||||||
|   color: var(--theme--code_attr-value) !important; |  | ||||||
| } |  | ||||||
| .token.keyword { |  | ||||||
|   color: var(--theme--code_keyword) !important; |  | ||||||
| } |  | ||||||
| .token.regex { |  | ||||||
|   color: var(--theme--code_regex) !important; |  | ||||||
| } |  | ||||||
| .token.important { |  | ||||||
|   color: var(--theme--code_important) !important; |  | ||||||
| } |  | ||||||
| .token.function { |  | ||||||
|   color: var(--theme--code_function) !important; |  | ||||||
| } |  | ||||||
| .token.class-name { |  | ||||||
|   color: var(--theme--code_class-name) !important; |  | ||||||
| } |  | ||||||
| .token.parameter { |  | ||||||
|   color: var(--theme--code_parameter) !important; |  | ||||||
| } |  | ||||||
| .token.decorator { |  | ||||||
|   color: var(--theme--code_decorator) !important; |  | ||||||
| } |  | ||||||
| .token.id { |  | ||||||
|   color: var(--theme--code_id) !important; |  | ||||||
| } |  | ||||||
| .token.class { |  | ||||||
|   color: var(--theme--code_class) !important; |  | ||||||
| } |  | ||||||
| .token.pseudo-element { |  | ||||||
|   color: var(--theme--code_pseudo-element) !important; |  | ||||||
| } |  | ||||||
| .token.pseudo-class { |  | ||||||
|   color: var(--theme--code_pseudo-class) !important; |  | ||||||
| } |  | ||||||
| .token.attribute { |  | ||||||
|   color: var(--theme--code_attribute) !important; |  | ||||||
| } |  | ||||||
| .token.value { |  | ||||||
|   color: var(--theme--code_value) !important; |  | ||||||
| } |  | ||||||
| .token.unit { |  | ||||||
|   color: var(--theme--code_unit) !important; |  | ||||||
| } |  | ||||||
| .token.punctuation { |  | ||||||
|   color: var(--theme--code_punctuation) !important; |  | ||||||
|   opacity: 0.7 !important; |  | ||||||
| } |  | ||||||
| .token.annotation { |  | ||||||
|   color: var(--theme--code_annotation) !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .token.operator { |  | ||||||
|   background: transparent !important; |  | ||||||
| } |  | ||||||
| .token.namespace { |  | ||||||
|   opacity: 0.7 !important; |  | ||||||
| } |  | ||||||
| .token.important, |  | ||||||
| .token.bold { |  | ||||||
|   font-weight: bold !important; |  | ||||||
| } |  | ||||||
| .token.italic { |  | ||||||
|   font-style: italic !important; |  | ||||||
| } |  | ||||||
| .token.entity { |  | ||||||
|   cursor: help !important; |  | ||||||
| } |  | ||||||
| .token a { |  | ||||||
|   color: inherit !important; |  | ||||||
| } |  | ||||||
| .token.punctuation.brace-hover, |  | ||||||
| .token.punctuation.brace-selected { |  | ||||||
|   outline: solid 1px !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .token.operator, |  | ||||||
| .token.entity, |  | ||||||
| .token.url, |  | ||||||
| .language-css .token.string, |  | ||||||
| .style .token.string { |  | ||||||
|   background: none !important; |  | ||||||
| } |  | ||||||
| @ -1,364 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer core: theming |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license |  | ||||||
|  * |  | ||||||
|  * (rgb|hsl|#)[^;]+; |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| :root { |  | ||||||
|   --theme--page-padding: calc(96px + env(safe-area-inset-left)); |  | ||||||
|   --theme--page-width: 900px; |  | ||||||
|   --theme--page-width_full: 100%; |  | ||||||
|   --theme--page_banner-height: 30vh; |  | ||||||
|   --theme--page_preview-padding: 8rem; |  | ||||||
|   --theme--page_preview-width: 977px; |  | ||||||
|   --theme--page_preview_banner-height: 20vh; |  | ||||||
| 
 |  | ||||||
|   --theme--font_sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, |  | ||||||
|     'Apple Color Emoji', Arial, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; |  | ||||||
|   --theme--font_serif: Lyon-Text, Georgia, YuMincho, 'Yu Mincho', 'Hiragino Mincho ProN', |  | ||||||
|     'Hiragino Mincho Pro', 'Songti TC', 'Songti SC', SimSun, 'Nanum Myeongjo', NanumMyeongjo, |  | ||||||
|     Batang, serif; |  | ||||||
|   --theme--font_mono: iawriter-mono, Nitti, Menlo, Courier, monospace; |  | ||||||
|   --theme--font_code: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; |  | ||||||
|   --theme--font_quote: var(--theme--font_sans); |  | ||||||
|   --theme--font_headings: var(--theme--font_sans); |  | ||||||
| 
 |  | ||||||
|   --theme--accent_blue: rgb(46, 170, 220); |  | ||||||
|   --theme--accent_blue-selection: rgb(46, 170, 220, 0.25); |  | ||||||
|   --theme--accent_blue-hover: rgb(6, 156, 205); |  | ||||||
|   --theme--accent_blue-focus: rgb(0, 141, 190); |  | ||||||
|   --theme--accent_blue-text: #fff; |  | ||||||
|   --theme--accent_red: #eb5757; |  | ||||||
|   --theme--accent_red-hover: rgba(235, 87, 87, 0.1); |  | ||||||
|   --theme--accent_red-text: #fff; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| :root { |  | ||||||
|   --theme--bg: #fff; |  | ||||||
|   --theme--bg_secondary: rgb(247, 246, 243); |  | ||||||
|   --theme--bg_popup: #fff; |  | ||||||
| 
 |  | ||||||
|   --theme--scrollbar_track: #edece9; |  | ||||||
|   --theme--scrollbar_thumb: #d3d1cb; |  | ||||||
|   --theme--scrollbar_thumb-hover: #aeaca6; |  | ||||||
| 
 |  | ||||||
|   --theme--ui_shadow: rgba(15, 15, 15, 0.15); |  | ||||||
|   --theme--ui_divider: rgb(237, 237, 236); |  | ||||||
|   --theme--ui_interactive-hover: rgba(55, 53, 47, 0.08); |  | ||||||
|   --theme--ui_interactive-active: rgba(55, 53, 47, 0.16); |  | ||||||
|   --theme--ui_toggle-on: var(--theme--accent_blue); |  | ||||||
|   --theme--ui_toggle-off: rgba(135, 131, 120, 0.3); |  | ||||||
|   --theme--ui_toggle-feature: #fff; |  | ||||||
|   --theme--ui_input: rgba(242, 241, 238, 0.6); |  | ||||||
|   --theme--ui_tooltip: rgb(15, 15, 15); |  | ||||||
|   --theme--ui_tooltip-title: rgba(255, 255, 255, 0.9); |  | ||||||
|   --theme--ui_tooltip-description: rgba(206, 205, 202, 0.6); |  | ||||||
| 
 |  | ||||||
|   --theme--icon: rgba(55, 53, 47, 0.8); |  | ||||||
|   --theme--icon_secondary: rgba(55, 53, 47, 0.4); |  | ||||||
| 
 |  | ||||||
|   --theme--text: rgb(55, 43, 47); |  | ||||||
|   --theme--text_secondary: rgba(55, 43, 47, 0.6); |  | ||||||
|   --theme--text_grey: rgb(155, 154, 151); |  | ||||||
|   --theme--text_brown: rgb(100, 71, 58); |  | ||||||
|   --theme--text_orange: rgb(217, 115, 13); |  | ||||||
|   --theme--text_yellow: rgb(223, 171, 1); |  | ||||||
|   --theme--text_green: rgb(15, 123, 108); |  | ||||||
|   --theme--text_blue: rgb(11, 110, 153); |  | ||||||
|   --theme--text_purple: rgb(105, 64, 165); |  | ||||||
|   --theme--text_pink: rgb(173, 26, 114); |  | ||||||
|   --theme--text_red: rgb(224, 62, 62); |  | ||||||
| 
 |  | ||||||
|   --theme--highlight-text: var(--theme--text); |  | ||||||
|   --theme--highlight_grey: rgb(235, 236, 237); |  | ||||||
|   --theme--highlight_grey-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_brown: rgb(233, 229, 227); |  | ||||||
|   --theme--highlight_brown-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_orange: rgb(250, 235, 221); |  | ||||||
|   --theme--highlight_orange-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_yellow: rgb(251, 243, 219); |  | ||||||
|   --theme--highlight_yellow-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_green: rgb(221, 237, 234); |  | ||||||
|   --theme--highlight_green-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_blue: rgb(221, 235, 241); |  | ||||||
|   --theme--highlight_blue-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_purple: rgb(234, 228, 242); |  | ||||||
|   --theme--highlight_purple-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_pink: rgb(244, 223, 235); |  | ||||||
|   --theme--highlight_pink-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_red: rgb(251, 228, 228); |  | ||||||
|   --theme--highlight_red-text: var(--theme--highlight-text); |  | ||||||
| 
 |  | ||||||
|   --theme--block-text: var(--theme--text); |  | ||||||
|   --theme--block_grey: rgb(235, 236, 237); |  | ||||||
|   --theme--block_grey-text: var(--theme--block-text); |  | ||||||
|   --theme--block_brown: rgb(233, 229, 227); |  | ||||||
|   --theme--block_brown-text: var(--theme--block-text); |  | ||||||
|   --theme--block_orange: rgb(250, 235, 221); |  | ||||||
|   --theme--block_orange-text: var(--theme--block-text); |  | ||||||
|   --theme--block_yellow: rgb(251, 243, 219); |  | ||||||
|   --theme--block_yellow-text: var(--theme--block-text); |  | ||||||
|   --theme--block_green: rgb(221, 237, 234); |  | ||||||
|   --theme--block_green-text: var(--theme--block-text); |  | ||||||
|   --theme--block_blue: rgb(221, 235, 241); |  | ||||||
|   --theme--block_blue-text: var(--theme--block-text); |  | ||||||
|   --theme--block_purple: rgb(234, 228, 242); |  | ||||||
|   --theme--block_purple-text: var(--theme--block-text); |  | ||||||
|   --theme--block_pink: rgb(244, 223, 235); |  | ||||||
|   --theme--block_pink-text: var(--theme--block-text); |  | ||||||
|   --theme--block_red: rgb(251, 228, 228); |  | ||||||
|   --theme--block_red-text: var(--theme--block-text); |  | ||||||
| 
 |  | ||||||
|   --theme--tag-text: var(--theme--text); |  | ||||||
|   --theme--tag_default: rgba(206, 205, 202, 0.5); |  | ||||||
|   --theme--tag_default-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_grey: rgba(140, 46, 0, 0.2); |  | ||||||
|   --theme--tag_grey-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_brown: rgba(140, 46, 0, 0.2); |  | ||||||
|   --theme--tag_brown-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_orange: rgba(245, 93, 0, 0.2); |  | ||||||
|   --theme--tag_orange-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_yellow: rgba(233, 168, 0, 0.2); |  | ||||||
|   --theme--tag_yellow-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_green: rgba(0, 135, 107, 0.2); |  | ||||||
|   --theme--tag_green-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_blue: rgba(0, 120, 223, 0.2); |  | ||||||
|   --theme--tag_blue-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_purple: rgba(103, 36, 222, 0.2); |  | ||||||
|   --theme--tag_purple-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_pink: rgba(221, 0, 129, 0.2); |  | ||||||
|   --theme--tag_pink-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_red: rgba(255, 0, 26, 0.2); |  | ||||||
|   --theme--tag_red-text: var(--theme--tag-text); |  | ||||||
| 
 |  | ||||||
|   --theme--callout-text: var(--theme--text); |  | ||||||
|   --theme--callout_grey: rgba(235, 236, 237, 0.3); |  | ||||||
|   --theme--callout_grey-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_brown: rgba(233, 229, 227, 0.3); |  | ||||||
|   --theme--callout_brown-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_orange: rgba(250, 235, 221, 0.3); |  | ||||||
|   --theme--callout_orange-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_yellow: rgba(251, 243, 219, 0.3); |  | ||||||
|   --theme--callout_yellow-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_green: rgba(221, 237, 234, 0.3); |  | ||||||
|   --theme--callout_green-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_blue: rgba(221, 235, 241, 0.3); |  | ||||||
|   --theme--callout_blue-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_purple: rgba(234, 228, 242, 0.3); |  | ||||||
|   --theme--callout_purple-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_pink: rgba(244, 223, 235, 0.3); |  | ||||||
|   --theme--callout_pink-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_red: rgba(251, 228, 228, 0.3); |  | ||||||
|   --theme--callout_red-text: var(--theme--callout-text); |  | ||||||
| 
 |  | ||||||
|   --theme--code_inline: rgba(135, 131, 120, 0.15); |  | ||||||
|   --theme--code_inline-text: #eb5757; |  | ||||||
| 
 |  | ||||||
|   --theme--code: #f7f6f3; |  | ||||||
|   --theme--code_plain: var(--theme--text); |  | ||||||
|   --theme--code_property: #905; |  | ||||||
|   --theme--code_tag: var(--theme--code_property); |  | ||||||
|   --theme--code_boolean: var(--theme--code_property); |  | ||||||
|   --theme--code_number: var(--theme--code_property); |  | ||||||
|   --theme--code_constant: var(--theme--code_property); |  | ||||||
|   --theme--code_symbol: var(--theme--code_property); |  | ||||||
|   --theme--code_deleted: var(--theme--code_property); |  | ||||||
|   --theme--code_selector: #690; |  | ||||||
|   --theme--code_attr-name: var(--theme--code_selector); |  | ||||||
|   --theme--code_string: var(--theme--code_selector); |  | ||||||
|   --theme--code_char: var(--theme--code_selector); |  | ||||||
|   --theme--code_builtin: var(--theme--code_selector); |  | ||||||
|   --theme--code_inserted: var(--theme--code_selector); |  | ||||||
|   --theme--code_operator: #9a6e3a; |  | ||||||
|   --theme--code_entity: var(--theme--code_operator); |  | ||||||
|   --theme--code_url: var(--theme--code_operator); |  | ||||||
|   --theme--code_variable: var(--theme--code_regex); |  | ||||||
|   --theme--code_comment: slategrey; |  | ||||||
|   --theme--code_cdata: var(--theme--code_comment); |  | ||||||
|   --theme--code_prolog: var(--theme--code_comment); |  | ||||||
|   --theme--code_doctype: var(--theme--code_comment); |  | ||||||
|   --theme--code_atrule: #07a; |  | ||||||
|   --theme--code_attr-value: var(--theme--code_atrule); |  | ||||||
|   --theme--code_keyword: var(--theme--code_atrule); |  | ||||||
|   --theme--code_regex: #e90; |  | ||||||
|   --theme--code_important: var(--theme--code_regex); |  | ||||||
|   --theme--code_function: #dd4a68; |  | ||||||
|   --theme--code_class-name: var(--theme--code_function); |  | ||||||
|   --theme--code_parameter: var(--theme--code_plain); |  | ||||||
|   --theme--code_decorator: var(--theme--code_plain); |  | ||||||
|   --theme--code_id: var(--theme--code_plain); |  | ||||||
|   --theme--code_class: var(--theme--code_plain); |  | ||||||
|   --theme--code_pseudo-element: var(--theme--code_plain); |  | ||||||
|   --theme--code_pseudo-class: var(--theme--code_plain); |  | ||||||
|   --theme--code_attribute: var(--theme--code_plain); |  | ||||||
|   --theme--code_value: var(--theme--code_plain); |  | ||||||
|   --theme--code_unit: var(--theme--code_plain); |  | ||||||
|   --theme--code_punctuation: #999; |  | ||||||
|   --theme--code_annotation: var(--theme--code_plain); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| :root.dark { |  | ||||||
|   --theme--bg: rgb(47, 52, 55); |  | ||||||
|   --theme--bg_secondary: rgb(55, 60, 63); |  | ||||||
|   --theme--bg_popup: rgb(63, 68, 71); |  | ||||||
| 
 |  | ||||||
|   --theme--scrollbar_track: rgba(202, 204, 206, 0.04); |  | ||||||
|   --theme--scrollbar_thumb: #474c50; |  | ||||||
|   --theme--scrollbar_thumb-hover: rgba(202, 204, 206, 0.3); |  | ||||||
| 
 |  | ||||||
|   --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-active: rgb(63, 68, 71); |  | ||||||
|   --theme--ui_toggle-on: var(--theme--accent_blue); |  | ||||||
|   --theme--ui_toggle-off: rgba(202, 204, 206, 0.3); |  | ||||||
|   --theme--ui_toggle-feature: #fff; |  | ||||||
|   --theme--ui_input: rgba(15, 15, 15, 0.3); |  | ||||||
|   --theme--ui_tooltip: rgb(202, 204, 206); |  | ||||||
|   --theme--ui_tooltip-title: rgb(15, 15, 15); |  | ||||||
|   --theme--ui_tooltip-description: rgba(47, 52, 55, 0.6); |  | ||||||
| 
 |  | ||||||
|   --theme--icon: rgba(202, 204, 206); |  | ||||||
|   --theme--icon_secondary: rgb(202, 204, 206, 0.6); |  | ||||||
| 
 |  | ||||||
|   --theme--text: rgba(255, 255, 255, 0.9); |  | ||||||
|   --theme--text_secondary: rgba(255, 255, 255, 0.6); |  | ||||||
|   --theme--text_grey: rgba(151, 154, 155, 0.95); |  | ||||||
|   --theme--text_brown: rgb(147, 114, 100); |  | ||||||
|   --theme--text_orange: rgb(255, 163, 68); |  | ||||||
|   --theme--text_yellow: rgb(255, 220, 73); |  | ||||||
|   --theme--text_green: rgb(77, 171, 154); |  | ||||||
|   --theme--text_blue: rgb(82, 156, 202); |  | ||||||
|   --theme--text_purple: rgb(154, 109, 215); |  | ||||||
|   --theme--text_pink: rgb(226, 85, 161); |  | ||||||
|   --theme--text_red: rgb(255, 115, 105); |  | ||||||
| 
 |  | ||||||
|   --theme--highlight-text: var(--theme--text); |  | ||||||
|   --theme--highlight_grey: rgb(69, 75, 78); |  | ||||||
|   --theme--highlight_grey-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_brown: rgb(67, 64, 64); |  | ||||||
|   --theme--highlight_brown-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_orange: rgb(89, 74, 58); |  | ||||||
|   --theme--highlight_orange-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_yellow: rgb(89, 86, 59); |  | ||||||
|   --theme--highlight_yellow-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_green: rgb(53, 76, 75); |  | ||||||
|   --theme--highlight_green-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_blue: rgb(54, 73, 84); |  | ||||||
|   --theme--highlight_blue-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_purple: rgb(68, 63, 87); |  | ||||||
|   --theme--highlight_purple-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_pink: rgb(83, 59, 76); |  | ||||||
|   --theme--highlight_pink-text: var(--theme--highlight-text); |  | ||||||
|   --theme--highlight_red: rgb(89, 65, 65); |  | ||||||
|   --theme--highlight_red-text: var(--theme--highlight-text); |  | ||||||
| 
 |  | ||||||
|   --theme--block-text: var(--theme--text); |  | ||||||
|   --theme--block_grey: rgb(69, 75, 78); |  | ||||||
|   --theme--block_grey-text: var(--theme--block-text); |  | ||||||
|   --theme--block_brown: rgb(67, 64, 64); |  | ||||||
|   --theme--block_brown-text: var(--theme--block-text); |  | ||||||
|   --theme--block_orange: rgb(89, 74, 58); |  | ||||||
|   --theme--block_orange-text: var(--theme--block-text); |  | ||||||
|   --theme--block_yellow: rgb(89, 86, 59); |  | ||||||
|   --theme--block_yellow-text: var(--theme--block-text); |  | ||||||
|   --theme--block_green: rgb(53, 76, 75); |  | ||||||
|   --theme--block_green-text: var(--theme--block-text); |  | ||||||
|   --theme--block_blue: rgb(54, 73, 84); |  | ||||||
|   --theme--block_blue-text: var(--theme--block-text); |  | ||||||
|   --theme--block_purple: rgb(68, 63, 87); |  | ||||||
|   --theme--block_purple-text: var(--theme--block-text); |  | ||||||
|   --theme--block_pink: rgb(83, 59, 76); |  | ||||||
|   --theme--block_pink-text: var(--theme--block-text); |  | ||||||
|   --theme--block_red: rgb(89, 65, 65); |  | ||||||
|   --theme--block_red-text: var(--theme--block-text); |  | ||||||
| 
 |  | ||||||
|   --theme--tag-text: var(--theme--text); |  | ||||||
|   --theme--tag_default: rgb(80, 85, 88); |  | ||||||
|   --theme--tag_default-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_grey: rgba(151, 154, 155, 0.5); |  | ||||||
|   --theme--tag_grey-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_brown: rgba(147, 114, 100, 0.5); |  | ||||||
|   --theme--tag_brown-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_orange: rgba(255, 163, 68, 0.5); |  | ||||||
|   --theme--tag_orange-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_yellow: rgba(255, 220, 73, 0.5); |  | ||||||
|   --theme--tag_yellow-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_green: rgba(77, 171, 154, 0.5); |  | ||||||
|   --theme--tag_green-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_blue: rgba(82, 156, 202, 0.5); |  | ||||||
|   --theme--tag_blue-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_purple: rgba(154, 109, 215, 0.5); |  | ||||||
|   --theme--tag_purple-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_pink: rgba(226, 85, 161, 0.5); |  | ||||||
|   --theme--tag_pink-text: var(--theme--tag-text); |  | ||||||
|   --theme--tag_red: rgba(255, 115, 105, 0.5); |  | ||||||
|   --theme--tag_red-text: var(--theme--tag-text); |  | ||||||
| 
 |  | ||||||
|   --theme--callout-text: var(--theme--text); |  | ||||||
|   --theme--callout_grey: rgba(69, 75, 78, 0.3); |  | ||||||
|   --theme--callout_grey-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_brown: rgba(67, 64, 64, 0.3); |  | ||||||
|   --theme--callout_brown-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_orange: rgba(89, 74, 58, 0.3); |  | ||||||
|   --theme--callout_orange-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_yellow: rgba(89, 86, 59, 0.3); |  | ||||||
|   --theme--callout_yellow-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_green: rgba(53, 76, 75, 0.3); |  | ||||||
|   --theme--callout_green-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_blue: rgba(54, 73, 84, 0.3); |  | ||||||
|   --theme--callout_blue-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_purple: rgba(68, 63, 87, 0.3); |  | ||||||
|   --theme--callout_purple-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_pink: rgba(83, 59, 76, 0.3); |  | ||||||
|   --theme--callout_pink-text: var(--theme--callout-text); |  | ||||||
|   --theme--callout_red: rgba(89, 65, 65, 0.3); |  | ||||||
|   --theme--callout_red-text: var(--theme--callout-text); |  | ||||||
| 
 |  | ||||||
|   --theme--code_inline: rgba(135, 131, 120, 0.15); |  | ||||||
|   --theme--code_inline-text: #eb5757; |  | ||||||
| 
 |  | ||||||
|   --theme--code: rgb(63, 68, 71); |  | ||||||
|   --theme--code_plain: var(--theme--text); |  | ||||||
|   --theme--code_property: hsl(350, 40%, 70%); |  | ||||||
|   --theme--code_tag: var(--theme--code_property); |  | ||||||
|   --theme--code_boolean: var(--theme--code_property); |  | ||||||
|   --theme--code_number: var(--theme--code_property); |  | ||||||
|   --theme--code_constant: var(--theme--code_property); |  | ||||||
|   --theme--code_symbol: var(--theme--code_property); |  | ||||||
|   --theme--code_deleted: #f00; |  | ||||||
|   --theme--code_selector: hsl(75, 70%, 60%); |  | ||||||
|   --theme--code_attr-name: var(--theme--code_selector); |  | ||||||
|   --theme--code_string: var(--theme--code_selector); |  | ||||||
|   --theme--code_char: var(--theme--code_selector); |  | ||||||
|   --theme--code_builtin: var(--theme--code_selector); |  | ||||||
|   --theme--code_inserted: var(--theme--code_selector); |  | ||||||
|   --theme--code_operator: hsl(40, 90%, 60%); |  | ||||||
|   --theme--code_entity: var(--theme--code_operator); |  | ||||||
|   --theme--code_url: var(--theme--code_operator); |  | ||||||
|   --theme--code_variable: var(--theme--code_operator); |  | ||||||
|   --theme--code_comment: hsl(30, 20%, 50%); |  | ||||||
|   --theme--code_cdata: var(--theme--code_comment); |  | ||||||
|   --theme--code_prolog: var(--theme--code_comment); |  | ||||||
|   --theme--code_doctype: var(--theme--code_comment); |  | ||||||
|   --theme--code_atrule: hsl(350, 40%, 70%); |  | ||||||
|   --theme--code_attr-value: var(--theme--code_atrule); |  | ||||||
|   --theme--code_keyword: var(--theme--code_atrule); |  | ||||||
|   --theme--code_regex: #e90; |  | ||||||
|   --theme--code_important: var(--theme--code_regex); |  | ||||||
|   --theme--code_function: var(--theme--code_plain); |  | ||||||
|   --theme--code_class-name: var(--theme--code_function); |  | ||||||
|   --theme--code_parameter: var(--theme--code_plain); |  | ||||||
|   --theme--code_decorator: var(--theme--code_plain); |  | ||||||
|   --theme--code_id: var(--theme--code_plain); |  | ||||||
|   --theme--code_class: var(--theme--code_plain); |  | ||||||
|   --theme--code_pseudo-element: var(--theme--code_plain); |  | ||||||
|   --theme--code_pseudo-class: var(--theme--code_plain); |  | ||||||
|   --theme--code_attribute: var(--theme--code_plain); |  | ||||||
|   --theme--code_value: var(--theme--code_plain); |  | ||||||
|   --theme--code_unit: var(--theme--code_plain); |  | ||||||
|   --theme--code_punctuation: var(--theme--code_plain); |  | ||||||
|   --theme--code_annotation: var(--theme--code_plain); |  | ||||||
| } |  | ||||||
| @ -1,61 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer: tweaks |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/) |  | ||||||
|  * (c) 2020 arecsu |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| .tweak--snappy_transitions * { |  | ||||||
|   animation-duration: 0s !important; |  | ||||||
|   transition-duration: 0s !important; |  | ||||||
| } |  | ||||||
| .tweak--snappy_transitions .notion-selectable-halo { |  | ||||||
|   opacity: 1 !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .tweak--hide_help .notion-help-button { |  | ||||||
|   display: none !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .tweak--thicker_bold .notion-page-content span[style*='font-weight:600'] { |  | ||||||
|   font-weight: 700 !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .tweak--spaced_lines .notion-page-content .notion-selectable.notion-text-block { |  | ||||||
|   line-height: 1.65 !important; |  | ||||||
|   margin-top: 0.75em !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .tweak--condensed_bullets .notion-selectable.notion-bulleted_list-block { |  | ||||||
|   margin-top: -1.5px !important; |  | ||||||
|   margin-bottom: -1.5px !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .tweak--responsive_breakpoint .notion-column_list-block [style='display: flex;'] > div { |  | ||||||
|   width: 100% !important; |  | ||||||
| } |  | ||||||
| .tweak--responsive_breakpoint .notion-column_list-block [style='display: flex;'] { |  | ||||||
|   flex-direction: column !important; |  | ||||||
| } |  | ||||||
| .tweak--responsive_breakpoint .notion-app-inner { |  | ||||||
|   --theme--page-width: 100%; |  | ||||||
|   --theme--page-padding: calc(48px + env(safe-area-inset-left)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .tweak--bracketed_links .notion-link-token span { |  | ||||||
|   border-bottom: none !important; |  | ||||||
| } |  | ||||||
| .tweak--bracketed_links .notion-link-token:before { |  | ||||||
|   content: '[['; |  | ||||||
|   opacity: 0.7; |  | ||||||
|   transition: opacity 100ms ease-in; |  | ||||||
| } |  | ||||||
| .tweak--bracketed_links .notion-link-token:after { |  | ||||||
|   content: ']]'; |  | ||||||
|   opacity: 0.7; |  | ||||||
|   transition: opacity 100ms ease-in; |  | ||||||
| } |  | ||||||
| .tweak--bracketed_links .notion-link-token:hover::before, |  | ||||||
| .tweak--bracketed_links .notion-link-token:hover::after { |  | ||||||
|   opacity: 1; |  | ||||||
| } |  | ||||||
| @ -1,49 +0,0 @@ | |||||||
| /* |  | ||||||
|  * notion-enhancer: tweaks |  | ||||||
|  * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 |  | ||||||
|  * (https://notion-enhancer.github.io/) under the MIT license
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| const _id = '5174a483-c88d-4bf8-a95f-35cd330b76e2'; |  | ||||||
| import { env, storage, web } from '../../api/_.mjs'; |  | ||||||
| 
 |  | ||||||
| web.whenReady().then(async () => { |  | ||||||
|   const cssInsert = await storage.get(_id, '_file.insert.css'); |  | ||||||
|   if (cssInsert) { |  | ||||||
|     document.body.append( |  | ||||||
|       web.createElement( |  | ||||||
|         web.html` |  | ||||||
|         <style id="${await storage.get(_id, 'insert.css')}@${_id}">${cssInsert}</style>` |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (['linux', 'win32'].includes(env.name)) { |  | ||||||
|     // dragarea_height
 |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   for (const tweak of [ |  | ||||||
|     'snappy_transitions', |  | ||||||
|     'thicker_bold', |  | ||||||
|     'spaced_lines', |  | ||||||
|     'hide_help', |  | ||||||
|     'condensed_bullets', |  | ||||||
|     'bracketed_links', |  | ||||||
|   ]) { |  | ||||||
|     if (await storage.get(_id, `tweak.${tweak}`)) { |  | ||||||
|       document.body.classList.add(`tweak--${tweak}`); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   const responsiveBreakpoint = await storage.get(_id, 'tweak.responsive_breakpoint'), |  | ||||||
|     addResponsiveBreakpoint = () => { |  | ||||||
|       document.body.classList.remove('tweak--responsive_breakpoint'); |  | ||||||
|       if (window.innerWidth <= responsiveBreakpoint) { |  | ||||||
|         document.body.classList.add('tweak--responsive_breakpoint'); |  | ||||||
|       } |  | ||||||
|     }; |  | ||||||
|   window.addEventListener('resize', addResponsiveBreakpoint); |  | ||||||
|   addResponsiveBreakpoint(); |  | ||||||
| }); |  | ||||||
| @ -1,84 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "tweaks", |  | ||||||
|   "id": "5174a483-c88d-4bf8-a95f-35cd330b76e2", |  | ||||||
|   "version": "0.2.0", |  | ||||||
|   "description": "common style/layout changes and custom CSS insertion.", |  | ||||||
|   "tags": ["extension", "customisation"], |  | ||||||
|   "authors": [ |  | ||||||
|     { |  | ||||||
|       "name": "dragonwocky", |  | ||||||
|       "email": "thedragonring.bod@gmail.com", |  | ||||||
|       "homepage": "https://dragonwocky.me/", |  | ||||||
|       "avatar": "https://dragonwocky.me/avatar.jpg" |  | ||||||
|     } |  | ||||||
|   ], |  | ||||||
|   "css": { |  | ||||||
|     "client": ["client.css"] |  | ||||||
|   }, |  | ||||||
|   "js": { |  | ||||||
|     "client": ["client.mjs"] |  | ||||||
|   }, |  | ||||||
|   "options": [ |  | ||||||
|     { |  | ||||||
|       "type": "file", |  | ||||||
|       "key": "insert.css", |  | ||||||
|       "label": "css insert", |  | ||||||
|       "extensions": [".css"] |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "key": "tweak.dragarea_height", |  | ||||||
|       "label": "height of frameless dragarea:", |  | ||||||
|       "tooltip": "the rectangle added at the top of a window in 'integrated titlebar' mode, used to drag/move the window.", |  | ||||||
|       "type": "number", |  | ||||||
|       "value": 15, |  | ||||||
|       "environments": ["linux", "win32"] |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "key": "tweak.responsive_breakpoint", |  | ||||||
|       "label": "responsive columns breakpoint (px)", |  | ||||||
|       "tooltip": "the width in pixels below which in-page columns are resized to appear full-width so content isn't squished.", |  | ||||||
|       "type": "number", |  | ||||||
|       "value": 600 |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "key": "tweak.snappy_transitions", |  | ||||||
|       "label": "snappy transitions", |  | ||||||
|       "tooltip": "set animation time for all css-driven animations to 0s. may not affect element motion e.g. the sidebar popping out.", |  | ||||||
|       "type": "toggle", |  | ||||||
|       "value": false |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "key": "tweak.hide_help", |  | ||||||
|       "label": "hide help button", |  | ||||||
|       "type": "toggle", |  | ||||||
|       "value": false |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "key": "tweak.thicker_bold", |  | ||||||
|       "label": "thicker bold text", |  | ||||||
|       "type": "toggle", |  | ||||||
|       "value": true |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "key": "tweak.spaced_lines", |  | ||||||
|       "label": "readable line spacing", |  | ||||||
|       "tooltip": "greater line spacing between text blocks.", |  | ||||||
|       "type": "toggle", |  | ||||||
|       "value": false |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "key": "tweak.condensed_bullets", |  | ||||||
|       "label": "condense bullet points", |  | ||||||
|       "tooltip": "tighter line spacing between bullet point blocks.", |  | ||||||
|       "type": "toggle", |  | ||||||
|       "value": false |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "key": "tweak.bracketed_links", |  | ||||||
|       "label": "bracketed links", |  | ||||||
|       "tooltip": "render links surrounded with [[brackets]] instead of __underlined__.", |  | ||||||
|       "type": "toggle", |  | ||||||
|       "value": false |  | ||||||
|     } |  | ||||||
|   ] |  | ||||||
| } |  | ||||||
| @ -6,11 +6,9 @@ | |||||||
| 
 | 
 | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| async function focusMenu() { | function focusMenu() { | ||||||
|   chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => { |   chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => { | ||||||
|     const url = chrome.runtime.getURL( |     const url = chrome.runtime.getURL('repo/menu/menu.html'), | ||||||
|         'repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.html' |  | ||||||
|       ), |  | ||||||
|       menu = tabs.find((tab) => tab.url.startsWith(url)); |       menu = tabs.find((tab) => tab.url.startsWith(url)); | ||||||
|     if (menu) { |     if (menu) { | ||||||
|       chrome.tabs.highlight({ 'tabs': menu.index }); |       chrome.tabs.highlight({ 'tabs': menu.index }); | ||||||
| @ -19,7 +17,7 @@ async function focusMenu() { | |||||||
| } | } | ||||||
| chrome.browserAction.onClicked.addListener(focusMenu); | chrome.browserAction.onClicked.addListener(focusMenu); | ||||||
| 
 | 
 | ||||||
| async function focusNotion() { | function focusNotion() { | ||||||
|   chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => { |   chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => { | ||||||
|     const notion = tabs.find((tab) => { |     const notion = tabs.find((tab) => { | ||||||
|       const url = new URL(tab.url), |       const url = new URL(tab.url), | ||||||
| @ -32,11 +30,9 @@ async function focusNotion() { | |||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function reload() { | function reload() { | ||||||
|   chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => { |   chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => { | ||||||
|     const menu = chrome.runtime.getURL( |     const menu = chrome.runtime.getURL('repo/menu/menu.html'); | ||||||
|       'repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.html' |  | ||||||
|     ); |  | ||||||
|     tabs.forEach((tab) => { |     tabs.forEach((tab) => { | ||||||
|       const url = new URL(tab.url), |       const url = new URL(tab.url), | ||||||
|         matches = |         matches = | ||||||
|  | |||||||