diff --git a/README.md b/README.md new file mode 100644 index 0000000..16ce2fc --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# CDRM Extension + +An extension to show keys from DRM protected content, which are used to decrypt content. + +## Notes + +Keep these extension core files inside `src`: + +- `background.js` +- `content.js` +- `inject.js` +- `manifest.json` + +Frontend React source stays in `frontend`. + +The build process will take care of everything into `extension-release`. + +To update the version across the entire project, simply change the version number in the root `package.json`. The build script will handle version sync automatically to both the extension's version and the frontend's title bar. + +## Build instructions + +### Prerequisites + +- Node.js v21 or higher. [Download Node.js here](https://nodejs.org/en/download). + +### How to build by yourself + +- Open terminal at the project root + +- Run the build script: + +```bash +npm run buildext +``` + +This will: + +- Sync the version number from the root `package.json` to `src/manifest.json` and `frontend/package.json` +- Install frontend dependencies if needed +- Build the React frontend +- Clean and prepare the `extension-release` folder +- Copy extension files in `src`, built frontend assets, and icons into `extension-release` + +### How to load the extension in Google Chrome or Chromium browsers + +1. Go to `chrome://extensions/` +2. Enable **Developer mode** +3. Click **Load unpacked** and select the `extension-release` folder +4. Verify the extension is working by clicking its icon or opening the developer console (F12) to check for any logs or errors. diff --git a/buildext.js b/buildext.js index de5beb0..632d6fb 100644 --- a/buildext.js +++ b/buildext.js @@ -2,6 +2,7 @@ import { execSync } from "child_process"; import fs from "fs"; import path from "path"; import url from "url"; +import syncVersion from "./syncVersion.js"; const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); const frontendDir = path.join(__dirname, "frontend"); @@ -10,21 +11,23 @@ const srcDir = path.join(__dirname, "src"); const iconDir = path.join(__dirname, "icons"); const releaseDir = path.join(__dirname, "extension-release"); -function run(cmd, cwd) { +const run = (cmd, cwd) => { console.log(`đŸ› ī¸ Running: ${cmd}`); execSync(cmd, { cwd, stdio: "inherit" }); -} +}; -async function copyDir(src, dest) { +const copyDir = async (src, dest) => { await fs.promises.mkdir(dest, { recursive: true }); await fs.promises.cp(src, dest, { recursive: true, force: true, filter: (src) => !src.endsWith(".map"), }); -} +}; + +const main = async () => { + await syncVersion(); -async function main() { console.log("🚀 Starting extension build..."); // 1. Install frontend deps if needed @@ -57,7 +60,7 @@ async function main() { await copyDir(iconDir, path.join(releaseDir, "icons")); console.log("✅ Build complete! extension-release ready."); -} +}; main().catch((e) => { console.error("❌ Build failed:", e); diff --git a/frontend/index.html b/frontend/index.html index e830ac7..cb4ef3c 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,7 +3,7 @@ - CDRM Decryption Extension + CDRM Decryption Extension v%APPVERSION%
diff --git a/frontend/package.json b/frontend/package.json index b4df8fd..326d96a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,30 +1,30 @@ { - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "@tailwindcss/vite": "^4.1.11", - "react": "^19.1.0", - "react-dom": "^19.1.0", - "react-router-dom": "^7.7.0", - "tailwindcss": "^4.1.11" - }, - "devDependencies": { - "@eslint/js": "^9.31.0", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", - "@vitejs/plugin-react": "^4.7.0", - "eslint": "^9.31.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", - "globals": "^16.3.0", - "vite": "^7.0.5" - } -} + "name": "frontend", + "private": true, + "version": "2.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@tailwindcss/vite": "^4.1.11", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.7.0", + "tailwindcss": "^4.1.11" + }, + "devDependencies": { + "@eslint/js": "^9.31.0", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.7.0", + "eslint": "^9.31.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "vite": "^7.0.5" + } +} \ No newline at end of file diff --git a/frontend/vite.config.js b/frontend/vite.config.js index a4c9f4d..01889a6 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -1,9 +1,21 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; import tailwindcss from "@tailwindcss/vite"; +import react from "@vitejs/plugin-react"; +import { readFileSync } from "fs"; +import { defineConfig } from "vite"; + +const packageJson = JSON.parse(readFileSync("./package.json", "utf8")); + +const replaceVersionPlugin = () => { + return { + name: "replace-version", + transformIndexHtml(html) { + return html.replace("%APPVERSION%", packageJson.version); + }, + }; +}; // https://vite.dev/config/ export default defineConfig({ base: "./", - plugins: [react(), tailwindcss()], + plugins: [react(), tailwindcss(), replaceVersionPlugin()], }); diff --git a/package.json b/package.json index 74ba2f6..2372915 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cdrm-extension", - "version": "1.0.0", + "version": "2.1.0", "description": "", "main": "background.js", "scripts": { diff --git a/src/manifest.json b/src/manifest.json index 5c54ba4..00a5ab7 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,41 +1,49 @@ { - "manifest_version": 2, - "name": "CDRM Extension 2.0", - "version": "2.0", - "description": "Decrypt DRM Protected content", - "permissions": [ - "webRequest", - "webRequestBlocking", - "", - "activeTab", - "storage", - "tabs", - "contextMenus" + "manifest_version": 2, + "name": "CDRM Extension", + "version": "2.1.0", + "description": "Decrypt DRM protected content", + "permissions": [ + "webRequest", + "webRequestBlocking", + "", + "activeTab", + "storage", + "tabs", + "contextMenus" + ], + "background": { + "scripts": [ + "background.js" ], - "background": { - "scripts": ["background.js"], - "persistent": true - }, - "content_scripts": [ - { - "matches": [""], - "js": ["content.js"], - "run_at": "document_start", - "all_frames": true - } - ], - "web_accessible_resources": ["inject.js"], - "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", - "browser_action": { - "default_icon": { - "16": "icons/icon16.png", - "32": "icons/icon32.png", - "128": "icons/icon128.png" - } - }, - "icons": { - "16": "icons/icon16.png", - "32": "icons/icon32.png", - "128": "icons/icon128.png" + "persistent": true + }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "content.js" + ], + "run_at": "document_start", + "all_frames": true } -} + ], + "web_accessible_resources": [ + "inject.js" + ], + "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", + "browser_action": { + "default_icon": { + "16": "icons/icon16.png", + "32": "icons/icon32.png", + "128": "icons/icon128.png" + } + }, + "icons": { + "16": "icons/icon16.png", + "32": "icons/icon32.png", + "128": "icons/icon128.png" + } +} \ No newline at end of file diff --git a/syncVersion.js b/syncVersion.js new file mode 100644 index 0000000..7acba5d --- /dev/null +++ b/syncVersion.js @@ -0,0 +1,46 @@ +import fs from "fs/promises"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const syncVersion = async () => { + const rootPkgPath = path.join(__dirname, "package.json"); + const frontendPkgPath = path.join(__dirname, "frontend", "package.json"); + const manifestPath = path.join(__dirname, "src", "manifest.json"); + + // Read root package.json version + const rootPkgRaw = await fs.readFile(rootPkgPath, "utf-8"); + const rootPkg = JSON.parse(rootPkgRaw); + const version = rootPkg.version; + + if (!version) { + console.warn("âš ī¸ No version field found in root package.json, skipping sync."); + return; + } + + // Update frontend/package.json if exists + try { + const frontendPkgRaw = await fs.readFile(frontendPkgPath, "utf-8"); + const frontendPkg = JSON.parse(frontendPkgRaw); + frontendPkg.version = version; + await fs.writeFile(frontendPkgPath, JSON.stringify(frontendPkg, null, 2)); + console.log(`🔄 Updated frontend/package.json version to ${version}`); + } catch { + console.log("â„šī¸ frontend/package.json not found or unreadable, skipping version update."); + } + + // Update src/manifest.json version + try { + const manifestRaw = await fs.readFile(manifestPath, "utf-8"); + const manifest = JSON.parse(manifestRaw); + manifest.version = version; + await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2)); + console.log(`🔄 Updated src/manifest.json version to ${version}`); + } catch (err) { + console.error(`❌ Failed to update src/manifest.json version: ${err.message}`); + } +}; + +export default syncVersion;