#!/usr/bin/perl
use warnings;
use strict;
# texml: a script to turn TeX-like \control{text} syntax into html
# input: a data file with formatting controls like \b{bold text}
# output: html-formatted data like <strong>text</strong>
# supports nested elements:
# \i{italic \b{and bold}} goes to
# <em>italic <strong>and bold</strong></em>
# deprecated HTML4 tags are macro'd to the appropriate HTML5 tags
# supports class, style, etc:
# \span class="important"{something important!} goes to
# <span class="important">somtrhing important!</span>
# supports a literal mode, useful for internal styles and scripts
# begin with {LIT} on a line by itself
# end with {UNLIT} on a line by itself
# important special characters here:
# $` (with a backtick) text before the string that matched
# $' (with a tick) text after the string that matched
# "abc123def" =~ m/123/ sets $` to "abc" and $' to "def"
# sub macro: expects a parameter like '\b class="foo"{'
# returns the appropriate HTML tag
sub macro {
shift =~ m/^\\(.*)\{$/;
my @params = split ' ', $1;
my $elem = shift @params;
if ($elem eq "b") {
$elem = "strong";
} elsif ($elem eq "i") {
$elem = "em";
} elsif ($elem eq "u") {
$elem = qq(span class="text-decoration: underline");
} elsif ($elem eq "tt") {
$elem = "code";
}
# unhandled: <s>, <strike> and <center> because i don't feel like it
unshift @params, $elem;
return (join ' ', @params);
}
my @stack = ();
my $mode = "interpolate";
while (<>) {
if ( m/^\{LIT\}$/ ) {
$mode = "literal";
next;
} elsif ( m/^\{UNLIT\}$/ ) {
$mode = "interpolate";
next;
}
if ($mode eq "literal") {
print;
next;
}
# this loop consumes most of the string
while ( m/(\\[^\{]+\{|\})/ ) {
my ($pre, $post) = ($`, $');
if ($1 eq "}") {
if (!@stack) {
warn __FILE__.": closing } without opening {\n";
} else {
print "${pre}</".(pop @stack).">";
}
} else {
my $elem = ¯o($1);
print "${pre}<$elem>";
my @attrib = split '\s+', $elem;
push @stack, $attrib[0];
}
$_ = $post;
}
print; # print remaining string
}
# if the stack contains elements, brackets have not been resolved
if (@stack) {
warn __FILE__.": unbalanced tags\n";
foreach (@stack) {
warn "\t<$_>\n";
}
}