From a88c45cc80f0cfd83f205ddfbbca695f50db16ef Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Sun, 29 Oct 2023 20:16:56 +1100 Subject: [PATCH] chore: update to support notion 2.2.4 (bundled webpack build) --- package-lock.json | 155 ++++++++++++++++++++++++++++++ package.json | 4 +- scripts/enhance-desktop-app.mjs | 2 +- scripts/patch-desktop-app.mjs | 108 ++++++++++----------- src/core/mod.json | 3 +- src/init.js | 39 +++----- src/load.mjs | 5 + yarn.lock | 163 -------------------------------- 8 files changed, 230 insertions(+), 249 deletions(-) create mode 100644 package-lock.json delete mode 100644 yarn.lock diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ec9eab0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,155 @@ +{ + "name": "notion-enhancer", + "version": "0.11.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "notion-enhancer", + "version": "0.11.1", + "license": "MIT", + "dependencies": { + "@electron/asar": "^3.2.7", + "arg": "^5.0.2", + "chalk-template": "^1.1.0" + }, + "bin": { + "notion-enhancer": "bin.mjs" + }, + "engines": { + "node": ">=18.x.x" + }, + "funding": { + "url": "https://github.com/sponsors/dragonwocky" + } + }, + "node_modules/@electron/asar": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.7.tgz", + "integrity": "sha512-8FaSCAIiZGYFWyjeevPQt+0e9xCK9YmJ2Rjg5SXgdsXon6cRnU0Yxnbe6CvJbQn26baifur2Y2G5EBayRIsjyg==", + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/chalk": { + "version": "5.2.0", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "chalk": "^5.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + } + } +} diff --git a/package.json b/package.json index dd17a5c..3c5359f 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "vendor": "node ./scripts/vendor-dependencies.mjs" }, "engines": { - "node": ">=16.x.x" + "node": ">=18.x.x" }, "keywords": [ "windows", @@ -35,7 +35,7 @@ "notion-enhancer" ], "dependencies": { - "@electron/asar": "^3.2.4", + "@electron/asar": "^3.2.7", "arg": "^5.0.2", "chalk-template": "^1.1.0" } diff --git a/scripts/enhance-desktop-app.mjs b/scripts/enhance-desktop-app.mjs index 1e35a69..45ec52b 100755 --- a/scripts/enhance-desktop-app.mjs +++ b/scripts/enhance-desktop-app.mjs @@ -124,7 +124,7 @@ const unpackApp = async () => { for (const file of notionScripts) { const scriptId = file.slice(appPath.length + 1, -3).replace(/\\/g, "/"), scriptContent = await fsp.readFile(file, { encoding: "utf8" }), - patchedContent = await patch(scriptId, scriptContent), + patchedContent = patch(scriptId, scriptContent), changesMade = patchedContent !== scriptContent; if (changesMade) scriptUpdates.push(fsp.writeFile(file, patchedContent)); } diff --git a/scripts/patch-desktop-app.mjs b/scripts/patch-desktop-app.mjs index e5bcdc4..a93d5c1 100755 --- a/scripts/patch-desktop-app.mjs +++ b/scripts/patch-desktop-app.mjs @@ -7,66 +7,60 @@ const replaceIfNotFound = (string, search, replacement) => string.includes(replacement) ? string : string.replace(search, replacement); -const patches = { - "*": async (scriptId, scriptContent) => { - if (scriptId === 'forge.config.js') return scriptContent; - const prevTriggerPattern = /require\(['|"]notion-enhancer['|"]\)/, - prevTriggerFound = prevTriggerPattern.test(scriptContent); - if (prevTriggerFound) return scriptContent; - const enhancerTrigger = - '\n\n/*notion-enhancer*/require("notion-enhancer")' + - `('${scriptId}',exports,(js)=>eval(js));`; - return scriptContent + enhancerTrigger; - }, +// require()-ing the notion-enhancer in worker scripts +// or in renderer scripts will throw errors => manually +// inject trigger into only the necessary scripts +// (avoid re-injection on re-enhancement) +const injectTriggerOnce = (scriptId, scriptContent) => + scriptContent + + (!/require\(['|"]notion-enhancer['|"]\)/.test(scriptContent) + ? `\n\nrequire("notion-enhancer")('${scriptId}',exports,(js)=>eval(js));` + : ""); - "main/main": async (scriptContent) => { - // https://github.com/notion-enhancer/desktop/issues/160 - // enable the notion:// url scheme/protocol on linux - const search = /process.platform === "win32"/g, - // prettier-ignore - replacement = 'process.platform === "win32" || process.platform === "linux"'; - return replaceIfNotFound(scriptContent, search, replacement); - }, +const mainScript = ".webpack/main/index", + rendererScript = ".webpack/renderer/tab_browser_view/preload", + patches = { + [mainScript]: (scriptContent) => { + scriptContent = injectTriggerOnce(mainScript, scriptContent); - "main/schemeHandler": async (scriptContent) => { - // https://github.com/notion-enhancer/desktop/issues/291 - // bypass csp issues by intercepting notion:// protocol - // prettier-ignore - const protocolSearch = "protocol.registerStreamProtocol(config_1.default.protocol, async (req, callback) => {", - protocolReplacement = `${protocolSearch} - {/*notion-enhancer*/ - const schemePrefix = "notion://www.notion.so/__notion-enhancer/"; - if (req.url.startsWith(schemePrefix)) { - const { search, hash, pathname } = new URL(req.url), - fileExt = pathname.split(".").reverse()[0], - filePath = \`../node_modules/notion-enhancer/\${req.url.slice( - schemePrefix.length, - -(search.length + hash.length) || undefined - )}\`; - return callback({ - data: require("fs").createReadStream(require("path").resolve(\`\${__dirname}/\${filePath}\`)), - headers: { "content-type": require("notion-enhancer/vendor/content-types.min.js").get(fileExt) }, - }); - }}`, - filterSearch = "function guardAgainstIFrameRequests(webRequest) {", - filterReplacement = `${filterSearch}/*notion-enhancer*/return;`; - return replaceIfNotFound( - replaceIfNotFound(scriptContent, filterSearch, filterReplacement), - protocolSearch, - protocolReplacement - ); - }, + // https://github.com/notion-enhancer/notion-enhancer/issues/160: + // enable the notion:// protocol, windows-style tab layouts, and + // quitting the app when the last window is closed on linux + scriptContent = scriptContent.replace( + /(?:"win32"===process\.platform(?:(?=,isFullscreen)|(?=&&\w\.BrowserWindow)|(?=&&\(\w\.app\.requestSingleInstanceLock)))/g, + '["win32","linux"].includes(process.platform)' + ); - "main/systemMenu": async (scriptContent) => { - // exposes template for modification - const search = "}\nexports.setupSystemMenu = setupSystemMenu;", - replacement = ` return template;\n${search}`; - return replaceIfNotFound(scriptContent, search, replacement); - }, -}; + // restore node integration in the renderer process + // so the notion-enhancer can be require()-d into it + scriptContent = replaceIfNotFound( + scriptContent, + /spellcheck:!0,sandbox:!0/g, + "spellcheck:!0,nodeIntegration:true" + ); -export default async (scriptId, scriptContent) => { - if (patches["*"]) scriptContent = await patches["*"](scriptId, scriptContent); - if (patches[scriptId]) scriptContent = await patches[scriptId](scriptContent); + // https://github.com/notion-enhancer/desktop/issues/291 + // bypass csp issues by intercepting the notion:// protocol + const protocolHandler = + "try{const t=await p.assetCache.handleRequest(e);"; + scriptContent = replaceIfNotFound( + scriptContent, + protocolHandler, + `{const n="notion://www.notion.so/__notion-enhancer/";if(e.url.startsWith(n))return require("electron").net.fetch(\`file://\${require("path").join(__dirname,"..","..","node_modules","notion-enhancer",e.url.slice(n.length))}\`)}${protocolHandler}` + ); + + // bypass webRequest filter to load enhancer menu + return replaceIfNotFound( + scriptContent, + /r\.top!==r\?t\({cancel:!0}\)/g, + "r.top!==r?t({})" + ); + }, + [rendererScript]: (scriptContent) => injectTriggerOnce(rendererScript, scriptContent) + }; + +export default (scriptId, scriptContent) => { + if (patches["*"]) scriptContent = patches["*"](scriptId, scriptContent); + if (patches[scriptId]) scriptContent = patches[scriptId](scriptContent); return scriptContent; }; diff --git a/src/core/mod.json b/src/core/mod.json index 50ab2b3..e98ff88 100644 --- a/src/core/mod.json +++ b/src/core/mod.json @@ -64,6 +64,5 @@ } ], "clientStyles": ["variables.css"], - "clientScripts": ["client.mjs"], - "electronScripts": [{ "source": "notionConfig.cjs", "target": "config.js" }] + "clientScripts": ["client.mjs"] } diff --git a/src/init.js b/src/init.js index 18a3889..51aec3b 100644 --- a/src/init.js +++ b/src/init.js @@ -19,29 +19,21 @@ if (isElectron()) { const { enhancerUrl } = globalThis.__enhancerApi, { getMods, isEnabled, modDatabase } = globalThis.__enhancerApi; - // calling require("electron") in a process require()-d - // from these paths throws "websocket connection to __ failed" - // and triggers infinite loading => ignore for now, but will - // require further investigation later - const ignoredPaths = [ - "shared/sqliteTypes", - "shared/TimeSource", - "shared/retryHelpers", - "shared/PromiseUtils", - "shared/typeUtils", - "shared/utils", - "shared/sqliteHelpers", - "main/sqlite/SqliteConnectionWrapper", - "main/sqlite/SqliteServer", - ]; + const mainScript = ".webpack/main/index", + rendererScript = ".webpack/renderer/tab_browser_view/preload"; module.exports = async (target, __exports, __eval) => { - if (ignoredPaths.includes(target)) return; - if (target.startsWith("main/")) require("./worker.js"); + if (target === mainScript) require("./worker.js"); - // clientStyles - // clientScripts - if (target === "renderer/preload") { + if (target === rendererScript) { + // expose globalThis.__enhancerApi to scripts + const { contextBridge } = require("electron"); + contextBridge.exposeInMainWorld( + "__getEnhancerApi", + () => globalThis.__enhancerApi + ); + + // load clientStyles, clientScripts document.addEventListener("readystatechange", () => { if (document.readyState !== "complete") return false; const $script = document.createElement("script"); @@ -51,13 +43,12 @@ if (isElectron()) { }); } - // electronScripts + // load electronScripts for (const mod of await getMods()) { if (!mod.electronScripts || !(await isEnabled(mod.id))) continue; const db = await modDatabase(mod.id); - for (const { source, target: targetScript } of mod.electronScripts) { - if (`${target}.js` !== targetScript) continue; - const script = require(`notion-enhancer/${mod._src}/${source}`); + for (let script of mod.clientScripts ?? []) { + script = require(`notion-enhancer/${mod._src}/${source}`); script(globalThis.__enhancerApi, db, __exports, __eval); } } diff --git a/src/load.mjs b/src/load.mjs index 4789f21..040e92a 100644 --- a/src/load.mjs +++ b/src/load.mjs @@ -7,6 +7,11 @@ "use strict"; export default (async () => { + if (globalThis.__getEnhancerApi) { + globalThis.__enhancerApi ??= {}; + Object.assign(globalThis.__enhancerApi, globalThis.__getEnhancerApi()); + } + // prettier-ignore const { enhancerUrl, platform } = globalThis.__enhancerApi, signedIn = localStorage["LRU:KeyValueStore2:current-user-id"], diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 695812a..0000000 --- a/yarn.lock +++ /dev/null @@ -1,163 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8 - -"@electron/asar@npm:^3.2.4": - version: 3.2.4 - resolution: "@electron/asar@npm:3.2.4" - dependencies: - chromium-pickle-js: ^0.2.0 - commander: ^5.0.0 - glob: ^7.1.6 - minimatch: ^3.0.4 - bin: - asar: bin/asar.js - checksum: 06e3e8fe7c894f7e7727410af5a9957ec77088f775b22441acf4ef718a9e6642a4dc1672f77ee1ce325fc367c8d59ac1e02f7db07869c8ced8a00132a3b54643 - languageName: node - linkType: hard - -"arg@npm:^5.0.2": - version: 5.0.2 - resolution: "arg@npm:5.0.2" - checksum: 6c69ada1a9943d332d9e5382393e897c500908d91d5cb735a01120d5f71daf1b339b7b8980cbeaba8fd1afc68e658a739746179e4315a26e8a28951ff9930078 - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 - languageName: node - linkType: hard - -"brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" - dependencies: - balanced-match: ^1.0.0 - concat-map: 0.0.1 - checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 - languageName: node - linkType: hard - -"chalk-template@npm:^1.1.0": - version: 1.1.0 - resolution: "chalk-template@npm:1.1.0" - dependencies: - chalk: ^5.2.0 - checksum: 868aae8d4e7556ad2f35de4e04fe65dbe1ea6c5c80ad783f1c156d0a5c33f444c6814f49cbb68fe348c78e99daf2bcf566b47ad7e13603e4691ca78b2f422824 - languageName: node - linkType: hard - -"chalk@npm:^5.2.0": - version: 5.2.0 - resolution: "chalk@npm:5.2.0" - checksum: 03d8060277de6cf2fd567dc25fcf770593eb5bb85f460ce443e49255a30ff1242edd0c90a06a03803b0466ff0687a939b41db1757bec987113e83de89a003caa - languageName: node - linkType: hard - -"chromium-pickle-js@npm:^0.2.0": - version: 0.2.0 - resolution: "chromium-pickle-js@npm:0.2.0" - checksum: 5ccacc538b0a1ecf3484c8fb3327eae129ceee858db0f64eb0a5ff87bda096a418d0d3e6f6e0967c6334d336a2c7463f7b683ec0e1cafbe736907fa2ee2f58ca - languageName: node - linkType: hard - -"commander@npm:^5.0.0": - version: 5.1.0 - resolution: "commander@npm:5.1.0" - checksum: 0b7fec1712fbcc6230fcb161d8d73b4730fa91a21dc089515489402ad78810547683f058e2a9835929c212fead1d6a6ade70db28bbb03edbc2829a9ab7d69447 - languageName: node - linkType: hard - -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af - languageName: node - linkType: hard - -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 - languageName: node - linkType: hard - -"glob@npm:^7.1.6": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.1.1 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 - languageName: node - linkType: hard - -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: ^1.3.0 - wrappy: 1 - checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd - languageName: node - linkType: hard - -"inherits@npm:2": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 - languageName: node - linkType: hard - -"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: ^1.1.7 - checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a - languageName: node - linkType: hard - -"notion-enhancer@workspace:.": - version: 0.0.0-use.local - resolution: "notion-enhancer@workspace:." - dependencies: - "@electron/asar": ^3.2.4 - arg: ^5.0.2 - chalk-template: ^1.1.0 - bin: - notion-enhancer: bin.mjs - languageName: unknown - linkType: soft - -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: 1 - checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 - languageName: node - linkType: hard - -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 - languageName: node - linkType: hard