From 975be6a4d00532b4c502fe1d2d8ade328c749e4f Mon Sep 17 00:00:00 2001 From: yakisova41 Date: Tue, 2 Apr 2024 22:13:49 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8Ffeat:=20add=20userscript=20do?= =?UTF-8?q?m=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-ja.md | 5 +++ README.md | 5 +++ dev/crx-monkey.config.js | 5 ++- packages/crx-monkey/src/node/config.ts | 1 + .../node/handlers/build/BuildUserScript.ts | 39 +++++++++++++------ .../src/node/handlers/dev/WatchUserScript.ts | 39 +++++++++++++------ .../crx-monkey/src/node/handlers/dev/index.ts | 2 +- .../crx-monkey/src/node/handlers/dev/utils.ts | 10 +++++ packages/crx-monkey/src/node/types.ts | 1 + 9 files changed, 81 insertions(+), 26 deletions(-) diff --git a/README-ja.md b/README-ja.md index f93bb7e..f52d12f 100644 --- a/README-ja.md +++ b/README-ja.md @@ -70,6 +70,7 @@ const config = { ['@author', 'me'], ['@grant', 'unsageWindow'], ], + userscriptInjectPage: ['src/contentScript/contentScript.ts'], }; export default config; @@ -121,3 +122,7 @@ publicフォルダーのディレクトリパスを指定できます。 ### importIconToUsercript `manifest.json`に指定された48ピクセルのiconをbase64に変換してuserscriptのiconに設定します + +### userscriptInjectPage + +userscriptとして読み込む際にunsafeWindowからアクセスしたbodyへ直接scriptタグを使用して挿入するcontentscriptを指定できます。 diff --git a/README.md b/README.md index b6ef0c4..bc1ff0a 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ const config = { ['@author', 'me'], ['@grant', 'unsageWindow'], ], + userscriptInjectPage: ['src/contentScript/contentScript.ts'], }; export default config; @@ -121,3 +122,7 @@ For detailed header format, please check [Documentation | Tampermonkey](https:// ### importIconToUsercript Convert the 48-pixel icon specified in the `manifest.json` to base64 and set it to the userscript icon. + +### userscriptInjectPage + +You can specify the contentscript to be inserted using a script tag directly into the body accessed from the unsafeWindow when loading as a userscript. diff --git a/dev/crx-monkey.config.js b/dev/crx-monkey.config.js index c2932d1..edd2555 100644 --- a/dev/crx-monkey.config.js +++ b/dev/crx-monkey.config.js @@ -1,6 +1,9 @@ // @ts-check /** @type {import('../packages/crx-monkey/dist/node/main').NonLoadedCrxMonkeyConfig} */ -const config = { importIconToUsercript: true }; +const config = { + importIconToUsercript: true, + userscriptInjectPage: ['src/contentScript/contentScript.ts'], +}; export default config; diff --git a/packages/crx-monkey/src/node/config.ts b/packages/crx-monkey/src/node/config.ts index cc70cbb..2ea96d7 100644 --- a/packages/crx-monkey/src/node/config.ts +++ b/packages/crx-monkey/src/node/config.ts @@ -17,6 +17,7 @@ const defaultConfig: CrxMonkeyConfig = { publicDir: path.join(process.cwd(), './public'), userScriptHeader: [], importIconToUsercript: false, + userscriptInjectPage: [], }; async function getConfigPath(): Promise { diff --git a/packages/crx-monkey/src/node/handlers/build/BuildUserScript.ts b/packages/crx-monkey/src/node/handlers/build/BuildUserScript.ts index 3ef31b8..556ad30 100644 --- a/packages/crx-monkey/src/node/handlers/build/BuildUserScript.ts +++ b/packages/crx-monkey/src/node/handlers/build/BuildUserScript.ts @@ -13,6 +13,7 @@ import { BuildResult } from 'esbuild'; import fse from 'fs-extra'; import path from 'path'; import { Build, BuildImplements } from './Build'; +import { generateInjectScriptCode } from '../dev/utils'; export class BuildUserScript extends Build implements BuildImplements { private readonly headerFactory: UserscriptHeaderFactory; @@ -38,14 +39,11 @@ export class BuildUserScript extends Build implements BuildImplements { if (contentScripts !== undefined) { const { jsFiles, cssFiles } = getAllJsAndCSSByContentScripts(contentScripts); - /** - * If even one css is loaded, a GM_addStyle grant is added to the header - */ - const isLoadedCss = cssFiles.length !== 0; - const { matchMap, allMatches } = createMatchMap(contentScripts, jsFiles, cssFiles); - this.headerRegister(allMatches, isLoadedCss); + const isExistInjectScripts = this.isIncludedInjectScripts(jsFiles); + + this.headerRegister(allMatches, isExistInjectScripts); this.loadContentCssFiles(cssFiles); @@ -62,7 +60,7 @@ export class BuildUserScript extends Build implements BuildImplements { } } - private async headerRegister(allMatches: string[], isLoadedCss: boolean) { + private async headerRegister(allMatches: string[], unsafeWindow: boolean) { allMatches.forEach((match) => { this.headerFactory.push('@match', match); }); @@ -93,10 +91,6 @@ export class BuildUserScript extends Build implements BuildImplements { }); } - if (isLoadedCss) { - this.headerFactory.push('@grant', 'GM_addStyle'); - } - const configHeader = this.config.userScriptHeader; if (configHeader !== undefined) { configHeader.forEach((configHeaderItem) => { @@ -108,6 +102,10 @@ export class BuildUserScript extends Build implements BuildImplements { }); } + if (unsafeWindow) { + this.headerFactory.push('@grant', 'unsafeWindow'); + } + if (this.config.importIconToUsercript) { const icons = this.manifest.icons; @@ -169,7 +167,12 @@ export class BuildUserScript extends Build implements BuildImplements { if (jsBuildResultStore[filePath] !== undefined) { const buildResultText = new TextDecoder().decode(jsBuildResultStore[filePath]); - scriptContent = scriptContent + buildResultText; + + if (this.config.userscriptInjectPage.includes(filePath)) { + scriptContent = scriptContent + generateInjectScriptCode(buildResultText); + } else { + scriptContent = scriptContent + buildResultText; + } } if (cssResultStore[filePath] !== undefined) { @@ -215,4 +218,16 @@ export class BuildUserScript extends Build implements BuildImplements { this.cssResultStore[cssFilePath] = result; }); } + + private isIncludedInjectScripts(jsFiles: string[]) { + let result = false; + + jsFiles.forEach((jsFile) => { + if (this.config.userscriptInjectPage.includes(jsFile)) { + result = true; + } + }); + + return result; + } } diff --git a/packages/crx-monkey/src/node/handlers/dev/WatchUserScript.ts b/packages/crx-monkey/src/node/handlers/dev/WatchUserScript.ts index 3d99d97..bfcdfba 100644 --- a/packages/crx-monkey/src/node/handlers/dev/WatchUserScript.ts +++ b/packages/crx-monkey/src/node/handlers/dev/WatchUserScript.ts @@ -14,6 +14,7 @@ import { BuildResult } from 'esbuild'; import fse from 'fs-extra'; import path from 'path'; import { ReloadServer } from './server/reloadServer'; +import { generateInjectScriptCode } from './utils'; export class WatchUserScript extends Watch implements WatchImplements { private readonly headerFactory: UserscriptHeaderFactory; @@ -41,14 +42,11 @@ export class WatchUserScript extends Watch implements WatchImplements { if (contentScripts !== undefined) { const { jsFiles, cssFiles } = getAllJsAndCSSByContentScripts(contentScripts); - /** - * If even one css is loaded, a GM_addStyle grant is added to the header - */ - const isLoadedCss = cssFiles.length !== 0; - const { matchMap, allMatches } = createMatchMap(contentScripts, jsFiles, cssFiles); - this.headerRegister(allMatches, isLoadedCss); + const isExistInjectScripts = this.isIncludedInjectScripts(jsFiles); + + this.headerRegister(allMatches, isExistInjectScripts); this.loadContentCssFiles(cssFiles); @@ -69,7 +67,7 @@ export class WatchUserScript extends Watch implements WatchImplements { } } - private async headerRegister(allMatches: string[], isLoadedCss: boolean) { + private async headerRegister(allMatches: string[], unsafeWindow: boolean) { allMatches.forEach((match) => { this.headerFactory.push('@match', match); }); @@ -100,10 +98,6 @@ export class WatchUserScript extends Watch implements WatchImplements { }); } - if (isLoadedCss) { - this.headerFactory.push('@grant', 'GM_addStyle'); - } - const configHeader = this.config.userScriptHeader; if (configHeader !== undefined) { configHeader.forEach((configHeaderItem) => { @@ -115,6 +109,10 @@ export class WatchUserScript extends Watch implements WatchImplements { }); } + if (unsafeWindow) { + this.headerFactory.push('@grant', 'unsafeWindow'); + } + if (this.config.importIconToUsercript) { const icons = this.manifest.icons; @@ -176,7 +174,12 @@ export class WatchUserScript extends Watch implements WatchImplements { if (jsBuildResultStore[filePath] !== undefined) { const buildResultText = new TextDecoder().decode(jsBuildResultStore[filePath]); - scriptContent = scriptContent + buildResultText; + + if (this.config.userscriptInjectPage.includes(filePath)) { + scriptContent = scriptContent + generateInjectScriptCode(buildResultText); + } else { + scriptContent = scriptContent + buildResultText; + } } if (cssResultStore[filePath] !== undefined) { @@ -222,4 +225,16 @@ export class WatchUserScript extends Watch implements WatchImplements { this.cssResultStore[cssFilePath] = result; }); } + + private isIncludedInjectScripts(jsFiles: string[]) { + let result = false; + + jsFiles.forEach((jsFile) => { + if (this.config.userscriptInjectPage.includes(jsFile)) { + result = true; + } + }); + + return result; + } } diff --git a/packages/crx-monkey/src/node/handlers/dev/index.ts b/packages/crx-monkey/src/node/handlers/dev/index.ts index dfed312..3cdc5e6 100644 --- a/packages/crx-monkey/src/node/handlers/dev/index.ts +++ b/packages/crx-monkey/src/node/handlers/dev/index.ts @@ -58,7 +58,7 @@ export default async function handleDev() { await hostingServer.start(); - console.clear(); + // console.clear(); consola.box( [ `${chalk.cyan.bold('CRX-MONKEY')} ${chalk.green(`v${pkg.version}`)}`, diff --git a/packages/crx-monkey/src/node/handlers/dev/utils.ts b/packages/crx-monkey/src/node/handlers/dev/utils.ts index 982fcaf..60a88db 100644 --- a/packages/crx-monkey/src/node/handlers/dev/utils.ts +++ b/packages/crx-monkey/src/node/handlers/dev/utils.ts @@ -11,3 +11,13 @@ export function getDevelopDir() { throw new Error(''); } } + +export function generateInjectScriptCode(scriptContent: string) { + return [ + `const inject = ()=>{${scriptContent}}`, + 'const script = document.createElement("script");', + 'script.innerHTML = `(${inject.toString()})()`', + 'unsafeWindow.document.body.appendChild(script)', + '', + ].join('\n'); +} diff --git a/packages/crx-monkey/src/node/types.ts b/packages/crx-monkey/src/node/types.ts index 98868a3..1108fe3 100644 --- a/packages/crx-monkey/src/node/types.ts +++ b/packages/crx-monkey/src/node/types.ts @@ -13,6 +13,7 @@ export interface CrxMonkeyConfig { publicDir: string; userScriptHeader: UserScriptHeader; importIconToUsercript: boolean; + userscriptInjectPage: string[]; } export type NonLoadedCrxMonkeyConfig = {