mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-22 03:05:32 +02:00
fix: use correct single-file hook event (single-file-on-before-capture-request)
Prior scripts listened on 'single-file-on-before-capture-start' which does not exist in single-file-core 1.1.49. The real hook is: single-file-on-before-capture-request (dispatched by initUserScriptHandler after receiving single-file-user-script-init; userScriptEnabled defaults to true in args.js so it always fires when --browser-script is passed) Changes: - strip-scripts: -start -> -request (no preventDefault needed; synchronous) - READER_MODE_SCRIPT: -start -> -request; add 'installed' meta marker at script-evaluation time so artifact inspection can distinguish 'script not injected' / 'hook never fired' / 'Readability parse failed'
This commit is contained in:
parent
ef8b5ac83b
commit
b4e092f10d
1 changed files with 87 additions and 53 deletions
|
|
@ -13,18 +13,47 @@ use crate::downloader::cookies::{domain_from_url, write_netscape_cookie_file};
|
|||
use crate::hash::hash_file;
|
||||
|
||||
/// Mozilla Readability.js (Apache 2.0) — embedded at compile time so captures
|
||||
/// don't need it on PATH. Path is relative to this source file.
|
||||
const READABILITY_JS: &str =
|
||||
include_str!("../../../../vendor/readability/Readability.js");
|
||||
|
||||
/// Single-file user script that applies Readability just before the page is
|
||||
/// serialised. Fires on `single-file-on-before-capture-start`.
|
||||
const READER_MODE_WRAPPER_JS: &str = r#"
|
||||
addEventListener('single-file-on-before-capture-start', function() {
|
||||
/// Combined reader-mode script: Readability.js (Apache 2.0) bundled with the
|
||||
/// archivr wrapper in a single IIFE so both share the same execution scope —
|
||||
/// passing them as separate `--browser-script` files can put each in its own
|
||||
/// context (observed with single-file-cli 1.1.49), making Readability invisible
|
||||
/// to the wrapper.
|
||||
///
|
||||
/// Emits `<meta name="archivr-reader-mode" content="applied|failed:REASON">`
|
||||
/// so the outcome is observable in the saved HTML.
|
||||
const READER_MODE_SCRIPT: &str = concat!(
|
||||
// Readability.js is injected verbatim first so `Readability` is in scope.
|
||||
include_str!("../../../../vendor/readability/Readability.js"),
|
||||
// Wrapper IIFE — runs on single-file-on-before-capture-request.
|
||||
// Sets 'installed' immediately at script-evaluation time so a missing meta
|
||||
// means the browser-script was never injected at all.
|
||||
r#"
|
||||
;(function() {
|
||||
function _archivrReaderMark(content) {
|
||||
try {
|
||||
if (typeof Readability === 'undefined') return;
|
||||
var m = document.querySelector('meta[name="archivr-reader-mode"]');
|
||||
if (!m) {
|
||||
m = document.createElement('meta');
|
||||
m.name = 'archivr-reader-mode';
|
||||
(document.head || document.documentElement).appendChild(m);
|
||||
}
|
||||
m.content = content;
|
||||
} catch(_) {}
|
||||
}
|
||||
// Mark immediately: if this meta is absent in the artifact the script
|
||||
// was never injected (separate from the hook never firing).
|
||||
_archivrReaderMark('installed');
|
||||
function _archivrApplyReader() {
|
||||
try {
|
||||
if (typeof Readability === 'undefined') {
|
||||
_archivrReaderMark('failed:no-readability');
|
||||
return;
|
||||
}
|
||||
var article = new Readability(document.cloneNode(true)).parse();
|
||||
if (!article || !article.content || article.content.length < 100) return;
|
||||
if (!article || !article.content || article.content.length < 100) {
|
||||
_archivrReaderMark('failed:no-article');
|
||||
return;
|
||||
}
|
||||
document.body.innerHTML = article.content;
|
||||
if (article.title) document.title = article.title;
|
||||
var hdr = document.createElement('header');
|
||||
|
|
@ -53,9 +82,16 @@ addEventListener('single-file-on-before-capture-start', function() {
|
|||
'blockquote{border-left:3px solid #ccc;margin:1em 0;padding-left:1.2em;color:#555}',
|
||||
].join('');
|
||||
document.head.appendChild(style);
|
||||
} catch (e) { /* non-fatal: fall back to original page */ }
|
||||
});
|
||||
"#;
|
||||
_archivrReaderMark('applied');
|
||||
} catch (e) {
|
||||
_archivrReaderMark('failed:exception:' + (e && e.message ? e.message : String(e)));
|
||||
}
|
||||
}
|
||||
// Synchronous work — no preventDefault()/response dispatch needed.
|
||||
addEventListener('single-file-on-before-capture-request', _archivrApplyReader);
|
||||
})();
|
||||
"#
|
||||
);
|
||||
|
||||
/// Result of archiving a web page with single-file.
|
||||
#[derive(Debug)]
|
||||
|
|
@ -183,24 +219,22 @@ fn save_with(
|
|||
let strip_scripts_path = temp_dir.join("sf-strip-scripts.js");
|
||||
std::fs::write(
|
||||
&strip_scripts_path,
|
||||
"addEventListener('single-file-on-before-capture-start',()=>{\
|
||||
"addEventListener('single-file-on-before-capture-request',()=>{\
|
||||
document.querySelectorAll('script:not([type=\"application/ld+json\"])')\
|
||||
.forEach(el=>el.remove());\
|
||||
});",
|
||||
)
|
||||
.context("failed to write single-file user script")?;
|
||||
|
||||
// Optional reader-mode scripts (Readability.js + wrapper).
|
||||
// Optional reader-mode script: Readability.js + wrapper combined into one
|
||||
// file so both run in the same execution scope. (Separate --browser-script
|
||||
// files can each get their own context depending on single-file version.)
|
||||
let mut extra_browser_scripts: Vec<PathBuf> = Vec::new();
|
||||
if reader_mode {
|
||||
let readability_path = temp_dir.join("sf-readability.js");
|
||||
std::fs::write(&readability_path, READABILITY_JS)
|
||||
.context("failed to write Readability.js script")?;
|
||||
let wrapper_path = temp_dir.join("sf-reader-mode.js");
|
||||
std::fs::write(&wrapper_path, READER_MODE_WRAPPER_JS)
|
||||
.context("failed to write reader-mode wrapper script")?;
|
||||
extra_browser_scripts.push(readability_path);
|
||||
extra_browser_scripts.push(wrapper_path);
|
||||
let reader_path = temp_dir.join("sf-reader-mode.js");
|
||||
std::fs::write(&reader_path, READER_MODE_SCRIPT)
|
||||
.context("failed to write reader-mode script")?;
|
||||
extra_browser_scripts.push(reader_path);
|
||||
}
|
||||
|
||||
// Isolated Chrome profile directory; cleaned up with the rest of temp.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue