dynamically add version to extension title bar and manifest.json, add readme
This commit is contained in:
		
							parent
							
								
									53aa7d66e3
								
							
						
					
					
						commit
						9c738d8a3e
					
				
							
								
								
									
										49
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								README.md
									
									
									
									
									
										Normal 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.
 | 
			
		||||
							
								
								
									
										15
									
								
								buildext.js
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								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);
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -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()],
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "cdrm-extension",
 | 
			
		||||
    "version": "1.0.0",
 | 
			
		||||
    "version": "2.1.0",
 | 
			
		||||
    "description": "",
 | 
			
		||||
    "main": "background.js",
 | 
			
		||||
    "scripts": {
 | 
			
		||||
 | 
			
		||||
@ -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
									
								
							
							
						
						
									
										46
									
								
								syncVersion.js
									
									
									
									
									
										Normal 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;
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user