Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
node_modules/
dist/
dist/
.output/
.wxt/
web-ext.config.ts
stats.html
stats-*.json
4 changes: 2 additions & 2 deletions .releaserc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
[
"@semantic-release/exec",
{
"prepareCmd": "sed -i 's/\"version\": \".*\"/\"version\": \"${nextRelease.version}\"/' src/manifest.json && bun run build && zip -r extension-chrome.zip dist/"
"prepareCmd": "bun run zip && cp .output/*chrome*.zip extension-chrome.zip"
}
],
[
"@semantic-release/git",
{
"assets": ["package.json", "CHANGELOG.md", "src/manifest.json"],
"assets": ["package.json", "CHANGELOG.md"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
Expand Down
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,36 @@ A Chrome extension for the SchoolBox LMS with integrations for the Box of Books

## Development

Install dependencies using Bun:
This project is built with [WXT](https://wxt.dev). Install dependencies and run the dev server (which launches Chrome with the extension auto-loaded):

```bash
# install dependencies
bun install
npm install # or: bun install

# build
bun run build
# dev server with HMR
npm run dev

# production build (writes to .output/chrome-mv3/)
npm run build

# build a zip for Web Store submission (writes to .output/<name>-<ver>-chrome.zip)
npm run zip
```

For development mode with file watching:
Firefox builds are also supported:

```bash
bun run dev
npm run dev:firefox
npm run build:firefox
npm run zip:firefox
```

Load the `dist/` directory as an unpacked extension in Chrome to test.
To manually load the production build as an unpacked extension in Chrome:

1. Open Google Chrome and go to `chrome://extensions/`.
2. Enable the Developer Mode toggle in the top right.
3. Click on "load unpacked" in the toolbar that appears.
4. Navigate to the `dist/` folder in the repository. If you don't see one, follow the instructions above to build the extension.
1. Run `npm run build`.
2. Open `chrome://extensions/`.
3. Enable Developer Mode (top right).
4. Click "Load Unpacked" and select the `.output/chrome-mv3/` folder.

## License

Expand Down
1,124 changes: 608 additions & 516 deletions bun.lock

Large diffs are not rendered by default.

33 changes: 12 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
"name": "schoolbox-chrome-extension",
"version": "1.3.0",
"description": "A Chrome extension for SchoolBox built with TypeScript, React, and Bun.",
"main": "src/background/background.ts",
"scripts": {
"typecheck": "node node_modules/typescript/bin/tsc --noEmit",
"build": "webpack --config webpack.config.cjs --mode production",
"dev": "webpack --config webpack.config.cjs --watch",
"serve-dist": "bun serve dist",
"start": "bun run build && bun run serve-dist"
"dev": "wxt",
"dev:firefox": "wxt -b firefox",
"build": "wxt build",
"build:firefox": "wxt build -b firefox",
"zip": "wxt zip",
"zip:firefox": "wxt zip -b firefox",
"postinstall": "wxt prepare",
"typecheck": "tsc --noEmit"
},
"keywords": [
"chrome",
Expand All @@ -20,37 +22,26 @@
"license": "MIT",
"dependencies": {
"@ali-tas/htmldiff-js": "^2.0.1",
"@babel/core": "^7.27.1",
"@babel/preset-env": "^7.27.2",
"@babel/preset-react": "^7.27.1",
"@babel/preset-typescript": "^7.27.1",
"@types/chrome": "^0.1.38",
"@types/diff": "^8.0.0",
"@types/html-to-text": "^9.0.4",
"babel-loader": "^10.0.0",
"copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2",
"diff": "^9.0.0",
"fast-xml-parser": "^5.2.3",
"fuse.js": "^7.1.0",
"html-to-text": "^9.0.5",
"html-webpack-plugin": "^5.6.3",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"style-loader": "^4.0.0",
"ts-loader": "^9.5.2",
"webpack": "^5.99.8",
"webpack-cli": "^6.0.1"
"react-dom": "^19.1.0"
},
"devDependencies": {
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/exec": "^7.1.0",
"@semantic-release/git": "^10.0.1",
"@types/chrome": "^0.1.42",
"@types/react": "^19.1.3",
"@types/react-dom": "^19.1.3",
"bun-types": "^0.1.0",
"prettier": "3.5.3",
"semantic-release": "^25.0.3",
"typescript": "^6.0.2"
"typescript": "^6.0.2",
"wxt": "^0.20.0"
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
12 changes: 0 additions & 12 deletions src/background/background.ts

This file was deleted.

21 changes: 4 additions & 17 deletions src/background/set_default_settings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Settings } from "../types/settings"
import { poll_feed } from "./pull_feed"

// set_setting was moved to ./set_setting so content-script entrypoints
// can import it without pulling in poll_feed / fast-xml-parser.
export { set_setting } from "./set_setting"

export async function init_settings(): Promise<void> {
let current_settings = await chrome.storage.sync.get("settings")

Expand Down Expand Up @@ -32,20 +36,3 @@ export async function init_settings(): Promise<void> {

await poll_feed()
}

export async function set_setting<K extends keyof Settings>(
key: K,
value: Settings[K]
): Promise<void> {
const current_settings = await chrome.storage.sync.get("settings")
if (!current_settings.settings) {
console.error("Settings not initialized yet.")
return
}

const new_settings = {
...current_settings.settings,
[key]: value,
}
await chrome.storage.sync.set({ settings: new_settings })
}
18 changes: 18 additions & 0 deletions src/background/set_setting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Settings } from "../types/settings"

export async function set_setting<K extends keyof Settings>(
key: K,
value: Settings[K]
): Promise<void> {
const current_settings = await chrome.storage.sync.get("settings")
if (!current_settings.settings) {
console.error("Settings not initialized yet.")
return
}

const new_settings = {
...current_settings.settings,
[key]: value,
}
await chrome.storage.sync.set({ settings: new_settings })
}
45 changes: 0 additions & 45 deletions src/content/auto_detection/detect_domain.ts

This file was deleted.

67 changes: 0 additions & 67 deletions src/content/auto_detection/detect_rss_feed.ts

This file was deleted.

46 changes: 0 additions & 46 deletions src/content/auto_detection/detect_schooltape.ts

This file was deleted.

35 changes: 35 additions & 0 deletions src/content/auto_detection/show_banner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
interface BannerOptions {
id: string
top: string
title: string
body_html: string
auto_hide_ms?: number
}

export function show_detection_banner(opts: BannerOptions): void {
const banner = document.createElement("div")
banner.id = opts.id
banner.style.position = "fixed"
banner.style.top = opts.top
banner.style.right = "20px"
banner.style.backgroundColor = "#e3ffe4"
banner.style.border = "2px solid #4CAF50"
banner.style.borderLeftWidth = "8px"
banner.style.color = "black"
banner.style.padding = "15px"
banner.style.borderRadius = "5px"
banner.style.zIndex = "10000"

banner.innerHTML = `
<p style="font-weight: bold;">${opts.title}</p>
${opts.body_html}
<p>Incorrectly detected? <a href='https://github.com/skid-dev/UltraBox' target='_blank'>Submit a bug report</a></p>
`

document.body.appendChild(banner)

const auto_hide_ms = opts.auto_hide_ms ?? 10000
setTimeout(() => {
banner.remove()
}, auto_hide_ms)
}
Loading
Loading