Add script to compile web inject JavaScript with minification and obfuscation options
- Introduced `compile-web-script.ts` for generating JavaScript files for userscripts. - Supports options for minification and obfuscation. - Generates base JS, minified JS, and obfuscated userscript. - Configurable via command line arguments and environment variables.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -604,7 +604,6 @@ export const injectJavascriptData = ({
|
||||
}
|
||||
|
||||
if(new RegExp(/^4[1-9]\\d\\d[DM]$/).test(列番データ) || new RegExp(/^5[1-7]\\d\\d[DM]$/).test(列番データ) || new RegExp(/^3[2-9]\\d\\d[DM]$/).test(TrainNumber) ){
|
||||
flag=true;
|
||||
isWanman = true;
|
||||
}
|
||||
if(new RegExp(/^49[0-4]\\dD$/).test(列番データ) || new RegExp(/^9[0-4]\\dD$/).test(列番データ)){
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"compile-web-script": "npx tsx scripts/compile-web-script.ts",
|
||||
"start": "expo start",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
|
||||
144
scripts/compile-web-script.ts
Normal file
144
scripts/compile-web-script.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env tsx
|
||||
/**
|
||||
* compile-web-script.ts
|
||||
*
|
||||
* Usage:
|
||||
* yarn compile-web-script
|
||||
* yarn compile-web-script --no-obf # minifyのみ(難読化なし)
|
||||
* yarn compile-web-script --no-userscript # .js のみ生成(userscript不要)
|
||||
*
|
||||
* Options (環境変数でも上書き可):
|
||||
* UI=tokyo|default (default: tokyo)
|
||||
* DARK=true|false (default: false)
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { injectJavascriptData } from '../lib/webViewInjectjavascript';
|
||||
|
||||
// ---- オプション解析 ----
|
||||
const args = process.argv.slice(2);
|
||||
const noObf = args.includes('--no-obf');
|
||||
const noUserscript = args.includes('--no-userscript');
|
||||
|
||||
const options = {
|
||||
mapSwitch: 'false',
|
||||
iconSetting: 'true',
|
||||
stationMenu: 'false',
|
||||
trainMenu: 'false',
|
||||
uiSetting: (process.env.UI ?? 'tokyo') as string,
|
||||
useUnyohub: 'false',
|
||||
useElesite: 'false',
|
||||
isDark: (process.env.DARK ?? 'false') === 'true',
|
||||
backendApiBaseUrl:'https://jr-shikoku-backend-api-v1.haruk.in',
|
||||
mockApiConfig: null,
|
||||
} as const;
|
||||
|
||||
// ---- 出力ディレクトリ ----
|
||||
const outDir = path.resolve(__dirname, '../docs/generated');
|
||||
fs.mkdirSync(outDir, { recursive: true });
|
||||
|
||||
// const baseJs = path.join(outDir, 'webInjectJavascript.parsed.current.js'); // 中間: ベタJS
|
||||
// const minJs = path.join(outDir, 'webInjectJavascript.parsed.current.min.js'); // 中間: minify済み
|
||||
// const obfJs = path.join(outDir, 'webInjectJavascript.parsed.current.obf.js'); // 中間: 難読化済みJS
|
||||
// const baseUser = path.join(outDir, 'webInjectJavascript.parsed.current.user.js'); // 中間: ベタuserscript
|
||||
const obfUser = path.join(outDir, 'webInjectJavascript.parsed.current.obf.user.js');
|
||||
|
||||
// 中間ファイルを出力したい場合は上の const を有効化して各ステップの writeFileSync コメントを外す
|
||||
const baseJs = '/tmp/webInjectJavascript.base.js';
|
||||
const minJs = '/tmp/webInjectJavascript.min.js';
|
||||
const obfJs = '/tmp/webInjectJavascript.obf.js';
|
||||
|
||||
// ---- userscript ヘッダ ----
|
||||
const userscriptHeader = `\
|
||||
// ==UserScript==
|
||||
// @name JR Shikoku WebInject
|
||||
// @namespace jrshikoku
|
||||
// @version 1.0.0
|
||||
// @description Generated inject script for train.jr-shikoku.co.jp
|
||||
// @match https://train.jr-shikoku.co.jp/*
|
||||
// @run-at document-end
|
||||
// @grant none
|
||||
// ==/UserScript==
|
||||
(function(){
|
||||
`;
|
||||
const userscriptFooter = `\n})();\n`;
|
||||
|
||||
function wrapUserscript(src: string): string {
|
||||
return userscriptHeader + src + userscriptFooter;
|
||||
}
|
||||
|
||||
// ---- Step 1: ベタJS生成 ----
|
||||
console.log('[1/3] Generating base JS...');
|
||||
const shim = `\
|
||||
/*
|
||||
Generated from lib/webViewInjectjavascript.ts
|
||||
Options: ${JSON.stringify(options)}
|
||||
Date: ${new Date().toISOString()}
|
||||
*/
|
||||
if (!window.ReactNativeWebView) {
|
||||
window.ReactNativeWebView = {
|
||||
postMessage: (msg) => console.log('[ReactNativeWebView.postMessage]', msg),
|
||||
};
|
||||
}
|
||||
`;
|
||||
const raw = injectJavascriptData(options);
|
||||
const baseContent = `${shim}\n${raw}`;
|
||||
fs.writeFileSync(baseJs, baseContent, 'utf8');
|
||||
// fs.writeFileSync(baseJs, baseContent, 'utf8'); // 中間ファイルとして保存する場合
|
||||
// if (!noUserscript) {
|
||||
// fs.writeFileSync(baseUser, wrapUserscript(baseContent), 'utf8'); // ベタuserscriptを保存する場合
|
||||
// }
|
||||
console.log(` -> base JS generated (${Math.round(Buffer.byteLength(baseContent) / 1024)}KB)`);
|
||||
|
||||
// ---- Step 2: minify (terser) ----
|
||||
console.log('[2/3] Minifying with terser...');
|
||||
const terserCmd = [
|
||||
'npx', 'terser', JSON.stringify(baseJs),
|
||||
'--compress', 'passes=3,drop_console=false,pure_getters=true',
|
||||
'--mangle', 'toplevel=true',
|
||||
'--output', JSON.stringify(minJs),
|
||||
].join(' ');
|
||||
execSync(terserCmd, { stdio: 'inherit' });
|
||||
// fs.copyFileSync(minJs, path.join(outDir, 'webInjectJavascript.parsed.current.min.js')); // 中間ファイルとして保存する場合
|
||||
console.log(` -> minified (${Math.round(fs.statSync(minJs).size / 1024)}KB)`);
|
||||
|
||||
if (noObf) {
|
||||
console.log('[3/3] Skipped obfuscation (--no-obf)');
|
||||
console.log('Done.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// ---- Step 3: 難読化 (javascript-obfuscator) ----
|
||||
console.log('[3/3] Obfuscating with javascript-obfuscator...');
|
||||
const obfCmd = [
|
||||
'npx', 'javascript-obfuscator', JSON.stringify(minJs),
|
||||
'--output', JSON.stringify(obfJs),
|
||||
'--compact', 'true',
|
||||
'--control-flow-flattening', 'false',
|
||||
'--dead-code-injection', 'false',
|
||||
'--string-array', 'true',
|
||||
'--string-array-encoding', 'base64',
|
||||
'--string-array-threshold', '0.75',
|
||||
'--string-array-rotate', 'true',
|
||||
'--string-array-shuffle', 'true',
|
||||
'--string-array-calls-transform', 'true',
|
||||
'--string-array-index-shift', 'true',
|
||||
'--string-array-wrappers-count', '2',
|
||||
'--string-array-wrappers-type', 'function',
|
||||
'--string-array-wrappers-chained-calls', 'true',
|
||||
'--split-strings', 'true',
|
||||
'--split-strings-chunk-length', '8',
|
||||
'--identifier-names-generator', 'hexadecimal',
|
||||
'--rename-globals', 'false',
|
||||
'--self-defending', 'false',
|
||||
].join(' ');
|
||||
execSync(obfCmd, { stdio: 'inherit' });
|
||||
// fs.copyFileSync(obfJs, path.join(outDir, 'webInjectJavascript.parsed.current.obf.js')); // 難読化JSを保存する場合
|
||||
|
||||
const obfContent = fs.readFileSync(obfJs, 'utf8');
|
||||
fs.writeFileSync(obfUser, wrapUserscript(obfContent), 'utf8');
|
||||
|
||||
console.log('\nDone. Generated:');
|
||||
console.log(` ${path.relative(process.cwd(), obfUser)} (${Math.round(fs.statSync(obfUser).size / 1024)}KB)`);
|
||||
Reference in New Issue
Block a user