#!/usr/bin/perl

use strict;
use warnings;
use feature ':5.10';
use utf8;
use LTXSVG;
use IO::Handle;
use Getopt::Long qw/:config no_ignore_case bundling/;
use Exception::Base;
#no warnings 'experimental::smartmatch';

my (%options, $outputName, $preambleName, $inplace);
GetOptions(
	'o|output-file=s'=>\$outputName,
	'p|preamble-file=s'=>\$preambleName,
	's|scale=f'=>\$options{scale},
	'tex=s'=>\$options{tex},
	'dvisvgm=s'=>\$options{dvisvgm},
	'C|clear-cache!'=>\$options{clearCache},
	'i|inplace=s'=>\$options{inplace},
	);

my $inputName=shift;
undef $outputName if defined $outputName and $outputName eq '-';

if(defined $preambleName)
{
	open my $preambleFile, '<', $preambleName
		or die "Can not open preamble file “$preambleName”: $!";
	my $preamble;
	$preamble.=$_ while <$preambleFile>;
	$options{preamble}=$preamble;
}

my $ltxsvg=LTXSVG->new(%options);
$ltxsvg->processFile($inputName, $outputName);

__END__

=pod

=encoding UTF-8

=head1 NAME

ltxsvg - converts LaTeX formulae embedded within XML file to SVG format

=head1 SYNOPSIS

ltxsvg I<input_file> [ I<option>... ]

=head1 DESCRIPTION

The command-line utility B<ltxsvg> is intended to be used as preprocessor
converting TeX formulae embedded within XML file to SVG format. The program
uses an approach similar to one that applied in MetaPost.

The program looks for any occurrence of B<E<lt>mathE<gt>> or
B<E<lt>displayE<gt>> elements bound to the custom namespace
B<"https://github.com/urbic/ltxsvg"> in the given XML document. The text
content of these elements prepended with LaTeX preamble is passed to L<tex(1)>.
Then the DVI output from L<tex(1)> is passed to L<dvisvgm(1)>.  The SVG output
of L<dvisvgm(1)> replaces the original B<E<lt>mathE<gt>> or
B<E<lt>displayE<gt>> element. The program performs some mangling on the B<id>
attributes in SVG elements to prevent their collisions.

B<ltxsvg> takes a special care when the parent element of B<E<lt>mathE<gt>> or
B<E<lt>displayE<gt>> element belongs to XHTML or SVG namespace. See L</"XHTML
Input"> and L</"SVG Input"> sections for details.

The preprocessed XHTML or SVG documents can be browsed in any SVG-capable
browser without use of tools such as L<MathJax|http://mathjax.org>.

B<ltxsvg> is a front-end for L<LTXSVG(3pm)>.

=head2 XHTML Input

When the parent of B<E<lt>mathE<gt>> or B<E<lt>displayE<gt>> element belongs to
XHTML namespace, B<ltxsvg> performs additional manipulations on the SVG
representation of the formula. The B<E<lt>svgE<gt>> element is wrapped into
XHTML B<E<lt>divE<gt>> element, whose attributes serve to align rendered
formula on the baseline of the surrounding text. The B<width> and the B<heigth>
attributes of the SVG element are expressed in relative units, so the size of
the rendered formula is properly adjusted to the size of the surrounding text.

The B<E<lt>divE<gt>> wrapper is provided with B<class> attributes, either
B<"ltxsvg-math"> or B<"ltxsvg-display">, depending on whether the formula is
contained in B<E<lt>mathE<gt>> or B<E<lt>displayE<gt>> element. The B<class>
attribute can serve to styling or scripting purposes.

=head2 SVG Input

When the B<E<lt>mathE<gt>> or B<E<lt>displayE<gt>> element is the child of SVG
element, B<ltxsvg> takes into account the attributes specified in
B<E<lt>mathE<gt>> or B<E<lt>displayE<gt>>:

=over

=item B<x>, B<y>

The coordinates of the formula reference point.

=item B<placement>

This attribute specifies the reference point position in the rendered formula.
Valid values are:

=over

=item B<"right">

in the middle of the left edge.

=item B<"topRight">

in the lower left corner.

=item B<"top">

in the middle of the upper edge.

=item B<"topLeft">

in the lower right corner.

=item B<"left">

in the middle of the right edge.

=item B<"bottomLeft">

in the upper right corner.

=item B<"bottom">

in the middle of the upper edge.

=item B<"bottomRight">

in the upper left corner.

=back

=item B<gap>

The additional gap between the formula and the reference point. The default
value is B<"3">.

=back

=head2 Optimization

The text characters in the resulting SVG are rendered using SVG
B<E<lt>pathE<gt>> elements. Since the same characters are usually found many
times within the document, their repeated occurrences are replaced by
B<E<lt>useE<gt>> elements linked to corresponding B<E<lt>pathE<gt>> elements.
This approach can significally reduce the size of the resulting file and
accelerate its rendering in a browser.

=head1 OPTIONS

=over

=item I<input_file>

The name of the input file to be converted.

=item B<-o>, B<--output-file> I<output_file>

The name of the output file. With no I<output_file> or when I<output_file> is
B<-> the result is redirected to the standard output.

=item B<-p>, B<--preamble-file> I<preamble_file>

The name of the file containing the LaTeX preamble. When not given, the
following preamble is assumed:

	%&latex
	\documentclass{article}
	\usepackage[utf8]{inputenc}
	\usepackage{stix}
	\usepackage{amsmath}
	\begin{document}

=item B<-s>, B<--scale> I<factor>

Scale all the SVG formulae by the given I<factor>.

=item B<--tex> I<command>

The TeX command, default value is B<"pdftex">.

=item B<--dvisvgm> I<command>

The dvisvgm command, default value is B<"dvisvgm">.

=item B<-C>, B<--clear-cache>

Clear cached formulae forcing TeX and dvisvgm to re-run.

=item B<-i>, B<--inplace> I<suffix>

Perform the conversion in-place, retaining a backup copy whose name is
constructed as original input file name with the I<suffix> appended to it. This
option has no effect when B<-o> option was specified.

=back

=head1 EXAMPLES

=head2 Example XHTML input

	<?xml version="1.0" encoding="UTF-8"?>
	<html
		xmlns="http://www.w3.org/1999/xhtml"
		xmlns:tex="https://github.com/urbic/ltxsvg"
		>
		<body>
			<p>
			If <tex:math>a</tex:math> and <tex:math>b</tex:math> are legs,
			<tex:math>c</tex:math> hypotenuse, then
			<tex:display>c^2=a^2+b^2.</tex:display>
			</p>
		</body>
	</html>

=head2 Example SVG input

	<?xml version="1.0" encoding="UTF-8"?>
	<svg
		xmlns="http://www.w3.org/2000/svg"
		xmlns:tex="https://github.com/urbic/ltxsvg"
		version="1.1"
		viewBox="-20 -20 120 100"
		width="240"
		height="200"
		>
		<path d="M 0 0 v 60 h 80 z" fill="none" stroke="black" stroke-width="1"/>
		<tex:math x="0" y="0" placement="top">A</tex:math>
		<tex:math x="80" y="60" placement="bottomRight">B</tex:math>
		<tex:math x="0" y="60" placement="bottom">C</tex:math>
	</svg>

=head2 Generic XML input

	<?xml version="1.0" encoding="UTF-8"?>
	<display xmlns="https://github.com/urbic/ltxsvg">
	\oint\limits_{\partial\sigma}\omega=\int\limits_\sigma d\omega
	</display>

=head1 LIMITATIONS

B<ltxsvg> supports only those TeX engines which work in DVI mode and produce
DVI format 2 output.

B<ltxsvg> fails with B<dviluatex> engine when B<fontspec.sty> or
B<unicode-math.sty> module is in use. This is due to limitations in L<dvisvgm>.

=head1 FILES

=over

=item B<~/.cache/ltxsvg>

The cache directory.

=back

=head1 SEE ALSO

L<tex(1)>, L<dvisvgm(1)>, L<LTXSVG(3pm)>.

Project site: L<https://github.com/urbic/ltxsvg>.

=head1 LICENSE

L<zlib/png|http://opensource.org/licenses/Zlib>.

=head1 AUTHOR

Anton Shvetz, L<mailto:tz@sectorb.msk.ru?subject=ltxsvg>.

=cut
