Printing maps with LeafletJS & a potent way to html2pdf
No replies — Read more | Post response
|
by bliako
on Aug 20, 2025 at 17:47
|
|
|
Recently I needed to display a map with some polygons, markers and popups on it. I wanted to have both an interactive map but also be able to create a hardcopy from my linux's terminal via a script in a headless server.
I found a solution which satisfies both requirements. Have the interactive map be from the HTML produced by LeafletJS and then spawn a headless browser (thank you WWW::Mechanize::Chrome & Corion!!) and take a screenshot of the map, via a script from any headless server.
To me, at least, the screenshot part sounds like a very roundabout way of getting a hardcopy of a map (a PDF or PNG) but after researching this for a few weeks, I realised that this is how it is done in R (and in the serpent world, it is called htmlwebshot).
Building on WWW::Mechanize::Chrome's screenshot functionality and on a conversation I had with LanX some years ago on how to inject JS into a mechanized browser and manipulate the DOM with it I have now published WWW::Mechanize::Chrome::DOMops which finds/deletes elements of the current DOM of your mechanized browser and then on top of that, WWW::Mechanize::Chrome::Webshot which takes a screenshot of your browser contents onto a local file. In short, it renders a URL or a local file onto a, possibly headless, mechanized browser (with all encompassing CSS and JS included), allows some settle time, optionally removing some DOM elements which clutter the view and takes a screenshot of what's currently rendered. I think this is as good as it gets for html2pdf. I mean the browser is the final arbiter on how html renders right? (well, sort of).
https://leafletjs.com/ is really very good at displaying map tiles, images/satellite or vectors, from various sources (e.g. OpenStreetMap for navigation vector maps or ArcGIS/ESRI for satellite images, both free). It is also very easy to draw polygons, markers, etc. on top of the map using map coordinates. And then allows you to move/pan/zoom interactively. Really cool software. Alas in Javascript.
And so, in the below script I combine both to get both a self-contained HTML (it requires lefleat.js external dependency) of an interactive map as well as a printout in the form of PDF/PNG.
Caveat: the output PDF contains only part of the view (increasing the dpi perhaps?) whereas the PNG contains everything the browser window contains. So, a PNG is output instead.
PS: I had in mind to create a Just another Perl Hacker all over Africa but the polyline is quite some bytes long and I will spare you the bandwidth. Just imagine Just another Perl Hacker sprayed all over the globe.
PS2: Geo::Leaflet does a good job at exposing the basic functionality of LeafletJS via Perl. But there are lots more features and options for your map. I propose that once you have a basic HTML map, to template it and keep adding more features there. You do not need to keep using Geo::Leaflet. Check the script's output HTML file.
# by bliako for perlmonks 21/08/2025
use Geo::Leaflet;
use FindBin;
use File::Spec;
use WWW::Mechanize::Chrome::Webshot;
my $lat = 11.1;
my $lon = 22.2;
my $outbase = 'hack';
my $map = Geo::Leaflet->new(
id => "myMap",
center => [$lat, $lon],
zoom => 3,
);
# the tiles are coming from:
$map->tileLayer(
# navigation vector tiles
#url => 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
# satellite images
url => 'https://server.arcgisonline.com/ArcGIS/rest/services/World_
+Imagery/MapServer/tile/{z}/{y}/{x}',
options => {
maxZoom => 19,
maxNativeZoom => 23,
#attribution => 'openstreetmap',
attribution => 'esri',
},
);
$map->polyline(
coordinates => [
[9.0, 20.0],
[11.3, 23.1],
[12.1, 19.4],
], options=>{color=>'red', weight=>'5'}
);
my $map_html = $map->html;
my $outdir = $FindBin::Bin;
my $map_html_outfile = File::Spec->catfile($outdir, $outbase.'_map.htm
+l');
my $FH;
open($FH, '>', $map_html_outfile)
or die "failed to open file for writing html '$map_html_outfile',
+$!";
print $FH $map->html;
close $FH;
my $map_pdf_outfile = File::Spec->catfile($outdir, $outbase.'_map.png'
+);
my $shooter = WWW::Mechanize::Chrome::Webshot->new({
'settle-time' => 10,
'resolution' => '2000x2000',
});
my $local_uri = URI->new('file://'.$map_html_outfile);
$shooter->shoot({
'output-filename' => $map_pdf_outfile,
'url' => $local_uri->as_string,
'remove-DOM-elements' => [
{'element-xpathselector' => '//div[id="leaflet-control-container
+"]'},
],
'exif' => {'created' => 'by the shooter'},
});
print "$0 : done, map saved to PDF '$map_pdf_outfile'\n";
bw, bliako
|
Improving core performance with SIMD
3 direct replies — Read more / Contribute
|
by phizel
on Aug 13, 2025 at 08:22
|
|
|
After running across the StringZilla library, it got me thinking that Perl could greatly benefit from similar improvements. After a glance through perlfunc and Module::CoreList the following is a list I think could be targeted for optimization. Thoughts?
core modules:
non-trivial:
|
Anyone migrated to the new 'class' way of OOP?
6 direct replies — Read more / Contribute
|
by stevieb
on Aug 07, 2025 at 05:28
|
|
|
ikegami recently posted a question that eventually led me to the new perlclass documentation.
I haven't been following along that much, but it seems intriguing.
I have a ton of OOP code using the old-school bless() way of doing things, and after a cursory look at this documentation, my gut says that I shouldn't change anything. There have been so many iterations of OOP modules and such, it just seems that it'll keep changing over and over again. However, with that said, I've been around a long time, and considering almost all of my code will still run on 5.8, Perl is known for its backward-compatibility.
What are your thoughts on this new way of Perl OOP development? Are you embracing it? Are you sticking with the old? For long-time developers, are you considering transitioning?
Legitimately curious,
-stevieb
|
Yet Another Program on Closures ~ Steven Lembark ~ TPRC 2025 - YouTube
1 direct reply — Read more / Contribute
|
by LanX
on Jul 30, 2025 at 11:37
|
|
|
|
|
Perl and the Unix Philosophy (Keynote) ~ David Both ~ TPRC 2025 - YouTube
No replies — Read more | Post response
|
by LanX
on Jul 27, 2025 at 11:30
|
|
|
|
|
Success in getting a boost for building extension modules using distcc
No replies — Read more | Post response
|
by Intrepid
on Jul 07, 2025 at 12:22
|
|
|
Hello worthy Monks and Nuns. I'm writing today because on Saturday (a couple
days ago) I had a personal triumph: I got the tool
distcc working across my LAN; at
present providing support to a laptop running Linux from a desktop also running
Linux. The speed-up in intensive compilations of some Perl extension modules is noticeable,
for example, in building modules in the the Digest:: namespace, particularly
with one module (I don't recall for sure which one) which had dozens of XS files
to convert to C and compile.
I had distcc set up on my client machine (the laptop) months ago, at that time
having made the little farm of symlinks recommended as the way to drive distcc in
turn to drive gcc. What I didn't have working and couldn't get a handle on
was the setup on the host(s), where the compilation is performed; in the file
/etc/distcc/clients.allow I needed to define client hostname specifications in CIDR notation (for me, 192.168.1.0/24) for "allowed clients."
Without that set up right, I kept seeing messages from distcc saying connection
refused or variants on that.
Obviously big jobs like building the Linux kernel or Samba are where having
something like distcc is really helpful. But it's just plain cool to have it
working for Perl tasks too.
Soren
Jul 07, 2025 at 16:22 UTC
A just machine to make big decisions
Programmed by fellows (and gals) with compassion and vision
We'll be clean when their work is done
We'll be eternally free yes, and eternally young
Donald Fagen —> I.G.Y.
(Slightly modified for inclusiveness)
|
Back to programming? A gossamer hope to automate SSL cert renewals
4 direct replies — Read more / Contribute
|
by Discipulus
on Jun 25, 2025 at 05:47
|
|
|
Hello nuns and monks,
As many of you know nowadays I'm not programming for my work since years. In the not so recent past I've made some stuff for my pure pleasure or just to help a bit here.
The programming communtiy did not cried for this :)
At work I suffered a fistfull of company mergeS and now I'm relegated to boring tasks as boring can be to renew SSL certificates.
Our IT world runs as a mad without a precise destination and strange things happens, as it happened that CA/Browser Forum decided to reduce SSL certificate duration in this way:
- after March 15 2026: validity reduced to 200 days
- after March 15 2027: validity reduced to 100 days
- after March 15 2029: validity reduced to 47 days <--- O_O
But, as we say in Eataly, "not all evils come to harm" and there is a remote possibility I can convice the whole pyramid of my bosses that I can setup some Perl code at least to renew certificates and maybe somewhere install them too.
For sure bosses will complain with: "hey, we have a Dev Dpt here" ..but they act at geological times, and if they insist I can at least propose to setup a demo or better the core functionality we'd like to have distilled into a Perl module (a group of..). This point is important.
I cant let this small chance to fade out, so I must be prepared ( dormitare de fuga cogitante vetat ).
Nowadays Macaroni Group uses Digicert for almost all SSL certificates. They have some APIs for their CertCentral (the new, shiny, fancy, fashion web interface). I asked to tech support if they have also a SandBox environment (money is involved) and they didnt even know the term.. :(
So here I'm, after this long rant, to ask you how to plan my strategy in the right way.
- A base module to use automation-api let say Digicert::Automation. Maybe there is the need to have a base module for the general API: service-apis
Ideally this module should be public even if I already fear the testing part.
- A serie of other modules using the above, private to the company I work for, to manage: customers, contacts, mail, orders info e renewals etc.
- a small DB to record customers, their certificates, contact informations, internal contact.. I'd like to keep this as small as possible, ideally an SQLite one.
- a CLI tool to inspect orders, renew certificates etc.. using the above modules and DB.
- ?? a web interface? I'd skip this part, but it depends how bosses see it.
- a cron job to run daily using the above CLI to monitor orders and automatically renew expiring ones.
What I'd like from your part at the moment are: suggestion on the big picture, its design implementation, on hoW to start coding the base module, previous experience in this.. and whatever you think is important to take in count.
Hopefully this is the first of many request on the matter.
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
|
1. Go compare! Guardian's algortithm riddle and mathematical proof
3 direct replies — Read more / Contribute
|
by LanX
on Jun 07, 2025 at 19:34
|
|
|
FWIW: It's not too off topic because it's about an algorithm
The Guardian asked in a recent Monday puzzle for an optimal strategy to find the smallest and the biggest
in a deck of 100 cards.
https://www.theguardian.com/science/2025/may/12/can-you-solve-it-are-you-craftier-than-a-cat-burglar
(It's not the rope riddle)
While my strategy was optimal like the proposed solution, they claimed the formal proof that there can't be any better solution to be "too technical" to be published there.
(Pierre de Fermat giggles in his tomb).
The attempts in the comment section didn't impress me either.
Anyway I spent the last hours figuring out an elegant proof for a general formula of any numbers of cards.
But the comment section there is long closed and I thought the local crowd here would like to try their best too ...:)
So here the task again: (copied from above link)
¹) It's quite rich to ask for an optimal strategy without presenting one...
|
AI in the workplace
10 direct replies — Read more / Contribute
|
by talexb
on May 30, 2025 at 22:13
|
|
|
I sit on a Program Advisory Committee for a local college as an industry representative, and at next week's meeting we're going to be asked about 'AI in the workforce'. They'll be asking about specific areas, a) How organizations are integrating AI tools, b) Whether AI can be used as a supplement or replacement, and c) What implications AI has for productivity and skill sets.
What do you think college graduates should know about AI? How much do you think they should rely on AI tools? Is vibe coding a real thing?
Alex / talexb / Toronto
For a long time, I had a link in my .sig going to Groklaw. I heard that as of December 2024, this link is dead. Still, thanks to PJ for all your work, we owe you so much. RIP Groklaw -- 2003 to 2013.
|
Proving Veritasiums riddle using Perl
4 direct replies — Read more / Contribute
|
by cavac
on Apr 30, 2025 at 15:36
|
|
|
About two years ago, Veritasium posted The Riddle That Seems Impossible Even If You Know The Answer on Youtube. Today i was rewatching that video, because after seeing it initially i had some doubts, and it was a bit of an itch i finally decided to scratch.
The basic riddle goes something like this (watch the video for a much more coherent explanation AND the solution):
- You have 100 prisoners, each with a number.
- There is a room with 100 (numbered) boxes, and every prisoner number is in one random box.
- Prisoners enter the room one by one
- Each prisoner can open 50 boxes and search for their prisoner number.
- Each prisoner has to leave the room exactly as he found it.
- If ALL prisoners find their own number, everyone goes free.
- If even a single prisoner fails to finds his number, everyone stays in jail.
- Prisoners can decide on a tactic BEFORE the event, but can't communicate in any way DURIN the event.
If prisoners just do random sampling, their chances are 0.5**100 = 0.0000000000000000000000000000008.
Is there a better tactic? (Rest of the post in spoiler tags if you want to have a go on the problem yourself).
Frankly, even having programmed a full simulation of the solution myself, it still absolutely boggles my mind that this actually works at all. Maths is weird.
|
Do Androids Dream of Electric Sheep? Control your smartphone from the desktop
2 direct replies — Read more / Contribute
|
by bliako
on Apr 19, 2025 at 06:52
|
|
|
Brothers and sisters, fellow Monks (lend me your ears),
I have recently discovered that there is still quite a lot of hope for
using a smartphone as a tool for empowering people and not enterprises.
Android is providing a very potent program: the Android Debug Bridge (ADB)
which communicates with an Android device connected to your desktop (via USB or in same wifi network). With this program, one can tell the device to wake up, to enter the passcode of the screensaver, to navigate to the home screen, to open apps, to close apps, to swipe, to click, to input text. To get readings from sensors, to get a screenshot or a screenvideo and finally to dump the current screen's UI as XML which can then be parsed to find widgets of interest, e.g. a button to click, a textbox to enter text, a list of contacts, etc.
The two main problems with controlling your smart device in such a way are: 1) Android API differences between versions, so standard apps or widgets are named differently. 2) Android remembers to notify you about something when in the middle of controlling an app and steals the focus. But neither of these problems is
insurmountable.
The idea of controlling a device from my desktop is very appealing. In fact, I do not use a real device but an emulator (A note of warning here, better use an emulator or an unimportant phone).
At first a friend wanted to keep tapping on an app in order to gain some points for an idiotic competition. Then I wanted to send viber and skype messages from the command line of my linux terminal. And so I have set out to make a thin wrapper to the ADB for Perl. There are a lot of such wrappers for a lot of environments but I did not see one for Perl yet. So here it is : Android::ElectricSheep::Automator
use Android::ElectricSheep::Automator;
my $mother = Android::ElectricSheep::Automator->new({
'configfile' => $configfile,
'verbosity' => 1,
# we already have a device connected and ready to control
'device-is-connected' => 1,
});
$mother->tap({position=>[1,2]});
use Android::ElectricSheep::Automator::Plugins::Viber;
my $vib = Android::ElectricSheep::Automator::Plugins::Viber->new({
configfile=>'config/plugins/viber.conf', 'device-is-connected' => 1
+});
$vib->open_viber_app();
$vib->send_message({recipient=>'My Notes', message=>'hello%sMonkees
+'});
$vib->close_viber_app();
bw, bliako
|
A Perl interpreter written in Perl?
4 direct replies — Read more / Contribute
|
by harangzsolt33
on Apr 15, 2025 at 22:35
|
|
|
Has anyone ever written a pure perl interpreter written entirely in Perl?
And of course, I know, you could do read_file() into $string and then eval($string) but that's not what I mean. LOL
Has Perl ever been reproduced in Perl?
|
RFC: a meditation on Module::List and Module::List::WithPath
2 direct replies — Read more / Contribute
|
by Intrepid
on Apr 03, 2025 at 19:57
|
|
|
Hello erudite Monks and Nuns,
I found a CPAN module recently that really makes me happy. As a habitual serial installer of anything from the CPAN that looks interesting, I sometimes forget what I have installed before I can start to write some code using it. Enter Module::List; which showed up as "recent" on MetaCPAN with the release of version 0.004. There is also a close relative, let's call it a talented nephew, Module::List::WithPath, which is based on Module::List and adds the ability to discover the filesystem path location of each module found. At the time of this writing, module Module::List::WithPath is at version 0.003002.
But we're ahead of ourselves. What Module::List does is a lookup on the prefix given as an argument to the sole subroutine in the module, list_modules, returning differing information depending on the options given (as an anonymous hash) -- for example, all the installed module names with that prefix (I won't describe every bit of the functionality or API since that's all right there on MetaCPAN for the reader to peruse). I'll make the observation that the API is a bit unusual: instead of providing a separate subroutine (either exported or not) for each kind of data sought, the module provides options (as just described above). The most interesting option (imho) is the first listed in the POD, list_modules. The return data is a hash reference with keys corresponding to module names found in the abstract namespace (regardless of where the modules were found on the filesystem). The values of the hash elements are in each case the empty string. In the case of the talented nephew, Module::List::WithPath, the element values are, instead, the filesystem locations of the modules found. Very nifty.
I just find these modules really neat and they fill a gap that I've been feeling for a long time. Quirks (arguably) of implementation aside, the modules have enabled me to write simple short scripts to query my Perl installation and discover what has lain there, waiting but forgotten.
Apr 03, 2025 at 23:54 UTC
A just machine to make big decisions
Programmed by fellows (and gals) with compassion and vision
We'll be clean when their work is done
We'll be eternally free yes, and eternally young
Donald Fagen —> I.G.Y.
(Slightly modified for inclusiveness)
|
Is ChatGPT like having a thousand monkeys?
4 direct replies — Read more / Contribute
|
by talexb
on Mar 19, 2025 at 09:49
|
|
|
I have a script that builds an HTML document and sends it out as an E-Mail. The problem we were seeing was that Outlook (Microsoft's E-Mail reader application) was having problems displaying the HTML document, while the raw document looked fine when I viewed it in my browser. Within Outlook, the HTML would render fine for a while, then it would drop down into showing the raw HTML, then go back to rendering the page. It was irritating.
I was using a template to generate the HTML document, so the tags were all matched: a starting and ending table tag, within that, a bunch of paired tr tags, and within each row, paired td or th tags. I've been generating tables in HTML since the late 90's, so I'm pretty sure that's right. The only new thing I've added is using styles that are defined in the page header.
Anyway, a new employee on the client team put my vanilla HTML into ChatGPT to see if it could identify what the problem was. ChatGPT listed six problems:
- Invalid table headers - except they were all matched, and contained within a tr element;
- CSS issues - telling me that border-collapse: collapse would be better than border-collapse: separate; - irrelevant;
- Missing closing th tags - same error as #1. All tags were matched;
- Potentially Incorrect Data Formatting - suggesting that <td class='left'>0</td> would be better displayed as <td class='left'>0.00</td>, which was irrelevant;
- Incorrect HTML Tag Nesting (Semantics Issue) - this was reporting that a style was declared in the page header but never used, irrelevant; and
- Email Signature Formatting - some discussion about how the confidentiality statement was too wordy.
None of these points addressed the issue of display breakage in Outlook. The only problem I could see in the file I was generating was that there were a few blank lines in the HTML document.
Oh.
Oh no. Really?
Finally, at 8pm last night, I realized what the problem was. Blank lines. Outlook doesn't like blank lines within an HTML document. It interprets that as the end of the document, and goes back to showing raw text. Until the HTML starts up again, at which point (for some special, lucky, magic, Microsoft reasons) it goes back to showing the interpreted HTML. Oh, Microsoft.
ChatGPT didn't pick up on the blank lines, instead, it picked up on a bunch of inconsequential or irrelevant issues with the HTML.
So, I'm still a little suspicious of AI in general. It's not yet at the point where it can make creative leaps; it still wants to examine each grain of sand on the beach, rather than look at the shape of the dune. Sure, maybe ChatGPT should have been specifically prompted with 'Outlook isn't rendering this HTML document correctly, tell me why' -- but I think you can get better mileage by Telling It To The Bear, or having another pair of eyes looking at the problem.
Alex / talexb / Toronto
For a long time, I had a link in my .sig going to Groklaw. I heard that as of December 2024, this link is dead. Still, thanks to PJ for all your work, we owe you so much. RIP Groklaw -- 2003 to 2013.
|
Goodbye Zefram
2 direct replies — Read more / Contribute
|
by Anonymous Monk
on Mar 12, 2025 at 04:58
|
|
|
In perl.perl5.porters, Philippe Bruhat wrote:
I'm very sorry to be the bearer of sad news, which I just learned
from a co-worker who was in regularl contact with Zefram.
He forwarded me this:
We are sad to announce that Zefram (Andrew Main) died yesterday
(2025-03-10) after being hit by a train. Further details are not yet
available. Everyone close to him is very shocked by this and contact
details and further arrangements will be announced in future. He was a long-time and prolific contributor to Perl core and CPAN,
and he will be missed.
I will forward further details (memorial or place to send condolences)
as I receive them.
Christian Walde then followed up with:
Thanks for bearing the news BooK, even if it is sad news.
As an additional bit of info, his personal website's section on this
matter is relevant: https://www.fysh.org/~zefram/personal/death
|
|