Address review findings on the lnw pointer read (#89)
- Share one lnw host regex between matches and the pointer validator so the two cannot drift apart. - Resolve the pointer href against the page address before validating, so a relative pointer still yields its Series instead of silently resolving to type other. - Pin pointer/breadcrumb agreement on the divergent page and pin that a pointer off-host or not /novel/<slug>/ resolves to other.
This commit is contained in:
@@ -132,26 +132,30 @@
|
||||
},
|
||||
};
|
||||
|
||||
// The host shape this adapter owns. One definition so the pointer validator
|
||||
// and `matches` cannot drift apart (a leading subdomain is allowed).
|
||||
const lnwHostRe = /(^|\.)lightnovelworld\.net$/;
|
||||
|
||||
// A chapter page's pointer is its own link back to its Series. The href is
|
||||
// page markup, so validate before trusting: the host must be this Site's (a
|
||||
// leading subdomain is allowed, as in `matches`) and the path the
|
||||
// /novel/<slug>/ Series shape. Anything else is not a pointer.
|
||||
function seriesIdFromLnwPointer(href) {
|
||||
// page markup, so validate before trusting: resolve it against the page
|
||||
// address, require the host above and the /novel/<slug>/ Series path.
|
||||
// Anything else is not a pointer.
|
||||
function seriesIdFromLnwPointer(href, base) {
|
||||
if (!href) return null;
|
||||
let u;
|
||||
try {
|
||||
u = new URL(href);
|
||||
u = new URL(href, base);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
if (!/(^|\.)lightnovelworld\.net$/.test(u.hostname)) return null;
|
||||
if (!lnwHostRe.test(u.hostname)) return null;
|
||||
const m = u.pathname.match(/^\/novel\/([^/]+)\/?$/);
|
||||
return m ? m[1] : null;
|
||||
}
|
||||
|
||||
const lightnovelworld = {
|
||||
site: "lightnovelworld",
|
||||
matches: (loc) => /(^|\.)lightnovelworld\.net$/.test(loc.hostname),
|
||||
matches: (loc) => lnwHostRe.test(loc.hostname),
|
||||
detect(loc) {
|
||||
const path = loc.pathname;
|
||||
// /<slug>-chapter-<n>/ — flat, at the site root, not under /novel/. The
|
||||
@@ -166,7 +170,7 @@
|
||||
// this replaced, not a safety net.
|
||||
const chapterSlug = m[1];
|
||||
const pointer = document.querySelector("a[aria-label='All Chapter']");
|
||||
let seriesId = pointer ? seriesIdFromLnwPointer(pointer.getAttribute("href")) : null;
|
||||
let seriesId = pointer ? seriesIdFromLnwPointer(pointer.getAttribute("href"), loc.href) : null;
|
||||
if (!seriesId) {
|
||||
// Fallback: the microdata breadcrumb's second crumb is the Series.
|
||||
// Scoped to the BreadcrumbList because itemprop="item" is not
|
||||
@@ -174,7 +178,7 @@
|
||||
const crumb = document.querySelector(
|
||||
'[itemtype="http://schema.org/BreadcrumbList"] a[itemprop="item"][href*="/novel/"]'
|
||||
);
|
||||
seriesId = crumb ? seriesIdFromLnwPointer(crumb.getAttribute("href")) : null;
|
||||
seriesId = crumb ? seriesIdFromLnwPointer(crumb.getAttribute("href"), loc.href) : null;
|
||||
}
|
||||
// Neither pointer present, nor either pointing at a /novel/<slug>/
|
||||
// address on this host: not a page the script understands, so no
|
||||
|
||||
Reference in New Issue
Block a user