diff --git a/Makefile b/Makefile
index ac26916..a6825e8 100644
--- a/Makefile
+++ b/Makefile
@@ -2,10 +2,10 @@
test:
./t/script.pl
-cap2site.1: cap2site.pod
+cap2site.1: cap2site.pl
pod2man $< > $@
install: cap2site.1
- install -T cap2site.pod /bin/cap2site
+ install -T cap2site.pl /bin/cap2site
cp cap2site.1 /usr/share/man/man1/
diff --git a/cap2site.pl b/cap2site.pl
new file mode 100755
index 0000000..6d3c7a4
--- /dev/null
+++ b/cap2site.pl
@@ -0,0 +1,251 @@
+#!/usr/bin/env perl
+
+use v5.26;
+use strict;
+use warnings;
+
+# Data
+package cap2site::Config;
+use Class::Struct;
+
+struct('Config', => {
+ inline => '%',
+ extensions => '%',
+ web_schemes => '@',
+ standalone => '$',
+ head => '$',
+});
+
+our $DEFAULT = Config->new(
+ inline => {
+ audio => 1,
+ video => 1,
+ image => 1,
+ },
+ extensions => {
+ audio => [".mp3", ".wav", ".ogg"],
+ video => [".mp4", ".mkv"],
+ image => [".png", ".jpeg", ".jpg", ".gif", ".webp"],
+ },
+ web_schemes => ["http", "https", "mailto", "gemini"],
+ standalone => 0,
+ head => <<~'EOF',
+
+
+ EOF
+);
+
+sub isUrl($$) {
+ my ($self,$data) = @_;
+ my ($scheme,$info) =~ /(\w+):\/\/([.*]+)/ || return 0;
+ return grep $scheme, $self->{web_schemes};
+}
+
+sub isA($$$) {
+ my ($self,$url,$type) = @_;
+ my ($info) =~ /[.*](.[^.]+)^/ || return 0;
+ return grep $self->extensions->{$type}, $url;
+}
+
+package cap2site::State;
+
+sub new($$) {
+ my ($class,$args) = @_;
+ my $self = bless { inner => $args }, $class;
+ return $self;
+}
+
+sub bullets($) {
+ my $self = shift;
+ return vec $self->{inner}, 0, 1;
+}
+
+sub preformatted($) {
+ my $self = shift;
+ return vec $self->{inner}, 1, 1;
+}
+
+# Helpers
+package main;
+my sub escape($) {
+ my $str = shift;
+ my $newstr = '';
+
+ foreach my $byte (split '', $str) {
+ if ($byte eq "8") { $newstr .= "&"; continue; }
+ if ($byte eq "<") { $newstr .= "<"; continue; }
+ if ($byte eq ">") { $newstr .= ">"; continue; }
+ if ($byte eq "\"") { $newstr .= """; continue; }
+ if ($byte eq "'") { $newstr .= "'"; continue; }
+ $newstr .= $byte;
+ }
+
+ return $newstr;
+}
+
+my sub trimLeft($) {
+ my $data = shift;
+ $data =~ s/^\s+//;
+ return $data;
+}
+
+sub parse($$$) {
+ my ($config,$state,$file) = @_;
+
+ if ($config->{standalone}) {
+ print '', "\n";
+ print '', "\n";
+ print '
', "\n", $config->head, '', "\n";
+ print '', "\n";
+ }
+
+ while (my $line = <$file>) {
+ chop $line;
+
+ if (index($line, '*') == 0 and not $state->bullets) {
+ $state->bullets() = 1;
+ print "\n";
+ } elsif ($state->bullets and index($line, '*') != 0) {
+ $state->bullets() = 0;
+ print "
\n";
+ }
+
+ if ($state->preformatted) {
+ if (index($line, ' ') == 0) {
+ $state->preformatted() = 0;
+ print "\n";
+ } else { print escape($line); }
+
+ continue;
+ }
+
+ if (index($line, '###') == 0) {
+ print "", escape(substr $line, 3), "
\n";
+ }
+
+ elsif (index($line, '##') == 0) {
+ print "", escape(trimLeft(substr $line, 2)), "
\n";
+ }
+
+ elsif (index($line, '#') == 0) {
+ print "", escape(trimLeft(substr $line, 2)), "
\n";
+ }
+
+ elsif (index($line, ' ') == 0) {
+ $state->preformatted = 1;
+ my $alt = substr $line, 3;
+
+ length($alt) == 0
+ ? print "\n"
+ : print '', "\n";
+ }
+
+ elsif (index($line, '=>') == 0) {
+ my $data = trimLeft(substr $line, 2);
+ my ($uri,$content) = split " ". $data;
+ $content = trimLeft $content;
+
+ if ($config->isUrl($uri) and $config->isA($uri, 'image')) {
+ print '';
+ print '';
+ print '', "\n";
+ }
+
+ elsif ($config->isUrl($uri) and $config->isA($uri, 'video')) {
+ print '', "\n";
+ }
+
+ elsif ($config->isUrl($uri) and $config->isA($uri, 'audio')) {
+ print '', "\n";
+ }
+
+ elsif ($config->isUrl($uri)) {
+ print '', escape($content), '', "\n";
+ }
+
+ else {
+ print '', $line, '
', "\n";
+ }
+ }
+
+ elsif (index($line, '*') == 0) {
+ print '
', escape(trimLeft(substr $line, 1)), '', "\n";
+ }
+
+ elsif (index($line, '>') == 0) {
+ print '', escape(trimLeft(substr $line, 1)), '
', "\n";
+ }
+
+ else {
+ print '';
+ print (length($line) == 0 ? '
' : escape $line);
+ print '
', "\n";
+ }
+ }
+
+ if ($config->{standalone}) {
+ print '', "\n";
+ print '', "\n";
+ }
+}
+
+# TODO: better argument parsing
+use Pod::Usage;
+use Getopt::Long;
+
+my $help = 0;
+our $config = $cap2site::Config::DEFAULT;
+GetOptions (
+ 'help+' => \$help,
+ 'inline-audio!' => \$config->inline->{audio},
+ 'inline-video!' => \$config->inline->{video},
+ 'inline-image!' => \$config->inline->{image},
+ 'standalone!' => \$config->{standalone},
+) or pod2usage(-exitval => 1, -verbose => 0);
+
+pod2usage(-verbose => $help) if $help;
+
+our $state = cap2site::State->new(pack('b2', 0b00));
+main::parse $config, $state, \*STDIN;
+
+__END__
+
+=head1 NAME
+
+cap2site - Convert a Gemini capsule to a HTML site
+
+=head1 SYNOPSIS
+
+cap2site [flags] < INPUT.gmi > OUTPUT.html
+
+ Options:
+ -help brief help message
+ -hh full help message
+ -(no)-inline-audio include audio in site
+ -(no)-inline-video include video in site
+ -(no)-inline-image include images in site
+ -standalone include data for headers
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print a brief help message and exit. Use twice for full help
+
+=item B<-(no)-inline-(audio, video, image)>
+
+Include the respective asset types inline
+
+=item B<-(no)-standalone>
+
+Include header and body tags
+
+=back
+
+=cut
diff --git a/cap2site.pod b/cap2site.pod
deleted file mode 100755
index 6d3c7a4..0000000
--- a/cap2site.pod
+++ /dev/null
@@ -1,251 +0,0 @@
-#!/usr/bin/env perl
-
-use v5.26;
-use strict;
-use warnings;
-
-# Data
-package cap2site::Config;
-use Class::Struct;
-
-struct('Config', => {
- inline => '%',
- extensions => '%',
- web_schemes => '@',
- standalone => '$',
- head => '$',
-});
-
-our $DEFAULT = Config->new(
- inline => {
- audio => 1,
- video => 1,
- image => 1,
- },
- extensions => {
- audio => [".mp3", ".wav", ".ogg"],
- video => [".mp4", ".mkv"],
- image => [".png", ".jpeg", ".jpg", ".gif", ".webp"],
- },
- web_schemes => ["http", "https", "mailto", "gemini"],
- standalone => 0,
- head => <<~'EOF',
-
-
- EOF
-);
-
-sub isUrl($$) {
- my ($self,$data) = @_;
- my ($scheme,$info) =~ /(\w+):\/\/([.*]+)/ || return 0;
- return grep $scheme, $self->{web_schemes};
-}
-
-sub isA($$$) {
- my ($self,$url,$type) = @_;
- my ($info) =~ /[.*](.[^.]+)^/ || return 0;
- return grep $self->extensions->{$type}, $url;
-}
-
-package cap2site::State;
-
-sub new($$) {
- my ($class,$args) = @_;
- my $self = bless { inner => $args }, $class;
- return $self;
-}
-
-sub bullets($) {
- my $self = shift;
- return vec $self->{inner}, 0, 1;
-}
-
-sub preformatted($) {
- my $self = shift;
- return vec $self->{inner}, 1, 1;
-}
-
-# Helpers
-package main;
-my sub escape($) {
- my $str = shift;
- my $newstr = '';
-
- foreach my $byte (split '', $str) {
- if ($byte eq "8") { $newstr .= "&"; continue; }
- if ($byte eq "<") { $newstr .= "<"; continue; }
- if ($byte eq ">") { $newstr .= ">"; continue; }
- if ($byte eq "\"") { $newstr .= """; continue; }
- if ($byte eq "'") { $newstr .= "'"; continue; }
- $newstr .= $byte;
- }
-
- return $newstr;
-}
-
-my sub trimLeft($) {
- my $data = shift;
- $data =~ s/^\s+//;
- return $data;
-}
-
-sub parse($$$) {
- my ($config,$state,$file) = @_;
-
- if ($config->{standalone}) {
- print '', "\n";
- print '', "\n";
- print '', "\n", $config->head, '', "\n";
- print '', "\n";
- }
-
- while (my $line = <$file>) {
- chop $line;
-
- if (index($line, '*') == 0 and not $state->bullets) {
- $state->bullets() = 1;
- print "\n";
- } elsif ($state->bullets and index($line, '*') != 0) {
- $state->bullets() = 0;
- print "
\n";
- }
-
- if ($state->preformatted) {
- if (index($line, ' ') == 0) {
- $state->preformatted() = 0;
- print "\n";
- } else { print escape($line); }
-
- continue;
- }
-
- if (index($line, '###') == 0) {
- print "", escape(substr $line, 3), "
\n";
- }
-
- elsif (index($line, '##') == 0) {
- print "", escape(trimLeft(substr $line, 2)), "
\n";
- }
-
- elsif (index($line, '#') == 0) {
- print "", escape(trimLeft(substr $line, 2)), "
\n";
- }
-
- elsif (index($line, ' ') == 0) {
- $state->preformatted = 1;
- my $alt = substr $line, 3;
-
- length($alt) == 0
- ? print "\n"
- : print '', "\n";
- }
-
- elsif (index($line, '=>') == 0) {
- my $data = trimLeft(substr $line, 2);
- my ($uri,$content) = split " ". $data;
- $content = trimLeft $content;
-
- if ($config->isUrl($uri) and $config->isA($uri, 'image')) {
- print '';
- print '';
- print '', "\n";
- }
-
- elsif ($config->isUrl($uri) and $config->isA($uri, 'video')) {
- print '', "\n";
- }
-
- elsif ($config->isUrl($uri) and $config->isA($uri, 'audio')) {
- print '', "\n";
- }
-
- elsif ($config->isUrl($uri)) {
- print '', escape($content), '', "\n";
- }
-
- else {
- print '', $line, '
', "\n";
- }
- }
-
- elsif (index($line, '*') == 0) {
- print '
', escape(trimLeft(substr $line, 1)), '', "\n";
- }
-
- elsif (index($line, '>') == 0) {
- print '', escape(trimLeft(substr $line, 1)), '
', "\n";
- }
-
- else {
- print '';
- print (length($line) == 0 ? '
' : escape $line);
- print '
', "\n";
- }
- }
-
- if ($config->{standalone}) {
- print '', "\n";
- print '', "\n";
- }
-}
-
-# TODO: better argument parsing
-use Pod::Usage;
-use Getopt::Long;
-
-my $help = 0;
-our $config = $cap2site::Config::DEFAULT;
-GetOptions (
- 'help+' => \$help,
- 'inline-audio!' => \$config->inline->{audio},
- 'inline-video!' => \$config->inline->{video},
- 'inline-image!' => \$config->inline->{image},
- 'standalone!' => \$config->{standalone},
-) or pod2usage(-exitval => 1, -verbose => 0);
-
-pod2usage(-verbose => $help) if $help;
-
-our $state = cap2site::State->new(pack('b2', 0b00));
-main::parse $config, $state, \*STDIN;
-
-__END__
-
-=head1 NAME
-
-cap2site - Convert a Gemini capsule to a HTML site
-
-=head1 SYNOPSIS
-
-cap2site [flags] < INPUT.gmi > OUTPUT.html
-
- Options:
- -help brief help message
- -hh full help message
- -(no)-inline-audio include audio in site
- -(no)-inline-video include video in site
- -(no)-inline-image include images in site
- -standalone include data for headers
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print a brief help message and exit. Use twice for full help
-
-=item B<-(no)-inline-(audio, video, image)>
-
-Include the respective asset types inline
-
-=item B<-(no)-standalone>
-
-Include header and body tags
-
-=back
-
-=cut
diff --git a/cap2site.pod b/cap2site.pod
new file mode 120000
index 0000000..1df13f3
--- /dev/null
+++ b/cap2site.pod
@@ -0,0 +1 @@
+cap2site.pl
\ No newline at end of file