From 45d6499eef3d4e7c97e246534ec5bf791100102e Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Tue, 28 May 2024 02:19:18 +0100 Subject: [PATCH] extension: switch to rollup for building instead of webpack NOTE: this will break chrome extension until we implement full manifest v3 support rollup switch is mainly because - rollup has a much better builtin ES6 module support (in webpack it's STILL experimental!) - minimal transformation to the source code, even possible to read without source maps some additional changes - somewhat more consistent import handling and bundling, less hacks with - add build script changes from grasp --- .../{babel.config.js => babel.config.cjs} | 0 extension/build | 9 +- extension/eslint.config.js | 9 +- extension/generate_manifest.js | 243 + extension/{jest.config.js => jest.config.cjs} | 0 extension/{ => old}/webpack.config.js | 3 + extension/package-lock.json | 9186 +++++++---------- extension/package.json | 37 +- extension/rollup.config.js | 161 + extension/src/background.ts | 9 +- extension/src/display.ts | 13 +- extension/src/filterlist.ts | 4 +- extension/{ => src}/images/generate | 0 .../{ => src}/images/ic_blacklisted_48.png | Bin extension/{ => src}/images/ic_blue_48.png | Bin extension/{ => src}/images/ic_boring_48.png | Bin extension/{ => src}/images/ic_error.png | Bin .../{ => src}/images/ic_not_visited_48.png | Bin .../{ => src}/images/ic_relatives_48.png | Bin extension/{ => src}/images/ic_visited_48.png | Bin extension/{ => src}/images/source_48.svg | 0 extension/src/notifications.ts | 6 +- extension/src/options.ts | 4 +- extension/src/options_page.html | 7 +- extension/src/options_page.ts | 20 +- extension/src/search.html | 4 +- extension/src/showvisited.js | 8 +- extension/src/sidebar.ts | 8 +- extension/tests/integration.test.js | 27 +- extension/tsconfig.json | 8 +- tests/end2end_test.py | 7 +- 31 files changed, 4196 insertions(+), 5577 deletions(-) rename extension/{babel.config.js => babel.config.cjs} (100%) create mode 100644 extension/generate_manifest.js rename extension/{jest.config.js => jest.config.cjs} (100%) rename extension/{ => old}/webpack.config.js (99%) create mode 100644 extension/rollup.config.js rename extension/{ => src}/images/generate (100%) rename extension/{ => src}/images/ic_blacklisted_48.png (100%) rename extension/{ => src}/images/ic_blue_48.png (100%) rename extension/{ => src}/images/ic_boring_48.png (100%) rename extension/{ => src}/images/ic_error.png (100%) rename extension/{ => src}/images/ic_not_visited_48.png (100%) rename extension/{ => src}/images/ic_relatives_48.png (100%) rename extension/{ => src}/images/ic_visited_48.png (100%) rename extension/{ => src}/images/source_48.svg (100%) diff --git a/extension/babel.config.js b/extension/babel.config.cjs similarity index 100% rename from extension/babel.config.js rename to extension/babel.config.cjs diff --git a/extension/build b/extension/build index b85b9d29..653dffa1 100755 --- a/extension/build +++ b/extension/build @@ -85,13 +85,13 @@ def main() -> None: if args.release: assert args.lint # TODO not sure.. - def firefox_release_args(): + def firefox_publish_args(): from firefox_dev_secrets import API_KEY, API_SECRET return [ '--artifacts-dir', str(artifacts_dir), '--api-key' , API_KEY, '--api-secret' , API_SECRET, - '--id' , IDS[target], + # seems like webext sign requires addon id to be in manifest now ] if args.publish is not None: @@ -99,11 +99,12 @@ def main() -> None: assert args.release if 'firefox' in target: check_call([ - npm, 'run', 'release:amo', + npm, 'run', 'web-ext', '--', + 'sign', '--use-submission-api', '--channel', args.publish, '--source-dir', str(ext_dir), - *firefox_release_args(), + *firefox_publish_args(), ]) elif target == 'chrome': assert args.publish == 'listed' # no notion of unlisted on chrome store? diff --git a/extension/eslint.config.js b/extension/eslint.config.js index 8c323536..3d1219ec 100644 --- a/extension/eslint.config.js +++ b/extension/eslint.config.js @@ -1,11 +1,10 @@ // @ts-check +import globals from 'globals' +import eslint from '@eslint/js' +import tseslint from 'typescript-eslint' -const globals = require('globals') -const eslint = require('@eslint/js') -const tseslint = require('typescript-eslint') - -module.exports = tseslint.config( +export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.recommended, // TODO recommendedTypeChecked?? { diff --git a/extension/generate_manifest.js b/extension/generate_manifest.js new file mode 100644 index 00000000..7b2be1b6 --- /dev/null +++ b/extension/generate_manifest.js @@ -0,0 +1,243 @@ +// due to firefox + chrome and manifest v2 + v3 combination, 95% of the manifest is JS generated anyway +// so with this we're just generaing it fully dynamically + +import assert from 'assert' + +import pkg from './package.json' with { type: "json" } + +const T = { + CHROME : 'chrome', + FIREFOX: 'firefox', +} + + +// ugh. declarative formats are shit. +export function generateManifest({ + target, // str + version, // str + release, // bool + publish, // bool + ext_id // str +} = {}) { + assert(target) + assert(version) + assert(release !== null) + assert(ext_id) + + const v3 = version == '3' + + // Firefox wouldn't let you rebind its default shortcuts most of which use Shift + // On the other hand, Chrome wouldn't let you use Alt + const modifier = target === T.CHROME ? 'Shift' : 'Alt' + + const action_name = v3 ? 'action' : 'browser_action' + + const commands = { + "mark_visited": { + "description": "Mark/unmark visited links on the current page", + "suggested_key": { + "default": `Ctrl+${modifier}+V`, + "mac": `Command+${modifier}+V`, + }, + }, + // right, 'S' interferes with OS hotkey? + // need all of that discoverable from menu anyway + // also dots and browser action too + "search": { + "description": "Open search page", + "suggested_key": { + "default": `Ctrl+${modifier}+H`, + "mac": `Command+${modifier}+H`, + }, + }, + } + + commands[`_execute_${action_name}`] = { + "description": "Activate sidebar", + "suggested_key": { + /* fucking hell, ubuntu is hijacking Ctrl-Shift-E... not sure what to do :( + * https://superuser.com/questions/358749/how-to-disable-ctrlshiftu-in-ubuntu-linux/1392682 + */ + "default": `Ctrl+${modifier}+E`, + "mac": `Command+${modifier}+E`, + }, + } + + + const action = { + "default_icon": "images/ic_not_visited_48.png", + "default_title": "Show promnesia sidebar", + } + + + const endpoints = (domain) => [ + // TODO not sure if need to include api subpages?? seems like connect-src doesn't like /* in path component.. + "http://" + domain + "/", + "https://" + domain + "/", + ] + + + // prepare for manifest v3 + const host_permissions = [ + // broad permissions (*) are necessary for webNavigation to work + // otherwise we get "Cannot access contents of the page. Extension manifest must request permission to access the respective host." + 'file:///*', + ...endpoints('*'), + /* also note that if we have host permissions, we don't need tabs/activeTab permission to inject css/code + * this is necessary to call insertCss and executeScript + * note that just activeTab isn't enough because things aren't necessarily happening after user interaction like action + * e.g. sidebar/icon state is updating after webNavigation callback + */ + ] + // FIXME not sure if need these considering it needs broad host permissions anyway? + const optional_host_permissions = endpoints('*') + + + // TODO make permissions literate + const permissions = [ + // for keeping extension settings + "storage", + + // receiving page status updates so extension kicks in on page loading + "webNavigation", + + // uses context menu actions + "contextMenus", + + // todo could be optional? + "notifications", + + // used as one of the sources + // todo could be optional? + "bookmarks", // NOTE: isn't available on mobile + + // to use local browsing history + // todo could be optional? + "history", // NOTE: isn't available on mobile + ] + + + const optional_permissions = [] + + if (target === T.FIREFOX || v3) { + // chrome v2 doesn't support scripting api + // FIXME need to actually start using it + permissions.push("scripting") + } + + + const content_security_policy = [ + "script-src 'self'", // this must be specified when overriding, otherwise it complains + /// also this works, but it seems that default-src somehow shadows style-src??? + // "default-src 'self'", + // "style-src 'unsafe-inline'", // FFS, otherwise