A way to run arbitrary javascript on the page being screenshot
andxyz opened this issue · 10 comments
Description
Previously in a different tool I would run it with something along the lines of
--js='window.setTimeout(function() {window.scrollTo(0,document.body.scrollHeight);}, 100);window.setTimeout(function() {window.scrollTo(0,0);}, 400)'
I know that js looks ugly. But, this way I could capture images that relied on scrolling past them to load. Lazy loading images make the page look empty when I capture with something like
hxn -b /Applications/Chromium.app/Contents/MacOS/Chromium --width 1440 --fullpage --url "$url"
Any thoughts on a workaround.
Or adding this as a feature?
My thought is that, as a workaround, I could also write an extension for chromium
that does this for me, and perhaps your program would end up autoloading my javascript extension on every webpage.
Related Documentation or Links
- The old tool I was using 10 plus years ago was called webkit2png, I believe it was written in python2 and used webkit (I am pretty sure it is unmaintained and does not work anymore without all the old dependencies)
- https://paulhammond.org/webkit2png
Hey,
Thanks for bringing this up!
Lazy loading images make the page look empty.
As a temporary solution, you can try the --delay
argument.
I'll investigate this further over the weekend. Your idea to actually run arbitrary javascript is interesting and might be a good approach. I'll keep you updated on any progress :3
I've added a way to run arbitrary js
inside the page. Can you clone from feat/js
branch and test if that suits your case?
you can add your preferred js from --javascript
option.
Okay! I can try out that branch, thank you. Please don't spend too much more time. I've also been working on an approach that uses puppeteer/puppeteer.
By the way, I tried the --delay
command. It didn't work, the images wait to lazy load until the viewport scrolls over them.
No worries! I implemented it during my break. Could you test the branch and let me know. I'll merge it into the main branch to release the new version.
I can confirm that the javascript feature is working.
POC:
Screencast.2024-06-20.12.45.41.mp4
FYI: Here's the snippet of code to test out this feature.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Change Background Color via Console</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
margin-top: 50px;
}
</style>
</head>
<body>
<h1>Change Background Color via Console</h1>
<p>Open the browser console and use the <code>changeBackgroundColor(color)</code> function to change the background color.</p>
<script>
function changeBackgroundColor(color) {
document.body.style.backgroundColor = color;
}
</script>
</body>
</html>
You can change the color using : changeBackgroundColor('color');
Thanks for confirming @subash0302 !
@pwnwriter I ended up testing this out, thanks for merging into master.
Here was what worked for me on a page with lazy loading images
hxn --url 'https://www.urbanstrategies.com/projects/' --binary '/Applications/Chromium.app/Contents/MacOS/Chromium' --delay 2 -x 1440 -y 5000 --javascript '!function(){async function e(e){return new Promise(n=>setTimeout(n,e))}function n(){(async()=>{console.log("hello from app"),scroll_max_height=Math.max(6e3,document.body.scrollHeight),scroll_jump_size=900,console.log(scroll_max_height),console.log(scroll_jump_size);for(let n=0;n<scroll_max_height;n+=scroll_jump_size)window.scrollTo(0,n),await e(600);window.scrollTo(0,0)})()}(function e(n){return n=n||0,new Promise(e=>e(chrome.runtime)).then(o=>o?Promise.resolve():n>3?Promise.reject("Failed waiting for chrome.runtime"):(n+=1,new Promise(e=>window.setTimeout(e,500)).then(()=>e(n))))})().then(n).catch(e=>{console.error(e),n()})}();'
I ended up having to:
- set a delay
- set the y height, otherwise it wouldn't capture the full height of the webpage.
- compress my javascript payload onto one line.
The final command line is a tad long, but it works! Thanks for this! ❤️
Note:
I previously tried a custom chrome extension to run my custom js but it was hard to make work from the commandline.
And my third attempt using a puppeteer script setup works, but is a bit too much to maintain for me.
In conclusion
This is a really nice solution. Thanks again for taking the time to add this feature
Glad It worked!
This is a really nice solution. Thanks again for taking the time to add this feature
Always happy to help :D
Amazing !