Skip to content

Conversation

@piquark6046
Copy link
Member

@piquark6046 piquark6046 commented Jan 14, 2026

Fix #39
Fix #42
Fix #40

@piquark6046 piquark6046 changed the title Resign repo structure and get domains list from multiple sources Redesign repo structure and get domains list from multiple sources Jan 14, 2026
…n path expression

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@piquark6046 piquark6046 marked this pull request as ready for review January 18, 2026 23:56
Copilot AI review requested due to automatic review settings January 18, 2026 23:56
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR redesigns the repository structure to use npm workspaces and implements a new multi-source approach for fetching Ad-Shield domains. The changes address issues where domains were missing from the userscript's @match rules, causing the script to not work on certain websites.

Changes:

  • Reorganized repository into workspaces (builder and userscript) with separate package.json and tsconfig.json files
  • Implemented domain fetching from multiple sources: IAB sellers.json, AdGuard filter lists, and uBlock Origin filter lists
  • Added build caching mechanism to reduce build times during development
  • Created a development debug server with file watching for hot-reload during development

Reviewed changes

Copilot reviewed 24 out of 29 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
package.json Added npm workspaces configuration, updated build scripts to use workspace commands
tsconfig.json Added path mappings for workspace aliases (@builder/, @userscript/, @root/, @reporoot/)
builder/package.json New workspace package with build, debug, and lint scripts; includes dependencies for building
builder/tsconfig.json TypeScript configuration extending root config for builder workspace
builder/source/build.ts Main build logic with domain fetching, wildcard expansion, and esbuild configuration
builder/source/buildci.ts CLI entry point for CI/CD builds with argument parsing
builder/source/debug.ts Development server with file watching for automatic rebuilds
builder/source/cache.ts Caching mechanism to store and load domains for faster development builds
builder/source/banner/index.ts UserScript metadata banner generation with domain injection
builder/source/references/index.ts Aggregates domains from multiple sources (IAB sellers, filter lists)
builder/source/references/iabsellers.ts Fetches domains from Ad-Shield's IAB sellers.json
builder/source/references/filterslists.ts Combines domains from AdGuard and uBlock Origin filter lists
builder/source/references/filterslists/ADG.ts Extracts Ad-Shield domains from AdGuard filter lists
builder/source/references/filterslists/uBO.ts Extracts Ad-Shield domains from uBlock Origin filter lists
builder/source/references/filterslists/keywords.ts Defines Ad-Shield CDN domains to exclude from matching
builder/source/references/custom-defined.ts Placeholder for custom domain definitions
builder/source/utils/http-server.ts HTTP server for serving built userscripts during development
builder/source/utils/wildcard-suffix-converter.ts Converts wildcard domain suffixes to concrete domain patterns
userscript/package.json New workspace package for userscript with lint script
userscript/tsconfig.json TypeScript configuration for userscript workspace
userscript/source/index.ts Main userscript logic (moved from sources/src/index.ts)
userscript/source/interface.ts Updated import path to reflect new structure
userscript/source/utils.ts Utility function for counting common strings between arrays
userscript/source/as-weakmap.ts Ad-Shield WeakMap detection logic (extracted from main file)
builder.ts Removed old monolithic build script
sources/banner.txt Removed old banner template file
sources/esbuild.inject.ts Removed empty inject file
.gitignore Added .buildcache to ignored files
.github/workflows/build.yml Changed to run on all branches instead of ignoring main

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ConvertWildcardSuffixToRegexPattern(Domain).forEach(GeneratedPattern => MatchingDomains.add(GeneratedPattern))
}
}

Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is trailing whitespace on this line. Consider removing it for consistency with code formatting standards.

Suggested change

Copilot uses AI. Check for mistakes.
BannerString += '// @run-at document-start\n'
BannerString += '//\n'
BannerString += `// @description ${Options.Description['en']}\n`

Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is trailing whitespace on this line. Consider removing it for consistency with code formatting standards.

Suggested change

Copilot uses AI. Check for mistakes.
Comment on lines 14 to 27
let StatrtingLine = -1
let EndingLine = -1
for (const [Index, Filter] of AGTreeFiltersList.children.entries()) {
if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(UBOFilterListAdShieldKeys.Starting)) {
StatrtingLine = Index
} else if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(UBOFilterListAdShieldKeys.Ending)) {
EndingLine = Index
} else if (StatrtingLine !== -1 && EndingLine !== -1) {
break
} else if (Index === AGTreeFiltersList.children.length - 1) {
throw new Error('Could not find Ad-Shield ad reinsertion section in ' + UBOFilterListSpecificURL)
}
}
const AdShieldFilters = AGTreeFiltersList.children.filter((Filter, Index) => Index > StatrtingLine && Index < EndingLine)
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name "StatrtingLine" is misspelled. It should be "StartingLine".

Suggested change
let StatrtingLine = -1
let EndingLine = -1
for (const [Index, Filter] of AGTreeFiltersList.children.entries()) {
if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(UBOFilterListAdShieldKeys.Starting)) {
StatrtingLine = Index
} else if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(UBOFilterListAdShieldKeys.Ending)) {
EndingLine = Index
} else if (StatrtingLine !== -1 && EndingLine !== -1) {
break
} else if (Index === AGTreeFiltersList.children.length - 1) {
throw new Error('Could not find Ad-Shield ad reinsertion section in ' + UBOFilterListSpecificURL)
}
}
const AdShieldFilters = AGTreeFiltersList.children.filter((Filter, Index) => Index > StatrtingLine && Index < EndingLine)
let StartingLine = -1
let EndingLine = -1
for (const [Index, Filter] of AGTreeFiltersList.children.entries()) {
if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(UBOFilterListAdShieldKeys.Starting)) {
StartingLine = Index
} else if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(UBOFilterListAdShieldKeys.Ending)) {
EndingLine = Index
} else if (StartingLine !== -1 && EndingLine !== -1) {
break
} else if (Index === AGTreeFiltersList.children.length - 1) {
throw new Error('Could not find Ad-Shield ad reinsertion section in ' + UBOFilterListSpecificURL)
}
}
const AdShieldFilters = AGTreeFiltersList.children.filter((Filter, Index) => Index > StartingLine && Index < EndingLine)

Copilot uses AI. Check for mistakes.
Comment on lines 14 to 27
let StatrtingLine = -1
let EndingLine = -1
for (const [Index, Filter] of AGTreeFiltersList.children.entries()) {
if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(AGBaseFilterListAdShieldKeys.Starting)) {
StatrtingLine = Index
} else if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(AGBaseFilterListAdShieldKeys.Ending)) {
EndingLine = Index
} else if (StatrtingLine !== -1 && EndingLine !== -1) {
break
} else if (Index === AGTreeFiltersList.children.length - 1) {
throw new Error('Could not find Ad-Shield ad reinsertion section in ' + AGBaseFilterListSpecificURL)
}
}
const AdShieldFilters = AGTreeFiltersList.children.filter((Filter, Index) => Index > StatrtingLine && Index < EndingLine)
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name "StatrtingLine" is misspelled. It should be "StartingLine".

Suggested change
let StatrtingLine = -1
let EndingLine = -1
for (const [Index, Filter] of AGTreeFiltersList.children.entries()) {
if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(AGBaseFilterListAdShieldKeys.Starting)) {
StatrtingLine = Index
} else if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(AGBaseFilterListAdShieldKeys.Ending)) {
EndingLine = Index
} else if (StatrtingLine !== -1 && EndingLine !== -1) {
break
} else if (Index === AGTreeFiltersList.children.length - 1) {
throw new Error('Could not find Ad-Shield ad reinsertion section in ' + AGBaseFilterListSpecificURL)
}
}
const AdShieldFilters = AGTreeFiltersList.children.filter((Filter, Index) => Index > StatrtingLine && Index < EndingLine)
let StartingLine = -1
let EndingLine = -1
for (const [Index, Filter] of AGTreeFiltersList.children.entries()) {
if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(AGBaseFilterListAdShieldKeys.Starting)) {
StartingLine = Index
} else if (Filter.category === 'Comment' && typeof Filter.raws.text === 'string' && Filter.raws.text.includes(AGBaseFilterListAdShieldKeys.Ending)) {
EndingLine = Index
} else if (StartingLine !== -1 && EndingLine !== -1) {
break
} else if (Index === AGTreeFiltersList.children.length - 1) {
throw new Error('Could not find Ad-Shield ad reinsertion section in ' + AGBaseFilterListSpecificURL)
}
}
const AdShieldFilters = AGTreeFiltersList.children.filter((Filter, Index) => Index > StartingLine && Index < EndingLine)

Copilot uses AI. Check for mistakes.

export async function FetchIABSellersJsonData(): Promise<string[]> {
const IABSellersJsonResponse: { StatusCode: number, Headers: Record<string, string | string[]>, Body: unknown } = await HTTPSRequest(new URL(IABSellersJsonURL), { ExpectedAs: 'JSON' })
let IABSellersJsonData =IABSellersJsonResponse.Body as {
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after the equals sign. Should be "let IABSellersJsonData = IABSellersJsonResponse.Body".

Suggested change
let IABSellersJsonData =IABSellersJsonResponse.Body as {
let IABSellersJsonData = IABSellersJsonResponse.Body as {

Copilot uses AI. Check for mistakes.
Comment on lines 9 to 14
const WatchingGlob = [];
['builder/', 'userscript/', ''].forEach(Dir => {
WatchingGlob.push(`${ProcessCwd}/${Dir}sources/**/*.ts`)
WatchingGlob.push(`${ProcessCwd}/${Dir}sources/**/*.json`)
WatchingGlob.push(`${ProcessCwd}/${Dir}sources/**/*.txt`)
})
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WatchingGlob array is constructed but never used. The Watcher uses hardcoded paths instead of the WatchingGlob. Either use WatchingGlob in the Chokidar.watch() call or remove it.

Suggested change
const WatchingGlob = [];
['builder/', 'userscript/', ''].forEach(Dir => {
WatchingGlob.push(`${ProcessCwd}/${Dir}sources/**/*.ts`)
WatchingGlob.push(`${ProcessCwd}/${Dir}sources/**/*.json`)
WatchingGlob.push(`${ProcessCwd}/${Dir}sources/**/*.txt`)
})

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +9
Minify: Zod.string().pipe(Zod.enum(['true', 'false'])).transform(Value => Value === 'true').default(true),
UseCache: Zod.string().pipe(Zod.enum(['true', 'false'])).transform(Value => Value === 'true').default(true),
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .default(true) method expects a boolean value, but it's being applied to a string schema before the transform. This should be .default('true') since the schema expects a string input that gets transformed to a boolean.

Suggested change
Minify: Zod.string().pipe(Zod.enum(['true', 'false'])).transform(Value => Value === 'true').default(true),
UseCache: Zod.string().pipe(Zod.enum(['true', 'false'])).transform(Value => Value === 'true').default(true),
Minify: Zod.string().pipe(Zod.enum(['true', 'false'])).transform(Value => Value === 'true').default('true'),
UseCache: Zod.string().pipe(Zod.enum(['true', 'false'])).transform(Value => Value === 'true').default('true'),

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +35
} else if (!IsLoopBack(Req.socket.remoteAddress)) {
Res.writeHead(403)
Res.end()
return
} else if (ShouldPreventHTTPResponse || !Fs.existsSync(ResolvedPath)) {
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expression Req.socket.remoteAddress may be undefined, which would cause IsLoopBack to receive undefined. Consider adding a null check or providing a default value before passing to IsLoopBack.

Suggested change
} else if (!IsLoopBack(Req.socket.remoteAddress)) {
Res.writeHead(403)
Res.end()
return
} else if (ShouldPreventHTTPResponse || !Fs.existsSync(ResolvedPath)) {
} else {
const RemoteAddress = Req.socket.remoteAddress
if (!RemoteAddress || !IsLoopBack(RemoteAddress)) {
Res.writeHead(403)
Res.end()
return
}
}
if (ShouldPreventHTTPResponse || !Fs.existsSync(ResolvedPath)) {

Copilot uses AI. Check for mistakes.
import { Build } from './build.js'

const ProcessCwd = Process.cwd()
const WatchingGlob = [];
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WatchingGlob array is declared without a type annotation. Consider adding an explicit type annotation: "const WatchingGlob: string[] = [];".

Suggested change
const WatchingGlob = [];
const WatchingGlob: string[] = [];

Copilot uses AI. Check for mistakes.
"@typescriptprime/parsing": "^1.0.4",
"@typescriptprime/securereq": "^1.1.0",
"chokidar": "^5.0.0",
"esbuild": "^0.27.2",
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The esbuild version 0.27.2 appears to be outdated. As of January 2025, esbuild was at version 0.24.x or higher. Consider updating to a more recent version.

Suggested change
"esbuild": "^0.27.2",
"esbuild": "^0.24.0",

Copilot uses AI. Check for mistakes.
@piquark6046 piquark6046 merged commit 169eaf3 into main Jan 19, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add https://mainichi.jp/ to supported target sites chanto.jp.net https://www.welt.de/

2 participants