dynamically add version to extension title bar and manifest.json, add readme

This commit is contained in:
voldemort 2025-07-20 15:03:43 +07:00
parent 53aa7d66e3
commit 9c738d8a3e
8 changed files with 196 additions and 78 deletions

49
README.md Normal file
View File

@ -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.

View File

@ -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);

View File

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CDRM Decryption Extension</title>
<title>CDRM Decryption Extension v%APPVERSION%</title>
</head>
<body class="min-w-full min-h-full w-full h-full">
<div class="min-w-full min-h-full w-full h-full" id="root"></div>

View File

@ -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"
}
}

View File

@ -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()],
});

View File

@ -1,6 +1,6 @@
{
"name": "cdrm-extension",
"version": "1.0.0",
"version": "2.1.0",
"description": "",
"main": "background.js",
"scripts": {

View File

@ -1,41 +1,49 @@
{
"manifest_version": 2,
"name": "CDRM Extension 2.0",
"version": "2.0",
"description": "Decrypt DRM Protected content",
"permissions": [
"webRequest",
"webRequestBlocking",
"<all_urls>",
"activeTab",
"storage",
"tabs",
"contextMenus"
"manifest_version": 2,
"name": "CDRM Extension",
"version": "2.1.0",
"description": "Decrypt DRM protected content",
"permissions": [
"webRequest",
"webRequestBlocking",
"<all_urls>",
"activeTab",
"storage",
"tabs",
"contextMenus"
],
"background": {
"scripts": [
"background.js"
],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"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": [
"<all_urls>"
],
"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"
}
}

46
syncVersion.js Normal file
View File

@ -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;