-
Notifications
You must be signed in to change notification settings - Fork 2
refactor: optimize event listener for vue:settled to handle HTMLTableElement variants
#234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -53,25 +53,16 @@ export async function RunNamuLinkUserscript(BrowserWindow: typeof window, Usersc | |||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const OCRInstance = CreateOcrWorkerClient(BrowserWindow, new Worker(URL.createObjectURL(new Blob([__OCR_WORKER_CODE__], { type: 'application/javascript' })))) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ArticleHTMLElement.addEventListener('vue:settled', async () => { | ||||||||||||||||||||||||||||||||||||||
| let Targeted = [...document.querySelectorAll('#app div[class] div[class] ~ div[class]')].filter(Ele => Ele instanceof HTMLElement) | ||||||||||||||||||||||||||||||||||||||
| Targeted = Targeted.filter(Ele => | ||||||||||||||||||||||||||||||||||||||
| parseFloat(getComputedStyle(Ele).getPropertyValue('padding-top')) >= 20 || | ||||||||||||||||||||||||||||||||||||||
| parseFloat(getComputedStyle(Ele).getPropertyValue('margin-top')) >= 20 || | ||||||||||||||||||||||||||||||||||||||
| parseFloat(getComputedStyle(Ele).getPropertyValue('margin-bottom')) >= 12.5 | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| Targeted = Targeted.filter(Ele => [...Ele.querySelectorAll('*')].filter(Child => | ||||||||||||||||||||||||||||||||||||||
| parseFloat(getComputedStyle(Child).getPropertyValue('padding-top')) >= 5 && parseFloat(getComputedStyle(Child).getPropertyValue('border-bottom-width')) >= 0.1 | ||||||||||||||||||||||||||||||||||||||
| ).length === 1) | ||||||||||||||||||||||||||||||||||||||
| Targeted = await (async () => { | ||||||||||||||||||||||||||||||||||||||
| const NextTargeted = [] | ||||||||||||||||||||||||||||||||||||||
| async function ExecuteOCR(Targeted: HTMLElement[]) { | ||||||||||||||||||||||||||||||||||||||
| const NextTargeted = [] | ||||||||||||||||||||||||||||||||||||||
| for (const Parent of Targeted) { | ||||||||||||||||||||||||||||||||||||||
| const CandidateChildren = [...Parent.querySelectorAll('*')] | ||||||||||||||||||||||||||||||||||||||
| .filter(Child => Child instanceof HTMLElement) | ||||||||||||||||||||||||||||||||||||||
| .filter(Child => | ||||||||||||||||||||||||||||||||||||||
| Child instanceof HTMLImageElement || | ||||||||||||||||||||||||||||||||||||||
| getComputedStyle(Child).backgroundImage !== 'none' | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| ).filter(Child => parseFloat(getComputedStyle(Child).getPropertyValue('width')) >= 5 && parseFloat(getComputedStyle(Child).getPropertyValue('height')) >= 5) | ||||||||||||||||||||||||||||||||||||||
| .filter(Child => parseFloat(getComputedStyle(Child).getPropertyValue('width')) <= 50 && parseFloat(getComputedStyle(Child).getPropertyValue('height')) <= 50) | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
61
to
+65
|
||||||||||||||||||||||||||||||||||||||
| let MatchedCount = 0 | ||||||||||||||||||||||||||||||||||||||
| for (const Child of CandidateChildren) { | ||||||||||||||||||||||||||||||||||||||
| const Result = await OCRInstance.DetectFromElement(Child, { | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -87,17 +78,48 @@ export async function RunNamuLinkUserscript(BrowserWindow: typeof window, Usersc | |||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return NextTargeted | ||||||||||||||||||||||||||||||||||||||
| })() | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ArticleHTMLElement.addEventListener('vue:settled', async () => { | ||||||||||||||||||||||||||||||||||||||
| let Targeted = [...document.querySelectorAll('#app div[class] div[class] ~ div[class]')].filter(Ele => Ele instanceof HTMLElement) | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
| let Targeted = [...document.querySelectorAll('#app div[class] div[class] ~ div[class]')].filter(Ele => Ele instanceof HTMLElement) | |
| let Targeted = [...BrowserWindow.document.querySelectorAll('#app div[class] div[class] ~ div[class]')].filter(Ele => Ele instanceof HTMLElement) |
Copilot
AI
Apr 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment // non-HTMLTableElement is misleading here: the predicate does not check that the child is not a table element, so table-related DOM could still satisfy this branch. Please either enforce the non-table condition or reword the comment to match the actual logic.
Copilot
AI
Apr 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ele.querySelectorAll('*') is executed again in subsequent Targeted = Targeted.filter(...) steps (e.g., the next filter starting at line 101). Consider collecting Children once per Ele (or combining these predicates) to avoid repeated full DOM traversals for the same element.
| if (Children.filter(Child => | |
| parseFloat(getComputedStyle(Child).getPropertyValue('padding-top')) >= 5 && | |
| parseFloat(getComputedStyle(Child).getPropertyValue('border-bottom-width')) >= 0.1 | |
| ).length === 1) return true | |
| // HTMLTableElement | |
| return Children.filter(Child => (Child instanceof HTMLTableElement || Child instanceof HTMLTableCellElement) && | |
| parseFloat(getComputedStyle(Child).getPropertyValue('padding-top')) >= 5 && parseFloat(getComputedStyle(Child).getPropertyValue('padding-bottom')) >= 5).length >= 2 | |
| }) | |
| Targeted = Targeted.filter(Ele => { | |
| let Children = [...Ele.querySelectorAll('*')].filter(Child => Child instanceof HTMLElement) | |
| const MatchesStructure = Children.filter(Child => | |
| parseFloat(getComputedStyle(Child).getPropertyValue('padding-top')) >= 5 && | |
| parseFloat(getComputedStyle(Child).getPropertyValue('border-bottom-width')) >= 0.1 | |
| ).length === 1 || | |
| // HTMLTableElement | |
| Children.filter(Child => (Child instanceof HTMLTableElement || Child instanceof HTMLTableCellElement) && | |
| parseFloat(getComputedStyle(Child).getPropertyValue('padding-top')) >= 5 && parseFloat(getComputedStyle(Child).getPropertyValue('padding-bottom')) >= 5).length >= 2 | |
| if (!MatchesStructure) return false |
Copilot
AI
Apr 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inside this some(...) predicate, getComputedStyle(Child) is effectively invoked multiple times per element (once per property). Consider caching const Style = getComputedStyle(Child) and reading all needed properties from it to reduce repeated style lookups.
| return parseFloat(getComputedStyle(Child).getPropertyValue('margin-bottom')) >= 10 && parseFloat(getComputedStyle(Child).getPropertyValue('padding-bottom')) >= 1 && parseFloat(getComputedStyle(Child).getPropertyValue('padding-top')) >= 1 && | |
| parseFloat(getComputedStyle(Child).getPropertyValue('border-top-width')) >= 0.25 && parseFloat(getComputedStyle(Child).getPropertyValue('border-bottom-width')) >= 0.25 | |
| const Style = getComputedStyle(Child) | |
| return parseFloat(Style.getPropertyValue('margin-bottom')) >= 10 && parseFloat(Style.getPropertyValue('padding-bottom')) >= 1 && parseFloat(Style.getPropertyValue('padding-top')) >= 1 && | |
| parseFloat(Style.getPropertyValue('border-top-width')) >= 0.25 && parseFloat(Style.getPropertyValue('border-bottom-width')) >= 0.25 |
Copilot
AI
Apr 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable name RealTabletTargeted looks like a typo given the surrounding table-related logic (HTMLTableElement). Consider renaming to RealTableTargeted (or similar) to avoid confusion and to keep log messages consistent.
| let RealTabletTargeted = Targeted.filter(Ele => { | |
| if (!(Ele instanceof HTMLElement) || !(Ele instanceof HTMLTableElement)) return false | |
| let Children = [...Ele.querySelectorAll('*')].filter(Child => Child instanceof HTMLElement) | |
| return Children.some(Child => parseFloat(getComputedStyle(Child).getPropertyValue('padding-top')) >= 5 && parseFloat(getComputedStyle(Child).getPropertyValue('padding-bottom')) >= 5) | |
| }) | |
| console.debug(`[${UserscriptName}] vue:settled RealTabletTargeted`, RealTabletTargeted) | |
| RealTabletTargeted.forEach(Ele => { | |
| let RealTableTargeted = Targeted.filter(Ele => { | |
| if (!(Ele instanceof HTMLElement) || !(Ele instanceof HTMLTableElement)) return false | |
| let Children = [...Ele.querySelectorAll('*')].filter(Child => Child instanceof HTMLElement) | |
| return Children.some(Child => parseFloat(getComputedStyle(Child).getPropertyValue('padding-top')) >= 5 && parseFloat(getComputedStyle(Child).getPropertyValue('padding-bottom')) >= 5) | |
| }) | |
| console.debug(`[${UserscriptName}] vue:settled RealTableTargeted`, RealTableTargeted) | |
| RealTableTargeted.forEach(Ele => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExecuteOCRreturns an untyped empty array (const NextTargeted = []), so TypeScript infersany[]and you lose type-safety forTargetedafterawait ExecuteOCR(Targeted). Please typeNextTargeted(e.g.,HTMLElement[]) and/or add an explicit return type likePromise<HTMLElement[]>.