InfoLens / extension /articleRoot.js
dqy08's picture
增强 articleRoot.js 中的根提取逻辑,添加 extractRootPatches 手动修补功能;
b25af45
Raw
History Blame Contribute Delete
2.5 kB
/**
* 定根:text/plain 整页即正文;其余走 Readability(预打标 → clone → data-il-rid 映回),
* 再经 extractRootPatches 手动修补。Readability 失败抛错,不回退启发式。
*/
(() => {
const ATTR = 'data-il-rid';
/**
* 浏览器对 text/plain(.txt / .py raw 等)的原生查看器:整页即正文。
* @param {Document} doc
* @returns {Element | null}
*/
function findPlainTextRoot(doc) {
if (!doc.body) return null;
if (doc.contentType === 'text/plain') return doc.body;
return null;
}
function mark(doc) {
if (!doc.body) return;
let seq = 0;
// body 本身也要打标:Readability 退到合成根时映回 page/body
doc.body.setAttribute(ATTR, String(++seq));
for (const el of doc.body.querySelectorAll('*')) {
el.setAttribute(ATTR, String(++seq));
}
}
function unmark(doc) {
if (!doc.body) return;
doc.body.removeAttribute(ATTR);
for (const el of doc.body.querySelectorAll(`[${ATTR}]`)) {
el.removeAttribute(ATTR);
}
}
/** @param {Element} root @param {Document} doc */
function applyPatches(root, doc) {
const apply = globalThis.IL_applyExtractRootPatches;
if (typeof apply !== 'function') {
throw new Error('IL_applyExtractRootPatches missing — inject extractRootPatches.js first');
}
return apply(root, doc);
}
/**
* @param {Document} doc
* @returns {Element}
*/
function findArticleRoot(doc) {
if (!doc?.body) {
throw new Error('document.body missing');
}
const plain = findPlainTextRoot(doc);
if (plain) return applyPatches(plain, doc);
if (typeof Readability !== 'function') {
throw new Error('Readability missing — inject vendor/Readability.js first');
}
mark(doc);
try {
const clone = doc.cloneNode(true);
const reader = new Readability(clone);
const parsed = reader.parse();
if (!parsed) {
throw new Error('Readability: parse failed');
}
const rid = reader._ilArticleRootRid;
if (rid == null || rid === '') {
throw new Error('Readability: no mappable article root');
}
const root = doc.querySelector(`[${ATTR}="${CSS.escape(String(rid))}"]`);
if (!root) {
throw new Error(`Readability: live root not found (rid=${rid})`);
}
return applyPatches(root, doc);
} finally {
unmark(doc);
}
}
globalThis.IL_findArticleRoot = findArticleRoot;
})();