From 8b973b430e2674e88fba20828c0e2ea37395bdde Mon Sep 17 00:00:00 2001 From: piquark6046 Date: Wed, 22 Apr 2026 23:46:15 +0000 Subject: [PATCH 1/2] feat: add GlobalMatchBuild class for enhanced domain matching functionality Co-authored-by: Copilot --- builder/package.json | 1 + builder/source/buildci.ts | 4 +- builder/source/globalmtach-test.ts | 75 ++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 builder/source/globalmtach-test.ts diff --git a/builder/package.json b/builder/package.json index 3f9c724..38476a4 100644 --- a/builder/package.json +++ b/builder/package.json @@ -42,6 +42,7 @@ "eslint": "^10.2.1", "piscina": "^5.1.4", "tldts": "^7.0.28", + "ts-morph": "^28.0.0", "tsx": "^4.21.0", "typescript": "^6.0.3", "typescript-eslint": "^8.58.2", diff --git a/builder/source/buildci.ts b/builder/source/buildci.ts index 493f4a3..65a46ba 100644 --- a/builder/source/buildci.ts +++ b/builder/source/buildci.ts @@ -5,6 +5,7 @@ import { StandardBuild } from './build.js' import { GroupedBuild } from './build-grouped.js' import { Build } from './build-core.js' import type { BuildOptions } from './build-core.js' +import { GlobalMatchBuild } from './globalmtach-test.js' let ParsedArgv = (await ParseArgumentsAndOptions(FilterArgumentsForOptions(Process.argv))).Options let Options = await Zod.strictObject({ @@ -21,4 +22,5 @@ const GroupedBuildInstance = new GroupedBuild(CoreBuildInstance, Options) await GroupedBuildInstance.Build() console.log('GroupedBuild completed successfully.') await GroupedBuildInstance.MakeGroupMetadata() -console.log('Group metadata creation completed successfully.') \ No newline at end of file +console.log('Group metadata creation completed successfully.') +await new GlobalMatchBuild(CoreBuildInstance, Options).Build() \ No newline at end of file diff --git a/builder/source/globalmtach-test.ts b/builder/source/globalmtach-test.ts new file mode 100644 index 0000000..14d4245 --- /dev/null +++ b/builder/source/globalmtach-test.ts @@ -0,0 +1,75 @@ +import * as Fs from 'node:fs' +import * as ESBuild from 'esbuild' +import PackageJson from '@npmcli/package-json' +import { CreateBanner } from './banner/index.js' +import { Build, type BuildOptions } from './build-core.js' + +export class GlobalMatchBuild extends Build { + constructor(FromOrOption: Build | BuildOptions, Option?: BuildOptions) { + if (FromOrOption instanceof Build) { + super(Option!) + this.CopyStateFrom(FromOrOption) + return + } + + super(FromOrOption) + } + + async Build() { + let MatchingDomains: Set = new Set(this.FetchedDomains.get('Full')) + let SubscriptionURL = new URL(`https://cdn.jsdelivr.net/npm/@filteringdev/tinyshield@${this.Options?.Version ?? (await PackageJson.load(this.ProjectRoot)).content.version ?? '0.0.0'}/dist/tinyShield-GlobalMatch.user.js`) + const Banner = CreateBanner({ + Version: this.Options?.Version ?? (await PackageJson.load(this.ProjectRoot)).content.version ?? '0.0.0', + BuildType: this.Options!.BuildType ?? 'production', + Domains: new Set(['*']), + Name: 'tinyShield GlobalMatch', + Namespace: 'https://github.com/FilteringDev/tinyShield', + DownloadURL: SubscriptionURL, + UpdateURL: SubscriptionURL, + HomepageURL: new URL('https://github.com/FilteringDev/tinyShield'), + SupportURL: new URL('https://github.com/FilteringDev/tinyShield/issues'), + License: 'MPL-2.0', + Author: 'PiQuark6046 and contributors', + Description: { + en: 'tinyShield allows AdGuard, uBlock Origin, Brave and ABP to resist against Ad-Shield quickly.', + ko: 'tinyShield는 AdGuard, uBlock Origin, Brave 와 ABP가 애드쉴드에 빠르게 저항할 수 있도록 합니다.', + ja: 'tinyShieldを使うと、AdGuard, uBlock Origin, Brave, およびABPがAd-Shieldに素早く対抗できます。' + } + }) + + Fs.copyFileSync(this.ProjectRoot + '/userscript/source/index.ts', this.ProjectRoot + '/userscript/source/index-globalmatch.ts') + const GlobalMatchIndexPath = this.ProjectRoot + '/userscript/source/index-globalmatch.ts' + const SourceText = Fs.readFileSync(GlobalMatchIndexPath, 'utf8') + const Anchor = 'export const OriginalRegExpTest = BrowserWindow.RegExp.prototype.test' + const AnchorIndex = SourceText.indexOf(Anchor) + if (AnchorIndex === -1) { + throw new Error('[globalmatch] Failed to find OriginalRegExpTest anchor in index-globalmatch.ts') + } + + const AnchorLineEndIndex = SourceText.indexOf('\n', AnchorIndex) + if (AnchorLineEndIndex === -1) { + throw new Error('[globalmatch] Failed to determine insertion point in index-globalmatch.ts') + } + + const DomainListElements = Array.from(MatchingDomains).map(Domain => JSON.stringify(Domain)).join(', ') + const ExecutionCondition = `(() => {\n const DomainList: string[] = [${DomainListElements}]\n const CurrentURL = new URL(BrowserWindow.location.href)\n if (!DomainList.some(Domain => BrowserWindow.location.href.includes(\`://\${Domain}/\`) || CurrentURL.hostname.endsWith(\`.\${Domain}\`))) {\n return\n }\n\n` + + const Head = SourceText.slice(0, AnchorLineEndIndex + 1) + const Tail = SourceText.slice(AnchorLineEndIndex + 1) + const TransformedSource = `${Head}\n${ExecutionCondition}${Tail}\n})()\n` + Fs.writeFileSync(GlobalMatchIndexPath, TransformedSource) + + await ESBuild.build({ + entryPoints: [this.ProjectRoot + '/userscript/source/index-globalmatch.ts'], + bundle: true, + minify: this.Options!.Minify, + outfile: `${this.ProjectRoot}/dist/tinyShield-GlobalMatch${this.Options!.BuildType === 'development' ? '.dev' : ''}.user.js`, + banner: { + js: Banner + }, + target: ['es2024', 'chrome119', 'firefox142', 'safari26'] + }) + + Fs.rmSync(this.ProjectRoot + '/userscript/source/index-globalmatch.ts') + } +} \ No newline at end of file From 1015d01b23a9b030891904f0920ba12646950a84 Mon Sep 17 00:00:00 2001 From: piquark6046 Date: Thu, 23 Apr 2026 00:53:09 +0000 Subject: [PATCH 2/2] fix: incorrect IIFE bundling --- builder/source/globalmtach-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/source/globalmtach-test.ts b/builder/source/globalmtach-test.ts index 14d4245..3a347f9 100644 --- a/builder/source/globalmtach-test.ts +++ b/builder/source/globalmtach-test.ts @@ -52,7 +52,7 @@ export class GlobalMatchBuild extends Build { } const DomainListElements = Array.from(MatchingDomains).map(Domain => JSON.stringify(Domain)).join(', ') - const ExecutionCondition = `(() => {\n const DomainList: string[] = [${DomainListElements}]\n const CurrentURL = new URL(BrowserWindow.location.href)\n if (!DomainList.some(Domain => BrowserWindow.location.href.includes(\`://\${Domain}/\`) || CurrentURL.hostname.endsWith(\`.\${Domain}\`))) {\n return\n }\n\n` + const ExecutionCondition = `;(() => {\n const DomainList: string[] = [${DomainListElements}]\n const CurrentURL = new URL(BrowserWindow.location.href)\n if (!DomainList.some(Domain => BrowserWindow.location.href.includes(\`://\${Domain}/\`) || CurrentURL.hostname.endsWith(\`.\${Domain}\`))) {\n return\n }\n\n` const Head = SourceText.slice(0, AnchorLineEndIndex + 1) const Tail = SourceText.slice(AnchorLineEndIndex + 1)