Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dynamic manifest #72

Merged
merged 12 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/lint-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,12 @@ jobs:

- name: Build
run: |
bun run build
bun run build:firefox

- name: web-ext Lint
run: |
bun run webext:lint

- name: Build
run: |
bun run build:chromium
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ format:
tsc:
bun tsc

build:
bun run build
build-firefox:
bun run build:firefox

build-chromium:
bun run build:chromium

spell:
bun run spell
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This document provides instructions for installing the Web Extension on various
1. **Download the extension package**: Clone the project and run `bun run build`. The package will be created in `build/` directory.
2. **Open Mozilla Firefox and navigate to about:debugging**: Enter `about:debugging` in the address bar of Firefox and press Enter.
3. **Load the extension**: Click on the "This Firefox" button in the upper right corner of the screen, then select "Load Temporary Add-on..." from the dropdown menu.
4. **Select the extension package**: Navigate to the folder where you downloaded the extension package and select the `manifest.json` file.
4. **Select the extension package**: Navigate to the folder where you downloaded the extension package and select the generated `manifest.json` file.
5. **Confirm installation**: You should now see the extension added to the list of installed extensions.

## Google Chrome 🌐
Expand Down
1 change: 1 addition & 0 deletions docs/cspell.dict.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Barkha
Brooooo
Cacher
camelcase
cfworker
Classts
compat
cpolyline
Expand Down
21 changes: 14 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,26 @@
},
"scripts": {
"watch": "bun tsc && bun tools/watcher.ts",
"build": "bun tools/bundler.ts",
"package": "bun tools/bundler.ts && web-ext build --source-dir=build --overwrite-dest",
"dev:firefox": "bun tools/bundler.ts && concurrently --kill-others \"bun tools/watcher.ts\" \"web-ext run --source-dir=build\"",
"dev:chromium": "bun tools/bundler.ts && concurrently --kill-others \"bun tools/watcher.ts\" \"web-ext run -t chromium --source-dir=build\"",
"dev:firefox-android": "bun tools/bundler.ts && concurrently --kill-others \"bun tools/watcher.ts\" \"web-ext run -t firefox-android --source-dir=build\"",
"build:firefox": "BROWSER=firefox bun tools/bundler.ts",
"build:chromium": "BROWSER=chromium bun tools/bundler.ts",
"package:firefox": "BROWSER=firefox bun tools/bundler.ts && web-ext build --source-dir=build --overwrite-dest",
"package:chromium": "BROWSER=chromium bun tools/bundler.ts && web-ext build --source-dir=build --overwrite-dest",
"dev:firefox": "cross-env BROWSER=firefox bun tools/bundler.ts && concurrently --kill-others \"cross-env BROWSER=firefox bun tools/watcher.ts\" \"web-ext run --source-dir=build\"",
"dev:chromium": "cross-env BROWSER=chromium bun tools/bundler.ts && concurrently --kill-others \"cross-env BROWSER=chromium bun tools/watcher.ts\" \"web-ext run -t chromium --source-dir=build\"",
"dev:firefox-android": "cross-env BROWSER=firefox bun tools/bundler.ts && concurrently --kill-others \"cross-env BROWSER=firefox bun tools/watcher.ts\" \"web-ext run -t firefox-android --source-dir=build\"",
"format": "prettier --write '**/*.{js,jsx,ts,tsx,json,md,html,css}' '!build/**' '!node_modules/**' '!web-ext-artifacts/**'",
"format:check": "prettier --check '**/*.{js,jsx,ts,tsx,json,md,html,css}' '!build/**' '!node_modules/**' '!web-ext-artifacts/**'",
"webext:lint": "web-ext lint --source-dir=build",
"lint": "eslint . --cache --cache-strategy content",
"lint:fix": "eslint . --cache --cache-strategy content --fix",
"tsc": "tsc --noEmit",
"spell": "cspell \"**/*.{ts,js,md,json,txt,html,css}\" \"Makefile\" --gitignore",
"precommit": "bun run lint && bun run format:check && bun run tsc && bun run spell && bun run build && bun run webext:lint",
"precommit": "bun run lint && bun run format:check && bun run tsc && bun run spell && bun run build:firefox && web-ext lint --source-dir=build && bun run build:chromium",
"prepare": "husky"
},
"type": "module",
"dependencies": {
"@cfworker/json-schema": "^4.0.3",
"@langchain/anthropic": "^0.3.8",
"@langchain/community": "^0.3.17",
"@langchain/google-genai": "^0.1.5",
Expand All @@ -65,9 +68,12 @@
"@eslint/js": "^9.16.0",
"@types/chrome": "^0.0.287",
"@types/firefox-webext-browser": "^120.0.4",
"@types/fs-extra": "^11.0.4",
"@types/node": "^22.10.1",
"@types/webextension-polyfill": "^0.12.1",
"chokidar": "^4.0.1",
"concurrently": "^9.1.0",
"cross-env": "^7.0.3",
"cspell": "^8.16.1",
"esbuild": "^0.24.0",
"eslint": "^9.16.0",
Expand All @@ -78,6 +84,7 @@
"husky": "^9.1.7",
"prettier": "^3.4.2",
"typescript-eslint": "^8.17.0",
"web-ext": "^8.3.0"
"web-ext": "^8.3.0",
"webextension-polyfill": "^0.12.0"
}
}
48 changes: 0 additions & 48 deletions public/manifest.json

This file was deleted.

18 changes: 16 additions & 2 deletions tools/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable no-console */
import * as esbuild from 'esbuild';

import fs from 'fs-extra';
import copyContents from './copier';
import entryPoints from './entrypoints';
import { writeManifest } from './manifestWriter';

const cleanBuildFolder = async () => {
try {
await fs.remove('./build');
await fs.ensureDir('./build');
console.log('Build folder cleaned and recreated.');
} catch (error) {
console.error('Error cleaning build folder:', error);
throw error;
}
};
const build = async (watch: boolean) => {
const entrypoints = await entryPoints();
await copyContents('./public', './build');
rootCircle marked this conversation as resolved.
Show resolved Hide resolved
copyContents('./public/assets', './build/assets');
copyContents('./public/src', './build/src');
rootCircle marked this conversation as resolved.
Show resolved Hide resolved
if (watch) {
const buildContext = await esbuild.context({
entryPoints: entrypoints,
Expand Down Expand Up @@ -45,6 +57,8 @@ const build = async (watch: boolean) => {

const runBuild = async (watch: boolean) => {
try {
await cleanBuildFolder();
await writeManifest();
await build(watch);
console.log('Build completed successfully.');
} catch (error) {
Expand Down
1 change: 0 additions & 1 deletion tools/bundler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-console */
import { runBuild } from './builder';

runBuild(false).catch(console.error);
102 changes: 102 additions & 0 deletions tools/manifest.ts
rootCircle marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import fs from 'fs-extra';
import type { Manifest } from 'webextension-polyfill';
import { resolve } from 'path';
import { fileURLToPath } from 'url';
import type PkgType from '../package.json';
import { writeManifest } from './manifestWriter';

const r = (...args: string[]) => {
return resolve(fileURLToPath(new URL('..', import.meta.url)), ...args);
};

const CHROMIUM_BASED = ['chrome', 'chromium', 'edge', 'brave', 'opera'];
const FIREFOX_BASED = ['firefox'];

export async function getManifest() {
if (!(await fs.pathExists(r('package.json')))) {
throw new Error('package.json not found');
}

const pkg = (await fs.readJSON(r('package.json'))) as typeof PkgType;
const targetBrowser = process.env.BROWSER;
if (!targetBrowser) {
throw new Error('BROWSER environment variable must be set');
}
const isFirefoxBased = FIREFOX_BASED.includes(targetBrowser);
const isChromiumBased = CHROMIUM_BASED.includes(targetBrowser);
if (!isFirefoxBased && !isChromiumBased) {
throw new Error(
`Unsupported or unspecified browser: ${targetBrowser}. Supported browsers: ${[...CHROMIUM_BASED, ...FIREFOX_BASED].join(', ')}`,
);
}
if (isFirefoxBased && isChromiumBased) {
throw new Error(
`Both Firefox and Chromium based browsers are specified. Please specify only one.`,
);
}

const baseManifest: Omit<Manifest.WebExtensionManifest, 'background'> = {
manifest_version: 3,
name: 'docFiller',
version: pkg.version,
description: pkg.description,
homepage_url: 'https://addons.mozilla.org/en-US/firefox/addon/docfiller/',
icons: {
'64': 'assets/icons/icon-form-64.png',
'96': 'assets/icons/icon-form-96.png',
},
developer: {
name: 'rootCircle',
url: 'https://github.com/rootCircle',
},
permissions: ['activeTab', 'storage'],
host_permissions: [
'http://docs.google.com/forms/d/e/*/viewform',
'https://docs.google.com/forms/d/e/*/viewform',
],
action: {
default_popup: 'src/popup/index.html',
default_title: 'docFiller',
},
options_ui: {
page: 'src/options/index.html',
open_in_tab: true,
},
content_scripts: [
{
matches: [
'http://docs.google.com/forms/*',
'https://docs.google.com/forms/*',
],
js: ['src/contentScript/index.js'],
},
],
};

const manifest: Manifest.WebExtensionManifest = {
...baseManifest,
background: (() => {
if (isFirefoxBased) {
return { scripts: ['src/background/index.js'] };
}
if (isChromiumBased) {
return { service_worker: 'src/background/index.js' };
}
throw new Error('Unsupported browser type');
})(),
browser_specific_settings: {
...(isFirefoxBased && {
gecko: {
id: 'docFiller@rootcircle.github.io',
strict_min_version: '109.0',
},
}),
},
};

return manifest;
}

if (require.main === module) {
writeManifest().catch(console.error);
}
rootCircle marked this conversation as resolved.
Show resolved Hide resolved
rootCircle marked this conversation as resolved.
Show resolved Hide resolved
24 changes: 24 additions & 0 deletions tools/manifestWriter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { resolve } from 'path';
import { fileURLToPath } from 'url';
import { getManifest } from './manifest';
import fs from 'fs-extra';

const r = (...args: string[]) => {
return resolve(fileURLToPath(new URL('..', import.meta.url)), ...args);
};

export async function writeManifest() {
const browser = process.env.BROWSER;
if (!browser) {
throw new Error('BROWSER environment variable must be set');
}
try {
await fs.ensureDir(r('build'));
const manifest = await getManifest();
await fs.writeJSON(r('build/manifest.json'), manifest, { spaces: 2 });
console.log(`✓ manifest.json generated for ${browser}`);
} catch (error) {
console.error('Error writing manifest:', error);
throw error;
}
}
31 changes: 14 additions & 17 deletions tools/watcher.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
/* eslint-disable no-console */
import chokidar from 'chokidar';

import { runBuild } from './builder';
import copyContents from './copier';

const buildWatch = () => {
runBuild(true).catch(console.error);
const buildWatch = async () => {
rootCircle marked this conversation as resolved.
Show resolved Hide resolved
await runBuild(true).catch(console.error);
rootCircle marked this conversation as resolved.
Show resolved Hide resolved

// Watch directories
const watcher = chokidar.watch(['public/'], {
ignored: /node_modules/,
persistent: true,
});
rootCircle marked this conversation as resolved.
Show resolved Hide resolved

watcher.on('change', () => {
// console.log(`File ${path} has been changed`);
copyContents('./public', './build').catch(console.error);
});
const handleChange = async () => {
try {
copyContents('./public/assets', './build/assets');
copyContents('./public/src', './build/src');
rootCircle marked this conversation as resolved.
Show resolved Hide resolved
await runBuild(true);
rootCircle marked this conversation as resolved.
Show resolved Hide resolved
} catch (error) {
console.error('error:', error);
}
};

watcher.on('add', () => {
// console.log(`File ${path} has been added`);
copyContents('./public', './build').catch(console.error);
});

watcher.on('unlink', () => {
// console.log(`File ${path} has been removed`);
copyContents('./public', './build').catch(console.error);
});
watcher.on('change', handleChange);
watcher.on('add', handleChange);
watcher.on('unlink', handleChange);
};

buildWatch();
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"types": [
"./types.d.ts", // add your own type definitions
"@types/chrome",
"@types/firefox-webext-browser"
"@types/firefox-webext-browser",
"webextension-polyfill"
],
"baseUrl": "src",
"paths": {
Expand Down
Loading