diff --git a/LICENSE b/LICENSE index 78b49b6..c531618 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 dragonwocky (https://dragonwocky.me/) +Copyright (c) 2023 dragonwocky (https://dragonwocky.me/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bin.mjs b/bin.mjs index 67c5305..6c06763 100755 --- a/bin.mjs +++ b/bin.mjs @@ -2,7 +2,7 @@ /** * notion-enhancer - * (c) 2022 dragonwocky (https://dragonwocky.me/) + * (c) 2023 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ diff --git a/package.json b/package.json index 39473e2..12de395 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,8 @@ "notion-enhancer" ], "dependencies": { - "@electron/asar": "^3.2.2", + "@electron/asar": "^3.2.4", "arg": "^5.0.2", - "chalk-template": "^0.4.0" + "chalk-template": "^1.0.0" } } diff --git a/scripts/enhance-desktop-app.mjs b/scripts/enhance-desktop-app.mjs index a797d05..1e35a69 100755 --- a/scripts/enhance-desktop-app.mjs +++ b/scripts/enhance-desktop-app.mjs @@ -1,6 +1,6 @@ /** * notion-enhancer - * (c) 2022 dragonwocky (https://dragonwocky.me/) + * (c) 2023 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ diff --git a/scripts/patch-desktop-app.mjs b/scripts/patch-desktop-app.mjs index 43fb75b..d89f7a4 100755 --- a/scripts/patch-desktop-app.mjs +++ b/scripts/patch-desktop-app.mjs @@ -1,6 +1,6 @@ /** * notion-enhancer - * (c) 2022 dragonwocky (https://dragonwocky.me/) + * (c) 2023 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ @@ -40,7 +40,7 @@ const patches = { schemePrefix.length, -(search.length + hash.length) || undefined )}\`; - callback({ + return callback({ data: require("fs").createReadStream(require("path").resolve(\`\${__dirname}/\${filePath}\`)), headers: { "content-type": require("notion-enhancer/vendor/content-types.min.js").get(fileExt) }, }); @@ -52,8 +52,8 @@ const patches = { "main/systemMenu": async (scriptContent) => { // exposes template for modification - const searchValue = "electron_1.Menu.setApplicationMenu(menu);", - replaceValue = `${searchValue} return template;`; + const searchValue = "}\nexports.setupSystemMenu = setupSystemMenu;", + replaceValue = ` return template;\n${searchValue}`; if (scriptContent.includes(replaceValue)) return scriptContent; return scriptContent.replace(searchValue, replaceValue); }, diff --git a/scripts/vendor-dependencies.mjs b/scripts/vendor-dependencies.mjs index a982df9..fd85e2a 100644 --- a/scripts/vendor-dependencies.mjs +++ b/scripts/vendor-dependencies.mjs @@ -1,6 +1,6 @@ /** * notion-enhancer - * (c) 2022 dragonwocky (https://dragonwocky.me/) + * (c) 2023 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ diff --git a/src/api/browser.js b/src/api/browser.js deleted file mode 100644 index 1331c14..0000000 --- a/src/api/browser.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * notion-enhancer - * (c) 2022 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -"use strict"; - -const platform = navigator.userAgent.includes("Firefox") - ? "firefox" - : "chromium", - version = chrome.runtime.getManifest().version, - enhancerUrl = (target) => chrome.runtime.getURL(target); - -const readFile = async (file) => { - file = file.startsWith("http") ? file : enhancerUrl(file); - const res = await fetch(file); - return await res.text(); - }, - readJson = async (file) => { - file = file.startsWith("http") ? file : enhancerUrl(file); - const res = await fetch(file); - return await res.json(); - }, - reloadApp = () => { - chrome.runtime.sendMessage({ - channel: "notion-enhancer", - message: "reload-app", - }); - }; - -const sendMessage = (channel, message) => { - chrome.runtime.sendMessage({ channel, message }); - }, - onMessage = (channel, listener) => { - chrome.runtime.onMessage.addListener((msg) => { - if (msg?.channel === channel) listener(msg.message); - }); - }; - -const initDatabase = (namespace, fallbacks = {}) => { - if (Array.isArray(namespace)) namespace = namespace.join("__"); - namespace = namespace ? namespace + "__" : ""; - const namespaceify = (key) => - key.startsWith(namespace) ? key : namespace + key; - return { - get: async (key) => { - const fallback = fallbacks[key]; - key = namespaceify(key); - return (await chrome.storage.local.get([key]))[key] ?? fallback; - }, - set: (key, value) => { - key = namespaceify(key); - return chrome.storage.local.set({ [key]: value }); - }, - remove: (keys) => { - keys = Array.isArray(keys) ? keys : [keys]; - keys = keys.map(namespaceify); - return chrome.storage.local.remove(keys); - }, - export: async () => { - const obj = await chrome.storage.local.get(); - if (!namespace) return obj; - const entries = Object.entries(obj) - .filter(([key]) => key.startsWith(namespace)) - .map(([key, value]) => [key.slice(namespace.length), value]); - return Object.fromEntries(entries); - }, - import: (obj) => { - const entries = Object.entries(obj) // - .map(([key, value]) => [namespace + key, value]); - return chrome.storage.local.set(Object.fromEntries(entries)); - }, - }; -}; - -globalThis.__enhancerApi ??= {}; -Object.assign(globalThis.__enhancerApi, { - platform, - version, - enhancerUrl, - readFile, - readJson, - reloadApp, - sendMessage, - onMessage, - initDatabase, -}); diff --git a/src/api/electron.cjs b/src/api/electron.cjs deleted file mode 100644 index 17d828a..0000000 --- a/src/api/electron.cjs +++ /dev/null @@ -1,160 +0,0 @@ -/** - * notion-enhancer - * (c) 2022 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -"use strict"; - -const fs = require("fs"), - path = require("path"), - notionRequire = (target) => require(`../../../${target}`); - -const platform = process.platform, - version = require("notion-enhancer/package.json").version, - enhancerUrl = (target) => - `notion://www.notion.so/__notion-enhancer/${target.replace(/^\//, "")}`; - -const readFile = (file) => { - // prettier-ignore - file = file.replace(/^https:\/\/www\.notion\.so\//, "notion://www.notion.so/"); - const useFetch = file.startsWith("http") || file.startsWith("notion://"); - if (useFetch) return fetch(file).then((res) => res.text()); - return fs.readFileSync(path.resolve(`${__dirname}/../${file}`), "utf-8"); - }, - readJson = (file) => { - // prettier-ignore - file = file.replace(/^https:\/\/www\.notion\.so\//, "notion://www.notion.so/"); - const useFetch = file.startsWith("http") || file.startsWith("notion://"); - if (useFetch) return fetch(file).then((res) => res.json()); - return require(path.resolve(`${__dirname}/../${file}`)); - }, - reloadApp = () => { - const { app, ipcRenderer } = require("electron"); - if (app) { - const args = process.argv.slice(1).filter((arg) => arg !== "--startup"); - app.relaunch({ args }); - app.exit(); - } else ipcRenderer.send("notion-enhancer", "reload-app"); - }; - -const sendMessage = (channel, message) => { - const { ipcRenderer } = require("electron"); - ipcRenderer.send(channel, message); - }, - onMessage = (channel, listener) => { - const { ipcRenderer } = require("electron"); - ipcRenderer.on(channel, listener); - }; - -let __db, __statements, __transactions; -const initDatabase = (namespace, fallbacks = {}) => { - if (Array.isArray(namespace)) namespace = namespace.join("__"); - namespace = namespace ? namespace + "__" : ""; - const namespaceify = (key) => - key.startsWith(namespace) ? key : namespace + key; - - __db ??= (async () => { - const { app, ipcRenderer } = require("electron"), - isRenderer = process?.type === "renderer", - userData = isRenderer - ? await ipcRenderer.invoke("notion-enhancer", "get-user-data-folder") - : app.getPath("userData"); - - const table = "settings", - sqlite = require("better-sqlite3"), - db = sqlite(path.resolve(`${userData}/notion-enhancer.db`)), - init = db.prepare(`CREATE TABLE IF NOT EXISTS ${table} ( - key TEXT PRIMARY KEY, - value TEXT - )`); - init.run(); - - // schema: - // - ("agreedToTerms") -> string: semver - // - ("lastTelemetryPing") -> string: iso - // - ("telemetryEnabled") -> boolean - // - ("profileIds") -> $profileId[] - // - ("activeProfile") -> $profileId - // - $profileId: ("profileName") -> string - // - $profileId__enabledMods: ($modId) -> boolean - // - $profileId__$modId: ($optionKey) -> value - - __statements = { - insert: db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`), - update: db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`), - select: db.prepare(`SELECT * FROM ${table} WHERE key = ? LIMIT 1`), - delete: db.prepare(`DELETE FROM ${table} WHERE key = ?`), - dump: db.prepare(`SELECT * FROM ${table}`), - }; - __transactions = { - remove: db.transaction((arr) => { - arr.forEach((key) => __statements.delete.run(key)); - }), - set: db.transaction((obj) => { - for (const key in obj) { - if (__statements.select.get(key) === undefined) { - __statements.insert.run(key, obj[key]); - } else __statements.update.run(obj[key], key); - } - }), - }; - return db; - })(); - - return { - get: async (key) => { - await __db; - const fallback = fallbacks[key]; - key = namespaceify(key); - try { - const value = JSON.parse(__statements.select.get(key)?.value); - return value ?? fallback; - } catch {} - return fallback; - }, - set: async (key, value) => { - await __db; - key = namespaceify(key); - value = JSON.stringify(value); - __transactions.set({ [key]: value }); - return true; - }, - remove: async (keys) => { - await __db; - keys = Array.isArray(keys) ? keys : [keys]; - keys = keys.map(namespaceify); - __transactions.remove(keys); - return true; - }, - export: async () => { - await __db; - const entries = __statements.dump - .all() - .filter(({ key }) => key.startsWith(namespace)) - .map(({ key, value }) => [key.slice(namespace.length), value]); - return Object.fromEntries(entries); - }, - import: async (obj) => { - await __db; - const entries = Object.entries(obj) // - .map(([key, value]) => [key.slice(namespace.length), value]); - __transactions.set(Object.fromEntries(entries)); - return true; - }, - }; -}; - -globalThis.__enhancerApi ??= {}; -Object.assign(globalThis.__enhancerApi, { - notionRequire, - platform, - version, - enhancerUrl, - readFile, - readJson, - reloadApp, - sendMessage, - onMessage, - initDatabase, -}); diff --git a/src/api/events.js b/src/api/events.js index 81e21d1..4214f1e 100644 --- a/src/api/events.js +++ b/src/api/events.js @@ -49,7 +49,7 @@ attachObserver(); let keyListeners = []; // accelerators approximately match electron accelerators. // logic used when recording hotkeys in menu matches logic used -// when triggering hotkeys ∴ detection should be reliable. +// when triggering hotkeys => detection should be reliable. // default hotkeys using "alt" may trigger an altcode or // accented character on some keyboard layouts (not recommended). const modifierAliases = [ diff --git a/src/api/mods.js b/src/api/mods.js index 0fedd5e..84c1166 100644 --- a/src/api/mods.js +++ b/src/api/mods.js @@ -1,6 +1,6 @@ /** * notion-enhancer - * (c) 2022 dragonwocky (https://dragonwocky.me/) + * (c) 2023 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ diff --git a/src/api/system.js b/src/api/system.js new file mode 100644 index 0000000..957699b --- /dev/null +++ b/src/api/system.js @@ -0,0 +1,150 @@ +/** + * notion-enhancer + * (c) 2023 dragonwocky (https://dragonwocky.me/) + * (https://notion-enhancer.github.io/) under the MIT license + */ + +"use strict"; + +const IS_ELECTRON = typeof module !== "undefined"; + +// expected values: 'linux', 'win32', 'darwin' (== macos), 'firefox' +// and 'chromium' (inc. chromium-based browsers like edge and brave) +// other possible values: 'aix', 'freebsd', 'openbsd', 'sunos' +const platform = IS_ELECTRON + ? process.platform + : navigator.userAgent.includes("Firefox") + ? "firefox" + : "chromium", + // currently installed version of the notion-enhancer + version = IS_ELECTRON + ? require("notion-enhancer/package.json").version + : chrome.runtime.getManifest().version, + // forms a url to a notion-enhancer asset or source file + // that can be accessed reliably over http + enhancerUrl = (target) => + IS_ELECTRON + ? `notion://www.notion.so/__notion-enhancer/${target.replace(/^\//, "")}` + : chrome.runtime.getURL(target), + // should only be used from an electron main process, does nothing elsewhere + notionRequire = (target) => IS_ELECTRON && require(`../../../${target}`); + +let __port; +const onMessage = (channel, listener) => { + // from worker to client + if (IS_ELECTRON) { + const { ipcRenderer } = require("electron"); + ipcRenderer.on(channel, listener); + } else { + __port ??= chrome.runtime.connect(); + __port.onMessage.addListener((msg) => { + if (msg?.channel !== channel || msg?.invocation) return; + listener(msg.message); + }); + } + }, + sendMessage = (channel, message) => { + // to worker from client + if (IS_ELECTRON) { + const { ipcRenderer } = require("electron"); + ipcRenderer.send(channel, message); + } else { + __port ??= chrome.runtime.connect(); + __port.postMessage({ channel, message }); + } + }, + invokeInWorker = (channel, message) => { + if (IS_ELECTRON) { + const { ipcRenderer } = require("electron"); + return ipcRenderer.invoke(channel, message); + } else { + // polyfills the electron.ipcRenderer.invoke method in + // the browser: uses a long-lived ipc connection to + // pass messages and handle responses asynchronously + let fulfilled; + __port ??= chrome.runtime.connect(); + const id = crypto.randomUUID(); + return new Promise((res, rej) => { + __port.onMessage.addListener((msg) => { + if (msg?.invocation !== id || fulfilled) return; + fulfilled = true; + res(msg.message); + }); + __port.postMessage({ channel, message, invocation: id }); + }); + } + }; + +const readFile = (file) => { + if (IS_ELECTRON) { + // read directly from filesys if possible, + // treating notion-enhancer/src as fs root + if (!file.startsWith("http")) { + const fsp = require("fs/promises"), + { resolve } = require("path"); + return fsp.readFile(resolve(`${__dirname}/../${file}`), "utf-8"); + } + // prefer using versions of files cached by the app + // or routed through the notion-enhancer's url interception + const notionProtocol = "notion://www.notion.so/"; + file = file.replace(/^https:\/\/www\.notion\.so\//, notionProtocol); + } else file = file.startsWith("http") ? file : enhancerUrl(file); + return fetch(file).then((res) => res.text()); + }, + readJson = (file) => { + // as above, uses require instead of readFile + // and res.json() instead of res.text() to return + // json content of file in object form + if (IS_ELECTRON) { + if (!file.startsWith("http")) { + const { resolve } = require("path"); + return require(resolve(`${__dirname}/../${file}`), "utf-8"); + } + const notionProtocol = "notion://www.notion.so/"; + file = file.replace(/^https:\/\/www\.notion\.so\//, notionProtocol); + } else file = file.startsWith("http") ? file : enhancerUrl(file); + return fetch(file).then((res) => res.json()); + }, + reloadApp = () => { + if (IS_ELECTRON && require("electron").app) { + const { app } = require("electron"), + args = process.argv.slice(1).filter((arg) => arg !== "--startup"); + app.relaunch({ args }); + app.exit(); + } else sendMessage("notion-enhancer", "reload-app"); + }; + +const initDatabase = (namespace, fallbacks = {}) => { + // all db operations are performed via ipc: + // with nodeintegration disabled, sqlite cannot + // be require()-d from the renderer process + const operation = (type, args = {}) => + invokeInWorker("notion-enhancer:db", { + namespace, + fallbacks, + operation: type, + ...args, + }); + return { + get: (key) => operation("get", { key }), + set: (key, value) => operation("set", { key, value }), + remove: (keys) => operation("remove", { keys }), + export: () => operation("export"), + import: (obj) => operation("import", { obj }), + }; +}; + +globalThis.__enhancerApi ??= {}; +Object.assign(globalThis.__enhancerApi, { + platform, + version, + enhancerUrl, + notionRequire, + onMessage, + sendMessage, + invokeInWorker, + readFile, + readJson, + reloadApp, + initDatabase, +}); diff --git a/src/core/menu/islands/List.mjs b/src/core/menu/islands/List.mjs index 188811f..d07409e 100644 --- a/src/core/menu/islands/List.mjs +++ b/src/core/menu/islands/List.mjs @@ -43,9 +43,9 @@ function List({ id, mods, description }) { const _get = () => isEnabled(mod.id), _set = async (enabled) => { await setEnabled(mod.id, enabled); - // only one theme of each mode may be - // enabled at a time ∴ disable others - // on theme of same mode enabled + // only one theme may be enabled per + // mode at a time => auto-disable other + // enabled themes of matching mode if (enabled && id === "themes") { const isDark = mod.tags.includes("dark"), isLight = mod.tags.includes("light"); diff --git a/src/core/menu/menu.mjs b/src/core/menu/menu.mjs index 8adf814..9212250 100644 --- a/src/core/menu/menu.mjs +++ b/src/core/menu/menu.mjs @@ -197,9 +197,9 @@ useState(["rerender"], async () => { if (!theme || !icon) return; // chrome extensions run in an isolated execution context // but extension:// pages can access chrome apis - // ∴ notion-enhancer api is imported directly + // => notion-enhancer api is imported directly if (typeof globalThis.__enhancerApi === "undefined") { - await import("../../api/browser.js"); + await import("../../api/system.js"); // in electron this isn't necessary, as a) scripts are // not running in an isolated execution context and b) // the notion:// protocol csp bypass allows scripts to diff --git a/src/init.js b/src/init.js index 71ac398..ee1d688 100644 --- a/src/init.js +++ b/src/init.js @@ -14,7 +14,7 @@ const isElectron = () => { }; if (isElectron()) { - require("./api/electron.cjs"); + require("./api/system.js"); require("./api/mods.js"); const { enhancerUrl } = globalThis.__enhancerApi, { getMods, isEnabled, modDatabase } = globalThis.__enhancerApi; @@ -48,7 +48,7 @@ if (isElectron()) { } else { // clientStyles // clientScripts - import(chrome.runtime.getURL("/api/browser.js")).then(() => { + import(chrome.runtime.getURL("/api/system.js")).then(() => { import(chrome.runtime.getURL("/load.mjs")); }); } diff --git a/src/worker.js b/src/worker.js index db2dde8..5ce41bd 100644 --- a/src/worker.js +++ b/src/worker.js @@ -1,19 +1,14 @@ /* * notion-enhancer - * (c) 2022 dragonwocky (https://dragonwocky.me/) + * (c) 2023 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ "use strict"; -const isElectron = () => { - try { - return typeof module !== "undefined"; - } catch {} - return false; -}; +const IS_ELECTRON = typeof module !== "undefined"; -if (isElectron()) { +if (IS_ELECTRON) { const { app, ipcMain } = require("electron"), reloadApp = () => { const args = process.argv.slice(1).filter((arg) => arg !== "--startup"); @@ -23,7 +18,7 @@ if (isElectron()) { ipcMain.on("notion-enhancer", (_event, message) => { if (message === "open-menu") { - // + // todo } else if (message === "reload-app") { reloadApp(); } @@ -62,6 +57,8 @@ if (isElectron()) { notionTabs.forEach((tab) => chrome.tabs.reload(tab.id)); }; + // listen for invoke: https://developer.chrome.com/docs/extensions/mv3/messaging/ + chrome.action.onClicked.addListener(openEnhancerMenu); chrome.runtime.onMessage.addListener((msg, sender) => { if (msg?.channel !== "notion-enhancer") return; @@ -78,3 +75,110 @@ if (isElectron()) { } }); } + +let __db, __statements, __transactions; +const initDatabase = (namespace, fallbacks = {}) => { + if (Array.isArray(namespace)) namespace = namespace.join("__"); + namespace = namespace ? namespace + "__" : ""; + const namespaceify = (key) => + key.startsWith(namespace) ? key : namespace + key; + + // schema: + // - ("agreedToTerms") -> string: semver + // - ("lastTelemetryPing") -> string: iso + // - ("telemetryEnabled") -> boolean + // - ("profileIds") -> $profileId[] + // - ("activeProfile") -> $profileId + // - $profileId: ("profileName") -> string + // - $profileId__enabledMods: ($modId) -> boolean + // - $profileId__$modId: ($optionKey) -> value + + __db ??= (async () => { + if (!IS_ELECTRON) return; + + const table = "kvstore", + { app } = require("electron"), + { resolve } = require("path"), + sqlite = require("better-sqlite3"), + db = sqlite(resolve(`${app.getPath("userData")}/notion-enhancer.db`)), + init = db.prepare(`CREATE TABLE IF NOT EXISTS ${table} ( + key TEXT PRIMARY KEY, + value TEXT + )`); + init.run(); + + __statements = { + insert: db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`), + update: db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`), + select: db.prepare(`SELECT * FROM ${table} WHERE key = ? LIMIT 1`), + delete: db.prepare(`DELETE FROM ${table} WHERE key = ?`), + dump: db.prepare(`SELECT * FROM ${table}`), + }; + __transactions = { + remove: db.transaction((arr) => { + arr.forEach((key) => __statements.delete.run(key)); + }), + set: db.transaction((obj) => { + for (const key in obj) { + if (__statements.select.get(key) === undefined) { + __statements.insert.run(key, obj[key]); + } else __statements.update.run(obj[key], key); + } + }), + }; + return db; + })(); + + return { + async get(key) { + await __db; + let value; + const fallback = fallbacks[key]; + key = namespaceify(key); + if (IS_ELECTRON) { + try { + value = JSON.parse(__statements.select.get(key)?.value); + } catch {} + } else value = (await chrome.storage.local.get([key]))[key]; + return value ?? fallback; + }, + async set(key, value) { + await __db; + key = namespaceify(key); + return IS_ELECTRON + ? // returns true instead of transaction completion data type + (__transactions.set({ [key]: JSON.stringify(value) }), true) + : chrome.storage.local.set({ [key]: value }); + }, + async remove(keys) { + await __db; + keys = Array.isArray(keys) ? keys : [keys]; + keys = keys.map(namespaceify); + return IS_ELECTRON + ? (__transactions.remove(keys), true) + : chrome.storage.local.remove(keys); + }, + async export() { + await __db; + // returns key/value pairs within scope w/out namespace + // prefix e.g. to streamline importing from one profile and + // then into another (where a diff. namespace is used) + let entries = IS_ELECTRON + ? __statements.dump.all().map(({ key, value }) => [key, value]) + : Object.entries(await chrome.storage.local.get()); + entries = entries + .filter(([key]) => key.startsWith(namespace)) + .map(([key, value]) => [key.slice(namespace.length), value]); + return Object.fromEntries(entries); + }, + async import(obj) { + await __db; + let entries = Object.entries(obj); + entries = entries.map(([key, value]) => [namespace + key, value]); + entries = Object.fromEntries(entries); + return IS_ELECTRON + ? (__transactions.set(entries), true) + : chrome.storage.local.set(entries); + }, + }; +}; diff --git a/yarn.lock b/yarn.lock index 497b305..a619013 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,54 +5,17 @@ __metadata: version: 6 cacheKey: 8 -"@electron/asar@npm:^3.2.2": - version: 3.2.2 - resolution: "@electron/asar@npm:3.2.2" +"@electron/asar@npm:^3.2.4": + version: 3.2.4 + resolution: "@electron/asar@npm:3.2.4" dependencies: - "@types/glob": ^7.1.1 chromium-pickle-js: ^0.2.0 commander: ^5.0.0 glob: ^7.1.6 minimatch: ^3.0.4 - dependenciesMeta: - "@types/glob": - optional: true bin: asar: bin/asar.js - checksum: 38a3b4a47180f2033a599421175f03706941ba05a32591a639127f6374e0007c6a7c8bde550129de394f4072a0bf39c24aea202540fe1faba6d74b4181c007a8 - languageName: node - linkType: hard - -"@types/glob@npm:^7.1.1": - version: 7.2.0 - resolution: "@types/glob@npm:7.2.0" - dependencies: - "@types/minimatch": "*" - "@types/node": "*" - checksum: 6ae717fedfdfdad25f3d5a568323926c64f52ef35897bcac8aca8e19bc50c0bd84630bbd063e5d52078b2137d8e7d3c26eabebd1a2f03ff350fff8a91e79fc19 - languageName: node - linkType: hard - -"@types/minimatch@npm:*": - version: 5.1.2 - resolution: "@types/minimatch@npm:5.1.2" - checksum: 0391a282860c7cb6fe262c12b99564732401bdaa5e395bee9ca323c312c1a0f45efbf34dce974682036e857db59a5c9b1da522f3d6055aeead7097264c8705a8 - languageName: node - linkType: hard - -"@types/node@npm:*": - version: 18.11.11 - resolution: "@types/node@npm:18.11.11" - checksum: c4b1176a8f1714a3ee3fc2a5e1d568b0cd50209000282db5c68154b3c975952928dbb834ef3a0ce55bd7b345ae29f2cbf4a34635a070294d135a24254231386a - languageName: node - linkType: hard - -"ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: ^2.0.1 - checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 + checksum: 06e3e8fe7c894f7e7727410af5a9957ec77088f775b22441acf4ef718a9e6642a4dc1672f77ee1ce325fc367c8d59ac1e02f7db07869c8ced8a00132a3b54643 languageName: node linkType: hard @@ -80,22 +43,19 @@ __metadata: languageName: node linkType: hard -"chalk-template@npm:^0.4.0": - version: 0.4.0 - resolution: "chalk-template@npm:0.4.0" +"chalk-template@npm:^1.0.0": + version: 1.0.0 + resolution: "chalk-template@npm:1.0.0" dependencies: - chalk: ^4.1.2 - checksum: 6c706802a79a7963cbce18f022b046fe86e438a67843151868852f80ea7346e975a6a9749991601e7e5d3b6a6c4852a04c53dc966a9a3d04031bd0e0ed53c819 + chalk: ^5.2.0 + checksum: 2cd8ae86d7e2ccc546a8fa93871931f7e5731b812e867be1bb77487f83ad6bd657dd25483a99dd0e4d615163551fde4457e48995597b69d58b8f1f633bc21952 languageName: node linkType: hard -"chalk@npm:^4.1.2": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: ^4.1.0 - supports-color: ^7.1.0 - checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc +"chalk@npm:^5.2.0": + version: 5.2.0 + resolution: "chalk@npm:5.2.0" + checksum: 03d8060277de6cf2fd567dc25fcf770593eb5bb85f460ce443e49255a30ff1242edd0c90a06a03803b0466ff0687a939b41db1757bec987113e83de89a003caa languageName: node linkType: hard @@ -106,22 +66,6 @@ __metadata: languageName: node linkType: hard -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: ~1.1.4 - checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 - languageName: node - linkType: hard - "commander@npm:^5.0.0": version: 5.1.0 resolution: "commander@npm:5.1.0" @@ -157,13 +101,6 @@ __metadata: languageName: node linkType: hard -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad - languageName: node - linkType: hard - "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -194,9 +131,9 @@ __metadata: version: 0.0.0-use.local resolution: "notion-enhancer@workspace:." dependencies: - "@electron/asar": ^3.2.2 + "@electron/asar": ^3.2.4 arg: ^5.0.2 - chalk-template: ^0.4.0 + chalk-template: ^1.0.0 bin: notion-enhancer: bin.mjs languageName: unknown @@ -218,15 +155,6 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: ^4.0.0 - checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a - languageName: node - linkType: hard - "wrappy@npm:1": version: 1.0.2 resolution: "wrappy@npm:1.0.2"