There are many ways to embed Perl in HTML. One of my
favorites that gets something in a browser rapidly is
the module Markup::Perl. Once imported with "use"
the script behaves like an HTML document with an
excellent new <perl> tag that enables perl embeds!
It automatically imports param, cookie and header
functions from the CGI distribution to handle input,
memory, and output tasks. It can also recursively
include files with more <perl> tags.
Markup::Perl has been around since 2006
with only 1 revision. The module code is miniscule and
powerful. The documentation is brief yet complete. Super
Search can't find any mention of it in The Monastery so
it must be time for a review! 12 years after release this
remains a mature and stable distribution.
This 240 line demo requires the
CPAN modules
Markup::Perl and
HTML::Entities.
Edit: Changed URL from http:// to file:// in POD USAGE CLI.
#!/usr/bin/perl #!__________________________________________.###@
#! ##
#! Markup::Perl -> Review/Demo by usemodperl 07/01/2018 #
#! |
#! "For some problems, particularly in the presentation layer, |
#! thinking of the solution as a webpage that can run perl is |
#! more natural than thinking of it as a perl script that can |
#! print a webpage." <- All quotes from Markup::Perl pod. .#
#!____________________________________________________________.##
#! #
use strict; # Avoid dreaded traps. |
use warnings; # Bug removal machine. |
use ExtUtils::Installed; # CORE |
use Pod::Simple::HTML; # CORE |
use HTML::Entities; # CPAN .#
#!____________________________________________________________.##
#! #
#! "It's a perl script when it starts. But as soon as the |
#! following line is encountered the rules all change": |
#! .#
#! use Markup::Perl; # CPAN .##
#!__________________________________________________________.###@
=head1 NAME
Markup::Perl -> Review/Demo by usemodperl
=head1 DESCRIPTION
Markup::Perl promises to "turn your CGI inside-out"
and the results are web programming paradise.
This demo is a basic CGI shell. When not supplied with
parameters it reads and prints its own pod as HTML and
displays its source code in a textarea. It also prints
the pod from Markup::Perl and displays its source in a
textarea.
Markup::Perl is extremely useful for rapid prototyping
and creating single user CGI utilities. It parses and
evals <perl> tags embedded in HTML in scripts that use
the module, and recursively from external files.
=head1 USAGE
Run this demo as CGI to render HTML; or command line
for raw output.
=over
=item CGI
HTML form, and query string: ?cmd=pwd
=item CLI
perl this.pl cmd=pwd
perl this.pl > that.html; open file:///path/to/that.html
=back
=head1 POWERS
Recursive includes!
Handle params and cookies!
fatalsToBrowser built-in!
=head1 QUIRKS
For more about running code with eval see:
perldoc -f eval.
Recursive self-referential includes will result in
busy zombies so try not to do anything like:
<perl>src($0)</perl>
Includes should not include themselves (or files
that include them). Watch out for unclosed loops
and <perl> tags. It's only an issue during
development.
=head1 TEMPLATE
#!/usr/bin/perl
use strict;
use warnings;
use Markup::Perl;
<!DOCTYPE html><html lang=en><head>
<title></title></head><body>
<perl>
print "Perl $^V"
</perl>
</body>
</html>
=head1 CONCLUSION
=over
=item Markup::Perl is powerful, productive and fun!
L<https://metacpan.org/pod/Markup::Perl>
=back
=head1 AUTHOR
=over
=item usemodperl
L<https://perlmonks.org/?node_id=1216830>
=back
=cut
# HERE COMES EVERYONE (PERL/HTML/CSS/JS):
use Markup::Perl;
<!DOCTYPE html>
<html lang=en>
<perl>
# DEFINE PERL VARIABLES
my $cmd = param('cmd') || '';
my $cfg = param('cfg') || '';
my $form = HTML::Entities::encode_entities($cmd) || '';
my $CPAN = 'https://metacpan.org/pod/Markup::Perl';
my $time = time;
</perl>
<!-- GENERATE DOCUMENT TITLE -->
<head><title><perl>
print $form ? "Perl $^V" : 'Markup::Perl CGI Demo';
</perl></title></head>
<body onload=document.getElementById("cmd").focus()>
<a name=top></a>
<div class=d>
<!-- COMMAND INPUT FORM -->
<span class=y><FORM><input type=text name=cmd
value="<perl> print $form </perl>" id=cmd size=32
class=darkform title="enter shell command"> <a
title=Reset class=c href=?cmd=>🐪</a></FORM></span>
<br clear=all>
<perl>
# RUN SHELL COMMAND
if ($cmd) {
# TAINT A THING
$_ = `$cmd`;
print '<br><ul><pre>',
HTML::Entities::encode_entities($_), '</pre></ul>'
}
# GENERATE DEFAULT DISPLAY
else {
# FIND MODULE FILE
$_ = ExtUtils::Installed->new;
@_ = $_->files("Markup::Perl");
@_ = grep/\.pm$/, @_;
# READ MODULE AND SELF
my $module = do{local(@ARGV,$/)=$_[0];<>};
my $self = do{local(@ARGV,$/)=$0;<>};
# SELF POD TO HTML
my $spod = Pod::Simple::HTML->new;
$spod->output_string(\my $shtml);
$spod->parse_string_document($self);
$shtml =~ s\^.*?(<h1>.*?)</body></html>\$1\s;
# INSERT DEMO LINK INTO PERLDOC
$shtml =~ s\(perldoc....eval)\<a
href="$ENV{REQUEST_SCHEME}://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}?cmd=pe
+rldoc+-f+eval">
$1</a>\sx;
# NOT USUALLY POSSIBLE! :-)
$shtml =~ s\(basic.....shell)\<a
href="$ENV{REQUEST_SCHEME}://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}?cmd=ls
++-l">
$1</a>\sx;
# PRINT SELF POD
print $shtml, '<h1>SOURCE</h1>',
"<h4><a href='file://$0'>$0</a></h4>",
# PRINT SELF SOURCE
'<FORM><textarea cols=80 rows=20 class=darkform>',
HTML::Entities::encode_entities($self),
'</textarea></FORM><br><br><hr>';
# MODULE POD TO HTML
my $mpod = Pod::Simple::HTML->new;
$mpod->output_string(\my $mhtml);
$mpod->parse_string_document($module);
$mhtml =~ s\^.*?(<h1>.*?)</body></html>\$1\s;
# REMOVE POD FROM SOURCE
$module =~ s\__END__.*$\\s;
# PRINT MODULE POD
print $mhtml, '<h1>SOURCE</h1>',
"<h4><a href='file://$_[0]'>$_[0]</a></h4><FORM>",
# PRINT MODULE SOURCE
'<FORM><textarea cols=80 rows=20 class=darkform>',
HTML::Entities::encode_entities($module),
'</textarea></FORM>',
# PRINT PERL INFO
'<h1>perl -v</h1><div class=s><pre>', `perl -v`, '</pre></div>';
}
# ADD HTTP HEADER
header('X-Powered-By' => 'Perl');
# KISS PERL GOODBYE, FOR NOW
</perl>
<!-- DARK THEME -->
<style>
textarea { width:100%; }
.darkform { background-color:#666666; color:#FFFFFF; }
html, body { max-width:100%; overflow-x:hidden; }
body { background-color:black; color:#cccccc; margin:0 auto; }
a { text-decoration:none; }
a:link{ color: #CFF } a:visited { color: #FFC } #dark theme :-)
.tt { font-family:monospace; }
.c { font-size:48px; }
.s { font-size:small; }
.y { float:right; margin:0px; padding:0px; }
.d { width:95%; margin:0 auto; }
</style>
<!-- FOOTER -->
<h1 align=center><a href=#top>⇪</a><br><br><h4 align=center><b>
STOP REINVENTING WHEELS, START BUILDING SPACE ROCKETS!
</b>—<a href="https://www.cpan.org/">CPAN</a> 🐪</h4
+>
</body>
</html>
<perl>
#!_Markup::Perl -> Review/Demo________________________.usemodperl
#! #
#! "It's a perl script when it starts. But as soon as the |
#! following line is encountered the rules all change": .#
#!___________________________________________________________.###
#! .#
#! use Markup::Perl: https://metacpan.org/pod/Markup::Perl .##
#!__________________________________________________________.###@
</perl>
STOP REINVENTING WHEELS, START BUILDING SPACE ROCKETS!—CPAN 🐪