diff -Nru elyxer-1.2.3/.gitignore elyxer-1.2.5/.gitignore --- elyxer-1.2.3/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/.gitignore 2013-03-10 11:31:59.000000000 +0000 @@ -0,0 +1,35 @@ +# git-ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +*\# +*~ +*.pyc +*.swp +*-test.html +*-test-*.html +po/locale/* +test/*.py +build/* +dist/* +samples/* +patch/* +elyxer.py +loremipsumize.py +math2html.py +setup.py +docs/*.html +docs/*.css +docs/cvs/ +docs/MathJax/ +docs/jsMath/ +config.py +elyxer.pot +test/copyimages/*.svg +test/copyimages/*.png +test/copyimages/*.jpg +test/copyimages/docs +test/subdir/mourning.png +forks + diff -Nru elyxer-1.2.3/README elyxer-1.2.5/README --- elyxer-1.2.3/README 2011-06-24 21:55:09.000000000 +0000 +++ elyxer-1.2.5/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,119 +0,0 @@ -eLyXer -- convert LyX source files to HTML output. - -Introduction -============ -eLyXer converts a LyX source file to a HTML page. Full documentation in HTML -format can be found at docs/index.html, or on the web: - http://www.nongnu.org/elyxer/ - -Installation -============ -Quick installation guide (for the impatient): -* download the latest version from http://www.nongnu.org/elyxer/, -* decompress the .zip or .tar.gz -* and install it using the provided script install.py as root: - # ./install.py - or on Windows: - > python install.py - -To install eLyXer first download a compressed version from - http://www.nongnu.org/elyxer/ -You will also need a recent (> 2.4) version of Python on your target machine. - -For decompression: open a terminal window in the directory that contains the -downloaded file and just write at the command line prompt: - $ tar -xzf elyxer-[version].tar.gz -Or for the .zip version: - $ unzip elyxer-[version].zip -where [version] should be something like 0.44; the full name might be something -like elyxer-0.44.tar.gz. - -On Windows or Mac OS X you can unzip the file using the graphical tool of your -choice. In any case, a directory called elyxer-[version] should appear, where -the installer script install.py can be found (along with this README). - -The recommended installation procedure is to just run this script. On Linux -type as root: - # ./install.py -and similarly for Mac OS X, while for Windows open a console and type: - > python install.py -Note the you don't need to write the prompt, # or >; the console will print it -for you. Double-clicking on install.py should also work if your Python -installation is minimally sane. It will tell you as a result to which directory -eLyXer has been installed as a binary, which is be the typical result; in this -case eLyXer should be run as follows: - $ elyxer.py [input file] [output file] -or, on Windows: - > elyxer.py [input file] [output file] -You can test that it works with the --help option: - $ elyxer.py --help -or, on Windows: - > elyxer.py --help -Usage and options should then be shown. - -LyX Integration -=============== - -To integrate eLyXer with LyX you just have to reconfigure LyX, selecting -Tools -> Reconfigure from within LyX. For rather old versions of LyX (< 1.6.2) -you may have to copy elyxer.py into the LyX directory, and reconfigure it. -Later versions will recognize eLyXer automatically, either if you install it -using distutils or as a binary. - -Usage -===== -eLyXer can be invoked from the command line as: - $ elyxer.py [source file] [destination file] - -If the source file is omitted then STDIN is used; likewise, if no destination -file is specified eLyXer will output to STDOUT. This allows its use in pipes -and other flexible configurations. - -Examples: - $ elyxer.py file.lyx file.html -converts file.lyx to file.html. Debug messages are shown. - $ cat file.lyx | elyxer.py > file.html -converts file.lyx to file.html, as before. This time debug messages are not -shown. - $ elyxer.py file.lyx | grep "
" | wc -counts all blockquote paragraphs. - $ elyxer.py file.lyx | wget --no-check-certificate --spider -nv -F -i - -checks all external links in a document recursively. (Local links will appear -as unresolved, but they can be ignored.) - -Documentation -============= -Documentation about eLyXer, including a user guide and a developer guide, can -be found in the docs directory. The project is hosted at Savannah.nongnu.org. -Be sure to visit the project home page at: - http://www.nongnu.org/elyxer/ - -License -======= -eLyXer is Copyright (C) 2009-2011 Alex Fernández. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - - -math2html (a subset of eLyXer) Copyright (C) 2009-2011 Alex Fernández - -Released under the terms of the `2-Clause BSD license'_, in short: -Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. -This file is offered as-is, without any warranty. -.. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause - -Enjoy! - diff -Nru elyxer-1.2.3/README.md elyxer-1.2.5/README.md --- elyxer-1.2.3/README.md 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/README.md 2013-01-11 22:11:36.000000000 +0000 @@ -0,0 +1,119 @@ +eLyXer -- convert LyX source files to HTML output. + +Introduction +============ +eLyXer converts a LyX source file to a HTML page. Full documentation in HTML +format can be found at docs/index.html, or on the web: + http://www.nongnu.org/elyxer/ + +Installation +============ +Quick installation guide (for the impatient): +* download the latest version from http://www.nongnu.org/elyxer/, +* decompress the .zip or .tar.gz +* and install it using the provided script install.py as root: + # ./install.py + or on Windows: + > python install.py + +To install eLyXer first download a compressed version from + http://www.nongnu.org/elyxer/ +You will also need a recent (> 2.4) version of Python on your target machine. + +For decompression: open a terminal window in the directory that contains the +downloaded file and just write at the command line prompt: + $ tar -xzf elyxer-[version].tar.gz +Or for the .zip version: + $ unzip elyxer-[version].zip +where [version] should be something like 0.44; the full name might be something +like elyxer-0.44.tar.gz. + +On Windows or Mac OS X you can unzip the file using the graphical tool of your +choice. In any case, a directory called elyxer-[version] should appear, where +the installer script install.py can be found (along with this README). + +The recommended installation procedure is to just run this script. On Linux +type as root: + # ./install.py +and similarly for Mac OS X, while for Windows open a console and type: + > python install.py +Note the you don't need to write the prompt, # or >; the console will print it +for you. Double-clicking on install.py should also work if your Python +installation is minimally sane. It will tell you as a result to which directory +eLyXer has been installed as a binary, which is be the typical result; in this +case eLyXer should be run as follows: + $ elyxer.py [input file] [output file] +or, on Windows: + > elyxer.py [input file] [output file] +You can test that it works with the --help option: + $ elyxer.py --help +or, on Windows: + > elyxer.py --help +Usage and options should then be shown. + +LyX Integration +=============== + +To integrate eLyXer with LyX you just have to reconfigure LyX, selecting +Tools -> Reconfigure from within LyX. For rather old versions of LyX (< 1.6.2) +you may have to copy elyxer.py into the LyX directory, and reconfigure it. +Later versions will recognize eLyXer automatically, either if you install it +using distutils or as a binary. + +Usage +===== +eLyXer can be invoked from the command line as: + $ elyxer.py [source file] [destination file] + +If the source file is omitted then STDIN is used; likewise, if no destination +file is specified eLyXer will output to STDOUT. This allows its use in pipes +and other flexible configurations. + +Examples: + $ elyxer.py file.lyx file.html +converts file.lyx to file.html. Debug messages are shown. + $ cat file.lyx | elyxer.py > file.html +converts file.lyx to file.html, as before. This time debug messages are not +shown. + $ elyxer.py file.lyx | grep "
" | wc +counts all blockquote paragraphs. + $ elyxer.py file.lyx | wget --no-check-certificate --spider -nv -F -i - +checks all external links in a document recursively. (Local links will appear +as unresolved, but they can be ignored.) + +Documentation +============= +Documentation about eLyXer, including a user guide and a developer guide, can +be found in the docs directory. The project is hosted at Savannah.nongnu.org. +Be sure to visit the project home page at: + http://www.nongnu.org/elyxer/ + +License +======= +eLyXer is Copyright (C) 2009-2011 Alex Fernández. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +math2html (a subset of eLyXer) Copyright (C) 2009-2011 Alex Fernández + +Released under the terms of the `2-Clause BSD license'_, in short: +Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. +This file is offered as-is, without any warranty. +.. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause + +Enjoy! + diff -Nru elyxer-1.2.3/create-version elyxer-1.2.5/create-version --- elyxer-1.2.3/create-version 2011-01-31 21:41:09.000000000 +0000 +++ elyxer-1.2.5/create-version 2013-03-10 11:24:04.000000000 +0000 @@ -58,12 +58,12 @@ zip -qr elyxer-$VERSION.zip elyxer-$VERSION/* # Sign packages -gpg -b elyxer-$VERSION.tar.gz -gpg -b elyxer-$VERSION.zip +# gpg -b elyxer-$VERSION.tar.gz +# gpg -b elyxer-$VERSION.zip # Upload to savannah -scp elyxer-$VERSION.tar.gz elyxer-$VERSION.tar.gz.sig alexfernandez@dl.sv.nongnu.org:/releases/elyxer/ -scp elyxer-$VERSION.zip elyxer-$VERSION.zip.sig alexfernandez@dl.sv.nongnu.org:/releases/elyxer/ +# scp elyxer-$VERSION.tar.gz elyxer-$VERSION.tar.gz.sig alexfernandez@dl.sv.nongnu.org:/releases/elyxer/ +# scp elyxer-$VERSION.zip elyxer-$VERSION.zip.sig alexfernandez@dl.sv.nongnu.org:/releases/elyxer/ # Upload docs cd ../docs diff -Nru elyxer-1.2.3/debian/changelog elyxer-1.2.5/debian/changelog --- elyxer-1.2.3/debian/changelog 2013-03-16 21:24:36.000000000 +0000 +++ elyxer-1.2.5/debian/changelog 2013-03-16 21:15:02.000000000 +0000 @@ -1,108 +1,16 @@ -elyxer (1.2.3-1) unstable; urgency=low - - * New upstream release. - + The --title option now works with non-ascii characters. - (Closes: #639712) - * Update the elyxer.1 manpage. - + Remove the long text from --imageformat. - + Mark --jsmath and --nocopy as deprecated. - + Document the new --mathjax remote option. - - -- Sven Hoexter Wed, 31 Aug 2011 20:32:28 +0200 - -elyxer (1.2.2-1) unstable; urgency=low - - * New upstream release - + Supports LyX 2.0.0 format. - * According to dev-ref 6.2.2 the short description is no sentence so - we should start in lowercase letters. - * Update Vcs-* to the new anonscm.d.o structure. - * Update Standards-Version to 3.9.2, no changes required. - - -- Sven Hoexter Sun, 12 Jun 2011 08:59:10 +0200 - -elyxer (1.2.1-1) unstable; urgency=low - - * New upstream release - * Remove override_dh_clean. - * Increase compat level to 8. - * Use dh_python2 to generate the python dependency. - * Update the elyxer manapge: - + Add --tocfor and --googlecharts. - + Deprecate --toc and --toctarget. - - -- Sven Hoexter Mon, 07 Mar 2011 13:35:05 +0100 - -elyxer (1.2.0-1) unstable; urgency=low - - * New upstream release - + This release no longer provides the elyxer Python module. - * Temporarily override_dh_clean to exclude a leftover tempfile - in /tests/ from the cleanup to keep the diff clean. - * Work around the current install facility and don't run dh_auto_install - at all. - * Remove the dh_auto_clean override. - * Increment all years in debian/copyright. - * Replace the use of python-support with a simple dependency on python. - * Note in debian/copyright that the code in math2html.py is additionally - licensed under the Apache License 2.0. - * Update the elyxer.1 manpage, add --simplemath. - - -- Sven Hoexter Mon, 31 Jan 2011 15:27:18 +0100 - -elyxer (1.1.2-1) experimental; urgency=low - - * New upstream release - + The --forceformat option got deprecated by --imageformat. - * Improve the manpage for the --forceformat and --noconvert option. - * Update the manpage for all new options: --embedcss, --imageformat, - several --*foot and --notoclabels. - - -- Sven Hoexter Thu, 23 Dec 2010 10:06:03 +0100 - -elyxer (1.0.4-1) experimental; urgency=low +elyxer (1.2.5-1~raring~ppa1) raring; urgency=low * New upstream release - + Mainly bugfixes for part numbering and BibTeX. - - -- Sven Hoexter Tue, 02 Nov 2010 07:36:43 +0100 - -elyxer (1.0.3-1) experimental; urgency=low - - * New upstream release - + Added support for \stackrel. - + Added a lot of escaped characters to the BibTeX parsing. - + A lot of other improvements, see the upstream changelog. - - -- Sven Hoexter Fri, 15 Oct 2010 10:27:33 +0200 - -elyxer (1.0.2-1) experimental; urgency=low - - * New upstream relese - + Added --noconvert option to use images in the original format. - + BibTeX improvements. - + Show footnotes as hovering text. - * Remove override_dh_clean target from debian/rules. - * Re-organize the manpage into sections as used in the --help output - and document the missing --noconvert and --toctarget options. + * Switch to format 3.0 (quilt) - -- Sven Hoexter Mon, 20 Sep 2010 08:53:25 +0200 + -- Liviu Andronic Sat, 16 Mar 2013 18:02:22 +0200 -elyxer (1.0.1-1) experimental; urgency=low +elyxer (1.2.3-1~lucid~ppa1) lucid; urgency=low + * Initial import from Natty * New upstream release - + More robust BibTeX parsing, parse comma separated entries correctly. - + Improved support for horizontal and vertical spacing. - + Support for sizes in tables columns, figures and boxes. - + Basic support for LyX change tracking. - + Solved bug in text handling which separated consecutive centered - lines with a space. - * Update to Standards-Version: 3.9.1 - no changes required. - * Do nothing for dh_auto_clean and add an override_dh_clean: target - to debian/rules to preserve a leftover docs/#changelog.lyx# file - so that it won't clutter the diff. - -- Sven Hoexter Thu, 02 Sep 2010 11:25:38 +0200 + -- Liviu Andronic Fri, 17 Feb 2012 18:02:22 +0200 elyxer (1.0.0-1) unstable; urgency=low diff -Nru elyxer-1.2.3/debian/compat elyxer-1.2.5/debian/compat --- elyxer-1.2.3/debian/compat 2013-03-16 21:24:36.000000000 +0000 +++ elyxer-1.2.5/debian/compat 2013-03-16 20:46:57.000000000 +0000 @@ -1 +1 @@ -8 +7 diff -Nru elyxer-1.2.3/debian/control elyxer-1.2.5/debian/control --- elyxer-1.2.3/debian/control 2013-03-16 21:24:36.000000000 +0000 +++ elyxer-1.2.5/debian/control 2013-03-16 20:46:57.000000000 +0000 @@ -1,18 +1,19 @@ Source: elyxer -Maintainer: Debian LyX Maintainers +Maintainer: Liviu Andronic Uploaders: Sven Hoexter Priority: optional Section: text -Standards-Version: 3.9.2 -Build-Depends-Indep: debhelper (>= 8), python (>= 2.6.6-3) -Vcs-Git: git://anonscm.debian.org/pkg-lyx/elyxer.git -Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-lyx/elyxer.git +Standards-Version: 3.9.0 +Build-Depends-Indep: debhelper (>= 7.0.50~), python-support +Vcs-Git: git://git.debian.org/git/pkg-lyx/elyxer.git +Vcs-Browser: http://git.debian.org/?p=pkg-lyx/elyxer.git Homepage: http://www.nongnu.org/elyxer/ +XS-Python-Version: >= 2.5 Package: elyxer Architecture: all Depends: ${misc:Depends}, ${python:Depends} -Description: standalone LyX to HTML converter +Description: Standalone LyX to HTML converter eLyXer (pronounced elixir) is a standalone LyX to HTML converter written in Python. eLyXer has a focus on flexibility and elegant output. It's not yet possible to convert every LyX document but a lot of document diff -Nru elyxer-1.2.3/debian/copyright elyxer-1.2.5/debian/copyright --- elyxer-1.2.3/debian/copyright 2013-03-16 21:24:36.000000000 +0000 +++ elyxer-1.2.5/debian/copyright 2013-03-16 20:46:57.000000000 +0000 @@ -15,11 +15,11 @@ Copyright: The manpages, included in the /debian/ directory, are -Copyright (C) 2009-2011 Sven Hoexter and Alex Fernández +Copyright (C) 2009-2010 Sven Hoexter and Alex Fernández Everything else is -Copyright (C) 2009-2011 Alex Fernández +Copyright (C) 2009-2010 Alex Fernández This program is free software: you can redistribute it and/or modify @@ -38,9 +38,3 @@ On any Debian system, you can find the complete text of the GNU GPL (GNU General Public License) in the file /usr/share/common-licenses/GPL-3 - -The code contained in math2html.py is additionally licensed under the terms -of the Apache License version 2.0. - -On any Debian system, you can find the complete text of the Apache License -version 2.0 in the file /usr/share/common-licenses/Apache-2.0 diff -Nru elyxer-1.2.3/debian/elyxer.1 elyxer-1.2.5/debian/elyxer.1 --- elyxer-1.2.3/debian/elyxer.1 2013-03-16 21:24:36.000000000 +0000 +++ elyxer-1.2.5/debian/elyxer.1 2013-03-16 20:46:57.000000000 +0000 @@ -1,4 +1,4 @@ -.TH eLyXer "1" "August 2011" +.TH eLyXer "1" "June 2010" .SH NAME elyxer - convert LyX files to html .SH SYNOPSIS @@ -14,45 +14,30 @@ .SH COMMON OPTIONS .sp 1 .TP 0.5i -.BR \-\-help -Display help. - -.TP 0.5i .BR \-\-quiet -Disable all runtime messages. - +Disables all runtime messages. -.SH ADVANCED OPTIONS -.sp 1 .TP 0.5i .BR \-\-debug Enable debugging messages (for developers). .TP 0.5i -.BR \-\-version -Show version number and release date. +.BR \-\-title " title" +Set the generated page title. .TP 0.5i -.BR \-\-lyxformat -Return the highest supported LyX version that can be converted. - +.BR \-\-directory " image_dir" +Look for images in the specified directory. -.SH HTML OUTPUT OPTIONS -.sp 1 .TP 0.5i -.BR \-\-title " title" -Set the generated page title. +.BR \-\-destdirectorty " dest_dir" +Place converted images into this directory. .TP 0.5i .BR \-\-css " file.css" Use a custom CSS file. .TP 0.5i -.BR \-\-embedcss " file.css" -Embed the CSS file into the HTML output instead of including -a separate file. - -.TP 0.5i .BR \-\-html Output HTML 4.0 instead of the default XHTML. @@ -66,94 +51,29 @@ instead of UTF-8. .TP 0.5i -.BR \-\-nofooter -Don't include the 'created by eLyXer' footer. - -.TP 0.5i -.BR \-\-simplemath -Do not generate fancy math constructions. +.BR \-\-splitpart " level" +Split the resulting webpage at the given level. -.SH IMAGE OUTPUT OPTIONS +.SH ESOTERIC OPTIONS .sp 1 .TP 0.5i -.BR \-\-directory " image_dir" -Look for images in the specified directory. - -.TP 0.5i -.BR \-\-destdirectorty " dest_dir" -Place converted images into this directory. - -.TP 0.5i -.BR \-\-forceformat " .extension (deprecated)" -Starting with eLyXer 1.1.1 this option has been replaced by the -\fB\-\-imageformat\fR option. - -.TP 0.5i -.BR \-\-imageformat " .extension | copy" -Force the image output format, default is PNG. - -This option is helpful in cases were you'd like to override the automatic -conversion to the PNG image format. If you'd like to preserve all images -in the original format use the \fBcopy\fR command. - -.TP 0.5i -.BR \-\-converter " inkscape" -Use Inkscape as the image converter. - -.TP 0.5i -.BR \-\-noconvert -Do not convert images, just use them in the current available -format they're stored in. - -Be aware that you've to copy your image files to the output directory if -you create the html output outside of the source directory. - -.SH FOODNOTE OPTIONS -.TP 0.5i -.BR \-\-numberfoot -Label footnotes with numbers instead of letters. - -.TP 0.5i -.BR \-\-symbolfoot -Label footnotes with symbols instead of letters, e.g. *, **. - -.TP 0.5i -.BR \-\-hoverfoot -Show footnotes as hovering text (default). - -.TP 0.5i -.BR \-\-marginfoot -Show footnotes on the page margin. - -.TP 0.5i -.BR \-\-endfoot -Show footnotes at the end of the page. - -.TP 0.5i -.BR \-\-supfoot -Use superscript for footnote markers (default). - -.TP 0.5i -.BR \-\-alignfoot -Use aligned text for footnote markers. +.BR \-\-version +Show version number and release date. .TP 0.5i -.BR \-\-footnotes " number,symbol,hover,margin,end,sup,align" -You can specify one or more of the above footnote options as -a comma speparated list. +.BR \-\-nofooter +Don't include the 'created by eLyXer' footer. -.SH ADVANCED OUTPUT OPTIONS -.sp 1 .TP 0.5i -.BR \-\-splitpart " level" -Split the resulting webpage at the given level. +.BR \-\-forceformat " .extension" +Force image output format. .TP 0.5i -.BR \-\-tocfor " page" -Generate a TOC that points to the given page. +.BR \-\-lyxformat +Return the highest supported LyX version that can be converted. .TP 0.5i -.BR \-\-toc " (deprecated)" +.BR \-\-toc Create a table of contents. .TP 0.5i @@ -161,37 +81,30 @@ Let all links point to the given frame. .TP 0.5i -.BR \-\-toctarget " page (deprecated)" -Generate a TOC that points to the given page. - -.TP 0.5i -.BR \-\-notoclabels -Omit the part lables like 'Chapter' in the TOC. - -.TP 0.5i .BR \-\-lowmem Force on the fly conversion to conserve memory. .br This is the old behaviour of eLyXer prior to 0.36. .TP 0.5i +.BR \-\-converter " inkscape" +Use Inkscape as the image converter. + +.TP 0.5i +.BR \-\-numberfoot +Label footnotes with numbers instead of letters. + +.TP 0.5i .BR \-\-raw Generate HTML without header or footer. .TP 0.5i -.BR \-\-jsmath " URL (deprecated)" +.BR \-\-jsmath " URL" Use jsMath fomr the given URL to display equations. .TP 0.5i -.BR \-\-mathjax " URL | remote" +.BR \-\-mathjax " URL" Use MathJax from the given URL to display equations. -If you use \fB\-\-mathjax\fR with the keyword \fBremote\fR -instead of an URL you can use the MathJax CDN instead of a -local copy. - -.TP 0.5i -.BR \-\-googlecharts -Use Google Charts to generate formular images. .TP 0.5i .BR \-\-template " file" @@ -202,7 +115,7 @@ Add a copyright notice at the bottom. .TP 0.5i -.BR \-\-nocopy " (deprecated)" +.BR \-\-nocopy (deprecated) Disables the copyright notice at the bottom. With eLyXer 0.99 the default changed to not include a copyright notice. See also \-\-copyright if you @@ -214,9 +127,9 @@ eLyXer was written by Alex Fernández . .SH COPYRIGHT -eLyXer is copyright \(co 2009-11 Alex Fernández. +eLyXer is copyright \(co 2009-10 Alex Fernández. .br -This manpage is copyright \(co 2009-11 Sven Hoexter and Alex Fernández. +This manpage is copyright \(co 2009-10 Sven Hoexter and Alex Fernández. .br License GPLv3+: GNU GPL version 3 or later . .br diff -Nru elyxer-1.2.3/debian/rules elyxer-1.2.5/debian/rules --- elyxer-1.2.3/debian/rules 2013-03-16 21:24:36.000000000 +0000 +++ elyxer-1.2.5/debian/rules 2013-03-16 20:46:57.000000000 +0000 @@ -1,12 +1,16 @@ #!/usr/bin/make -f %: - dh $@ --with python2 + dh $@ override_dh_auto_install: + dh_auto_install install --mode=755 elyxer.py debian/elyxer/usr/bin/elyxer install --mode=755 loremipsumize.py debian/elyxer/usr/bin/loremipsumize cp -r po/locale debian/elyxer/usr/share/ override_dh_installchangelogs: dh_installchangelogs docs/changelog.html + +override_dh_auto_clean: + dh_clean -d diff -Nru elyxer-1.2.3/debian/source/format elyxer-1.2.5/debian/source/format --- elyxer-1.2.3/debian/source/format 2013-03-16 21:24:36.000000000 +0000 +++ elyxer-1.2.5/debian/source/format 2013-03-16 21:24:36.756467820 +0000 @@ -1 +1 @@ -1.0 +3.0 (quilt) diff -Nru elyxer-1.2.3/docs/changelog.html elyxer-1.2.5/docs/changelog.html --- elyxer-1.2.3/docs/changelog.html 2011-08-31 00:35:31.000000000 +0000 +++ elyxer-1.2.5/docs/changelog.html 2013-03-10 21:25:51.000000000 +0000 @@ -4,7 +4,7 @@ - + eLyXer changelog @@ -19,6 +19,48 @@
  • +1.2.5 (2013-01-11):
      +
    • +Solved a bug in the previous release: José Ramón’s fix was not properly applied in the executable elyxer.py. Sorry about that. +
    • + +
    + +
  • +
  • +1.2.4 (2013-01-10):
      +
    • +Implemented generic converters, and lyx -C as an image converter (thanks, Tommaso!). +
    • +
    • +Implemented command \today: Mar 10, 2013. +
    • +
    • +Added a Russian translation (thanks, Vladimir!). +
    • +
    • +Solved a bug when parsing a BibTeX entry with a trailing comma (thanks, Bob!). +
    • +
    • +BibTeX: correctly use booktitle instead of journal in an @inproceedings entry (thanks, Pascal!). +
    • +
    • +Expose language information as additional markup (using the lang attribute in HTML). +
    • +
    • +Fix by Guenter Milde for math2html under Python 3.0. +
    • +
    • +Convert em-dash only when surrounded by spaces (thanks, Robert). +
    • +
    • +Fix by José Ramón Álvarez Sánchez of problem in simultaneous use of hover and end options for footnotes (thanks, Tim!). +
    • + +
    + +
  • +
  • 1.2.3 (2011-08-31):
    • Changed the license for math2html from Apache v2 to FreeBSD 2-clause license, to better suit integration with DocUtils. @@ -1763,7 +1805,7 @@ diff -Nru elyxer-1.2.3/docs/changelog.lyx elyxer-1.2.5/docs/changelog.lyx --- elyxer-1.2.3/docs/changelog.lyx 2011-08-31 00:35:27.000000000 +0000 +++ elyxer-1.2.5/docs/changelog.lyx 2013-03-10 21:25:51.000000000 +0000 @@ -1,5 +1,5 @@ -#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ -\lyxformat 345 +#LyX 2.0 created this file. For more info see http://www.lyx.org/ +\lyxformat 413 \begin_document \begin_header \textclass article @@ -29,18 +29,26 @@ \usepackage{upgreek} \end_preamble \use_default_options false +\maintain_unincluded_children false \language english +\language_package default \inputencoding auto +\fontencoding global \font_roman default \font_sans default \font_typewriter default \font_default_family default +\use_non_tex_fonts false \font_sc false \font_osf false \font_sf_scale 100 \font_tt_scale 100 \graphics default +\default_output_format default +\output_sync 0 +\bibtex_command default +\index_command default \paperfontsize default \spacing single \use_hyperref false @@ -48,21 +56,31 @@ \use_geometry false \use_amsmath 1 \use_esint 1 +\use_mhchem 1 +\use_mathdots 1 \cite_engine basic \use_bibtopic false +\use_indices false \paperorientation portrait +\suppress_date false +\use_refstyle 0 +\index Index +\shortcut idx +\color #008000 +\end_index \secnumdepth 3 \tocdepth 3 \paragraph_separation indent -\defskip medskip +\paragraph_indentation default \quotes_language english \papercolumns 1 \papersides 1 \paperpagestyle default \tracking_changes false \output_changes false -\author "" -\author "" +\html_math_output 0 +\html_css_as_file 0 +\html_be_strict false \end_header \begin_body @@ -92,6 +110,108 @@ \end_layout \begin_layout Itemize +1.2.5 (2013-01-11): +\end_layout + +\begin_deeper +\begin_layout Itemize +Solved a bug in the previous release: José Ramón's fix was not properly + applied in the executable +\family typewriter +elyxer.py +\family default +. + Sorry about that. +\end_layout + +\end_deeper +\begin_layout Itemize +1.2.4 (2013-01-10): +\end_layout + +\begin_deeper +\begin_layout Itemize +Implemented generic converters, and +\family typewriter +lyx -C +\family default + as an image converter (thanks, Tommaso!). +\end_layout + +\begin_layout Itemize +Implemented command +\family typewriter + +\backslash +today +\family default +: +\begin_inset ERT +status open + +\begin_layout Plain Layout + + +\backslash +today +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Itemize +Added a Russian translation (thanks, Vladimir!). +\end_layout + +\begin_layout Itemize +Solved a bug when parsing a BibTeX entry with a trailing comma (thanks, + Bob!). +\end_layout + +\begin_layout Itemize +BibTeX: correctly use booktitle instead of journal in an +\family typewriter +@inproceedings +\family default + entry (thanks, Pascal!). +\end_layout + +\begin_layout Itemize +Expose language information as additional markup (using the +\family typewriter +lang +\family default + attribute in HTML). +\end_layout + +\begin_layout Itemize +Fix by Guenter Milde for +\family typewriter +math2html +\family default + under Python 3.0. +\end_layout + +\begin_layout Itemize +Convert em-dash only when surrounded by spaces (thanks, Robert). +\end_layout + +\begin_layout Itemize +Fix by José Ramón Álvarez Sánchez of problem in simultaneous use of +\family typewriter +hover +\family default + and +\family typewriter +end +\family default + options for footnotes (thanks, Tim!). +\end_layout + +\end_deeper +\begin_layout Itemize 1.2.3 (2011-08-31): \end_layout diff -Nru elyxer-1.2.3/docs/devguide.html elyxer-1.2.5/docs/devguide.html --- elyxer-1.2.3/docs/devguide.html 2011-08-31 00:08:58.000000000 +0000 +++ elyxer-1.2.5/docs/devguide.html 2013-03-10 21:23:57.000000000 +0000 @@ -4,7 +4,7 @@ - + eLyxer Developer Guide @@ -867,7 +867,7 @@ diff -Nru elyxer-1.2.3/docs/index.html elyxer-1.2.5/docs/index.html --- elyxer-1.2.3/docs/index.html 2011-08-31 00:09:28.000000000 +0000 +++ elyxer-1.2.5/docs/index.html 2013-03-10 21:24:01.000000000 +0000 @@ -4,7 +4,7 @@ - + eLyXer @@ -78,7 +78,7 @@ Downloads
      -You can download the latest version 1.2.3, created on 2011-08-31, from the project’s download area. See the change log for information about past versions. +You can download the latest version 1.2.5, created on 2013-03-10, from the project’s download area. See the change log for information about past versions.
      eLyXer (including this page and all accompanying materials) is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See the LICENSE file for details. @@ -102,10 +102,10 @@ This little project is my little contribution back to the wonderful LyX community, for all these years of fruitful use.
      -Thanks to Stevan White for encouraging me to publish the tool. Thanks also to John D. Cook, rikal, Bradley M. Bell, Markus Kuhn, Jens Nöckel, Günter Milde and LyX developers Georg Baum, Uwe Stöhr and Jürgen Spitzmüller for their wonderful lists of TeX commands and Unicode equivalents; to FileFormat.info for their complete tables of Unicode characters. More thanks go to Christian Ridderström for helping me out right at the start; to Ignacio García for relentless encouragement; to Abdelrazak Younes, Pavel Sanda, Günter Milde, Olivier Ripoll, José Matos, Iain Mac Donald, Uwe Stöhr for their interesting suggestions. Thanks to Uwe Stöhr, Hans Bezemer, Sara Teinturier for their translations. Packagers Sven Hoexter (for Debian) and Uwe Stöhr (on Windows) have helped with their work to make it easy to try it out. Olivier Ripoll, Geremy Condra, Simon South, Jack Desert, John Boik, Yan Wong, Jose Ramón Álvarez Sánchez, Günter Milde, Pascal Francq, Marco R. Gazzetta have provided quite interesting patches. Davide P. Cervone has been extremely helpful and responsive about jsMath and MathJax integration, while Paul Hunter has also gone beyond the call of duty with his help integrating MathToWeb (which unfortunately has not been fruitful yet, due to my lack of skill and certainly not to his lack of interest). +Thanks to Stevan White for encouraging me to publish the tool. Thanks also to John D. Cook, rikal, Bradley M. Bell, Markus Kuhn, Jens Nöckel, Günter Milde and LyX developers Georg Baum, Uwe Stöhr and Jürgen Spitzmüller for their wonderful lists of TeX commands and Unicode equivalents; to FileFormat.info for their complete tables of Unicode characters. More thanks go to Christian Ridderström for helping me out right at the start; to Ignacio García for relentless encouragement; to Abdelrazak Younes, Pavel Sanda, Günter Milde, Olivier Ripoll, José Matos, Iain Mac Donald, Uwe Stöhr for their interesting suggestions. Thanks to Uwe Stöhr, Hans Bezemer, Sara Teinturier, Vladimir Ermakov for their translations. Packagers Sven Hoexter (for Debian) and Uwe Stöhr (on Windows) have helped with their work to make it easy to try it out. Olivier Ripoll, Geremy Condra, Simon South, Jack Desert, John Boik, Yan Wong, Jose Ramón Álvarez Sánchez, Günter Milde, Pascal Francq, Marco R. Gazzetta have provided quite interesting patches. Davide P. Cervone has been extremely helpful and responsive about jsMath and MathJax integration, while Paul Hunter has also gone beyond the call of duty with his help integrating MathToWeb (which unfortunately has not been fruitful yet, due to my lack of skill and certainly not to his lack of interest).
      -Thanks to Nikos Alexandris, Joachim Kreimer-de Fries (Osnabryg), Richard Talley, Wolfgang Keller, Murray Eisenberg, Robert Orr, a Linux guy in Singapore, Anders Ekberg, Pavel Sanda, Steve Hastings, Sven Hoexter, Xie Chao, Uwe Stöhr, Jürgen Spitzmüller, Olivier Ripoll, Konrad Hofbauer, Eduardo Grosclaude, Ken, Jens Nöckel, Dr Eberhard W Lisse, William Crocker, Sara Teinturier, Hans Bezemer, Jack Desert, Hartmut Haase, Rainer Dorsch, Wolfgang Engelmann, Rodrigo Benenson, Stefano Franchi, Steve Litt, Paul Johnson, Yan Wong, Yaron Goland, Francis Girard, Rene de Zwart, Jose Ramón Álvarez Sánchez, Günter Milde, Axel Jacobs, Tiago Pedro Alves-Ferreira, Hoy Loper, Bob Alvarez for their testing and bug reporting. +Thanks to Nikos Alexandris, Joachim Kreimer-de Fries (Osnabryg), Richard Talley, Wolfgang Keller, Murray Eisenberg, Robert Orr, a Linux guy in Singapore, Anders Ekberg, Pavel Sanda, Steve Hastings, Sven Hoexter, Xie Chao, Uwe Stöhr, Jürgen Spitzmüller, Olivier Ripoll, Konrad Hofbauer, Eduardo Grosclaude, Ken, Jens Nöckel, Dr Eberhard W Lisse, William Crocker, Sara Teinturier, Hans Bezemer, Jack Desert, Hartmut Haase, Rainer Dorsch, Wolfgang Engelmann, Rodrigo Benenson, Stefano Franchi, Steve Litt, Paul Johnson, Yan Wong, Yaron Goland, Francis Girard, Rene de Zwart, Jose Ramón Álvarez Sánchez, Günter Milde, Axel Jacobs, Tiago Pedro Alves-Ferreira, Hoy Loper, Bob Alvarez, Tommaso Cucinotta for their testing and bug reporting.
      A silent “thank you” goes to all those who downloaded the tool and silently tested it to their satisfaction (or were not bugged enough to write about it). Thanks to those who have criticized the tool for making eLyXer improve every day, if only to prove you wrong. And finally thanks to all those who have helped and yet I am now forgetting about them, for not hating me for it. @@ -113,7 +113,7 @@
      diff -Nru elyxer-1.2.3/docs/index.lyx elyxer-1.2.5/docs/index.lyx --- elyxer-1.2.3/docs/index.lyx 2011-07-08 21:50:10.000000000 +0000 +++ elyxer-1.2.5/docs/index.lyx 2013-01-11 22:11:36.000000000 +0000 @@ -478,7 +478,8 @@ start; to Ignacio García for relentless encouragement; to Abdelrazak Younes, Pavel Sanda, Günter Milde, Olivier Ripoll, José Matos, Iain Mac Donald, Uwe Stöhr for their interesting suggestions. - Thanks to Uwe Stöhr, Hans Bezemer, Sara Teinturier for their translations. + Thanks to Uwe Stöhr, Hans Bezemer, Sara Teinturier, Vladimir Ermakov for + their translations. Packagers Sven Hoexter (for Debian) and Uwe Stöhr (on Windows) have helped with their work to make it easy to try it out. Olivier Ripoll, Geremy Condra, Simon South, Jack Desert, @@ -525,7 +526,8 @@ Rainer Dorsch, Wolfgang Engelmann, Rodrigo Benenson, Stefano Franchi, Steve Litt, Paul Johnson, Yan Wong, Yaron Goland, Francis Girard, Rene de Zwart, Jose Ramón Álvarez Sánchez, Günter Milde, Axel Jacobs, Tiago Pedro Alves-Ferrei -ra, Hoy Loper, Bob Alvarez for their testing and bug reporting. +ra, Hoy Loper, Bob Alvarez, Tommaso Cucinotta for their testing and bug + reporting. \end_layout \begin_layout Standard diff -Nru elyxer-1.2.3/docs/math-googlecharts.html elyxer-1.2.5/docs/math-googlecharts.html --- elyxer-1.2.3/docs/math-googlecharts.html 2011-08-31 00:09:27.000000000 +0000 +++ elyxer-1.2.5/docs/math-googlecharts.html 2013-03-10 21:24:00.000000000 +0000 @@ -4,7 +4,7 @@ - + eLyxer Math Showcase (Google Charts edition) @@ -400,7 +400,7 @@ diff -Nru elyxer-1.2.3/docs/math-html.html elyxer-1.2.5/docs/math-html.html --- elyxer-1.2.3/docs/math-html.html 2011-08-31 00:09:22.000000000 +0000 +++ elyxer-1.2.5/docs/math-html.html 2013-03-10 21:24:00.000000000 +0000 @@ -3,7 +3,7 @@ - + eLyxer Math Showcase (HTML edition) @@ -705,7 +705,7 @@ diff -Nru elyxer-1.2.3/docs/math-iso885915.html elyxer-1.2.5/docs/math-iso885915.html --- elyxer-1.2.3/docs/math-iso885915.html 2011-08-31 00:09:19.000000000 +0000 +++ elyxer-1.2.5/docs/math-iso885915.html 2013-03-10 21:23:59.000000000 +0000 @@ -4,7 +4,7 @@ - + eLyxer Math Showcase (ISO-8859-15 edition) @@ -706,7 +706,7 @@ diff -Nru elyxer-1.2.3/docs/math-jsmath.html elyxer-1.2.5/docs/math-jsmath.html --- elyxer-1.2.3/docs/math-jsmath.html 2011-07-08 23:31:55.000000000 +0000 +++ elyxer-1.2.5/docs/math-jsmath.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,369 +0,0 @@ - - - - - - - - -eLyxer Math Showcase (jsMath edition) - - - - -
      - -

      -figure elyxer.png -eLyXer Math Showcase -

      -

      -Alex Fernández (elyxer@gmail.com) -

      - -

      -1 Introduction -

      -
      -This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. -
      -

      -1.1 Versions -

      -
      -There are several versions of this page: -
      - -
      -All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. -
      -
      -Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. -
      -

      -2 Typography -

      -
      -Math formulae use a lot of different symbols and fonts. -
      -

      -2.1 Greek Symbols -

      -
      -Greek symbols are very important in equations: \phi, \pi, \Xi. eLyXer offers a complete set in both upper case: \Gamma\ldots\Omega and lower case: \alpha\ldots\omega. Also the AMS italicized upper case: \varGamma\ldots\varOmega. -
      -

      -2.2 Math Symbols -

      -
      -eLyXer supports the whole set of math symbols in John D. Cook's list: \exists\partial\nabla\geq. It can also render a few more: \propto\times. You also get all symbols from Markus Kuhn's list: \bigodot\amalg. -
      -

      -2.3 Other Symbols -

      -
      -There are other symbols like arrows: \leftarrow\rightarrow, or geometrical shapes: \circ, \square. eLyXer offers limited support for them. You might also want to use financial symbols in formulae: \yen\euro\$. -
      -

      -2.4 Spacing -

      -
      -Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: x=3. -Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: \frac{4}{18}\mathrm{em} for medium mathematical spaces versus \frac{1}{2}\mathrm{en}, where 1\mathrm{em}=2\mathrm{en}. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. - - -
      -
      -The command \raisebox is useful to, surprisingly, raise a little box,
      -\raisebox{2mm}{raised}over\raisebox{-2mm}{lowered}\textrm{and back}.
      Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      - \raisebox{5mm}{}B^{V}. -
      -
      -There are other spacing commands: \hspace: a\hspace{4mm}b, protected space: a\ b, and (at “block level”) \vspace: a\vspace{1cm}b. -
      -
      -There should be 1 cm of vertical space above this paragraph. -
      -

      -2.5 Fonts -

      -
      -By default, letters denote variables and are taken from the \mathnormal font, which is italic, \alpha x+\alpha y=\alpha(x+y), with the exception of upright capital Greek letters, G\ne\Gamma. -
      -
      -Function names should be upright: \sin(2\pi),\log(x),\tan\delta. -
      -
      -Mathematical fonts used in equations include \mathrm{Roman} (\mathrm), \mathsf{Sans\: Serif} (\mathsf), \mathtt{Typewriter} (\mathtt), \mathbf{Bold} (\mathbf), \mathscr{SCRIPT} (\mathscr), \mathcal{CALLIGRAPHIC} (\mathcal), \mathbb{BLACKBOARD\: BOLD} (\mathbb), and \mathfrak{Fraktur} (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: \mathscr{F}, \mathbb{F}, \mathfrak{F}. -
      -
      -Regular text in a formula can be achieved via text font commands like \textrm: 5\:\textrm{to}\:10, via boxes like \mbox (prevents line breaks): 6\mbox{ is more than }5, or the AMSmath \text macro (scales like math symbols) \text{base}_{\text{sub}}^{\text{super}}. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: \mbox{\textbf{\textsf{\textbf{\textit{sfbfit}}}}, \textipa{tipa}}. -
      -
      -Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, \unit{km}, with magnitude, \unit[57]{km}, with fractional unit, \unitfrac[200]{km}{h}, or with a fraction before the units, \unit[\nicefrac{3}{2}]{km}, \unit[\frac{7}{16}]{s}. -
      -

      -3 Numeration -

      -
      -Equations can be numbered, like ()
      \begin{equation} -y=x\label{eq:first}\end{equation}
      And also like (↓).
      \begin{equation} -x=3\label{eq:second}\end{equation}
      Some equations can be numbered even if they don’t have a label. -
      -
      -
      \begin{equation} -x=2y\end{equation}
      Notice that equation () comes after (). -
      -

      -4 Simple Structures -

      -
      -Let’s now see a few of the simpler structures that eLyXer can output. -
      -

      -4.1 Fractions -

      -
      -A simple fraction:
      -\frac{1}{2}.
      Inlined: \frac{2}{3}. -
      -
      -A big recursive fraction:
      -\frac{1}{\left(1+\left(\frac{1}{1+\left(\frac{1}{1+2x}\lyxlock\right)}\lyxlock\right)\right)}\lyxlock
      -
      -
      -A nice fraction: \nicefrac{5}{6}. A non-diminishing fraction containing alignments:
      -\cfrac{1}{1+\left(\cfrac[l]{1}{1+x}\times\cfrac[r]{1}{1+x}\right)}.
      -
      -
      -A similar concept is a binomial coefficient: \binom{A+1}{B}. It can be prettily presented:
      -\dbinom{A}{B+1}.
      -
      -
      -A symbol can be stacked over another using \stackrel: x\stackrel{R}{\rightarrow}y. Anything can be stacked:
      -d\stackrel{x>3}{\lim}x,\quad\stackrel{\mathrm{head}}{\mathrm{heels}}.
      -
      -

      -4.2 Limits -

      -
      -\lim_{x\rightarrow\infty}f(x) should appear as x\rightarrow\infty in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol:
      -\lim_{x\rightarrow\infty}\lyxlock f(x).
      -
      -
      -Limits are also used in sums and integrals:
      -\sum_{i=1}^{\infty}x,\;\int_{0}^{\infty}f(x)\,\mathrm{d}x
      where the sum’s limits should appear below (i=1) and above (\infty) the \sum. The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the \int. Limits are shown to the right in inline formulae: \sum_{i=1}^{\infty}x and \intop_{i=1}^{\infty}x. -
      -
      -The placing of limits can be configured with the \limits and \nolimits macros:
      -\lim\nolimits _{x\rightarrow\infty}\lyxlock f(x),\;\sum\nolimits _{i=1}^{\infty}x,\;\int\limits _{0}^{\infty}f(x)\,\mathrm{d}x
      -
      -

      -4.3 Roots -

      -
      -A square root: \sqrt{3}. A more complex root in a fraction:
      -\frac{1}{\left(1+\sqrt{2}\left(\frac{1}{1+\sqrt{2}}\lyxlock\right)+\sqrt{\frac{1}{2}}\right)}\lyxlock.
      -
      -
      -eLyXer can also do higher-order roots: \sqrt[3]{x+y}. A devilish case mixing everything we have seen so far:
      -\frac{\sqrt[\nicefrac{7}{8}]{\frac{8}{4}x}+\sum_{i=1}^{\infty}x}{\sqrt[s+5]{\frac{(78x+45y)\times\sqrt{\Omega}}{\sin(x+1)}+\unit[38]{km}}}\lyxlock.
      -
      -

      -5 Complex Structures -

      -
      -In this section we will explore arrays and related constructs. -
      -

      -5.1 Arrays -

      -
      -An inline array \left[\begin{array}{cc} -a & b\\ -c & d\end{array}\right] is always shown in the same line. In display mode, the array is shown on its own line:
      -\left[\begin{array}{lc} -12 & 2\\ -3 & 4\times y^{x}\end{array}\right]
      Apart from that the appearance should be the same. -
      -

      -5.2 Brackets -

      -
      -Arrays are separated by variable-size brackets: \left(\begin{array}{cc} -a & b\\ -c & d\end{array}\right) \left[\begin{array}{cc} -a & b\\ -c & d\end{array}\right] \left\{ \begin{array}{cc} -a & b\\ -c & d\end{array}\right\} \left\langle \begin{array}{cc} -a & b\\ -c & d\end{array}\right\rangle \left|\begin{array}{cc} -a & b\\ -c & d\end{array}\right|which might also differ on right and left \left(\begin{array}{cc} -a & b\\ -c & d\end{array}\right) or use the empty opening \left\{ \begin{array}{cc} -a & b\\ -c & d\end{array}\right. or closing: \left.\begin{array}{cc} -a & b\\ -c & d\end{array}\right|. There are also fixed-size big brackets, e.g. \bigl\langle f\bigr\rangle. -
      -

      -5.3 Cases -

      -
      -Used to switch between several values. -
      -
      -
      -y=\begin{cases} -x & i=0,\\ -x+1 & i<3\end{cases}
      -
      -
      -Cases may have more than two rows: -
      -
      -
      -f(x)=\begin{cases} -0 & x<0,\\ -\infty & x=0\\ -0 & x>0\end{cases}
      -
      -

      -5.4 Braces -

      -
      -Values can be underbraced or overbraced. -
      -
      -\underbrace{a-b}=\overbrace{b+c+d+e}. -
      -

      -6 Macros -

      -
      -Now it’s time for user-defined commands (sometimes called “macros”). -
      -
      -Definitions can be added as macros -\newcommand{\stupidroot}[2]{\sqrt[#1]{#2}} -{\sqrt[#1]{#2}} -. Then they can be used in formulae: \stupidroot 12. They can accept default parameters -\newcommand{\defaultroot}[2][4][5]{\sqrt[#1]{#2}} -{#1\sqrt{#2}} -. Again, useful in formulae: \defaultroot. -
      -
      -Other definitions from the preamble can be used: \preambleroot{3}{4}. -
      -
      -Definitions on the fly are also possible: \newcommand{\ontheflyroot}[2]{\sqrt[#1]{#2}}\ontheflyroot{7}{8}, and used with different values: \ontheflyroot{a}{b}. -
      - - - -
      - - diff -Nru elyxer-1.2.3/docs/math-mathjax-local.html elyxer-1.2.5/docs/math-mathjax-local.html --- elyxer-1.2.3/docs/math-mathjax-local.html 2011-08-31 00:09:26.000000000 +0000 +++ elyxer-1.2.5/docs/math-mathjax-local.html 2013-03-10 21:24:00.000000000 +0000 @@ -4,7 +4,7 @@ - + eLyxer Math Showcase (MathJax local edition) + + +
      + + +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: +, +, +. eLyXer offers a complete set in both upper case: + and lower case: +. Also the AMS italicized upper case: +. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: +. It can also render a few more: +. You also get all symbols from Markus Kuhn's list: +. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows: +, or geometrical shapes: +, +. eLyXer offers limited support for them. You might also want to use financial symbols in formulae: +. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: +. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: + for medium mathematical spaces versus +, where +. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box, + + + +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + +. +
      +
      +There are other spacing commands: \hspace: +, protected space: +, and (at “block level”) \vspace: +. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, +, with the exception of upright capital Greek letters, +. +
      +
      +Function names should be upright: +. +
      +
      +Mathematical fonts used in equations include + (\mathrm), + (\mathsf), + (\mathtt), + (\mathbf), + (\mathscr), + (\mathcal), + (\mathbb), and + (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: +, +, +. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: +, via boxes like \mbox (prevents line breaks): +, or the AMSmath \text macro (scales like math symbols) +. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: +. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, +, with magnitude, +, with fractional unit, +, or with a fraction before the units, +, +. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like () + + + + And also like (↓). + + + + Some equations can be numbered even if they don’t have a label. +
      +
      + + + + + Notice that equation () comes after (). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction: + + + +Inlined: + +
      +
      +A big recursive fraction: + + + + +
      +
      +A nice fraction: +. A non-diminishing fraction containing alignments: + + + + +
      +
      +A similar concept is a binomial coefficient: + It can be prettily presented: + + + + +
      +
      +A symbol can be stacked over another using \stackrel: +. Anything can be stacked: + + + + +
      +

      +4.2 Limits +

      +
      + + should appear as + in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol: + + + + +
      +
      +Limits are also used in sums and integrals: + + + +where the sum’s limits should appear below ( +) and above ( +) the +. The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the +. Limits are shown to the right in inline formulae: + and + +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros: + + + + +
      +

      +4.3 Roots +

      +
      +A square root: + A more complex root in a fraction: + + + + +
      +
      +eLyXer can also do higher-order roots: +. A devilish case mixing everything we have seen so far: + + + + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + is always shown in the same line. In display mode, the array is shown on its own line: + + + +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + + + + +which might also differ on right and left + or use the empty opening + or closing: +. There are also fixed-size big brackets, e.g. +. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      + + + + + +
      +
      +Cases may have more than two rows: +
      +
      + + + + + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      + +. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: +. They can accept default parameters. Again, useful in formulae: +. +
      +
      +Other definitions from the preamble can be used: +. +
      +
      +Definitions on the fly are also possible: +, and used with different values: +. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/math-mathjax.html elyxer-1.2.5/forks/jras-elyxer/docs/math-mathjax.html --- elyxer-1.2.3/forks/jras-elyxer/docs/math-mathjax.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/math-mathjax.html 2013-03-10 10:39:40.000000000 +0000 @@ -0,0 +1,691 @@ + + + + + + + + +eLyxer Math Showcase (MathJax remote edition) + + + +
      + + +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: +, +, +. eLyXer offers a complete set in both upper case: + and lower case: +. Also the AMS italicized upper case: +. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: +. It can also render a few more: +. You also get all symbols from Markus Kuhn's list: +. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows: +, or geometrical shapes: +, +. eLyXer offers limited support for them. You might also want to use financial symbols in formulae: +. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: +. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: + for medium mathematical spaces versus +, where +. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box, + + + +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + +. +
      +
      +There are other spacing commands: \hspace: +, protected space: +, and (at “block level”) \vspace: +. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, +, with the exception of upright capital Greek letters, +. +
      +
      +Function names should be upright: +. +
      +
      +Mathematical fonts used in equations include + (\mathrm), + (\mathsf), + (\mathtt), + (\mathbf), + (\mathscr), + (\mathcal), + (\mathbb), and + (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: +, +, +. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: +, via boxes like \mbox (prevents line breaks): +, or the AMSmath \text macro (scales like math symbols) +. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: +. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, +, with magnitude, +, with fractional unit, +, or with a fraction before the units, +, +. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like () + + + + And also like (↓). + + + + Some equations can be numbered even if they don’t have a label. +
      +
      + + + + + Notice that equation () comes after (). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction: + + + +Inlined: + +
      +
      +A big recursive fraction: + + + + +
      +
      +A nice fraction: +. A non-diminishing fraction containing alignments: + + + + +
      +
      +A similar concept is a binomial coefficient: + It can be prettily presented: + + + + +
      +
      +A symbol can be stacked over another using \stackrel: +. Anything can be stacked: + + + + +
      +

      +4.2 Limits +

      +
      + + should appear as + in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol: + + + + +
      +
      +Limits are also used in sums and integrals: + + + +where the sum’s limits should appear below ( +) and above ( +) the +. The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the +. Limits are shown to the right in inline formulae: + and + +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros: + + + + +
      +

      +4.3 Roots +

      +
      +A square root: + A more complex root in a fraction: + + + + +
      +
      +eLyXer can also do higher-order roots: +. A devilish case mixing everything we have seen so far: + + + + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + is always shown in the same line. In display mode, the array is shown on its own line: + + + +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + + + + +which might also differ on right and left + or use the empty opening + or closing: +. There are also fixed-size big brackets, e.g. +. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      + + + + + +
      +
      +Cases may have more than two rows: +
      +
      + + + + + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      + +. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: +. They can accept default parameters. Again, useful in formulae: +. +
      +
      +Other definitions from the preamble can be used: +. +
      +
      +Definitions on the fly are also possible: +, and used with different values: +. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/math-unicode.html elyxer-1.2.5/forks/jras-elyxer/docs/math-unicode.html --- elyxer-1.2.3/forks/jras-elyxer/docs/math-unicode.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/math-unicode.html 2013-03-10 10:39:38.000000000 +0000 @@ -0,0 +1,713 @@ + + + + + + + + +eLyxer Math Showcase (Unicode edition) + + +
      +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: φ, π, Ξ. eLyXer offers a complete set in both upper case: Γ…Ω and lower case: αω. Also the AMS italicized upper case: ΓΩ. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: ∃∂∇ ≥ . It can also render a few more:  ∝  × . You also get all symbols from Markus Kuhn's list: ⊙∐. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows:  ←  → , or geometrical shapes: , . eLyXer offers limited support for them. You might also want to use financial symbols in formulae: ¥€$. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: x = 3. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: (4)/(18) em for medium mathematical spaces versus (1)/(2) en, where 1 em = 2 en. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box,
      +raisedoverloweredand back. +
      +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + BV. +
      +
      +There are other spacing commands: \hspace: a b, protected space: a b, and (at “block level”) \vspace: a b. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, αx + αy = α(x + y), with the exception of upright capital Greek letters, G ≠ Γ. +
      +
      +Function names should be upright: sin(2π), log(x), tanδ. +
      +
      +Mathematical fonts used in equations include Roman (\mathrm), Sans Serif (\mathsf), Typewriter (\mathtt), Bold (\mathbf), SCRIPT (\mathscr), CALLIGRAPHIC (\mathcal), BLACKBOARD BOLD (\mathbb), and Fraktur (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: , 𝔽, 𝔉. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: 5  to 10, via boxes like \mbox (prevents line breaks): 6  is more than 5, or the AMSmath \text macro (scales like math symbols) basesupersub. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: sfbfit, tipa. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, km, with magnitude, 57 km, with fractional unit, 200 kmh, or with a fraction before the units, 32 km, (7)/(16) s. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like (1↓)
      +(1) y = x +
      + And also like (2↓).
      +(2) x = 3 +
      + Some equations can be numbered even if they don’t have a label. +
      +
      +
      +(3) x = 2y +
      + Notice that equation (2↑) comes after (1↑). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction:
      +(1)/(2). +
      +Inlined: (2)/(3). +
      +
      +A big recursive fraction:
      +(1)/(1 + (1)/(1 + (1)/(1 + 2x))) +
      + +
      +
      +A nice fraction: 56. A non-diminishing fraction containing alignments:
      +(1)/(1 + (1)/(1 + x) × (1)/(1 + x)). +
      + +
      +
      +A similar concept is a binomial coefficient: (A + 1B). It can be prettily presented:
      +AB + 1. +
      + +
      +
      +A symbol can be stacked over another using \stackrel: xR → y. Anything can be stacked:
      +dx > 3limx,  headheels. +
      + +
      +

      +4.2 Limits +

      +
      +limx → ∞f(x) should appear as x → ∞ in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol:
      +limx → ∞f(x). +
      + +
      +
      +Limits are also used in sums and integrals:
      +i = 1x,  0f(x) dx +
      +where the sum’s limits should appear below (i = 1) and above () the . The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the . Limits are shown to the right in inline formulae: i = 1x and i = 1x. +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros:
      +limx → ∞f(x),  i = 1x,  0f(x) dx +
      + +
      +

      +4.3 Roots +

      +
      +A square root: (3). A more complex root in a fraction:
      +(1)/(1 + (2)(1)/(1 + (2)) + ((1)/(2))). +
      + +
      +
      +eLyXer can also do higher-order roots: 3(x + y). A devilish case mixing everything we have seen so far:
      +(78((8)/(4)x) + i = 1x)/(s + 5(((78x + 45y) × (Ω))/(sin(x + 1)) + 38 km)). +
      + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + is always shown in the same line. In display mode, the array is shown on its own line:
      + + +12 + + +2 + + + + + +  + + +  + + + + + +3 + + +4 × yx + + + + +
      +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + ||| + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||which might also differ on right and left + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or use the empty opening + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or closing: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||. There are also fixed-size big brackets, e.g. f. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      +
      +y =  + + +x  + + +i = 0,   + + + + + +   + + +   + + + + + +x + 1  + + +i < 3  + + + + + + +
      + +
      +
      +Cases may have more than two rows: +
      +
      +
      +f(x) =  + + +0  + + +x < 0,   + + + + + +   + + +   + + + + + +∞  + + +x = 0  + + + + + +   + + +   + + + + + +0  + + +x > 0  + + + + + + +
      + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      +a − b = b + c + d + e. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: 1(2). They can accept default parameters. Again, useful in formulae: 4(5). +
      +
      +Other definitions from the preamble can be used: 3(4). +
      +
      +Definitions on the fly are also possible: 7(8), and used with different values: a(b). +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/math.css elyxer-1.2.5/forks/jras-elyxer/docs/math.css --- elyxer-1.2.3/forks/jras-elyxer/docs/math.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/math.css 2013-03-10 10:39:36.000000000 +0000 @@ -0,0 +1,274 @@ +/* +* math2html: convert LaTeX equations to HTML output. +* +* Copyright (C) 2009,2010 Alex Fernández +* +* Released under the terms of the `2-Clause BSD license'_, in short: +* Copying and distribution of this file, with or without modification, +* are permitted in any medium without royalty provided the copyright +* notice and this notice are preserved. +* This file is offered as-is, without any warranty. +* +* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause +* +* Based on eLyXer: convert LyX source files to HTML output. +* http://elyxer.nongnu.org/ +*/ +/* --end-- +* CSS file for LaTeX formulas. +*/ + +/* Formulas */ +.formula { + text-align: center; + font-family: "DejaVu Serif", serif; + margin: 1.2em 0; +} +span.formula { + white-space: nowrap; +} +div.formula { + padding: 0.5ex; + margin-left: auto; + margin-right: auto; +} + +/* Basic features */ +a.eqnumber { + display: inline-block; + float: right; + clear: right; + font-weight: bold; +} +span.unknown { + color: #800000; +} +span.ignored, span.arraydef { + display: none; +} +.formula i { + letter-spacing: 0.1ex; +} + +/* Alignment */ +.align-left, .align-l { + text-align: left; +} +.align-right, .align-r { + text-align: right; +} +.align-center, .align-c { + text-align: center; +} + +/* Structures */ +span.overline, span.bar { + text-decoration: overline; +} +.fraction, .fullfraction { + display: inline-block; + vertical-align: middle; + text-align: center; +} +.fraction .fraction { + font-size: 80%; + line-height: 100%; +} +span.numerator { + display: block; +} +span.denominator { + display: block; + padding: 0ex; + border-top: thin solid; +} +sup.numerator, sup.unit { + font-size: 70%; + vertical-align: 80%; +} +sub.denominator, sub.unit { + font-size: 70%; + vertical-align: -20%; +} +span.sqrt { + display: inline-block; + vertical-align: middle; + padding: 0.1ex; +} +sup.root { + font-size: 70%; + position: relative; + left: 1.4ex; +} +span.radical { + display: inline-block; + padding: 0ex; + font-size: 150%; + vertical-align: top; +} +span.root { + display: inline-block; + border-top: thin solid; + padding: 0ex; + vertical-align: middle; +} +span.symbol { + font-size: 125%; +} +span.bigsymbol { + font-size: 150%; +} +span.largesymbol { + font-size: 175%; +} +span.hugesymbol { + font-size: 200%; +} +span.scripts { + display: inline-table; + vertical-align: middle; +} +.script { + display: table-row; + text-align: left; + line-height: 150%; +} +span.limits { + display: inline-table; + vertical-align: middle; +} +.limit { + display: table-row; + line-height: 95%; +} +sup.limit, sub.limit { + line-height: 150%; +} +span.symbolover { + display: inline-block; + text-align: center; + position: relative; + float: right; + right: 100%; + bottom: 0.5em; + width: 0px; +} +span.withsymbol { + display: inline-block; +} +span.symbolunder { + display: inline-block; + text-align: center; + position: relative; + float: right; + right: 80%; + top: 0.3em; + width: 0px; +} + +/* Environments */ +span.array, span.bracketcases, span.binomial, span.environment { + display: inline-table; + text-align: center; + border-collapse: collapse; + margin: 0em; + vertical-align: middle; +} +span.arrayrow, span.binomrow { + display: table-row; + padding: 0ex; + border: 0ex; +} +span.arraycell, span.bracket, span.case, span.binomcell, span.environmentcell { + display: table-cell; + padding: 0ex 0.2ex; + line-height: 99%; + border: 0ex; +} +/* +* CSS file for LaTeX formulas, extra stuff: +* binomials, vertical braces, stackrel, fonts and colors. +*/ + +/* Inline binomials */ +span.binom { + display: inline-block; + vertical-align: middle; + text-align: center; + font-size: 80%; +} +span.binomstack { + display: block; + padding: 0em; +} + +/* Over- and underbraces */ +span.overbrace { + border-top: 2pt solid; +} +span.underbrace { + border-bottom: 2pt solid; +} + +/* Stackrel */ +span.stackrel { + display: inline-block; + text-align: center; +} +span.upstackrel { + display: block; + padding: 0em; + font-size: 80%; + line-height: 64%; + position: relative; + top: 0.15em; + +} +span.downstackrel { + display: block; + vertical-align: bottom; + padding: 0em; +} + +/* Fonts */ +span.mathsf, span.textsf { + font-style: normal; + font-family: sans-serif; +} +span.mathrm, span.textrm { + font-style: normal; + font-family: serif; +} +span.text, span.textnormal { + font-style: normal; +} +span.textipa { + color: #008080; +} +span.fraktur { + font-family: "Lucida Blackletter", eufm10, blackletter; +} +span.blackboard { + font-family: Blackboard, msbm10, serif; +} +span.scriptfont { + font-family: "Monotype Corsiva", "Apple Chancery", "URW Chancery L", cursive; + font-style: italic; +} + +/* Colors */ +span.colorbox { + display: inline-block; + padding: 5px; +} +span.fbox { + display: inline-block; + border: thin solid black; + padding: 2px; +} +span.boxed, span.framebox { + display: inline-block; + border: thin solid black; + padding: 5px; +} + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/math.html elyxer-1.2.5/forks/jras-elyxer/docs/math.html --- elyxer-1.2.3/forks/jras-elyxer/docs/math.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/math.html 2013-03-10 10:39:38.000000000 +0000 @@ -0,0 +1,713 @@ + + + + + + + + +eLyxer Math Showcase (non-Unicode edition) + + +
      +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: φ, π, Ξ. eLyXer offers a complete set in both upper case: Γ…Ω and lower case: αω. Also the AMS italicized upper case: ΓΩ. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: ∃∂∇ ≥ . It can also render a few more:  ∝  × . You also get all symbols from Markus Kuhn's list: ⊙∐. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows:  ←  → , or geometrical shapes: , . eLyXer offers limited support for them. You might also want to use financial symbols in formulae: ¥€$. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: x = 3. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: (4)/(18) em for medium mathematical spaces versus (1)/(2) en, where 1 em = 2 en. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box,
      +raisedoverloweredand back. +
      +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + BV. +
      +
      +There are other spacing commands: \hspace: a b, protected space: a b, and (at “block level”) \vspace: a b. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, αx + αy = α(x + y), with the exception of upright capital Greek letters, G ≠ Γ. +
      +
      +Function names should be upright: sin(2π), log(x), tanδ. +
      +
      +Mathematical fonts used in equations include Roman (\mathrm), Sans Serif (\mathsf), Typewriter (\mathtt), Bold (\mathbf), SCRIPT (\mathscr), CALLIGRAPHIC (\mathcal), BLACKBOARD BOLD (\mathbb), and Fraktur (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: , 𝔽, 𝔉. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: 5  to 10, via boxes like \mbox (prevents line breaks): 6  is more than 5, or the AMSmath \text macro (scales like math symbols) basesupersub. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: sfbfit, tipa. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, km, with magnitude, 57 km, with fractional unit, 200 kmh, or with a fraction before the units, 32 km, (7)/(16) s. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like (1↓)
      +(1) y = x +
      + And also like (2↓).
      +(2) x = 3 +
      + Some equations can be numbered even if they don’t have a label. +
      +
      +
      +(3) x = 2y +
      + Notice that equation (2↑) comes after (1↑). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction:
      +(1)/(2). +
      +Inlined: (2)/(3). +
      +
      +A big recursive fraction:
      +(1)/(1 + (1)/(1 + (1)/(1 + 2x))) +
      + +
      +
      +A nice fraction: 56. A non-diminishing fraction containing alignments:
      +(1)/(1 + (1)/(1 + x) × (1)/(1 + x)). +
      + +
      +
      +A similar concept is a binomial coefficient: (A + 1B). It can be prettily presented:
      +AB + 1. +
      + +
      +
      +A symbol can be stacked over another using \stackrel: xR → y. Anything can be stacked:
      +dx > 3limx,  headheels. +
      + +
      +

      +4.2 Limits +

      +
      +limx → ∞f(x) should appear as x → ∞ in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol:
      +limx → ∞f(x). +
      + +
      +
      +Limits are also used in sums and integrals:
      +i = 1x,  0f(x) dx +
      +where the sum’s limits should appear below (i = 1) and above () the . The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the . Limits are shown to the right in inline formulae: i = 1x and i = 1x. +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros:
      +limx → ∞f(x),  i = 1x,  0f(x) dx +
      + +
      +

      +4.3 Roots +

      +
      +A square root: (3). A more complex root in a fraction:
      +(1)/(1 + (2)(1)/(1 + (2)) + ((1)/(2))). +
      + +
      +
      +eLyXer can also do higher-order roots: 3(x + y). A devilish case mixing everything we have seen so far:
      +(78((8)/(4)x) + i = 1x)/(s + 5(((78x + 45y) × (Ω))/(sin(x + 1)) + 38 km)). +
      + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + is always shown in the same line. In display mode, the array is shown on its own line:
      + + +12 + + +2 + + + + + +  + + +  + + + + + +3 + + +4 × yx + + + + +
      +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + ||| + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||which might also differ on right and left + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or use the empty opening + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or closing: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||. There are also fixed-size big brackets, e.g. f. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      +
      +y =  + + +x  + + +i = 0,   + + + + + +   + + +   + + + + + +x + 1  + + +i < 3  + + + + + + +
      + +
      +
      +Cases may have more than two rows: +
      +
      +
      +f(x) =  + + +0  + + +x < 0,   + + + + + +   + + +   + + + + + +∞  + + +x = 0  + + + + + +   + + +   + + + + + +0  + + +x > 0  + + + + + + +
      + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      +a − b = b + c + d + e. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: 1(2). They can accept default parameters. Again, useful in formulae: 4(5). +
      +
      +Other definitions from the preamble can be used: 3(4). +
      +
      +Definitions on the fly are also possible: 7(8), and used with different values: a(b). +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/math.lyx elyxer-1.2.5/forks/jras-elyxer/docs/math.lyx --- elyxer-1.2.3/forks/jras-elyxer/docs/math.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/math.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1263 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2011 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . + +% DO NOT ALTER THIS PREAMBLE!!! +% +% This preamble is designed to ensure that the User's Guide prints +% out as advertised. If you mess with this preamble, +% parts of the User's Guide may not print out as expected. If you +% have problems LaTeXing this file, please contact +% the documentation team +% email: lyx-docs@lists.lyx.org + +\usepackage{ifpdf} % part of the hyperref bundle +\ifpdf % if pdflatex is used + + % set fonts for nicer pdf view + \IfFileExists{lmodern.sty}{\usepackage{lmodern}}{} + +\fi % end if pdflatex is used + +% for correct jump positions whe clicking on a link to a float +\usepackage[figure]{hypcap} + + +% redefine the \LyX macro for PDF bookmarks +\def\LyX{\texorpdfstring{% + L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} + {LyX}} + + +% test macro with two arguments +\newcommand{\preambleroot}[2]{\sqrt[#1]{#2}} + +% redefine the greyed out note + +\usepackage{mathrsfs} +\usepackage{eurosym} +\end_preamble +\options intoc,bibtotoc,idxtotoc,BCOR7mm,tablecaptionabove +\use_default_options false +\language english +\inputencoding utf8 +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize 12 +\spacing single +\use_hyperref true +\pdf_title "eLyXer Math Showcase" +\pdf_author "Alex Fernández" +\pdf_subject "The amazing all-time-wonder eLyXer Math Showcase" +\pdf_keywords "LyX" +\pdf_bookmarks true +\pdf_bookmarksnumbered false +\pdf_bookmarksopen false +\pdf_bookmarksopenlevel 1 +\pdf_breaklinks false +\pdf_pdfborder false +\pdf_colorlinks false +\pdf_backref false +\pdf_pdfusetitle true +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 0 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\branch Pregunta +\selected 1 +\color #00ff00 +\end_branch +\branch Respuesta +\selected 0 +\color #aa55ff +\end_branch +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 2 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +\begin_inset Graphics + filename elyxer.svg + lyxscale 50 + +\end_inset + +eLyXer Math Showcase +\end_layout + +\begin_layout Author +Alex Fernández (elyxer@gmail.com) +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Section +Introduction +\end_layout + +\begin_layout Standard +This document is intended as a showcase of the mathematical abilities of + eLyXer; for more information be sure to visit the +\begin_inset CommandInset href +LatexCommand href +name "main page" +target "index.html" + +\end_inset + +. +\end_layout + +\begin_layout Subsection +Versions +\end_layout + +\begin_layout Standard +There are several versions of this page: +\end_layout + +\begin_layout Itemize +A +\begin_inset CommandInset href +LatexCommand href +name "non-Unicode version" +target "math.html" + +\end_inset + + of this page with midspaces. +\end_layout + +\begin_layout Itemize +A +\begin_inset CommandInset href +LatexCommand href +name "Unicode version" +target "math-unicode.html" + +\end_inset + + with mathematical spaces (generated with +\family typewriter +--unicode +\family default +). +\end_layout + +\begin_layout Itemize +An +\begin_inset CommandInset href +LatexCommand href +name "ISO-8859-15 version" +target "math-iso885915.html" + +\end_inset + + (generated with +\family typewriter +--iso885915 +\family default +). +\end_layout + +\begin_layout Itemize +An +\begin_inset CommandInset href +LatexCommand href +name "HTML version" +target "math-html.html" + +\end_inset + + (generated with +\family typewriter +--html +\family default +). +\end_layout + +\begin_layout Itemize +A +\begin_inset CommandInset href +LatexCommand href +name "MathJax remote version" +target "math-mathjax.html" + +\end_inset + + with +\begin_inset CommandInset href +LatexCommand href +name "MathJax" +target "http://www.mathjax.org/" + +\end_inset + + (generated with +\family typewriter +--mathjax remote +\family default +). +\end_layout + +\begin_layout Itemize +A +\begin_inset CommandInset href +LatexCommand href +name "MathJax local version" +target "math-mathjax-local.html" + +\end_inset + + with +\begin_inset CommandInset href +LatexCommand href +name "MathJax" +target "http://www.mathjax.org/" + +\end_inset + + (generated with +\family typewriter +--mathjax +\family default + and a local URL). +\end_layout + +\begin_layout Itemize +A +\begin_inset CommandInset href +LatexCommand href +name "Google Charts version" +target "math-googlecharts.html" + +\end_inset + + with +\begin_inset CommandInset href +LatexCommand href +name "Google Charts" +target "http://code.google.com/apis/chart/index.html" + +\end_inset + + (generated with +\family typewriter +--googlecharts +\family default +). +\end_layout + +\begin_layout Standard +All of them are generated from the same +\family typewriter +.lyx +\family default + source file; they should help you decide which rendering options suit you + best. +\end_layout + +\begin_layout Standard +Also available online is the eLyXer translation of the latest +\begin_inset CommandInset href +LatexCommand href +name "LyX’s detailed Math manual" +target "http://elyxer.nongnu.org/lyx/Math.html" + +\end_inset + +, which contains a lot more examples of LyX maths. +\end_layout + +\begin_layout Section +Typography +\end_layout + +\begin_layout Standard +Math formulae use a lot of different symbols and fonts. +\end_layout + +\begin_layout Subsection +Greek Symbols +\end_layout + +\begin_layout Standard +Greek symbols are very important in equations: +\begin_inset Formula $\phi$ +\end_inset + +, +\begin_inset Formula $\pi$ +\end_inset + +, +\begin_inset Formula $\Xi$ +\end_inset + +. + eLyXer offers a complete set in both upper case: +\begin_inset Formula $\Gamma\ldots\Omega$ +\end_inset + + and lower case: +\begin_inset Formula $\alpha\ldots\omega$ +\end_inset + +. + Also the AMS italicized upper case: +\begin_inset Formula $\varGamma\ldots\varOmega$ +\end_inset + +. +\end_layout + +\begin_layout Subsection +Math Symbols +\end_layout + +\begin_layout Standard +eLyXer supports the whole set of math symbols in +\begin_inset CommandInset href +LatexCommand href +name "John D. Cook's list" +target "http://www.johndcook.com/math_symbols.html" + +\end_inset + +: +\begin_inset Formula $\exists\partial\nabla\geq$ +\end_inset + +. + It can also render a few more: +\begin_inset Formula $\propto\times$ +\end_inset + +. +\begin_inset Note Note +status collapsed + +\begin_layout Plain Layout +The +\backslash +propto symbol is rendered as +\begin_inset Formula $\mu$ +\end_inset + + in the LyX 1.6.8 window. + LyX bug? +\end_layout + +\end_inset + + You also get all symbols from +\begin_inset CommandInset href +LatexCommand href +name "Markus Kuhn's list" +target "http://www.cl.cam.ac.uk/~mgk25/ucs/examples/TeX.txt" + +\end_inset + +: +\begin_inset Formula $\bigodot\amalg$ +\end_inset + +. +\end_layout + +\begin_layout Subsection +Other Symbols +\end_layout + +\begin_layout Standard +There are other symbols like arrows: +\begin_inset Formula $\leftarrow\rightarrow$ +\end_inset + +, or geometrical shapes: +\begin_inset Formula $\circ$ +\end_inset + +, +\begin_inset Formula $\square$ +\end_inset + +. + eLyXer offers limited support for them. + You might also want to use financial symbols in formulae: +\begin_inset Formula $\yen\euro\$$ +\end_inset + +. +\end_layout + +\begin_layout Subsection +Spacing +\end_layout + +\begin_layout Standard +Equations look good when items are properly separated. + The main separation is the Medium Mathematical Space: +\begin_inset Formula $x=3$ +\end_inset + +. + +\begin_inset Note Greyedout +status open + +\begin_layout Plain Layout +Note: if you are viewing the non-Unicode version +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +math.html +\end_layout + +\end_inset + + of this page then you are in fact seeing midspaces, which are very similar + but not exactly the same: +\begin_inset Formula $\frac{4}{18}\mathrm{em}$ +\end_inset + + for medium mathematical spaces versus +\begin_inset Formula $\frac{1}{2}\mathrm{en}$ +\end_inset + +, where +\begin_inset Formula $1\mathrm{em}=2\mathrm{en}$ +\end_inset + +. + Try out the Unicode version +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +math-unicode.html +\end_layout + +\end_inset + + -- and viceversa. + You can check out what version this page is in the page title. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +The command +\family typewriter + +\backslash +raisebox +\family default + is useful to, surprisingly, raise a little box, +\begin_inset Formula \[ +\raisebox{2mm}{raised}over\raisebox{-2mm}{lowered}\textrm{and back}.\] + +\end_inset + +Like +\family typewriter + +\backslash +mbox +\family default +, it puts its content in a text box. + It can also be used just for spacing: +\begin_inset Newline newline +\end_inset + + +\begin_inset Formula $\raisebox{5mm}{}B^{V}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +There are other spacing commands: +\family typewriter + +\backslash +hspace +\family default +: +\begin_inset Formula $a\hspace{4mm}b$ +\end_inset + +, protected space: +\begin_inset Formula $a\ b$ +\end_inset + +, and (at +\begin_inset Quotes eld +\end_inset + +block level +\begin_inset Quotes erd +\end_inset + +) +\family typewriter + +\backslash +vspace +\family default +: +\begin_inset Formula $a\vspace{1cm}b$ +\end_inset + +. +\end_layout + +\begin_layout Standard +There should be 1 +\begin_inset space ~ +\end_inset + +cm of vertical space above this paragraph. +\end_layout + +\begin_layout Subsection +Fonts +\end_layout + +\begin_layout Standard +By default, letters denote variables and are taken from the +\family typewriter + +\backslash +mathnormal +\family default + font, which is italic, +\begin_inset Formula $\alpha x+\alpha y=\alpha(x+y)$ +\end_inset + +, with the exception of upright capital Greek letters, +\begin_inset Formula $G\ne\Gamma$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Function names should be upright: +\begin_inset Formula $\sin(2\pi),\log(x),\tan\delta$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Mathematical fonts used in equations include +\begin_inset Formula $\mathrm{Roman}$ +\end_inset + + ( +\family typewriter + +\backslash +mathrm +\family default +), +\begin_inset Formula $\mathsf{Sans\: Serif}$ +\end_inset + + ( +\family typewriter + +\backslash +mathsf +\family default +), +\begin_inset Formula $\mathtt{Typewriter}$ +\end_inset + + ( +\family typewriter + +\backslash +mathtt +\family default +), +\begin_inset Formula $\mathbf{Bold}$ +\end_inset + + ( +\family typewriter + +\backslash +mathbf +\family default +), +\begin_inset Formula $\mathscr{SCRIPT}$ +\end_inset + + ( +\family typewriter + +\backslash +mathscr +\family default +), +\begin_inset Formula $\mathcal{CALLIGRAPHIC}$ +\end_inset + + ( +\family typewriter + +\backslash +mathcal +\family default +), +\begin_inset Formula $\mathbb{BLACKBOARD\: BOLD}$ +\end_inset + + ( +\family typewriter +\noun on + +\backslash + +\noun default +mathbb +\family default +), and +\begin_inset Formula $\mathfrak{Fraktur}$ +\end_inset + + ( +\family typewriter + +\backslash +mathfrak +\family default +). + For the latter, some single characters are translated to their Unicode + equivalents: +\begin_inset Formula $\mathscr{F}$ +\end_inset + +, +\begin_inset Formula $\mathbb{F}$ +\end_inset + +, +\begin_inset Formula $\mathfrak{F}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Regular text in a formula can be achieved via text font commands like +\family typewriter + +\backslash +textrm +\family default +: +\begin_inset Formula $5\:\textrm{to}\:10$ +\end_inset + +, via boxes like +\backslash +mbox (prevents line breaks): +\begin_inset Formula $6\mbox{ is more than }5$ +\end_inset + +, or the AMSmath +\family typewriter + +\backslash +text +\family default + macro (scales like math symbols) +\begin_inset Formula $\text{base}_{\text{sub}}^{\text{super}}$ +\end_inset + +. + The content of an mbox is processed in LaTeX text mode. + This allows text font commands, e.g. + a switch to +\family sans +\series bold +\shape italic +sans-serif-bold-italic +\family default +\series default +\shape default +, or the phonetic alphabet: +\begin_inset Formula $\mbox{\textbf{\textsf{\textbf{\textit{sfbfit}}}}, \textipa{tipa}}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Units should be written upright, either with +\family typewriter + +\backslash +mathrm +\family default + or with macros from the +\family typewriter +units +\family default + package, e.g. + as simple unit, +\begin_inset Formula $\unit{km}$ +\end_inset + +, with magnitude, +\begin_inset Formula $\unit[57]{km}$ +\end_inset + +, with fractional unit, +\begin_inset Formula $\unitfrac[200]{km}{h}$ +\end_inset + +, or with a fraction before the units, +\begin_inset Formula $\unit[\nicefrac{3}{2}]{km}$ +\end_inset + +, +\begin_inset Formula $\unit[\frac{7}{16}]{s}$ +\end_inset + +. +\end_layout + +\begin_layout Section +Numeration +\end_layout + +\begin_layout Standard +Equations can be numbered, like ( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:first" + +\end_inset + +) +\begin_inset Formula \begin{equation} +y=x\label{eq:first}\end{equation} + +\end_inset + + And also like +\begin_inset CommandInset ref +LatexCommand eqref +reference "eq:second" + +\end_inset + +. + +\begin_inset Formula \begin{equation} +x=3\label{eq:second}\end{equation} + +\end_inset + + Some equations can be numbered even if they don't have a label. +\end_layout + +\begin_layout Standard +\begin_inset Formula \begin{equation} +x=2y\end{equation} + +\end_inset + + Notice that equation ( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:second" + +\end_inset + +) comes after ( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:first" + +\end_inset + +). +\end_layout + +\begin_layout Section +Simple Structures +\end_layout + +\begin_layout Standard +Let's now see a few of the simpler structures that eLyXer can output. +\end_layout + +\begin_layout Subsection +Fractions +\end_layout + +\begin_layout Standard +A simple fraction: +\begin_inset Formula \[ +\frac{1}{2}.\] + +\end_inset + +Inlined: +\begin_inset Formula $\frac{2}{3}.$ +\end_inset + + +\end_layout + +\begin_layout Standard +A big recursive fraction: +\begin_inset Formula \[ +\frac{1}{\left(1+\left(\frac{1}{1+\left(\frac{1}{1+2x}\lyxlock\right)}\lyxlock\right)\right)}\lyxlock\] + +\end_inset + + +\end_layout + +\begin_layout Standard +A nice fraction: +\begin_inset Formula $\nicefrac{5}{6}$ +\end_inset + +. + A non-diminishing fraction containing alignments: +\begin_inset Formula \[ +\cfrac{1}{1+\left(\cfrac[l]{1}{1+x}\times\cfrac[r]{1}{1+x}\right)}.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +A similar concept is a binomial coefficient: +\begin_inset Formula $\binom{A+1}{B}.$ +\end_inset + + It can be prettily presented: +\begin_inset Formula \[ +\dbinom{A}{B+1}.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +A symbol can be stacked over another using +\family typewriter + +\backslash +stackrel +\family default +: +\begin_inset Formula $x\stackrel{R}{\rightarrow}y$ +\end_inset + +. + Anything can be stacked: +\begin_inset Formula \[ +d\stackrel{x>3}{\lim}x,\quad\stackrel{\mathrm{head}}{\mathrm{heels}}.\] + +\end_inset + + +\end_layout + +\begin_layout Subsection +Limits +\end_layout + +\begin_layout Standard +\begin_inset Formula $\lim_{x\rightarrow\infty}f(x)$ +\end_inset + + should appear as +\begin_inset Formula $x\rightarrow\infty$ +\end_inset + + in italics, and +\begin_inset Quotes fld +\end_inset + +lim +\begin_inset Quotes frd +\end_inset + + in plain style. + In display mode, a limit must appear below the main symbol: +\begin_inset Formula \[ +\lim_{x\rightarrow\infty}\lyxlock f(x).\] + +\end_inset + + +\end_layout + +\begin_layout Standard +Limits are also used in sums and integrals: +\begin_inset Formula \[ +\sum_{i=1}^{\infty}x,\;\int_{0}^{\infty}f(x)\,\mathrm{d}x\] + +\end_inset + +where the sum's limits should appear below ( +\begin_inset Formula $i=1$ +\end_inset + +) and above ( +\begin_inset Formula $\infty$ +\end_inset + +) the +\begin_inset Formula $\sum$ +\end_inset + +. + The placement of the integral limits depends on the document class: LaTeX + standard classes place them right to the +\begin_inset Formula $\int$ +\end_inset + +. + Limits are shown to the right in inline formulae: +\begin_inset Formula $\sum_{i=1}^{\infty}x$ +\end_inset + + and +\begin_inset Formula $\intop_{i=1}^{\infty}x.$ +\end_inset + + +\end_layout + +\begin_layout Standard +The placing of limits can be configured with the +\family typewriter + +\backslash +limits +\family default + and +\family typewriter + +\backslash +nolimits +\family default + macros: +\begin_inset Formula \[ +\lim\nolimits _{x\rightarrow\infty}\lyxlock f(x),\;\sum\nolimits _{i=1}^{\infty}x,\;\int\limits _{0}^{\infty}f(x)\,\mathrm{d}x\] + +\end_inset + + +\end_layout + +\begin_layout Subsection +Roots +\end_layout + +\begin_layout Standard +A square root: +\begin_inset Formula $\sqrt{3}.$ +\end_inset + + A more complex root in a fraction: +\begin_inset Formula \[ +\frac{1}{\left(1+\sqrt{2}\left(\frac{1}{1+\sqrt{2}}\lyxlock\right)+\sqrt{\frac{1}{2}}\right)}\lyxlock.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +eLyXer can also do higher-order roots: +\begin_inset Formula $\sqrt[3]{x+y}$ +\end_inset + +. + A devilish case mixing everything we have seen so far: +\begin_inset Formula \[ +\frac{\sqrt[\nicefrac{7}{8}]{\frac{8}{4}x}+\sum_{i=1}^{\infty}x}{\sqrt[s+5]{\frac{(78x+45y)\times\sqrt{\Omega}}{\sin(x+1)}+\unit[38]{km}}}\lyxlock.\] + +\end_inset + + +\end_layout + +\begin_layout Section +Complex Structures +\end_layout + +\begin_layout Standard +In this section we will explore arrays and related constructs. +\end_layout + +\begin_layout Subsection +Arrays +\end_layout + +\begin_layout Standard +An inline array +\begin_inset Formula $\left[\begin{array}{cc} +a & b\\ +c & d\end{array}\right]$ +\end_inset + + is always shown in the same line. + In display mode, the array is shown on its own line: +\begin_inset Formula \[ +\left[\begin{array}{lc} +12 & 2\\ +3 & 4\times y^{x}\end{array}\right]\] + +\end_inset + +Apart from that the appearance should be the same. +\end_layout + +\begin_layout Subsection +Brackets +\end_layout + +\begin_layout Standard +Arrays are separated by variable-size brackets: +\begin_inset Formula $\left(\begin{array}{cc} +a & b\\ +c & d\end{array}\right)$ +\end_inset + + +\begin_inset Formula $\left[\begin{array}{cc} +a & b\\ +c & d\end{array}\right]$ +\end_inset + + +\begin_inset Formula $\left\{ \begin{array}{cc} +a & b\\ +c & d\end{array}\right\} $ +\end_inset + + +\begin_inset Formula $\left\langle \begin{array}{cc} +a & b\\ +c & d\end{array}\right\rangle $ +\end_inset + + +\begin_inset Formula $\left|\begin{array}{cc} +a & b\\ +c & d\end{array}\right|$ +\end_inset + +which might also differ on right and left +\begin_inset Formula $\left(\begin{array}{cc} +a & b\\ +c & d\end{array}\right)$ +\end_inset + + or use the empty opening +\begin_inset Formula $\left\{ \begin{array}{cc} +a & b\\ +c & d\end{array}\right.$ +\end_inset + + or closing: +\begin_inset Formula $\left.\begin{array}{cc} +a & b\\ +c & d\end{array}\right|$ +\end_inset + +. + There are also fixed-size big brackets, e.g. + +\begin_inset Formula $\bigl\langle f\bigr\rangle$ +\end_inset + +. +\end_layout + +\begin_layout Subsection +Cases +\end_layout + +\begin_layout Standard +Used to switch between several values. +\end_layout + +\begin_layout Standard +\begin_inset Formula \[ +y=\begin{cases} +x & i=0,\\ +x+1 & i<3\end{cases}\] + +\end_inset + + +\end_layout + +\begin_layout Standard +Cases may have more than two rows: +\end_layout + +\begin_layout Standard +\begin_inset Formula \[ +f(x)=\begin{cases} +0 & x<0,\\ +\infty & x=0\\ +0 & x>0\end{cases}\] + +\end_inset + + +\end_layout + +\begin_layout Subsection +Braces +\end_layout + +\begin_layout Standard +Values can be underbraced or overbraced. +\end_layout + +\begin_layout Standard +\begin_inset Formula $\underbrace{a-b}=\overbrace{b+c+d+e}$ +\end_inset + +. +\end_layout + +\begin_layout Section +Macros +\end_layout + +\begin_layout Standard +Now it's time for user-defined commands (sometimes called +\begin_inset Quotes eld +\end_inset + +macros +\begin_inset Quotes erd +\end_inset + +). +\end_layout + +\begin_layout Standard +Definitions can be added as macros +\begin_inset FormulaMacro +\newcommand{\stupidroot}[2]{\sqrt[#1]{#2}} +{\sqrt[#1]{#2}} +\end_inset + +. + Then they can be used in formulae: +\begin_inset Formula $\stupidroot 12$ +\end_inset + +. + They can accept default parameters +\begin_inset FormulaMacro +\newcommand{\defaultroot}[2][4][5]{\sqrt[#1]{#2}} +{#1\sqrt{#2}} +\end_inset + +. + Again, useful in formulae: +\begin_inset Formula $\defaultroot$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Other definitions from the preamble can be used: +\begin_inset Formula $\preambleroot{3}{4}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Definitions on the fly are also possible: +\begin_inset Formula $\newcommand{\ontheflyroot}[2]{\sqrt[#1]{#2}}\ontheflyroot{7}{8}$ +\end_inset + +, and used with different values: +\begin_inset Formula $\ontheflyroot{a}{b}$ +\end_inset + +. +\end_layout + +\end_body +\end_document Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/docs/parse tree.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/docs/parse tree.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/parse tree.svg elyxer-1.2.5/forks/jras-elyxer/docs/parse tree.svg --- elyxer-1.2.3/forks/jras-elyxer/docs/parse tree.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/parse tree.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,437 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + \begin_inset + + + + Graphics + + + + Text + + + + LatexCommand + + + + Inset + + + + label + + + + ref + + + + + + + + Image + + + + Reference + + + + Label + + + + + + + + + InsetText + + + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/docs/pipeline.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/docs/pipeline.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/pipeline.svg elyxer-1.2.5/forks/jras-elyxer/docs/pipeline.svg --- elyxer-1.2.3/forks/jras-elyxer/docs/pipeline.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/pipeline.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + elyxer + + + + LyX file + + + + singleHTML file + + + + + + multipleHTML files + + + + + elyxer --splitpart + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/svg/elyxer-svg.svg elyxer-1.2.5/forks/jras-elyxer/docs/svg/elyxer-svg.svg --- elyxer-1.2.3/forks/jras-elyxer/docs/svg/elyxer-svg.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/svg/elyxer-svg.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/svg/svg-test.html elyxer-1.2.5/forks/jras-elyxer/docs/svg/svg-test.html --- elyxer-1.2.3/forks/jras-elyxer/docs/svg/svg-test.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/svg/svg-test.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,52 @@ + + + + + + + +SVG Test + + +
      +

      +SVG Test +

      +
      1: + + Object with size. + +Object with size information equal to the SVG. +
      +
      2: + + Object with half size. + +Object with size information half the SVG. +
      +
      3: + + Object without size. + +Object without size information. +
      +
      4: +Img with size +Img with size information equal to the SVG. +
      +
      5: +Img with half size +Img with size information half the SVG. +
      +
      6: +Img without size +Img without size information. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/toc.css elyxer-1.2.5/forks/jras-elyxer/docs/toc.css --- elyxer-1.2.3/forks/jras-elyxer/docs/toc.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/toc.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,40 @@ +/* +* Styles for lyx TOC. +*/ +body { + font: small sans-serif; + background: #f9f9f9; + color: black; + margin: 0; + padding: 0; +} + +#globalWrapper { + font-size: 115%; + margin: 5px 20px 5px 20px; + padding: 0px; + background: #ffffff; + line-height: 1.5em; + overflow: hidden; +} +a { + text-decoration: none; + color: #0030c0; + background: none; +} +a:visited { + color: #603090; +} +a:active { + color: #ffa000; +} +a:hover { + text-decoration: underline; +} +div.tocindent { + padding: 0 0 0 2em; +} +div.toc { + margin: 0.5em 0; + font-size: 0.95em; +} diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/upload.sh elyxer-1.2.5/forks/jras-elyxer/docs/upload.sh --- elyxer-1.2.3/forks/jras-elyxer/docs/upload.sh 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/upload.sh 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,38 @@ +#!/bin/bash + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Alex 20090315: upload generated documentation to Savannah CVS + +# download current docs +mkdir cvs +cd cvs +#rm -Rf elyxer +#cvs -z3 -d:ext:alexfernandez@cvs.savannah.nongnu.org:/web/elyxer co elyxer +cvs -z3 -d:ext:alexfernandez@cvs.savannah.nongnu.org:/web/elyxer update elyxer +# overwrite with current docs +cp ../*.html elyxer/ +cp ../*.png elyxer/ +cp ../*.css elyxer/ +# remove MathJaX and jsMath (comment if they are updated) +#rm -Rf elyxer/MathJax +#rm -Rf elyxer/jsMath +# commit +cd elyxer +cvs commit -m "Automatic upload" + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/userguide-frameset.html elyxer-1.2.5/forks/jras-elyxer/docs/userguide-frameset.html --- elyxer-1.2.3/forks/jras-elyxer/docs/userguide-frameset.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/userguide-frameset.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,13 @@ + + + + eLyXer User Guide + + + + + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/userguide-toc.html elyxer-1.2.5/forks/jras-elyxer/docs/userguide-toc.html --- elyxer-1.2.3/forks/jras-elyxer/docs/userguide-toc.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/userguide-toc.html 2013-03-10 10:39:37.000000000 +0000 @@ -0,0 +1,180 @@ + + + + + + + + +Converted document + + +
      +
      + + + + + + + +
      + + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/userguide.html elyxer-1.2.5/forks/jras-elyxer/docs/userguide.html --- elyxer-1.2.3/forks/jras-elyxer/docs/userguide.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/userguide.html 2013-03-10 10:39:36.000000000 +0000 @@ -0,0 +1,1776 @@ + + + + + + + + +eLyXer User Guide + + +
      +

      +figure elyxer.png +eLyXer User Guide +

      +

      +Alex Fernández (elyxer@gmail.com) +

      +
      +
      +Table of Contents +
      +
      + + + + + + + +
      + + +
      +

      +1 The Basics +

      +
      +elixir, n: a substance believed to cure all ills[1]. +
      +
      +eLyXer (pronounced elixir) is a LyX to HTML converter. While there are a ton of such projects all over the web, eLyXer has a clear focus on flexibility and elegant output. +
      +
      +eLyXer (including this guide and all accompanying materials) is licensed under the GPL version 3 or, at your option, any later version. See the LICENSE file for details. +
      +
      +Please visit the main page to find out about the latest developments. +
      +

      +1.1 System Requirements +

      +
      +eLyXer requires Python 2.4.x, and should work with versions up to 2.6.y; it will convert documents generated by LyX 1.5.x to 2.0. It has been tested on the most common operating systems: on Mac OS X, Linux and Windows, with and without CygWin. +
      +
      +Resource usage should be quite frugal; eLyXer runs quite happily on my 1st-gen Asus Eee, with its puny Celeron@570MHz and 512 MB of RAM. It should also be fast — the Eee can convert ~200 pages of LyX text in just over 50 seconds. Performance is fairly linear: 200 pages take 10 ×  as long as 20, so there are no scalability problems. Memory usage stays low even when processing large documents, and conversion can be done on the fly (with --lowmem) for even lower memory requirements. +
      +

      +1.2 Installation +

      +
      +This section looks at how to install eLyXer on your system, assuming that Python 2.4 to 2.6 is already there. +
      +

      +Download eLyXer +

      +
      +First you will need to fetch the official distribution file from the download area. Now, there is more than one way to install eLyXe, but all of them start by uncompressing the distributed file to a suitable directory. Just write at the command prompt: +
      +
      +$ tar -xzf elyxer-[version].tar.gz
      +
      +
      +Or for the .zip version: +
      +
      +$ unzip elyxer-[version].zip
      +
      +
      +A directory called elyxer should appear, where the main executable file elyxer.py resides. +
      +

      +Using the Installer +

      +
      +An installer is provided in the root directory, called install.py; it is the recommended way to install eLyXer. To run it just type in a console as root: +
      +
      +# python install.py
      +
      +
      +On Windows you can type (as a regular user): +
      +
      +> python.exe install.py
      +
      +
      +In any case, the script will install eLyXer as a Python script. Now you can check if it was installed successfully: +
      +
      +$ elyxer.py --help
      +
      +
      +A brief help text and the list of command line options should appear. +
      +
      +The installer will also copy existing translation files to your hard drive so that they can be used from within eLyXer for internationalization. +
      +

      +Prepackaged Versions +

      +
      +The easiest way to install eLyXer is if someone has prepackaged it for your system. Some Linux distributions include eLyXer: Debian squeeze and Ubuntu Lucid. Installation is done using apt-get or aptitude, for Debian as root: +
      +
      +# apt-get install elyxer
      +
      +
      +or, for Ubuntu: +
      +
      +$ sudo aptitude install elyxer
      +
      +
      +For both Debian and Ubuntu eLyXer needs to be run as "elyxer": +
      +
      +$ elyxer --help
      +
      +
      +On Windows, the alternate LyX installer includes eLyXer in the default installation. See 1.6↓ for LyX integration. +
      +

      +Manual Installation +

      +
      +If the installer did not work for you, you can manually install it as a module. On Linux go to the elyxer directory and type, as root: +
      +
      +# python setup.py install
      +
      +
      +On Windows just type: +
      +
      +> python.exe setup.py install
      +
      +
      +On Mac OS X you can use sudo to get the necessary permissions: +
      +
      +% sudo python setup.py install
      +
      +
      +Now you can run eLyXer as a Python script: +
      +
      +$ elyxer.py --help
      +
      +
      +The list of command line options should appear. You can also manually copy the file elyxer.py to a directory found in the execution path (for instance, /usr/bin on Linux or c:\windows\system32 on Windows). +
      +

      +1.3 Test Drive +

      +
      +Now you may want to try to convert the user guide: +
      +
      +$ elyxer.py --css lyx.css --title "eLyXer User Guide" docs/userguide.lyx docs/userguide2.html
      +
      +
      +It should generate a working web page identical to the one distributed: +
      +
      +$ diff docs/userguide.html docs/userguide2.html
      +
      +
      +The typical output will contain just the changed lines, which in this case should be only the header with the file creation date. An example is shown on listing 1↓. +
      +
      +
      +
      +
      +7c7
      +< <meta name="create-date" content="2009-09-11"/>
      +---
      +> <meta name="create-date" content="2009-09-12"/> +
      +
      +Algorithm 1 Example of diff output for functionally identical HTML files. +
      + +
      + +
      + +
      +
      +If nothing else appears (i.e. both files are functionally equal) then everything is working fine. If you have bash installed, to test that everything really works fine you can just run the included tests: +
      +
      +$ ./run-tests
      +
      +
      +It will run a number of test and check the results, so you can see if everything is well. You also need to have installed the command-line tool diff to show differences between two files. +
      +

      +1.4 Usage +

      +
      +eLyXer is a standalone command line tool. It can be invoked from the command line as: +
      +
      +$ elyxer.py [options] [source file] [destination file]
      +
      +
      +If the source file is omitted then STDIN is used; likewise, if no destination file is specified eLyXer will output to STDOUT. This allows its use in pipes and other flexible configurations. Some examples: +
      +
      +$ elyxer.py file.lyx file.html
      +
      +
      +converts file.lyx to file.html. Debug messages are shown. +
      +
      +$ cat file.lyx | elyxer.py > file.html
      +
      +
      +converts file.lyx to file.html, as before. This time debug messages are not shown. +
      +
      +$ elyxer.py file.lyx | grep "<blockquote>" | wc
      +
      +
      +counts all blockquote paragraphs. +
      +
      +$ elyxer.py file.lyx | wget --no-check-certificate --spider -nv -F -i -
      +
      +
      +checks all external links in a document recursively. (Local links will appear as unresolved, but they can be ignored.) +
      +

      +1.5 Image Processing +

      +
      +eLyXer does not convert images directly; it uses the ImageMagick package, in particular the convert tool, to create PNG versions of the images embedded in the original LyX documents, and then it inserts links to those PNG images in the resulting HTML pages. If ImageMagick is not installed eLyXer will show an error message and will not try to convert further images. +
      +
      +HTML pages, unlike PDF documents, do not contain images in the document file; rather they contain pointers to image locations on disk. (Fortunately, LyX documents do not contain images either.) eLyXer will generate pages that point to the same locations as the original images, when they are PNG images, or to the converted versions otherwise. Image types like Encapsulated PostScript cannot be used directly from within pages. +
      +
      +Image location is fragile. All images should be placed in the same location (and with the same structure) as the original document; and they should all be referenced relatively to the current document. During conversion from within LyX image locations can be lost, since LyX does not do in-place conversion; instead, LyX copies the original file to a temporary directory, converts the file and then copies everything back to a directory ending in .LyXconv. +
      +

      +1.6 LyX Integration +

      +
      +If you used the eLyXer installer LyX will automatically detect it after reconfiguration. Just make sure that you are running LyX 1.6.5 or later, and click on Tools ▷ Reconfigure. +
      +
      +LyX should be able to detect if eLyXer was installed as a script, or even if it has been installed from a Linux distribution. In any case you can verify that it has been recognized by LyX by opening Tools ▷ Preferences…, going to External formats ▷ Converters, and finding the converter for “LyX -> HTML”. If eLyXer is there, it worked! Now you can convert your documents using View ▷ HTML. Otherwise try to reinstall eLyXer from scratch and then reconfigure LyX. +
      +

      +Installing as a Package or as a Module +

      +
      +Versions of the eLyXer installer prior to 1.2.0 tried to install eLyXer as a module, so it could be run using "python -m elyxer". This option is deprecated since a module called elyxer would collide with a Python package of the same name, and there are plans to install eLyXer as a proper Python package in the future (probably in the 1.3.0 time frame). In the interim eLyXer is installed only as a script called elyxer.py. +
      +
      +LyX (starting with versions 2.0.0 and 1.6.9) has been patched to recognize only the script and disregard the module. +
      +

      +2 Advanced Use +

      +
      +There are some advanced uses for eLyXer if you want to extract the most of it. +
      +

      +2.1 Command Line Options +

      +
      +eLyXer supports a few command line options: +
      +
      +--help: Show command line help. +
      +
      +--quiet: Be quiet and do not output messages (except errors). This way you can avoid the comforting “Parsing line 1000” messages. When STDIN or STDOUT are used (e.g. in a pipeline) --quiet is always enabled. +
      +

      +Advanced Options +

      +
      +--debug: Show debug messages. They may help a developer understand your problem. +
      +
      +--version: Show version number and date. Use to check which version you are actually running. +
      +
      +--lyxformat: Return the highest LyX version that eLyXer understands. This parameter is provided to help with lyx2lyx integration, so that this tool knows if it must convert the file to a lower LyX format. +
      +

      +Options to Control HTML output +

      +
      +--title "title": Change the title of the generated web page. +
      +
      +--css "new.css": Change default CSS. See section 2.2↓: CSS. +
      +
      +--embedcss "file.css": Embed the styles in file.css into the resulting HTML document. See section 2.2↓: CSS. +
      +
      +--html: Generate HTML 4.0 (instead of XHTML). The resulting pages should be easier to import from certain word processors. See section 2.6↓: HTML code. +
      +
      +--unicode: Restore full Unicode output. Right now switches midspaces to medium mathematical spaces. See also section 2.6↓: HTML code. +
      +
      +--iso885915: Generate a document using ISO-8859-1 encoding. Again, see section 2.6↓: HTML code. +
      +
      +--nofooter: Omit the footer message “Document generated by eLyXer” (shown at the bottom). +
      +

      +Options to Control image output +

      +
      +--directory "images_dir": Look for images in the directory specified. +
      +
      +--destdirectory "dest_dir": Converted images will end up into this directory. +
      +
      +--imageformat ".extension": Force the format implied by the extension (e.g. ".jpg" for JPEG) for output images. Use --imageformat "copy" to make images be copied over instead of converted. +
      +
      +--converter "program":Use the given program to convert images. Right now the supported converters are: imagemagick (default), inkscape and lyx itself. With --converter inkscape eLyXer picks Inkscape as the image converter (Inkscape uses some non-standard extensions so it might be needed to convert SVG images to PNG); with --converter lyx the new LyX option lyx -C is used. You can also supply your own converter command line, using $input and $output as variables (note the single quotes): +
      +
      +$ elyxer.py --converter ’lyx -C $input $output’ [source file] [destination file]
      +
      +
      +--noconvert: Use all images in their original location and do not convert anything. Useful when using images which do not convert well, such as SVG files. +
      +

      +Options to Control footnote output +

      +
      +--numberfoot: Number all footnotes using numbers: “[1]”, instead of the default “[A]”. +
      +
      +--symbolfoot: mark footnotes with symbols (*, **, †, ‡…). +
      +
      +--hoverfoot: show footnotes as hovering text. This is the default position. +
      +
      +--marginfoot: show footnotes with numbers instead of letters. +
      +
      +--endfoot: show footnotes at the end of the page. +
      +
      +--supfoot: use superscript for footnote markers. This is the default style. +
      +
      +--alignfoot: use aligned text for footnote markers, instead of superscript. +
      +
      +--footnotes "options": specify several footnotes options at the same time, separated with commas. Available options are: "number", "hover", "margin", "end". See section 2.9↓: Footnotes. +
      +

      +Advanced Options to Control HTML output +

      +
      +--splitpart "depth": Split the resulting webpage at the given depth. See section 2.5↓: Segmenting Pages. +
      +
      +--tocfor "original.html": Generate just a table of contents with links to the original HTML file. See section 2.4↓: TOC. +
      +
      +--target "frame": Add a target attribute to every link in the generated HTML, making all links point to the provided frame. Again, see section 2.4↓: TOC. +
      +
      +--notoclabels: Omit “Chapter”, “Part” and similar labels from the TOC; just output part numbers (and separate using a period). For instance, a chapter that without this option is labeled “Chapter 2: Advanced Use” in the TOC would now become “2. Advanced Use”, as on the PDF. Option adapted from the wish list: 3.2↓. +
      +
      +--lowmem: Activate a low memory mode which does not keep the whole document in memory: conversion is done on the fly. Keep in mind that some features as the TOC will be missing from the generated document. +
      +
      +--numberfoot:Label footnotes using numbers, instead of letters. Useful when bibliographical references are not numbered and therefore cannot be confused with footnotes. +
      +
      +--raw: Generate an HTML page without header or footer. +
      +
      +--mathjax remote: Use the excellent JavaScript library MathJax remotely to pretty-print mathematical equations. See section 2.8↓. +
      +
      +--mathjax "URL": Use the excellent JavaScript library MathJax at the given URL (usually a local URL is used). See also section 2.8↓. +
      +
      +--googlecharts: Use Google Charts to generate images for every formula. Again, see 2.8↓. +
      +
      +--simplemath: Do not generate fancy math structures such as multi-line Unicode brackets or stacked limits. This option is automatically activated when --html is selected; once more see section 2.8↓. +
      +
      +--template "file": Use an HTML template. The raw converted document will be placed where <!--$content--> appears in the template. Available variables: <!--$content-->, <!--$title-->, <!--$author-->, <!--$encoding-->, <!--$css-->, <!--$navigation-->, <!--$year-->, <!--$date-->, <!--$datetime-->, <!--$version-->, <!--$script-->, <!--$mathjax-->. +
      +
      +--copyright: Include a copyright notice at the bottom. +
      +

      +Deprecated Options +

      +
      +--toc: Generate just a table of contents. Use --tocfor instead. +
      +
      +--toctarget "original.html": Generate a table of contents with links to the original HTML file. Use --tocfor instead. +
      +
      +--nocopy: No effect since the copyright notice is now optional, maintained for backwards compatibility. +
      +
      +When an option accepts an argument it can be added after a space as --target "frame", or with an equals sign as in --target="frame". The quotes are optional and can be useful if your arguments include e.g. spaces. +
      +

      +Adding Options In LyX +

      +
      +To add one of these options so that it is used from within LyX, you have to modify the converter line. To this effect open Tools ▷ Preferences…, go to External formats ▷ Converters, find the converter for “LyX -> HTML” and edit the converter line. It should read something like this: +
      +
      +elyxer.py --directory $$r $$i $$o
      +
      +
      +If you want to generate pure HTML instead of XHTML, change the line to: +
      +
      +elyxer.py --html --directory $$r $$i $$o
      +
      +
      +And so on. Figure 1 shows what to do to add the --html option: after editing the line and adding the new option, click on “Modify” and then “Save” or “Apply” the changes. +You should never remove the $$i $$o at the end, since it is what tells eLyXer where to find the input and output files. + + +
      +
      +
      +
      +
      +figure converters.png + +
      +
      +Figure 1 eLyXer converter in LyX 1.6.5. +
      + +
      + +
      + +
      +
      +LyX 1.6.5 supports a new “extra flag” line; however, at this moment it does not work with eLyXer. +
      +

      +2.2 CSS +

      +
      +HTML output, as generated, can fall short in certain situations. Some CSS wizardry can go a long way to customize eLyXer. +
      +
      +eLyXer tags most elements with the type so you can later modify them using a CSS. The default HTML header is similar to listing 2↓, so the default remote CSS file is used. +
      +
      +
      +
      +
      +<head>
      +[...]
      +<link rel="stylesheet" href="http://elyxer.nongnu.org/lyx.css" type="text/css" media="all"/>
      +<title>Your title here</title>
      +</head> +
      +
      +Algorithm 2 CSS link automatically added to HTML +
      + +
      + +
      + +
      +
      +This sample CSS file is published on nongnu.org and distributed along with the scripts, docs/lyx.css. (You may have found that your document shows minor changes in its appearance with time — this is the reason. The main author regularly publishes a new, updated version of lyx.css on nongnu.org, and all documents using it automatically appear with the changes. Backwards compatibility is maintained as much as possible.) +
      +
      +To give your document a customized appearance (or for pages to be accessible offline) you probably will want to use your own CSS file; to use it first copy it to the directory where your document resides (e.g. renaming it to custom.css), and customize as needed. Then run elyxer.py with the following option: +
      +
      +$ elyxer.py --css=custom.css document.lyx page.html
      +
      +
      +This will make the generated page.html use your custom.css file. The ‘=’ sign between the constant ‘--css’ and the name of the CSS file is optional. More than one --css option can be added if you want several CSS files to be used in the header. +
      +
      +Sometimes the styles in a CSS are needed in the HTML document (for offline viewing, or to distribute as stand-alone pages). For these uses there is the option --embedcss: the styles contained in the CSS file passed as an argument will be embedded in the resulting HTML document. For instance: +
      +
      +$ elyxer.py --embedcss custom.css document.lyx page.html
      +
      +
      +This command generates a document page.html where the styles in custom.css are embedded. The CSS to embed must be a file, not a remote URL. Listing 3↓ shows the resulting HTML header for a test CSS with just one style, div.Standard. Note that the remote CSS is still added by default; to avoid it just add an option with an empty CSS file, --css="". +
      +
      +
      +
      +
      +<head>
      +[...]
      +<head>
      +<link rel="stylesheet" href="http://elyxer.nongnu.org/lyx.css" type="text/css" media="all"/>
      +<style type="text/css">
      +<!--
      +/* Embedded CSS */
      +div.Standard {
      +  background: #909090;
      +}
      +-->
      +</style>
      +<title>Your title here</title>
      +</head> +
      +
      +Algorithm 3 CSS embedded into the HTML +
      + +
      + +
      + +
      +
      +As with the --css option, several --embedcss options can be added to embed more than one file. +
      +
      +The CSS file for eLyXer uses some CSS2 features for math structures (fractions, arrays). This makes the output incompatible with older browsers; it requires Microsoft Internet Explorer 7, Firefox 3, Safari 3 or Chrome 1. Check the Math Showcase to see if your browser can render eLyXer output correctly. +
      +

      +2.3 Title +

      +
      +By default the generated web pages have the title “Converted Document”. If a PDF title is found then it is used instead. The proper LyX title (a paragraph of type “Title” embedded in the text) will also be used if found. But when --lowmem is in use eLyXer does not try to get the proper title, since it may be found in the middle of the document or not be present at all; scanning for it would mean doing two passes, one to look for the title in all the document and another to output the web page, and --lowmem implies on-the-fly conversion to save memory. +
      +
      +You can change the title of the generated web page with the --title option: +
      +
      +$ elyxer.py --title "My Beautiful Document" document.lyx page.html
      +
      +

      +2.4 Table Of Contents +

      +
      +A table of contents (or TOC) can be generated for every converted LyX document. You can optionally also add a target frame to every link. The trick is to combine both options to generate a TOC that links to the original document on a different frame. For example, if the original page is called page.html and you generated it with this command: +
      +
      +$ elyxer.py document.lyx page.html
      +
      +
      +you can generate the TOC linking to this page, and at the same time point it to frame contents: +
      +
      +$ elyxer.py --tocfor page.html --target contents document.lyx page-toc.html
      +
      +
      +Then you can put it all together with a simple frameset generated manually. Just remember to place the original document in the frame called contents. +
      +
      +
      +
      +
      +<html>
      +  <frameset cols="30%,70%">
      +    <frame name="toc" src="page-toc.html" />
      +    <frame name="contents" src="page.html" />
      +  </frameset>
      +</html> +
      +
      +Algorithm 4 An example frameset for TOC navegation +
      + +
      + +
      + +
      +
      +TOC generation accepts the same options as normal document conversion. For example, if you follow these instructions literally you will notice that the TOC has very wide margins and looks a bit weird; that is because it is using the default CSS. A special CSS file for TOC files is provided in docs/toc.css, so better results should be obtained with the --css option: +
      +
      +$ elyxer.py --tocfor page.html --css docs/toc.css --target contents document.lyx page-toc.html
      +
      +
      +With a little bit of practice you will be able to generate useful (and nice looking) TOC files. You can see an example for the user guide (if you are not already looking at it). +
      +

      +2.5 Segmenting Pages +

      +
      +Quite often you don’t want a huge monolithic page, but a set of linked pages. To do so you can use the --splitpart option, specifying the level at which eLyXer should split pages. For instance: +
      +
      +$ elyxer.py --splitpart 1 document.lyx output.html
      +
      +
      +will split document.lyx into pages at level 1, using output.html as the root page. Each page will get a number that starts with output and ends with .html, with a suffix that depends on the page — output-2.html will correspond to the second split part. +
      +
      +The level corresponding to 1 depends on the document class: books will be split at chapters, but articles will get a section per page. And so on with lower levels. +
      +

      +2.6 HTML Code +

      +
      +The HTML code generated is technically XHTML Transitional, version 1.0 [2], using UTF-8 encoding. Some programs have (in this day and age) trouble importing XHTML, notably some popular word processors. To work around this problem and provide more flexible output in general you can output HTML 4.0: +
      +
      +$ elyxer.py --html document.lyx page-to-import.html
      +
      +
      +Again, technically the code generated is HTML 4.01 Transitional [3] using UTF-8 encoding. Both versions should pass the W3C tests [4]. If your particular web page doesn’t pass the tests, then it is a bug and it will be treated as such. +
      +
      +The --html option also activates the --simplemath option; see section 2.8↓: Math for details. +
      +

      +Character Encodings +

      +
      +For better browser compatibility, medium mathematical spaces are substituted in the output with midspaces — improving the output for some popular browsers. If you want your mathematical spaces back, just use the --unicode option: +
      +
      +$ elyxer.py --unicode document.lyx page-to-import.html
      +
      +
      +Check out the Math Showcase with Unicode to see the results. In the future other non-Unicode substitutions might be used. +
      +
      +In case you want to use the ISO-8859-15 encoding in your generated document, you can add the --iso885915 option: +
      +
      +$ elyxer.py --iso885915 document.lyx page.html
      +
      +
      +This will make eLyXer output a document with all non-ASCII characters encoded as &nbsp;, &#x2005; and so on. This encoding is similar to ISO-8859-1, also called Latin-1, but including the Euro sign. The Math Showcase (ISO-8859-15 edition) has been generated using this option. +
      +
      +Both encoding options can be combined with --html at will. +
      +

      +2.7 Internationalization +

      +
      +eLyXer is distributed along with a few translation files. They are automatically regenerated every time make is run, and reside in the folder po/. Internationalization is done using GNU gettext, so every locale is identified by a two-letter code (such as “en” for English and “es” for Spanish). There are two kinds of files: the text .po file (which can be found in po/my.po for locale “my”), and the binary .mo file (found in po/my/elyxer.po). +
      +
      +For internationalization to work properly, Linux distributors should take all binary .mo files and place them in the directory corresponding to locale files, which we will call $localedir. As the Python gettext page explains, this is distribution-dependent: for example on Debian $localedir is /usr/share/locale, so for locale “es” the correct route would be +
      +
      +/usr/share/locale/es/LC_MESSAGES/elyxer.mo
      +
      +
      +Windows distributors on the other hand should place files in %PYTHONHOME%\share\locale, for example for locale “es” on a machine where Python is in C:\python: +
      +
      +C:\python\share\locale\es\LC_MESSAGES\elyxer.mo
      +
      +
      +To generate a new translation file (we will use “my” as an example locale here, corresponding to Burmese): you need to have the GNU gettext package installed. Then go to the directory where elyxer.pot resides: +
      +
      +$ cd src/conf
      +
      +
      +and generate a .po file for your locale: +
      +
      +$ msginit --output-file=my.po --locale=my
      +
      +
      +Then move the file to the po/ directory: +
      +
      +$ mv my.po ../../po/
      +
      +
      +and start translating it to Burmese! Once you are done run make from the root directory: +
      +
      +$ ./make
      +
      +
      +and it will generate the file po/my/elyxer.mo. Finally, place this file in +
      +
      +$localedir/my/LC_MESSAGES/elyxer.mo
      +
      +
      +and you are done. +
      +

      +2.8 Math +

      +
      +Math equations are an important part of what takes LyX apart from other editors, since it supports the full LaTeX feature set — that is, about everything under the sun. Unfortunately, math support is hard to get right. Many developers are focusing on MathML, but at the time of this writing (Q2 2010) support on some common browsers is still missing. +
      +
      +eLyXer follows its usual minimalistic approach and doesn’t try to be everything to everybody — instead, it supports out of the box a set of usual constructs (fraction, square root) and tries to simulate others (binomial, overbrace). See the Math showcase for yourself and learn what eLyXer supports and what not. +
      +
      +For more sophisticated math equations there are a couple of advanced features. +
      +

      +MathJax +

      +
      +The first option is to use MathJax, which is as simple as using the option --mathjax: +
      +
      +$ elyxer.py --mathjax remote math.lyx math-mathjax-remote.html
      +
      +
      +The remote argument tells MathJax to access the MathJax library remotely on the MathJax CDN. (You should always comply with their terms of service.) See the Math showcase (MathJax remote edition) to check the results. +
      +
      +In case you need to go outside the terms of service, or you want the content to be accessible offline, you can always use a local copy of MathJax. Just use the URL of the repository as an argument to the --mathjax option: +
      +
      +$ elyxer.py --mathjax MathJax/ math.lyx math-mathjax-local.html
      +
      +
      +This way eLyXer uses the given URL (in the example MathJax/) to load MathJax from and set it up. Although some code needs to be hosted on the same site as the pages, MathJax uses a feature called web-fonts which can be downloaded from a public server; this is quite easier to host. See the Math showcase (MathJax edition) to see how MathJax fares with eLyXer. +
      +
      +Something to note is that MathJax is a JavaScript library; all rendering is done client-side by the user’s browser. This has quite a few advantages: +
      +
        +
      • +Math processing on the server is quite light; equations are basically surrounded by a special tag and left in TeX form. +
      • +
      • +For developers: integration of these libraries is very easy. It took just a few days to integrate both libraries with eLyXer. +
      • +
      • +MathJax is improving all the time thanks to the efforts of Davide P. Cervone and the rest of the developer team; eLyXer and its users reap the benefits readily. +
      • +
      • +The client browser already knows its abilities, and can choose the rendering method it considers to be the best. MathJax can even choose between MathML and HTML+CSS at page rendering time, showing MathML on fancier browsers and simpler HTML where it is not available. +
      • + +
      +
      +It also brings some disadvantages: +
      +
        +
      • +With the remote argument, JavaScript code resides at a remote server and your users will need online access to view the maths. +
      • +
      • +If MathJax is accessed locally you need to also host the code for MathJax. (Web fonts used in MathJax can at least be hosted elsewhere, so publishers do not need to also host the fonts package, but this hasn’t still been used in eLyXer.) +
      • +
      • +And of course it takes some time to render everything on the client, which can degrade the user experience on older machines. +
      • + +
      +
      +Publishers should carefully consider pros and cons before deciding what to use. +
      +

      +Google Charts +

      +
      +Google Charts is an online service which generates images that contain charts and other stuff; it can also generate TeX formulas. eLyXer can use it using the option --googlecharts: +
      +
      +$ elyxer.py --googlecharts math.lyx math-googlecharts.html
      +
      +
      +There are some limitations to Google Charts: no macros, formulas cannot exceed 200 characters, and the supported command set is limited (commands in text mode, for instance, are out of bounds). Also, generated images can be hard to align vertically — by default they are middle-aligned, but some small characters or superscripted formulas can look weird. But this option can be a quick&dirty way of showing math for older or unsupported browsers. +
      +

      +Brackets and Limits +

      +
      +Fancy math structures are generated by default: arrays and binomials are surrounded by multi-line Unicode brackets, limits in display mode are stacked above / below the symbol, and so on. When the option --simplemath is used eLyXer avoids such structures and just outputs enlarged regular symbols. It is also included in the --html option. +
      +
      +Check out the Math showcase (HTML edition) to see the results. +
      +

      +2.9 Footnotes +

      +
      +Footnote generation is surprisingly hard to get right in an HTML document. eLyXer has a fairly complete set of command line options to customize how footnotes are generated. Here we will use the aggregated option --footnotes "options" which can be used to specify any combination, but they can be turned on independently using --…foot. For instance: --footnotes number,margin is equivalent to --numberfoot --marginfoot. +
      +

      +Markers +

      +
      +The footnote is attached to a point of the text (the referring text) which is usually marked by a bit of text. The default behavior for the marker is to use a superscript letter surrounded by square brackets, in blue: [A]. The text can be changed to aligned text with --footnotes align: [A], so markers are not mistaken with other superscript constructs such as exponents (like ea). +
      +
      +Markers can also be converted to numbers using --footnotes number: [1]. Or, they can be switched over to symbols using --footnotes symbol: *. Available symbols are rotated from this sequence: * ** † ‡ § §§ ¶ ¶¶ # ##. All options can be combined. For instance, symbol markers look best when shown aligned; --footnotes align,symbol will show aligned symbolic markers such as * or . +
      +

      +Position +

      +
      +Footnotes are supposed to appear at the foot of the page, but that is not always possible or practical in web pages. Huge pages make scrolling up and down quite uncomfortable, and remove the immediacy of having the note in the same page as the referring text. +
      +
      +There are a few alternatives: use the margin, show hovering text, or link to the note at the bottom of the page. eLyXer can use all three. --footnotes margin will place the notes at the margin, just as margin notes but with the addition of the footnote marker. While --footnotes hover will show hovering text when the mouse is placed on the marker; this is the default behavior. Note that hovering notes are converted into margin notes when printing. +
      +
      +When footnotes are shown at the end of the page with --footnotes end, footnote markers turn into links. The actual footnote at the end then contains a link back to the marker. +
      +
      +The most interesting part is that these three options can be combined at will: --footnotes margin,hover,end will show footnotes at the three possible locations. The most practical combination is probably --footnotes hover,end, which will show notes as hovering text and also at the end of the page. Note however that in this case notes will be printed twice (at the margin instead of hovering and at the end). +
      +

      +3 Work in Progress +

      +
      +As you can see eLyXer is a mature and tried package, but it has some rough edges. +
      +

      +3.1 Known Issues +

      +
      +The following issues (including bugs and missing features) are acknowledged. Some of them should be solved soon; others may take longer. +
      +
        +
      1. +On Mac OS X the output of a message with Unicode characters may cause an error. Workaround: run elyxer.py with the --quiet option. +
      2. +
      3. +Some phonetic alphabet symbols are not well supported — if generated with LyX they only appear in a different color: [sample]. +
      4. +
      5. +Multi-column layouts are lost. This one is almost impossible to get right in CSS, so there are no plans to even try. +
      6. +
      7. +Many BibTeX styles are missing. (They are quite trivial to add though.) +
      8. +
      9. +ERT (bare TeX code) is ignored. +
      10. +
      11. +Many AMS environments (like alignat, gather…) are not working or look strange — some non-AMS environments too. +
      12. +
      13. +Images are never scaled above their nominal resolution. This is seldom needed if at all, so there are no plans to change it; if people really need the feature just let the author know so it can be added as an option. +
      14. + +
      +

      +3.2 Wish List +

      +
      +The following features have been requested by users; specific people are referenced by a couple of initials so they can recognize themselves while keeping some anonymity. (If you prefer that your initials do not to appear here at all just let me know.) +
      +
      +Queued features will be added at the next big release — the priority for each feature will be set by the number of users requesting it and date requested. Pending features need some assessment. Those marked as too complex have been evaluated as requiring too much work, but the decision might be reversed if there are enough people interested or a simple way to implement them is found. Once done, features are marked with the first release where they appear. +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +Feature + +Date + +Users + +Status +
      +Understand \setcounter{section}{1} + +2010-05-15 + +JB + +1.1.0 +
      +Option to turn off title prefixes in TOC + +2010-07-10 + +YG + +1.1.0 +
      +Use BibLaTeX with eLyXer + +2010-09-14 + +PJ, WE + +Pending +
      +Render change tracking: "Show changes in output" + +2010-09-18 + +YG + +1.1.0 +
      +Option for footnotes at the margin + +2010-09-21 + +A + +1.1.0 +
      +Output SVG as <img> tags (20↓) + +2010-09-22 + +YG + +Pending +
      +EPUB output format (19↓) + +2010-09-23 + +MJ, MG + +Too complex +
      +Option for footnotes at the end of each section + +2010-09-23 + +MJ + +1.1.0 +
      +Add more controls for image conversion (21↓) + +2010-10-02 + +WE + +1.1.0 +
      +Support for format 401 (Insert Horizontal Line) + +2010-10-06 + +US + +1.1.2 +
      +Parse contents of ERTs + +2010-10-06 + +US, JW + +1.2.0 +
      +Correct scaling of tables with relative sizes (e.g. %col) + +2010-10-09 + +US + +Pending +
      +BibTeX: parse math formulas inside BibTeX files + +2010-10-16 + +JA + +1.1.1 +
      +BibTeX: display \url{} as an URL + +2010-10-16 + +JA + +1.1.1 +
      +Do not label bibliography items in comments + +2010-10-21 + +JA + +Pending +
      +Unit tests should warn if ImageMagick not installed + +2010-10-24 + +JA + +Pending +
      +Unit tests should run fine without PNG conversion tools + +2010-10-30 + +JA + +Pending +
      +Option --imageformat copy to avoid converting images + +2010-11-12 + +JD + +1.1.1 +
      +Option to embed the CSS in the HTML file22↓ + +2010-11-23 + +GM, JA + +1.1.1 +
      +Display sub- and superscript aligned vertically (as in integrals) + +2010-11-23 + +GM + +1.1.1 +
      +Use Unicode large characters for sums, integrals, matrices… + +2010-12-07 + +GM + +1.1.2 +
      +Do not number captions in code listings + +2010-12-08 + +DC + +1.2.0 +
      +Support brushes for SyntaxHighlighter + +2010-12-10 + +DC + +Pending +
      +Generate formula images using Google Charts + +2011-01-07 + +ET + +1.2.1 +
      +Output reference arrows as CSS pseudo-elements + +2011-01-12 + +GM + +Pending +
      +Include part names in --splitpart navigation header + +2011-01-15 + +AJ + +1.2.1 +
      +Merge options --toc and --toctarget into --tocfor + +2010-01-17 + +JA + +1.2.1 +
      +Make --splitpart and --tocfor work together + +2010-01-17 + +JA, TP + +1.2.1 +
      +Generate named references (equivalent to \nameref) + +2011-01-19 + +TP + +1.2.1 +
      +Do not generate entries when index or nomenclature are missing + +2011-01-19 + +TP + +Queued +
      +Do not output unknown commands in red except in --debug + +2011-02-22 + +JA + +Queued +
      +Output equations as images + +2011-05-31 + +GK + +Pending +
      +Parse modules for custom Flex CharStyles + +2011-06-08 + +MG + +Pending +
      +Convert several files with a single command + +2011-06-01 + +PF + +Pending +
      +Export slides as HTML5 presentation + +2011-06-28 + +RK + +Pending +
      +Add an option to remove navigation bars + +2011-06-29 + +AH + +Pending +
      +Support for External Material: PDF, Date + +2011-10-22 + +MI + +Pending +
      + +
      +
      +Some features require further explanations. +
      +

      +EPUB output format +

      +
      +The EPUB management package calibre does not output valid EPUB documents when converted from eLyXer HTML files, at least according to the Threepress validator. +
      +
      +This is a complex feature request; calibre does minimal formatting in its EPUB conversion, so making it generate valid EPUB documents requires changing deeply how eLyXer outputs XHTML. Lots of help would be needed to get this working. +
      +
      +That said, EPUB readers are often much less strict than the official format and they readily accept eLyXer output. Just convert your LyX document to HTML using eLyXer, and then import the resulting HTML document into your EPUB reader. Let us know how it goes for you. +
      +

      +Output SVG as <img> tags +

      +
      +This feature would be most welcome from the part of the author. Unfortunately, Firefox alone from the major browsers refuses to render <img> tags correctly for SVG. According to bug #276431, this was fixed on 2010-09-08, so the next version should do the right thing; at that point this feature will be queued for inclusion. +
      +
      +You can check out how your browser does with SVG images with this SVG test page. +
      +

      +More controls for image conversion +

      +
      +eLyXer uses ImageMagick to convert images. Some images (in EPS format, for example) do have blank borders, or they come in varied sizes. It would be nice to remove blank borders and have some kind of unified resolution in the conversion, which would be passed to ImageMagick. +
      +
      +As of 1.1.0, the improvements include using ps:use-cropbox=true in ImageMagick for PostScript and EPS images. Unified resolution has not been added as it might collide with picture density, but suggestions are welcome. +
      +

      +CSS controls +

      +
      +Proposed by JRAS on the elyxer-users mailing list, the following is a direct quote of his message. +
      +
      +“[…]A mixed solution for CSS styles: +
      +
        +
      1. +The essential minimum css for math formatting (a compacted version of a math.css subset) included directly inside HTML head. +
      2. +
      3. +Then a call to download the on-line full CSS, that can repeat the minimum already included math.css (from item 1) plus some other styles. The default can be changed by --css command line option. +
      4. +
      5. +A new option (--addcss) to add another CSS defined by the user. For example, to only redefine some styles from the default, etc. +
      6. + +
      +
      +The styles should be included in that order (using the "cascading" property). Item 1 is fixed in every HTML file. Item 2 is always added and by default pointing to the eLyXer on-line css, but it can be changed by option --css to another url or file. Item 3 is optional and its url would be added after the other two items, only if the --addcss option was used in conversion.” +
      +
      +As of 1.1.1, an option --embedcss has been added which allows embedding one or more custom CSS files into the resulting HTML document. Also, --css can be repeated as many times as desired to use several CSS files. +
      +

      +3.3 Contact Information +

      +
      +If your problem does not appear in the above list, please let the author know; you can find him at elyxer@gmail.com. In the words of Rich Talley: “the tool’s author really likes getting challenging documents and making eLyXer work with them”. You can send your sample documents and we will try to make eLyXer convert them acceptably. Any documents sent will be treated with the utmost confidentiality. +
      +
      +You can also join the mailing list to discuss any information related to eLyXer. The author monitors the official LyX lists for mentions of eLyXer. Bugs can also be reported at the Savannah page. +
      +

      +3.4 Extending eLyXer +

      +
      +eLyXer should now support most LyX features; but sometimes it will ignore a command, sometimes it will signal it, and it might even refuse to work with certain documents. What can you do if eLyXer does not work with your LyX file? Worry not! Its flexible approach to processing allows anyone to write support for the missing commands. +
      +
      +eLyXer is written in Python so that it does not need to be compiled; its code is interpreted on the fly. See the accompanying developer guide to learn how to extend eLyXer for your own purposes. If you know how to program in Python it should not be difficult to support other LyX features. If you don’t your best bet is to ask the author. +
      +

      +4 FAQ +

      +
      +Q: What versions of LyX are supported? +
      +
      +A: The tool should work with all LyX versions from 1.5.5 to the latest and greatest. It has been tested on Linux, Mac OS X and Windows. +
      +
      +Q: There are indeed a ton of similar projects over the web. Why add another one? +
      +
      +A: The four tools supported by LyX (tex4ht, hevea, tth and latex2html) gave inferior results in 2009, and were quite inflexible. The author found the need for a good converter, while at the same time acknowledging the difficulty of the problem. +
      +
      +Q: Speaking of that: why build a LyX to HTML converter, instead of a more generic LaTeX to HTML converter? +
      +
      +A: The problem space is quite simplified, and therefore progress is much faster. To make it even easier eLyXer has historically centered on the subset of LyX functionality that is useful to most LyX users, leaving the rest for a later stage. Nowadays eLyXer aims to support the full LyX feature set. +
      +
      +Q: What can we expect from the tool in the future? +
      +
      +A: eLyXer should fulfill the needs of 99% of LyX users in the short term. It has also learned a couple of tricks of its own such as page segmenting. Eventually it could be distributed along with LyX as part of the standard installer. +
      +
      +Q: Why did you leave out my favorite feature <insert random LyX command here>? +
      +
      +A: In short, because nobody asked for it. Every feature which has been requested (either to me personally or to the list) has been tended to, unless it was too far out or I forgot about it. At this point of development every missing LyX feature will be considered a high priority item for the next version, if at all possible to implement. +
      +
      +Q: My document changed its appearance without my intervention. Was it black magic, elves or what? +
      +
      +A: It probably uses the online CSS file, which is regularly updated. See section 2.2↑ for details. +
      +
      +Q: Why use an online CSS, instead of placing the CSS file in the same directory as the converted file? +
      +
      +A: There were pros and cons. An online CSS resource allowed me to update it for everyone at the same time, but might make it more difficult for people without an internet connection; local CSS files are more flexible but can also be confusing to novice users. In the end the online solution was preferred, with the --css option as a fallback. +
      +
      +Q: My MathJax pages are not rendering correctly; equations are silently ignored. +
      +
      +A: Check that MathJax is installed on the same server as your pages; for security reasons the browser’s “same-origin” policy mandates that JavaScript can only be loaded from the same site as the original page. Also make sure that JavaScript is enabled on the browser. +
      +
      +Q: How can I disable hovering notes? Isn’t there a --nohover option? +
      +
      +A: It can be done using --footnotes margin. This will disable hovering text but keep footnotes in the margin. +
      +
      +Q: I found a bug, what should I do? +
      +
      +A: Just send it to the author at elyxer@gmail.com. You can also report it to the Savannah interface. +
      +

      +References +

      +

      +[1] WordReference.com: “definition of elixir”, accessed March 2009. http://www.wordreference.com/definition/elixir +

      +

      +[2] W3C: “XHTML™ 1.0 The Extensible HyperText Markup Language (Second Edition)”, revised 1 August 2002. http://www.w3.org/TR/xhtml1/ +

      +

      +[3] W3C: “HTML 4.01 Specification”, 24 December 1999. http://www.w3.org/TR/REC-html40/ +

      +

      +[4] W3C: “Markup Validation Service”, accessed March 2009. http://validator.w3.org/ +

      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/docs/userguide.lyx elyxer-1.2.5/forks/jras-elyxer/docs/userguide.lyx --- elyxer-1.2.3/forks/jras-elyxer/docs/userguide.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/docs/userguide.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,5742 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2011 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +\begin_inset Graphics + filename elyxer.svg + lyxscale 50 + +\end_inset + +eLyXer User Guide +\end_layout + +\begin_layout Author +Alex Fernández (elyxer@gmail.com) +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Section +The Basics +\end_layout + +\begin_layout Quotation + +\emph on +elixir, n: a substance believed to cure all ills +\begin_inset CommandInset citation +LatexCommand cite +key "wordreference-elixir" + +\end_inset + +. +\end_layout + +\begin_layout Standard +eLyXer (pronounced +\emph on +elixir +\emph default +) is a LyX to HTML converter. + While there are a ton of such projects all over the web, eLyXer has a clear + focus on flexibility and elegant output. +\end_layout + +\begin_layout Standard +eLyXer (including this guide and all accompanying materials) is licensed + under the +\begin_inset CommandInset href +LatexCommand href +name "GPL version 3" +target "http://www.gnu.org/licenses/gpl-3.0-standalone.html" + +\end_inset + + or, at your option, any later version. + See the +\family typewriter +LICENSE +\family default + file for details. +\end_layout + +\begin_layout Standard +Please visit the +\begin_inset CommandInset href +LatexCommand href +name "main page" +target "index.html" + +\end_inset + + to find out about the latest developments. +\end_layout + +\begin_layout Subsection +System Requirements +\end_layout + +\begin_layout Standard +eLyXer requires Python 2.4. +\begin_inset Formula $x$ +\end_inset + +, and should work with versions up to 2.6. +\begin_inset Formula $y$ +\end_inset + +; it will convert documents generated by LyX 1.5. +\begin_inset Formula $x$ +\end_inset + + to 2.0. + It has been tested on the most common operating systems: on Mac OS X, Linux + and Windows, with and without CygWin. +\end_layout + +\begin_layout Standard +Resource usage should be quite frugal; eLyXer runs quite happily on my 1st-gen + Asus Eee, with its puny Celeron@570MHz and 512 MB of RAM. + It should also be fast -- the Eee can convert ~200 pages of LyX text in + just over 50 seconds. + Performance is fairly linear: 200 pages take +\begin_inset Formula $10\times$ +\end_inset + + as long as 20, so there are no scalability problems. + Memory usage stays low even when processing large documents, and conversion + can be done on the fly (with +\family typewriter +--lowmem +\family default +) for even lower memory requirements. +\end_layout + +\begin_layout Subsection +Installation +\end_layout + +\begin_layout Standard +This section looks at how to install eLyXer on your system, assuming that + Python 2.4 to 2.6 is already there. +\end_layout + +\begin_layout Subsubsection* +Download eLyXer +\end_layout + +\begin_layout Standard +First you will need to fetch the official distribution file from the +\begin_inset CommandInset href +LatexCommand href +name "download area" +target "https://savannah.nongnu.org/files/?group=elyxer" + +\end_inset + +. + Now, there is more than one way to install eLyXe, but all of them start + by uncompressing the distributed file to a suitable directory. + Just write at the command prompt: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + tar -xzf elyxer- +\emph on +[version] +\emph default +.tar.gz +\end_layout + +\begin_layout Standard +Or for the +\family typewriter +.zip +\family default + version: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + unzip elyxer- +\emph on +[version] +\emph default +.zip +\end_layout + +\begin_layout Standard +A directory called +\family typewriter +elyxer +\family default + should appear, where the main executable file +\family typewriter +elyxer.py +\family default + resides. +\end_layout + +\begin_layout Subsubsection* +Using the Installer +\end_layout + +\begin_layout Standard +An installer is provided in the root directory, called +\family typewriter +install.py +\family default +; it is the recommended way to install eLyXer. + To run it just type in a console as root: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +# +\color inherit + python install.py +\end_layout + +\begin_layout Standard +On Windows you can type (as a regular user): +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +> +\color inherit + python.exe install.py +\end_layout + +\begin_layout Standard +In any case, the script will install eLyXer as a Python script. + Now you can check if it was installed successfully: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --help +\end_layout + +\begin_layout Standard +A brief help text and the list of command line options should appear. +\end_layout + +\begin_layout Standard +The installer will also copy existing translation files to your hard drive + so that they can be used from within eLyXer for internationalization. +\end_layout + +\begin_layout Subsubsection* +Prepackaged Versions +\end_layout + +\begin_layout Standard +The easiest way to install eLyXer is if someone has prepackaged it for your + system. + Some Linux distributions include eLyXer: +\begin_inset CommandInset href +LatexCommand href +name "Debian squeeze" +target "http://packages.debian.org/squeeze/elyxer" + +\end_inset + + and +\begin_inset CommandInset href +LatexCommand href +name "Ubuntu Lucid" +target "http://packages.ubuntu.com/lucid/elyxer" + +\end_inset + +. + Installation is done using apt-get or aptitude, for Debian as root: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +# +\color inherit + apt-get install elyxer +\end_layout + +\begin_layout Standard +or, for Ubuntu: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + sudo aptitude install elyxer +\end_layout + +\begin_layout Standard +For both Debian and Ubuntu eLyXer needs to be run as +\family typewriter +"elyxer" +\family default +: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer --help +\end_layout + +\begin_layout Standard +On Windows, the +\begin_inset CommandInset href +LatexCommand href +name "alternate LyX installer" +target "http://wiki.lyx.org/Windows/LyXWinInstaller" + +\end_inset + + includes eLyXer in the default installation. + See +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:LyX-Integration" + +\end_inset + + for LyX integration. +\end_layout + +\begin_layout Subsubsection* +Manual Installation +\end_layout + +\begin_layout Standard +If the installer did not work for you, you can manually install it as a + module. + On Linux go to the elyxer directory and type, as root: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +# +\color inherit + python setup.py install +\end_layout + +\begin_layout Standard +On Windows just type: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +> +\color inherit + python.exe setup.py install +\end_layout + +\begin_layout Standard +On Mac OS X you can use sudo to get the necessary permissions: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +% +\color inherit + sudo python setup.py install +\end_layout + +\begin_layout Standard +Now you can run eLyXer as a Python script: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --help +\end_layout + +\begin_layout Standard +The list of command line options should appear. + You can also manually copy the file +\family typewriter +elyxer.py +\family default + to a directory found in the execution path (for instance, +\family typewriter +/usr/bin +\family default + on Linux or +\family typewriter +c: +\backslash +windows +\backslash +system32 +\family default + on Windows). +\end_layout + +\begin_layout Subsection +Test Drive +\end_layout + +\begin_layout Standard +Now you may want to try to convert the user guide: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --css lyx.css --title "eLyXer User Guide" docs/userguide.lyx docs/usergu +ide2.html +\end_layout + +\begin_layout Standard +It should generate a working web page identical to the one distributed: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + diff docs/userguide.html docs/userguide2.html +\end_layout + +\begin_layout Standard +The typical output will contain just the changed lines, which in this case + should be only the header with the file creation date. + An example is shown on listing +\begin_inset CommandInset ref +LatexCommand ref +reference "alg:diff" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Quotation + +\family typewriter +7c7 +\end_layout + +\begin_layout Quotation + +\family typewriter +< +\end_layout + +\begin_layout Quotation + +\family typewriter +--- +\end_layout + +\begin_layout Quotation + +\family typewriter +> +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "alg:diff" + +\end_inset + +Example of +\family typewriter +diff +\family default + output for functionally identical HTML files. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +If nothing else appears (i.e. + both files are functionally equal) then everything is working fine. + If you have +\family typewriter +bash +\family default + installed, to test that everything +\emph on +really +\emph default + works fine you can just run the included tests: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + ./run-tests +\end_layout + +\begin_layout Standard +It will run a number of test and check the results, so you can see if everything + is well. + You also need to have installed the command-line tool +\family typewriter +diff +\family default + to show differences between two files. +\end_layout + +\begin_layout Subsection +Usage +\end_layout + +\begin_layout Standard +eLyXer is a standalone command line tool. + It can be invoked from the command line as: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py [options] [source file] [destination file] +\end_layout + +\begin_layout Standard +If the source file is omitted then +\family typewriter +STDIN +\family default + is used; likewise, if no destination file is specified eLyXer will output + to +\family typewriter +STDOUT +\family default +. + This allows its use in pipes and other flexible configurations. + Some examples: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py file.lyx file.html +\end_layout + +\begin_layout Standard +converts +\family typewriter +file.lyx +\family default + to +\family typewriter +file.html +\family default +. + Debug messages are shown. +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + cat file.lyx | elyxer.py > file.html +\end_layout + +\begin_layout Standard +converts +\family typewriter +file.lyx +\family default + to +\family typewriter +file.html +\family default +, as before. + This time debug messages are not shown. +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py file.lyx | grep "
      " | wc +\end_layout + +\begin_layout Standard +counts all blockquote paragraphs. +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py file.lyx | wget --no-check-certificate --spider -nv -F -i - +\end_layout + +\begin_layout Standard +checks all external links in a document recursively. + (Local links will appear as unresolved, but they can be ignored.) +\end_layout + +\begin_layout Subsection +Image Processing +\end_layout + +\begin_layout Standard +eLyXer does not convert images directly; it uses the +\begin_inset CommandInset href +LatexCommand href +name "ImageMagick" +target "http://www.imagemagick.org/" + +\end_inset + + package, in particular the +\family typewriter +convert +\family default + tool, to create PNG versions of the images embedded in the original LyX + documents, and then it inserts links to those PNG images in the resulting + HTML pages. + If ImageMagick is not installed eLyXer will show an error message and will + not try to convert further images. +\end_layout + +\begin_layout Standard +HTML pages, unlike PDF documents, do not contain images in the document + file; rather they contain pointers to image locations on disk. + (Fortunately, LyX documents do not contain images either.) eLyXer will generate + pages that point to the same locations as the original images, when they + are PNG images, or to the converted versions otherwise. + Image types like Encapsulated PostScript cannot be used directly from within + pages. +\end_layout + +\begin_layout Standard +Image location is fragile. + All images should be placed in the same location (and with the same structure) + as the original document; and they should all be referenced relatively + to the current document. + During conversion from within LyX image locations can be lost, since LyX + does not do in-place conversion; instead, LyX copies the original file + to a temporary directory, converts the file and then copies everything + back to a directory ending in +\family typewriter +.LyXconv +\family default +. +\end_layout + +\begin_layout Subsection +\begin_inset CommandInset label +LatexCommand label +name "sub:LyX-Integration" + +\end_inset + +LyX Integration +\end_layout + +\begin_layout Standard +If you used the eLyXer installer LyX will automatically detect it after + reconfiguration. + Just make sure that you are running LyX 1.6.5 or later, and click on Tools\SpecialChar \menuseparator +Reconfi +gure. +\end_layout + +\begin_layout Standard +LyX should be able to detect if eLyXer was installed as a script, or even + if it has been installed from a Linux distribution. + In any case you can verify that it has been recognized by LyX by opening + Tools\SpecialChar \menuseparator +Preferences\SpecialChar \ldots{} +, going to External formats\SpecialChar \menuseparator +Converters, and finding the + converter for +\begin_inset Quotes eld +\end_inset + +LyX -> HTML +\begin_inset Quotes erd +\end_inset + +. + If eLyXer is there, it worked! Now you can convert your documents using + View\SpecialChar \menuseparator +HTML. + Otherwise try to reinstall eLyXer from scratch and then reconfigure LyX. +\end_layout + +\begin_layout Subsubsection* +Installing as a Package or as a Module +\end_layout + +\begin_layout Standard +Versions of the eLyXer installer prior to 1.2.0 tried to install eLyXer as + a module, so it could be run using +\family typewriter +"python -m elyxer" +\family default +. + This option is deprecated since a module called +\family typewriter +elyxer +\family default + would collide with a Python package of the same name, and there are plans + to install eLyXer as a proper Python package in the future (probably in + the 1.3.0 time frame). + In the interim eLyXer is installed only as a script called +\family typewriter +elyxer.py +\family default +. +\end_layout + +\begin_layout Standard +LyX (starting with versions 2.0.0 and 1.6.9) has been patched to recognize only + the script and disregard the module. +\end_layout + +\begin_layout Section +Advanced Use +\end_layout + +\begin_layout Standard +There are some advanced uses for eLyXer if you want to extract the most + of it. +\end_layout + +\begin_layout Subsection +Command Line Options +\end_layout + +\begin_layout Standard +eLyXer supports a few command line options: +\end_layout + +\begin_layout Description + +\family typewriter +--help +\family default +: Show command line help. +\end_layout + +\begin_layout Description + +\family typewriter +--quiet +\family default +: Be quiet and do not output messages (except errors). + This way you can avoid the comforting +\begin_inset Quotes eld +\end_inset + +Parsing line 1000 +\begin_inset Quotes erd +\end_inset + + messages. + When STDIN or STDOUT are used (e.g. + in a pipeline) +\family typewriter +--quiet +\family default + is always enabled. +\end_layout + +\begin_layout Subsubsection* +Advanced Options +\end_layout + +\begin_layout Description + +\family typewriter +--debug +\family default +: Show debug messages. + They may help a developer understand your problem. +\end_layout + +\begin_layout Description + +\family typewriter +--version +\family default +: Show version number and date. + Use to check which version you are actually running. +\end_layout + +\begin_layout Description + +\family typewriter +--lyxformat +\family default +: Return the highest LyX version that eLyXer understands. + This parameter is provided to help with +\family typewriter +lyx2lyx +\family default + integration, so that this tool knows if it must convert the file to a lower + LyX format. +\end_layout + +\begin_layout Subsubsection* +Options to Control HTML output +\end_layout + +\begin_layout Description + +\family typewriter +--title +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +title +\series bold +" +\family default +\series default +: Change the title of the generated web page. +\end_layout + +\begin_layout Description + +\family typewriter +--css +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +new.css +\series bold +" +\family default +\series default +: Change default CSS. + See section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:CSS" + +\end_inset + +: CSS. +\end_layout + +\begin_layout Description + +\family typewriter +--embedcss +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +file.css +\series bold +" +\family default +\series default +: Embed the styles in +\family typewriter +file.css +\family default + into the resulting HTML document. + See section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:CSS" + +\end_inset + +: CSS. +\end_layout + +\begin_layout Description + +\family typewriter +--html +\family default +: Generate HTML 4.0 (instead of XHTML). + The resulting pages should be easier to import from certain word processors. + See section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:HTML-Code" + +\end_inset + +: HTML code. +\end_layout + +\begin_layout Description + +\family typewriter +--unicode +\family default +: Restore full Unicode output. + Right now switches midspaces to medium mathematical spaces. + See also section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:HTML-Code" + +\end_inset + +: HTML code. +\end_layout + +\begin_layout Description + +\family typewriter +--iso885915 +\family default +: Generate a document using ISO-8859-1 encoding. + Again, see section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:HTML-Code" + +\end_inset + +: HTML code. +\end_layout + +\begin_layout Description + +\family typewriter +--nofooter +\family default +: Omit the footer message +\begin_inset Quotes eld +\end_inset + +Document generated by eLyXer +\begin_inset Quotes erd +\end_inset + + (shown at the bottom). +\end_layout + +\begin_layout Subsubsection* +Options to Control image output +\end_layout + +\begin_layout Description + +\family typewriter +--directory +\begin_inset space ~ +\end_inset + +"images_dir" +\family default +: Look for images in the directory specified. +\end_layout + +\begin_layout Description + +\family typewriter +--destdirectory +\begin_inset space ~ +\end_inset + +"dest_dir" +\family default +: Converted images will end up into this directory. +\end_layout + +\begin_layout Description + +\family typewriter +--imageformat +\begin_inset space ~ +\end_inset + +".extension" +\family default +: Force the format implied by the extension (e.g. + +\family typewriter +".jpg" +\family default + for JPEG) for output images. + Use +\family typewriter +--imageformat "copy" +\family default + to make images be copied over instead of converted. +\end_layout + +\begin_layout Description + +\family typewriter +--converter +\begin_inset space ~ +\end_inset + + +\series bold +"program" +\family default +\series default +: +\family typewriter + +\family default +Use the given program to convert images. + Right now the supported converters are: +\family typewriter +\series bold +imagemagick +\family default +\series default + (default), +\family typewriter +\series bold +inkscape +\family default +\series default + and +\family typewriter +\series bold +lyx +\family default +\series default + itself. + With +\family typewriter +--converter inkscape +\family default + eLyXer picks Inkscape as the image converter (Inkscape uses some non-standard + extensions so it might be needed to convert SVG images to PNG); with +\family typewriter +--converter lyx +\family default + the new LyX option +\family typewriter +lyx -C +\family default + is used. + You can also supply your own converter command line, using +\family typewriter +$input +\family default + and +\family typewriter +$output +\family default + as variables (note the single quotes): +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --converter 'lyx -C $input $output' [source file] [destination + file] +\end_layout + +\begin_layout Description + +\family typewriter +--noconvert +\family default +: Use all images in their original location and do not convert anything. + Useful when using images which do not convert well, such as SVG files. +\end_layout + +\begin_layout Subsubsection* +Options to Control footnote output +\end_layout + +\begin_layout Description + +\family typewriter +--numberfoot +\family default +: Number all footnotes using numbers: +\begin_inset Quotes eld +\end_inset + +[1] +\begin_inset Quotes erd +\end_inset + +, instead of the default +\begin_inset Quotes eld +\end_inset + +[A] +\begin_inset Quotes erd +\end_inset + +. +\end_layout + +\begin_layout Description + +\family typewriter +--symbolfoot +\family default +: mark footnotes with symbols (*, **, †, ‡\SpecialChar \ldots{} +). +\end_layout + +\begin_layout Description + +\family typewriter +--hoverfoot +\family default +: show footnotes as hovering text. + This is the default position. +\end_layout + +\begin_layout Description + +\family typewriter +--marginfoot +\family default +: show footnotes with numbers instead of letters. +\end_layout + +\begin_layout Description + +\family typewriter +--endfoot +\family default +: show footnotes at the end of the page. +\end_layout + +\begin_layout Description + +\family typewriter +--supfoot +\family default +: use superscript for footnote markers. + This is the default style. +\end_layout + +\begin_layout Description + +\family typewriter +--alignfoot +\family default +: use aligned text for footnote markers, instead of superscript. +\end_layout + +\begin_layout Description + +\family typewriter +--footnotes +\begin_inset space ~ +\end_inset + +"options" +\family default +: specify several footnotes options at the same time, separated with commas. + Available options are: "number", "hover", "margin", "end". + See section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Footnotes" + +\end_inset + +: Footnotes. +\end_layout + +\begin_layout Subsubsection* +Advanced Options to Control HTML output +\end_layout + +\begin_layout Description + +\family typewriter +--splitpart +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +depth +\series bold +" +\family default +\series default +: Split the resulting webpage at the given depth. + See section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Segmenting-Pages" + +\end_inset + +: Segmenting Pages. +\end_layout + +\begin_layout Description + +\family typewriter +--tocfor +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +original.html +\series bold +" +\family default +\series default +: Generate just a table of contents with links to the original HTML file. + See section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:TOC" + +\end_inset + +: TOC. +\end_layout + +\begin_layout Description + +\family typewriter +--target +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +frame +\series bold +" +\family default +\series default +: Add a +\family typewriter +target +\family default + attribute to every link in the generated HTML, making all links point to + the provided frame. + Again, see section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:TOC" + +\end_inset + +: TOC. +\end_layout + +\begin_layout Description + +\family typewriter +--notoclabels +\family default +: Omit +\begin_inset Quotes eld +\end_inset + +Chapter +\begin_inset Quotes erd +\end_inset + +, +\begin_inset Quotes eld +\end_inset + +Part +\begin_inset Quotes erd +\end_inset + + and similar labels from the TOC; just output part numbers (and separate + using a period). + For instance, a chapter that without this option is labeled +\begin_inset Quotes eld +\end_inset + +Chapter 2: Advanced Use +\begin_inset Quotes erd +\end_inset + + in the TOC would now become +\begin_inset Quotes eld +\end_inset + +2. + Advanced Use +\begin_inset Quotes erd +\end_inset + +, as on the PDF. + Option adapted from the wish list: +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Wish-List" + +\end_inset + +. +\end_layout + +\begin_layout Description + +\family typewriter +--lowmem +\family default +: Activate a low memory mode which does not keep the whole document in memory: + conversion is done on the fly. + Keep in mind that some features as the TOC will be missing from the generated + document. +\end_layout + +\begin_layout Description + +\family typewriter +--numberfoot +\family default +: +\family typewriter + +\family default +Label footnotes using numbers, instead of letters. + Useful when bibliographical references are not numbered and therefore cannot + be confused with footnotes. +\end_layout + +\begin_layout Description + +\family typewriter +--raw +\family default +: Generate an HTML page without header or footer. +\end_layout + +\begin_layout Description + +\family typewriter +--mathjax +\begin_inset space ~ +\end_inset + + +\series bold +remote +\family default +\series default +: Use the excellent JavaScript library +\begin_inset CommandInset href +LatexCommand href +name "MathJax" +target "http://www.mathjax.org/" + +\end_inset + + remotely to pretty-print mathematical equations. + See section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Math" + +\end_inset + +. +\end_layout + +\begin_layout Description + +\family typewriter +--mathjax +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +URL +\series bold +" +\family default +\series default +: Use the excellent JavaScript library +\begin_inset CommandInset href +LatexCommand href +name "MathJax" +target "http://www.mathjax.org/" + +\end_inset + + at the given URL (usually a local URL is used). + See also section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Math" + +\end_inset + +. +\end_layout + +\begin_layout Description + +\family typewriter +--googlecharts +\family default +: Use +\begin_inset CommandInset href +LatexCommand href +name "Google Charts" +target "http://code.google.com/apis/chart/index.html" + +\end_inset + + to generate images for every formula. + Again, see +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Math" + +\end_inset + +. +\end_layout + +\begin_layout Description + +\family typewriter +--simplemath +\family default +: Do not generate fancy math structures such as multi-line Unicode brackets + or stacked limits. + This option is automatically activated when +\family typewriter +--html +\family default + is selected; once more see section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Math" + +\end_inset + +. +\end_layout + +\begin_layout Description + +\family typewriter +--template +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +file +\series bold +" +\family default +\series default +: Use an HTML template. + The raw converted document will be placed where +\family typewriter + +\family default + appears in the template. + Available variables: +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +, +\family typewriter + +\family default +. +\end_layout + +\begin_layout Description + +\family typewriter +--copyright +\family default +: Include a copyright notice at the bottom. +\end_layout + +\begin_layout Subsubsection* +Deprecated Options +\end_layout + +\begin_layout Description + +\family typewriter +--toc +\family default +: Generate just a table of contents. + Use +\family typewriter +--tocfor +\family default + instead. +\end_layout + +\begin_layout Description + +\family typewriter +--toctarget +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +original.html +\series bold +" +\family default +\series default +: Generate a table of contents with links to the original HTML file. + Use +\family typewriter +--tocfor +\family default + instead. +\end_layout + +\begin_layout Description + +\family typewriter +--nocopy +\family default +: No effect since the copyright notice is now optional, maintained for backwards + compatibility. +\end_layout + +\begin_layout Standard +When an option accepts an argument it can be added after a space as +\family typewriter +--target +\begin_inset space ~ +\end_inset + + +\series bold +" +\series default +frame +\series bold +" +\family default +\series default +, or with an equals sign as in +\family typewriter +--target= +\series bold +" +\series default +frame +\series bold +" +\family default +\series default +. + The quotes are optional and can be useful if your arguments include e.g. + spaces. +\end_layout + +\begin_layout Subsubsection* +Adding Options In LyX +\end_layout + +\begin_layout Standard +To add one of these options so that it is used from within LyX, you have + to modify the converter line. + To this effect open Tools\SpecialChar \menuseparator +Preferences\SpecialChar \ldots{} +, go to External formats\SpecialChar \menuseparator +Converters, + find the converter for +\begin_inset Quotes eld +\end_inset + +LyX -> HTML +\begin_inset Quotes erd +\end_inset + + and edit the converter line. + It should read something like this: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +elyxer.py --directory $$r $$i $$o +\end_layout + +\begin_layout Standard +If you want to generate pure HTML instead of XHTML, change the line to: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +elyxer.py +\family default +\series bold +--html +\family typewriter +\series default + --directory $$r $$i $$o +\end_layout + +\begin_layout Standard +And so on. + Figure 1 shows what to do to add the +\family typewriter +--html +\family default + option: after editing the line and adding the new option, click on +\begin_inset Quotes eld +\end_inset + +Modify +\begin_inset Quotes erd +\end_inset + + and then +\begin_inset Quotes eld +\end_inset + +Save +\begin_inset Quotes erd +\end_inset + + or +\begin_inset Quotes eld +\end_inset + +Apply +\begin_inset Quotes erd +\end_inset + + the changes. +\begin_inset Marginal +status open + +\begin_layout Plain Layout +You should never remove the +\family typewriter +$$i $$o +\family default + at the end, since it is what tells eLyXer where to find the input and output + files. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename converters.png + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +eLyXer converter in LyX 1.6.5. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +LyX 1.6.5 supports a new +\begin_inset Quotes eld +\end_inset + +extra flag +\begin_inset Quotes erd +\end_inset + + line; however, at this moment it does not work with eLyXer. +\end_layout + +\begin_layout Subsection +CSS +\begin_inset CommandInset label +LatexCommand label +name "sub:CSS" + +\end_inset + + +\end_layout + +\begin_layout Standard +HTML output, as generated, can fall short in certain situations. + Some CSS wizardry can go a long way to customize eLyXer. +\end_layout + +\begin_layout Standard +eLyXer tags most elements with the type so you can later modify them using + a CSS. + The default HTML header is similar to listing +\begin_inset CommandInset ref +LatexCommand ref +reference "alg:CSS" + +\end_inset + +, so the default remote CSS file is used. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Quotation + +\family typewriter + +\end_layout + +\begin_layout Quotation + +\family typewriter +[...] +\end_layout + +\begin_layout Quotation + +\family typewriter +\series bold + +\end_layout + +\begin_layout Quotation + +\family typewriter +Your title here +\end_layout + +\begin_layout Quotation + +\family typewriter + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "alg:CSS" + +\end_inset + +CSS link automatically added to HTML +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +This sample CSS file is published on nongnu.org and distributed along with + the scripts, +\family typewriter +docs/lyx.css +\family default +. + (You may have found that your document shows minor changes in its appearance + with time -- this is the reason. + The main author regularly publishes a new, updated version of +\family typewriter +lyx.css +\family default + on nongnu.org, and all documents using it automatically appear with the + changes. + Backwards compatibility is maintained as much as possible.) +\end_layout + +\begin_layout Standard +To give your document a customized appearance (or for pages to be accessible + offline) you probably will want to use your own CSS file; to use it first + copy it to the directory where your document resides (e.g. + renaming it to +\family typewriter +custom.css +\family default +), and customize as needed. + Then run +\family typewriter +elyxer.py +\family default + with the following option: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --css=custom.css document.lyx page.html +\end_layout + +\begin_layout Standard +This will make the generated +\family typewriter +page.html +\family default + use your +\family typewriter +custom.css +\family default + file. + The +\family typewriter +`=' +\family default + sign between the constant +\family typewriter +`--css' +\family default + and the name of the CSS file is optional. + More than one +\family typewriter +--css +\family default + option can be added if you want several CSS files to be used in the header. +\end_layout + +\begin_layout Standard +Sometimes the styles in a CSS are needed in the HTML document (for offline + viewing, or to distribute as stand-alone pages). + For these uses there is the option +\family typewriter +--embedcss +\family default +: the styles contained in the CSS file passed as an argument will be embedded + in the resulting HTML document. + For instance: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --embedcss custom.css document.lyx page.html +\end_layout + +\begin_layout Standard +This command generates a document +\family typewriter +page.html +\family default + where the styles in +\family typewriter +custom.css +\family default + are embedded. + The CSS to embed must be a file, not a remote URL. + Listing +\begin_inset CommandInset ref +LatexCommand ref +reference "alg:embed-CSS" + +\end_inset + + shows the resulting HTML header for a test CSS with just one style, +\family typewriter +div.Standard +\family default +. + Note that the remote CSS is still added by default; to avoid it just add + an option with an empty CSS file, +\family typewriter +--css="" +\family default +. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Quotation + +\family typewriter + +\end_layout + +\begin_layout Quotation + +\family typewriter +[...] +\end_layout + +\begin_layout Quotation + +\family typewriter + +\end_layout + +\begin_layout Quotation + +\family typewriter + +\end_layout + +\begin_layout Quotation + +\family typewriter +\series bold + +\end_layout + +\begin_layout Quotation + +\family typewriter +Your title here +\end_layout + +\begin_layout Quotation + +\family typewriter + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "alg:embed-CSS" + +\end_inset + +CSS embedded into the HTML +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +As with the +\family typewriter +--css +\family default + option, several +\family typewriter +--embedcss +\family default + options can be added to embed more than one file. +\end_layout + +\begin_layout Standard +The CSS file for eLyXer uses some CSS2 features for math structures (fractions, + arrays). + This makes the output incompatible with older browsers; it requires Microsoft + Internet Explorer 7, Firefox 3, Safari 3 or Chrome 1. + Check the +\begin_inset CommandInset href +LatexCommand href +name "Math Showcase" +target "math.html" + +\end_inset + + to see if your browser can render eLyXer output correctly. +\end_layout + +\begin_layout Subsection +Title +\end_layout + +\begin_layout Standard +By default the generated web pages have the title +\begin_inset Quotes eld +\end_inset + +Converted Document +\begin_inset Quotes erd +\end_inset + +. + If a PDF title is found then it is used instead. + The proper LyX title (a paragraph of type +\begin_inset Quotes eld +\end_inset + +Title +\begin_inset Quotes erd +\end_inset + + embedded in the text) will also be used if found. + But when +\family typewriter +--lowmem +\family default + is in use eLyXer does not try to get the proper title, since it may be + found in the middle of the document or not be present at all; scanning + for it would mean doing two passes, one to look for the title in all the + document and another to output the web page, and +\family typewriter +--lowmem +\family default + implies on-the-fly conversion to save memory. +\end_layout + +\begin_layout Standard +You can change the title of the generated web page with the +\family typewriter +--title +\family default + option: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --title "My Beautiful Document" document.lyx page.html +\end_layout + +\begin_layout Subsection +Table Of Contents +\begin_inset CommandInset label +LatexCommand label +name "sub:TOC" + +\end_inset + + +\end_layout + +\begin_layout Standard +A table of contents (or TOC) can be generated for every converted LyX document. + You can optionally also add a target frame to every link. + The trick is to combine both options to generate a TOC that links to the + original document on a different frame. + For example, if the original page is called +\family typewriter +page.html +\family default + and you generated it with this command: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py document.lyx page.html +\end_layout + +\begin_layout Standard +you can generate the TOC linking to this page, and at the same time point + it to frame +\family typewriter +contents +\family default +: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --tocfor page.html --target contents document.lyx page-toc.html +\end_layout + +\begin_layout Standard +Then you can put it all together with a simple frameset generated manually. + Just remember to place the original document in the frame called +\family typewriter +contents +\family default +. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Plain Layout + +\family typewriter + +\end_layout + +\begin_layout Plain Layout + +\family typewriter +\begin_inset space ~ +\end_inset + + +\begin_inset space ~ +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\family typewriter +\begin_inset space ~ +\end_inset + + +\begin_inset space ~ +\end_inset + + +\begin_inset space ~ +\end_inset + + +\begin_inset space ~ +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\family typewriter +\begin_inset space ~ +\end_inset + + +\begin_inset space ~ +\end_inset + + +\begin_inset space ~ +\end_inset + + +\begin_inset space ~ +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\family typewriter +\begin_inset space ~ +\end_inset + + +\begin_inset space ~ +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\family typewriter + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "alg:frameset" + +\end_inset + +An example frameset for TOC navegation +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +TOC generation accepts the same options as normal document conversion. + For example, if you follow these instructions literally you will notice + that the TOC has very wide margins and looks a bit weird; that is because + it is using the default CSS. + A special CSS file for TOC files is provided in +\family typewriter +docs/toc.css +\family default +, so better results should be obtained with the +\family typewriter +--css +\family default + option: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --tocfor page.html --css docs/toc.css --target contents document.lyx + page-toc.html +\end_layout + +\begin_layout Standard +With a little bit of practice you will be able to generate useful (and nice + looking) TOC files. + You can see an example for the +\begin_inset CommandInset href +LatexCommand href +name "user guide" +target "userguide-frameset.html" + +\end_inset + + (if you are not already looking at it). +\end_layout + +\begin_layout Subsection +Segmenting Pages +\begin_inset CommandInset label +LatexCommand label +name "sub:Segmenting-Pages" + +\end_inset + + +\end_layout + +\begin_layout Standard +Quite often you don't want a huge monolithic page, but a set of linked pages. + To do so you can use the +\family typewriter +--splitpart +\family default + option, specifying the level at which eLyXer should split pages. + For instance: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --splitpart 1 document.lyx output.html +\end_layout + +\begin_layout Standard +will split +\family typewriter +document.lyx +\family default + into pages at level 1, using +\family typewriter +output.html +\family default + as the root page. + Each page will get a number that starts with +\family typewriter +output +\family default + and ends with +\family typewriter +.html +\family default +, with a suffix that depends on the page -- +\family typewriter +output-2.html +\family default + will correspond to the second split part. +\end_layout + +\begin_layout Standard +The level corresponding to 1 depends on the document class: books will be + split at chapters, but articles will get a section per page. + And so on with lower levels. +\end_layout + +\begin_layout Subsection +HTML Code +\begin_inset CommandInset label +LatexCommand label +name "sub:HTML-Code" + +\end_inset + + +\end_layout + +\begin_layout Standard +The HTML code generated is technically XHTML Transitional, version 1.0 +\begin_inset CommandInset citation +LatexCommand cite +key "xhtml" + +\end_inset + +, using UTF-8 encoding. + Some programs have (in this day and age) trouble importing XHTML, notably + some popular word processors. + To work around this problem and provide more flexible output in general + you can output HTML 4.0: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --html document.lyx page-to-import.html +\end_layout + +\begin_layout Standard +Again, technically the code generated is HTML 4.01 Transitional +\begin_inset CommandInset citation +LatexCommand cite +key "html-401" + +\end_inset + + using UTF-8 encoding. + Both versions should pass the W3C tests +\begin_inset CommandInset citation +LatexCommand cite +key "w3c-validator" + +\end_inset + +. + If your particular web page doesn't pass the tests, then it is a bug and + it will be treated as such. +\end_layout + +\begin_layout Standard +The +\family typewriter +--html +\family default + option also activates the +\family typewriter +--simplemath +\family default + option; see section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Math" + +\end_inset + +: Math for details. +\end_layout + +\begin_layout Subsubsection* +Character Encodings +\end_layout + +\begin_layout Standard +For better browser compatibility, medium mathematical spaces are substituted + in the output with midspaces -- improving the output for some popular browsers. + If you want your mathematical spaces back, just use the +\family typewriter +--unicode +\family default + option: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --unicode document.lyx page-to-import.html +\end_layout + +\begin_layout Standard +Check out the +\begin_inset CommandInset href +LatexCommand href +name "Math Showcase with Unicode" +target "math-unicode.html" + +\end_inset + + to see the results. + In the future other non-Unicode substitutions might be used. +\end_layout + +\begin_layout Standard +In case you want to use the ISO-8859-15 encoding in your generated document, + you can add the +\family typewriter +--iso885915 +\family default + option: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --iso885915 document.lyx page.html +\end_layout + +\begin_layout Standard +This will make eLyXer output a document with all non-ASCII characters encoded + as +\family typewriter +  +\family default +, +\family typewriter +  +\family default + and so on. + This encoding is similar to ISO-8859-1, also called Latin-1, but including + the Euro sign. + The +\begin_inset CommandInset href +LatexCommand href +name "Math Showcase (ISO-8859-15 edition)" +target "math-iso885915.html" + +\end_inset + + has been generated using this option. +\end_layout + +\begin_layout Standard +Both encoding options can be combined with +\family typewriter +--html +\family default + at will. +\end_layout + +\begin_layout Subsection +Internationalization +\end_layout + +\begin_layout Standard +eLyXer is distributed along with a few translation files. + They are automatically regenerated every time +\family typewriter +make +\family default + is run, and reside in the folder +\family typewriter +po/ +\family default +. + Internationalization is done using GNU +\family typewriter +gettext +\family default +, so every locale is identified by a two-letter code (such as +\begin_inset Quotes eld +\end_inset + +en +\begin_inset Quotes erd +\end_inset + + for English and +\begin_inset Quotes eld +\end_inset + +es +\begin_inset Quotes erd +\end_inset + + for Spanish). + There are two kinds of files: the text +\family typewriter +.po +\family default + file (which can be found in +\family typewriter +po/my.po +\family default + for locale +\begin_inset Quotes eld +\end_inset + +my +\begin_inset Quotes erd +\end_inset + +), and the binary +\family typewriter +.mo +\family default + file (found in +\family typewriter +po/my/elyxer.po +\family default +). +\end_layout + +\begin_layout Standard +For internationalization to work properly, Linux distributors should take + all binary +\family typewriter +.mo +\family default + files and place them in the directory corresponding to locale files, which + we will call +\family typewriter +$localedir +\family default +. + As +\begin_inset CommandInset href +LatexCommand href +name "the Python gettext page" +target "http://docs.python.org/library/gettext.html" + +\end_inset + + explains, this is distribution-dependent: for example on Debian +\family typewriter +$localedir +\family default + is +\family typewriter +/usr/share/locale +\family default +, so for locale +\begin_inset Quotes eld +\end_inset + +es +\begin_inset Quotes erd +\end_inset + + the correct route would be +\end_layout + +\begin_layout LyX-Code + +\family typewriter +/usr/share/locale/es/LC_MESSAGES/elyxer.mo +\end_layout + +\begin_layout Standard +Windows distributors on the other hand should place files in +\family typewriter +%PYTHONHOME% +\backslash +share +\backslash +locale +\family default +, for example for locale +\begin_inset Quotes eld +\end_inset + +es +\begin_inset Quotes erd +\end_inset + + on a machine where Python is in +\family typewriter +C: +\backslash +python +\family default +: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +C: +\backslash +python +\backslash +share +\backslash +locale +\backslash +es +\backslash +LC_MESSAGES +\backslash +elyxer.mo +\end_layout + +\begin_layout Standard +To generate a new translation file (we will use +\begin_inset Quotes eld +\end_inset + +my +\begin_inset Quotes erd +\end_inset + + as an example locale here, corresponding to Burmese): you need to have + the GNU +\family typewriter +gettext +\family default + package installed. + Then go to the directory where elyxer.pot resides: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + cd src/conf +\end_layout + +\begin_layout Standard +and generate a +\family typewriter +.po +\family default + file for your locale: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + msginit --output-file=my.po --locale=my +\end_layout + +\begin_layout Standard +Then move the file to the +\family typewriter +po/ +\family default + directory: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + mv my.po ../../po/ +\end_layout + +\begin_layout Standard +and start translating it to Burmese! Once you are done run make from the + root directory: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + ./make +\end_layout + +\begin_layout Standard +and it will generate the file +\family typewriter +po/my/elyxer.mo +\family default +. + Finally, place this file in +\end_layout + +\begin_layout LyX-Code + +\family typewriter +$localedir/my/LC_MESSAGES/elyxer.mo +\end_layout + +\begin_layout Standard +and you are done. +\end_layout + +\begin_layout Subsection +Math +\begin_inset CommandInset label +LatexCommand label +name "sub:Math" + +\end_inset + + +\end_layout + +\begin_layout Standard +Math equations are an important part of what takes LyX apart from other + editors, since it supports the full LaTeX feature set -- that is, about + everything under the sun. + Unfortunately, math support is hard to get right. + Many developers are focusing on MathML, but at the time of this writing + (Q2 2010) support on some common browsers is still missing. +\end_layout + +\begin_layout Standard +eLyXer follows its usual minimalistic approach and doesn't try to be everything + to everybody -- instead, it supports out of the box a set of usual constructs + (fraction, square root) and tries to simulate others (binomial, overbrace). + See the +\begin_inset CommandInset href +LatexCommand href +name "Math showcase" +target "math.html" + +\end_inset + + for yourself and learn what eLyXer supports and what not. +\end_layout + +\begin_layout Standard +For more sophisticated math equations there are a couple of advanced features. +\end_layout + +\begin_layout Subsubsection* +MathJax +\end_layout + +\begin_layout Standard +The first option is to use +\begin_inset CommandInset href +LatexCommand href +name "MathJax" +target "http://www.mathjax.org/" + +\end_inset + +, which is as simple as using the option +\family typewriter +--mathjax +\family default +: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --mathjax +\family default +\series bold +remote +\family typewriter +\series default + math.lyx math- +\family default +mathjax-remote +\family typewriter +.html +\end_layout + +\begin_layout Standard +The +\family typewriter +\series bold +remote +\family default +\series default + argument tells MathJax to access the MathJax library remotely on the MathJax + CDN. + (You should always comply with their +\begin_inset CommandInset href +LatexCommand href +name "terms of service" +target "http://www.mathjax.org/download/mathjax-cdn-terms-of-service/" + +\end_inset + +.) See the +\begin_inset CommandInset href +LatexCommand href +name "Math showcase (MathJax remote edition)" +target "math-mathjax-remote.html" + +\end_inset + + to check the results. +\end_layout + +\begin_layout Standard +In case you need to go outside the terms of service, or you want the content + to be accessible offline, you can always use a local copy of MathJax. + Just use the URL of the repository as an argument to the +\family typewriter +--mathjax +\family default + option: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --mathjax MathJax/ math.lyx math- +\family default +mathjax-local +\family typewriter +.html +\end_layout + +\begin_layout Standard +This way eLyXer uses the given URL (in the example +\family typewriter +MathJax/ +\family default +) to load MathJax from and set it up. + Although some code needs to be hosted on the same site as the pages, MathJax + uses a feature called web-fonts which can be downloaded from a public server; + this is quite easier to host. + See the +\begin_inset CommandInset href +LatexCommand href +name "Math showcase (MathJax edition)" +target "math-mathjax.html" + +\end_inset + + to see how MathJax fares with eLyXer. +\end_layout + +\begin_layout Standard +Something to note is that MathJax is a JavaScript library; all rendering + is done client-side by the user's browser. + This has quite a few advantages: +\end_layout + +\begin_layout Itemize +Math processing on the server is quite light; equations are basically surrounded + by a special tag and left in TeX form. +\end_layout + +\begin_layout Itemize +For developers: integration of these libraries is very easy. + It took just a few days to integrate both libraries with eLyXer. +\end_layout + +\begin_layout Itemize +MathJax is improving all the time thanks to the efforts of Davide P. + Cervone and the rest of the developer team; eLyXer and its users reap the + benefits readily. +\end_layout + +\begin_layout Itemize +The client browser already knows its abilities, and can choose the rendering + method it considers to be the best. + MathJax can even choose between MathML and HTML+CSS +\emph on +at page rendering time +\emph default +, showing MathML on fancier browsers and simpler HTML where it is not available. +\end_layout + +\begin_layout Standard +It also brings some disadvantages: +\end_layout + +\begin_layout Itemize +With the +\family typewriter +remote +\family default + argument, JavaScript code resides at +\begin_inset CommandInset href +LatexCommand href +name "a remote server" +target "http://cdn.mathjax.org/" + +\end_inset + + and your users will need online access to view the maths. +\end_layout + +\begin_layout Itemize +If MathJax is accessed locally you need to also host the code for MathJax. + (Web fonts used in MathJax can at least be hosted elsewhere, so publishers + do not need to also host the fonts package, but this hasn't still been + used in eLyXer.) +\end_layout + +\begin_layout Itemize +And of course it takes some time to render everything on the client, which + can degrade the user experience on older machines. +\end_layout + +\begin_layout Standard +Publishers should carefully consider pros and cons before deciding what + to use. +\end_layout + +\begin_layout Subsubsection* +Google Charts +\end_layout + +\begin_layout Standard +\begin_inset CommandInset href +LatexCommand href +name "Google Charts" +target "http://code.google.com/apis/chart/index.html" + +\end_inset + + is an online service which generates images that contain charts and other + stuff; it can also generate TeX formulas. + eLyXer can use it using the option +\family typewriter +--googlecharts +\family default +: +\end_layout + +\begin_layout LyX-Code + +\family typewriter +\color blue +$ +\color inherit + elyxer.py --googlecharts math.lyx math-googlecharts.html +\end_layout + +\begin_layout Standard +There are some limitations to Google Charts: no macros, formulas cannot + exceed 200 characters, and the supported command set is limited (commands + in text mode, for instance, are out of bounds). + Also, generated images can be hard to align vertically -- by default they + are middle-aligned, but some small characters or superscripted formulas + can look weird. + But this option can be a quick&dirty way of showing math for older or unsupport +ed browsers. +\end_layout + +\begin_layout Subsubsection* +Brackets and Limits +\end_layout + +\begin_layout Standard +Fancy math structures are generated by default: arrays and binomials are + surrounded by multi-line Unicode brackets, limits in display mode are stacked + above / below the symbol, and so on. + When the option +\family typewriter +--simplemath +\family default + is used eLyXer avoids such structures and just outputs enlarged regular + symbols. + It is also included in the +\family typewriter +--html +\family default + option. +\end_layout + +\begin_layout Standard +Check out the +\begin_inset CommandInset href +LatexCommand href +name "Math showcase (HTML edition)" +target "math-html.html" + +\end_inset + + to see the results. +\end_layout + +\begin_layout Subsection +Footnotes +\begin_inset CommandInset label +LatexCommand label +name "sub:Footnotes" + +\end_inset + + +\end_layout + +\begin_layout Standard +Footnote generation is surprisingly hard to get right in an HTML document. + eLyXer has a fairly complete set of command line options to customize how + footnotes are generated. + Here we will use the aggregated option +\family typewriter +--footnotes "options" +\family default + which can be used to specify any combination, but they can be turned on + independently using +\family typewriter +--\SpecialChar \ldots{} +foot +\family default +. + For instance: +\family typewriter +--footnotes number,margin +\family default + is equivalent to +\family typewriter +--numberfoot --marginfoot +\family default +. +\end_layout + +\begin_layout Subsubsection* +Markers +\end_layout + +\begin_layout Standard +The footnote is attached to a point of the text (the +\emph on +referring +\emph default + text) which is usually marked by a bit of text. + The default behavior for the marker is to use a superscript letter surrounded + by square brackets, in blue: +\color blue + +\begin_inset Formula $^{\text{[A]}}$ +\end_inset + + +\color inherit +. + The text can be changed to aligned text with +\family typewriter +--footnotes align +\family default +: +\color blue +[A] +\color inherit +, so markers are not mistaken with other superscript constructs such as + exponents (like +\begin_inset Formula $e^{a}$ +\end_inset + +). +\end_layout + +\begin_layout Standard +Markers can also be converted to numbers using +\family typewriter +--footnotes number +\family default +: +\color blue + +\begin_inset Formula $^{\text{[1]}}$ +\end_inset + +. + +\color inherit + Or, they can be switched over to symbols using +\family typewriter +--footnotes symbol +\family default +: +\color blue +* +\color inherit +. + Available symbols are rotated from this sequence: * ** † ‡ § §§ ¶ ¶¶ # + ##. + All options can be combined. + For instance, symbol markers look best when shown aligned; +\family typewriter +--footnotes align,symbol +\family default + will show aligned symbolic markers such as +\color blue +* +\color inherit + or +\color blue +† +\color inherit +. +\end_layout + +\begin_layout Subsubsection* +Position +\end_layout + +\begin_layout Standard +Footnotes are supposed to appear at the foot of the page, but that is not + always possible or practical in web pages. + Huge pages make scrolling up and down quite uncomfortable, and remove the + immediacy of having the note in the same page as the referring text. +\end_layout + +\begin_layout Standard +There are a few alternatives: use the margin, show hovering text, or link + to the note at the bottom of the page. + eLyXer can use all three. + +\family typewriter +--footnotes margin +\family default + will place the notes at the margin, just as margin notes but with the addition + of the footnote marker. + While +\family typewriter +--footnotes hover +\family default + will show hovering text when the mouse is placed on the marker; this is + the default behavior. + Note that hovering notes are converted into margin notes when printing. +\end_layout + +\begin_layout Standard +When footnotes are shown at the end of the page with +\family typewriter +--footnotes end +\family default +, footnote markers turn into links. + The actual footnote at the end then contains a link back to the marker. +\end_layout + +\begin_layout Standard +The most interesting part is that these three options can be combined at + will: +\family typewriter +--footnotes margin,hover,end +\family default + will show footnotes at the three possible locations. + The most practical combination is probably +\family typewriter +--footnotes hover,end +\family default +, which will show notes as hovering text and also at the end of the page. + Note however that in this case notes will be printed twice (at the margin + instead of hovering and at the end). +\end_layout + +\begin_layout Section +Work in Progress +\end_layout + +\begin_layout Standard +As you can see eLyXer is a mature and tried package, but it has some rough + edges. +\end_layout + +\begin_layout Subsection +Known Issues +\end_layout + +\begin_layout Standard +The following issues (including bugs and missing features) are acknowledged. + Some of them should be solved soon; others may take longer. +\end_layout + +\begin_layout Enumerate +On Mac OS X the output of a message with Unicode characters may cause an + error. + Workaround: run +\family typewriter +elyxer.py +\family default + with the +\family typewriter +--quiet +\family default + option. +\end_layout + +\begin_layout Enumerate +Some phonetic alphabet symbols are not well supported -- if generated with + LyX they only appear in a different color: +\begin_inset Formula $\text{\textipa{[sample]}}$ +\end_inset + +. + +\begin_inset Note Note +status open + +\begin_layout Plain Layout +This happens only in the HTML file converted with eLyXer, not from within + LyX. +\end_layout + +\end_inset + + +\begin_inset Note Comment +status open + +\begin_layout Plain Layout +By the way, the previous note (and this one) should not appear on the HTML. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Enumerate +Multi-column layouts are lost. + This one is almost impossible to get right in CSS, so there are no plans + to even try. +\end_layout + +\begin_layout Enumerate +Many BibTeX styles are missing. + (They are quite trivial to add though.) +\end_layout + +\begin_layout Enumerate +ERT (bare TeX code) is ignored. +\end_layout + +\begin_layout Enumerate +Many AMS environments (like +\family typewriter +alignat +\family default +, +\family typewriter +gather +\family default +\SpecialChar \ldots{} +) are not working or look strange -- some non-AMS environments too. +\end_layout + +\begin_layout Enumerate +Images are never scaled above their nominal resolution. + This is seldom needed if at all, so there are no plans to change it; if + people really need the feature just let the author know so it can be added + as an option. +\end_layout + +\begin_layout Subsection +Wish List +\begin_inset CommandInset label +LatexCommand label +name "sub:Wish-List" + +\end_inset + + +\end_layout + +\begin_layout Standard +The following features have been requested by users; specific people are + referenced by a couple of initials so they can recognize themselves while + keeping some anonymity. + (If you prefer that your initials do not to appear here at all just let + me know.) +\end_layout + +\begin_layout Standard +Queued features will be added at the next big release -- the priority for + each feature will be set by the number of users requesting it and date + requested. + Pending features need some assessment. + Those marked as too complex have been evaluated as requiring too much work, + but the decision might be reversed if there are enough people interested + or a simple way to implement them is found. + Once done, features are marked with the first release where they appear. +\end_layout + +\begin_layout Standard +\begin_inset Tabular + + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Feature +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Date +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Users +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Status +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Understand +\backslash +setcounter{section}{1} +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-05-15 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JB +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.0 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\family roman +\series medium +\shape up +\size normal +\emph off +\bar no +\noun off +\color none +Option to turn off title prefixes in TOC +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\family roman +\series medium +\shape up +\size normal +\emph off +\bar no +\noun off +\color none +2010-07-10 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +YG +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.0 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Use BibLaTeX with eLyXer +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-09-14 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +PJ, WE +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Render change tracking: "Show changes in output" +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-09-18 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +YG +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.0 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Option for footnotes at the margin +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-09-21 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +A +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.0 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Output SVG as +\family typewriter + +\family default + tags ( +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:Output-SVG-as" + +\end_inset + +) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-09-22 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +YG +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +EPUB output format ( +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:EPUB-output-format" + +\end_inset + +) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-09-23 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +MJ, MG +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Too complex +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Option for footnotes at the end of each section +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-09-23 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +MJ +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.0 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Add more controls for image conversion ( +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:More-controls-for" + +\end_inset + +) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-02 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +WE +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.0 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Support for format 401 (Insert Horizontal Line) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-06 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +US +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.2 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Parse contents of ERTs +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-06 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +US, JW +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.2.0 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Correct scaling of tables with relative sizes (e.g. + +\family typewriter +%col +\family default +) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-09 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +US +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +BibTeX: parse math formulas inside BibTeX files +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-16 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JA +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +BibTeX: display +\family typewriter + +\backslash +url{} +\family default + as an URL +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-16 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JA +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Do not label bibliography items in comments +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-21 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JA +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Unit tests should warn if ImageMagick not installed +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-24 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JA +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Unit tests should run fine without PNG conversion tools +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-10-30 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JA +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Option +\family typewriter +--imageformat copy +\family default + to avoid converting images +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-11-12 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JD +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Option to embed the CSS in the HTML file +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:CSS-controls" + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-11-23 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +GM, JA +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Display sub- and superscript aligned vertically (as in integrals) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-11-23 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +GM +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Use Unicode large characters for sums, integrals, matrices\SpecialChar \ldots{} + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-12-07 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +GM +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.1.2 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Do not number captions in code listings +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-12-08 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +DC +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.2.0 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Support brushes for +\begin_inset CommandInset href +LatexCommand href +name "SyntaxHighlighter" +target "http://alexgorbatchev.com/SyntaxHighlighter/manual/api/autoloader.html" + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-12-10 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +DC +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Generate formula images using Google Charts +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-01-07 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +ET +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.2.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Output reference arrows as CSS pseudo-elements +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-01-12 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +GM +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Include part names in +\family typewriter +--splitpart +\family default + navigation header +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-01-15 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +AJ +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.2.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Merge options +\family typewriter +--toc +\family default + and +\family typewriter +--toctarget +\family default + into +\family typewriter +--tocfor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-01-17 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JA +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.2.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Make +\family typewriter +--splitpart +\family default + and +\family typewriter +--tocfor +\family default + work together +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2010-01-17 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JA, TP +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.2.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Generate named references (equivalent to +\family typewriter + +\backslash +nameref +\family default +) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-01-19 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +TP +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +1.2.1 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Do not generate entries when index or nomenclature are missing +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-01-19 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +TP +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Queued +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Do not output unknown commands in red except in +\family typewriter +--debug +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-02-22 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +JA +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Queued +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Output equations as images +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-05-31 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +GK +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Parse modules for custom Flex CharStyles +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-06-08 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +MG +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Convert several files with a single command +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-06-01 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +PF +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Export slides as HTML5 presentation +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-06-28 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +RK +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Add an option to remove navigation bars +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-06-29 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +AH +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Support for External Material: PDF, Date +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2011-10-22 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +MI +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Pending +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Standard +Some features require further explanations. +\end_layout + +\begin_layout Subsubsection* +EPUB output format +\begin_inset CommandInset label +LatexCommand label +name "sub:EPUB-output-format" + +\end_inset + + +\end_layout + +\begin_layout Standard +The EPUB management package +\begin_inset CommandInset href +LatexCommand href +name "calibre" +target "http://calibre-ebook.com/user_manual/conversion.html" + +\end_inset + + does not output valid EPUB documents when converted from eLyXer HTML files, + at least according to the +\begin_inset CommandInset href +LatexCommand href +name "Threepress validator" +target "http://threepress.org/document/epub-validate" + +\end_inset + +. +\end_layout + +\begin_layout Standard +This is a complex feature request; calibre does minimal formatting in its + EPUB conversion, so making it generate valid EPUB documents requires changing + deeply how eLyXer outputs XHTML. + Lots of help would be needed to get this working. +\end_layout + +\begin_layout Standard +That said, EPUB readers are often much less strict than the official format + and they readily accept eLyXer output. + Just convert your LyX document to HTML using eLyXer, and then import the + resulting HTML document into your EPUB reader. + Let us know how it goes for you. +\end_layout + +\begin_layout Subsubsection* +Output SVG as +\family typewriter + +\family default + tags +\begin_inset CommandInset label +LatexCommand label +name "sub:Output-SVG-as" + +\end_inset + + +\end_layout + +\begin_layout Standard +This feature would be most welcome from the part of the author. + Unfortunately, Firefox alone from the major browsers refuses to render + +\family typewriter + +\family default + tags correctly for SVG. + According to +\begin_inset CommandInset href +LatexCommand href +name "bug #276431" +target "https://bugzilla.mozilla.org/show_bug.cgi?id=276431" + +\end_inset + +, this was fixed on 2010-09-08, so the next version should do the right + thing; at that point this feature will be queued for inclusion. +\end_layout + +\begin_layout Standard +You can check out how your browser does with SVG images with this +\begin_inset CommandInset href +LatexCommand href +name "SVG test page" +target "svg/svg-test.html" + +\end_inset + +. +\end_layout + +\begin_layout Subsubsection* +More controls for image conversion +\begin_inset CommandInset label +LatexCommand label +name "sub:More-controls-for" + +\end_inset + + +\end_layout + +\begin_layout Standard +eLyXer uses ImageMagick to convert images. + Some images (in EPS format, for example) do have blank borders, or they + come in varied sizes. + It would be nice to remove blank borders and have some kind of unified + resolution in the conversion, which would be passed to ImageMagick. +\end_layout + +\begin_layout Standard +As of 1.1.0, the improvements include using +\family typewriter +ps:use-cropbox=true +\family default + in ImageMagick for PostScript and EPS images. + Unified resolution has not been added as it might collide with picture + density, but suggestions are welcome. +\end_layout + +\begin_layout Subsubsection* +CSS controls +\begin_inset CommandInset label +LatexCommand label +name "sub:CSS-controls" + +\end_inset + + +\end_layout + +\begin_layout Standard +Proposed by JRAS on the elyxer-users mailing list, the following is a direct + quote of +\begin_inset CommandInset href +LatexCommand href +name "his message" +target "http://www.mail-archive.com/elyxer-users@nongnu.org/msg00194.html" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Quotes eld +\end_inset + +[\SpecialChar \ldots{} +]A mixed solution for CSS styles: +\end_layout + +\begin_layout Enumerate +The essential minimum css for math formatting (a compacted version of a + +\family typewriter +math.css +\family default + subset) included directly inside HTML head. +\end_layout + +\begin_layout Enumerate +Then a call to download the on-line full CSS, that can repeat the minimum + already included +\family typewriter +math.css +\family default + (from item 1) plus some other styles. + The default can be changed by +\family typewriter +--css +\family default + command line option. +\end_layout + +\begin_layout Enumerate +A new option ( +\family typewriter +--addcss +\family default +) to add another CSS defined by the user. + For example, to only redefine some styles from the default, etc. +\end_layout + +\begin_layout Standard +The styles should be included in that order (using the "cascading" property). + Item 1 is fixed in every HTML file. + Item 2 is always added and by default pointing to the eLyXer on-line css, + but it can be changed by option +\family typewriter +--css +\family default + to another url or file. + Item 3 is optional and its url would be added after the other two items, + only if the +\family typewriter +--addcss +\family default + option was used in conversion. +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\begin_layout Standard +As of 1.1.1, an option +\family typewriter +--embedcss +\family default + has been added which allows embedding one or more custom CSS files into + the resulting HTML document. + Also, +\family typewriter +--css +\family default + can be repeated as many times as desired to use several CSS files. +\end_layout + +\begin_layout Subsection +Contact Information +\end_layout + +\begin_layout Standard +If your problem does not appear in the above list, please let the author + know; you can find him at +\begin_inset CommandInset href +LatexCommand href +name "elyxer@gmail.com" +target "mailto:elyxer@gmail.com" +type "mailto:" + +\end_inset + +. + In the words of Rich Talley: +\begin_inset Quotes eld +\end_inset + +the tool's author really likes getting challenging documents and making + eLyXer work with them +\begin_inset Quotes erd +\end_inset + +. + You can send your sample documents and we will try to make eLyXer convert + them acceptably. + Any documents sent will be treated with the utmost confidentiality. +\end_layout + +\begin_layout Standard +You can also join the +\begin_inset CommandInset href +LatexCommand href +name "mailing list" +target "http://lists.nongnu.org/mailman/listinfo/elyxer-users" + +\end_inset + + to discuss any information related to eLyXer. + The author monitors the official LyX lists for mentions of eLyXer. + Bugs can also be reported at the +\begin_inset CommandInset href +LatexCommand href +name "Savannah page" +target "https://savannah.nongnu.org/bugs/?func=additem&group=elyxer" + +\end_inset + +. +\end_layout + +\begin_layout Subsection +Extending eLyXer +\end_layout + +\begin_layout Standard +eLyXer should now support most LyX features; but sometimes it will ignore + a command, sometimes it will signal it, and it might even refuse to work + with certain documents. + What can you do if eLyXer does not work with your LyX file? Worry not! + Its flexible approach to processing allows anyone to write support for + the missing commands. +\end_layout + +\begin_layout Standard +eLyXer is written in Python so that it does not need to be compiled; its + code is interpreted on the fly. + See the accompanying +\begin_inset CommandInset href +LatexCommand href +name "developer guide" +target "devguide.html" + +\end_inset + + to learn how to extend eLyXer for your own purposes. + If you know how to program in Python it should not be difficult to support + other LyX features. + If you don't your best bet is to ask the author. +\end_layout + +\begin_layout Section +FAQ +\end_layout + +\begin_layout Description +Q: What versions of LyX are supported? +\end_layout + +\begin_layout Description +A: The tool should work with all LyX versions from 1.5.5 to the latest and + greatest. + It has been tested on Linux, Mac OS X and Windows. +\end_layout + +\begin_layout Description +Q: There are indeed +\emph on +a ton +\emph default + of similar projects over the web. + Why add another one? +\end_layout + +\begin_layout Description +A: The four tools supported by LyX (tex4ht, hevea, tth and latex2html) gave + inferior results in 2009, and were quite inflexible. + The author found the need for a good converter, while at the same time + acknowledging the difficulty of the problem. +\end_layout + +\begin_layout Description +Q: Speaking of that: why build a LyX to HTML converter, instead of a more + generic LaTeX to HTML converter? +\end_layout + +\begin_layout Description +A: The problem space is quite simplified, and therefore progress is much + faster. + To make it even easier eLyXer has historically centered on the subset of + LyX functionality that is useful to most LyX users, leaving the rest for + a later stage. + Nowadays eLyXer aims to support the full LyX feature set. +\end_layout + +\begin_layout Description +Q: What can we expect from the tool in the future? +\end_layout + +\begin_layout Description +A: eLyXer should fulfill the needs of 99% of LyX users in the short term. + It has also learned a couple of tricks of its own such as page segmenting. + Eventually it could be distributed along with LyX as part of the standard + installer. +\end_layout + +\begin_layout Description +Q: Why did you leave out my favorite feature +\emph on + +\emph default +? +\end_layout + +\begin_layout Description +A: In short, because nobody asked for it. + Every feature which has been requested (either to me personally or to the + list) has been tended to, unless it was too far out or I forgot about it. + At this point of development every missing LyX feature will be considered + a high priority item for the next version, if at all possible to implement. +\end_layout + +\begin_layout Description +Q: My document changed its appearance without my intervention. + Was it black magic, elves or what? +\end_layout + +\begin_layout Description +A: It probably uses the online CSS file, which is regularly updated. + See section +\begin_inset CommandInset ref +LatexCommand ref +reference "sub:CSS" + +\end_inset + + for details. +\end_layout + +\begin_layout Description +Q: Why use an online CSS, instead of placing the CSS file in the same directory + as the converted file? +\end_layout + +\begin_layout Description +A: There were pros and cons. + An online CSS resource allowed me to update it for everyone at the same + time, but might make it more difficult for people without an internet connectio +n; local CSS files are more flexible but can also be confusing to novice + users. + In the end the online solution was preferred, with the +\family typewriter +--css +\family default + option as a fallback. + +\end_layout + +\begin_layout Description +Q: My MathJax pages are not rendering correctly; equations are silently + ignored. +\end_layout + +\begin_layout Description +A: Check that MathJax is installed on the same server as your pages; for + security reasons the browser's +\begin_inset Quotes eld +\end_inset + +same-origin +\begin_inset Quotes erd +\end_inset + + policy mandates that JavaScript can only be loaded from the same site as + the original page. + Also make sure that JavaScript is enabled on the browser. +\end_layout + +\begin_layout Description +Q: How can I disable hovering notes? Isn't there a +\family typewriter +--nohover +\family default + option? +\end_layout + +\begin_layout Description +A: It can be done using +\family typewriter +--footnotes margin +\family default +. + This will disable hovering text but keep footnotes in the margin. +\end_layout + +\begin_layout Description +Q: I found a bug, what should I do? +\end_layout + +\begin_layout Description +A: Just send it to the author at +\begin_inset CommandInset href +LatexCommand href +name "elyxer@gmail.com" +target "mailto:elyxer@gmail.com" +type "mailto:" + +\end_inset + +. + You can also report it to the +\begin_inset CommandInset href +LatexCommand href +name "Savannah interface" +target "https://savannah.nongnu.org/bugs/?func=additem&group=elyxer" + +\end_inset + +. +\end_layout + +\begin_layout Bibliography +\begin_inset CommandInset bibitem +LatexCommand bibitem +key "wordreference-elixir" + +\end_inset + +WordReference.com: +\begin_inset Quotes eld +\end_inset + +definition of elixir +\begin_inset Quotes erd +\end_inset + +, accessed March 2009. + +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +http://www.wordreference.com/definition/elixir +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Bibliography +\begin_inset CommandInset bibitem +LatexCommand bibitem +key "xhtml" + +\end_inset + +W3C: +\begin_inset Quotes eld +\end_inset + +XHTML™ 1.0 The Extensible HyperText Markup Language (Second Edition) +\begin_inset Quotes erd +\end_inset + +, revised 1 August 2002. + +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +http://www.w3.org/TR/xhtml1/ +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Bibliography +\begin_inset CommandInset bibitem +LatexCommand bibitem +key "html-401" + +\end_inset + +W3C: +\begin_inset Quotes eld +\end_inset + +HTML 4.01 Specification +\begin_inset Quotes erd +\end_inset + +, 24 December 1999. + +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +http://www.w3.org/TR/REC-html40/ +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Bibliography +\begin_inset CommandInset bibitem +LatexCommand bibitem +key "w3c-validator" + +\end_inset + +W3C: +\begin_inset Quotes eld +\end_inset + +Markup Validation Service +\begin_inset Quotes erd +\end_inset + +, accessed March 2009. + +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +http://validator.w3.org/ +\end_layout + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/elyxer.py elyxer-1.2.5/forks/jras-elyxer/elyxer.py --- elyxer-1.2.3/forks/jras-elyxer/elyxer.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/elyxer.py 2013-03-10 10:39:35.000000000 +0000 @@ -0,0 +1,10160 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090308 +# eLyXer main script +# http://www.nongnu.org/elyxer/ + + +import sys + + + + +import os.path + + + +import sys +import codecs + + + +import sys + +class Trace(object): + "A tracing class" + + debugmode = False + quietmode = False + showlinesmode = False + + prefix = None + + def debug(cls, message): + "Show a debug message" + if not Trace.debugmode or Trace.quietmode: + return + Trace.show(message, sys.stdout) + + def message(cls, message): + "Show a trace message" + if Trace.quietmode: + return + if Trace.prefix and Trace.showlinesmode: + message = Trace.prefix + message + Trace.show(message, sys.stdout) + + def error(cls, message): + "Show an error message" + message = '* ' + message + if Trace.prefix and Trace.showlinesmode: + message = Trace.prefix + message + Trace.show(message, sys.stderr) + + def fatal(cls, message): + "Show an error message and terminate" + Trace.error('FATAL: ' + message) + exit(-1) + + def show(cls, message, channel): + "Show a message out of a channel" + if sys.version_info < (3,0): + message = message.encode('utf-8') + channel.write(message + '\n') + + debug = classmethod(debug) + message = classmethod(message) + error = classmethod(error) + fatal = classmethod(fatal) + show = classmethod(show) + + + +class LineReader(object): + "Reads a file line by line" + + def __init__(self, filename): + if isinstance(filename, file): + self.file = filename + else: + self.file = codecs.open(filename, 'rU', 'utf-8') + self.linenumber = 1 + self.lastline = None + self.current = None + self.mustread = True + self.depleted = False + try: + self.readline() + except UnicodeDecodeError: + # try compressed file + import gzip + self.file = gzip.open(filename, 'rb') + self.readline() + + def setstart(self, firstline): + "Set the first line to read." + for i in range(firstline): + self.file.readline() + self.linenumber = firstline + + def setend(self, lastline): + "Set the last line to read." + self.lastline = lastline + + def currentline(self): + "Get the current line" + if self.mustread: + self.readline() + return self.current + + def nextline(self): + "Go to next line" + if self.depleted: + Trace.fatal('Read beyond file end') + self.mustread = True + + def readline(self): + "Read a line from elyxer.file" + self.current = self.file.readline() + if not isinstance(self.file, codecs.StreamReaderWriter): + self.current = self.current.decode('utf-8') + if len(self.current) == 0: + self.depleted = True + self.current = self.current.rstrip('\n\r') + self.linenumber += 1 + self.mustread = False + Trace.prefix = 'Line ' + unicode(self.linenumber) + ': ' + if self.linenumber % 1000 == 0: + Trace.message('Parsing') + + def finished(self): + "Find out if the file is finished" + if self.lastline and self.linenumber == self.lastline: + return True + if self.mustread: + self.readline() + return self.depleted + + def close(self): + self.file.close() + +class LineWriter(object): + "Writes a file as a series of lists" + + file = False + + def __init__(self, filename): + if isinstance(filename, file): + self.file = filename + self.filename = None + else: + self.filename = filename + + def write(self, strings): + "Write a list of strings" + for string in strings: + if not isinstance(string, basestring): + Trace.error('Not a string: ' + unicode(string) + ' in ' + unicode(strings)) + return + self.writestring(string) + + def writestring(self, string): + "Write a string" + if not self.file: + self.file = codecs.open(self.filename, 'w', "utf-8") + if self.file == sys.stdout and sys.version_info < (3,0): + string = string.encode('utf-8') + self.file.write(string) + + def writeline(self, line): + "Write a line to file" + self.writestring(line + '\n') + + def close(self): + self.file.close() + + + + +import os.path +import sys + + +class BibStylesConfig(object): + "Configuration class from elyxer.config file" + + abbrvnat = { + + u'@article':u'$authors. $title. $journal,{ {$volume:}$pages,} $month $year.{ doi: $doi.}{ URL $url.}{ $note.}', + u'cite':u'$surname($year)', + u'default':u'$authors. $title. $publisher, $year.{ URL $url.}{ $note.}', + } + + alpha = { + + u'@article':u'$authors. $title.{ $journal{, {$volume}{($number)}}{: $pages}{, $year}.}{ $url.}{ $filename.}{ $note.}', + u'cite':u'$Sur$YY', + u'default':u'$authors. $title.{ $journal,} $year.{ $url.}{ $filename.}{ $note.}', + } + + authordate2 = { + + u'@article':u'$authors. $year. $title. $journal, $volume($number), $pages.{ URL $url.}{ $note.}', + u'@book':u'$authors. $year. $title. $publisher.{ URL $url.}{ $note.}', + u'cite':u'$surname, $year', + u'default':u'$authors. $year. $title. $publisher.{ URL $url.}{ $note.}', + } + + default = { + + u'@article':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@book':u'{$authors: }$title{ ($editor, ed.)}.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@booklet':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@conference':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@inbook':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@incollection':u'$authors: $title{ in $booktitle{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@inproceedings':u'$authors: “$title”, $booktitle,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@manual':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@mastersthesis':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@misc':u'$authors: $title.{{ $publisher,}{ $howpublished,} $year.}{ URL $url.}{ $note.}', + u'@phdthesis':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@proceedings':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@techreport':u'$authors: $title, $year.{ URL $url.}{ $note.}', + u'@unpublished':u'$authors: “$title”, $journal, $year.{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + } + + defaulttags = { + u'YY':u'??', u'authors':u'', u'surname':u'', + } + + ieeetr = { + + u'@article':u'$authors, “$title”, $journal, vol. $volume, no. $number, pp. $pages, $year.{ URL $url.}{ $note.}', + u'@book':u'$authors, $title. $publisher, $year.{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors, “$title”. $year.{ URL $url.}{ $note.}', + } + + plain = { + + u'@article':u'$authors. $title.{ $journal{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL $url.}{ $note.}', + u'@book':u'$authors. $title. $publisher,{ $month} $year.{ URL $url.}{ $note.}', + u'@incollection':u'$authors. $title.{ In $booktitle {($editor, ed.)}.} $publisher,{ $month} $year.{ URL $url.}{ $note.}', + u'@inproceedings':u'$authors. $title. { $booktitle{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'{$authors. }$title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + } + + vancouver = { + + u'@article':u'$authors. $title. $journal, $year{;{$volume}{($number)}{:$pages}}.{ URL: $url.}{ $note.}', + u'@book':u'$authors. $title. {$publisher, }$year.{ URL: $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors. $title; {$publisher, }$year.{ $howpublished.}{ URL: $url.}{ $note.}', + } + +class BibTeXConfig(object): + "Configuration class from elyxer.config file" + + replaced = { + u'--':u'—', u'..':u'.', + } + +class ContainerConfig(object): + "Configuration class from elyxer.config file" + + endings = { + u'Align':u'\\end_layout', u'BarredText':u'\\bar', + u'BoldText':u'\\series', u'Cell':u'':u'>', + } + + html = { + u'/>':u'>', + } + + iso885915 = { + u' ':u' ', u' ':u' ', u' ':u' ', + } + + nonunicode = { + u' ':u' ', + } + +class FormulaConfig(object): + "Configuration class from elyxer.config file" + + alphacommands = { + u'\\AA':u'Å', u'\\AE':u'Æ', + u'\\AmS':u'AmS', u'\\Angstroem':u'Å', + u'\\DH':u'Ð', u'\\Koppa':u'Ϟ', u'\\L':u'Ł', u'\\Micro':u'µ', u'\\O':u'Ø', + u'\\OE':u'Œ', u'\\Sampi':u'Ϡ', u'\\Stigma':u'Ϛ', u'\\TH':u'Þ', + u'\\aa':u'å', u'\\ae':u'æ', u'\\alpha':u'α', u'\\beta':u'β', + u'\\delta':u'δ', u'\\dh':u'ð', u'\\digamma':u'ϝ', u'\\epsilon':u'ϵ', + u'\\eta':u'η', u'\\eth':u'ð', u'\\gamma':u'γ', u'\\i':u'ı', + u'\\imath':u'ı', u'\\iota':u'ι', u'\\j':u'ȷ', u'\\jmath':u'ȷ', + u'\\kappa':u'κ', u'\\koppa':u'ϟ', u'\\l':u'ł', u'\\lambda':u'λ', + u'\\mu':u'μ', u'\\nu':u'ν', u'\\o':u'ø', u'\\oe':u'œ', u'\\omega':u'ω', + u'\\phi':u'φ', u'\\pi':u'π', u'\\psi':u'ψ', u'\\rho':u'ρ', + u'\\sampi':u'ϡ', u'\\sigma':u'σ', u'\\ss':u'ß', u'\\stigma':u'ϛ', + u'\\tau':u'τ', u'\\tcohm':u'Ω', u'\\textcrh':u'ħ', u'\\th':u'þ', + u'\\theta':u'θ', u'\\upsilon':u'υ', u'\\varDelta':u'∆', + u'\\varGamma':u'Γ', u'\\varLambda':u'Λ', u'\\varOmega':u'Ω', + u'\\varPhi':u'Φ', u'\\varPi':u'Π', u'\\varPsi':u'Ψ', u'\\varSigma':u'Σ', + u'\\varTheta':u'Θ', u'\\varUpsilon':u'Υ', u'\\varXi':u'Ξ', + u'\\varbeta':u'ϐ', u'\\varepsilon':u'ε', u'\\varkappa':u'ϰ', + u'\\varphi':u'φ', u'\\varpi':u'ϖ', u'\\varrho':u'ϱ', u'\\varsigma':u'ς', + u'\\vartheta':u'ϑ', u'\\xi':u'ξ', u'\\zeta':u'ζ', + } + + array = { + u'begin':u'\\begin', u'cellseparator':u'&', u'end':u'\\end', + u'rowseparator':u'\\\\', + } + + bigbrackets = { + u'(':[u'⎛',u'⎜',u'⎝',], u')':[u'⎞',u'⎟',u'⎠',], u'[':[u'⎡',u'⎢',u'⎣',], + u']':[u'⎤',u'⎥',u'⎦',], u'{':[u'⎧',u'⎪',u'⎨',u'⎩',], u'|':[u'|',], + u'}':[u'⎫',u'⎪',u'⎬',u'⎭',], u'∥':[u'∥',], + } + + bigsymbols = { + u'∑':[u'⎲',u'⎳',], u'∫':[u'⌠',u'⌡',], + } + + bracketcommands = { + u'\\left':u'span class="symbol"', + u'\\left.':u'', + u'\\middle':u'span class="symbol"', u'\\right':u'span class="symbol"', + u'\\right.':u'', + } + + combiningfunctions = { + u'\\"':u'̈', u'\\\'':u'́', u'\\^':u'̂', u'\\`':u'̀', u'\\acute':u'́', + u'\\bar':u'̄', u'\\breve':u'̆', u'\\c':u'̧', u'\\check':u'̌', + u'\\dddot':u'⃛', u'\\ddot':u'̈', u'\\dot':u'̇', u'\\grave':u'̀', + u'\\hat':u'̂', u'\\mathring':u'̊', u'\\overleftarrow':u'⃖', + u'\\overrightarrow':u'⃗', u'\\r':u'̊', u'\\s':u'̩', + u'\\textcircled':u'⃝', u'\\textsubring':u'̥', u'\\tilde':u'̃', + u'\\v':u'̌', u'\\vec':u'⃗', u'\\~':u'̃', + } + + commands = { + u'\\ ':u' ', u'\\!':u'', u'\\#':u'#', u'\\$':u'$', u'\\%':u'%', + u'\\&':u'&', u'\\,':u' ', u'\\:':u' ', u'\\;':u' ', u'\\AC':u'∿', + u'\\APLcomment':u'⍝', u'\\APLdownarrowbox':u'⍗', u'\\APLinput':u'⍞', + u'\\APLinv':u'⌹', u'\\APLleftarrowbox':u'⍇', u'\\APLlog':u'⍟', + u'\\APLrightarrowbox':u'⍈', u'\\APLuparrowbox':u'⍐', u'\\Box':u'□', + u'\\Bumpeq':u'≎', u'\\CIRCLE':u'●', u'\\Cap':u'⋒', + u'\\CapitalDifferentialD':u'ⅅ', u'\\CheckedBox':u'☑', u'\\Circle':u'○', + u'\\Coloneqq':u'⩴', u'\\ComplexI':u'ⅈ', u'\\ComplexJ':u'ⅉ', + u'\\Corresponds':u'≙', u'\\Cup':u'⋓', u'\\Delta':u'Δ', u'\\Diamond':u'◇', + u'\\Diamondblack':u'◆', u'\\Diamonddot':u'⟐', u'\\DifferentialD':u'ⅆ', + u'\\Downarrow':u'⇓', u'\\EUR':u'€', u'\\Euler':u'ℇ', + u'\\ExponetialE':u'ⅇ', u'\\Finv':u'Ⅎ', u'\\Game':u'⅁', u'\\Gamma':u'Γ', + u'\\Im':u'ℑ', u'\\Join':u'⨝', u'\\LEFTCIRCLE':u'◖', u'\\LEFTcircle':u'◐', + u'\\LHD':u'◀', u'\\Lambda':u'Λ', u'\\Lbag':u'⟅', u'\\Leftarrow':u'⇐', + u'\\Lleftarrow':u'⇚', u'\\Longleftarrow':u'⟸', + u'\\Longleftrightarrow':u'⟺', u'\\Longrightarrow':u'⟹', u'\\Lparen':u'⦅', + u'\\Lsh':u'↰', u'\\Mapsfrom':u'⇐|', u'\\Mapsto':u'|⇒', u'\\Omega':u'Ω', + u'\\P':u'¶', u'\\Phi':u'Φ', u'\\Pi':u'Π', u'\\Pr':u'Pr', u'\\Psi':u'Ψ', + u'\\Qoppa':u'Ϙ', u'\\RHD':u'▶', u'\\RIGHTCIRCLE':u'◗', + u'\\RIGHTcircle':u'◑', u'\\Rbag':u'⟆', u'\\Re':u'ℜ', u'\\Rparen':u'⦆', + u'\\Rrightarrow':u'⇛', u'\\Rsh':u'↱', u'\\S':u'§', u'\\Sigma':u'Σ', + u'\\Square':u'☐', u'\\Subset':u'⋐', u'\\Sun':u'☉', u'\\Supset':u'⋑', + u'\\Theta':u'Θ', u'\\Uparrow':u'⇑', u'\\Updownarrow':u'⇕', + u'\\Upsilon':u'Υ', u'\\Vdash':u'⊩', u'\\Vert':u'∥', u'\\Vvdash':u'⊪', + u'\\XBox':u'☒', u'\\Xi':u'Ξ', u'\\Yup':u'⅄', u'\\\\':u'
      ', + u'\\_':u'_', u'\\aleph':u'ℵ', u'\\amalg':u'∐', u'\\anchor':u'⚓', + u'\\angle':u'∠', u'\\aquarius':u'♒', u'\\arccos':u'arccos', + u'\\arcsin':u'arcsin', u'\\arctan':u'arctan', u'\\arg':u'arg', + u'\\aries':u'♈', u'\\arrowbullet':u'➢', u'\\ast':u'∗', u'\\asymp':u'≍', + u'\\backepsilon':u'∍', u'\\backprime':u'‵', u'\\backsimeq':u'⋍', + u'\\backslash':u'\\', u'\\ballotx':u'✗', u'\\barwedge':u'⊼', + u'\\because':u'∵', u'\\beth':u'ℶ', u'\\between':u'≬', u'\\bigcap':u'∩', + u'\\bigcirc':u'○', u'\\bigcup':u'∪', u'\\bigodot':u'⊙', + u'\\bigoplus':u'⊕', u'\\bigotimes':u'⊗', u'\\bigsqcup':u'⊔', + u'\\bigstar':u'★', u'\\bigtriangledown':u'▽', u'\\bigtriangleup':u'△', + u'\\biguplus':u'⊎', u'\\bigvee':u'∨', u'\\bigwedge':u'∧', + u'\\biohazard':u'☣', u'\\blacklozenge':u'⧫', u'\\blacksmiley':u'☻', + u'\\blacksquare':u'■', u'\\blacktriangle':u'▲', + u'\\blacktriangledown':u'▼', u'\\blacktriangleleft':u'◂', + u'\\blacktriangleright':u'▶', u'\\blacktriangleup':u'▴', u'\\bot':u'⊥', + u'\\bowtie':u'⋈', u'\\box':u'▫', u'\\boxast':u'⧆', u'\\boxbar':u'◫', + u'\\boxbox':u'⧈', u'\\boxbslash':u'⧅', u'\\boxcircle':u'⧇', + u'\\boxdot':u'⊡', u'\\boxminus':u'⊟', u'\\boxplus':u'⊞', + u'\\boxslash':u'⧄', u'\\boxtimes':u'⊠', u'\\bullet':u'•', + u'\\bumpeq':u'≏', u'\\cancer':u'♋', u'\\cap':u'∩', u'\\capricornus':u'♑', + u'\\cat':u'⁀', u'\\cdot':u'⋅', u'\\cdots':u'⋯', u'\\cent':u'¢', + u'\\centerdot':u'∙', u'\\checkmark':u'✓', u'\\chi':u'χ', u'\\circ':u'○', + u'\\circeq':u'≗', u'\\circlearrowleft':u'↺', u'\\circlearrowright':u'↻', + u'\\circledR':u'®', u'\\circledast':u'⊛', u'\\circledbslash':u'⦸', + u'\\circledcirc':u'⊚', u'\\circleddash':u'⊝', u'\\circledgtr':u'⧁', + u'\\circledless':u'⧀', u'\\clubsuit':u'♣', u'\\coloneqq':u'≔', + u'\\complement':u'∁', u'\\cong':u'≅', u'\\coprod':u'∐', + u'\\copyright':u'©', u'\\cos':u'cos', u'\\cosh':u'cosh', u'\\cot':u'cot', + u'\\coth':u'coth', u'\\csc':u'csc', u'\\cup':u'∪', u'\\curlyvee':u'⋎', + u'\\curlywedge':u'⋏', u'\\curvearrowleft':u'↶', + u'\\curvearrowright':u'↷', u'\\dag':u'†', u'\\dagger':u'†', + u'\\daleth':u'ℸ', u'\\dashleftarrow':u'⇠', u'\\dashv':u'⊣', + u'\\ddag':u'‡', u'\\ddagger':u'‡', u'\\ddots':u'⋱', u'\\deg':u'deg', + u'\\det':u'det', u'\\diagdown':u'╲', u'\\diagup':u'╱', + u'\\diameter':u'⌀', u'\\diamond':u'◇', u'\\diamondsuit':u'♦', + u'\\dim':u'dim', u'\\div':u'÷', u'\\divideontimes':u'⋇', + u'\\dotdiv':u'∸', u'\\doteq':u'≐', u'\\doteqdot':u'≑', u'\\dotplus':u'∔', + u'\\dots':u'…', u'\\doublebarwedge':u'⌆', u'\\downarrow':u'↓', + u'\\downdownarrows':u'⇊', u'\\downharpoonleft':u'⇃', + u'\\downharpoonright':u'⇂', u'\\dsub':u'⩤', u'\\earth':u'♁', + u'\\eighthnote':u'♪', u'\\ell':u'ℓ', u'\\emptyset':u'∅', + u'\\eqcirc':u'≖', u'\\eqcolon':u'≕', u'\\eqsim':u'≂', u'\\euro':u'€', + u'\\exists':u'∃', u'\\exp':u'exp', u'\\fallingdotseq':u'≒', + u'\\fcmp':u'⨾', u'\\female':u'♀', u'\\flat':u'♭', u'\\forall':u'∀', + u'\\fourth':u'⁗', u'\\frown':u'⌢', u'\\frownie':u'☹', u'\\gcd':u'gcd', + u'\\gemini':u'♊', u'\\geq)':u'≥', u'\\geqq':u'≧', u'\\geqslant':u'≥', + u'\\gets':u'←', u'\\gg':u'≫', u'\\ggg':u'⋙', u'\\gimel':u'ℷ', + u'\\gneqq':u'≩', u'\\gnsim':u'⋧', u'\\gtrdot':u'⋗', u'\\gtreqless':u'⋚', + u'\\gtreqqless':u'⪌', u'\\gtrless':u'≷', u'\\gtrsim':u'≳', + u'\\guillemotleft':u'«', u'\\guillemotright':u'»', u'\\hbar':u'ℏ', + u'\\heartsuit':u'♥', u'\\hfill':u' ', + u'\\hom':u'hom', u'\\hookleftarrow':u'↩', u'\\hookrightarrow':u'↪', + u'\\hslash':u'ℏ', u'\\idotsint':u'∫⋯∫', + u'\\iiint':u'', + u'\\iint':u'', u'\\imath':u'ı', + u'\\inf':u'inf', u'\\infty':u'∞', u'\\intercal':u'⊺', + u'\\interleave':u'⫴', u'\\invamp':u'⅋', u'\\invneg':u'⌐', + u'\\jmath':u'ȷ', u'\\jupiter':u'♃', u'\\ker':u'ker', u'\\land':u'∧', + u'\\landupint':u'', u'\\lang':u'⟪', + u'\\langle':u'⟨', u'\\lblot':u'⦉', u'\\lbrace':u'{', u'\\lbrace)':u'{', + u'\\lbrack':u'[', u'\\lceil':u'⌈', u'\\ldots':u'…', u'\\leadsto':u'⇝', + u'\\leftarrow)':u'←', u'\\leftarrowtail':u'↢', u'\\leftarrowtobar':u'⇤', + u'\\leftharpoondown':u'↽', u'\\leftharpoonup':u'↼', + u'\\leftleftarrows':u'⇇', u'\\leftleftharpoons':u'⥢', u'\\leftmoon':u'☾', + u'\\leftrightarrow':u'↔', u'\\leftrightarrows':u'⇆', + u'\\leftrightharpoons':u'⇋', u'\\leftthreetimes':u'⋋', u'\\leo':u'♌', + u'\\leq)':u'≤', u'\\leqq':u'≦', u'\\leqslant':u'≤', u'\\lessdot':u'⋖', + u'\\lesseqgtr':u'⋛', u'\\lesseqqgtr':u'⪋', u'\\lessgtr':u'≶', + u'\\lesssim':u'≲', u'\\lfloor':u'⌊', u'\\lg':u'lg', u'\\lgroup':u'⟮', + u'\\lhd':u'⊲', u'\\libra':u'♎', u'\\lightning':u'↯', u'\\limg':u'⦇', + u'\\liminf':u'liminf', u'\\limsup':u'limsup', u'\\ll':u'≪', + u'\\llbracket':u'⟦', u'\\llcorner':u'⌞', u'\\lll':u'⋘', u'\\ln':u'ln', + u'\\lneqq':u'≨', u'\\lnot':u'¬', u'\\lnsim':u'⋦', u'\\log':u'log', + u'\\longleftarrow':u'⟵', u'\\longleftrightarrow':u'⟷', + u'\\longmapsto':u'⟼', u'\\longrightarrow':u'⟶', u'\\looparrowleft':u'↫', + u'\\looparrowright':u'↬', u'\\lor':u'∨', u'\\lozenge':u'◊', + u'\\lrcorner':u'⌟', u'\\ltimes':u'⋉', u'\\lyxlock':u'', u'\\male':u'♂', + u'\\maltese':u'✠', u'\\mapsfrom':u'↤', u'\\mapsto':u'↦', + u'\\mathcircumflex':u'^', u'\\max':u'max', u'\\measuredangle':u'∡', + u'\\medbullet':u'⚫', u'\\medcirc':u'⚪', u'\\mercury':u'☿', u'\\mho':u'℧', + u'\\mid':u'∣', u'\\min':u'min', u'\\models':u'⊨', u'\\mp':u'∓', + u'\\multimap':u'⊸', u'\\nLeftarrow':u'⇍', u'\\nLeftrightarrow':u'⇎', + u'\\nRightarrow':u'⇏', u'\\nVDash':u'⊯', u'\\nabla':u'∇', + u'\\napprox':u'≉', u'\\natural':u'♮', u'\\ncong':u'≇', u'\\nearrow':u'↗', + u'\\neg':u'¬', u'\\neg)':u'¬', u'\\neptune':u'♆', u'\\nequiv':u'≢', + u'\\newline':u'
      ', u'\\nexists':u'∄', u'\\ngeqslant':u'≱', + u'\\ngtr':u'≯', u'\\ngtrless':u'≹', u'\\ni':u'∋', u'\\ni)':u'∋', + u'\\nleftarrow':u'↚', u'\\nleftrightarrow':u'↮', u'\\nleqslant':u'≰', + u'\\nless':u'≮', u'\\nlessgtr':u'≸', u'\\nmid':u'∤', u'\\nolimits':u'', + u'\\nonumber':u'', u'\\not':u'¬', u'\\not<':u'≮', u'\\not=':u'≠', + u'\\not>':u'≯', u'\\notbackslash':u'⍀', u'\\notin':u'∉', u'\\notni':u'∌', + u'\\notslash':u'⌿', u'\\nparallel':u'∦', u'\\nprec':u'⊀', + u'\\nrightarrow':u'↛', u'\\nsim':u'≁', u'\\nsimeq':u'≄', + u'\\nsqsubset':u'⊏̸', u'\\nsubseteq':u'⊈', u'\\nsucc':u'⊁', + u'\\nsucccurlyeq':u'⋡', u'\\nsupset':u'⊅', u'\\nsupseteq':u'⊉', + u'\\ntriangleleft':u'⋪', u'\\ntrianglelefteq':u'⋬', + u'\\ntriangleright':u'⋫', u'\\ntrianglerighteq':u'⋭', u'\\nvDash':u'⊭', + u'\\nvdash':u'⊬', u'\\nwarrow':u'↖', u'\\odot':u'⊙', + u'\\officialeuro':u'€', u'\\oiiint':u'', + u'\\oiint':u'', + u'\\oint':u'', + u'\\ointclockwise':u'', + u'\\ointctrclockwise':u'', + u'\\ominus':u'⊖', u'\\oplus':u'⊕', u'\\oslash':u'⊘', u'\\otimes':u'⊗', + u'\\owns':u'∋', u'\\parallel':u'∥', u'\\partial':u'∂', u'\\pencil':u'✎', + u'\\perp':u'⊥', u'\\pisces':u'♓', u'\\pitchfork':u'⋔', u'\\pluto':u'♇', + u'\\pm':u'±', u'\\pointer':u'➪', u'\\pointright':u'☞', u'\\pounds':u'£', + u'\\prec':u'≺', u'\\preccurlyeq':u'≼', u'\\preceq':u'≼', + u'\\precsim':u'≾', u'\\prime':u'′', u'\\prompto':u'∝', u'\\qoppa':u'ϙ', + u'\\qquad':u' ', u'\\quad':u' ', u'\\quarternote':u'♩', + u'\\radiation':u'☢', u'\\rang':u'⟫', u'\\rangle':u'⟩', u'\\rblot':u'⦊', + u'\\rbrace':u'}', u'\\rbrace)':u'}', u'\\rbrack':u']', u'\\rceil':u'⌉', + u'\\recycle':u'♻', u'\\rfloor':u'⌋', u'\\rgroup':u'⟯', u'\\rhd':u'⊳', + u'\\rightangle':u'∟', u'\\rightarrow)':u'→', u'\\rightarrowtail':u'↣', + u'\\rightarrowtobar':u'⇥', u'\\rightharpoondown':u'⇁', + u'\\rightharpoonup':u'⇀', u'\\rightharpooondown':u'⇁', + u'\\rightharpooonup':u'⇀', u'\\rightleftarrows':u'⇄', + u'\\rightleftharpoons':u'⇌', u'\\rightmoon':u'☽', + u'\\rightrightarrows':u'⇉', u'\\rightrightharpoons':u'⥤', + u'\\rightthreetimes':u'⋌', u'\\rimg':u'⦈', u'\\risingdotseq':u'≓', + u'\\rrbracket':u'⟧', u'\\rsub':u'⩥', u'\\rtimes':u'⋊', + u'\\sagittarius':u'♐', u'\\saturn':u'♄', u'\\scorpio':u'♏', + u'\\searrow':u'↘', u'\\sec':u'sec', u'\\second':u'″', u'\\setminus':u'∖', + u'\\sharp':u'♯', u'\\simeq':u'≃', u'\\sin':u'sin', u'\\sinh':u'sinh', + u'\\sixteenthnote':u'♬', u'\\skull':u'☠', u'\\slash':u'∕', + u'\\smallsetminus':u'∖', u'\\smalltriangledown':u'▿', + u'\\smalltriangleleft':u'◃', u'\\smalltriangleright':u'▹', + u'\\smalltriangleup':u'▵', u'\\smile':u'⌣', u'\\smiley':u'☺', + u'\\spadesuit':u'♠', u'\\spddot':u'¨', u'\\sphat':u'', + u'\\sphericalangle':u'∢', u'\\spot':u'⦁', u'\\sptilde':u'~', + u'\\sqcap':u'⊓', u'\\sqcup':u'⊔', u'\\sqsubset':u'⊏', + u'\\sqsubseteq':u'⊑', u'\\sqsupset':u'⊐', u'\\sqsupseteq':u'⊒', + u'\\square':u'□', u'\\sslash':u'⫽', u'\\star':u'⋆', u'\\steaming':u'☕', + u'\\subseteqq':u'⫅', u'\\subsetneqq':u'⫋', u'\\succ':u'≻', + u'\\succcurlyeq':u'≽', u'\\succeq':u'≽', u'\\succnsim':u'⋩', + u'\\succsim':u'≿', u'\\sun':u'☼', u'\\sup':u'sup', u'\\supseteqq':u'⫆', + u'\\supsetneqq':u'⫌', u'\\surd':u'√', u'\\swarrow':u'↙', + u'\\swords':u'⚔', u'\\talloblong':u'⫾', u'\\tan':u'tan', + u'\\tanh':u'tanh', u'\\taurus':u'♉', u'\\textasciicircum':u'^', + u'\\textasciitilde':u'~', u'\\textbackslash':u'\\', + u'\\textcopyright':u'©\'', u'\\textdegree':u'°', u'\\textellipsis':u'…', + u'\\textemdash':u'—', u'\\textendash':u'—', u'\\texteuro':u'€', + u'\\textgreater':u'>', u'\\textless':u'<', u'\\textordfeminine':u'ª', + u'\\textordmasculine':u'º', u'\\textquotedblleft':u'“', + u'\\textquotedblright':u'”', u'\\textquoteright':u'’', + u'\\textregistered':u'®', u'\\textrightarrow':u'→', + u'\\textsection':u'§', u'\\texttrademark':u'™', + u'\\texttwosuperior':u'²', u'\\textvisiblespace':u' ', + u'\\therefore':u'∴', u'\\third':u'‴', u'\\top':u'⊤', u'\\triangle':u'△', + u'\\triangleleft':u'⊲', u'\\trianglelefteq':u'⊴', u'\\triangleq':u'≜', + u'\\triangleright':u'▷', u'\\trianglerighteq':u'⊵', + u'\\twoheadleftarrow':u'↞', u'\\twoheadrightarrow':u'↠', + u'\\twonotes':u'♫', u'\\udot':u'⊍', u'\\ulcorner':u'⌜', u'\\unlhd':u'⊴', + u'\\unrhd':u'⊵', u'\\unrhl':u'⊵', u'\\uparrow':u'↑', + u'\\updownarrow':u'↕', u'\\upharpoonleft':u'↿', u'\\upharpoonright':u'↾', + u'\\uplus':u'⊎', u'\\upuparrows':u'⇈', u'\\uranus':u'♅', + u'\\urcorner':u'⌝', u'\\vDash':u'⊨', u'\\varclubsuit':u'♧', + u'\\vardiamondsuit':u'♦', u'\\varheartsuit':u'♥', u'\\varnothing':u'∅', + u'\\varspadesuit':u'♤', u'\\vdash':u'⊢', u'\\vdots':u'⋮', u'\\vee':u'∨', + u'\\vee)':u'∨', u'\\veebar':u'⊻', u'\\vert':u'∣', u'\\virgo':u'♍', + u'\\warning':u'⚠', u'\\wasylozenge':u'⌑', u'\\wedge':u'∧', + u'\\wedge)':u'∧', u'\\wp':u'℘', u'\\wr':u'≀', u'\\yen':u'¥', + u'\\yinyang':u'☯', u'\\{':u'{', u'\\|':u'∥', u'\\}':u'}', + } + + decoratedcommand = { + + } + + decoratingfunctions = { + u'\\overleftarrow':u'⟵', u'\\overrightarrow':u'⟶', u'\\widehat':u'^', + } + + endings = { + u'bracket':u'}', u'complex':u'\\]', u'endafter':u'}', + u'endbefore':u'\\end{', u'squarebracket':u']', + } + + environments = { + u'align':[u'r',u'l',], u'eqnarray':[u'r',u'c',u'l',], + u'gathered':[u'l',u'l',], + } + + fontfunctions = { + u'\\boldsymbol':u'b', u'\\mathbb':u'span class="blackboard"', + u'\\mathbb{A}':u'𝔸', u'\\mathbb{B}':u'𝔹', u'\\mathbb{C}':u'ℂ', + u'\\mathbb{D}':u'𝔻', u'\\mathbb{E}':u'𝔼', u'\\mathbb{F}':u'𝔽', + u'\\mathbb{G}':u'𝔾', u'\\mathbb{H}':u'ℍ', u'\\mathbb{J}':u'𝕁', + u'\\mathbb{K}':u'𝕂', u'\\mathbb{L}':u'𝕃', u'\\mathbb{N}':u'ℕ', + u'\\mathbb{O}':u'𝕆', u'\\mathbb{P}':u'ℙ', u'\\mathbb{Q}':u'ℚ', + u'\\mathbb{R}':u'ℝ', u'\\mathbb{S}':u'𝕊', u'\\mathbb{T}':u'𝕋', + u'\\mathbb{W}':u'𝕎', u'\\mathbb{Z}':u'ℤ', u'\\mathbf':u'b', + u'\\mathcal':u'span class="scriptfont"', u'\\mathcal{B}':u'ℬ', + u'\\mathcal{E}':u'ℰ', u'\\mathcal{F}':u'ℱ', u'\\mathcal{H}':u'ℋ', + u'\\mathcal{I}':u'ℐ', u'\\mathcal{L}':u'ℒ', u'\\mathcal{M}':u'ℳ', + u'\\mathcal{R}':u'ℛ', u'\\mathfrak':u'span class="fraktur"', + u'\\mathfrak{C}':u'ℭ', u'\\mathfrak{F}':u'𝔉', u'\\mathfrak{H}':u'ℌ', + u'\\mathfrak{I}':u'ℑ', u'\\mathfrak{R}':u'ℜ', u'\\mathfrak{Z}':u'ℨ', + u'\\mathit':u'i', u'\\mathring{A}':u'Å', u'\\mathring{U}':u'Ů', + u'\\mathring{a}':u'å', u'\\mathring{u}':u'ů', u'\\mathring{w}':u'ẘ', + u'\\mathring{y}':u'ẙ', u'\\mathrm':u'span class="mathrm"', + u'\\mathscr':u'span class="scriptfont"', u'\\mathscr{B}':u'ℬ', + u'\\mathscr{E}':u'ℰ', u'\\mathscr{F}':u'ℱ', u'\\mathscr{H}':u'ℋ', + u'\\mathscr{I}':u'ℐ', u'\\mathscr{L}':u'ℒ', u'\\mathscr{M}':u'ℳ', + u'\\mathscr{R}':u'ℛ', u'\\mathsf':u'span class="mathsf"', + u'\\mathtt':u'tt', + } + + hybridfunctions = { + u'\\addcontentsline':[u'{$p!}{$q!}{$r!}',u'f0{}',u'ignored',], + u'\\addtocontents':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\backmatter':[u'',u'f0{}',u'ignored',], + u'\\binom':[u'{$1}{$2}',u'f2{(}f0{f1{$1}f1{$2}}f2{)}',u'span class="binom"',u'span class="binomstack"',u'span class="bigsymbol"',], + u'\\boxed':[u'{$1}',u'f0{$1}',u'span class="boxed"',], + u'\\cfrac':[u'[$p!]{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator align-$p"',u'span class="denominator"',u'span class="ignored"',], + u'\\color':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], + u'\\colorbox':[u'{$p!}{$1}',u'f0{$1}',u'span class="colorbox" style="background: $p;"',], + u'\\dbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], + u'\\dfrac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], + u'\\displaystyle':[u'{$1}',u'f0{$1}',u'span class="displaystyle"',], + u'\\fancyfoot':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fancyhead':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fbox':[u'{$1}',u'f0{$1}',u'span class="fbox"',], + u'\\fboxrule':[u'{$p!}',u'f0{}',u'ignored',], + u'\\fboxsep':[u'{$p!}',u'f0{}',u'ignored',], + u'\\fcolorbox':[u'{$p!}{$q!}{$1}',u'f0{$1}',u'span class="boxed" style="border-color: $p; background: $q;"',], + u'\\frac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], + u'\\framebox':[u'[$p!][$q!]{$1}',u'f0{$1}',u'span class="framebox align-$q" style="width: $p;"',], + u'\\frontmatter':[u'',u'f0{}',u'ignored',], + u'\\href':[u'[$o]{$u!}{$t!}',u'f0{$t}',u'a href="$u"',], + u'\\hspace':[u'{$p!}',u'f0{ }',u'span class="hspace" style="width: $p;"',], + u'\\leftroot':[u'{$p!}',u'f0{ }',u'span class="leftroot" style="width: $p;px"',], + u'\\mainmatter':[u'',u'f0{}',u'ignored',], + u'\\markboth':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\markright':[u'{$p!}',u'f0{}',u'ignored',], + u'\\nicefrac':[u'{$1}{$2}',u'f0{f1{$1}⁄f2{$2}}',u'span class="fraction"',u'sup class="numerator"',u'sub class="denominator"',u'span class="ignored"',], + u'\\parbox':[u'[$p!]{$w!}{$1}',u'f0{1}',u'div class="Boxed" style="width: $w;"',], + u'\\raisebox':[u'{$p!}{$1}',u'f0{$1.font}',u'span class="raisebox" style="vertical-align: $p;"',], + u'\\renewenvironment':[u'{$1!}{$2!}{$3!}',u'',], + u'\\rule':[u'[$v!]{$w!}{$h!}',u'f0/',u'hr class="line" style="width: $w; height: $h;"',], + u'\\scriptscriptstyle':[u'{$1}',u'f0{$1}',u'span class="scriptscriptstyle"',], + u'\\scriptstyle':[u'{$1}',u'f0{$1}',u'span class="scriptstyle"',], + u'\\sqrt':[u'[$0]{$1}',u'f0{f1{$0}f2{√}f4{(}f3{$1}f4{)}}',u'span class="sqrt"',u'sup class="root"',u'span class="radical"',u'span class="root"',u'span class="ignored"',], + u'\\stackrel':[u'{$1}{$2}',u'f0{f1{$1}f2{$2}}',u'span class="stackrel"',u'span class="upstackrel"',u'span class="downstackrel"',], + u'\\tbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], + u'\\textcolor':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], + u'\\textstyle':[u'{$1}',u'f0{$1}',u'span class="textstyle"',], + u'\\thispagestyle':[u'{$p!}',u'f0{}',u'ignored',], + u'\\unit':[u'[$0]{$1}',u'$0f0{$1.font}',u'span class="unit"',], + u'\\unitfrac':[u'[$0]{$1}{$2}',u'$0f0{f1{$1.font}⁄f2{$2.font}}',u'span class="fraction"',u'sup class="unit"',u'sub class="unit"',], + u'\\uproot':[u'{$p!}',u'f0{ }',u'span class="uproot" style="width: $p;px"',], + u'\\url':[u'{$u!}',u'f0{$u}',u'a href="$u"',], + u'\\vspace':[u'{$p!}',u'f0{ }',u'span class="vspace" style="height: $p;"',], + } + + hybridsizes = { + u'\\binom':u'$1+$2', u'\\cfrac':u'$1+$2', u'\\dbinom':u'$1+$2+1', + u'\\dfrac':u'$1+$2', u'\\frac':u'$1+$2', u'\\tbinom':u'$1+$2+1', + } + + labelfunctions = { + u'\\label':u'a name="#"', + } + + limitcommands = { + u'\\biginterleave':u'⫼', u'\\bigsqcap':u'⨅', u'\\fint':u'⨏', + u'\\iiiint':u'⨌', u'\\int':u'∫', u'\\intop':u'∫', u'\\lim':u'lim', + u'\\prod':u'∏', u'\\smallint':u'∫', u'\\sqint':u'⨖', u'\\sum':u'∑', + u'\\varointclockwise':u'∲', u'\\varprod':u'⨉', u'\\zcmp':u'⨟', + u'\\zhide':u'⧹', u'\\zpipe':u'⨠', u'\\zproject':u'⨡', + } + + misccommands = { + u'\\limits':u'LimitPreviousCommand', u'\\newcommand':u'MacroDefinition', + u'\\renewcommand':u'MacroDefinition', + u'\\setcounter':u'SetCounterFunction', u'\\tag':u'FormulaTag', + u'\\tag*':u'FormulaTag', u'\\today':u'TodayCommand', + } + + modified = { + u'\n':u'', u' ':u'', u'$':u'', u'&':u' ', u'\'':u'’', u'+':u' + ', + u',':u', ', u'-':u' − ', u'/':u' ⁄ ', u'<':u' < ', u'=':u' = ', + u'>':u' > ', u'@':u'', u'~':u'', + } + + onefunctions = { + u'\\Big':u'span class="bigsymbol"', u'\\Bigg':u'span class="hugesymbol"', + u'\\bar':u'span class="bar"', u'\\begin{array}':u'span class="arraydef"', + u'\\big':u'span class="symbol"', u'\\bigg':u'span class="largesymbol"', + u'\\bigl':u'span class="bigsymbol"', u'\\bigr':u'span class="bigsymbol"', + u'\\centering':u'span class="align-center"', + u'\\ensuremath':u'span class="ensuremath"', + u'\\hphantom':u'span class="phantom"', + u'\\noindent':u'span class="noindent"', + u'\\overbrace':u'span class="overbrace"', + u'\\overline':u'span class="overline"', + u'\\phantom':u'span class="phantom"', + u'\\underbrace':u'span class="underbrace"', u'\\underline':u'u', + u'\\vphantom':u'span class="phantom"', + } + + spacedcommands = { + u'\\Bot':u'⫫', u'\\Doteq':u'≑', u'\\DownArrowBar':u'⤓', + u'\\DownLeftTeeVector':u'⥞', u'\\DownLeftVectorBar':u'⥖', + u'\\DownRightTeeVector':u'⥟', u'\\DownRightVectorBar':u'⥗', + u'\\Equal':u'⩵', u'\\LeftArrowBar':u'⇤', u'\\LeftDownTeeVector':u'⥡', + u'\\LeftDownVectorBar':u'⥙', u'\\LeftTeeVector':u'⥚', + u'\\LeftTriangleBar':u'⧏', u'\\LeftUpTeeVector':u'⥠', + u'\\LeftUpVectorBar':u'⥘', u'\\LeftVectorBar':u'⥒', + u'\\Leftrightarrow':u'⇔', u'\\Longmapsfrom':u'⟽', u'\\Longmapsto':u'⟾', + u'\\MapsDown':u'↧', u'\\MapsUp':u'↥', u'\\Nearrow':u'⇗', + u'\\NestedGreaterGreater':u'⪢', u'\\NestedLessLess':u'⪡', + u'\\NotGreaterLess':u'≹', u'\\NotGreaterTilde':u'≵', + u'\\NotLessTilde':u'≴', u'\\Nwarrow':u'⇖', u'\\Proportion':u'∷', + u'\\RightArrowBar':u'⇥', u'\\RightDownTeeVector':u'⥝', + u'\\RightDownVectorBar':u'⥕', u'\\RightTeeVector':u'⥛', + u'\\RightTriangleBar':u'⧐', u'\\RightUpTeeVector':u'⥜', + u'\\RightUpVectorBar':u'⥔', u'\\RightVectorBar':u'⥓', + u'\\Rightarrow':u'⇒', u'\\Same':u'⩶', u'\\Searrow':u'⇘', + u'\\Swarrow':u'⇙', u'\\Top':u'⫪', u'\\UpArrowBar':u'⤒', u'\\VDash':u'⊫', + u'\\approx':u'≈', u'\\approxeq':u'≊', u'\\backsim':u'∽', u'\\barin':u'⋶', + u'\\barleftharpoon':u'⥫', u'\\barrightharpoon':u'⥭', u'\\bij':u'⤖', + u'\\coloneq':u'≔', u'\\corresponds':u'≙', u'\\curlyeqprec':u'⋞', + u'\\curlyeqsucc':u'⋟', u'\\dashrightarrow':u'⇢', u'\\dlsh':u'↲', + u'\\downdownharpoons':u'⥥', u'\\downuparrows':u'⇵', + u'\\downupharpoons':u'⥯', u'\\drsh':u'↳', u'\\eqslantgtr':u'⪖', + u'\\eqslantless':u'⪕', u'\\equiv':u'≡', u'\\ffun':u'⇻', u'\\finj':u'⤕', + u'\\ge':u'≥', u'\\geq':u'≥', u'\\ggcurly':u'⪼', u'\\gnapprox':u'⪊', + u'\\gneq':u'⪈', u'\\gtrapprox':u'⪆', u'\\hash':u'⋕', u'\\iddots':u'⋰', + u'\\implies':u' ⇒ ', u'\\in':u'∈', u'\\le':u'≤', u'\\leftarrow':u'←', + u'\\leftarrowtriangle':u'⇽', u'\\leftbarharpoon':u'⥪', + u'\\leftrightarrowtriangle':u'⇿', u'\\leftrightharpoon':u'⥊', + u'\\leftrightharpoondown':u'⥐', u'\\leftrightharpoonup':u'⥎', + u'\\leftrightsquigarrow':u'↭', u'\\leftslice':u'⪦', + u'\\leftsquigarrow':u'⇜', u'\\leftupdownharpoon':u'⥑', u'\\leq':u'≤', + u'\\lessapprox':u'⪅', u'\\llcurly':u'⪻', u'\\lnapprox':u'⪉', + u'\\lneq':u'⪇', u'\\longmapsfrom':u'⟻', u'\\multimapboth':u'⧟', + u'\\multimapdotbothA':u'⊶', u'\\multimapdotbothB':u'⊷', + u'\\multimapinv':u'⟜', u'\\nVdash':u'⊮', u'\\ne':u'≠', u'\\neq':u'≠', + u'\\ngeq':u'≱', u'\\nleq':u'≰', u'\\nni':u'∌', u'\\not\\in':u'∉', + u'\\notasymp':u'≭', u'\\npreceq':u'⋠', u'\\nsqsubseteq':u'⋢', + u'\\nsqsupseteq':u'⋣', u'\\nsubset':u'⊄', u'\\nsucceq':u'⋡', + u'\\pfun':u'⇸', u'\\pinj':u'⤔', u'\\precapprox':u'⪷', u'\\preceqq':u'⪳', + u'\\precnapprox':u'⪹', u'\\precnsim':u'⋨', u'\\propto':u'∝', + u'\\psur':u'⤀', u'\\rightarrow':u'→', u'\\rightarrowtriangle':u'⇾', + u'\\rightbarharpoon':u'⥬', u'\\rightleftharpoon':u'⥋', + u'\\rightslice':u'⪧', u'\\rightsquigarrow':u'⇝', + u'\\rightupdownharpoon':u'⥏', u'\\sim':u'~', u'\\strictfi':u'⥼', + u'\\strictif':u'⥽', u'\\subset':u'⊂', u'\\subseteq':u'⊆', + u'\\subsetneq':u'⊊', u'\\succapprox':u'⪸', u'\\succeqq':u'⪴', + u'\\succnapprox':u'⪺', u'\\supset':u'⊃', u'\\supseteq':u'⊇', + u'\\supsetneq':u'⊋', u'\\times':u'×', u'\\to':u'→', + u'\\updownarrows':u'⇅', u'\\updownharpoons':u'⥮', u'\\upupharpoons':u'⥣', + u'\\vartriangleleft':u'⊲', u'\\vartriangleright':u'⊳', + } + + starts = { + u'beginafter':u'}', u'beginbefore':u'\\begin{', u'bracket':u'{', + u'command':u'\\', u'comment':u'%', u'complex':u'\\[', u'simple':u'$', + u'squarebracket':u'[', u'unnumbered':u'*', + } + + symbolfunctions = { + u'^':u'sup', u'_':u'sub', + } + + textfunctions = { + u'\\mbox':u'span class="mbox"', u'\\text':u'span class="text"', + u'\\textbf':u'b', u'\\textipa':u'span class="textipa"', u'\\textit':u'i', + u'\\textnormal':u'span class="textnormal"', + u'\\textrm':u'span class="textrm"', + u'\\textsc':u'span class="versalitas"', + u'\\textsf':u'span class="textsf"', u'\\textsl':u'i', u'\\texttt':u'tt', + u'\\textup':u'span class="normal"', + } + + unmodified = { + + u'characters':[u'.',u'*',u'€',u'(',u')',u'[',u']',u':',u'·',u'!',u';',u'|',u'§',u'"',], + } + + urls = { + u'googlecharts':u'http://chart.googleapis.com/chart?cht=tx&chl=', + } + +class GeneralConfig(object): + "Configuration class from elyxer.config file" + + version = { + u'date':u'2013-03-10', u'lyxformat':u'413', u'number':u'1.2.4', + } + +class HeaderConfig(object): + "Configuration class from elyxer.config file" + + parameters = { + u'beginpreamble':u'\\begin_preamble', u'branch':u'\\branch', + u'documentclass':u'\\textclass', u'endbranch':u'\\end_branch', + u'endpreamble':u'\\end_preamble', u'language':u'\\language', + u'lstset':u'\\lstset', u'outputchanges':u'\\output_changes', + u'paragraphseparation':u'\\paragraph_separation', + u'pdftitle':u'\\pdf_title', u'secnumdepth':u'\\secnumdepth', + u'tocdepth':u'\\tocdepth', + } + + styles = { + + u'article':[u'article',u'aastex',u'aapaper',u'acmsiggraph',u'sigplanconf',u'achemso',u'amsart',u'apa',u'arab-article',u'armenian-article',u'article-beamer',u'chess',u'dtk',u'elsarticle',u'heb-article',u'IEEEtran',u'iopart',u'kluwer',u'scrarticle-beamer',u'scrartcl',u'extarticle',u'paper',u'mwart',u'revtex4',u'spie',u'svglobal3',u'ltugboat',u'agu-dtd',u'jgrga',u'agums',u'entcs',u'egs',u'ijmpc',u'ijmpd',u'singlecol-new',u'doublecol-new',u'isprs',u'tarticle',u'jsarticle',u'jarticle',u'jss',u'literate-article',u'siamltex',u'cl2emult',u'llncs',u'svglobal',u'svjog',u'svprobth',], + u'book':[u'book',u'amsbook',u'scrbook',u'extbook',u'tufte-book',u'report',u'extreport',u'scrreprt',u'memoir',u'tbook',u'jsbook',u'jbook',u'mwbk',u'svmono',u'svmult',u'treport',u'jreport',u'mwrep',], + } + +class ImageConfig(object): + "Configuration class from elyxer.config file" + + converters = { + + u'imagemagick':u'convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output"', + u'inkscape':u'inkscape "$input" --export-png="$output"', + u'lyx':u'lyx -C "$input" "$output"', + } + + cropboxformats = { + u'.eps':u'ps', u'.pdf':u'pdf', u'.ps':u'ps', + } + + formats = { + u'default':u'.png', u'vector':[u'.svg',u'.eps',], + } + +class LayoutConfig(object): + "Configuration class from elyxer.config file" + + groupable = { + + u'allowed':[u'StringContainer',u'Constant',u'TaggedText',u'Align',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + } + +class NewfangleConfig(object): + "Configuration class from elyxer.config file" + + constants = { + u'chunkref':u'chunkref{', u'endcommand':u'}', u'endmark':u'>', + u'startcommand':u'\\', u'startmark':u'=<', + } + +class NumberingConfig(object): + "Configuration class from elyxer.config file" + + layouts = { + + u'ordered':[u'Chapter',u'Section',u'Subsection',u'Subsubsection',u'Paragraph',], + u'roman':[u'Part',u'Book',], + } + + sequence = { + u'symbols':[u'*',u'**',u'†',u'‡',u'§',u'§§',u'¶',u'¶¶',u'#',u'##',], + } + +class StyleConfig(object): + "Configuration class from elyxer.config file" + + hspaces = { + u'\\enskip{}':u' ', u'\\hfill{}':u' ', + u'\\hspace*{\\fill}':u' ', u'\\hspace*{}':u'', u'\\hspace{}':u' ', + u'\\negthinspace{}':u'', u'\\qquad{}':u'  ', u'\\quad{}':u' ', + u'\\space{}':u' ', u'\\thinspace{}':u' ', u'~':u' ', + } + + quotes = { + u'ald':u'»', u'als':u'›', u'ard':u'«', u'ars':u'‹', u'eld':u'“', + u'els':u'‘', u'erd':u'”', u'ers':u'’', u'fld':u'«', + u'fls':u'‹', u'frd':u'»', u'frs':u'›', u'gld':u'„', u'gls':u'‚', + u'grd':u'“', u'grs':u'‘', u'pld':u'„', u'pls':u'‚', u'prd':u'”', + u'prs':u'’', u'sld':u'”', u'srd':u'”', + } + + referenceformats = { + u'eqref':u'(@↕)', u'formatted':u'¶↕', u'nameref':u'$↕', u'pageref':u'#↕', + u'ref':u'@↕', u'vpageref':u'on-page#↕', u'vref':u'@on-page#↕', + } + + size = { + u'ignoredtexts':[u'col',u'text',u'line',u'page',u'theight',u'pheight',], + } + + vspaces = { + u'bigskip':u'
      ', + u'defskip':u'
      ', + u'medskip':u'
      ', + u'smallskip':u'
      ', + u'vfill':u'
      ', + } + +class TOCConfig(object): + "Configuration class from elyxer.config file" + + extractplain = { + + u'allowed':[u'StringContainer',u'Constant',u'TaggedText',u'Align',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + u'cloned':[u'',], u'extracted':[u'',], + } + + extracttitle = { + u'allowed':[u'StringContainer',u'Constant',u'Space',], + u'cloned':[u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + u'extracted':[u'PlainLayout',u'TaggedText',u'Align',u'Caption',u'StandardLayout',u'FlexInset',], + } + +class TagConfig(object): + "Configuration class from elyxer.config file" + + barred = { + u'under':u'u', + } + + family = { + u'sans':u'span class="sans"', u'typewriter':u'tt', + } + + flex = { + u'CharStyle:Code':u'span class="code"', + u'CharStyle:MenuItem':u'span class="menuitem"', + u'Code':u'span class="code"', u'MenuItem':u'span class="menuitem"', + u'Noun':u'span class="noun"', u'Strong':u'span class="strong"', + } + + group = { + u'layouts':[u'Quotation',u'Quote',], + } + + layouts = { + u'Center':u'div', u'Chapter':u'h?', u'Date':u'h2', u'Paragraph':u'div', + u'Part':u'h1', u'Quotation':u'blockquote', u'Quote':u'blockquote', + u'Section':u'h?', u'Subsection':u'h?', u'Subsubsection':u'h?', + } + + listitems = { + u'Enumerate':u'ol', u'Itemize':u'ul', + } + + notes = { + u'Comment':u'', u'Greyedout':u'span class="greyedout"', u'Note':u'', + } + + script = { + u'subscript':u'sub', u'superscript':u'sup', + } + + shaped = { + u'italic':u'i', u'slanted':u'i', u'smallcaps':u'span class="versalitas"', + } + +class TranslationConfig(object): + "Configuration class from elyxer.config file" + + constants = { + u'Appendix':u'Appendix', u'Book':u'Book', u'Chapter':u'Chapter', + u'Paragraph':u'Paragraph', u'Part':u'Part', u'Section':u'Section', + u'Subsection':u'Subsection', u'Subsubsection':u'Subsubsection', + u'abstract':u'Abstract', u'bibliography':u'Bibliography', + u'figure':u'figure', u'float-algorithm':u'Algorithm ', + u'float-figure':u'Figure ', u'float-listing':u'Listing ', + u'float-table':u'Table ', u'float-tableau':u'Tableau ', + u'footnotes':u'Footnotes', u'generated-by':u'Document generated by ', + u'generated-on':u' on ', u'index':u'Index', + u'jsmath-enable':u'Please enable JavaScript on your browser.', + u'jsmath-requires':u' requires JavaScript to correctly process the mathematics on this page. ', + u'jsmath-warning':u'Warning: ', u'list-algorithm':u'List of Algorithms', + u'list-figure':u'List of Figures', u'list-table':u'List of Tables', + u'list-tableau':u'List of Tableaux', u'main-page':u'Main page', + u'next':u'Next', u'nomenclature':u'Nomenclature', + u'on-page':u' on page ', u'prev':u'Prev', u'references':u'References', + u'toc':u'Table of Contents', u'toc-for':u'Contents for ', u'up':u'Up', + } + + languages = { + u'american':u'en', u'british':u'en', u'deutsch':u'de', u'dutch':u'nl', + u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'russian':u'ru', + u'spanish':u'es', + } + + + + + + +class CommandLineParser(object): + "A parser for runtime options" + + def __init__(self, options): + self.options = options + + def parseoptions(self, args): + "Parse command line options" + if len(args) == 0: + return None + while len(args) > 0 and args[0].startswith('--'): + key, value = self.readoption(args) + if not key: + return 'Option ' + value + ' not recognized' + if not value: + return 'Option ' + key + ' needs a value' + setattr(self.options, key, value) + return None + + def readoption(self, args): + "Read the key and value for an option" + arg = args[0][2:] + del args[0] + if '=' in arg: + key = self.readequalskey(arg, args) + else: + key = arg.replace('-', '') + if not hasattr(self.options, key): + return None, key + current = getattr(self.options, key) + if isinstance(current, bool): + return key, True + # read value + if len(args) == 0: + return key, None + if args[0].startswith('"'): + initial = args[0] + del args[0] + return key, self.readquoted(args, initial) + value = args[0].decode('utf-8') + del args[0] + if isinstance(current, list): + current.append(value) + return key, current + return key, value + + def readquoted(self, args, initial): + "Read a value between quotes" + Trace.error('Oops') + value = initial[1:] + while len(args) > 0 and not args[0].endswith('"') and not args[0].startswith('--'): + Trace.error('Appending ' + args[0]) + value += ' ' + args[0] + del args[0] + if len(args) == 0 or args[0].startswith('--'): + return None + value += ' ' + args[0:-1] + return value + + def readequalskey(self, arg, args): + "Read a key using equals" + split = arg.split('=', 1) + key = split[0] + value = split[1] + args.insert(0, value) + return key + + + +class Options(object): + "A set of runtime options" + + instance = None + + location = None + nocopy = False + copyright = False + debug = False + quiet = False + version = False + hardversion = False + versiondate = False + html = False + help = False + showlines = True + unicode = False + iso885915 = False + css = [] + title = None + directory = None + destdirectory = None + toc = False + toctarget = '' + tocfor = None + forceformat = None + lyxformat = False + target = None + splitpart = None + memory = True + lowmem = False + nobib = False + converter = 'imagemagick' + raw = False + jsmath = None + mathjax = None + nofooter = False + simplemath = False + template = None + noconvert = False + notoclabels = False + letterfoot = True + numberfoot = False + symbolfoot = False + hoverfoot = True + marginfoot = False + endfoot = False + supfoot = True + alignfoot = False + footnotes = None + imageformat = None + copyimages = False + googlecharts = False + embedcss = [] + + branches = dict() + + def parseoptions(self, args): + "Parse command line options" + Options.location = args[0] + del args[0] + parser = CommandLineParser(Options) + result = parser.parseoptions(args) + if result: + Trace.error(result) + self.usage() + self.processoptions() + + def processoptions(self): + "Process all options parsed." + if Options.help: + self.usage() + if Options.version: + self.showversion() + if Options.hardversion: + self.showhardversion() + if Options.versiondate: + self.showversiondate() + if Options.lyxformat: + self.showlyxformat() + if Options.splitpart: + try: + Options.splitpart = int(Options.splitpart) + if Options.splitpart <= 0: + Trace.error('--splitpart requires a number bigger than zero') + self.usage() + except: + Trace.error('--splitpart needs a numeric argument, not ' + Options.splitpart) + self.usage() + if Options.lowmem or Options.toc or Options.tocfor: + Options.memory = False + self.parsefootnotes() + if Options.forceformat and not Options.imageformat: + Options.imageformat = Options.forceformat + if Options.imageformat == 'copy': + Options.copyimages = True + if Options.css == []: + Options.css = ['http://elyxer.nongnu.org/lyx.css'] + if Options.html: + Options.simplemath = True + if Options.toc and not Options.tocfor: + Trace.error('Option --toc is deprecated; use --tocfor "page" instead') + Options.tocfor = Options.toctarget + if Options.nocopy: + Trace.error('Option --nocopy is deprecated; it is no longer needed') + if Options.jsmath: + Trace.error('Option --jsmath is deprecated; use --mathjax instead') + # set in Trace if necessary + for param in dir(Trace): + if param.endswith('mode'): + setattr(Trace, param, getattr(self, param[:-4])) + + def usage(self): + "Show correct usage" + Trace.error('Usage: ' + os.path.basename(Options.location) + ' [options] [filein] [fileout]') + Trace.error('Convert LyX input file "filein" to HTML file "fileout".') + Trace.error('If filein (or fileout) is not given use standard input (or output).') + Trace.error('Main program of the eLyXer package (http://elyxer.nongnu.org/).') + self.showoptions() + + def parsefootnotes(self): + "Parse footnotes options." + if not Options.footnotes: + return + Options.marginfoot = False + Options.letterfoot = False + Options.hoverfoot = False + options = Options.footnotes.split(',') + for option in options: + footoption = option + 'foot' + if hasattr(Options, footoption): + setattr(Options, footoption, True) + else: + Trace.error('Unknown footnotes option: ' + option) + if not Options.endfoot and not Options.marginfoot and not Options.hoverfoot: + Options.hoverfoot = True + if not Options.numberfoot and not Options.symbolfoot: + Options.letterfoot = True + + def showoptions(self): + "Show all possible options" + Trace.error(' Common options:') + Trace.error(' --help: show this online help') + Trace.error(' --quiet: disables all runtime messages') + Trace.error('') + Trace.error(' Advanced options:') + Trace.error(' --debug: enable debugging messages (for developers)') + Trace.error(' --version: show version number and release date') + Trace.error(' --lyxformat: return the highest LyX version supported') + Trace.error(' Options for HTML output:') + Trace.error(' --title "title": set the generated page title') + Trace.error(' --css "file.css": use a custom CSS file') + Trace.error(' --embedcss "file.css": embed styles from a CSS file into the output') + Trace.error(' --html: output HTML 4.0 instead of the default XHTML') + Trace.error(' --unicode: full Unicode output') + Trace.error(' --iso885915: output a document with ISO-8859-15 encoding') + Trace.error(' --nofooter: remove the footer "generated by eLyXer"') + Trace.error(' --simplemath: do not generate fancy math constructions') + Trace.error(' Options for image output:') + Trace.error(' --directory "img_dir": look for images in the specified directory') + Trace.error(' --destdirectory "dest": put converted images into this directory') + Trace.error(' --imageformat ".ext": image output format, or "copy" to copy images') + Trace.error(' --noconvert: do not convert images, use in original locations') + Trace.error(' --converter "inkscape": use an alternative program to convert images') + Trace.error(' Options for footnote display:') + Trace.error(' --numberfoot: mark footnotes with numbers instead of letters') + Trace.error(' --symbolfoot: mark footnotes with symbols (*, **...)') + Trace.error(' --hoverfoot: show footnotes as hovering text (default)') + Trace.error(' --marginfoot: show footnotes on the page margin') + Trace.error(' --endfoot: show footnotes at the end of the page') + Trace.error(' --supfoot: use superscript for footnote markers (default)') + Trace.error(' --alignfoot: use aligned text for footnote markers') + Trace.error(' --footnotes "options": specify several comma-separated footnotes options') + Trace.error(' Available options are: "number", "symbol", "hover", "margin", "end",') + Trace.error(' "sup", "align"') + Trace.error(' Advanced output options:') + Trace.error(' --splitpart "depth": split the resulting webpage at the given depth') + Trace.error(' --tocfor "page": generate a TOC that points to the given page') + Trace.error(' --target "frame": make all links point to the given frame') + Trace.error(' --notoclabels: omit the part labels in the TOC, such as Chapter') + Trace.error(' --lowmem: do the conversion on the fly (conserve memory)') + Trace.error(' --raw: generate HTML without header or footer.') + Trace.error(' --mathjax remote: use MathJax remotely to display equations') + Trace.error(' --mathjax "URL": use MathJax from the given URL to display equations') + Trace.error(' --googlecharts: use Google Charts to generate formula images') + Trace.error(' --template "file": use a template, put everything in ') + Trace.error(' --copyright: add a copyright notice at the bottom') + Trace.error(' Deprecated options:') + Trace.error(' --toc: (deprecated) create a table of contents') + Trace.error(' --toctarget "page": (deprecated) generate a TOC for the given page') + Trace.error(' --nocopy: (deprecated) maintained for backwards compatibility') + Trace.error(' --jsmath "URL": use jsMath from the given URL to display equations') + sys.exit() + + def showversion(self): + "Return the current eLyXer version string" + string = 'eLyXer version ' + GeneralConfig.version['number'] + string += ' (' + GeneralConfig.version['date'] + ')' + Trace.error(string) + sys.exit() + + def showhardversion(self): + "Return just the version string" + Trace.message(GeneralConfig.version['number']) + sys.exit() + + def showversiondate(self): + "Return just the version dte" + Trace.message(GeneralConfig.version['date']) + sys.exit() + + def showlyxformat(self): + "Return just the lyxformat parameter" + Trace.message(GeneralConfig.version['lyxformat']) + sys.exit() + +class BranchOptions(object): + "A set of options for a branch" + + def __init__(self, name): + self.name = name + self.options = {'color':'#ffffff'} + + def set(self, key, value): + "Set a branch option" + if not key.startswith(ContainerConfig.string['startcommand']): + Trace.error('Invalid branch option ' + key) + return + key = key.replace(ContainerConfig.string['startcommand'], '') + self.options[key] = value + + def isselected(self): + "Return if the branch is selected" + if not 'selected' in self.options: + return False + return self.options['selected'] == '1' + + def __unicode__(self): + "String representation" + return 'options for ' + self.name + ': ' + unicode(self.options) + + + + + + + + + + + + + +import gettext + + + + + +class DocumentParameters(object): + "Global parameters for the document." + + pdftitle = None + indentstandard = False + tocdepth = 10 + startinglevel = 0 + maxdepth = 10 + language = None + bibliography = None + outputchanges = False + displaymode = False + + + +class Translator(object): + "Reads the configuration file and tries to find a translation." + "Otherwise falls back to the messages in the config file." + + instance = None + + def translate(cls, key): + "Get the translated message for a key." + return cls.instance.getmessage(key) + + translate = classmethod(translate) + + def __init__(self): + self.translation = None + self.first = True + + def findtranslation(self): + "Find the translation for the document language." + self.langcodes = None + if not DocumentParameters.language: + Trace.error('No language in document') + return + if not DocumentParameters.language in TranslationConfig.languages: + Trace.error('Unknown language ' + DocumentParameters.language) + return + if TranslationConfig.languages[DocumentParameters.language] == 'en': + return + langcodes = [TranslationConfig.languages[DocumentParameters.language]] + try: + self.translation = gettext.translation('elyxer', None, langcodes) + except IOError: + Trace.error('No translation for ' + unicode(langcodes)) + + def getmessage(self, key): + "Get the translated message for the given key." + if self.first: + self.findtranslation() + self.first = False + message = self.getuntranslated(key) + if not self.translation: + return message + try: + message = self.translation.ugettext(message) + except IOError: + pass + return message + + def getuntranslated(self, key): + "Get the untranslated message." + if not key in TranslationConfig.constants: + Trace.error('Cannot translate ' + key) + return key + return TranslationConfig.constants[key] + +Translator.instance = Translator() + + + +class NumberCounter(object): + "A counter for numbers (by default)." + "The type can be changed to return letters, roman numbers..." + + name = None + value = None + mode = None + master = None + + letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + symbols = NumberingConfig.sequence['symbols'] + romannumerals = [ + ('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), + ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), + ('IV', 4), ('I', 1) + ] + + def __init__(self, name): + "Give a name to the counter." + self.name = name + + def setmode(self, mode): + "Set the counter mode. Can be changed at runtime." + self.mode = mode + return self + + def init(self, value): + "Set an initial value." + self.value = value + + def gettext(self): + "Get the next value as a text string." + return unicode(self.value) + + def getletter(self): + "Get the next value as a letter." + return self.getsequence(self.letters) + + def getsymbol(self): + "Get the next value as a symbol." + return self.getsequence(self.symbols) + + def getsequence(self, sequence): + "Get the next value from elyxer.a sequence." + return sequence[(self.value - 1) % len(sequence)] + + def getroman(self): + "Get the next value as a roman number." + result = '' + number = self.value + for numeral, value in self.romannumerals: + if number >= value: + result += numeral * (number / value) + number = number % value + return result + + def getvalue(self): + "Get the current value as configured in the current mode." + if not self.mode or self.mode in ['text', '1']: + return self.gettext() + if self.mode == 'A': + return self.getletter() + if self.mode == 'a': + return self.getletter().lower() + if self.mode == 'I': + return self.getroman() + if self.mode == '*': + return self.getsymbol() + Trace.error('Unknown counter mode ' + self.mode) + return self.gettext() + + def getnext(self): + "Increase the current value and get the next value as configured." + if not self.value: + self.value = 0 + self.value += 1 + return self.getvalue() + + def reset(self): + "Reset the counter." + self.value = 0 + + def __unicode__(self): + "Return a printable representation." + result = 'Counter ' + self.name + if self.mode: + result += ' in mode ' + self.mode + return result + +class DependentCounter(NumberCounter): + "A counter which depends on another one (the master)." + + def setmaster(self, master): + "Set the master counter." + self.master = master + self.last = self.master.getvalue() + return self + + def getnext(self): + "Increase or, if the master counter has changed, restart." + if self.last != self.master.getvalue(): + self.reset() + value = NumberCounter.getnext(self) + self.last = self.master.getvalue() + return value + + def getvalue(self): + "Get the value of the combined counter: master.dependent." + return self.master.getvalue() + '.' + NumberCounter.getvalue(self) + +class NumberGenerator(object): + "A number generator for unique sequences and hierarchical structures. Used in:" + " * ordered part numbers: Chapter 3, Section 5.3." + " * unique part numbers: Footnote 15, Bibliography cite [15]." + " * chaptered part numbers: Figure 3.15, Equation (8.3)." + " * unique roman part numbers: Part I, Book IV." + + chaptered = None + generator = None + + romanlayouts = [x.lower() for x in NumberingConfig.layouts['roman']] + orderedlayouts = [x.lower() for x in NumberingConfig.layouts['ordered']] + + counters = dict() + appendix = None + + def deasterisk(self, type): + "Remove the possible asterisk in a layout type." + return type.replace('*', '') + + def isunique(self, type): + "Find out if the layout type corresponds to a unique part." + return self.isroman(type) + + def isroman(self, type): + "Find out if the layout type should have roman numeration." + return self.deasterisk(type).lower() in self.romanlayouts + + def isinordered(self, type): + "Find out if the layout type corresponds to an (un)ordered part." + return self.deasterisk(type).lower() in self.orderedlayouts + + def isnumbered(self, type): + "Find out if the type for a layout corresponds to a numbered layout." + if '*' in type: + return False + if self.isroman(type): + return True + if not self.isinordered(type): + return False + if self.getlevel(type) > DocumentParameters.maxdepth: + return False + return True + + def isunordered(self, type): + "Find out if the type contains an asterisk, basically." + return '*' in type + + def getlevel(self, type): + "Get the level that corresponds to a layout type." + if self.isunique(type): + return 0 + if not self.isinordered(type): + Trace.error('Unknown layout type ' + type) + return 0 + type = self.deasterisk(type).lower() + level = self.orderedlayouts.index(type) + 1 + return level - DocumentParameters.startinglevel + + def getparttype(self, type): + "Obtain the type for the part: without the asterisk, " + "and switched to Appendix if necessary." + if NumberGenerator.appendix and self.getlevel(type) == 1: + return 'Appendix' + return self.deasterisk(type) + + def generate(self, type): + "Generate a number for a layout type." + "Unique part types such as Part or Book generate roman numbers: Part I." + "Ordered part types return dot-separated tuples: Chapter 5, Subsection 2.3.5." + "Everything else generates unique numbers: Bibliography [1]." + "Each invocation results in a new number." + return self.getcounter(type).getnext() + + def getcounter(self, type): + "Get the counter for the given type." + type = type.lower() + if not type in self.counters: + self.counters[type] = self.create(type) + return self.counters[type] + + def create(self, type): + "Create a counter for the given type." + if self.isnumbered(type) and self.getlevel(type) > 1: + index = self.orderedlayouts.index(type) + above = self.orderedlayouts[index - 1] + master = self.getcounter(above) + return self.createdependent(type, master) + counter = NumberCounter(type) + if self.isroman(type): + counter.setmode('I') + return counter + + def getdependentcounter(self, type, master): + "Get (or create) a counter of the given type that depends on another." + if not type in self.counters or not self.counters[type].master: + self.counters[type] = self.createdependent(type, master) + return self.counters[type] + + def createdependent(self, type, master): + "Create a dependent counter given the master." + return DependentCounter(type).setmaster(master) + + def startappendix(self): + "Start appendices here." + firsttype = self.orderedlayouts[DocumentParameters.startinglevel] + counter = self.getcounter(firsttype) + counter.setmode('A').reset() + NumberGenerator.appendix = True + +class ChapteredGenerator(NumberGenerator): + "Generate chaptered numbers, as in Chapter.Number." + "Used in equations, figures: Equation (5.3), figure 8.15." + + def generate(self, type): + "Generate a number which goes with first-level numbers (chapters). " + "For the article classes a unique number is generated." + if DocumentParameters.startinglevel > 0: + return NumberGenerator.generator.generate(type) + chapter = self.getcounter('Chapter') + return self.getdependentcounter(type, chapter).getnext() + + +NumberGenerator.chaptered = ChapteredGenerator() +NumberGenerator.generator = NumberGenerator() + + + + + + +class Parser(object): + "A generic parser" + + def __init__(self): + self.begin = 0 + self.parameters = dict() + + def parseheader(self, reader): + "Parse the header" + header = reader.currentline().split() + reader.nextline() + self.begin = reader.linenumber + return header + + def parseparameter(self, reader): + "Parse a parameter" + if reader.currentline().strip().startswith('<'): + key, value = self.parsexml(reader) + self.parameters[key] = value + return + split = reader.currentline().strip().split(' ', 1) + reader.nextline() + if len(split) == 0: + return + key = split[0] + if len(split) == 1: + self.parameters[key] = True + return + if not '"' in split[1]: + self.parameters[key] = split[1].strip() + return + doublesplit = split[1].split('"') + self.parameters[key] = doublesplit[1] + + def parsexml(self, reader): + "Parse a parameter in xml form: " + strip = reader.currentline().strip() + reader.nextline() + if not strip.endswith('>'): + Trace.error('XML parameter ' + strip + ' should be <...>') + split = strip[1:-1].split() + if len(split) == 0: + Trace.error('Empty XML parameter <>') + return None, None + key = split[0] + del split[0] + if len(split) == 0: + return key, dict() + attrs = dict() + for attr in split: + if not '=' in attr: + Trace.error('Erroneous attribute for ' + key + ': ' + attr) + attr += '="0"' + parts = attr.split('=') + attrkey = parts[0] + value = parts[1].split('"')[1] + attrs[attrkey] = value + return key, attrs + + def parseending(self, reader, process): + "Parse until the current ending is found" + if not self.ending: + Trace.error('No ending for ' + unicode(self)) + return + while not reader.currentline().startswith(self.ending): + process() + + def parsecontainer(self, reader, contents): + container = self.factory.createcontainer(reader) + if container: + container.parent = self.parent + contents.append(container) + + def __unicode__(self): + "Return a description" + return self.__class__.__name__ + ' (' + unicode(self.begin) + ')' + +class LoneCommand(Parser): + "A parser for just one command line" + + def parse(self,reader): + "Read nothing" + return [] + +class TextParser(Parser): + "A parser for a command and a bit of text" + + stack = [] + + def __init__(self, container): + Parser.__init__(self) + self.ending = None + if container.__class__.__name__ in ContainerConfig.endings: + self.ending = ContainerConfig.endings[container.__class__.__name__] + self.endings = [] + + def parse(self, reader): + "Parse lines as long as they are text" + TextParser.stack.append(self.ending) + self.endings = TextParser.stack + [ContainerConfig.endings['Layout'], + ContainerConfig.endings['Inset'], self.ending] + contents = [] + while not self.isending(reader): + self.parsecontainer(reader, contents) + return contents + + def isending(self, reader): + "Check if text is ending" + current = reader.currentline().split() + if len(current) == 0: + return False + if current[0] in self.endings: + if current[0] in TextParser.stack: + TextParser.stack.remove(current[0]) + else: + TextParser.stack = [] + return True + return False + +class ExcludingParser(Parser): + "A parser that excludes the final line" + + def parse(self, reader): + "Parse everything up to (and excluding) the final line" + contents = [] + self.parseending(reader, lambda: self.parsecontainer(reader, contents)) + return contents + +class BoundedParser(ExcludingParser): + "A parser bound by a final line" + + def parse(self, reader): + "Parse everything, including the final line" + contents = ExcludingParser.parse(self, reader) + # skip last line + reader.nextline() + return contents + +class BoundedDummy(Parser): + "A bound parser that ignores everything" + + def parse(self, reader): + "Parse the contents of the container" + self.parseending(reader, lambda: reader.nextline()) + # skip last line + reader.nextline() + return [] + +class StringParser(Parser): + "Parses just a string" + + def parseheader(self, reader): + "Do nothing, just take note" + self.begin = reader.linenumber + 1 + return [] + + def parse(self, reader): + "Parse a single line" + contents = reader.currentline() + reader.nextline() + return contents + +class InsetParser(BoundedParser): + "Parses a LyX inset" + + def parse(self, reader): + "Parse inset parameters into a dictionary" + startcommand = ContainerConfig.string['startcommand'] + while reader.currentline() != '' and not reader.currentline().startswith(startcommand): + self.parseparameter(reader) + return BoundedParser.parse(self, reader) + + + + + + +class ContainerOutput(object): + "The generic HTML output for a container." + + def gethtml(self, container): + "Show an error." + Trace.error('gethtml() not implemented for ' + unicode(self)) + + def isempty(self): + "Decide if the output is empty: by default, not empty." + return False + +class EmptyOutput(ContainerOutput): + + def gethtml(self, container): + "Return empty HTML code." + return [] + + def isempty(self): + "This output is particularly empty." + return True + +class FixedOutput(ContainerOutput): + "Fixed output" + + def gethtml(self, container): + "Return constant HTML code" + return container.html + +class ContentsOutput(ContainerOutput): + "Outputs the contents converted to HTML" + + def gethtml(self, container): + "Return the HTML code" + html = [] + if container.contents == None: + return html + for element in container.contents: + if not hasattr(element, 'gethtml'): + Trace.error('No html in ' + element.__class__.__name__ + ': ' + unicode(element)) + return html + html += element.gethtml() + return html + +class TaggedOutput(ContentsOutput): + "Outputs an HTML tag surrounding the contents." + + tag = None + breaklines = False + empty = False + + def settag(self, tag, breaklines=False, empty=False): + "Set the value for the tag and other attributes." + self.tag = tag + if breaklines: + self.breaklines = breaklines + if empty: + self.empty = empty + return self + + def setbreaklines(self, breaklines): + "Set the value for breaklines." + self.breaklines = breaklines + return self + + def gethtml(self, container): + "Return the HTML code." + if self.empty: + return [self.selfclosing(container)] + html = [self.open(container)] + html += ContentsOutput.gethtml(self, container) + html.append(self.close(container)) + return html + + def open(self, container): + "Get opening line." + if not self.checktag(): + return '' + open = '<' + self.tag + '>' + if self.breaklines: + return open + '\n' + return open + + def close(self, container): + "Get closing line." + if not self.checktag(): + return '' + close = '' + if self.breaklines: + return '\n' + close + '\n' + return close + + def selfclosing(self, container): + "Get self-closing line." + if not self.checktag(): + return '' + selfclosing = '<' + self.tag + '/>' + if self.breaklines: + return selfclosing + '\n' + return selfclosing + + def checktag(self): + "Check that the tag is valid." + if not self.tag: + Trace.error('No tag in ' + unicode(container)) + return False + if self.tag == '': + return False + return True + +class FilteredOutput(ContentsOutput): + "Returns the output in the contents, but filtered:" + "some strings are replaced by others." + + def __init__(self): + "Initialize the filters." + self.filters = [] + + def addfilter(self, original, replacement): + "Add a new filter: replace the original by the replacement." + self.filters.append((original, replacement)) + + def gethtml(self, container): + "Return the HTML code" + result = [] + html = ContentsOutput.gethtml(self, container) + for line in html: + result.append(self.filter(line)) + return result + + def filter(self, line): + "Filter a single line with all available filters." + for original, replacement in self.filters: + if original in line: + line = line.replace(original, replacement) + return line + +class StringOutput(ContainerOutput): + "Returns a bare string as output" + + def gethtml(self, container): + "Return a bare string" + return [container.string] + + + + + + + + + +class Cloner(object): + "An object used to clone other objects." + + def clone(cls, original): + "Return an exact copy of an object." + "The original object must have an empty constructor." + return cls.create(original.__class__) + + def create(cls, type): + "Create an object of a given class." + clone = type.__new__(type) + clone.__init__() + return clone + + clone = classmethod(clone) + create = classmethod(create) + +class ContainerExtractor(object): + "A class to extract certain containers." + + def __init__(self, config): + "The config parameter is a map containing three lists: allowed, copied and extracted." + "Each of the three is a list of class names for containers." + "Allowed containers are included as is into the result." + "Cloned containers are cloned and placed into the result." + "Extracted containers are looked into." + "All other containers are silently ignored." + self.allowed = config['allowed'] + self.cloned = config['cloned'] + self.extracted = config['extracted'] + + def extract(self, container): + "Extract a group of selected containers from elyxer.a container." + list = [] + locate = lambda c: c.__class__.__name__ in self.allowed + self.cloned + recursive = lambda c: c.__class__.__name__ in self.extracted + process = lambda c: self.process(c, list) + container.recursivesearch(locate, recursive, process) + return list + + def process(self, container, list): + "Add allowed containers, clone cloned containers and add the clone." + name = container.__class__.__name__ + if name in self.allowed: + list.append(container) + elif name in self.cloned: + list.append(self.safeclone(container)) + else: + Trace.error('Unknown container class ' + name) + + def safeclone(self, container): + "Return a new container with contents only in a safe list, recursively." + clone = Cloner.clone(container) + clone.output = container.output + clone.contents = self.extract(container) + return clone + + + + + + + + + +class Globable(object): + """A bit of text which can be globbed (lumped together in bits). + Methods current(), skipcurrent(), checkfor() and isout() have to be + implemented by subclasses.""" + + leavepending = False + + def __init__(self): + self.endinglist = EndingList() + + def checkbytemark(self): + "Check for a Unicode byte mark and skip it." + if self.finished(): + return + if ord(self.current()) == 0xfeff: + self.skipcurrent() + + def isout(self): + "Find out if we are out of the position yet." + Trace.error('Unimplemented isout()') + return True + + def current(self): + "Return the current character." + Trace.error('Unimplemented current()') + return '' + + def checkfor(self, string): + "Check for the given string in the current position." + Trace.error('Unimplemented checkfor()') + return False + + def finished(self): + "Find out if the current text has finished." + if self.isout(): + if not self.leavepending: + self.endinglist.checkpending() + return True + return self.endinglist.checkin(self) + + def skipcurrent(self): + "Return the current character and skip it." + Trace.error('Unimplemented skipcurrent()') + return '' + + def glob(self, currentcheck): + "Glob a bit of text that satisfies a check on the current char." + glob = '' + while not self.finished() and currentcheck(): + glob += self.skipcurrent() + return glob + + def globalpha(self): + "Glob a bit of alpha text" + return self.glob(lambda: self.current().isalpha()) + + def globnumber(self): + "Glob a row of digits." + return self.glob(lambda: self.current().isdigit()) + + def isidentifier(self): + "Return if the current character is alphanumeric or _." + if self.current().isalnum() or self.current() == '_': + return True + return False + + def globidentifier(self): + "Glob alphanumeric and _ symbols." + return self.glob(self.isidentifier) + + def isvalue(self): + "Return if the current character is a value character:" + "not a bracket or a space." + if self.current().isspace(): + return False + if self.current() in '{}()': + return False + return True + + def globvalue(self): + "Glob a value: any symbols but brackets." + return self.glob(self.isvalue) + + def skipspace(self): + "Skip all whitespace at current position." + return self.glob(lambda: self.current().isspace()) + + def globincluding(self, magicchar): + "Glob a bit of text up to (including) the magic char." + glob = self.glob(lambda: self.current() != magicchar) + magicchar + self.skip(magicchar) + return glob + + def globexcluding(self, excluded): + "Glob a bit of text up until (excluding) any excluded character." + return self.glob(lambda: self.current() not in excluded) + + def pushending(self, ending, optional = False): + "Push a new ending to the bottom" + self.endinglist.add(ending, optional) + + def popending(self, expected = None): + "Pop the ending found at the current position" + if self.isout() and self.leavepending: + return expected + ending = self.endinglist.pop(self) + if expected and expected != ending: + Trace.error('Expected ending ' + expected + ', got ' + ending) + self.skip(ending) + return ending + + def nextending(self): + "Return the next ending in the queue." + nextending = self.endinglist.findending(self) + if not nextending: + return None + return nextending.ending + +class EndingList(object): + "A list of position endings" + + def __init__(self): + self.endings = [] + + def add(self, ending, optional = False): + "Add a new ending to the list" + self.endings.append(PositionEnding(ending, optional)) + + def pickpending(self, pos): + "Pick any pending endings from a parse position." + self.endings += pos.endinglist.endings + + def checkin(self, pos): + "Search for an ending" + if self.findending(pos): + return True + return False + + def pop(self, pos): + "Remove the ending at the current position" + if pos.isout(): + Trace.error('No ending out of bounds') + return '' + ending = self.findending(pos) + if not ending: + Trace.error('No ending at ' + pos.current()) + return '' + for each in reversed(self.endings): + self.endings.remove(each) + if each == ending: + return each.ending + elif not each.optional: + Trace.error('Removed non-optional ending ' + each) + Trace.error('No endings left') + return '' + + def findending(self, pos): + "Find the ending at the current position" + if len(self.endings) == 0: + return None + for index, ending in enumerate(reversed(self.endings)): + if ending.checkin(pos): + return ending + if not ending.optional: + return None + return None + + def checkpending(self): + "Check if there are any pending endings" + if len(self.endings) != 0: + Trace.error('Pending ' + unicode(self) + ' left open') + + def __unicode__(self): + "Printable representation" + string = 'endings [' + for ending in self.endings: + string += unicode(ending) + ',' + if len(self.endings) > 0: + string = string[:-1] + return string + ']' + +class PositionEnding(object): + "An ending for a parsing position" + + def __init__(self, ending, optional): + self.ending = ending + self.optional = optional + + def checkin(self, pos): + "Check for the ending" + return pos.checkfor(self.ending) + + def __unicode__(self): + "Printable representation" + string = 'Ending ' + self.ending + if self.optional: + string += ' (optional)' + return string + + + +class Position(Globable): + """A position in a text to parse. + Including those in Globable, functions to implement by subclasses are: + skip(), identifier(), extract(), isout() and current().""" + + def __init__(self): + Globable.__init__(self) + + def skip(self, string): + "Skip a string" + Trace.error('Unimplemented skip()') + + def identifier(self): + "Return an identifier for the current position." + Trace.error('Unimplemented identifier()') + return 'Error' + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text," + "without advancing the parse position." + Trace.error('Unimplemented extract()') + return None + + def checkfor(self, string): + "Check for a string at the given position." + return string == self.extract(len(string)) + + def checkforlower(self, string): + "Check for a string in lower case." + extracted = self.extract(len(string)) + if not extracted: + return False + return string.lower() == self.extract(len(string)).lower() + + def skipcurrent(self): + "Return the current character and skip it." + current = self.current() + self.skip(current) + return current + + def next(self): + "Advance the position and return the next character." + self.skipcurrent() + return self.current() + + def checkskip(self, string): + "Check for a string at the given position; if there, skip it" + if not self.checkfor(string): + return False + self.skip(string) + return True + + def error(self, message): + "Show an error message and the position identifier." + Trace.error(message + ': ' + self.identifier()) + +class TextPosition(Position): + "A parse position based on a raw text." + + def __init__(self, text): + "Create the position from elyxer.some text." + Position.__init__(self) + self.pos = 0 + self.text = text + self.checkbytemark() + + def skip(self, string): + "Skip a string of characters." + self.pos += len(string) + + def identifier(self): + "Return a sample of the remaining text." + length = 30 + if self.pos + length > len(self.text): + length = len(self.text) - self.pos + return '*' + self.text[self.pos:self.pos + length] + '*' + + def isout(self): + "Find out if we are out of the text yet." + return self.pos >= len(self.text) + + def current(self): + "Return the current character, assuming we are not out." + return self.text[self.pos] + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text." + if self.pos + length > len(self.text): + return None + return self.text[self.pos : self.pos + length] + +class FilePosition(Position): + "A parse position based on an underlying file." + + def __init__(self, filename): + "Create the position from a file." + Position.__init__(self) + self.reader = LineReader(filename) + self.pos = 0 + self.checkbytemark() + + def skip(self, string): + "Skip a string of characters." + length = len(string) + while self.pos + length > len(self.reader.currentline()): + length -= len(self.reader.currentline()) - self.pos + 1 + self.nextline() + self.pos += length + + def currentline(self): + "Get the current line of the underlying file." + return self.reader.currentline() + + def nextline(self): + "Go to the next line." + self.reader.nextline() + self.pos = 0 + + def linenumber(self): + "Return the line number of the file." + return self.reader.linenumber + 1 + + def identifier(self): + "Return the current line and line number in the file." + before = self.reader.currentline()[:self.pos - 1] + after = self.reader.currentline()[self.pos:] + return 'line ' + unicode(self.getlinenumber()) + ': ' + before + '*' + after + + def isout(self): + "Find out if we are out of the text yet." + if self.pos > len(self.reader.currentline()): + if self.pos > len(self.reader.currentline()) + 1: + Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos)) + self.nextline() + return self.reader.finished() + + def current(self): + "Return the current character, assuming we are not out." + if self.pos == len(self.reader.currentline()): + return '\n' + if self.pos > len(self.reader.currentline()): + Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos)) + return '*' + return self.reader.currentline()[self.pos] + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text." + if self.pos + length > len(self.reader.currentline()): + return None + return self.reader.currentline()[self.pos : self.pos + length] + + + +class Container(object): + "A container for text and objects in a lyx file" + + partkey = None + parent = None + begin = None + + def __init__(self): + self.contents = list() + + def process(self): + "Process contents" + pass + + def gethtml(self): + "Get the resulting HTML" + html = self.output.gethtml(self) + if isinstance(html, basestring): + Trace.error('Raw string ' + html) + html = [html] + return self.escapeall(html) + + def escapeall(self, lines): + "Escape all lines in an array according to the output options." + result = [] + for line in lines: + if Options.html: + line = self.escape(line, EscapeConfig.html) + if Options.iso885915: + line = self.escape(line, EscapeConfig.iso885915) + line = self.escapeentities(line) + elif not Options.unicode: + line = self.escape(line, EscapeConfig.nonunicode) + result.append(line) + return result + + def escape(self, line, replacements = EscapeConfig.entities): + "Escape a line with replacements from elyxer.a map" + pieces = replacements.keys() + # do them in order + pieces.sort() + for piece in pieces: + if piece in line: + line = line.replace(piece, replacements[piece]) + return line + + def escapeentities(self, line): + "Escape all Unicode characters to HTML entities." + result = '' + pos = TextPosition(line) + while not pos.finished(): + if ord(pos.current()) > 128: + codepoint = hex(ord(pos.current())) + if codepoint == '0xd835': + codepoint = hex(ord(pos.next()) + 0xf800) + result += '&#' + codepoint[1:] + ';' + else: + result += pos.current() + pos.skipcurrent() + return result + + def searchall(self, type): + "Search for all embedded containers of a given type" + list = [] + self.searchprocess(type, lambda container: list.append(container)) + return list + + def searchremove(self, type): + "Search for all containers of a type and remove them" + list = self.searchall(type) + for container in list: + container.parent.contents.remove(container) + return list + + def searchprocess(self, type, process): + "Search for elements of a given type and process them" + self.locateprocess(lambda container: isinstance(container, type), process) + + def locateprocess(self, locate, process): + "Search for all embedded containers and process them" + for container in self.contents: + container.locateprocess(locate, process) + if locate(container): + process(container) + + def recursivesearch(self, locate, recursive, process): + "Perform a recursive search in the container." + for container in self.contents: + if recursive(container): + container.recursivesearch(locate, recursive, process) + if locate(container): + process(container) + + def extracttext(self): + "Extract all text from elyxer.allowed containers." + result = '' + constants = ContainerExtractor(ContainerConfig.extracttext).extract(self) + for constant in constants: + result += constant.string + return result + + def group(self, index, group, isingroup): + "Group some adjoining elements into a group" + if index >= len(self.contents): + return + if hasattr(self.contents[index], 'grouped'): + return + while index < len(self.contents) and isingroup(self.contents[index]): + self.contents[index].grouped = True + group.contents.append(self.contents[index]) + self.contents.pop(index) + self.contents.insert(index, group) + + def remove(self, index): + "Remove a container but leave its contents" + container = self.contents[index] + self.contents.pop(index) + while len(container.contents) > 0: + self.contents.insert(index, container.contents.pop()) + + def tree(self, level = 0): + "Show in a tree" + Trace.debug(" " * level + unicode(self)) + for container in self.contents: + container.tree(level + 1) + + def getparameter(self, name): + "Get the value of a parameter, if present." + if not name in self.parameters: + return None + return self.parameters[name] + + def getparameterlist(self, name): + "Get the value of a comma-separated parameter as a list." + paramtext = self.getparameter(name) + if not paramtext: + return [] + return paramtext.split(',') + + def hasemptyoutput(self): + "Check if the parent's output is empty." + current = self.parent + while current: + if current.output.isempty(): + return True + current = current.parent + return False + + def __unicode__(self): + "Get a description" + if not self.begin: + return self.__class__.__name__ + return self.__class__.__name__ + '@' + unicode(self.begin) + +class BlackBox(Container): + "A container that does not output anything" + + def __init__(self): + self.parser = LoneCommand() + self.output = EmptyOutput() + self.contents = [] + +class LyXFormat(BlackBox): + "Read the lyxformat command" + + def process(self): + "Show warning if version < 276" + version = int(self.header[1]) + if version < 276: + Trace.error('Warning: unsupported old format version ' + str(version)) + if version > int(GeneralConfig.version['lyxformat']): + Trace.error('Warning: unsupported new format version ' + str(version)) + +class StringContainer(Container): + "A container for a single string" + + parsed = None + + def __init__(self): + self.parser = StringParser() + self.output = StringOutput() + self.string = '' + + def process(self): + "Replace special chars from elyxer.the contents." + if self.parsed: + self.string = self.replacespecial(self.parsed) + self.parsed = None + + def replacespecial(self, line): + "Replace all special chars from elyxer.a line" + replaced = self.escape(line, EscapeConfig.entities) + replaced = self.changeline(replaced) + if ContainerConfig.string['startcommand'] in replaced and len(replaced) > 1: + # unprocessed commands + if self.begin: + message = 'Unknown command at ' + unicode(self.begin) + ': ' + else: + message = 'Unknown command: ' + Trace.error(message + replaced.strip()) + return replaced + + def changeline(self, line): + line = self.escape(line, EscapeConfig.chars) + if not ContainerConfig.string['startcommand'] in line: + return line + line = self.escape(line, EscapeConfig.commands) + return line + + def extracttext(self): + "Return all text." + return self.string + + def __unicode__(self): + "Return a printable representation." + result = 'StringContainer' + if self.begin: + result += '@' + unicode(self.begin) + ellipsis = '...' + if len(self.string.strip()) <= 15: + ellipsis = '' + return result + ' (' + self.string.strip()[:15] + ellipsis + ')' + +class Constant(StringContainer): + "A constant string" + + def __init__(self, text): + self.contents = [] + self.string = text + self.output = StringOutput() + + def __unicode__(self): + return 'Constant: ' + self.string + +class TaggedText(Container): + "Text inside a tag" + + output = None + + def __init__(self): + self.parser = TextParser(self) + self.output = TaggedOutput() + + def complete(self, contents, tag, breaklines=False): + "Complete the tagged text and return it" + self.contents = contents + self.output.tag = tag + self.output.breaklines = breaklines + return self + + def constant(self, text, tag, breaklines=False): + "Complete the tagged text with a constant" + constant = Constant(text) + return self.complete([constant], tag, breaklines) + + def __unicode__(self): + "Return a printable representation." + if not hasattr(self.output, 'tag'): + return 'Emtpy tagged text' + if not self.output.tag: + return 'Tagged ' + return 'Tagged <' + self.output.tag + '>' + + + + + + +class ContainerSize(object): + "The size of a container." + + width = None + height = None + maxwidth = None + maxheight = None + scale = None + + def set(self, width = None, height = None): + "Set the proper size with width and height." + self.setvalue('width', width) + self.setvalue('height', height) + return self + + def setmax(self, maxwidth = None, maxheight = None): + "Set max width and/or height." + self.setvalue('maxwidth', maxwidth) + self.setvalue('maxheight', maxheight) + return self + + def readparameters(self, container): + "Read some size parameters off a container." + self.setparameter(container, 'width') + self.setparameter(container, 'height') + self.setparameter(container, 'scale') + self.checkvalidheight(container) + return self + + def setparameter(self, container, name): + "Read a size parameter off a container, and set it if present." + value = container.getparameter(name) + self.setvalue(name, value) + + def setvalue(self, name, value): + "Set the value of a parameter name, only if it's valid." + value = self.processparameter(value) + if value: + setattr(self, name, value) + + def checkvalidheight(self, container): + "Check if the height parameter is valid; otherwise erase it." + heightspecial = container.getparameter('height_special') + if self.height and self.extractnumber(self.height) == '1' and heightspecial == 'totalheight': + self.height = None + + def processparameter(self, value): + "Do the full processing on a parameter." + if not value: + return None + if self.extractnumber(value) == '0': + return None + for ignored in StyleConfig.size['ignoredtexts']: + if ignored in value: + value = value.replace(ignored, '') + return value + + def extractnumber(self, text): + "Extract the first number in the given text." + result = '' + decimal = False + for char in text: + if char.isdigit(): + result += char + elif char == '.' and not decimal: + result += char + decimal = True + else: + return result + return result + + def checkimage(self, width, height): + "Check image dimensions, set them if possible." + if width: + self.maxwidth = unicode(width) + 'px' + if self.scale and not self.width: + self.width = self.scalevalue(width) + if height: + self.maxheight = unicode(height) + 'px' + if self.scale and not self.height: + self.height = self.scalevalue(height) + if self.width and not self.height: + self.height = 'auto' + if self.height and not self.width: + self.width = 'auto' + + def scalevalue(self, value): + "Scale the value according to the image scale and return it as unicode." + scaled = value * int(self.scale) / 100 + return unicode(int(scaled)) + 'px' + + def removepercentwidth(self): + "Remove percent width if present, to set it at the figure level." + if not self.width: + return None + if not '%' in self.width: + return None + width = self.width + self.width = None + if self.height == 'auto': + self.height = None + return width + + def addstyle(self, container): + "Add the proper style attribute to the output tag." + if not isinstance(container.output, TaggedOutput): + Trace.error('No tag to add style, in ' + unicode(container)) + if not self.width and not self.height and not self.maxwidth and not self.maxheight: + # nothing to see here; move along + return + tag = ' style="' + tag += self.styleparameter('width') + tag += self.styleparameter('maxwidth') + tag += self.styleparameter('height') + tag += self.styleparameter('maxheight') + if tag[-1] == ' ': + tag = tag[:-1] + tag += '"' + container.output.tag += tag + + def styleparameter(self, name): + "Get the style for a single parameter." + value = getattr(self, name) + if value: + return name.replace('max', 'max-') + ': ' + value + '; ' + return '' + + + +class QuoteContainer(Container): + "A container for a pretty quote" + + def __init__(self): + self.parser = BoundedParser() + self.output = FixedOutput() + + def process(self): + "Process contents" + self.type = self.header[2] + if not self.type in StyleConfig.quotes: + Trace.error('Quote type ' + self.type + ' not found') + self.html = ['"'] + return + self.html = [StyleConfig.quotes[self.type]] + +class LyXLine(Container): + "A Lyx line" + + def __init__(self): + self.parser = LoneCommand() + self.output = FixedOutput() + + def process(self): + self.html = ['
      '] + +class EmphaticText(TaggedText): + "Text with emphatic mode" + + def process(self): + self.output.tag = 'i' + +class ShapedText(TaggedText): + "Text shaped (italic, slanted)" + + def process(self): + self.type = self.header[1] + if not self.type in TagConfig.shaped: + Trace.error('Unrecognized shape ' + self.header[1]) + self.output.tag = 'span' + return + self.output.tag = TagConfig.shaped[self.type] + +class VersalitasText(TaggedText): + "Text in versalitas" + + def process(self): + self.output.tag = 'span class="versalitas"' + +class ColorText(TaggedText): + "Colored text" + + def process(self): + self.color = self.header[1] + self.output.tag = 'span class="' + self.color + '"' + +class SizeText(TaggedText): + "Sized text" + + def process(self): + self.size = self.header[1] + self.output.tag = 'span class="' + self.size + '"' + +class BoldText(TaggedText): + "Bold text" + + def process(self): + self.output.tag = 'b' + +class TextFamily(TaggedText): + "A bit of text from elyxer.a different family" + + def process(self): + "Parse the type of family" + self.type = self.header[1] + if not self.type in TagConfig.family: + Trace.error('Unrecognized family ' + type) + self.output.tag = 'span' + return + self.output.tag = TagConfig.family[self.type] + +class Hfill(TaggedText): + "Horizontall fill" + + def process(self): + self.output.tag = 'span class="hfill"' + +class BarredText(TaggedText): + "Text with a bar somewhere" + + def process(self): + "Parse the type of bar" + self.type = self.header[1] + if not self.type in TagConfig.barred: + Trace.error('Unknown bar type ' + self.type) + self.output.tag = 'span' + return + self.output.tag = TagConfig.barred[self.type] + +class LangLine(TaggedText): + "A line with language information" + + def process(self): + "Only generate a span with lang info when the language is recognized." + lang = self.header[1] + if not lang in TranslationConfig.languages: + self.output = ContentsOutput() + return + isolang = TranslationConfig.languages[lang] + self.output = TaggedOutput().settag('span lang="' + isolang + '"', False) + +class InsetLength(BlackBox): + "A length measure inside an inset." + + def process(self): + self.length = self.header[1] + +class Space(Container): + "A space of several types" + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + + def process(self): + self.type = self.header[2] + if self.type not in StyleConfig.hspaces: + Trace.error('Unknown space type ' + self.type) + self.html = [' '] + return + self.html = [StyleConfig.hspaces[self.type]] + length = self.getlength() + if not length: + return + self.output = TaggedOutput().settag('span class="hspace"', False) + ContainerSize().set(length).addstyle(self) + + def getlength(self): + "Get the space length from elyxer.the contents or parameters." + if len(self.contents) == 0 or not isinstance(self.contents[0], InsetLength): + return None + return self.contents[0].length + +class VerticalSpace(Container): + "An inset that contains a vertical space." + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + + def process(self): + "Set the correct tag" + self.type = self.header[2] + if self.type not in StyleConfig.vspaces: + self.output = TaggedOutput().settag('div class="vspace" style="height: ' + self.type + ';"', True) + return + self.html = [StyleConfig.vspaces[self.type]] + +class Align(Container): + "Bit of aligned text" + + def __init__(self): + self.parser = ExcludingParser() + self.output = TaggedOutput().setbreaklines(True) + + def process(self): + self.output.tag = 'div class="' + self.header[1] + '"' + +class Newline(Container): + "A newline" + + def __init__(self): + self.parser = LoneCommand() + self.output = FixedOutput() + + def process(self): + "Process contents" + self.html = ['
      \n'] + +class NewPage(Newline): + "A new page" + + def process(self): + "Process contents" + self.html = ['


      \n

      \n'] + +class Separator(Container): + "A separator string which is not extracted by extracttext()." + + def __init__(self, constant): + self.output = FixedOutput() + self.contents = [] + self.html = [constant] + +class StrikeOut(TaggedText): + "Striken out text." + + def process(self): + "Set the output tag to strike." + self.output.tag = 'strike' + +class StartAppendix(BlackBox): + "Mark to start an appendix here." + "From this point on, all chapters become appendices." + + def process(self): + "Activate the special numbering scheme for appendices, using letters." + NumberGenerator.generator.startappendix() + + + + + + +class Link(Container): + "A link to another part of the document" + + anchor = None + url = None + type = None + page = None + target = None + destination = None + title = None + + def __init__(self): + "Initialize the link, add target if configured." + self.contents = [] + self.parser = InsetParser() + self.output = LinkOutput() + if Options.target: + self.target = Options.target + + def complete(self, text, anchor = None, url = None, type = None, title = None): + "Complete the link." + self.contents = [Constant(text)] + if anchor: + self.anchor = anchor + if url: + self.url = url + if type: + self.type = type + if title: + self.title = title + return self + + def computedestination(self): + "Use the destination link to fill in the destination URL." + if not self.destination: + return + self.url = '' + if self.destination.anchor: + self.url = '#' + self.destination.anchor + if self.destination.page: + self.url = self.destination.page + self.url + + def setmutualdestination(self, destination): + "Set another link as destination, and set its destination to this one." + self.destination = destination + destination.destination = self + + def __unicode__(self): + "Return a printable representation." + result = 'Link' + if self.anchor: + result += ' #' + self.anchor + if self.url: + result += ' to ' + self.url + return result + +class URL(Link): + "A clickable URL" + + def process(self): + "Read URL from elyxer.parameters" + target = self.escape(self.getparameter('target')) + self.url = target + type = self.getparameter('type') + if type: + self.url = self.escape(type) + target + name = self.getparameter('name') + if not name: + name = target + self.contents = [Constant(name)] + +class FlexURL(URL): + "A flexible URL" + + def process(self): + "Read URL from elyxer.contents" + self.url = self.extracttext() + +class LinkOutput(ContainerOutput): + "A link pointing to some destination" + "Or an anchor (destination)" + + def gethtml(self, link): + "Get the HTML code for the link" + type = link.__class__.__name__ + if link.type: + type = link.type + tag = 'a class="' + type + '"' + if link.anchor: + tag += ' name="' + link.anchor + '"' + if link.destination: + link.computedestination() + if link.url: + tag += ' href="' + link.url + '"' + if link.target: + tag += ' target="' + link.target + '"' + if link.title: + tag += ' title="' + link.title + '"' + return TaggedOutput().settag(tag).gethtml(link) + + + + + + + + +class Postprocessor(object): + "Postprocess a container keeping some context" + + stages = [] + + def __init__(self): + self.stages = StageDict(Postprocessor.stages, self) + self.current = None + self.last = None + + def postprocess(self, next): + "Postprocess a container and its contents." + self.postrecursive(self.current) + result = self.postcurrent(next) + self.last = self.current + self.current = next + return result + + def postrecursive(self, container): + "Postprocess the container contents recursively" + if not hasattr(container, 'contents'): + return + if len(container.contents) == 0: + return + if hasattr(container, 'postprocess'): + if not container.postprocess: + return + postprocessor = Postprocessor() + contents = [] + for element in container.contents: + post = postprocessor.postprocess(element) + if post: + contents.append(post) + # two rounds to empty the pipeline + for i in range(2): + post = postprocessor.postprocess(None) + if post: + contents.append(post) + container.contents = contents + + def postcurrent(self, next): + "Postprocess the current element taking into account next and last." + stage = self.stages.getstage(self.current) + if not stage: + return self.current + return stage.postprocess(self.last, self.current, next) + +class StageDict(object): + "A dictionary of stages corresponding to classes" + + def __init__(self, classes, postprocessor): + "Instantiate an element from elyxer.each class and store as a dictionary" + instances = self.instantiate(classes, postprocessor) + self.stagedict = dict([(x.processedclass, x) for x in instances]) + + def instantiate(self, classes, postprocessor): + "Instantiate an element from elyxer.each class" + stages = [x.__new__(x) for x in classes] + for element in stages: + element.__init__() + element.postprocessor = postprocessor + return stages + + def getstage(self, element): + "Get the stage for a given element, if the type is in the dict" + if not element.__class__ in self.stagedict: + return None + return self.stagedict[element.__class__] + + + +class Label(Link): + "A label to be referenced" + + names = dict() + lastlayout = None + + def __init__(self): + Link.__init__(self) + self.lastnumbered = None + + def process(self): + "Process a label container." + key = self.getparameter('name') + self.create(' ', key) + self.lastnumbered = Label.lastlayout + + def create(self, text, key, type = 'Label'): + "Create the label for a given key." + self.key = key + self.complete(text, anchor = key, type = type) + Label.names[key] = self + if key in Reference.references: + for reference in Reference.references[key]: + reference.destination = self + return self + + def findpartkey(self): + "Get the part key for the latest numbered container seen." + numbered = self.numbered(self) + if numbered and numbered.partkey: + return numbered.partkey + return '' + + def numbered(self, container): + "Get the numbered container for the label." + if container.partkey: + return container + if not container.parent: + if self.lastnumbered: + return self.lastnumbered + return None + return self.numbered(container.parent) + + def __unicode__(self): + "Return a printable representation." + if not hasattr(self, 'key'): + return 'Unnamed label' + return 'Label ' + self.key + +class Reference(Link): + "A reference to a label." + + references = dict() + key = 'none' + + def process(self): + "Read the reference and set the arrow." + self.key = self.getparameter('reference') + if self.key in Label.names: + self.direction = u'↑' + label = Label.names[self.key] + else: + self.direction = u'↓' + label = Label().complete(' ', self.key, 'preref') + self.destination = label + self.formatcontents() + if not self.key in Reference.references: + Reference.references[self.key] = [] + Reference.references[self.key].append(self) + + def formatcontents(self): + "Format the reference contents." + formatkey = self.getparameter('LatexCommand') + if not formatkey: + formatkey = 'ref' + self.formatted = u'↕' + if formatkey in StyleConfig.referenceformats: + self.formatted = StyleConfig.referenceformats[formatkey] + else: + Trace.error('Unknown reference format ' + formatkey) + self.replace(u'↕', self.direction) + self.replace('#', '1') + self.replace('on-page', Translator.translate('on-page')) + partkey = self.destination.findpartkey() + # only if partkey and partkey.number are not null, send partkey.number + self.replace('@', partkey and partkey.number) + self.replace(u'¶', partkey and partkey.tocentry) + if not '$' in self.formatted or not partkey or not partkey.titlecontents: + # there is a $ left, but it should go away on preprocessing + self.contents = [Constant(self.formatted)] + return + pieces = self.formatted.split('$') + self.contents = [Constant(pieces[0])] + for piece in pieces[1:]: + self.contents += partkey.titlecontents + self.contents.append(Constant(piece)) + + def replace(self, key, value): + "Replace a key in the format template with a value." + if not key in self.formatted: + return + if not value: + value = '' + self.formatted = self.formatted.replace(key, value) + + def __unicode__(self): + "Return a printable representation." + return 'Reference ' + self.key + + + + + + + + + + + + + + + +class HeaderParser(Parser): + "Parses the LyX header" + + def parse(self, reader): + "Parse header parameters into a dictionary, return the preamble." + contents = [] + self.parseending(reader, lambda: self.parseline(reader, contents)) + # skip last line + reader.nextline() + return contents + + def parseline(self, reader, contents): + "Parse a single line as a parameter or as a start" + line = reader.currentline() + if line.startswith(HeaderConfig.parameters['branch']): + self.parsebranch(reader) + return + elif line.startswith(HeaderConfig.parameters['lstset']): + LstParser().parselstset(reader) + return + elif line.startswith(HeaderConfig.parameters['beginpreamble']): + contents.append(self.factory.createcontainer(reader)) + return + # no match + self.parseparameter(reader) + + def parsebranch(self, reader): + "Parse all branch definitions." + branch = reader.currentline().split()[1] + reader.nextline() + subparser = HeaderParser().complete(HeaderConfig.parameters['endbranch']) + subparser.parse(reader) + options = BranchOptions(branch) + for key in subparser.parameters: + options.set(key, subparser.parameters[key]) + Options.branches[branch] = options + + def complete(self, ending): + "Complete the parser with the given ending." + self.ending = ending + return self + +class PreambleParser(Parser): + "A parser for the LyX preamble." + + preamble = [] + + def parse(self, reader): + "Parse the full preamble with all statements." + self.ending = HeaderConfig.parameters['endpreamble'] + self.parseending(reader, lambda: self.parsepreambleline(reader)) + return [] + + def parsepreambleline(self, reader): + "Parse a single preamble line." + PreambleParser.preamble.append(reader.currentline()) + reader.nextline() + +class LstParser(object): + "Parse global and local lstparams." + + globalparams = dict() + + def parselstset(self, reader): + "Parse a declaration of lstparams in lstset." + paramtext = self.extractlstset(reader) + if not '{' in paramtext: + Trace.error('Missing opening bracket in lstset: ' + paramtext) + return + lefttext = paramtext.split('{')[1] + croppedtext = lefttext[:-1] + LstParser.globalparams = self.parselstparams(croppedtext) + + def extractlstset(self, reader): + "Extract the global lstset parameters." + paramtext = '' + while not reader.finished(): + paramtext += reader.currentline() + reader.nextline() + if paramtext.endswith('}'): + return paramtext + Trace.error('Could not find end of \\lstset settings; aborting') + + def parsecontainer(self, container): + "Parse some lstparams from elyxer.a container." + container.lstparams = LstParser.globalparams.copy() + paramlist = container.getparameterlist('lstparams') + container.lstparams.update(self.parselstparams(paramlist)) + + def parselstparams(self, paramlist): + "Process a number of lstparams from elyxer.a list." + paramdict = dict() + for param in paramlist: + if not '=' in param: + if len(param.strip()) > 0: + Trace.error('Invalid listing parameter ' + param) + else: + key, value = param.split('=', 1) + paramdict[key] = value + return paramdict + + + + + +import datetime + + + +import os +import codecs + + +class BulkFile(object): + "A file to treat in bulk" + + encodings = ['utf-8','Cp1252'] + + def __init__(self, filename): + self.filename = filename + self.temp = self.filename + '.temp' + + def readall(self): + "Read the whole file" + for encoding in BulkFile.encodings: + try: + return self.readcodec(encoding) + except UnicodeDecodeError: + pass + Trace.error('No suitable encoding for ' + self.filename) + return [] + + def readcodec(self, encoding): + "Read the whole file with the given encoding" + filein = codecs.open(self.filename, 'rU', encoding) + lines = filein.readlines() + result = [] + for line in lines: + result.append(line.strip('\r\n') + '\n') + filein.close() + return result + + def getfiles(self): + "Get reader and writer for a file name" + reader = LineReader(self.filename) + writer = LineWriter(self.temp) + return reader, writer + + def swaptemp(self): + "Swap the temp file for the original" + os.chmod(self.temp, os.stat(self.filename).st_mode) + os.rename(self.temp, self.filename) + + def __unicode__(self): + "Get the unicode representation" + return 'file ' + self.filename + + + +class HTMLTemplate(object): + "A template for HTML generation." + + current = None + + def getheader(self): + "Get the header (before content) of the template." + return [] + + def convertheader(self): + "Convert the header and all variables." + return self.convert(self.getheader()) + + def convertfooter(self): + "Convert the footer and all variables." + return self.convert(self.getfooter()) + + def convert(self, html): + "Convert a bit of HTML replacing all variables." + varmap = VariableMap() + for index, line in enumerate(html): + if '\n'] + + def getfooter(self): + "Get the raw footer." + return ['\n\n'] + +class FileTemplate(HTMLTemplate): + "A template read from elyxer.a file." + + divider = '' + + def read(self): + "Read the file, separate header and footer." + self.header = [] + lines = [] + for line in self.templatelines(): + if FileTemplate.divider == line: + self.header = lines + lines = [] + else: + lines.append(line) + if self.header == []: + Trace.error('No ' + FileTemplate.divider + ' in template') + self.header = lines + lines = [] + self.footer = lines + return self + + def templatelines(self): + "Read all lines in the template, separate content into its own line." + template = BulkFile(Options.template).readall() + for line in template: + if not FileTemplate.divider in line: + yield line + else: + split = line.split(FileTemplate.divider) + for part in split[:-1]: + yield part + yield FileTemplate.divider + yield split[-1] + + def getheader(self): + "Return the header (before content)." + return self.header + + def getfooter(self): + "Return the footer (after the content)." + return self.footer + +class DefaultTemplate(HTMLTemplate): + "The default HTML template when not configured." + + def getheader(self): + "Get the default header (before content)." + html = [] + if not Options.html: + html.append(u'"?>\n') + html.append(u'\n') + html.append(u'\n') + else: + html.append(u'\n') + html.append(u'\n') + html.append(u'\n') + html.append(u'\n') + html.append(u'\n') + html.append(u'\n') + html += self.getcss() + html.append(u'<!--$title-->\n') + if Options.jsmath: + html.append(u'\n') + html.append(u'\n') + if Options.mathjax: + if Options.mathjax == 'remote': + html.append(u'\n') + else: + html.append(u'\n') + html.append('\n') + html.append('\n') + html.append('
      \n') + if Options.jsmath or Options.mathjax: + if Options.mathjax: + html.append(u'\n') + html.append(u'\n') + return html + + def getcss(self): + "Get the CSS headers, both linked and embedded." + html = [] + for cssdoc in Options.css: + if cssdoc != '': + html.append(u'\n') + for cssfile in Options.embedcss: + html.append(u'\n') + return html + + def getfooter(self): + "Get the default footer (after content)." + html = [] + html.append('\n') + footer = self.createfooter() + if len(footer) > 0: + html.append('\n') + html += footer + html.append('
      \n') + html.append('\n') + html.append('\n') + return html + + def createfooter(self): + "Create the footer proper." + html = [] + if Options.copyright: + html.append('\n') + if Options.nofooter: + return html + html.append('\n') + return html + +class VariableMap(object): + "A map with all replacement variables." + + def __init__(self): + self.variables = dict() + self.variables['title'] = DocumentTitle().getvalue() + self.variables['author'] = DocumentAuthor().getvalue() + self.variables['version'] = GeneralConfig.version['number'] + ' (' \ + + GeneralConfig.version['date'] + ')' + self.variables['year'] = unicode(datetime.date.today().year) + self.variables['date'] = datetime.date.today().isoformat() + self.variables['datetime'] = datetime.datetime.now().isoformat() + self.variables['css'] = Options.css[0] + if Options.iso885915: + self.variables['encoding'] = 'ISO-8859-1' + else: + self.variables['encoding'] = 'UTF-8' + if Options.jsmath: + self.variables['jsmath'] = Options.jsmath + if Options.mathjax: + self.variables['mathjax'] = Options.mathjax + + def replace(self, line): + "Replace all variables in a line." + result = '' + pos = TextPosition(line) + while not pos.finished(): + if pos.checkskip(''): + Trace.error('Weird template format in ' + line) + return value + +class DocumentTitle(object): + "The title of the whole document." + + title = None + + def getvalue(self): + "Return the correct title from elyxer.the option or the PDF title." + if Options.title: + return Options.title + if DocumentTitle.title: + return DocumentTitle.title + if DocumentParameters.pdftitle: + return DocumentParameters.pdftitle + return 'Converted document' + +class DocumentAuthor(object): + "The author of the document." + + author = '' + + def appendauthor(cls, authorline): + "Append a line with author information." + cls.author += authorline + + appendauthor = classmethod(appendauthor) + + def getvalue(self): + "Get the document author." + return DocumentAuthor.author + +class HeaderOutput(ContainerOutput): + "Returns the HTML headers" + + def gethtml(self, container): + "Return a constant header" + return HTMLTemplate.get().convertheader() + +class FooterOutput(ContentsOutput): + "Return the HTML code for the footer" + + def gethtml(self, container): + "Footer HTML" + contents = ContentsOutput.gethtml(self, container) + return contents + HTMLTemplate.get().convertfooter() + + + + + + + + + +class InsetText(Container): + "An inset of text in a lyx file" + + def __init__(self): + self.parser = BoundedParser() + self.output = ContentsOutput() + +class Inset(Container): + "A generic inset in a LyX document" + + def __init__(self): + self.contents = list() + self.parser = InsetParser() + self.output = TaggedOutput().setbreaklines(True) + + def process(self): + self.type = self.header[1] + self.output.tag = 'span class="' + self.type + '"' + + def __unicode__(self): + return 'Inset of type ' + self.type + +class NewlineInset(Newline): + "A newline or line break in an inset" + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + +class NewPageInset(NewPage): + "A new page command." + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + +class Branch(Container): + "A branch within a LyX document" + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="branch"', True) + + def process(self): + "Disable inactive branches" + self.branch = self.header[2] + if not self.isactive(): + Trace.debug('Branch ' + self.branch + ' not active') + self.output = EmptyOutput() + + def isactive(self): + "Check if the branch is active" + if not self.branch in Options.branches: + Trace.error('Invalid branch ' + self.branch) + return True + branch = Options.branches[self.branch] + return branch.isselected() + +class ShortTitle(Container): + "A short title to display (always hidden)" + + def __init__(self): + self.parser = InsetParser() + self.output = EmptyOutput() + +class FlexInset(Container): + "A flexible inset, generic version." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span', False) + + def process(self): + "Set the correct flex tag." + self.type = self.header[2] + if self.type in TagConfig.flex: + self.output.settag(TagConfig.flex[self.type], False) + else: + self.output.settag('span class="' + self.type + '"', False) + +class InfoInset(Container): + "A LyX Info inset" + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="Info"', False) + + def process(self): + "Set the shortcut as text" + self.type = self.getparameter('type') + self.contents = [Constant(self.getparameter('arg'))] + +class BoxInset(Container): + "A box inset" + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('div', True) + + def process(self): + "Set the correct tag" + self.type = self.header[2] + self.output.settag('div class="' + self.type + '"', True) + ContainerSize().readparameters(self).addstyle(self) + +class PhantomText(Container): + "A line of invisible text (white over white)." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="phantom"', False) + +class LineInset(LyXLine): + "A LaTeX ruler, but parsed as an inset." + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + +class Caption(Container): + "A caption for a figure or a table" + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('div class="caption"', True) + + def create(self, message): + "Create a caption with a given message." + self.contents = [Constant(message)] + return self + +class ScriptInset(Container): + "Sub- or super-script in an inset." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span', False) + + def process(self): + "Set the correct script tag." + self.type = self.header[2] + if not self.type in TagConfig.script: + Trace.error('Unknown script type ' + self.type) + return + self.output.settag(TagConfig.script[self.type], False) + + + +class PartKey(object): + "A key to identify a given document part (chapter, section...)." + + partkey = None + tocentry = None + anchortext = None + number = None + filename = None + titlecontents = None + header = False + + def __init__(self): + self.level = 0 + + def createindex(self, partkey): + "Create a part key for an index page." + self.partkey = partkey + self.tocentry = partkey + self.filename = partkey + return self + + def createfloat(self, float): + "Create a part key for a float." + self.number = NumberGenerator.chaptered.generate(float.type) + self.partkey = Translator.translate('float-' + float.type) + self.number + if Options.notoclabels: + self.tocentry = self.number + else: + self.tocentry = self.partkey + self.readtitle(float) + return self + + def createsubfloat(self, number): + "Create the part key for a subfloat." + self.partkey = '(' + number + ')' + self.number = number + return self + + def createformula(self, number): + "Create the part key for a formula." + self.number = number + self.partkey = 'formula-' + number + self.tocentry = '(' + number + ')' + return self + + def createheader(self, headorfooter): + "Create the part key for a header or footer." + self.partkey = headorfooter + self.tocentry = None + self.header = True + return self + + def createanchor(self, partkey): + "Create an anchor for the page." + self.partkey = partkey + self.tocentry = partkey + self.header = True + return self + + def createmain(self): + "Create the part key for the main page." + self.partkey = '' + self.tocentry = DocumentTitle().getvalue() + return self + + def addtoclabel(self, container): + "Create the label for the TOC, and add it to the container." + labeltext = '' + if self.anchortext: + labeltext = self.anchortext + container.contents.insert(0, Separator(u' ')) + label = Label().create(labeltext, self.partkey, type='toc') + container.contents.insert(0, label) + + def readtitle(self, container): + "Read the title of the TOC entry." + shorttitles = container.searchall(ShortTitle) + if len(shorttitles) > 0: + self.titlecontents = [] + for shorttitle in shorttitles: + self.titlecontents += shorttitle.contents + return + extractor = ContainerExtractor(TOCConfig.extracttitle) + captions = container.searchall(Caption) + if len(captions) == 1: + self.titlecontents = extractor.extract(captions[0]) + return + self.titlecontents = extractor.extract(container) + + def __unicode__(self): + "Return a printable representation." + return 'Part key for ' + self.partkey + +class LayoutPartKey(PartKey): + "The part key for a layout." + + generator = NumberGenerator() + + def create(self, layout): + "Set the layout for which we are creating the part key." + self.processtype(layout.type) + self.readtitle(layout) + return self + + def processtype(self, type): + "Process the layout type." + self.level = self.generator.getlevel(type) + self.number = self.generator.generate(type) + anchortype = self.getanchortype(type) + self.partkey = 'toc-' + anchortype + '-' + self.number + self.tocentry = self.gettocentry(type) + self.filename = self.getfilename(type) + if self.generator.isnumbered(type): + if not self.tocentry: + self.tocentry = '' + else: + self.tocentry += ' ' + self.tocentry += self.number + self.anchortext = self.getanchortext(type) + + def getanchortype(self, type): + "Get the type for the anchor." + parttype = self.generator.getparttype(type) + if self.generator.isunordered(type): + parttype += '-' + return parttype + + def gettocentry(self, type): + "Get the entry for the TOC: Chapter, Section..." + if Options.notoclabels: + return '' + return Translator.translate(self.generator.getparttype(type)) + + def addtotocentry(self, text): + "Add some text to the tocentry; create if None." + if not self.tocentry: + self.tocentry = '' + self.tocentry += text + + def getanchortext(self, type): + "Get the text for the anchor given to a layout type." + if self.generator.isunique(type): + return self.tocentry + '.' + return self.number + + def getfilename(self, type): + "Get the filename to be used if splitpart is active." + if self.level == Options.splitpart and self.generator.isnumbered(type): + return self.number + if self.level <= Options.splitpart: + return self.partkey.replace('toc-', '') + return None + + def needspartkey(self, layout): + "Find out if a layout needs a part key." + if self.generator.isunique(layout.type): + return True + return self.generator.isinordered(layout.type) + + def __unicode__(self): + "Get a printable representation." + return 'Part key for layout ' + self.tocentry + +class PartKeyGenerator(object): + "Number a layout with the relevant attributes." + + partkeyed = [] + layoutpartkey = LayoutPartKey() + + def forlayout(cls, layout): + "Get the part key for a layout." + if layout.hasemptyoutput(): + return None + if not cls.layoutpartkey.needspartkey(layout): + return None + Label.lastlayout = layout + cls.partkeyed.append(layout) + return LayoutPartKey().create(layout) + + def forindex(cls, index): + "Get the part key for an index or nomenclature." + if index.hasemptyoutput(): + return None + cls.partkeyed.append(index) + return PartKey().createindex(index.name) + + forlayout = classmethod(forlayout) + forindex = classmethod(forindex) + + + + +import unicodedata + + + +import urllib + + + + + +class FormulaParser(Parser): + "Parses a formula" + + def parseheader(self, reader): + "See if the formula is inlined" + self.begin = reader.linenumber + 1 + type = self.parsetype(reader) + if not type: + reader.nextline() + type = self.parsetype(reader) + if not type: + Trace.error('Unknown formula type in ' + reader.currentline().strip()) + return ['unknown'] + return [type] + + def parsetype(self, reader): + "Get the formula type from the first line." + if reader.currentline().find(FormulaConfig.starts['simple']) >= 0: + return 'inline' + if reader.currentline().find(FormulaConfig.starts['complex']) >= 0: + return 'block' + if reader.currentline().find(FormulaConfig.starts['unnumbered']) >= 0: + return 'block' + if reader.currentline().find(FormulaConfig.starts['beginbefore']) >= 0: + return 'numbered' + return None + + def parse(self, reader): + "Parse the formula until the end" + formula = self.parseformula(reader) + while not reader.currentline().startswith(self.ending): + stripped = reader.currentline().strip() + if len(stripped) > 0: + Trace.error('Unparsed formula line ' + stripped) + reader.nextline() + reader.nextline() + return formula + + def parseformula(self, reader): + "Parse the formula contents" + simple = FormulaConfig.starts['simple'] + if simple in reader.currentline(): + rest = reader.currentline().split(simple, 1)[1] + if simple in rest: + # formula is $...$ + return self.parsesingleliner(reader, simple, simple) + # formula is multiline $...$ + return self.parsemultiliner(reader, simple, simple) + if FormulaConfig.starts['complex'] in reader.currentline(): + # formula of the form \[...\] + return self.parsemultiliner(reader, FormulaConfig.starts['complex'], + FormulaConfig.endings['complex']) + beginbefore = FormulaConfig.starts['beginbefore'] + beginafter = FormulaConfig.starts['beginafter'] + if beginbefore in reader.currentline(): + if reader.currentline().strip().endswith(beginafter): + current = reader.currentline().strip() + endsplit = current.split(beginbefore)[1].split(beginafter) + startpiece = beginbefore + endsplit[0] + beginafter + endbefore = FormulaConfig.endings['endbefore'] + endafter = FormulaConfig.endings['endafter'] + endpiece = endbefore + endsplit[0] + endafter + return startpiece + self.parsemultiliner(reader, startpiece, endpiece) + endpiece + Trace.error('Missing ' + beginafter + ' in ' + reader.currentline()) + return '' + begincommand = FormulaConfig.starts['command'] + beginbracket = FormulaConfig.starts['bracket'] + if begincommand in reader.currentline() and beginbracket in reader.currentline(): + endbracket = FormulaConfig.endings['bracket'] + return self.parsemultiliner(reader, beginbracket, endbracket) + Trace.error('Formula beginning ' + reader.currentline() + ' is unknown') + return '' + + def parsesingleliner(self, reader, start, ending): + "Parse a formula in one line" + line = reader.currentline().strip() + if not start in line: + Trace.error('Line ' + line + ' does not contain formula start ' + start) + return '' + if not line.endswith(ending): + Trace.error('Formula ' + line + ' does not end with ' + ending) + return '' + index = line.index(start) + rest = line[index + len(start):-len(ending)] + reader.nextline() + return rest + + def parsemultiliner(self, reader, start, ending): + "Parse a formula in multiple lines" + formula = '' + line = reader.currentline() + if not start in line: + Trace.error('Line ' + line.strip() + ' does not contain formula start ' + start) + return '' + index = line.index(start) + line = line[index + len(start):].strip() + while not line.endswith(ending): + formula += line + '\n' + reader.nextline() + line = reader.currentline() + formula += line[:-len(ending)] + reader.nextline() + return formula + +class MacroParser(FormulaParser): + "A parser for a formula macro." + + def parseheader(self, reader): + "See if the formula is inlined" + self.begin = reader.linenumber + 1 + return ['inline'] + + def parse(self, reader): + "Parse the formula until the end" + formula = self.parsemultiliner(reader, self.parent.start, self.ending) + reader.nextline() + return formula + + + + + + + + + +class FormulaBit(Container): + "A bit of a formula" + + type = None + size = 1 + original = '' + + def __init__(self): + "The formula bit type can be 'alpha', 'number', 'font'." + self.contents = [] + self.output = ContentsOutput() + + def setfactory(self, factory): + "Set the internal formula factory." + self.factory = factory + return self + + def add(self, bit): + "Add any kind of formula bit already processed" + self.contents.append(bit) + self.original += bit.original + bit.parent = self + + def skiporiginal(self, string, pos): + "Skip a string and add it to the original formula" + self.original += string + if not pos.checkskip(string): + Trace.error('String ' + string + ' not at ' + pos.identifier()) + + def computesize(self): + "Compute the size of the bit as the max of the sizes of all contents." + if len(self.contents) == 0: + return 1 + self.size = max([element.size for element in self.contents]) + return self.size + + def clone(self): + "Return a copy of itself." + return self.factory.parseformula(self.original) + + def __unicode__(self): + "Get a string representation" + return self.__class__.__name__ + ' read in ' + self.original + +class TaggedBit(FormulaBit): + "A tagged string in a formula" + + def constant(self, constant, tag): + "Set the constant and the tag" + self.output = TaggedOutput().settag(tag) + self.add(FormulaConstant(constant)) + return self + + def complete(self, contents, tag, breaklines = False): + "Set the constant and the tag" + self.contents = contents + self.output = TaggedOutput().settag(tag, breaklines) + return self + + def selfcomplete(self, tag): + "Set the self-closing tag, no contents (as in
      )." + self.output = TaggedOutput().settag(tag, empty = True) + return self + +class FormulaConstant(Constant): + "A constant string in a formula" + + def __init__(self, string): + "Set the constant string" + Constant.__init__(self, string) + self.original = string + self.size = 1 + self.type = None + + def computesize(self): + "Compute the size of the constant: always 1." + return self.size + + def clone(self): + "Return a copy of itself." + return FormulaConstant(self.original) + + def __unicode__(self): + "Return a printable representation." + return 'Formula constant: ' + self.string + +class RawText(FormulaBit): + "A bit of text inside a formula" + + def detect(self, pos): + "Detect a bit of raw text" + return pos.current().isalpha() + + def parsebit(self, pos): + "Parse alphabetic text" + alpha = pos.globalpha() + self.add(FormulaConstant(alpha)) + self.type = 'alpha' + +class FormulaSymbol(FormulaBit): + "A symbol inside a formula" + + modified = FormulaConfig.modified + unmodified = FormulaConfig.unmodified['characters'] + + def detect(self, pos): + "Detect a symbol" + if pos.current() in FormulaSymbol.unmodified: + return True + if pos.current() in FormulaSymbol.modified: + return True + return False + + def parsebit(self, pos): + "Parse the symbol" + if pos.current() in FormulaSymbol.unmodified: + self.addsymbol(pos.current(), pos) + return + if pos.current() in FormulaSymbol.modified: + self.addsymbol(FormulaSymbol.modified[pos.current()], pos) + return + Trace.error('Symbol ' + pos.current() + ' not found') + + def addsymbol(self, symbol, pos): + "Add a symbol" + self.skiporiginal(pos.current(), pos) + self.contents.append(FormulaConstant(symbol)) + +class FormulaNumber(FormulaBit): + "A string of digits in a formula" + + def detect(self, pos): + "Detect a digit" + return pos.current().isdigit() + + def parsebit(self, pos): + "Parse a bunch of digits" + digits = pos.glob(lambda: pos.current().isdigit()) + self.add(FormulaConstant(digits)) + self.type = 'number' + +class Comment(FormulaBit): + "A LaTeX comment: % to the end of the line." + + start = FormulaConfig.starts['comment'] + + def detect(self, pos): + "Detect the %." + return pos.current() == self.start + + def parsebit(self, pos): + "Parse to the end of the line." + self.original += pos.globincluding('\n') + +class WhiteSpace(FormulaBit): + "Some white space inside a formula." + + def detect(self, pos): + "Detect the white space." + return pos.current().isspace() + + def parsebit(self, pos): + "Parse all whitespace." + self.original += pos.skipspace() + + def __unicode__(self): + "Return a printable representation." + return 'Whitespace: *' + self.original + '*' + +class Bracket(FormulaBit): + "A {} bracket inside a formula" + + start = FormulaConfig.starts['bracket'] + ending = FormulaConfig.endings['bracket'] + + def __init__(self): + "Create a (possibly literal) new bracket" + FormulaBit.__init__(self) + self.inner = None + + def detect(self, pos): + "Detect the start of a bracket" + return pos.checkfor(self.start) + + def parsebit(self, pos): + "Parse the bracket" + self.parsecomplete(pos, self.innerformula) + return self + + def parsetext(self, pos): + "Parse a text bracket" + self.parsecomplete(pos, self.innertext) + return self + + def parseliteral(self, pos): + "Parse a literal bracket" + self.parsecomplete(pos, self.innerliteral) + return self + + def parsecomplete(self, pos, innerparser): + "Parse the start and end marks" + if not pos.checkfor(self.start): + Trace.error('Bracket should start with ' + self.start + ' at ' + pos.identifier()) + return None + self.skiporiginal(self.start, pos) + pos.pushending(self.ending) + innerparser(pos) + self.original += pos.popending(self.ending) + self.computesize() + + def innerformula(self, pos): + "Parse a whole formula inside the bracket" + while not pos.finished(): + self.add(self.factory.parseany(pos)) + + def innertext(self, pos): + "Parse some text inside the bracket, following textual rules." + specialchars = FormulaConfig.symbolfunctions.keys() + specialchars.append(FormulaConfig.starts['command']) + specialchars.append(FormulaConfig.starts['bracket']) + specialchars.append(Comment.start) + while not pos.finished(): + if pos.current() in specialchars: + self.add(self.factory.parseany(pos)) + if pos.checkskip(' '): + self.original += ' ' + else: + self.add(FormulaConstant(pos.skipcurrent())) + + def innerliteral(self, pos): + "Parse a literal inside the bracket, which does not generate HTML." + self.literal = '' + while not pos.finished() and not pos.current() == self.ending: + if pos.current() == self.start: + self.parseliteral(pos) + else: + self.literal += pos.skipcurrent() + self.original += self.literal + +class SquareBracket(Bracket): + "A [] bracket inside a formula" + + start = FormulaConfig.starts['squarebracket'] + ending = FormulaConfig.endings['squarebracket'] + + def clone(self): + "Return a new square bracket with the same contents." + bracket = SquareBracket() + bracket.contents = self.contents + return bracket + + + +class MathsProcessor(object): + "A processor for a maths construction inside the FormulaProcessor." + + def process(self, contents, index): + "Process an element inside a formula." + Trace.error('Unimplemented process() in ' + unicode(self)) + + def __unicode__(self): + "Return a printable description." + return 'Maths processor ' + self.__class__.__name__ + +class FormulaProcessor(object): + "A processor specifically for formulas." + + processors = [] + + def process(self, bit): + "Process the contents of every formula bit, recursively." + self.processcontents(bit) + self.processinsides(bit) + self.traversewhole(bit) + + def processcontents(self, bit): + "Process the contents of a formula bit." + if not isinstance(bit, FormulaBit): + return + bit.process() + for element in bit.contents: + self.processcontents(element) + + def processinsides(self, bit): + "Process the insides (limits, brackets) in a formula bit." + if not isinstance(bit, FormulaBit): + return + for index, element in enumerate(bit.contents): + for processor in self.processors: + processor.process(bit.contents, index) + # continue with recursive processing + self.processinsides(element) + + def traversewhole(self, formula): + "Traverse over the contents to alter variables and space units." + last = None + for bit, contents in self.traverse(formula): + if bit.type == 'alpha': + self.italicize(bit, contents) + elif bit.type == 'font' and last and last.type == 'number': + bit.contents.insert(0, FormulaConstant(u' ')) + last = bit + + def traverse(self, bit): + "Traverse a formula and yield a flattened structure of (bit, list) pairs." + for element in bit.contents: + if hasattr(element, 'type') and element.type: + yield (element, bit.contents) + elif isinstance(element, FormulaBit): + for pair in self.traverse(element): + yield pair + + def italicize(self, bit, contents): + "Italicize the given bit of text." + index = contents.index(bit) + contents[index] = TaggedBit().complete([bit], 'i') + + + + +class Formula(Container): + "A LaTeX formula" + + def __init__(self): + self.parser = FormulaParser() + self.output = TaggedOutput().settag('span class="formula"') + + def process(self): + "Convert the formula to tags" + if self.header[0] == 'inline': + DocumentParameters.displaymode = False + else: + DocumentParameters.displaymode = True + self.output.settag('div class="formula"', True) + if Options.jsmath: + self.jsmath() + elif Options.mathjax: + self.mathjax() + elif Options.googlecharts: + self.googlecharts() + else: + self.classic() + + def jsmath(self): + "Make the contents for jsMath." + if self.header[0] != 'inline': + self.output = TaggedOutput().settag('div class="math"') + else: + self.output = TaggedOutput().settag('span class="math"') + self.contents = [Constant(self.parsed)] + + def mathjax(self): + "Make the contents for MathJax." + self.output.tag = 'span class="MathJax_Preview"' + tag = 'script type="math/tex' + if self.header[0] != 'inline': + tag += ';mode=display' + self.contents = [TaggedText().constant(self.parsed, tag + '"', True)] + + def googlecharts(self): + "Make the contents using Google Charts http://code.google.com/apis/chart/." + url = FormulaConfig.urls['googlecharts'] + urllib.quote_plus(self.parsed) + img = '' + self.parsed + '' + self.contents = [Constant(img)] + + def classic(self): + "Make the contents using classic output generation with XHTML and CSS." + whole = FormulaFactory().parseformula(self.parsed) + FormulaProcessor().process(whole) + whole.parent = self + self.contents = [whole] + + def parse(self, pos): + "Parse using a parse position instead of self.parser." + if pos.checkskip('$$'): + self.parsedollarblock(pos) + elif pos.checkskip('$'): + self.parsedollarinline(pos) + elif pos.checkskip('\\('): + self.parseinlineto(pos, '\\)') + elif pos.checkskip('\\['): + self.parseblockto(pos, '\\]') + else: + pos.error('Unparseable formula') + self.process() + return self + + def parsedollarinline(self, pos): + "Parse a $...$ formula." + self.header = ['inline'] + self.parsedollar(pos) + + def parsedollarblock(self, pos): + "Parse a $$...$$ formula." + self.header = ['block'] + self.parsedollar(pos) + if not pos.checkskip('$'): + pos.error('Formula should be $$...$$, but last $ is missing.') + + def parsedollar(self, pos): + "Parse to the next $." + pos.pushending('$') + self.parsed = pos.globexcluding('$') + pos.popending('$') + + def parseinlineto(self, pos, limit): + "Parse a \\(...\\) formula." + self.header = ['inline'] + self.parseupto(pos, limit) + + def parseblockto(self, pos, limit): + "Parse a \\[...\\] formula." + self.header = ['block'] + self.parseupto(pos, limit) + + def parseupto(self, pos, limit): + "Parse a formula that ends with the given command." + pos.pushending(limit) + self.parsed = pos.glob(lambda: True) + pos.popending(limit) + + def __unicode__(self): + "Return a printable representation." + if self.partkey and self.partkey.number: + return 'Formula (' + self.partkey.number + ')' + return 'Unnumbered formula' + +class WholeFormula(FormulaBit): + "Parse a whole formula" + + def detect(self, pos): + "Not outside the formula is enough." + return not pos.finished() + + def parsebit(self, pos): + "Parse with any formula bit" + while not pos.finished(): + self.add(self.factory.parseany(pos)) + +class FormulaFactory(object): + "Construct bits of formula" + + # bit types will be appended later + types = [FormulaSymbol, RawText, FormulaNumber, Bracket, Comment, WhiteSpace] + skippedtypes = [Comment, WhiteSpace] + defining = False + + def __init__(self): + "Initialize the map of instances." + self.instances = dict() + + def detecttype(self, type, pos): + "Detect a bit of a given type." + if pos.finished(): + return False + return self.instance(type).detect(pos) + + def instance(self, type): + "Get an instance of the given type." + if not type in self.instances or not self.instances[type]: + self.instances[type] = self.create(type) + return self.instances[type] + + def create(self, type): + "Create a new formula bit of the given type." + return Cloner.create(type).setfactory(self) + + def clearskipped(self, pos): + "Clear any skipped types." + while not pos.finished(): + if not self.skipany(pos): + return + return + + def skipany(self, pos): + "Skip any skipped types." + for type in self.skippedtypes: + if self.instance(type).detect(pos): + return self.parsetype(type, pos) + return None + + def parseany(self, pos): + "Parse any formula bit at the current location." + for type in self.types + self.skippedtypes: + if self.detecttype(type, pos): + return self.parsetype(type, pos) + Trace.error('Unrecognized formula at ' + pos.identifier()) + return FormulaConstant(pos.skipcurrent()) + + def parsetype(self, type, pos): + "Parse the given type and return it." + bit = self.instance(type) + self.instances[type] = None + returnedbit = bit.parsebit(pos) + if returnedbit: + return returnedbit.setfactory(self) + return bit + + def parseformula(self, formula): + "Parse a string of text that contains a whole formula." + pos = TextPosition(formula) + whole = self.create(WholeFormula) + if whole.detect(pos): + whole.parsebit(pos) + return whole + # no formula found + if not pos.finished(): + Trace.error('Unknown formula at: ' + pos.identifier()) + whole.add(TaggedBit().constant(formula, 'span class="unknown"')) + return whole + + + +class FormulaCommand(FormulaBit): + "A LaTeX command inside a formula" + + types = [] + start = FormulaConfig.starts['command'] + commandmap = None + + def detect(self, pos): + "Find the current command." + return pos.checkfor(FormulaCommand.start) + + def parsebit(self, pos): + "Parse the command." + command = self.extractcommand(pos) + bit = self.parsewithcommand(command, pos) + if bit: + return bit + if command.startswith('\\up') or command.startswith('\\Up'): + upgreek = self.parseupgreek(command, pos) + if upgreek: + return upgreek + if not self.factory.defining: + Trace.error('Unknown command ' + command) + self.output = TaggedOutput().settag('span class="unknown"') + self.add(FormulaConstant(command)) + return None + + def parsewithcommand(self, command, pos): + "Parse the command type once we have the command." + for type in FormulaCommand.types: + if command in type.commandmap: + return self.parsecommandtype(command, type, pos) + return None + + def parsecommandtype(self, command, type, pos): + "Parse a given command type." + bit = self.factory.create(type) + bit.setcommand(command) + returned = bit.parsebit(pos) + if returned: + return returned + return bit + + def extractcommand(self, pos): + "Extract the command from elyxer.the current position." + if not pos.checkskip(FormulaCommand.start): + pos.error('Missing command start ' + FormulaCommand.start) + return + if pos.finished(): + return self.emptycommand(pos) + if pos.current().isalpha(): + # alpha command + command = FormulaCommand.start + pos.globalpha() + # skip mark of short command + pos.checkskip('*') + return command + # symbol command + return FormulaCommand.start + pos.skipcurrent() + + def emptycommand(self, pos): + """Check for an empty command: look for command disguised as ending. + Special case against '{ \{ \} }' situation.""" + command = '' + if not pos.isout(): + ending = pos.nextending() + if ending and pos.checkskip(ending): + command = ending + return FormulaCommand.start + command + + def parseupgreek(self, command, pos): + "Parse the Greek \\up command.." + if len(command) < 4: + return None + if command.startswith('\\up'): + upcommand = '\\' + command[3:] + elif pos.checkskip('\\Up'): + upcommand = '\\' + command[3:4].upper() + command[4:] + else: + Trace.error('Impossible upgreek command: ' + command) + return + upgreek = self.parsewithcommand(upcommand, pos) + if upgreek: + upgreek.type = 'font' + return upgreek + +class CommandBit(FormulaCommand): + "A formula bit that includes a command" + + def setcommand(self, command): + "Set the command in the bit" + self.command = command + if self.commandmap: + self.original += command + self.translated = self.commandmap[self.command] + + def parseparameter(self, pos): + "Parse a parameter at the current position" + self.factory.clearskipped(pos) + if pos.finished(): + return None + parameter = self.factory.parseany(pos) + self.add(parameter) + return parameter + + def parsesquare(self, pos): + "Parse a square bracket" + self.factory.clearskipped(pos) + if not self.factory.detecttype(SquareBracket, pos): + return None + bracket = self.factory.parsetype(SquareBracket, pos) + self.add(bracket) + return bracket + + def parseliteral(self, pos): + "Parse a literal bracket." + self.factory.clearskipped(pos) + if not self.factory.detecttype(Bracket, pos): + if not pos.isvalue(): + Trace.error('No literal parameter found at: ' + pos.identifier()) + return None + return pos.globvalue() + bracket = Bracket().setfactory(self.factory) + self.add(bracket.parseliteral(pos)) + return bracket.literal + + def parsesquareliteral(self, pos): + "Parse a square bracket literally." + self.factory.clearskipped(pos) + if not self.factory.detecttype(SquareBracket, pos): + return None + bracket = SquareBracket().setfactory(self.factory) + self.add(bracket.parseliteral(pos)) + return bracket.literal + + def parsetext(self, pos): + "Parse a text parameter." + self.factory.clearskipped(pos) + if not self.factory.detecttype(Bracket, pos): + Trace.error('No text parameter for ' + self.command) + return None + bracket = Bracket().setfactory(self.factory).parsetext(pos) + self.add(bracket) + return bracket + +class EmptyCommand(CommandBit): + "An empty command (without parameters)" + + commandmap = FormulaConfig.commands + + def parsebit(self, pos): + "Parse a command without parameters" + self.contents = [FormulaConstant(self.translated)] + +class SpacedCommand(CommandBit): + "An empty command which should have math spacing in formulas." + + commandmap = FormulaConfig.spacedcommands + + def parsebit(self, pos): + "Place as contents the command translated and spaced." + self.contents = [FormulaConstant(u' ' + self.translated + u' ')] + +class AlphaCommand(EmptyCommand): + "A command without paramters whose result is alphabetical" + + commandmap = FormulaConfig.alphacommands + + def parsebit(self, pos): + "Parse the command and set type to alpha" + EmptyCommand.parsebit(self, pos) + self.type = 'alpha' + +class OneParamFunction(CommandBit): + "A function of one parameter" + + commandmap = FormulaConfig.onefunctions + simplified = False + + def parsebit(self, pos): + "Parse a function with one parameter" + self.output = TaggedOutput().settag(self.translated) + self.parseparameter(pos) + self.simplifyifpossible() + + def simplifyifpossible(self): + "Try to simplify to a single character." + if self.original in self.commandmap: + self.output = FixedOutput() + self.html = [self.commandmap[self.original]] + self.simplified = True + +class SymbolFunction(CommandBit): + "Find a function which is represented by a symbol (like _ or ^)" + + commandmap = FormulaConfig.symbolfunctions + + def detect(self, pos): + "Find the symbol" + return pos.current() in SymbolFunction.commandmap + + def parsebit(self, pos): + "Parse the symbol" + self.setcommand(pos.current()) + pos.skip(self.command) + self.output = TaggedOutput().settag(self.translated) + self.parseparameter(pos) + +class TextFunction(CommandBit): + "A function where parameters are read as text." + + commandmap = FormulaConfig.textfunctions + + def parsebit(self, pos): + "Parse a text parameter" + self.output = TaggedOutput().settag(self.translated) + self.parsetext(pos) + + def process(self): + "Set the type to font" + self.type = 'font' + +class LabelFunction(CommandBit): + "A function that acts as a label" + + commandmap = FormulaConfig.labelfunctions + + def parsebit(self, pos): + "Parse a literal parameter" + self.key = self.parseliteral(pos) + + def process(self): + "Add an anchor with the label contents." + self.type = 'font' + self.label = Label().create(' ', self.key, type = 'eqnumber') + self.contents = [self.label] + # store as a Label so we know it's been seen + Label.names[self.key] = self.label + +class FontFunction(OneParamFunction): + "A function of one parameter that changes the font" + + commandmap = FormulaConfig.fontfunctions + + def process(self): + "Simplify if possible using a single character." + self.type = 'font' + self.simplifyifpossible() + +FormulaFactory.types += [FormulaCommand, SymbolFunction] +FormulaCommand.types = [ + AlphaCommand, EmptyCommand, OneParamFunction, FontFunction, LabelFunction, + TextFunction, SpacedCommand, + ] + + + + + + + + + + + + + + + +class BigSymbol(object): + "A big symbol generator." + + symbols = FormulaConfig.bigsymbols + + def __init__(self, symbol): + "Create the big symbol." + self.symbol = symbol + + def getpieces(self): + "Get an array with all pieces." + if not self.symbol in self.symbols: + return [self.symbol] + if self.smalllimit(): + return [self.symbol] + return self.symbols[self.symbol] + + def smalllimit(self): + "Decide if the limit should be a small, one-line symbol." + if not DocumentParameters.displaymode: + return True + if len(self.symbols[self.symbol]) == 1: + return True + return Options.simplemath + +class BigBracket(BigSymbol): + "A big bracket generator." + + def __init__(self, size, bracket, alignment='l'): + "Set the size and symbol for the bracket." + self.size = size + self.original = bracket + self.alignment = alignment + self.pieces = None + if bracket in FormulaConfig.bigbrackets: + self.pieces = FormulaConfig.bigbrackets[bracket] + + def getpiece(self, index): + "Return the nth piece for the bracket." + function = getattr(self, 'getpiece' + unicode(len(self.pieces))) + return function(index) + + def getpiece1(self, index): + "Return the only piece for a single-piece bracket." + return self.pieces[0] + + def getpiece3(self, index): + "Get the nth piece for a 3-piece bracket: parenthesis or square bracket." + if index == 0: + return self.pieces[0] + if index == self.size - 1: + return self.pieces[-1] + return self.pieces[1] + + def getpiece4(self, index): + "Get the nth piece for a 4-piece bracket: curly bracket." + if index == 0: + return self.pieces[0] + if index == self.size - 1: + return self.pieces[3] + if index == (self.size - 1)/2: + return self.pieces[2] + return self.pieces[1] + + def getcell(self, index): + "Get the bracket piece as an array cell." + piece = self.getpiece(index) + span = 'span class="bracket align-' + self.alignment + '"' + return TaggedBit().constant(piece, span) + + def getcontents(self): + "Get the bracket as an array or as a single bracket." + if self.size == 1 or not self.pieces: + return self.getsinglebracket() + rows = [] + for index in range(self.size): + cell = self.getcell(index) + rows.append(TaggedBit().complete([cell], 'span class="arrayrow"')) + return [TaggedBit().complete(rows, 'span class="array"')] + + def getsinglebracket(self): + "Return the bracket as a single sign." + if self.original == '.': + return [TaggedBit().constant('', 'span class="emptydot"')] + return [TaggedBit().constant(self.original, 'span class="symbol"')] + + + + + + +class FormulaEquation(CommandBit): + "A simple numbered equation." + + piece = 'equation' + + def parsebit(self, pos): + "Parse the array" + self.output = ContentsOutput() + self.add(self.factory.parsetype(WholeFormula, pos)) + +class FormulaCell(FormulaCommand): + "An array cell inside a row" + + def setalignment(self, alignment): + self.alignment = alignment + self.output = TaggedOutput().settag('span class="arraycell align-' + alignment +'"', True) + return self + + def parsebit(self, pos): + self.factory.clearskipped(pos) + if pos.finished(): + return + self.add(self.factory.parsetype(WholeFormula, pos)) + +class FormulaRow(FormulaCommand): + "An array row inside an array" + + cellseparator = FormulaConfig.array['cellseparator'] + + def setalignments(self, alignments): + self.alignments = alignments + self.output = TaggedOutput().settag('span class="arrayrow"', True) + return self + + def parsebit(self, pos): + "Parse a whole row" + index = 0 + pos.pushending(self.cellseparator, optional=True) + while not pos.finished(): + cell = self.createcell(index) + cell.parsebit(pos) + self.add(cell) + index += 1 + pos.checkskip(self.cellseparator) + if len(self.contents) == 0: + self.output = EmptyOutput() + + def createcell(self, index): + "Create the cell that corresponds to the given index." + alignment = self.alignments[index % len(self.alignments)] + return self.factory.create(FormulaCell).setalignment(alignment) + +class MultiRowFormula(CommandBit): + "A formula with multiple rows." + + def parserows(self, pos): + "Parse all rows, finish when no more row ends" + self.rows = [] + first = True + for row in self.iteraterows(pos): + if first: + first = False + else: + # intersparse empty rows + self.addempty() + row.parsebit(pos) + self.addrow(row) + self.size = len(self.rows) + + def iteraterows(self, pos): + "Iterate over all rows, end when no more row ends" + rowseparator = FormulaConfig.array['rowseparator'] + while True: + pos.pushending(rowseparator, True) + row = self.factory.create(FormulaRow) + yield row.setalignments(self.alignments) + if pos.checkfor(rowseparator): + self.original += pos.popending(rowseparator) + else: + return + + def addempty(self): + "Add an empty row." + row = self.factory.create(FormulaRow).setalignments(self.alignments) + for index, originalcell in enumerate(self.rows[-1].contents): + cell = row.createcell(index) + cell.add(FormulaConstant(u' ')) + row.add(cell) + self.addrow(row) + + def addrow(self, row): + "Add a row to the contents and to the list of rows." + self.rows.append(row) + self.add(row) + +class FormulaArray(MultiRowFormula): + "An array within a formula" + + piece = 'array' + + def parsebit(self, pos): + "Parse the array" + self.output = TaggedOutput().settag('span class="array"', False) + self.parsealignments(pos) + self.parserows(pos) + + def parsealignments(self, pos): + "Parse the different alignments" + # vertical + self.valign = 'c' + literal = self.parsesquareliteral(pos) + if literal: + self.valign = literal + # horizontal + literal = self.parseliteral(pos) + self.alignments = [] + for l in literal: + self.alignments.append(l) + +class FormulaMatrix(MultiRowFormula): + "A matrix (array with center alignment)." + + piece = 'matrix' + + def parsebit(self, pos): + "Parse the matrix, set alignments to 'c'." + self.output = TaggedOutput().settag('span class="array"', False) + self.valign = 'c' + self.alignments = ['c'] + self.parserows(pos) + +class FormulaCases(MultiRowFormula): + "A cases statement" + + piece = 'cases' + + def parsebit(self, pos): + "Parse the cases" + self.output = ContentsOutput() + self.alignments = ['l', 'l'] + self.parserows(pos) + for row in self.contents: + for cell in row.contents: + cell.output.settag('span class="case align-l"', True) + cell.contents.append(FormulaConstant(u' ')) + array = TaggedBit().complete(self.contents, 'span class="bracketcases"', True) + brace = BigBracket(len(self.contents), '{', 'l') + self.contents = brace.getcontents() + [array] + +class EquationEnvironment(MultiRowFormula): + "A \\begin{}...\\end equation environment with rows and cells." + + def parsebit(self, pos): + "Parse the whole environment." + self.output = TaggedOutput().settag('span class="environment"', False) + environment = self.piece.replace('*', '') + if environment in FormulaConfig.environments: + self.alignments = FormulaConfig.environments[environment] + else: + Trace.error('Unknown equation environment ' + self.piece) + self.alignments = ['l'] + self.parserows(pos) + +class BeginCommand(CommandBit): + "A \\begin{}...\end command and what it entails (array, cases, aligned)" + + commandmap = {FormulaConfig.array['begin']:''} + + types = [FormulaEquation, FormulaArray, FormulaCases, FormulaMatrix] + + def parsebit(self, pos): + "Parse the begin command" + command = self.parseliteral(pos) + bit = self.findbit(command) + ending = FormulaConfig.array['end'] + '{' + command + '}' + pos.pushending(ending) + bit.parsebit(pos) + self.add(bit) + self.original += pos.popending(ending) + self.size = bit.size + + def findbit(self, piece): + "Find the command bit corresponding to the \\begin{piece}" + for type in BeginCommand.types: + if piece.replace('*', '') == type.piece: + return self.factory.create(type) + bit = self.factory.create(EquationEnvironment) + bit.piece = piece + return bit + +FormulaCommand.types += [BeginCommand] + + +import datetime + + +class CombiningFunction(OneParamFunction): + + commandmap = FormulaConfig.combiningfunctions + + def parsebit(self, pos): + "Parse a combining function." + self.type = 'alpha' + combining = self.translated + parameter = self.parsesingleparameter(pos) + if not parameter: + Trace.error('Empty parameter for combining function ' + self.command) + elif len(parameter.extracttext()) != 1: + Trace.error('Applying combining function ' + self.command + ' to invalid string "' + parameter.extracttext() + '"') + self.contents.append(Constant(combining)) + + def parsesingleparameter(self, pos): + "Parse a parameter, or a single letter." + self.factory.clearskipped(pos) + if pos.finished(): + Trace.error('Error while parsing single parameter at ' + pos.identifier()) + return None + if self.factory.detecttype(Bracket, pos) \ + or self.factory.detecttype(FormulaCommand, pos): + return self.parseparameter(pos) + letter = FormulaConstant(pos.skipcurrent()) + self.add(letter) + return letter + +class DecoratingFunction(OneParamFunction): + "A function that decorates some bit of text" + + commandmap = FormulaConfig.decoratingfunctions + + def parsebit(self, pos): + "Parse a decorating function" + self.type = 'alpha' + symbol = self.translated + self.symbol = TaggedBit().constant(symbol, 'span class="symbolover"') + self.parameter = self.parseparameter(pos) + self.output = TaggedOutput().settag('span class="withsymbol"') + self.contents.insert(0, self.symbol) + self.parameter.output = TaggedOutput().settag('span class="undersymbol"') + self.simplifyifpossible() + +class LimitCommand(EmptyCommand): + "A command which accepts limits above and below, in display mode." + + commandmap = FormulaConfig.limitcommands + + def parsebit(self, pos): + "Parse a limit command." + pieces = BigSymbol(self.translated).getpieces() + self.output = TaggedOutput().settag('span class="limits"') + for piece in pieces: + self.contents.append(TaggedBit().constant(piece, 'span class="limit"')) + +class LimitPreviousCommand(LimitCommand): + "A command to limit the previous command." + + commandmap = None + + def parsebit(self, pos): + "Do nothing." + self.output = TaggedOutput().settag('span class="limits"') + self.factory.clearskipped(pos) + + def __unicode__(self): + "Return a printable representation." + return 'Limit previous command' + +class LimitsProcessor(MathsProcessor): + "A processor for limits inside an element." + + def process(self, contents, index): + "Process the limits for an element." + if Options.simplemath: + return + if self.checklimits(contents, index): + self.modifylimits(contents, index) + if self.checkscript(contents, index) and self.checkscript(contents, index + 1): + self.modifyscripts(contents, index) + + def checklimits(self, contents, index): + "Check if the current position has a limits command." + if not DocumentParameters.displaymode: + return False + if self.checkcommand(contents, index + 1, LimitPreviousCommand): + self.limitsahead(contents, index) + return False + if not isinstance(contents[index], LimitCommand): + return False + return self.checkscript(contents, index + 1) + + def limitsahead(self, contents, index): + "Limit the current element based on the next." + contents[index + 1].add(contents[index].clone()) + contents[index].output = EmptyOutput() + + def modifylimits(self, contents, index): + "Modify a limits commands so that the limits appear above and below." + limited = contents[index] + subscript = self.getlimit(contents, index + 1) + limited.contents.append(subscript) + if self.checkscript(contents, index + 1): + superscript = self.getlimit(contents, index + 1) + else: + superscript = TaggedBit().constant(u' ', 'sup class="limit"') + limited.contents.insert(0, superscript) + + def getlimit(self, contents, index): + "Get the limit for a limits command." + limit = self.getscript(contents, index) + limit.output.tag = limit.output.tag.replace('script', 'limit') + return limit + + def modifyscripts(self, contents, index): + "Modify the super- and subscript to appear vertically aligned." + subscript = self.getscript(contents, index) + # subscript removed so instead of index + 1 we get index again + superscript = self.getscript(contents, index) + scripts = TaggedBit().complete([superscript, subscript], 'span class="scripts"') + contents.insert(index, scripts) + + def checkscript(self, contents, index): + "Check if the current element is a sub- or superscript." + return self.checkcommand(contents, index, SymbolFunction) + + def checkcommand(self, contents, index, type): + "Check for the given type as the current element." + if len(contents) <= index: + return False + return isinstance(contents[index], type) + + def getscript(self, contents, index): + "Get the sub- or superscript." + bit = contents[index] + bit.output.tag += ' class="script"' + del contents[index] + return bit + +class BracketCommand(OneParamFunction): + "A command which defines a bracket." + + commandmap = FormulaConfig.bracketcommands + + def parsebit(self, pos): + "Parse the bracket." + OneParamFunction.parsebit(self, pos) + + def create(self, direction, character): + "Create the bracket for the given character." + self.original = character + self.command = '\\' + direction + self.contents = [FormulaConstant(character)] + return self + +class BracketProcessor(MathsProcessor): + "A processor for bracket commands." + + def process(self, contents, index): + "Convert the bracket using Unicode pieces, if possible." + if Options.simplemath: + return + if self.checkleft(contents, index): + return self.processleft(contents, index) + + def processleft(self, contents, index): + "Process a left bracket." + rightindex = self.findright(contents, index + 1) + if not rightindex: + return + size = self.findmax(contents, index, rightindex) + self.resize(contents[index], size) + self.resize(contents[rightindex], size) + + def checkleft(self, contents, index): + "Check if the command at the given index is left." + return self.checkdirection(contents[index], '\\left') + + def checkright(self, contents, index): + "Check if the command at the given index is right." + return self.checkdirection(contents[index], '\\right') + + def checkdirection(self, bit, command): + "Check if the given bit is the desired bracket command." + if not isinstance(bit, BracketCommand): + return False + return bit.command == command + + def findright(self, contents, index): + "Find the right bracket starting at the given index, or 0." + depth = 1 + while index < len(contents): + if self.checkleft(contents, index): + depth += 1 + if self.checkright(contents, index): + depth -= 1 + if depth == 0: + return index + index += 1 + return None + + def findmax(self, contents, leftindex, rightindex): + "Find the max size of the contents between the two given indices." + sliced = contents[leftindex:rightindex] + return max([element.size for element in sliced]) + + def resize(self, command, size): + "Resize a bracket command to the given size." + character = command.extracttext() + alignment = command.command.replace('\\', '') + bracket = BigBracket(size, character, alignment) + command.output = ContentsOutput() + command.contents = bracket.getcontents() + +class TodayCommand(EmptyCommand): + "Shows today's date." + + commandmap = None + + def parsebit(self, pos): + "Parse a command without parameters" + self.output = FixedOutput() + self.html = [datetime.date.today().strftime('%b %d, %Y')] + + +FormulaCommand.types += [ + DecoratingFunction, CombiningFunction, LimitCommand, BracketCommand, + ] + +FormulaProcessor.processors += [ + LimitsProcessor(), BracketProcessor(), + ] + + + +class ParameterDefinition(object): + "The definition of a parameter in a hybrid function." + "[] parameters are optional, {} parameters are mandatory." + "Each parameter has a one-character name, like {$1} or {$p}." + "A parameter that ends in ! like {$p!} is a literal." + "Example: [$1]{$p!} reads an optional parameter $1 and a literal mandatory parameter p." + + parambrackets = [('[', ']'), ('{', '}')] + + def __init__(self): + self.name = None + self.literal = False + self.optional = False + self.value = None + self.literalvalue = None + + def parse(self, pos): + "Parse a parameter definition: [$0], {$x}, {$1!}..." + for (opening, closing) in ParameterDefinition.parambrackets: + if pos.checkskip(opening): + if opening == '[': + self.optional = True + if not pos.checkskip('$'): + Trace.error('Wrong parameter name, did you mean $' + pos.current() + '?') + return None + self.name = pos.skipcurrent() + if pos.checkskip('!'): + self.literal = True + if not pos.checkskip(closing): + Trace.error('Wrong parameter closing ' + pos.skipcurrent()) + return None + return self + Trace.error('Wrong character in parameter template: ' + pos.skipcurrent()) + return None + + def read(self, pos, function): + "Read the parameter itself using the definition." + if self.literal: + if self.optional: + self.literalvalue = function.parsesquareliteral(pos) + else: + self.literalvalue = function.parseliteral(pos) + if self.literalvalue: + self.value = FormulaConstant(self.literalvalue) + elif self.optional: + self.value = function.parsesquare(pos) + else: + self.value = function.parseparameter(pos) + + def __unicode__(self): + "Return a printable representation." + result = 'param ' + self.name + if self.value: + result += ': ' + unicode(self.value) + else: + result += ' (empty)' + return result + +class ParameterFunction(CommandBit): + "A function with a variable number of parameters defined in a template." + "The parameters are defined as a parameter definition." + + def readparams(self, readtemplate, pos): + "Read the params according to the template." + self.params = dict() + for paramdef in self.paramdefs(readtemplate): + paramdef.read(pos, self) + self.params['$' + paramdef.name] = paramdef + + def paramdefs(self, readtemplate): + "Read each param definition in the template" + pos = TextPosition(readtemplate) + while not pos.finished(): + paramdef = ParameterDefinition().parse(pos) + if paramdef: + yield paramdef + + def getparam(self, name): + "Get a parameter as parsed." + if not name in self.params: + return None + return self.params[name] + + def getvalue(self, name): + "Get the value of a parameter." + return self.getparam(name).value + + def getliteralvalue(self, name): + "Get the literal value of a parameter." + param = self.getparam(name) + if not param or not param.literalvalue: + return None + return param.literalvalue + +class HybridFunction(ParameterFunction): + """ + A parameter function where the output is also defined using a template. + The template can use a number of functions; each function has an associated + tag. + Example: [f0{$1},span class="fbox"] defines a function f0 which corresponds + to a span of class fbox, yielding $1. + Literal parameters can be used in tags definitions: + [f0{$1},span style="color: $p;"] + yields $1, where $p is a literal parameter. + Sizes can be specified in hybridsizes, e.g. adding parameter sizes. By + default the resulting size is the max of all arguments. Sizes are used + to generate the right parameters. + A function followed by a single / is output as a self-closing XHTML tag: + [f0/,hr] + will generate
      . + """ + + commandmap = FormulaConfig.hybridfunctions + + def parsebit(self, pos): + "Parse a function with [] and {} parameters" + readtemplate = self.translated[0] + writetemplate = self.translated[1] + self.readparams(readtemplate, pos) + self.contents = self.writeparams(writetemplate) + self.computehybridsize() + + def writeparams(self, writetemplate): + "Write all params according to the template" + return self.writepos(TextPosition(writetemplate)) + + def writepos(self, pos): + "Write all params as read in the parse position." + result = [] + while not pos.finished(): + if pos.checkskip('$'): + param = self.writeparam(pos) + if param: + result.append(param) + elif pos.checkskip('f'): + function = self.writefunction(pos) + if function: + function.type = None + result.append(function) + elif pos.checkskip('('): + result.append(self.writebracket('left', '(')) + elif pos.checkskip(')'): + result.append(self.writebracket('right', ')')) + else: + result.append(FormulaConstant(pos.skipcurrent())) + return result + + def writeparam(self, pos): + "Write a single param of the form $0, $x..." + name = '$' + pos.skipcurrent() + if not name in self.params: + Trace.error('Unknown parameter ' + name) + return None + if not self.params[name]: + return None + if pos.checkskip('.'): + self.params[name].value.type = pos.globalpha() + return self.params[name].value + + def writefunction(self, pos): + "Write a single function f0,...,fn." + tag = self.readtag(pos) + if not tag: + return None + if pos.checkskip('/'): + # self-closing XHTML tag, such as
      + return TaggedBit().selfcomplete(tag) + if not pos.checkskip('{'): + Trace.error('Function should be defined in {}') + return None + pos.pushending('}') + contents = self.writepos(pos) + pos.popending() + if len(contents) == 0: + return None + return TaggedBit().complete(contents, tag) + + def readtag(self, pos): + "Get the tag corresponding to the given index. Does parameter substitution." + if not pos.current().isdigit(): + Trace.error('Function should be f0,...,f9: f' + pos.current()) + return None + index = int(pos.skipcurrent()) + if 2 + index > len(self.translated): + Trace.error('Function f' + unicode(index) + ' is not defined') + return None + tag = self.translated[2 + index] + if not '$' in tag: + return tag + for variable in self.params: + if variable in tag: + param = self.params[variable] + if not param.literal: + Trace.error('Parameters in tag ' + tag + ' should be literal: {' + variable + '!}') + continue + if param.literalvalue: + value = param.literalvalue + else: + value = '' + tag = tag.replace(variable, value) + return tag + + def writebracket(self, direction, character): + "Return a new bracket looking at the given direction." + return self.factory.create(BracketCommand).create(direction, character) + + def computehybridsize(self): + "Compute the size of the hybrid function." + if not self.command in HybridSize.configsizes: + self.computesize() + return + self.size = HybridSize().getsize(self) + # set the size in all elements at first level + for element in self.contents: + element.size = self.size + +class HybridSize(object): + "The size associated with a hybrid function." + + configsizes = FormulaConfig.hybridsizes + + def getsize(self, function): + "Read the size for a function and parse it." + sizestring = self.configsizes[function.command] + for name in function.params: + if name in sizestring: + size = function.params[name].value.computesize() + sizestring = sizestring.replace(name, unicode(size)) + if '$' in sizestring: + Trace.error('Unconverted variable in hybrid size: ' + sizestring) + return 1 + return eval(sizestring) + + +FormulaCommand.types += [HybridFunction] + + + +class MacroDefinition(CommandBit): + "A function that defines a new command (a macro)." + + macros = dict() + + def parsebit(self, pos): + "Parse the function that defines the macro." + self.output = EmptyOutput() + self.parameternumber = 0 + self.defaults = [] + self.factory.defining = True + self.parseparameters(pos) + self.factory.defining = False + Trace.debug('New command ' + self.newcommand + ' (' + \ + unicode(self.parameternumber) + ' parameters)') + self.macros[self.newcommand] = self + + def parseparameters(self, pos): + "Parse all optional parameters (number of parameters, default values)" + "and the mandatory definition." + self.newcommand = self.parsenewcommand(pos) + # parse number of parameters + literal = self.parsesquareliteral(pos) + if literal: + self.parameternumber = int(literal) + # parse all default values + bracket = self.parsesquare(pos) + while bracket: + self.defaults.append(bracket) + bracket = self.parsesquare(pos) + # parse mandatory definition + self.definition = self.parseparameter(pos) + + def parsenewcommand(self, pos): + "Parse the name of the new command." + self.factory.clearskipped(pos) + if self.factory.detecttype(Bracket, pos): + return self.parseliteral(pos) + if self.factory.detecttype(FormulaCommand, pos): + return self.factory.create(FormulaCommand).extractcommand(pos) + Trace.error('Unknown formula bit in defining function at ' + pos.identifier()) + return 'unknown' + + def instantiate(self): + "Return an instance of the macro." + return self.definition.clone() + +class MacroParameter(FormulaBit): + "A parameter from elyxer.a macro." + + def detect(self, pos): + "Find a macro parameter: #n." + return pos.checkfor('#') + + def parsebit(self, pos): + "Parse the parameter: #n." + if not pos.checkskip('#'): + Trace.error('Missing parameter start #.') + return + self.number = int(pos.skipcurrent()) + self.original = '#' + unicode(self.number) + self.contents = [TaggedBit().constant('#' + unicode(self.number), 'span class="unknown"')] + +class MacroFunction(CommandBit): + "A function that was defined using a macro." + + commandmap = MacroDefinition.macros + + def parsebit(self, pos): + "Parse a number of input parameters." + self.output = FilteredOutput() + self.values = [] + macro = self.translated + self.parseparameters(pos, macro) + self.completemacro(macro) + + def parseparameters(self, pos, macro): + "Parse as many parameters as are needed." + self.parseoptional(pos, list(macro.defaults)) + self.parsemandatory(pos, macro.parameternumber - len(macro.defaults)) + if len(self.values) < macro.parameternumber: + Trace.error('Missing parameters in macro ' + unicode(self)) + + def parseoptional(self, pos, defaults): + "Parse optional parameters." + optional = [] + while self.factory.detecttype(SquareBracket, pos): + optional.append(self.parsesquare(pos)) + if len(optional) > len(defaults): + break + for value in optional: + default = defaults.pop() + if len(value.contents) > 0: + self.values.append(value) + else: + self.values.append(default) + self.values += defaults + + def parsemandatory(self, pos, number): + "Parse a number of mandatory parameters." + for index in range(number): + parameter = self.parsemacroparameter(pos, number - index) + if not parameter: + return + self.values.append(parameter) + + def parsemacroparameter(self, pos, remaining): + "Parse a macro parameter. Could be a bracket or a single letter." + "If there are just two values remaining and there is a running number," + "parse as two separater numbers." + self.factory.clearskipped(pos) + if pos.finished(): + return None + if self.factory.detecttype(FormulaNumber, pos): + return self.parsenumbers(pos, remaining) + return self.parseparameter(pos) + + def parsenumbers(self, pos, remaining): + "Parse the remaining parameters as a running number." + "For example, 12 would be {1}{2}." + number = self.factory.parsetype(FormulaNumber, pos) + if not len(number.original) == remaining: + return number + for digit in number.original: + value = self.factory.create(FormulaNumber) + value.add(FormulaConstant(digit)) + value.type = number + self.values.append(value) + return None + + def completemacro(self, macro): + "Complete the macro with the parameters read." + self.contents = [macro.instantiate()] + replaced = [False] * len(self.values) + for parameter in self.searchall(MacroParameter): + index = parameter.number - 1 + if index >= len(self.values): + Trace.error('Macro parameter index out of bounds: ' + unicode(index)) + return + replaced[index] = True + parameter.contents = [self.values[index].clone()] + for index in range(len(self.values)): + if not replaced[index]: + self.addfilter(index, self.values[index]) + + def addfilter(self, index, value): + "Add a filter for the given parameter number and parameter value." + original = '#' + unicode(index + 1) + value = ''.join(self.values[0].gethtml()) + self.output.addfilter(original, value) + +class FormulaMacro(Formula): + "A math macro defined in an inset." + + def __init__(self): + self.parser = MacroParser() + self.output = EmptyOutput() + + def __unicode__(self): + "Return a printable representation." + return 'Math macro' + +FormulaFactory.types += [ MacroParameter ] + +FormulaCommand.types += [ + MacroFunction, + ] + + + + + + +class SideNote(Container): + "A side note that appears at the right." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput() + + def process(self): + "Enclose everything in a marginal span." + self.output.settag('span class="Marginal"', True) + +class FootnoteMarker(Container): + "A marker for a footnote." + + def __init__(self): + "Set the correct span class." + self.contents = [] + span = 'span class="SupFootMarker"' + if Options.alignfoot: + span = 'span class="AlignFootMarker"' + self.output = TaggedOutput().settag(span, False) + mode = 'A' + if Options.numberfoot: + mode = '1' + if Options.symbolfoot: + mode = '*' + NumberGenerator.generator.getcounter('Footnote').setmode(mode) + + def create(self): + "Create the marker for a footnote." + self.order = NumberGenerator.generator.generate('Footnote') + if Options.endfoot: + self.link = Link().complete(self.getmark(), 'footmarker-' + self.order) + self.createcontents() + return self + + def createanchor(self, marker): + "Create the anchor for a footnote. Adds a link for end footnotes." + self.order = marker.order + if Options.endfoot: + self.link = Link().complete(self.getmark(), 'footnote-' + self.order) + self.link.setmutualdestination(marker.link) + self.createcontents() + return self + + def createlabel(self, marker): + "Create the label for a footnote. Used in hoverfoot and marginfoot." + self.order = marker.order + self.contents = [Constant(self.getmark())] + space = Constant(u' ') + self.contents = [space] + self.contents + [space] + return self + + def createcontents(self): + "Create the contents of the marker." + if Options.endfoot: + self.contents = [self.link] + else: + self.contents = [Constant(self.getmark())] + space = Constant(u' ') + self.contents = [space] + self.contents + [space] + + def getmark(self): + "Get the mark to be displayed in the marker based on the order." + if Options.symbolfoot: + return self.order + else: + return '[' + self.order + ']' + +class Footnote(Container): + "A footnote to the main text." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="FootOuter"', False) + + def process(self): + "Add a counter for the footnote." + "Can be numeric or a letter depending on runtime options." + marker = FootnoteMarker().create() + anchor = FootnoteMarker().createanchor(marker) + label = FootnoteMarker().createlabel(marker) + notecontents = list(self.contents) + self.contents = [marker] + if Options.hoverfoot: + self.contents.append(self.createnote([label] + notecontents, 'span class="HoverFoot"')) + if Options.marginfoot: + self.contents.append(self.createnote([label] + notecontents, 'span class="MarginFoot"')) + if Options.endfoot: + EndFootnotes.footnotes.append(self.createnote([anchor] + notecontents, 'div class="EndFoot"')) + + def createnote(self, contents, tag): + "Create a note with the given contents and HTML tag." + return TaggedText().complete(contents, tag, False) + +class EndFootnotes(Container): + "The collection of footnotes at the document end." + + footnotes = [] + + def __init__(self): + "Generate all footnotes and a proper header for them all." + self.output = ContentsOutput() + header = TaggedText().constant(Translator.translate('footnotes'), 'h1 class="index"') + self.contents = [header] + self.footnotes + +class Note(Container): + "A LyX note of several types" + + def __init__(self): + self.parser = InsetParser() + self.output = EmptyOutput() + + def process(self): + "Hide note and comment, dim greyed out" + self.type = self.header[2] + if TagConfig.notes[self.type] == '': + return + self.output = TaggedOutput().settag(TagConfig.notes[self.type], True) + + + +class LyXHeader(Container): + "Reads the header, outputs the HTML header" + + def __init__(self): + self.contents = [] + self.parser = HeaderParser() + self.output = HeaderOutput() + self.parameters = dict() + self.partkey = PartKey().createheader('header') + + def process(self): + "Find pdf title" + DocumentParameters.pdftitle = self.getheaderparameter('pdftitle') + documentclass = self.getheaderparameter('documentclass') + if documentclass in HeaderConfig.styles['article']: + DocumentParameters.startinglevel = 1 + if documentclass in HeaderConfig.styles['book']: + DocumentParameters.bibliography = 'bibliography' + else: + DocumentParameters.bibliography = 'references' + if self.getheaderparameter('paragraphseparation') == 'indent': + DocumentParameters.indentstandard = True + DocumentParameters.tocdepth = self.getlevel('tocdepth') + DocumentParameters.maxdepth = self.getlevel('secnumdepth') + DocumentParameters.language = self.getheaderparameter('language') + if self.getheaderparameter('outputchanges') == 'true': + DocumentParameters.outputchanges = True + return self + + def getheaderparameter(self, configparam): + "Get a parameter configured in HeaderConfig." + key = HeaderConfig.parameters[configparam] + if not key in self.parameters: + return None + return self.parameters[key] + + def getlevel(self, configparam): + "Get a level read as a parameter from elyxer.HeaderConfig." + paramvalue = self.getheaderparameter(configparam) + if not paramvalue: + return 0 + value = int(paramvalue) + if DocumentParameters.startinglevel == 1: + return value + return value + 1 + +class LyXPreamble(Container): + "The preamble at the beginning of a LyX file. Parsed for macros." + + def __init__(self): + self.parser = PreambleParser() + self.output = EmptyOutput() + self.factory = FormulaFactory() + + def process(self): + "Parse the LyX preamble, if needed." + if len(PreambleParser.preamble) == 0: + return + pos = TextPosition('\n'.join(PreambleParser.preamble)) + while not pos.finished(): + if self.detectfunction(pos): + self.parsefunction(pos) + else: + pos.globincluding('\n') + PreambleParser.preamble = [] + + def detectfunction(self, pos): + "Detect a macro definition or a preamble function." + for function in FormulaConfig.misccommands: + if pos.checkfor(function): + return True + return False + + def parsefunction(self, pos): + "Parse a single command." + self.factory.parsetype(FormulaCommand, pos) + +class LyXFooter(Container): + "Reads the footer, outputs the HTML footer" + + def __init__(self): + self.contents = [] + self.parser = BoundedDummy() + self.output = FooterOutput() + self.partkey = PartKey().createheader('footer') + + def process(self): + "Include any footnotes at the end." + if EndFootnotes.footnotes: + endnotes = EndFootnotes() + self.contents = [endnotes] + + + +class Layout(Container): + "A layout (block of text) inside a lyx file" + + type = 'none' + + def __init__(self): + "Initialize the layout." + self.contents = [] + self.parser = BoundedParser() + self.output = TaggedOutput().setbreaklines(True) + + def process(self): + "Get the type and numerate if necessary." + self.type = self.header[1] + if self.type in TagConfig.layouts: + self.output.tag = TagConfig.layouts[self.type] + ' class="' + self.type + '"' + elif self.type.replace('*', '') in TagConfig.layouts: + self.output.tag = TagConfig.layouts[self.type.replace('*', '')] + self.output.tag += ' class="' + self.type.replace('*', '-') + '"' + else: + self.output.tag = 'div class="' + self.type + '"' + self.numerate() + + def numerate(self): + "Numerate if necessary." + partkey = PartKeyGenerator.forlayout(self) + if partkey: + self.partkey = partkey + self.output.tag = self.output.tag.replace('?', unicode(partkey.level)) + + def __unicode__(self): + "Return a printable representation." + if self.partkey: + return 'Layout ' + self.type + ' #' + unicode(self.partkey.partkey) + return 'Layout of type ' + self.type + +class StandardLayout(Layout): + "A standard layout -- can be a true div or nothing at all" + + indentation = False + + def process(self): + self.type = 'standard' + self.output = ContentsOutput() + + def complete(self, contents): + "Set the contents and return it." + self.process() + self.contents = contents + return self + +class Title(Layout): + "The title of the whole document" + + def process(self): + self.type = 'title' + self.output.tag = 'h1 class="title"' + title = self.extracttext() + DocumentTitle.title = title + Trace.message('Title: ' + title) + +class Author(Layout): + "The document author" + + def process(self): + self.type = 'author' + self.output.tag = 'h2 class="author"' + author = self.extracttext() + Trace.debug('Author: ' + author) + DocumentAuthor.appendauthor(author) + +class Abstract(Layout): + "A paper abstract" + + done = False + + def process(self): + self.type = 'abstract' + self.output.tag = 'div class="abstract"' + if Abstract.done: + return + message = Translator.translate('abstract') + tagged = TaggedText().constant(message, 'p class="abstract-message"', True) + self.contents.insert(0, tagged) + Abstract.done = True + +class FirstWorder(Layout): + "A layout where the first word is extracted" + + def extractfirstword(self): + "Extract the first word as a list" + return self.extractfromcontents(self.contents) + + def extractfromcontents(self, contents): + "Extract the first word in contents." + firstcontents = [] + while len(contents) > 0: + if self.isfirstword(contents[0]): + firstcontents.append(contents[0]) + del contents[0] + return firstcontents + if self.spaceincontainer(contents[0]): + extracted = self.extractfromcontainer(contents[0]) + firstcontents.append(extracted) + return firstcontents + firstcontents.append(contents[0]) + del contents[0] + return firstcontents + + def extractfromcontainer(self, container): + "Extract the first word from a container cloning it including its output." + if isinstance(container, StringContainer): + return self.extractfromstring(container) + result = Cloner.clone(container) + result.output = container.output + result.contents = self.extractfromcontents(container.contents) + return result + + def extractfromstring(self, container): + "Extract the first word from elyxer.a string container." + if not ' ' in container.string: + Trace.error('No space in string ' + container.string) + return container + split = container.string.split(' ', 1) + container.string = split[1] + return Constant(split[0]) + + def spaceincontainer(self, container): + "Find out if the container contains a space somewhere." + return ' ' in container.extracttext() + + def isfirstword(self, container): + "Find out if the container is valid as a first word." + if not isinstance(container, FirstWord): + return False + return not container.isempty() + +class FirstWord(Container): + "A container which is in itself a first word, unless it's empty." + "Should be inherited by other containers, e.g. ERT." + + def isempty(self): + "Find out if the first word is empty." + Trace.error('Unimplemented isempty()') + return True + +class Description(FirstWorder): + "A description layout" + + def process(self): + "Set the first word to bold" + self.type = 'Description' + self.output.tag = 'div class="Description"' + firstword = self.extractfirstword() + if not firstword: + return + tag = 'span class="Description-entry"' + self.contents.insert(0, TaggedText().complete(firstword, tag)) + self.contents.insert(1, Constant(u' ')) + +class List(FirstWorder): + "A list layout" + + def process(self): + "Set the first word to bold" + self.type = 'List' + self.output.tag = 'div class="List"' + firstword = self.extractfirstword() + if not firstword: + return + first = TaggedText().complete(firstword, 'span class="List-entry"') + second = TaggedText().complete(self.contents, 'span class="List-contents"') + self.contents = [first, second] + +class PlainLayout(Layout): + "A plain layout" + + def process(self): + "Output just as contents." + self.output = ContentsOutput() + self.type = 'Plain' + + def makevisible(self): + "Make the layout visible, output as tagged text." + self.output = TaggedOutput().settag('div class="PlainVisible"', True) + +class LyXCode(Layout): + "A bit of LyX-Code." + + def process(self): + "Output as pre." + self.output.tag = 'pre class="LyX-Code"' + for newline in self.searchall(Newline): + index = newline.parent.contents.index(newline) + newline.parent.contents[index] = Constant('\n') + +class PostLayout(object): + "Numerate an indexed layout" + + processedclass = Layout + + def postprocess(self, last, layout, next): + "Group layouts and/or number them." + if layout.type in TagConfig.group['layouts']: + return self.group(last, layout) + if layout.partkey: + self.number(layout) + return layout + + def group(self, last, layout): + "Group two layouts if they are the same type." + if not self.isgroupable(layout) or not self.isgroupable(last) or last.type != layout.type: + return layout + layout.contents = last.contents + [Constant('
      \n')] + layout.contents + last.contents = [] + last.output = EmptyOutput() + return layout + + def isgroupable(self, container): + "Check that the container can be grouped." + if not isinstance(container, Layout): + return False + for element in container.contents: + if not element.__class__.__name__ in LayoutConfig.groupable['allowed']: + return False + return True + + def number(self, layout): + "Generate a number and place it before the text" + layout.partkey.addtoclabel(layout) + +class PostStandard(object): + "Convert any standard spans in root to divs" + + processedclass = StandardLayout + + def postprocess(self, last, standard, next): + "Switch to div, and clear if empty." + type = 'Standard' + if self.isempty(standard): + standard.output = EmptyOutput() + return standard + if DocumentParameters.indentstandard: + if isinstance(last, StandardLayout): + type = 'Indented' + else: + type = 'Unindented' + standard.output = TaggedOutput().settag('div class="' + type + '"', True) + return standard + + def isempty(self, standard): + "Find out if the standard layout is empty." + for element in standard.contents: + if not element.output.isempty(): + return False + return True + +class PostPlainLayout(PostLayout): + "Numerate a plain layout" + + processedclass = PlainLayout + + def postprocess(self, last, plain, next): + "Group plain layouts." + if not self.istext(last) or not self.istext(plain): + return plain + plain.makevisible() + return self.group(last, plain) + + def istext(self, container): + "Find out if the container is only text." + if not isinstance(container, PlainLayout): + return False + extractor = ContainerExtractor(TOCConfig.extractplain) + text = extractor.extract(container) + return (len(text) > 0) + +class PostLyXCode(object): + "Coalesce contiguous LyX-Code layouts." + + processedclass = LyXCode + + def postprocess(self, last, lyxcode, next): + "Coalesce if last was also LyXCode" + if not isinstance(last, LyXCode): + return lyxcode + if hasattr(last, 'first'): + lyxcode.first = last.first + else: + lyxcode.first = last + toappend = lyxcode.first.contents + toappend.append(Constant('\n')) + toappend += lyxcode.contents + lyxcode.output = EmptyOutput() + return lyxcode + +Postprocessor.stages += [ + PostLayout, PostStandard, PostLyXCode, PostPlainLayout + ] + + + +class BiblioCitation(Container): + "A complete bibliography citation (possibly with many cites)." + + citations = dict() + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="bibcites"') + self.contents = [] + + def process(self): + "Process the complete citation and all cites within." + self.contents = [Constant('[')] + keys = self.getparameterlist('key') + for key in keys: + self.contents += [BiblioCite().create(key), Constant(', ')] + if len(keys) > 0: + # remove trailing , + self.contents.pop() + self.contents.append(Constant(']')) + +class BiblioCite(Link): + "Cite of a bibliography entry" + + cites = dict() + + def create(self, key): + "Create the cite to the given key." + self.key = key + number = NumberGenerator.generator.generate('bibliocite') + ref = BiblioReference().create(key, number) + self.complete(number, 'cite-' + number, type='bibliocite') + self.setmutualdestination(ref) + if not key in BiblioCite.cites: + BiblioCite.cites[key] = [] + BiblioCite.cites[key].append(self) + return self + +class Bibliography(Container): + "A bibliography layout containing an entry" + + def __init__(self): + self.parser = BoundedParser() + self.output = TaggedOutput().settag('p class="biblio"', True) + +class BiblioHeader(Container): + "The header of the bibliography." + + def __init__(self): + "Create the header for the bibliography section." + self.type = 'biblio' + self.output = ContentsOutput() + self.name = Translator.translate(DocumentParameters.bibliography) + self.contents = [TaggedText().constant(self.name, 'h1 class="biblio"', True)] + + def addtotoc(self, parent): + "Add the bibliography header to the TOC." + self.parent = parent + self.partkey = PartKeyGenerator.forindex(self) + if not self.partkey: + return + self.partkey.addtoclabel(self) + while parent: + parent.partkey = self.partkey + parent = parent.parent + +class PostBiblio(object): + "Insert a Bibliography legend before the first item" + + processedclass = Bibliography + + def postprocess(self, last, element, next): + "If we have the first bibliography insert a tag" + if isinstance(last, Bibliography) or Options.nobib: + return element + layout = StandardLayout() + header = BiblioHeader() + header.addtotoc(layout) + layout.complete([header, element]) + return layout + +Postprocessor.stages += [PostBiblio] + +class BiblioReference(Link): + "A reference to a bibliographical entry." + + references = dict() + + def create(self, key, number): + "Create the reference with the given key and number." + self.key = key + self.complete(number, 'biblio-' + number, type='biblioentry') + if not key in BiblioReference.references: + BiblioReference.references[key] = [] + BiblioReference.references[key].append(self) + return self + +class BiblioEntry(Container): + "A bibliography entry" + + entries = dict() + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="entry"') + self.contents = [] + + def process(self): + "Process the cites for the entry's key" + self.citeref = [Constant(NumberGenerator.generator.generate('biblioentry'))] + self.processcites(self.getparameter('key')) + + def processcites(self, key): + "Get all the cites of the entry" + self.key = key + if not key in BiblioReference.references: + self.contents.append(Constant('[-] ')) + return + self.contents = [Constant('[')] + for ref in BiblioReference.references[key]: + self.contents.append(ref) + self.contents.append(Constant(',')) + self.contents.pop(-1) + self.contents.append(Constant('] ')) + + + + + + + + + + +class Processor(object): + "Process a container and its contents." + + prestages = [] + skipfiltered = ['LyXHeader', 'LyXFooter', 'Title', 'Author', 'TableOfContents'] + + def __init__(self, filtering): + "Set filtering mode (to skip postprocessing)." + "With filtering on, the classes in skipfiltered are not processed at all." + self.filtering = filtering + self.postprocessor = Postprocessor() + + def process(self, container): + "Do the whole processing on a container." + if self.filtering and container.__class__.__name__ in self.skipfiltered: + return None + container = self.preprocess(container) + self.processcontainer(container) + if not container: + # do not postprocess empty containers from elyxer.here + return container + return self.postprocess(container) + + def preprocess(self, root): + "Preprocess a root container with all prestages." + if not root: + return None + for stage in self.prestages: + root = stage.preprocess(root) + if not root: + return None + return root + + def processcontainer(self, container): + "Process a container and its contents, recursively." + if not container: + return + for element in container.contents: + self.processcontainer(element) + container.process() + + def postprocess(self, container): + "Postprocess a container, unless filtering is on." + if self.filtering: + return container + return self.postprocessor.postprocess(container) + + + +class ListInset(Container): + "An inset with a list, normally made of links." + + def __init__(self): + self.parser = InsetParser() + self.output = ContentsOutput() + + def sortdictionary(self, dictionary): + "Sort all entries in the dictionary" + keys = dictionary.keys() + # sort by name + keys.sort() + return keys + + sortdictionary = classmethod(sortdictionary) + +class ListOf(ListInset): + "A list of entities (figures, tables, algorithms)" + + def process(self): + "Parse the header and get the type" + self.type = self.header[2] + text = Translator.translate('list-' + self.type) + self.contents = [TaggedText().constant(text, 'div class="tocheader"', True)] + +class TableOfContents(ListInset): + "Table of contents" + + def process(self): + "Parse the header and get the type" + self.create(Translator.translate('toc')) + + def create(self, heading): + "Create a table of contents with the given heading text." + self.output = TaggedOutput().settag('div class="fulltoc"', True) + self.contents = [TaggedText().constant(heading, 'div class="tocheader"', True)] + return self + + def add(self, entry): + "Add a new entry to the TOC." + if entry: + self.contents.append(entry) + +class IndexReference(Link): + "A reference to an entry in the alphabetical index." + + name = 'none' + + def process(self): + "Put entry in index" + name = self.getparameter('name') + if name: + self.name = name.strip() + else: + self.name = self.extracttext() + IndexEntry.get(self.name).addref(self) + + def __unicode__(self): + "Return a printable representation." + return 'Reference to ' + self.name + +class IndexHeader(Link): + "The header line for an index entry. Keeps all arrows." + + keyescapes = {'!':'', '|':'-', ' ':'-', '--':'-', ',':'', '\\':'', '@':'_', u'°':''} + + def create(self, names): + "Create the header for the given index entry." + self.output = TaggedOutput().settag('p class="printindex"', True) + self.name = names[-1] + keys = [self.escape(part, self.keyescapes) for part in names] + self.key = '-'.join(keys) + self.anchor = Link().complete('', 'index-' + self.key, None, 'printindex') + self.contents = [self.anchor, Constant(self.name + ': ')] + self.arrows = [] + return self + + def addref(self, reference): + "Create an arrow pointing to a reference." + reference.index = unicode(len(self.arrows)) + reference.destination = self.anchor + reference.complete(u'↓', 'entry-' + self.key + '-' + reference.index) + arrow = Link().complete(u'↑', type = 'IndexArrow') + arrow.destination = reference + if len(self.arrows) > 0: + self.contents.append(Constant(u', ')) + self.arrows.append(arrow) + self.contents.append(arrow) + + def __unicode__(self): + "Return a printable representation." + return 'Index header for ' + self.name + +class IndexGroup(Container): + "A group of entries in the alphabetical index, for an entry." + + root = None + + def create(self): + "Create an index group." + self.entries = dict() + self.output = EmptyOutput() + return self + + def findentry(self, names): + "Find the entry with the given names." + if self == IndexGroup.root: + self.output = ContentsOutput() + else: + self.output = TaggedOutput().settag('div class="indexgroup"', True) + lastname = names[-1] + if not lastname in self.entries: + self.entries[lastname] = IndexEntry().create(names) + return self.entries[lastname] + + def sort(self): + "Sort all entries in the group." + for key in ListInset.sortdictionary(self.entries): + entry = self.entries[key] + entry.group.sort() + self.contents.append(entry) + + def __unicode__(self): + "Return a printable representation." + return 'Index group' + +IndexGroup.root = IndexGroup().create() + +class IndexEntry(Container): + "An entry in the alphabetical index." + "When an index entry is of the form 'part1 ! part2 ...', " + "a hierarchical structure in the form of an IndexGroup is constructed." + "An index entry contains a mandatory header, and an optional group." + + def create(self, names): + "Create an index entry with the given name." + self.output = ContentsOutput() + self.header = IndexHeader().create(names) + self.group = IndexGroup().create() + self.contents = [self.header, self.group] + return self + + def addref(self, reference): + "Add a reference to the entry." + self.header.addref(reference) + + def get(cls, name): + "Get the index entry for the given name." + group = IndexGroup.root + parts = IndexEntry.splitname(name) + readparts = [] + for part in parts: + readparts.append(part) + entry = group.findentry(readparts) + group = entry.group + return entry + + def splitname(cls, name): + "Split a name in parts divided by !." + return [part.strip() for part in name.split('!')] + + def __unicode__(self): + "Return a printable representation." + return 'Index entry for ' + self.header.name + + get = classmethod(get) + splitname = classmethod(splitname) + +class PrintIndex(ListInset): + "Command to print an index" + + def process(self): + "Create the alphabetic index" + self.name = Translator.translate('index') + self.partkey = PartKeyGenerator.forindex(self) + if not self.partkey: + return + self.contents = [TaggedText().constant(self.name, 'h1 class="index"')] + self.partkey.addtoclabel(self) + IndexGroup.root.sort() + self.contents.append(IndexGroup.root) + +class NomenclatureEntry(Link): + "An entry of LyX nomenclature" + + entries = dict() + + def process(self): + "Put entry in index" + symbol = self.getparameter('symbol') + description = self.getparameter('description') + key = symbol.replace(' ', '-').lower() + if key in NomenclatureEntry.entries: + Trace.error('Duplicated nomenclature entry ' + key) + self.complete(u'↓', 'noment-' + key) + entry = Link().complete(u'↑', 'nom-' + key) + entry.symbol = symbol + entry.description = description + self.setmutualdestination(entry) + NomenclatureEntry.entries[key] = entry + +class PrintNomenclature(ListInset): + "Print all nomenclature entries" + + def process(self): + "Create the nomenclature." + self.name = Translator.translate('nomenclature') + self.partkey = PartKeyGenerator.forindex(self) + if not self.partkey: + return + self.contents = [TaggedText().constant(self.name, 'h1 class="nomenclature"')] + self.partkey.addtoclabel(self) + for key in self.sortdictionary(NomenclatureEntry.entries): + entry = NomenclatureEntry.entries[key] + contents = [entry, Constant(entry.symbol + u' ' + entry.description)] + text = TaggedText().complete(contents, 'div class="Nomenclated"', True) + self.contents.append(text) + +class PreListInset(object): + "Preprocess any container that contains a list inset." + + def preprocess(self, container): + "Preprocess a container, extract any list inset and return it." + listinsets = container.searchall(ListInset) + if len(listinsets) == 0: + return container + if len(container.contents) > 1: + return container + return listinsets[0] + +Processor.prestages += [PreListInset()] + + + + + + + + + +class TableParser(BoundedParser): + "Parse the whole table" + + headers = ContainerConfig.table['headers'] + + def __init__(self): + BoundedParser.__init__(self) + self.columns = list() + + def parseheader(self, reader): + "Parse table headers" + reader.nextline() + while self.startswithheader(reader): + self.parseparameter(reader) + return [] + + def startswithheader(self, reader): + "Check if the current line starts with a header line" + for start in TableParser.headers: + if reader.currentline().strip().startswith(start): + return True + return False + +class TablePartParser(BoundedParser): + "Parse a table part (row or cell)" + + def parseheader(self, reader): + "Parse the header" + tablekey, parameters = self.parsexml(reader) + self.parameters = parameters + return list() + +class ColumnParser(LoneCommand): + "Parse column properties" + + def parseheader(self, reader): + "Parse the column definition" + key, parameters = self.parsexml(reader) + self.parameters = parameters + return [] + + + +class Table(Container): + "A lyx table" + + def __init__(self): + self.parser = TableParser() + self.output = TaggedOutput().settag('table', True) + self.columns = [] + + def process(self): + "Set the columns on every row" + index = 0 + while index < len(self.contents): + element = self.contents[index] + if isinstance(element, Column): + self.columns.append(element) + del self.contents[index] + elif isinstance(element, BlackBox): + del self.contents[index] + elif isinstance(element, Row): + element.setcolumns(self.columns) + index += 1 + else: + Trace.error('Unknown element type ' + element.__class__.__name__ + + ' in table: ' + unicode(element.contents[0])) + index += 1 + +class Row(Container): + "A row in a table" + + def __init__(self): + self.parser = TablePartParser() + self.output = TaggedOutput().settag('tr', True) + self.columns = list() + + def setcolumns(self, columns): + "Process alignments for every column" + if len(columns) != len(self.contents): + Trace.error('Columns: ' + unicode(len(columns)) + ', cells: ' + unicode(len(self.contents))) + return + for index, cell in enumerate(self.contents): + columns[index].set(cell) + +class Column(Container): + "A column definition in a table" + + def __init__(self): + self.parser = ColumnParser() + self.output = EmptyOutput() + + def process(self): + "Read size parameters if present." + self.size = ContainerSize().readparameters(self) + + def set(self, cell): + "Set alignments in the corresponding cell" + alignment = self.getparameter('alignment') + if alignment == 'block': + alignment = 'justify' + cell.setattribute('align', alignment) + valignment = self.getparameter('valignment') + cell.setattribute('valign', valignment) + self.size.addstyle(cell) + +class Cell(Container): + "A cell in a table" + + def __init__(self): + self.parser = TablePartParser() + self.output = TaggedOutput().settag('td', True) + + def setmulticolumn(self, span): + "Set the cell as multicolumn" + self.setattribute('colspan', span) + + def setattribute(self, attribute, value): + "Set a cell attribute in the tag" + self.output.tag += ' ' + attribute + '="' + unicode(value) + '"' + +class PostTable(object): + "Postprocess a table" + + processedclass = Table + + def postprocess(self, last, table, next): + "Postprocess a table: long table, multicolumn rows" + self.longtable(table) + for row in table.contents: + index = 0 + while index < len(row.contents): + self.checkforplain(row, index) + self.checkmulticolumn(row, index) + index += 1 + return table + + def longtable(self, table): + "Postprocess a long table, removing unwanted rows" + features = table.getparameter('features') + if not features: + return + if not 'islongtable' in features: + return + if features['islongtable'] != 'true': + return + if self.hasrow(table, 'endfirsthead'): + self.removerows(table, 'endhead') + if self.hasrow(table, 'endlastfoot'): + self.removerows(table, 'endfoot') + + def hasrow(self, table, attrname): + "Find out if the table has a row of first heads" + for row in table.contents: + if row.getparameter(attrname): + return True + return False + + def removerows(self, table, attrname): + "Remove the head rows, since the table has first head rows." + for row in table.contents: + if row.getparameter(attrname): + row.output = EmptyOutput() + + def checkforplain(self, row, index): + "Make plain layouts visible if necessary." + cell = row.contents[index] + plainlayouts = cell.searchall(PlainLayout) + if len(plainlayouts) <= 1: + return + for plain in plainlayouts: + plain.makevisible() + + def checkmulticolumn(self, row, index): + "Process a multicolumn attribute" + cell = row.contents[index] + mc = cell.getparameter('multicolumn') + if not mc: + return + if mc != '1': + Trace.error('Unprocessed multicolumn=' + unicode(multicolumn) + + ' cell ' + unicode(cell)) + return + total = 1 + index += 1 + while self.checkbounds(row, index): + del row.contents[index] + total += 1 + cell.setmulticolumn(total) + + def checkbounds(self, row, index): + "Check if the index is within bounds for the row" + if index >= len(row.contents): + return False + mc = row.contents[index].getparameter('multicolumn') + if mc != '2': + return False + return True + +Postprocessor.stages.append(PostTable) + + + + +import struct +import sys +import os +import shutil + + + +import os +import os.path +import codecs + + +class Path(object): + "Represents a generic path" + + def exists(self): + "Check if the file exists" + return os.path.exists(self.path) + + def open(self): + "Open the file as readonly binary" + return codecs.open(self.path, 'rb') + + def getmtime(self): + "Return last modification time" + return os.path.getmtime(self.path) + + def hasexts(self, exts): + "Check if the file has one of the given extensions." + for ext in exts: + if self.hasext(ext): + return True + return False + + def hasext(self, ext): + "Check if the file has the given extension" + return self.getext() == ext + + def getext(self): + "Get the current extension of the file." + base, ext = os.path.splitext(self.path) + return ext + + def __unicode__(self): + "Return a unicode string representation" + return self.path + + def __eq__(self, path): + "Compare to another path" + if not hasattr(path, 'path'): + return False + return self.path == path.path + +class InputPath(Path): + "Represents an input file" + + def __init__(self, url): + "Create the input path based on url" + self.url = url + self.path = url + if not os.path.isabs(url): + self.path = os.path.join(Options.directory, url) + +class OutputPath(Path): + "Represents an output file" + + def __init__(self, inputpath): + "Create the output path based on an input path" + self.url = inputpath.url + if os.path.isabs(self.url): + self.url = os.path.basename(self.url) + self.path = os.path.join(Options.destdirectory, self.url) + + def changeext(self, ext): + "Change extension to the given one" + base, oldext = os.path.splitext(self.path) + self.path = base + ext + base, oldext = os.path.splitext(self.url) + self.url = base + ext + + def exists(self): + "Check if the file exists" + return os.path.exists(self.path) + + def createdirs(self): + "Create any intermediate directories that don't exist" + dir = os.path.dirname(self.path) + if len(dir) > 0 and not os.path.exists(dir): + os.makedirs(dir) + + def removebackdirs(self): + "Remove any occurrences of ../ (or ..\ on Windows)" + self.path = os.path.normpath(self.path) + backdir = '..' + os.path.sep + while self.path.startswith(backdir): + self.path = self.path[len(backdir):] + while self.url.startswith('../'): + self.url = self.url[len('../'):] + + + +class Image(Container): + "An embedded image" + + defaultformat = ImageConfig.formats['default'] + size = None + copy = None + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput() + self.type = 'embedded' + + def process(self): + "Place the url, convert the image if necessary." + self.origin = InputPath(self.getparameter('filename')) + self.destination = self.getdestination(self.origin) + self.size = ContainerSize().readparameters(self) + if self.origin.exists(): + ImageConverter.instance.convert(self) + else: + Trace.error('Image ' + unicode(self.origin) + ' not found') + self.setsize() + self.settag() + + def getdestination(self, origin): + "Convert origin path to destination path." + "Changes extension of destination to output image format." + destination = OutputPath(origin) + if Options.noconvert: + return destination + self.convertformat(destination) + destination.removebackdirs() + return destination + + def convertformat(self, destination): + "Convert the format of the destination image." + if Options.copyimages: + return + imageformat = '.jpg' + forcedest = Image.defaultformat + if Options.imageformat: + imageformat = Options.imageformat + forcedest = Options.imageformat + if not destination.hasext(imageformat): + destination.changeext(forcedest) + + def setsize(self): + "Set the size attributes width and height." + width, height = ImageFile(self.destination).getdimensions() + self.size.checkimage(width, height) + + def scalevalue(self, value): + "Scale the value according to the image scale and return it as unicode." + scaled = value * int(self.size.scale) / 100 + return unicode(int(scaled)) + 'px' + + def settag(self): + "Set the output tag for the image." + tag = 'img class="' + self.type + '"' + if self.origin.exists(): + url = self.destination.url + else: + url = self.origin.url + alt = Translator.translate('figure') + ' ' + url + tag += ' src="' + url + '" alt="' + alt + '"' + emptytag = True + if self.destination.hasext('.svg'): + self.contents = [Constant(alt)] + tag = 'object class="' + self.type + '" data="' + url + '"' + emptytag = False + self.output.settag(tag, True, empty=emptytag) + self.size.addstyle(self) + +class ImageConverter(object): + "A converter from elyxer.one image file to another." + + vectorformats = ImageConfig.formats['vector'] + cropboxformats = ImageConfig.cropboxformats + + active = True + instance = None + + def convert(self, image): + "Convert an image to PNG" + if not ImageConverter.active or Options.noconvert: + return + if image.origin.path == image.destination.path: + return + if image.destination.exists(): + if image.origin.getmtime() <= image.destination.getmtime(): + # file has not changed; do not convert + return + image.destination.createdirs() + if Options.copyimages: + Trace.debug('Copying ' + image.origin.path + ' to ' + image.destination.path) + shutil.copy2(image.origin.path, image.destination.path) + return + converter, command = self.buildcommand(image) + try: + Trace.debug(converter + ' command: "' + command + '"') + result = os.system(command.encode(sys.getfilesystemencoding())) + if result != 0: + Trace.error(converter + ' not installed; images will not be processed') + ImageConverter.active = False + return + Trace.message('Converted ' + unicode(image.origin) + ' to ' + + unicode(image.destination)) + except OSError, exception: + Trace.error('Error while converting image ' + unicode(image.origin) + + ': ' + unicode(exception)) + + def buildcommand(self, image): + "Build the command to convert the image." + if Options.converter in ImageConfig.converters: + command = ImageConfig.converters[Options.converter] + else: + command = Options.converter; + params = self.getparams(image) + for param in params: + command = command.replace('$' + param, unicode(params[param])) + # remove unwanted options + while '[' in command and ']' in command: + command = self.removeparam(command) + return Options.converter, command + + def removeparam(self, command): + "Remove an unwanted param." + if command.index('[') > command.index(']'): + Trace.error('Converter command should be [...$...]: ' + command) + exit() + before = command[:command.index('[')] + after = command[command.index(']') + 1:] + between = command[command.index('[') + 1:command.index(']')] + if '$' in between: + return before + after + return before + between + after + + def getparams(self, image): + "Get the parameters for ImageMagick conversion" + params = dict() + params['input'] = image.origin + params['output'] = image.destination + if image.origin.hasexts(self.vectorformats): + scale = 100 + if image.size.scale: + scale = image.size.scale + # descale + image.size.scale = None + params['scale'] = scale + if image.origin.getext() in self.cropboxformats: + params['format'] = self.cropboxformats[image.origin.getext()] + return params + +ImageConverter.instance = ImageConverter() + +class ImageFile(object): + "A file corresponding to an image (JPG or PNG)" + + dimensions = dict() + + def __init__(self, path): + "Create the file based on its path" + self.path = path + + def getdimensions(self): + "Get the dimensions of a JPG or PNG image" + if not self.path.exists(): + return None, None + if unicode(self.path) in ImageFile.dimensions: + return ImageFile.dimensions[unicode(self.path)] + dimensions = (None, None) + if self.path.hasext('.png'): + dimensions = self.getpngdimensions() + elif self.path.hasext('.jpg'): + dimensions = self.getjpgdimensions() + elif self.path.hasext('.svg'): + dimensions = self.getsvgdimensions() + ImageFile.dimensions[unicode(self.path)] = dimensions + return dimensions + + def getpngdimensions(self): + "Get the dimensions of a PNG image" + pngfile = self.path.open() + pngfile.seek(16) + width = self.readlong(pngfile) + height = self.readlong(pngfile) + pngfile.close() + return (width, height) + + def getjpgdimensions(self): + "Get the dimensions of a JPEG image" + jpgfile = self.path.open() + start = self.readword(jpgfile) + if start != int('ffd8', 16): + Trace.error(unicode(self.path) + ' not a JPEG file') + return (None, None) + self.skipheaders(jpgfile, ['ffc0', 'ffc2']) + self.seek(jpgfile, 3) + height = self.readword(jpgfile) + width = self.readword(jpgfile) + jpgfile.close() + return (width, height) + + def getsvgdimensions(self): + "Get the dimensions of a SVG image." + return (None, None) + + def skipheaders(self, file, hexvalues): + "Skip JPEG headers until one of the parameter headers is found" + headervalues = [int(value, 16) for value in hexvalues] + header = self.readword(file) + safetycounter = 0 + while header not in headervalues and safetycounter < 30: + length = self.readword(file) + if length == 0: + Trace.error('End of file ' + file.name) + return + self.seek(file, length - 2) + header = self.readword(file) + safetycounter += 1 + + def readlong(self, file): + "Read a long (32-bit) value from elyxer.file" + return self.readformat(file, '>L', 4) + + def readword(self, file): + "Read a 16-bit value from elyxer.file" + return self.readformat(file, '>H', 2) + + def readformat(self, file, format, bytes): + "Read any format from elyxer.file" + read = file.read(bytes) + if read == '' or len(read) < bytes: + Trace.error('EOF reached') + return 0 + tuple = struct.unpack(format, read) + return tuple[0] + + def seek(self, file, bytes): + "Seek forward, just by reading the given number of bytes" + file.read(bytes) + + + + + + +class ListItem(Container): + "An element in a list" + + type = 'none' + + def __init__(self): + "Create a list item." + self.parser = BoundedParser() + self.output = ContentsOutput() + + def process(self): + "Set the correct type and contents." + self.type = self.header[1] + tag = TaggedText().complete(self.contents, 'li', True) + self.contents = [tag] + + def __unicode__(self): + return self.type + ' item @ ' + unicode(self.begin) + +class DeeperList(Container): + "A nested list" + + def __init__(self): + "Create a nested list element." + self.parser = BoundedParser() + self.output = ContentsOutput() + self.contents = [] + + def process(self): + "Create the deeper list" + if len(self.contents) == 0: + Trace.error('Empty deeper list') + return + + def __unicode__(self): + result = 'deeper list @ ' + unicode(self.begin) + ': [' + for element in self.contents: + result += unicode(element) + ', ' + return result[:-2] + ']' + +class PendingList(object): + "A pending list" + + def __init__(self): + self.contents = [] + self.type = None + + def additem(self, item): + "Add a list item" + self.contents += item.contents + if not self.type: + self.type = item.type + + def adddeeper(self, deeper): + "Add a deeper list item" + if self.empty(): + self.insertfake() + self.contents[-1].contents += deeper.contents + + def generate(self): + "Get the resulting list" + if not self.type: + tag = 'ul' + else: + tag = TagConfig.listitems[self.type] + text = TaggedText().complete(self.contents, tag, True) + self.__init__() + return text + + def isduewithitem(self, item): + "Decide whether the pending list must be generated before the given item" + if not self.type: + return False + if self.type != item.type: + return True + return False + + def isduewithnext(self, next): + "Applies only if the list is finished with next item." + if not next: + return True + if not isinstance(next, ListItem) and not isinstance(next, DeeperList): + return True + return False + + def empty(self): + return len(self.contents) == 0 + + def insertfake(self): + "Insert a fake item" + item = TaggedText().constant('', 'li class="nested"', True) + self.contents = [item] + self.type = 'Itemize' + + def __unicode__(self): + result = 'pending ' + unicode(self.type) + ': [' + for element in self.contents: + result += unicode(element) + ', ' + if len(self.contents) > 0: + result = result[:-2] + return result + ']' + +class PostListItem(object): + "Postprocess a list item" + + processedclass = ListItem + + def postprocess(self, last, item, next): + "Add the item to pending and return an empty item" + if not hasattr(self.postprocessor, 'list'): + self.postprocessor.list = PendingList() + self.postprocessor.list.additem(item) + if self.postprocessor.list.isduewithnext(next): + return self.postprocessor.list.generate() + if isinstance(next, ListItem) and self.postprocessor.list.isduewithitem(next): + return self.postprocessor.list.generate() + return BlackBox() + +class PostDeeperList(object): + "Postprocess a deeper list" + + processedclass = DeeperList + + def postprocess(self, last, deeper, next): + "Append to the list in the postprocessor" + if not hasattr(self.postprocessor, 'list'): + self.postprocessor.list = PendingList() + self.postprocessor.list.adddeeper(deeper) + if self.postprocessor.list.isduewithnext(next): + return self.postprocessor.list.generate() + return BlackBox() + +Postprocessor.stages += [PostListItem, PostDeeperList] + + + + + + + + + +class Float(Container): + "A floating inset" + + type = 'none' + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('div class="float"', True) + + def process(self): + "Get the float type." + self.type = self.header[2] + self.processnumber() + self.processfloats() + self.processtags() + + def isparent(self): + "Find out whether the float is the parent float or is contained in another float." + current = self.parent + while current: + if isinstance(current, Float): + return False + current = current.parent + return True + + def processnumber(self): + "Number a float if it isn't numbered." + if not self.isparent(): + # do nothing; parent will take care of numbering + return + self.partkey = PartKey().createfloat(self) + + def processtags(self): + "Process the HTML tags." + tagged = self.embed() + self.applywideningtag(tagged) + + def embed(self): + "Embed the whole contents in a div." + embeddedtag = self.getembeddedtag() + tagged = TaggedText().complete(self.contents, embeddedtag, True) + self.contents = [tagged] + return tagged + + def processfloats(self): + "Process all floats contained inside." + floats = self.searchall(Float) + counter = NumberCounter('subfloat').setmode('a') + for subfloat in floats: + subfloat.output.tag = subfloat.output.tag.replace('div', 'span') + subfloat.partkey = PartKey().createsubfloat(counter.getnext()) + + def getembeddedtag(self): + "Get the tag for the embedded object." + floats = self.searchall(Float) + if len(floats) > 0: + return 'div class="multi' + self.type + '"' + return 'div class="' + self.type + '"' + + def applywideningtag(self, container): + "Apply the tag to set float width, if present." + images = self.searchall(Image) + if len(images) != 1: + return '' + image = images[0] + if not image.size: + return + width = image.size.removepercentwidth() + if not width: + return + image.type = 'figure' + ContainerSize().setmax(width).addstyle(container) + image.settag() + + def searchinside(self, type): + "Search for a given type in the contents" + return self.searchincontents(self.contents, type) + + def searchincontents(self, contents, type): + "Search in the given contents for the required type." + list = [] + for element in contents: + list += self.searchinelement(element, type) + return list + + def searchinelement(self, element, type): + "Search for a given type outside floats" + if isinstance(element, Float): + return [] + if isinstance(element, type): + return [element] + return self.searchincontents(element.contents, type) + + def __unicode__(self): + "Return a printable representation" + return 'Floating inset of type ' + self.type + +class Wrap(Float): + "A wrapped (floating) float" + + def processtags(self): + "Add the widening tag to the parent tag." + self.embed() + placement = self.getparameter('placement') + if not placement: + placement = 'o' + self.output.tag = 'div class="wrap-' + placement + '"' + self.applywideningtag(self) + +class Listing(Container): + "A code listing" + + processor = None + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('div class="listing"', True) + self.numbered = None + + def process(self): + "Remove all layouts" + self.counter = 0 + self.type = 'listing' + self.processparams() + if Listing.processor: + Listing.processor.preprocess(self) + for container in self.extractcontents(): + if container: + self.contents.append(container) + if 'caption' in self.lstparams: + text = self.lstparams['caption'][1:-1] + self.contents.insert(0, Caption().create(text)) + if Listing.processor: + Listing.processor.postprocess(self) + + def extractcontents(self): + "Extract all contents one container at a time." + oldcontents = self.contents + self.contents = [] + inpre = [] + for container in oldcontents: + if self.iscaption(container): + yield self.completepre(inpre) + inpre = [] + yield container + else: + inpre += self.extract(container) + yield self.completepre(inpre) + + def processparams(self): + "Process listing parameteres." + LstParser().parsecontainer(self) + if 'numbers' in self.lstparams: + self.numbered = self.lstparams['numbers'] + + def iscaption(self, container): + "Find out if the container has a caption (which should not be in
      )."
      +    return (len(container.searchall(Caption)) > 0)
      +
      +  def completepre(self, listinpre):
      +    "Complete the 
       tag with whatever has already been added."
      +    if len(listinpre) == 0:
      +      return None
      +    return TaggedText().complete(listinpre, 'pre class="listing"', False)
      +
      +  def extract(self, container):
      +    "Extract the container's contents and return them"
      +    if isinstance(container, StringContainer):
      +      return self.modifystring(container)
      +    if isinstance(container, StandardLayout):
      +      return self.modifylayout(container)
      +    if isinstance(container, PlainLayout):
      +      return self.modifylayout(container)
      +    Trace.error('Unexpected container ' + container.__class__.__name__ +
      +        ' in listing')
      +    container.tree()
      +    return []
      +
      +  def modifystring(self, string):
      +    "Modify a listing string"
      +    if string.string == '':
      +      string.string = u'​'
      +    return self.modifycontainer(string)
      +
      +  def modifylayout(self, layout):
      +    "Modify a standard layout"
      +    if len(layout.contents) == 0:
      +      layout.contents = [Constant(u'​')]
      +    return self.modifycontainer(layout)
      +
      +  def modifycontainer(self, container):
      +    "Modify a listing container"
      +    contents = [container, Constant('\n')]
      +    if self.numbered:
      +      self.counter += 1
      +      tag = 'span class="number-' + self.numbered + '"'
      +      contents.insert(0, TaggedText().constant(unicode(self.counter), tag))
      +    return contents
      +
      +class FloatNumber(Container):
      +  "Holds the number for a float in the caption."
      +
      +  def __init__(self):
      +    self.output = ContentsOutput()
      +
      +  def create(self, float):
      +    "Create the float number."
      +    self.contents = [Constant(float.partkey.partkey)]
      +    return self
      +
      +class PostFloat(object):
      +  "Postprocess a float: number it and move the label"
      +
      +  processedclass = Float
      +
      +  def postprocess(self, last, float, next):
      +    "Move the label to the top and number the caption"
      +    number = FloatNumber().create(float)
      +    for caption in float.searchinside(Caption):
      +      self.postlabels(float, caption)
      +      caption.contents = [number, Separator(u' ')] + caption.contents
      +    return float
      +
      +  def postlabels(self, float, caption):
      +    "Search for labels and move them to the top"
      +    labels = caption.searchremove(Label)
      +    if len(labels) == 0 and float.partkey.tocentry:
      +      labels = [Label().create(' ', float.partkey.partkey.replace(' ', '-'))]
      +    float.contents = labels + float.contents
      +
      +class PostWrap(PostFloat):
      +  "For a wrap: exactly like a float"
      +
      +  processedclass = Wrap
      +
      +Postprocessor.stages += [PostFloat, PostWrap]
      +
      +
      +
      +class IncludeInset(Container):
      +  "A child document included within another."
      +
      +  # the converter factory will be set in converter.py
      +  converterfactory = None
      +  filename = None
      +
      +  def __init__(self):
      +    self.parser = InsetParser()
      +    self.output = ContentsOutput()
      +
      +  def process(self):
      +    "Include the provided child document"
      +    self.filename = os.path.join(Options.directory, self.getparameter('filename'))
      +    Trace.debug('Child document: ' + self.filename)
      +    LstParser().parsecontainer(self)
      +    command = self.getparameter('LatexCommand')
      +    if command == 'verbatiminput':
      +      self.readverbatim()
      +      return
      +    elif command == 'lstinputlisting':
      +      self.readlisting()
      +      return
      +    self.processinclude()
      +
      +  def processinclude(self):
      +    "Process a regular include: standard child document."
      +    self.contents = []
      +    olddir = Options.directory
      +    newdir = os.path.dirname(self.getparameter('filename'))
      +    if newdir != '':
      +      Trace.debug('Child dir: ' + newdir)
      +      Options.directory = os.path.join(Options.directory, newdir)
      +    try:
      +      self.convertinclude()
      +    finally:
      +      Options.directory = olddir
      +
      +  def convertinclude(self):
      +    "Convert an included document."
      +    try:
      +      converter = IncludeInset.converterfactory.create(self)
      +    except:
      +      Trace.error('Could not read ' + self.filename + ', please check that the file exists and has read permissions.')
      +      return
      +    if self.hasemptyoutput():
      +      return
      +    converter.convert()
      +    self.contents = converter.getcontents()
      +
      +  def readverbatim(self):
      +    "Read a verbatim document."
      +    self.contents = [TaggedText().complete(self.readcontents(), 'pre', True)]
      +
      +  def readlisting(self):
      +    "Read a document as a listing."
      +    listing = Listing()
      +    listing.contents = self.readcontents()
      +    listing.parameters = self.parameters
      +    listing.process()
      +    self.contents = [listing]
      +
      +  def readcontents(self):
      +    "Read the contents of a complete file."
      +    contents = list()
      +    lines = BulkFile(self.filename).readall()
      +    for line in lines:
      +      contents.append(Constant(line))
      +    return contents
      +
      +  def __unicode__(self):
      +    "Return a printable description."
      +    if not self.filename:
      +      return 'Included unnamed file'
      +    return 'Included "' + self.filename + '"'
      +
      +
      +
      +
      +
      +
      +class ChangeInserted(Container):
      +  "A change which consists of an insertion."
      +
      +  def __init__(self):
      +    self.parser = TextParser(self)
      +    if DocumentParameters.outputchanges:
      +      self.output = TaggedOutput().settag('span class="inserted"')
      +    else:
      +      self.output = ContentsOutput()
      +
      +class ChangeDeleted(TaggedText):
      +  "A change which consists of a deletion."
      +
      +  def __init__(self):
      +    self.parser = TextParser(self)
      +    if DocumentParameters.outputchanges:
      +      self.output = TaggedOutput().settag('span class="deleted"')
      +    else:
      +      self.output = EmptyOutput()
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +class ERT(FirstWord):
      +  "Evil Red Text: embedded TeX code."
      +  "Considered as a first word for descriptions."
      +
      +  def __init__(self):
      +    self.parser = InsetParser()
      +    self.output = ContentsOutput()
      +
      +  def process(self):
      +    "Process all TeX code, formulas, commands."
      +    text = ''
      +    separator = ''
      +    for container in self.contents:
      +      text += separator + container.extracttext()
      +      separator = '\n'
      +    pos = TextPosition(text)
      +    pos.leavepending = True
      +    code = TeXCode()
      +    code.parse(pos)
      +    self.contents = [code]
      +
      +  def isempty(self):
      +    "Find out if the ERT is empty or not."
      +    if len(self.contents) == 0:
      +      return True
      +    if len(self.contents) > 1:
      +      Trace.error('Unknown ERT length 2')
      +      return False
      +    texcode = self.contents[0]
      +    return len(texcode.contents) == 0
      +
      +class TeXCode(Container):
      +  "A parser and processor for TeX code."
      +
      +  texseparators = ['{', '\\', '}', '$', '%']
      +  replaced = BibTeXConfig.replaced
      +  factory = FormulaFactory()
      +  endinglist = EndingList()
      +
      +  def __init__(self):
      +    self.contents = []
      +    self.output = ContentsOutput()
      +
      +  def parse(self, pos):
      +    "Parse some TeX code."
      +    self.parserecursive(pos)
      +    if pos.leavepending:
      +      self.endinglist.pickpending(pos)
      +
      +  def findlaststring(self):
      +    "Find the last string in the contents."
      +    if len(self.contents) == 0:
      +      return None
      +    string = self.contents[-1]
      +    if not isinstance(string, StringContainer):
      +      return None
      +    return string
      +
      +  def add(self, piece):
      +    "Add a new piece to the tag."
      +    if isinstance(piece, basestring):
      +      self.addtext(piece)
      +    else:
      +      self.contents.append(piece)
      +
      +  def addtext(self, piece):
      +    "Add a text string to the tag."
      +    last = self.findlaststring()
      +    if last:
      +      last.string += piece
      +      return
      +    self.contents.append(Constant(piece))
      +
      +  def parserecursive(self, pos):
      +    "Parse brackets or quotes recursively."
      +    while not pos.finished():
      +      self.parsetext(pos)
      +      if pos.finished():
      +        return
      +      elif pos.checkfor('{'):
      +        self.parseopenbracket(pos)
      +      elif pos.checkfor('}'):
      +        self.parseclosebracket(pos)
      +      elif pos.checkfor('\\'):
      +        self.parseescaped(pos)
      +      elif pos.checkfor('$'):
      +        self.parseformula(pos)
      +      elif pos.checkfor('%'):
      +        self.parsecomment(pos)
      +      else:
      +        pos.error('Unexpected character ' + pos.current())
      +        pos.skipcurrent()
      +
      +  def parsetext(self, pos):
      +    "Parse a bit of text, excluding separators and compressing spaces."
      +    text = self.parsecompressingspace(pos)
      +    if text == '':
      +      return
      +    for key in self.replaced:
      +      if key in text:
      +        text = text.replace(key, self.replaced[key])
      +    self.add(text)
      +
      +  def parsecompressingspace(self, pos):
      +    "Parse some text excluding value separators and compressing spaces."
      +    parsed = ''
      +    while not pos.finished():
      +      parsed += pos.glob(lambda: self.excludespaces(pos))
      +      if not pos.finished() and pos.current().isspace():
      +        parsed += ' '
      +        pos.skipspace()
      +      else:
      +        return parsed
      +    return parsed
      +
      +  def excludespaces(self, pos):
      +    "Exclude value separators and spaces."
      +    current = pos.current()
      +    if current in self.texseparators:
      +      return False
      +    if current.isspace():
      +      return False
      +    return True
      +
      +  def parseescaped(self, pos):
      +    "Parse an escaped string \\*."
      +    if pos.checkfor('\\(') or pos.checkfor('\\['):
      +      # start of formula commands
      +      self.parseformula(pos)
      +      return
      +    if not self.factory.detecttype(FormulaCommand, pos):
      +      pos.error('Not an escape sequence')
      +      return
      +    self.add(self.factory.parsetype(FormulaCommand, pos))
      +
      +  def parseopenbracket(self, pos):
      +    "Parse a { bracket."
      +    if not pos.checkskip('{'):
      +      pos.error('Missing opening { bracket')
      +      return
      +    pos.pushending('}')
      +    self.parserecursive(pos)
      +    pos.popending('}')
      +
      +  def parseclosebracket(self, pos):
      +    "Parse a } bracket."
      +    ending = self.endinglist.findending(pos)
      +    if not ending:
      +      Trace.error('Unexpected closing } bracket')
      +    else:
      +      self.endinglist.pop(pos)
      +    if not pos.checkskip('}'):
      +      pos.error('Missing closing } bracket')
      +      return
      +
      +  def parseformula(self, pos):
      +    "Parse a whole formula."
      +    formula = Formula().parse(pos)
      +    self.add(formula)
      +
      +  def parsecomment(self, pos):
      +    "Parse a TeX comment: % to the end of the line."
      +    pos.globexcluding('\n')
      +
      +  def __unicode__(self):
      +    "Return a printable representation."
      +    return 'TeX code: ' + self.extracttext()
      +
      +
      +
      +class BibTagParser(object):
      +  "A parser for BibTeX tags."
      +
      +  nameseparators = ['{', '=', '"', '#']
      +
      +  def __init__(self):
      +    self.key = None
      +    tags = BibStylesConfig.defaulttags
      +    self.tags = dict((x, BibTag().constant(tags[x])) for x in tags)
      +
      +  def parse(self, pos):
      +    "Parse the entry between {}."
      +    self.type = pos.globexcluding(self.nameseparators).strip()
      +    if not pos.checkskip('{'):
      +      pos.error('Entry should start with {')
      +      return
      +    pos.pushending('}')
      +    self.parsetags(pos)
      +    pos.popending('}')
      +    pos.skipspace()
      +
      +  def parsetags(self, pos):
      +    "Parse all tags in the entry."
      +    pos.skipspace()
      +    while not pos.finished():
      +      if pos.checkskip('{'):
      +        pos.error('Unmatched {')
      +        return
      +      pos.pushending(',', True)
      +      self.parsetag(pos)
      +      if pos.checkfor(','):
      +        pos.popending(',')
      +  
      +  def parsetag(self, pos):
      +    "Parse a single tag."
      +    (key, value) = self.getkeyvalue(pos)
      +    if not key:
      +      return
      +    if not value:
      +      self.key = key
      +      return
      +    name = key.lower()
      +    self.tags[name] = value
      +    if hasattr(self, 'dissect' + name):
      +      dissector = getattr(self, 'dissect' + name)
      +      dissector(value.extracttext())
      +    if not pos.finished():
      +      remainder = pos.globexcluding(',')
      +      pos.error('Ignored ' + remainder + ' before comma')
      +
      +  def getkeyvalue(self, pos):
      +    "Parse a string of the form key=value."
      +    piece = pos.globexcluding(self.nameseparators).strip()
      +    if pos.finished():
      +      return (piece, None)
      +    if not pos.checkskip('='):
      +      pos.error('Undesired character in tag name ' + piece)
      +      pos.skipcurrent()
      +      return (piece, None)
      +    key = piece.lower()
      +    pos.skipspace()
      +    value = self.parsevalue(pos)
      +    return (key, value)
      +
      +  def parsevalue(self, pos):
      +    "Parse the value for a tag."
      +    tag = BibTag()
      +    pos.skipspace()
      +    if pos.checkfor(','):
      +      pos.error('Unexpected ,')
      +      return tag.error()
      +    tag.parse(pos)
      +    return tag
      +
      +  def dissectauthor(self, authortag):
      +    "Dissect the author tag into pieces."
      +    authorsplit = authortag.split(' and ')
      +    if len(authorsplit) == 0:
      +      return
      +    authorlist = []
      +    for authorname in authorsplit:
      +      author = BibAuthor().parse(authorname)
      +      authorlist.append(author)
      +    initials = ''
      +    authors = ''
      +    if len(authorlist) == 1:
      +      initials = authorlist[0].surname[0:3]
      +      authors = unicode(authorlist[0])
      +    else:
      +      for author in authorlist:
      +        initials += author.surname[0:1]
      +        authors += unicode(author) + ', '
      +      authors = authors[:-2]
      +    self.tags['surname'] = BibTag().constant(authorlist[0].surname)
      +    self.tags['Sur'] = BibTag().constant(initials)
      +    self.tags['authors'] = BibTag().constant(authors)
      +
      +  def dissectyear(self, yeartag):
      +    "Dissect the year tag into pieces, looking for 4 digits in a row."
      +    pos = TextPosition(yeartag)
      +    while not pos.finished():
      +      if pos.current().isdigit():
      +        number = pos.globnumber()
      +        if len(number) == 4:
      +          self.tags['YY'] = BibTag().constant(number[2:])
      +          return
      +      else:
      +        pos.skipcurrent()
      +
      +  def dissectfile(self, filetag):
      +    "Extract the filename from elyxer.the file tag as ':filename:FORMAT'."
      +    if not filetag.startswith(':'):
      +      return
      +    bits = filetag.split(':')
      +    if len(bits) != 3:
      +      return
      +    self.tags['filename'] = BibTag().constant(bits[1])
      +    self.tags['format'] = BibTag().constant(bits[2])
      +
      +  def gettag(self, key):
      +    "Get the tag for a given key."
      +    if not key in self.tags:
      +      return None
      +    return self.tags[key]
      +
      +  def gettagtext(self, key):
      +    "Get the tag for a key as raw text."
      +    return self.gettag(key).extracttext()
      +
      +class BibTag(Container):
      +  "A tag in a BibTeX file."
      +
      +  valueseparators = ['{', '"', '#', '}']
      +  stringdefs = dict()
      +
      +  def __init__(self):
      +    self.contents = []
      +    self.output = ContentsOutput()
      +
      +  def constant(self, text):
      +    "Initialize for a single constant."
      +    self.contents = [Constant(text)]
      +    return self
      +
      +  def error(self):
      +    "To use when parsing resulted in an error."
      +    return self.constant('')
      +
      +  def parse(self, pos):
      +    "Parse brackets or quotes at the first level."
      +    while not pos.finished():
      +      self.parsetext(pos)
      +      if pos.finished():
      +        return
      +      elif pos.checkfor('{'):
      +        self.parsebracket(pos)
      +      elif pos.checkfor('"'):
      +        self.parsequoted(pos)
      +      elif pos.checkfor('#'):
      +        self.parsehash(pos)
      +      else:
      +        pos.error('Unexpected character ' + pos.current())
      +        pos.skipcurrent()
      +
      +  def parsetext(self, pos):
      +    "Parse a bit of text, try to substitute strings with string defs."
      +    text = pos.globexcluding(self.valueseparators)
      +    key = text.strip()
      +    if key == '':
      +      return
      +    if key in self.stringdefs:
      +      self.add(self.stringdefs[key])
      +      return
      +    self.add(Constant(key))
      +
      +  def add(self, piece):
      +    "Add a new piece to the tag."
      +    self.contents.append(piece)
      +
      +  def parsetex(self, pos):
      +    "Parse some TeX code."
      +    tex = TeXCode()
      +    tex.parse(pos)
      +    self.add(tex)
      +
      +  def parsebracket(self, pos):
      +    "Parse a {} bracket"
      +    if not pos.checkskip('{'):
      +      pos.error('Missing opening { in bracket')
      +      return
      +    pos.pushending('}')
      +    self.parsetex(pos)
      +    pos.popending('}')
      +
      +  def parsequoted(self, pos):
      +    "Parse a piece of quoted text"
      +    if not pos.checkskip('"'):
      +      pos.error('Missing opening " in quote')
      +      return
      +    pos.pushending('"')
      +    self.parsetex(pos)
      +    pos.popending('"')
      +    pos.skipspace()
      +
      +  def parsehash(self, pos):
      +    "Parse a hash mark #."
      +    if not pos.checkskip('#'):
      +      pos.error('Missing # in hash')
      +      return
      +
      +  def __unicode__(self):
      +    "Return a printable representation."
      +    return 'BibTag: ' + self.extracttext()
      +
      +class BibAuthor(object):
      +  "A BibTeX individual author."
      +
      +  def __init__(self):
      +    self.surname = ''
      +    self.firstnames = []
      +
      +  def parse(self, tag):
      +    "Parse an individual author tag."
      +    if ',' in tag:
      +      self.parsecomma(tag)
      +    else:
      +      self.parsewithoutcomma(tag)
      +    return self
      +
      +  def parsecomma(self, tag):
      +    "Parse an author with a comma: Python, M."
      +    bits = tag.split(',')
      +    if len(bits) > 2:
      +      Trace.error('Too many commas in ' + tag)
      +    self.surname = bits[0].strip()
      +    self.parsefirstnames(bits[1].strip())
      +
      +  def parsewithoutcomma(self, tag):
      +    "Parse an author without a comma: M. Python."
      +    bits = tag.rsplit(None, 1)
      +    if len(bits) == 0:
      +      Trace.error('Empty author')
      +      ppp()
      +      return
      +    self.surname = bits[-1].strip()
      +    if len(bits) == 1:
      +      return
      +    self.parsefirstnames(bits[0].strip())
      +
      +  def parsefirstnames(self, firstnames):
      +    "Parse the first name."
      +    for firstname in firstnames.split():
      +      self.firstnames.append(firstname)
      +
      +  def getinitial(self):
      +    "Get the main initial for the author."
      +    if len(self.surname) == 0:
      +      return ''
      +    return self.surname[0].toupper()
      +
      +  def __unicode__(self):
      +    "Return a printable representation."
      +    result = ''
      +    for firstname in self.firstnames:
      +      result += firstname + ' '
      +    return result + self.surname
      +
      +
      +
      +class BibTeX(Container):
      +  "Show a BibTeX bibliography and all referenced entries"
      +
      +  def __init__(self):
      +    self.parser = InsetParser()
      +    self.output = ContentsOutput()
      +
      +  def process(self):
      +    "Read all bibtex files and process them."
      +    self.entries = []
      +    self.contents = [self.createheader()]
      +    bibliography = Translator.translate('bibliography')
      +    files = self.getparameterlist('bibfiles')
      +    showall = False
      +    if self.getparameter('btprint') == 'btPrintAll':
      +      showall = True
      +    for file in files:
      +      bibfile = BibFile(file, showall)
      +      bibfile.parse()
      +      self.entries += bibfile.entries
      +      Trace.message('Parsed ' + unicode(bibfile))
      +    self.entries.sort(key = unicode)
      +    self.applystyle()
      +
      +  def createheader(self):
      +    "Create the header for the bibliography."
      +    header = BiblioHeader()
      +    if 'bibtotoc' in self.getparameterlist('options'):
      +      header.addtotoc(self)
      +    return header
      +
      +  def applystyle(self):
      +    "Read the style and apply it to all entries"
      +    style = self.readstyle()
      +    for entry in self.entries:
      +      entry.template = style['default']
      +      entry.citetemplate = style['cite']
      +      type = entry.type.lower()
      +      if type in style:
      +        entry.template = style[type]
      +      entry.process()
      +      self.contents.append(entry)
      +
      +  def readstyle(self):
      +    "Read the style from elyxer.the bibliography options"
      +    for option in self.getparameterlist('options'):
      +      if hasattr(BibStylesConfig, option):
      +        return getattr(BibStylesConfig, option)
      +    return BibStylesConfig.default
      +
      +class BibFile(object):
      +  "A BibTeX file"
      +
      +  def __init__(self, filename, showall):
      +    "Create the BibTeX file"
      +    self.filename = filename + '.bib'
      +    self.showall = showall
      +    self.added = 0
      +    self.ignored = 0
      +    self.entries = []
      +
      +  def parse(self):
      +    "Parse the BibTeX file and extract all entries."
      +    try:
      +      self.parsefile()
      +    except IOError:
      +      Trace.error('Error reading ' + self.filename + '; make sure the file exists and can be read.')
      +
      +  def parsefile(self):
      +    "Parse the whole file."
      +    bibpath = InputPath(self.filename)
      +    if Options.lowmem:
      +      pos = FilePosition(bibpath.path)
      +    else:
      +      bulkfile = BulkFile(bibpath.path)
      +      text = ''.join(bulkfile.readall())
      +      pos = TextPosition(text)
      +    while not pos.finished():
      +      pos.skipspace()
      +      if pos.checkskip(','):
      +        pos.skipspace()
      +      self.parseentry(pos)
      +
      +  def parseentry(self, pos):
      +    "Parse a single entry"
      +    for entry in BibEntry.instances:
      +      if entry.detect(pos):
      +        newentry = Cloner.clone(entry)
      +        newentry.parse(pos)
      +        if not newentry.isvisible():
      +          return
      +        if self.showall or newentry.isreferenced():
      +          self.entries.append(newentry)
      +          self.added += 1
      +        else:
      +          Trace.debug('Ignored entry ' + unicode(newentry))
      +          self.ignored += 1
      +        return
      +    # Skip the whole line since it's a comment outside an entry
      +    pos.globincluding('\n').strip()
      +
      +  def __unicode__(self):
      +    "String representation"
      +    string = self.filename + ': ' + unicode(self.added) + ' entries added, '
      +    string += unicode(self.ignored) + ' entries ignored'
      +    return string
      +
      +class BibEntry(Container):
      +  "An entry in a BibTeX file"
      +
      +  instances = []
      +
      +  def detect(self, pos):
      +    "Throw an error."
      +    Trace.error('Tried to detect() in ' + unicode(self))
      +
      +  def parse(self, pos):
      +    "Throw an error."
      +    Trace.error('Tried to parse() in ' + unicode(self))
      +
      +  def isvisible(self):
      +    "Return if the entry should be visible. Throws an error."
      +    Trace.error('Function isvisible() not implemented for ' + unicode(self))
      +
      +  def isreferenced(self):
      +    "Return if the entry is referenced. Throws an error."
      +    Trace.error('Function isreferenced() not implemented for ' + unicode(self))
      +
      +  def __unicode__(self):
      +    "Return a string representation"
      +    return 'BibTeX entry ' + self.__class__.__name__
      +
      +class CommentEntry(BibEntry):
      +  "A simple comment."
      +
      +  def detect(self, pos):
      +    "Detect the special entry"
      +    return pos.checkfor('%')
      +
      +  def parse(self, pos):
      +    "Parse all consecutive comment lines."
      +    while pos.checkfor('%'):
      +      pos.globincluding('\n')
      +
      +  def isvisible(self):
      +    "A comment entry is never visible."
      +    return False
      +
      +  def __unicode__(self):
      +    "Return a string representation"
      +    return 'Comment'
      +
      +class SpecialEntry(BibEntry):
      +  "A special entry"
      +
      +  types = ['@preamble', '@comment']
      +
      +  def __init__(self):
      +    self.contents = []
      +    self.output = EmptyOutput()
      +
      +  def detect(self, pos):
      +    "Detect the special entry"
      +    for type in self.types:
      +      if pos.checkforlower(type):
      +        return True
      +    return False
      +
      +  def parse(self, pos):
      +    "Parse and ignore."
      +    self.type = 'special'
      +    pos.globincluding('{')
      +    pos.pushending('}')
      +    while not pos.finished():
      +      if pos.checkfor('{'):
      +        self.parse(pos)
      +      else:
      +        pos.skipcurrent()
      +    pos.popending()
      +
      +  def isvisible(self):
      +    "A special entry is never visible."
      +    return False
      +
      +  def __unicode__(self):
      +    "Return a string representation"
      +    return self.type
      +
      +class StringEntry(SpecialEntry):
      +  "A string definition. The definition can later be used in other entries."
      +
      +  parser = BibTagParser()
      +  start = '@string'
      +  key = None
      +
      +  def detect(self, pos):
      +    "Detect the string definition."
      +    return pos.checkforlower(self.start)
      +
      +  def parse(self, pos):
      +    "Parse a single tag, which will define a string."
      +    self.type = self.start
      +    if not self.checkstart(pos):
      +      return
      +    pos.skipspace()
      +    if not pos.checkskip('{'):
      +      Trace.error('Missing opening { in ' + unicode(self))
      +      pos.globincluding('\n')
      +      return
      +    pos.pushending('}')
      +    (self.key, value) = self.parser.getkeyvalue(pos)
      +    BibTag.stringdefs[self.key] = value
      +    pos.popending('}')
      +
      +  def checkstart(self, pos):
      +    "Check that the entry starts with @string."
      +    if not pos.checkskip('@'):
      +      Trace.error('Missing @ from elyxer.string definition')
      +      return False
      +    name = '@' + pos.globalpha()
      +    if not name.lower() == self.start.lower():
      +      Trace.error('Invalid start @' + name +', missing ' + self.start + ' from elyxer.' + unicode(self))
      +      pos.globincluding('\n')
      +      return False
      +    return True
      +
      +  def __unicode__(self):
      +    "Return a printable representation."
      +    result = 'string definition'
      +    if self.key:
      +      result += ' for ' + self.key
      +    return result
      +
      +
      +BibEntry.instances += [CommentEntry(), SpecialEntry(), StringEntry()]
      +
      +
      +
      +
      +
      +
      +class PubEntry(BibEntry):
      +  "A publication entry"
      +
      +  def __init__(self):
      +    self.output = TaggedOutput().settag('p class="biblio"', True)
      +
      +  def detect(self, pos):
      +    "Detect a publication entry."
      +    return pos.checkfor('@')
      +
      +  def parse(self, pos):
      +    "Parse the publication entry."
      +    self.parser = BibTagParser()
      +    self.parser.parse(pos)
      +    self.type = self.parser.type
      +
      +  def isvisible(self):
      +    "A publication entry is always visible."
      +    return True
      +
      +  def isreferenced(self):
      +    "Check if the entry is referenced."
      +    if not self.parser.key:
      +      return False
      +    return self.parser.key in BiblioReference.references
      +
      +  def process(self):
      +    "Process the entry."
      +    self.index = NumberGenerator.generator.generate('pubentry')
      +    self.parser.tags['index'] = Constant(self.index)
      +    biblio = BiblioEntry()
      +    biblio.citeref = self.createref()
      +    biblio.processcites(self.parser.key)
      +    self.contents = [biblio, Constant(' ')]
      +    self.contents += self.entrycontents()
      +
      +  def entrycontents(self):
      +    "Get the contents of the entry."
      +    return self.translatetemplate(self.template)
      +
      +  def createref(self):
      +    "Create the reference to cite."
      +    return self.translatetemplate(self.citetemplate)
      +
      +  def translatetemplate(self, template):
      +    "Translate a complete template into a list of contents."
      +    pos = TextPosition(template)
      +    part = BibPart(self.parser.tags).parse(pos)
      +    for variable in part.searchall(BibVariable):
      +      if variable.empty():
      +        Trace.error('Error parsing BibTeX template for ' + unicode(self) + ': '
      +            + unicode(variable) + ' is empty')
      +    return [part]
      +
      +  def __unicode__(self):
      +    "Return a string representation"
      +    string = ''
      +    if 'author' in self.parser.tags:
      +      string += self.parser.gettagtext('author') + ': '
      +    if 'title' in self.parser.tags:
      +      string += '"' + self.parser.gettagtext('title') + '"'
      +    return string
      +
      +class BibPart(Container):
      +  "A part of a BibTeX template."
      +
      +  def __init__(self, tags):
      +    self.output = ContentsOutput()
      +    self.contents = []
      +    self.tags = tags
      +    self.quotes = 0
      +
      +  def parse(self, pos):
      +    "Parse a part of a template, return a list of contents."
      +    while not pos.finished():
      +      self.add(self.parsepiece(pos))
      +    return self
      +
      +  def parsepiece(self, pos):
      +    "Get the next piece of the template, return if it was empty."
      +    if pos.checkfor('{'):
      +      return self.parsebraces(pos)
      +    elif pos.checkfor('$'):
      +      return self.parsevariable(pos)
      +    result = ''
      +    while not pos.finished() and not pos.current() in '{$':
      +      if pos.current() == '"':
      +        self.quotes += 1
      +      result += pos.skipcurrent()
      +    return Constant(result)
      +
      +  def parsebraces(self, pos):
      +    "Parse a pair of curly braces {}."
      +    if not pos.checkskip('{'):
      +      Trace.error('Missing { in braces.')
      +      return None
      +    pos.pushending('}')
      +    part = BibPart(self.tags).parse(pos)
      +    pos.popending('}')
      +    empty = part.emptyvariables()
      +    if empty:
      +      return None
      +    return part
      +
      +  def parsevariable(self, pos):
      +    "Parse a variable $name."
      +    var = BibVariable(self.tags).parse(pos)
      +    if self.quotes % 2 == 1:
      +      # odd number of quotes; don't add spans in an attribute
      +      var.removetag()
      +    return var
      +
      +  def emptyvariables(self):
      +    "Find out if there are only empty variables in the part."
      +    for variable in self.searchall(BibVariable):
      +      if not variable.empty():
      +        return False
      +    return True
      +
      +  def add(self, piece):
      +    "Add a new piece to the current part."
      +    if not piece:
      +      return
      +    if self.redundantdot(piece):
      +      # remove extra dot
      +      piece.string = piece.string[1:]
      +    self.contents.append(piece)
      +    piece.parent = self
      +
      +  def redundantdot(self, piece):
      +    "Find out if there is a redundant dot in the next piece."
      +    if not isinstance(piece, Constant):
      +      return False
      +    if not piece.string.startswith('.'):
      +      return False
      +    if len(self.contents) == 0:
      +      return False
      +    if not isinstance(self.contents[-1], BibVariable):
      +      return False
      +    if not self.contents[-1].extracttext().endswith('.'):
      +      return False
      +    return True
      +
      +class BibVariable(Container):
      +  "A variable in a BibTeX template."
      +  
      +  def __init__(self, tags):
      +    self.output = TaggedOutput()
      +    self.contents = []
      +    self.tags = tags
      +
      +  def parse(self, pos):
      +    "Parse the variable name."
      +    if not pos.checkskip('$'):
      +      Trace.error('Missing $ in variable name.')
      +      return self
      +    self.key = pos.globalpha()
      +    self.output.tag = 'span class="bib-' + self.key + '"'
      +    self.processtags()
      +    return self
      +
      +  def processtags(self):
      +    "Find the tag with the appropriate key in the list of tags."
      +    if not self.key in self.tags:
      +      return
      +    result = self.tags[self.key]
      +    self.contents = [result]
      +
      +  def empty(self):
      +    "Find out if the variable is empty."
      +    if not self.contents:
      +      return True
      +    if self.extracttext() == '':
      +      return True
      +    return False
      +
      +  def removetag(self):
      +    "Remove the output tag and leave just the contents."
      +    self.output = ContentsOutput()
      +
      +  def __unicode__(self):
      +    "Return a printable representation."
      +    result = 'variable ' + self.key
      +    if not self.empty():
      +      result += ':' + self.extracttext()
      +    return result
      +
      +BibEntry.instances += [PubEntry()]
      +
      +
      +
      +
      +
      +
      +class NewfangledChunk(Layout):
      +  "A chunk of literate programming."
      +
      +  names = dict()
      +  firsttime = True
      +
      +  def process(self):
      +    "Process the literate chunk."
      +    self.output.tag = 'div class="chunk"'
      +    self.type = 'chunk'
      +    text = self.extracttext()
      +    parts = text.split(',')
      +    if len(parts) < 1:
      +      Trace.error('Not enough parameters in ' + text)
      +      return
      +    self.name = parts[0]
      +    self.number = self.order()
      +    self.createlinks()
      +    self.contents = [self.left, self.declaration(), self.right]
      +    ChunkProcessor.lastchunk = self
      +
      +  def order(self):
      +    "Create the order number for the chunk."
      +    return NumberGenerator.generator.generate('chunk')
      +
      +  def createlinks(self):
      +    "Create back and forward links."
      +    self.leftlink = Link().complete(self.number, 'chunk:' + self.number, type='chunk')
      +    self.left = TaggedText().complete([self.leftlink], 'span class="chunkleft"', False)
      +    self.right = TaggedText().constant('', 'span class="chunkright"', False)
      +    if not self.name in NewfangledChunk.names:
      +      NewfangledChunk.names[self.name] = []
      +    else:
      +      last = NewfangledChunk.names[self.name][-1]
      +      forwardlink = Link().complete(self.number + u'→', 'chunkback:' + last.number, type='chunk')
      +      backlink = Link().complete(u'←' + last.number + u' ', 'chunkforward:' + self.number, type='chunk')
      +      forwardlink.setmutualdestination(backlink)
      +      last.right.contents.append(forwardlink)
      +      self.right.contents.append(backlink)
      +    NewfangledChunk.names[self.name].append(self)
      +    self.origin = self.createorigin()
      +    if self.name in NewfangledChunkRef.references:
      +      for ref in NewfangledChunkRef.references[self.name]:
      +        self.linkorigin(ref.origin)
      +
      +  def createorigin(self):
      +    "Create a link that points to the chunks' origin."
      +    link = Link()
      +    self.linkorigin(link)
      +    return link
      +
      +  def linkorigin(self, link):
      +    "Create a link to the origin."
      +    start = NewfangledChunk.names[self.name][0]
      +    link.complete(start.number, type='chunk')
      +    link.destination = start.leftlink
      +    link.computedestination()
      +
      +  def declaration(self):
      +    "Get the chunk declaration."
      +    contents = []
      +    text = u'⟨' + self.name + '[' + unicode(len(NewfangledChunk.names[self.name])) + '] '
      +    contents.append(Constant(text))
      +    contents.append(self.origin)
      +    text = ''
      +    if NewfangledChunk.firsttime:
      +      Listing.processor = ChunkProcessor()
      +      NewfangledChunk.firsttime = False
      +    text += u'⟩'
      +    if len(NewfangledChunk.names[self.name]) > 1:
      +      text += '+'
      +    text += u'≡'
      +    contents.append(Constant(text))
      +    return TaggedText().complete(contents, 'span class="chunkdecl"', True)
      +
      +class ChunkProcessor(object):
      +  "A processor for listings that belong to chunks."
      +
      +  lastchunk = None
      +  counters = dict()
      +  endcommand = '}'
      +  chunkref = 'chunkref'
      +
      +  def preprocess(self, listing):
      +    "Preprocess a listing: set the starting counter."
      +    if not ChunkProcessor.lastchunk:
      +      return
      +    name = ChunkProcessor.lastchunk.name
      +    if not name in ChunkProcessor.counters:
      +      ChunkProcessor.counters[name] = 0
      +    listing.counter = ChunkProcessor.counters[name]
      +    for command, container, index in self.commandsinlisting(listing):
      +      chunkref = self.getchunkref(command)
      +      if chunkref:
      +        self.insertchunkref(chunkref, container, index)
      +
      +  def commandsinlisting(self, listing):
      +    "Find all newfangle commands in a listing."
      +    for container in listing.contents:
      +      for index in range(len(container.contents) - 2):
      +        if self.findinelement(container, index):
      +          third = container.contents[index + 2].string
      +          end = third.index(NewfangleConfig.constants['endmark'])
      +          command = third[:end]
      +          lenstart = len(NewfangleConfig.constants['startmark'])
      +          container.contents[index].string = container.contents[index].string[:-lenstart]
      +          del container.contents[index + 1]
      +          container.contents[index + 1].string = third[end + len(NewfangleConfig.constants['endmark']):]
      +          yield command, container, index
      +
      +  def findinelement(self, container, index):
      +    "Find a newfangle command in an element."
      +    for i in range(2):
      +      if not isinstance(container.contents[index + i], StringContainer):
      +        return False
      +    first = container.contents[index].string
      +    second = container.contents[index + 1].string
      +    third = container.contents[index + 2].string
      +    if not first.endswith(NewfangleConfig.constants['startmark']):
      +      return False
      +    if second != NewfangleConfig.constants['startcommand']:
      +      return False
      +    if not NewfangleConfig.constants['endmark'] in third:
      +      return False
      +    return True
      +
      +  def getchunkref(self, command):
      +    "Get the contents of a chunkref command, if present."
      +    if not command.startswith(NewfangleConfig.constants['chunkref']):
      +      return None
      +    if not NewfangleConfig.constants['endcommand'] in command:
      +      return None
      +    start = len(NewfangleConfig.constants['chunkref'])
      +    end = command.index(NewfangleConfig.constants['endcommand'])
      +    return command[start:end]
      +
      +  def insertchunkref(self, ref, container, index):
      +    "Insert a chunkref after the given index at the given container."
      +    chunkref = NewfangledChunkRef().complete(ref)
      +    container.contents.insert(index + 1, chunkref)
      +
      +  def postprocess(self, listing):
      +    "Postprocess a listing: store the ending counter for next chunk."
      +    if not ChunkProcessor.lastchunk:
      +      return
      +    ChunkProcessor.counters[ChunkProcessor.lastchunk.name] = listing.counter
      +
      +class NewfangledChunkRef(Inset):
      +  "A reference to a chunk."
      +
      +  references = dict()
      +
      +  def process(self):
      +    "Show the reference."
      +    self.output.tag = 'span class="chunkref"'
      +    self.ref = self.extracttext()
      +    self.addbits()
      +
      +  def complete(self, ref):
      +    "Complete the reference to the given string."
      +    self.output = ContentsOutput()
      +    self.ref = ref
      +    self.contents = [Constant(self.ref)]
      +    self.addbits()
      +    return self
      +
      +  def addbits(self):
      +    "Add the bits to the reference."
      +    if not self.ref in NewfangledChunkRef.references:
      +      NewfangledChunkRef.references[self.ref] = []
      +    NewfangledChunkRef.references[self.ref].append(self)
      +    if self.ref in NewfangledChunk.names:
      +      start = NewfangledChunk.names[self.ref][0]
      +      self.origin = start.createorigin()
      +    else:
      +      self.origin = Link()
      +    self.contents.insert(0, Constant(u'⟨'))
      +    self.contents.append(Constant(' '))
      +    self.contents.append(self.origin)
      +    self.contents.append(Constant(u'⟩'))
      +
      +  def __unicode__(self):
      +    "Return a printable representation."
      +    return 'Reference to chunk ' + self.ref
      +
      +
      +
      +
      +
      +
      +class SetCounterFunction(CommandBit):
      +  "A function which is used in the preamble to set a counter."
      +
      +  def parsebit(self, pos):
      +    "Parse a function with [] and {} parameters."
      +    counter = self.parseliteral(pos)
      +    value = self.parseliteral(pos)
      +    try:
      +      self.setcounter(counter, int(value))
      +    except:
      +      Trace.error('Counter ' + counter + ' cannot be set to ' + value)
      +
      +  def setcounter(self, counter, value):
      +    "Set a global counter."
      +    Trace.debug('Setting counter ' + unicode(counter) + ' to ' + unicode(value))
      +    NumberGenerator.generator.getcounter(counter).init(value)
      +
      +class FormulaTag(CommandBit):
      +  "A \\tag command."
      +
      +  def parsebit(self, pos):
      +    "Parse the tag and apply it."
      +    self.output = EmptyOutput()
      +    self.tag = self.parseliteral(pos)
      +
      +class MiscCommand(CommandBit):
      +  "A generic command which maps to a command class."
      +
      +  commandmap = FormulaConfig.misccommands
      +
      +  def parsebit(self, pos):
      +    "Find the right command to parse and parse it."
      +    commandtype = globals()[self.translated]
      +    return self.parsecommandtype(self.translated, commandtype, pos)
      +
      +FormulaCommand.types += [MiscCommand]
      +
      +
      +
      +class ContainerFactory(object):
      +  "Creates containers depending on the first line"
      +
      +  def __init__(self):
      +    "Read table that convert start lines to containers"
      +    types = dict()
      +    for start, typename in ContainerConfig.starts.iteritems():
      +      types[start] = globals()[typename]
      +    self.tree = ParseTree(types)
      +
      +  def createcontainer(self, reader):
      +    "Parse a single container."
      +    #Trace.debug('processing "' + reader.currentline().strip() + '"')
      +    if reader.currentline() == '':
      +      reader.nextline()
      +      return None
      +    container = Cloner.create(self.tree.find(reader))
      +    container.start = reader.currentline().strip()
      +    self.parse(container, reader)
      +    return container
      +
      +  def parse(self, container, reader):
      +    "Parse a container"
      +    parser = container.parser
      +    parser.parent = container
      +    parser.ending = self.getending(container)
      +    parser.factory = self
      +    container.header = parser.parseheader(reader)
      +    container.begin = parser.begin
      +    self.parsecontents(container, reader)
      +    container.parameters = parser.parameters
      +    container.parser = None
      +
      +  def parsecontents(self, container, reader):
      +    "Parse the contents of a container."
      +    contents = container.parser.parse(reader)
      +    if isinstance(contents, basestring):
      +      # read a string, set as parsed
      +      container.parsed = contents
      +      container.contents = []
      +    else:
      +      container.contents = contents
      +
      +  def getending(self, container):
      +    "Get the ending for a container"
      +    split = container.start.split()
      +    if len(split) == 0:
      +      return None
      +    start = split[0]
      +    if start in ContainerConfig.startendings:
      +      return ContainerConfig.startendings[start]
      +    classname = container.__class__.__name__
      +    if classname in ContainerConfig.endings:
      +      return ContainerConfig.endings[classname]
      +    if hasattr(container, 'ending'):
      +      Trace.error('Pending ending in ' + container.__class__.__name__)
      +      return container.ending
      +    return None
      +
      +class ParseTree(object):
      +  "A parsing tree"
      +
      +  default = '~~default~~'
      +
      +  def __init__(self, types):
      +    "Create the parse tree"
      +    self.root = dict()
      +    for start, type in types.iteritems():
      +      self.addstart(type, start)
      +
      +  def addstart(self, type, start):
      +    "Add a start piece to the tree"
      +    tree = self.root
      +    for piece in start.split():
      +      if not piece in tree:
      +        tree[piece] = dict()
      +      tree = tree[piece]
      +    if ParseTree.default in tree:
      +      Trace.error('Start ' + start + ' duplicated')
      +    tree[ParseTree.default] = type
      +
      +  def find(self, reader):
      +    "Find the current sentence in the tree"
      +    branches = self.matchline(reader.currentline())
      +    while not ParseTree.default in branches[-1]:
      +      branches.pop()
      +    last = branches[-1]
      +    return last[ParseTree.default]
      +
      +  def matchline(self, line):
      +    "Match a given line against the tree, as deep as possible."
      +    branches = [self.root]
      +    for piece in line.split(' '):
      +      current = branches[-1]
      +      piece = piece.rstrip('>')
      +      if piece in current:
      +        branches.append(current[piece])
      +      else:
      +        return branches
      +    return branches
      +
      +
      +
      +
      +
      +
      +
      +class TOCEntry(Container):
      +  "A container for a TOC entry."
      +
      +  def __init__(self):
      +    Container.__init__(self)
      +    self.branches = []
      +
      +  def create(self, container):
      +    "Create the TOC entry for a container, consisting of a single link."
      +    if container.partkey.header:
      +      return self.header(container)
      +    self.contents = [self.createlink(container)]
      +    self.output = TaggedOutput().settag('div class="toc"', True)
      +    self.partkey = container.partkey
      +    return self
      +
      +  def header(self, container):
      +    "Create a TOC entry for header and footer (0 depth)."
      +    self.partkey = container.partkey
      +    self.output = EmptyOutput()
      +    return self
      +
      +  def createlink(self, container):
      +    "Create the link that will make the whole TOC entry."
      +    labels = container.searchall(Label)
      +    link = Link()
      +    if self.isanchor(labels):
      +      link.url = '#' + container.partkey.partkey
      +      if Options.tocfor:
      +        link.url = Options.tocfor + link.url
      +    else:
      +      label = labels[0]
      +      link.destination = label
      +    if container.partkey.tocentry:
      +      link.complete(container.partkey.tocentry)
      +    if container.partkey.titlecontents:
      +      if Options.notoclabels:
      +        separator = u' '
      +      else:
      +        separator = u': '
      +      if container.partkey.tocentry:
      +        link.contents.append(Constant(separator))
      +      link.contents += container.partkey.titlecontents
      +    return link
      +
      +  def isanchor(self, labels):
      +    "Decide if the link is an anchor based on a set of labels."
      +    if len(labels) == 0:
      +      return True
      +    if not Options.tocfor:
      +      return False
      +    if Options.splitpart:
      +      return False
      +    return True
      +
      +  def __unicode__(self):
      +    "Return a printable representation."
      +    if not self.partkey.tocentry:
      +      return 'Unnamed TOC entry'
      +    return 'TOC entry: ' + self.partkey.tocentry
      +
      +class Indenter(object):
      +  "Manages and writes indentation for the TOC."
      +
      +  def __init__(self):
      +    self.depth = 0
      +
      +  def getindent(self, depth):
      +    indent = ''
      +    if depth > self.depth:
      +      indent = self.openindent(depth - self.depth)
      +    elif depth < self.depth:
      +      indent = self.closeindent(self.depth - depth)
      +    self.depth = depth
      +    return Constant(indent)
      +
      +  def openindent(self, times):
      +    "Open the indenting div a few times."
      +    indent = ''
      +    for i in range(times):
      +      indent += '
      \n' + return indent + + def closeindent(self, times): + "Close the indenting div a few times." + indent = '' + for i in range(times): + indent += '
      \n' + return indent + +class IndentedEntry(Container): + "An entry with an indentation." + + def __init__(self): + self.output = ContentsOutput() + + def create(self, indent, entry): + "Create the indented entry." + self.entry = entry + self.contents = [indent, entry] + return self + + def __unicode__(self): + "Return a printable documentation." + return 'Indented ' + unicode(self.entry) + +class TOCTree(object): + "A tree that contains the full TOC." + + def __init__(self): + self.tree = [] + self.branches = [] + + def store(self, entry): + "Place the entry in a tree of entries." + while len(self.tree) < entry.partkey.level: + self.tree.append(None) + if len(self.tree) > entry.partkey.level: + self.tree = self.tree[:entry.partkey.level] + stem = self.findstem() + if len(self.tree) == 0: + self.branches.append(entry) + self.tree.append(entry) + if stem: + entry.stem = stem + stem.branches.append(entry) + + def findstem(self): + "Find the stem where our next element will be inserted." + for element in reversed(self.tree): + if element: + return element + return None + +class TOCConverter(object): + "A converter from elyxer.containers to TOC entries." + + cache = dict() + tree = TOCTree() + + def __init__(self): + self.indenter = Indenter() + + def convertindented(self, container): + "Convert a container into an indented TOC entry." + entry = self.convert(container) + if not entry: + return None + return self.indent(entry) + + def indent(self, entry): + "Indent a TOC entry." + indent = self.indenter.getindent(entry.partkey.level) + return IndentedEntry().create(indent, entry) + + def convert(self, container): + "Convert a container to a TOC entry." + if not container.partkey: + return None + if container.partkey.partkey in self.cache: + return TOCConverter.cache[container.partkey.partkey] + if container.partkey.level > DocumentParameters.tocdepth: + return None + entry = TOCEntry().create(container) + TOCConverter.cache[container.partkey.partkey] = entry + TOCConverter.tree.store(entry) + return entry + + + + + + + +class Basket(object): + "A basket to place a set of containers. Can write them, store them..." + + def setwriter(self, writer): + self.writer = writer + return self + +class WriterBasket(Basket): + "A writer of containers. Just writes them out to a writer." + + def write(self, container): + "Write a container to the line writer." + self.writer.write(container.gethtml()) + + def finish(self): + "Mark as finished." + self.writer.close() + +class KeeperBasket(Basket): + "Keeps all containers stored." + + def __init__(self): + self.contents = [] + + def write(self, container): + "Keep the container." + self.contents.append(container) + + def finish(self): + "Finish the basket by flushing to disk." + self.flush() + + def flush(self): + "Flush the contents to the writer." + for container in self.contents: + self.writer.write(container.gethtml()) + self.writer.close() + +class TOCBasket(Basket): + "A basket to place the TOC of a document." + + def __init__(self): + self.converter = TOCConverter() + + def setwriter(self, writer): + Basket.setwriter(self, writer) + Options.nocopy = True + self.writer.write(LyXHeader().gethtml()) + return self + + def write(self, container): + "Write the table of contents for a container." + entry = self.converter.convertindented(container) + if entry: + self.writer.write(entry.gethtml()) + + def finish(self): + "Mark as finished." + self.writer.write(LyXFooter().gethtml()) + self.writer.close() + + + + + + +class IntegralProcessor(object): + "A processor for an integral document." + + def __init__(self): + "Create the processor for the integral contents." + self.storage = [] + + def locate(self, container): + "Locate only containers of the processed type." + return isinstance(container, self.processedtype) + + def store(self, container): + "Store a new container." + self.storage.append(container) + + def process(self): + "Process the whole storage." + for container in self.storage: + self.processeach(container) + +class IntegralTOC(IntegralProcessor): + "A processor for an integral TOC." + + processedtype = TableOfContents + tocentries = [] + + def processeach(self, toc): + "Fill in a Table of Contents." + converter = TOCConverter() + for container in PartKeyGenerator.partkeyed: + toc.add(converter.convertindented(container)) + # finish off with the footer to align indents + toc.add(converter.convertindented(LyXFooter())) + + def writetotoc(self, entries, toc): + "Write some entries to the TOC." + for entry in entries: + toc.contents.append(entry) + +class IntegralBiblioEntry(IntegralProcessor): + "A processor for an integral bibliography entry." + + processedtype = BiblioEntry + + def processeach(self, entry): + "Process each entry." + number = NumberGenerator.generator.generate('integralbib') + link = Link().complete('cite', 'biblio-' + number, type='biblioentry') + link.contents = entry.citeref + entry.contents = [Constant('['), link, Constant('] ')] + if entry.key in BiblioCite.cites: + for cite in BiblioCite.cites[entry.key]: + cite.contents = entry.citeref + cite.anchor = 'cite-' + number + cite.destination = link + +class IntegralFloat(IntegralProcessor): + "Store all floats in the document by type." + + processedtype = Float + bytype = dict() + + def processeach(self, float): + "Store each float by type." + if not float.type in IntegralFloat.bytype: + IntegralFloat.bytype[float.type] = [] + IntegralFloat.bytype[float.type].append(float) + +class IntegralListOf(IntegralProcessor): + "A processor for an integral list of floats." + + processedtype = ListOf + + def processeach(self, listof): + "Fill in a list of floats." + listof.output = TaggedOutput().settag('div class="fulltoc"', True) + if not listof.type in IntegralFloat.bytype: + Trace.message('No floats of type ' + listof.type) + return + for float in IntegralFloat.bytype[listof.type]: + entry = self.processfloat(float) + if entry: + listof.contents.append(entry) + + def processfloat(self, float): + "Get an entry for the list of floats." + if not float.isparent(): + return None + return TOCEntry().create(float) + +class IntegralReference(IntegralProcessor): + "A processor for a reference to a label." + + processedtype = Reference + + def processeach(self, reference): + "Extract the text of the original label." + reference.formatcontents() + +class MemoryBasket(KeeperBasket): + "A basket which stores everything in memory, processes it and writes it." + + def __init__(self): + "Create all processors in one go." + KeeperBasket.__init__(self) + self.processors = [ + IntegralTOC(), IntegralBiblioEntry(), + IntegralFloat(), IntegralListOf(), IntegralReference(), + ] + + def finish(self): + "Process everything which cannot be done in one pass and write to disk." + self.process() + self.flush() + + def process(self): + "Process everything with the integral processors." + self.searchintegral() + for processor in self.processors: + processor.process() + + def searchintegral(self): + "Search for all containers for all integral processors." + for container in self.contents: + # container.tree() + if self.integrallocate(container): + self.integralstore(container) + container.locateprocess(self.integrallocate, self.integralstore) + + def integrallocate(self, container): + "Locate all integrals." + for processor in self.processors: + if processor.locate(container): + return True + return False + + def integralstore(self, container): + "Store a container in one or more processors." + for processor in self.processors: + if processor.locate(container): + processor.store(container) + + + + + + + +class SplitPartLink(IntegralProcessor): + "A link processor for multi-page output." + + processedtype = Link + + def processeach(self, link): + "Process each link and add the current page." + link.page = self.page + +class NavigationLink(Container): + "A link in the navigation header." + + def __init__(self, name): + "Create the link for a given name (prev, next...)." + self.name = name + self.link = Link().complete(u' ', name, type=name) + self.output = TaggedOutput().settag('span class="' + name + '"') + self.contents = [self.link] + + def complete(self, container, after = False): + "Complete the navigation link with destination container." + "The 'after' parameter decides if the link goes after the part title." + if not container.partkey: + Trace.error('No part key for link name ' + unicode(container)) + return + self.link.contents = [Constant(Translator.translate(self.name))] + partname = self.getpartname(container) + separator = Constant(u' ') + if after: + self.contents = partname + [separator, self.link] + else: + self.contents = [self.link, separator] + partname + + def getpartname(self, container): + "Get the part name for a container, title optional." + partname = [Constant(container.partkey.tocentry)] + if not container.partkey.titlecontents: + return partname + if Options.notoclabels: + return container.partkey.titlecontents + return partname + [Constant(': ')] + container.partkey.titlecontents + + def setdestination(self, destination): + "Set the destination for this link." + self.link.destination = destination + + def setmutualdestination(self, destination): + "Set the destination for this link, and vice versa." + self.link.setmutualdestination(destination.link) + +class UpAnchor(Link): + "An anchor to the top of the page for the up links." + + def create(self, container): + "Create the up anchor based on the first container." + if not container.partkey: + Trace.error('No part key for ' + unicode(container)) + return None + self.createliteral(container.partkey.tocentry) + self.partkey.titlecontents = container.partkey.titlecontents + return self + + def createmain(self): + "Create the up anchor for the main page." + return self.createliteral(Translator.translate('main-page')) + + def createliteral(self, literal): + "Create the up anchor based on a literal string." + self.complete('', '') + self.output = EmptyOutput() + self.partkey = PartKey().createanchor(literal) + return self + +class SplitPartNavigation(object): + "Used to create the navigation links for a new split page." + + def __init__(self): + self.upanchors = [] + self.lastcontainer = None + self.nextlink = None + self.lastnavigation = None + + def writefirstheader(self, basket): + "Write the first header to the basket." + anchor = self.createmainanchor() + basket.write(anchor) + basket.write(self.createnavigation(anchor)) + + def writeheader(self, basket, container): + "Write the header to the basket." + basket.write(LyXHeader()) + basket.write(self.currentupanchor(container)) + basket.write(self.createnavigation(container)) + + def writefooter(self, basket): + "Write the footer to the basket." + if self.lastnavigation: + basket.write(self.lastnavigation) + basket.write(LyXFooter()) + + def createnavigation(self, container): + "Create the navigation bar with all links." + prevlink = NavigationLink('prev') + uplink = NavigationLink('up') + if self.nextlink: + prevlink.complete(self.lastcontainer) + self.nextlink.complete(container, after=True) + prevlink.setmutualdestination(self.nextlink) + uplink.complete(self.getupdestination(container)) + uplink.setdestination(self.getupdestination(container)) + self.nextlink = NavigationLink('next') + contents = [prevlink, Constant('\n'), uplink, Constant('\n'), self.nextlink] + header = TaggedText().complete(contents, 'div class="splitheader"', True) + self.lastcontainer = container + self.lastnavigation = header + return header + + def currentupanchor(self, container): + "Update the internal list of up anchors, and return the current one." + level = self.getlevel(container) + while len(self.upanchors) > level: + del self.upanchors[-1] + while len(self.upanchors) < level: + self.upanchors.append(self.upanchors[-1]) + upanchor = UpAnchor().create(container) + self.upanchors.append(upanchor) + return upanchor + + def createmainanchor(self): + "Create the up anchor to the main page." + mainanchor = UpAnchor().createmain() + self.upanchors.append(mainanchor) + return mainanchor + + def getupdestination(self, container): + "Get the name of the up page." + level = self.getlevel(container) + if len(self.upanchors) < level: + uppage = self.upanchors[-1] + else: + uppage = self.upanchors[level - 1] + return uppage + + def getlevel(self, container): + "Get the level of the container." + if not container.partkey: + return 1 + else: + return container.partkey.level + 1 + +class SplitFileBasket(MemoryBasket): + "A memory basket which contains a part split into a file, possibly with a TOC." + + def __init__(self): + MemoryBasket.__init__(self) + self.entrycount = 0 + self.root = None + self.converter = TOCConverter() + + def write(self, container): + "Keep track of numbered layouts." + MemoryBasket.write(self, container) + if not container.partkey: + return + if container.partkey.header: + return + entry = self.converter.convert(container) + if not entry: + return + self.entrycount += 1 + self.root = entry + + def addtoc(self): + "Add the table of contents if necessary." + if self.entrycount != 1: + return + if self.root.branches == []: + return + text = Translator.translate('toc-for') + self.root.partkey.tocentry + toc = TableOfContents().create(text) + self.addbranches(self.root, toc) + toc.add(self.converter.convertindented(LyXFooter())) + self.write(toc) + + def addbranches(self, entry, toc): + "Add an entry and all of its branches to the table of contents." + for branch in entry.branches: + toc.add(self.converter.indent(branch)) + self.addbranches(branch, toc) + +class SplitPartBasket(Basket): + "A basket used to split the output in different files." + + baskets = [] + + def setwriter(self, writer): + if not hasattr(writer, 'filename') or not writer.filename: + Trace.error('Cannot use standard output for split output; ' + + 'please supply an output filename.') + exit() + self.writer = writer + self.filename = writer.filename + self.converter = TOCConverter() + self.basket = MemoryBasket() + self.basket.page = writer.filename + return self + + def write(self, container): + "Write a container, possibly splitting the file." + self.basket.write(container) + + def splitbaskets(self): + "Process the whole basket and create all baskets for split part pages." + self.basket.process() + basket = self.firstbasket() + navigation = SplitPartNavigation() + for container in self.basket.contents: + if self.mustsplit(container): + filename = self.getfilename(container) + Trace.debug('New page ' + filename) + basket.addtoc() + navigation.writefooter(basket) + basket = self.addbasket(filename) + navigation.writeheader(basket, container) + basket.write(container) + if self.afterheader(container): + navigation.writefirstheader(basket) + self.mainanchor = navigation.upanchors[0] + for basket in self.baskets: + basket.process() + + def finish(self): + "Process the whole basket, split into page baskets and flush all of them." + self.splitbaskets() + for basket in self.baskets: + basket.flush() + + def afterheader(self, container): + "Find out if this is the header on the file." + return isinstance(container, LyXHeader) + + def firstbasket(self): + "Create the first basket." + return self.addbasket(self.filename, self.writer) + + def addbasket(self, filename, writer = None): + "Add a new basket." + if not writer: + writer = LineWriter(filename) + basket = SplitFileBasket() + basket.setwriter(writer) + self.baskets.append(basket) + # set the page name everywhere + basket.page = filename + splitpartlink = SplitPartLink() + splitpartlink.page = os.path.basename(basket.page) + basket.processors = [splitpartlink] + return basket + + def mustsplit(self, container): + "Find out if the oputput file has to be split at this entry." + if not container.partkey: + return False + if not container.partkey.filename: + return False + return True + + def getfilename(self, container): + "Get the new file name for a given container." + partname = container.partkey.filename + basename = self.filename + if Options.tocfor: + basename = Options.tocfor + base, extension = os.path.splitext(basename) + return base + '-' + partname + extension + +class SplitTOCBasket(SplitPartBasket): + "A basket which contains the TOC for a split part document." + + def finish(self): + "Process the whole basket, split into page baskets and flush all of them." + self.splitbaskets() + tocbasket = TOCBasket().setwriter(self.writer) + self.mainanchor.partkey = PartKey().createmain() + tocbasket.write(self.mainanchor) + for container in self.basket.contents: + tocbasket.write(container) + tocbasket.finish() + + + + + + +class PostFormula(object): + "Postprocess a formula" + + processedclass = Formula + + def postprocess(self, last, formula, next): + "Postprocess any formulae" + if Options.jsmath or Options.mathjax: + return formula + self.postnumbering(formula) + return formula + + def postnumbering(self, formula): + "Check if it's a numbered equation, insert number." + if formula.header[0] != 'numbered': + return + functions = formula.searchremove(LabelFunction) + if len(functions) == 0: + label = self.createlabel(formula) + elif len(functions) == 1: + label = self.createlabel(formula, functions[0]) + if len(functions) <= 1: + label.parent = formula + formula.contents.insert(0, label) + return + for function in functions: + label = self.createlabel(formula, function) + row = self.searchrow(function) + label.parent = row + row.contents.insert(0, label) + + def createlabel(self, formula, function = None): + "Create a new label for a formula." + "Add a label to a formula." + tag = self.createtag(formula) + partkey = PartKey().createformula(tag) + if not formula.partkey: + formula.partkey = partkey + if not function: + label = Label() + label.create(partkey.tocentry + ' ', 'eq-' + tag, type="eqnumber") + else: + label = function.label + label.complete(partkey.tocentry + ' ') + return label + + def createtag(self, formula): + "Create the label tag." + tags = formula.searchall(FormulaTag) + if len(tags) == 0: + return NumberGenerator.chaptered.generate('formula') + if len(tags) > 1: + Trace.error('More than one tag in formula: ' + unicode(formula)) + return tags[0].tag + + def searchrow(self, function): + "Search for the row that contains the label function." + if isinstance(function.parent, Formula) or isinstance(function.parent, FormulaRow): + return function.parent + return self.searchrow(function.parent) + +Postprocessor.stages.append(PostFormula) + + + +class eLyXerConverter(object): + "Converter for a document in a lyx file. Places all output in a given basket." + + def __init__(self): + self.filtering = False + + def setio(self, ioparser): + "Set the InOutParser" + self.reader = ioparser.getreader() + self.basket = self.getbasket() + self.basket.setwriter(ioparser.getwriter()) + return self + + def getbasket(self): + "Get the appropriate basket for the current options." + if Options.tocfor: + if Options.splitpart: + return SplitTOCBasket() + return TOCBasket() + if Options.splitpart: + return SplitPartBasket() + if Options.memory: + return MemoryBasket() + return WriterBasket() + + def embed(self, reader): + "Embed the results from elyxer.a reader into a memory basket." + "Header and footer are ignored. Useful for embedding one document inside another." + self.filtering = True + self.reader = reader + self.basket = MemoryBasket() + return self + + def convert(self): + "Perform the conversion for the document" + try: + self.processcontents() + except (Exception): + version = '[eLyXer version ' + GeneralConfig.version['number'] + version += ' (' + GeneralConfig.version['date'] + ') in ' + version += Options.location + '] ' + Trace.error(version) + Trace.error('Conversion failed at ' + self.reader.currentline()) + raise + + def processcontents(self): + "Parse the contents and write it by containers" + factory = ContainerFactory() + processor = Processor(self.filtering) + while not self.reader.finished(): + container = factory.createcontainer(self.reader) + result = processor.process(container) + self.writecontainer(result) + result = processor.postprocess(None) + self.writecontainer(result) + if not self.filtering: + self.basket.finish() + + def writecontainer(self, container): + "Write each container to the correct basket." + if not container: + return + includes = container.searchremove(IncludeInset) + self.basket.write(container) + # recursive processing for IncludeInset + for include in includes: + for element in include.contents: + self.basket.write(element) + + def getcontents(self): + "Return the contents of the basket." + return self.basket.contents + + def __unicode__(self): + "Printable representation." + string = 'Converter with filtering ' + unicode(self.filtering) + string += ' and basket ' + unicode(self.basket) + return string + +class InOutParser(object): + "Parse in and out arguments" + + def __init__(self): + self.filein = sys.stdin + self.fileout = sys.stdout + + def parse(self, args): + "Parse command line arguments" + self.filein = sys.stdin + self.fileout = sys.stdout + if len(args) < 2: + Trace.quietmode = True + if len(args) > 0: + self.filein = args[0] + del args[0] + self.readdir(self.filein, 'directory') + else: + Options.directory = '.' + if len(args) > 0: + self.fileout = args[0] + del args[0] + self.readdir(self.fileout, 'destdirectory') + else: + Options.destdirectory = '.' + if len(args) > 0: + raise Exception('Unused arguments: ' + unicode(args)) + return self + + def getreader(self): + "Get the resulting reader." + return LineReader(self.filein) + + def getwriter(self): + "Get the resulting writer." + return LineWriter(self.fileout) + + def readdir(self, filename, diroption): + "Read the current directory if needed" + if getattr(Options, diroption) != None: + return + setattr(Options, diroption, os.path.dirname(filename)) + if getattr(Options, diroption) == '': + setattr(Options, diroption, '.') + +class NullWriter(object): + "A writer that goes nowhere." + + def write(self, list): + "Do nothing." + pass + +class ConverterFactory(object): + "Create a converter fit for converting a filename and embedding the result." + + def create(self, container): + "Create a converter for a given container, with filename" + " and possibly other parameters." + fullname = os.path.join(Options.directory, container.filename) + reader = LineReader(container.filename) + if 'firstline' in container.lstparams: + reader.setstart(int(container.lstparams['firstline'])) + if 'lastline' in container.lstparams: + reader.setend(int(container.lstparams['lastline'])) + return eLyXerConverter().embed(reader) + +IncludeInset.converterfactory = ConverterFactory() + +def convertdoc(args): + "Read a whole document from the command line and write it." + Options().parseoptions(args) + ioparser = InOutParser().parse(args) + converter = eLyXerConverter().setio(ioparser) + converter.convert() + +def main(): + "Main function, called if invoked from the command line" + convertdoc(list(sys.argv)) + + + +if __name__ == '__main__': + main() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/gpl-3.0-standalone.html elyxer-1.2.5/forks/jras-elyxer/gpl-3.0-standalone.html --- elyxer-1.2.3/forks/jras-elyxer/gpl-3.0-standalone.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/gpl-3.0-standalone.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,692 @@ + + + + + + GNU General Public License - GNU Project - Free Software Foundation (FSF) + +

      GNU GENERAL PUBLIC LICENSE

      +

      Version 3, 29 June 2007

      + +

      Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>

      + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed.

      + +

      Preamble

      + +

      The GNU General Public License is a free, copyleft license for +software and other kinds of works.

      + +

      The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too.

      + +

      When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things.

      + +

      To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others.

      + +

      For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights.

      + +

      Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it.

      + +

      For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions.

      + +

      Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users.

      + +

      Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free.

      + +

      The precise terms and conditions for copying, distribution and +modification follow.

      + +

      TERMS AND CONDITIONS

      + +

      0. Definitions.

      + +

      “This License” refers to version 3 of the GNU General Public License.

      + +

      “Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks.

      + +

      “The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations.

      + +

      To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work.

      + +

      A “covered work” means either the unmodified Program or a work based +on the Program.

      + +

      To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well.

      + +

      To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying.

      + +

      An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion.

      + +

      1. Source Code.

      + +

      The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work.

      + +

      A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language.

      + +

      The “System Libraries” of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it.

      + +

      The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work.

      + +

      The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source.

      + +

      The Corresponding Source for a work in source code form is that +same work.

      + +

      2. Basic Permissions.

      + +

      All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law.

      + +

      You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you.

      + +

      Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary.

      + +

      3. Protecting Users' Legal Rights From Anti-Circumvention Law.

      + +

      No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures.

      + +

      When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures.

      + +

      4. Conveying Verbatim Copies.

      + +

      You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program.

      + +

      You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee.

      + +

      5. Conveying Modified Source Versions.

      + +

      You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions:

      + +
        +
      • a) The work must carry prominent notices stating that you modified + it, and giving a relevant date.
      • + +
      • b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + “keep intact all notices”.
      • + +
      • c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it.
      • + +
      • d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so.
      • +
      + +

      A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate.

      + +

      6. Conveying Non-Source Forms.

      + +

      You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways:

      + +
        +
      • a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange.
      • + +
      • b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge.
      • + +
      • c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b.
      • + +
      • d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements.
      • + +
      • e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d.
      • +
      + +

      A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work.

      + +

      A “User Product” is either (1) a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product.

      + +

      “Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made.

      + +

      If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM).

      + +

      The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network.

      + +

      Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying.

      + +

      7. Additional Terms.

      + +

      “Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions.

      + +

      When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission.

      + +

      Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms:

      + +
        +
      • a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or
      • + +
      • b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or
      • + +
      • c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or
      • + +
      • d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or
      • + +
      • e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or
      • + +
      • f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors.
      • +
      + +

      All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying.

      + +

      If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms.

      + +

      Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way.

      + +

      8. Termination.

      + +

      You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11).

      + +

      However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation.

      + +

      Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice.

      + +

      Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10.

      + +

      9. Acceptance Not Required for Having Copies.

      + +

      You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so.

      + +

      10. Automatic Licensing of Downstream Recipients.

      + +

      Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License.

      + +

      An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts.

      + +

      You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it.

      + +

      11. Patents.

      + +

      A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”.

      + +

      A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License.

      + +

      Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version.

      + +

      In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party.

      + +

      If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid.

      + +

      If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it.

      + +

      A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007.

      + +

      Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law.

      + +

      12. No Surrender of Others' Freedom.

      + +

      If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program.

      + +

      13. Use with the GNU Affero General Public License.

      + +

      Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such.

      + +

      14. Revised Versions of this License.

      + +

      The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns.

      + +

      Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation.

      + +

      If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program.

      + +

      Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version.

      + +

      15. Disclaimer of Warranty.

      + +

      THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

      + +

      16. Limitation of Liability.

      + +

      IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES.

      + +

      17. Interpretation of Sections 15 and 16.

      + +

      If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee.

      + +

      END OF TERMS AND CONDITIONS

      + +

      How to Apply These Terms to Your New Programs

      + +

      If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms.

      + +

      To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found.

      + +
          <one line to give the program's name and a brief idea of what it does.>
      +    Copyright (C) <year>  <name of author>
      +
      +    This program is free software: you can redistribute it and/or modify
      +    it under the terms of the GNU General Public License as published by
      +    the Free Software Foundation, either version 3 of the License, or
      +    (at your option) any later version.
      +
      +    This program is distributed in the hope that it will be useful,
      +    but WITHOUT ANY WARRANTY; without even the implied warranty of
      +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      +    GNU General Public License for more details.
      +
      +    You should have received a copy of the GNU General Public License
      +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      +
      + +

      Also add information on how to contact you by electronic and paper mail.

      + +

      If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode:

      + +
          <program>  Copyright (C) <year>  <name of author>
      +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
      +    This is free software, and you are welcome to redistribute it
      +    under certain conditions; type `show c' for details.
      +
      + +

      The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an “about box”.

      + +

      You should also get your employer (if you work as a programmer) or school, +if any, to sign a “copyright disclaimer” for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>.

      + +

      The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>.

      + + + \ No newline at end of file diff -Nru elyxer-1.2.3/forks/jras-elyxer/install.py elyxer-1.2.5/forks/jras-elyxer/install.py --- elyxer-1.2.3/forks/jras-elyxer/install.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/install.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,144 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100411 +# eLyXer multi-platform installation + +import platform +import sys +import os +import shutil +import gettext + + +class Installer(object): + "The eLyXer installer." + + elyxer = 'elyxer.py' + separators = {'Linux':':', 'Windows':';', 'Darwin':':'} + preferredstarts = ['/usr/bin', 'c:\\windows\\system', '/usr/local/bin'] + + def error(self, string): + "Print an error string." + self.show(string, sys.stderr) + + def show(self, message, channel = sys.stdout): + "Show a message out of a channel" + channel.write(message + '\n') + + def usage(self): + "Show usage and requirements." + self.error('Usage: python install.py') + self.error('Requirements: Python version 2.3 and above, Python 3 not supported.') + exit() + + def copybin(self): + "Check permissions, try to copy binary file to any system path." + for path in self.sortpaths(): + try: + shutil.copy2(Installer.elyxer, path) + self.show('eLyXer installed as a binary in ' + path) + self.show('Please run as "elyxer.py [options] input.lyx output.html" to use it') + return + except IOError: + pass + self.error('eLyXer not installed') + + def sortpaths(self): + "Sort the environment variable PATH, place those containing 'python' first." + "Remove a dot directory." + system = platform.system() + if not system in Installer.separators: + self.error('Unknown operating system ' + system + '; aborting') + self.usage() + separator = Installer.separators[system] + paths = os.environ['PATH'].split(separator) + withpython = [] + preferred = [] + rest = [] + while len(paths) > 0: + path = paths.pop() + if 'python' in path.lower(): + withpython.append(path) + elif self.ispreferred(path): + preferred.append(path) + elif path != '.': + rest.append(path + '/') + return withpython + preferred + rest + + def ispreferred(self, path): + "Find out if the path starts with one of the preferred paths." + for preferredstart in Installer.preferredstarts: + if path.lower().startswith(preferredstart): + return True + return False + + def installmodule(self): + "Install eLyXer as a module." + return + if not self.checkpermissions('install as a Python module'): + return + sys.argv.append('install') + import setup + self.show('eLyXer installed as a module.') + self.show('You can also run eLyXer as "python -m elyxer [options] input.lyx output.html"') + + def installtranslations(self): + "Install the translation files." + destination = gettext.bindtextdomain('elyxer') + self.copy('po/locale', destination) + + def copy(self, source, destination): + "Recursively copy a file or directory into another." + if not self.checkpermissions('install translation modules'): + return + if os.path.isfile(source): + shutil.copy2(source, destination) + return + if not os.path.exists(destination): + shutil.copytree(source, destination) + return + for filename in os.listdir(source): + self.copy(os.path.join(source, filename), os.path.join(destination, filename)) + + def checkpermissions(self, purpose): + "Check if the user has permissions as root to do something." + if platform.system() == 'Linux': + if os.getuid() != 0: + self.error('Need to be root to ' + purpose) + return False + return True + + def checkversion(self): + "Check the current version." + version = platform.python_version_tuple() + if int(version[0]) != 2: + self.error('Invalid Python version ' + version[0] + '.' + version[1]) + self.usage() + if int(version[1]) < 3: + self.usage() + self.copybin() + if int(version[1]) > 3: + self.installmodule() + self.installtranslations() + +Installer().checkversion() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/loremipsumize.py elyxer-1.2.5/forks/jras-elyxer/loremipsumize.py --- elyxer-1.2.3/forks/jras-elyxer/loremipsumize.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/loremipsumize.py 2013-03-10 10:39:35.000000000 +0000 @@ -0,0 +1,1540 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20091210 +# Lorem-ipsumize a document: replace all alphanumeric texts longer than two words with "Lorem ipsum" and leave the symbols. + +import sys + + + +import sys +import codecs + + + +import sys + +class Trace(object): + "A tracing class" + + debugmode = False + quietmode = False + showlinesmode = False + + prefix = None + + def debug(cls, message): + "Show a debug message" + if not Trace.debugmode or Trace.quietmode: + return + Trace.show(message, sys.stdout) + + def message(cls, message): + "Show a trace message" + if Trace.quietmode: + return + if Trace.prefix and Trace.showlinesmode: + message = Trace.prefix + message + Trace.show(message, sys.stdout) + + def error(cls, message): + "Show an error message" + message = '* ' + message + if Trace.prefix and Trace.showlinesmode: + message = Trace.prefix + message + Trace.show(message, sys.stderr) + + def fatal(cls, message): + "Show an error message and terminate" + Trace.error('FATAL: ' + message) + exit(-1) + + def show(cls, message, channel): + "Show a message out of a channel" + if sys.version_info < (3,0): + message = message.encode('utf-8') + channel.write(message + '\n') + + debug = classmethod(debug) + message = classmethod(message) + error = classmethod(error) + fatal = classmethod(fatal) + show = classmethod(show) + + + +class LineReader(object): + "Reads a file line by line" + + def __init__(self, filename): + if isinstance(filename, file): + self.file = filename + else: + self.file = codecs.open(filename, 'rU', 'utf-8') + self.linenumber = 1 + self.lastline = None + self.current = None + self.mustread = True + self.depleted = False + try: + self.readline() + except UnicodeDecodeError: + # try compressed file + import gzip + self.file = gzip.open(filename, 'rb') + self.readline() + + def setstart(self, firstline): + "Set the first line to read." + for i in range(firstline): + self.file.readline() + self.linenumber = firstline + + def setend(self, lastline): + "Set the last line to read." + self.lastline = lastline + + def currentline(self): + "Get the current line" + if self.mustread: + self.readline() + return self.current + + def nextline(self): + "Go to next line" + if self.depleted: + Trace.fatal('Read beyond file end') + self.mustread = True + + def readline(self): + "Read a line from elyxer.file" + self.current = self.file.readline() + if not isinstance(self.file, codecs.StreamReaderWriter): + self.current = self.current.decode('utf-8') + if len(self.current) == 0: + self.depleted = True + self.current = self.current.rstrip('\n\r') + self.linenumber += 1 + self.mustread = False + Trace.prefix = 'Line ' + unicode(self.linenumber) + ': ' + if self.linenumber % 1000 == 0: + Trace.message('Parsing') + + def finished(self): + "Find out if the file is finished" + if self.lastline and self.linenumber == self.lastline: + return True + if self.mustread: + self.readline() + return self.depleted + + def close(self): + self.file.close() + +class LineWriter(object): + "Writes a file as a series of lists" + + file = False + + def __init__(self, filename): + if isinstance(filename, file): + self.file = filename + self.filename = None + else: + self.filename = filename + + def write(self, strings): + "Write a list of strings" + for string in strings: + if not isinstance(string, basestring): + Trace.error('Not a string: ' + unicode(string) + ' in ' + unicode(strings)) + return + self.writestring(string) + + def writestring(self, string): + "Write a string" + if not self.file: + self.file = codecs.open(self.filename, 'w', "utf-8") + if self.file == sys.stdout and sys.version_info < (3,0): + string = string.encode('utf-8') + self.file.write(string) + + def writeline(self, line): + "Write a line to file" + self.writestring(line + '\n') + + def close(self): + self.file.close() + + + + + + +class BibStylesConfig(object): + "Configuration class from elyxer.config file" + + abbrvnat = { + + u'@article':u'$authors. $title. $journal,{ {$volume:}$pages,} $month $year.{ doi: $doi.}{ URL $url.}{ $note.}', + u'cite':u'$surname($year)', + u'default':u'$authors. $title. $publisher, $year.{ URL $url.}{ $note.}', + } + + alpha = { + + u'@article':u'$authors. $title.{ $journal{, {$volume}{($number)}}{: $pages}{, $year}.}{ $url.}{ $filename.}{ $note.}', + u'cite':u'$Sur$YY', + u'default':u'$authors. $title.{ $journal,} $year.{ $url.}{ $filename.}{ $note.}', + } + + authordate2 = { + + u'@article':u'$authors. $year. $title. $journal, $volume($number), $pages.{ URL $url.}{ $note.}', + u'@book':u'$authors. $year. $title. $publisher.{ URL $url.}{ $note.}', + u'cite':u'$surname, $year', + u'default':u'$authors. $year. $title. $publisher.{ URL $url.}{ $note.}', + } + + default = { + + u'@article':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@book':u'{$authors: }$title{ ($editor, ed.)}.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@booklet':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@conference':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@inbook':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@incollection':u'$authors: $title{ in $booktitle{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@inproceedings':u'$authors: “$title”, $booktitle,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@manual':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@mastersthesis':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@misc':u'$authors: $title.{{ $publisher,}{ $howpublished,} $year.}{ URL $url.}{ $note.}', + u'@phdthesis':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@proceedings':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@techreport':u'$authors: $title, $year.{ URL $url.}{ $note.}', + u'@unpublished':u'$authors: “$title”, $journal, $year.{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + } + + defaulttags = { + u'YY':u'??', u'authors':u'', u'surname':u'', + } + + ieeetr = { + + u'@article':u'$authors, “$title”, $journal, vol. $volume, no. $number, pp. $pages, $year.{ URL $url.}{ $note.}', + u'@book':u'$authors, $title. $publisher, $year.{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors, “$title”. $year.{ URL $url.}{ $note.}', + } + + plain = { + + u'@article':u'$authors. $title.{ $journal{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL $url.}{ $note.}', + u'@book':u'$authors. $title. $publisher,{ $month} $year.{ URL $url.}{ $note.}', + u'@incollection':u'$authors. $title.{ In $booktitle {($editor, ed.)}.} $publisher,{ $month} $year.{ URL $url.}{ $note.}', + u'@inproceedings':u'$authors. $title. { $booktitle{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'{$authors. }$title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + } + + vancouver = { + + u'@article':u'$authors. $title. $journal, $year{;{$volume}{($number)}{:$pages}}.{ URL: $url.}{ $note.}', + u'@book':u'$authors. $title. {$publisher, }$year.{ URL: $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors. $title; {$publisher, }$year.{ $howpublished.}{ URL: $url.}{ $note.}', + } + +class BibTeXConfig(object): + "Configuration class from elyxer.config file" + + replaced = { + u'--':u'—', u'..':u'.', + } + +class ContainerConfig(object): + "Configuration class from elyxer.config file" + + endings = { + u'Align':u'\\end_layout', u'BarredText':u'\\bar', + u'BoldText':u'\\series', u'Cell':u'':u'>', + } + + html = { + u'/>':u'>', + } + + iso885915 = { + u' ':u' ', u' ':u' ', u' ':u' ', + } + + nonunicode = { + u' ':u' ', + } + +class FormulaConfig(object): + "Configuration class from elyxer.config file" + + alphacommands = { + u'\\AA':u'Å', u'\\AE':u'Æ', + u'\\AmS':u'AmS', u'\\Angstroem':u'Å', + u'\\DH':u'Ð', u'\\Koppa':u'Ϟ', u'\\L':u'Ł', u'\\Micro':u'µ', u'\\O':u'Ø', + u'\\OE':u'Œ', u'\\Sampi':u'Ϡ', u'\\Stigma':u'Ϛ', u'\\TH':u'Þ', + u'\\aa':u'å', u'\\ae':u'æ', u'\\alpha':u'α', u'\\beta':u'β', + u'\\delta':u'δ', u'\\dh':u'ð', u'\\digamma':u'ϝ', u'\\epsilon':u'ϵ', + u'\\eta':u'η', u'\\eth':u'ð', u'\\gamma':u'γ', u'\\i':u'ı', + u'\\imath':u'ı', u'\\iota':u'ι', u'\\j':u'ȷ', u'\\jmath':u'ȷ', + u'\\kappa':u'κ', u'\\koppa':u'ϟ', u'\\l':u'ł', u'\\lambda':u'λ', + u'\\mu':u'μ', u'\\nu':u'ν', u'\\o':u'ø', u'\\oe':u'œ', u'\\omega':u'ω', + u'\\phi':u'φ', u'\\pi':u'π', u'\\psi':u'ψ', u'\\rho':u'ρ', + u'\\sampi':u'ϡ', u'\\sigma':u'σ', u'\\ss':u'ß', u'\\stigma':u'ϛ', + u'\\tau':u'τ', u'\\tcohm':u'Ω', u'\\textcrh':u'ħ', u'\\th':u'þ', + u'\\theta':u'θ', u'\\upsilon':u'υ', u'\\varDelta':u'∆', + u'\\varGamma':u'Γ', u'\\varLambda':u'Λ', u'\\varOmega':u'Ω', + u'\\varPhi':u'Φ', u'\\varPi':u'Π', u'\\varPsi':u'Ψ', u'\\varSigma':u'Σ', + u'\\varTheta':u'Θ', u'\\varUpsilon':u'Υ', u'\\varXi':u'Ξ', + u'\\varbeta':u'ϐ', u'\\varepsilon':u'ε', u'\\varkappa':u'ϰ', + u'\\varphi':u'φ', u'\\varpi':u'ϖ', u'\\varrho':u'ϱ', u'\\varsigma':u'ς', + u'\\vartheta':u'ϑ', u'\\xi':u'ξ', u'\\zeta':u'ζ', + } + + array = { + u'begin':u'\\begin', u'cellseparator':u'&', u'end':u'\\end', + u'rowseparator':u'\\\\', + } + + bigbrackets = { + u'(':[u'⎛',u'⎜',u'⎝',], u')':[u'⎞',u'⎟',u'⎠',], u'[':[u'⎡',u'⎢',u'⎣',], + u']':[u'⎤',u'⎥',u'⎦',], u'{':[u'⎧',u'⎪',u'⎨',u'⎩',], u'|':[u'|',], + u'}':[u'⎫',u'⎪',u'⎬',u'⎭',], u'∥':[u'∥',], + } + + bigsymbols = { + u'∑':[u'⎲',u'⎳',], u'∫':[u'⌠',u'⌡',], + } + + bracketcommands = { + u'\\left':u'span class="symbol"', + u'\\left.':u'', + u'\\middle':u'span class="symbol"', u'\\right':u'span class="symbol"', + u'\\right.':u'', + } + + combiningfunctions = { + u'\\"':u'̈', u'\\\'':u'́', u'\\^':u'̂', u'\\`':u'̀', u'\\acute':u'́', + u'\\bar':u'̄', u'\\breve':u'̆', u'\\c':u'̧', u'\\check':u'̌', + u'\\dddot':u'⃛', u'\\ddot':u'̈', u'\\dot':u'̇', u'\\grave':u'̀', + u'\\hat':u'̂', u'\\mathring':u'̊', u'\\overleftarrow':u'⃖', + u'\\overrightarrow':u'⃗', u'\\r':u'̊', u'\\s':u'̩', + u'\\textcircled':u'⃝', u'\\textsubring':u'̥', u'\\tilde':u'̃', + u'\\v':u'̌', u'\\vec':u'⃗', u'\\~':u'̃', + } + + commands = { + u'\\ ':u' ', u'\\!':u'', u'\\#':u'#', u'\\$':u'$', u'\\%':u'%', + u'\\&':u'&', u'\\,':u' ', u'\\:':u' ', u'\\;':u' ', u'\\AC':u'∿', + u'\\APLcomment':u'⍝', u'\\APLdownarrowbox':u'⍗', u'\\APLinput':u'⍞', + u'\\APLinv':u'⌹', u'\\APLleftarrowbox':u'⍇', u'\\APLlog':u'⍟', + u'\\APLrightarrowbox':u'⍈', u'\\APLuparrowbox':u'⍐', u'\\Box':u'□', + u'\\Bumpeq':u'≎', u'\\CIRCLE':u'●', u'\\Cap':u'⋒', + u'\\CapitalDifferentialD':u'ⅅ', u'\\CheckedBox':u'☑', u'\\Circle':u'○', + u'\\Coloneqq':u'⩴', u'\\ComplexI':u'ⅈ', u'\\ComplexJ':u'ⅉ', + u'\\Corresponds':u'≙', u'\\Cup':u'⋓', u'\\Delta':u'Δ', u'\\Diamond':u'◇', + u'\\Diamondblack':u'◆', u'\\Diamonddot':u'⟐', u'\\DifferentialD':u'ⅆ', + u'\\Downarrow':u'⇓', u'\\EUR':u'€', u'\\Euler':u'ℇ', + u'\\ExponetialE':u'ⅇ', u'\\Finv':u'Ⅎ', u'\\Game':u'⅁', u'\\Gamma':u'Γ', + u'\\Im':u'ℑ', u'\\Join':u'⨝', u'\\LEFTCIRCLE':u'◖', u'\\LEFTcircle':u'◐', + u'\\LHD':u'◀', u'\\Lambda':u'Λ', u'\\Lbag':u'⟅', u'\\Leftarrow':u'⇐', + u'\\Lleftarrow':u'⇚', u'\\Longleftarrow':u'⟸', + u'\\Longleftrightarrow':u'⟺', u'\\Longrightarrow':u'⟹', u'\\Lparen':u'⦅', + u'\\Lsh':u'↰', u'\\Mapsfrom':u'⇐|', u'\\Mapsto':u'|⇒', u'\\Omega':u'Ω', + u'\\P':u'¶', u'\\Phi':u'Φ', u'\\Pi':u'Π', u'\\Pr':u'Pr', u'\\Psi':u'Ψ', + u'\\Qoppa':u'Ϙ', u'\\RHD':u'▶', u'\\RIGHTCIRCLE':u'◗', + u'\\RIGHTcircle':u'◑', u'\\Rbag':u'⟆', u'\\Re':u'ℜ', u'\\Rparen':u'⦆', + u'\\Rrightarrow':u'⇛', u'\\Rsh':u'↱', u'\\S':u'§', u'\\Sigma':u'Σ', + u'\\Square':u'☐', u'\\Subset':u'⋐', u'\\Sun':u'☉', u'\\Supset':u'⋑', + u'\\Theta':u'Θ', u'\\Uparrow':u'⇑', u'\\Updownarrow':u'⇕', + u'\\Upsilon':u'Υ', u'\\Vdash':u'⊩', u'\\Vert':u'∥', u'\\Vvdash':u'⊪', + u'\\XBox':u'☒', u'\\Xi':u'Ξ', u'\\Yup':u'⅄', u'\\\\':u'
      ', + u'\\_':u'_', u'\\aleph':u'ℵ', u'\\amalg':u'∐', u'\\anchor':u'⚓', + u'\\angle':u'∠', u'\\aquarius':u'♒', u'\\arccos':u'arccos', + u'\\arcsin':u'arcsin', u'\\arctan':u'arctan', u'\\arg':u'arg', + u'\\aries':u'♈', u'\\arrowbullet':u'➢', u'\\ast':u'∗', u'\\asymp':u'≍', + u'\\backepsilon':u'∍', u'\\backprime':u'‵', u'\\backsimeq':u'⋍', + u'\\backslash':u'\\', u'\\ballotx':u'✗', u'\\barwedge':u'⊼', + u'\\because':u'∵', u'\\beth':u'ℶ', u'\\between':u'≬', u'\\bigcap':u'∩', + u'\\bigcirc':u'○', u'\\bigcup':u'∪', u'\\bigodot':u'⊙', + u'\\bigoplus':u'⊕', u'\\bigotimes':u'⊗', u'\\bigsqcup':u'⊔', + u'\\bigstar':u'★', u'\\bigtriangledown':u'▽', u'\\bigtriangleup':u'△', + u'\\biguplus':u'⊎', u'\\bigvee':u'∨', u'\\bigwedge':u'∧', + u'\\biohazard':u'☣', u'\\blacklozenge':u'⧫', u'\\blacksmiley':u'☻', + u'\\blacksquare':u'■', u'\\blacktriangle':u'▲', + u'\\blacktriangledown':u'▼', u'\\blacktriangleleft':u'◂', + u'\\blacktriangleright':u'▶', u'\\blacktriangleup':u'▴', u'\\bot':u'⊥', + u'\\bowtie':u'⋈', u'\\box':u'▫', u'\\boxast':u'⧆', u'\\boxbar':u'◫', + u'\\boxbox':u'⧈', u'\\boxbslash':u'⧅', u'\\boxcircle':u'⧇', + u'\\boxdot':u'⊡', u'\\boxminus':u'⊟', u'\\boxplus':u'⊞', + u'\\boxslash':u'⧄', u'\\boxtimes':u'⊠', u'\\bullet':u'•', + u'\\bumpeq':u'≏', u'\\cancer':u'♋', u'\\cap':u'∩', u'\\capricornus':u'♑', + u'\\cat':u'⁀', u'\\cdot':u'⋅', u'\\cdots':u'⋯', u'\\cent':u'¢', + u'\\centerdot':u'∙', u'\\checkmark':u'✓', u'\\chi':u'χ', u'\\circ':u'○', + u'\\circeq':u'≗', u'\\circlearrowleft':u'↺', u'\\circlearrowright':u'↻', + u'\\circledR':u'®', u'\\circledast':u'⊛', u'\\circledbslash':u'⦸', + u'\\circledcirc':u'⊚', u'\\circleddash':u'⊝', u'\\circledgtr':u'⧁', + u'\\circledless':u'⧀', u'\\clubsuit':u'♣', u'\\coloneqq':u'≔', + u'\\complement':u'∁', u'\\cong':u'≅', u'\\coprod':u'∐', + u'\\copyright':u'©', u'\\cos':u'cos', u'\\cosh':u'cosh', u'\\cot':u'cot', + u'\\coth':u'coth', u'\\csc':u'csc', u'\\cup':u'∪', u'\\curlyvee':u'⋎', + u'\\curlywedge':u'⋏', u'\\curvearrowleft':u'↶', + u'\\curvearrowright':u'↷', u'\\dag':u'†', u'\\dagger':u'†', + u'\\daleth':u'ℸ', u'\\dashleftarrow':u'⇠', u'\\dashv':u'⊣', + u'\\ddag':u'‡', u'\\ddagger':u'‡', u'\\ddots':u'⋱', u'\\deg':u'deg', + u'\\det':u'det', u'\\diagdown':u'╲', u'\\diagup':u'╱', + u'\\diameter':u'⌀', u'\\diamond':u'◇', u'\\diamondsuit':u'♦', + u'\\dim':u'dim', u'\\div':u'÷', u'\\divideontimes':u'⋇', + u'\\dotdiv':u'∸', u'\\doteq':u'≐', u'\\doteqdot':u'≑', u'\\dotplus':u'∔', + u'\\dots':u'…', u'\\doublebarwedge':u'⌆', u'\\downarrow':u'↓', + u'\\downdownarrows':u'⇊', u'\\downharpoonleft':u'⇃', + u'\\downharpoonright':u'⇂', u'\\dsub':u'⩤', u'\\earth':u'♁', + u'\\eighthnote':u'♪', u'\\ell':u'ℓ', u'\\emptyset':u'∅', + u'\\eqcirc':u'≖', u'\\eqcolon':u'≕', u'\\eqsim':u'≂', u'\\euro':u'€', + u'\\exists':u'∃', u'\\exp':u'exp', u'\\fallingdotseq':u'≒', + u'\\fcmp':u'⨾', u'\\female':u'♀', u'\\flat':u'♭', u'\\forall':u'∀', + u'\\fourth':u'⁗', u'\\frown':u'⌢', u'\\frownie':u'☹', u'\\gcd':u'gcd', + u'\\gemini':u'♊', u'\\geq)':u'≥', u'\\geqq':u'≧', u'\\geqslant':u'≥', + u'\\gets':u'←', u'\\gg':u'≫', u'\\ggg':u'⋙', u'\\gimel':u'ℷ', + u'\\gneqq':u'≩', u'\\gnsim':u'⋧', u'\\gtrdot':u'⋗', u'\\gtreqless':u'⋚', + u'\\gtreqqless':u'⪌', u'\\gtrless':u'≷', u'\\gtrsim':u'≳', + u'\\guillemotleft':u'«', u'\\guillemotright':u'»', u'\\hbar':u'ℏ', + u'\\heartsuit':u'♥', u'\\hfill':u' ', + u'\\hom':u'hom', u'\\hookleftarrow':u'↩', u'\\hookrightarrow':u'↪', + u'\\hslash':u'ℏ', u'\\idotsint':u'∫⋯∫', + u'\\iiint':u'', + u'\\iint':u'', u'\\imath':u'ı', + u'\\inf':u'inf', u'\\infty':u'∞', u'\\intercal':u'⊺', + u'\\interleave':u'⫴', u'\\invamp':u'⅋', u'\\invneg':u'⌐', + u'\\jmath':u'ȷ', u'\\jupiter':u'♃', u'\\ker':u'ker', u'\\land':u'∧', + u'\\landupint':u'', u'\\lang':u'⟪', + u'\\langle':u'⟨', u'\\lblot':u'⦉', u'\\lbrace':u'{', u'\\lbrace)':u'{', + u'\\lbrack':u'[', u'\\lceil':u'⌈', u'\\ldots':u'…', u'\\leadsto':u'⇝', + u'\\leftarrow)':u'←', u'\\leftarrowtail':u'↢', u'\\leftarrowtobar':u'⇤', + u'\\leftharpoondown':u'↽', u'\\leftharpoonup':u'↼', + u'\\leftleftarrows':u'⇇', u'\\leftleftharpoons':u'⥢', u'\\leftmoon':u'☾', + u'\\leftrightarrow':u'↔', u'\\leftrightarrows':u'⇆', + u'\\leftrightharpoons':u'⇋', u'\\leftthreetimes':u'⋋', u'\\leo':u'♌', + u'\\leq)':u'≤', u'\\leqq':u'≦', u'\\leqslant':u'≤', u'\\lessdot':u'⋖', + u'\\lesseqgtr':u'⋛', u'\\lesseqqgtr':u'⪋', u'\\lessgtr':u'≶', + u'\\lesssim':u'≲', u'\\lfloor':u'⌊', u'\\lg':u'lg', u'\\lgroup':u'⟮', + u'\\lhd':u'⊲', u'\\libra':u'♎', u'\\lightning':u'↯', u'\\limg':u'⦇', + u'\\liminf':u'liminf', u'\\limsup':u'limsup', u'\\ll':u'≪', + u'\\llbracket':u'⟦', u'\\llcorner':u'⌞', u'\\lll':u'⋘', u'\\ln':u'ln', + u'\\lneqq':u'≨', u'\\lnot':u'¬', u'\\lnsim':u'⋦', u'\\log':u'log', + u'\\longleftarrow':u'⟵', u'\\longleftrightarrow':u'⟷', + u'\\longmapsto':u'⟼', u'\\longrightarrow':u'⟶', u'\\looparrowleft':u'↫', + u'\\looparrowright':u'↬', u'\\lor':u'∨', u'\\lozenge':u'◊', + u'\\lrcorner':u'⌟', u'\\ltimes':u'⋉', u'\\lyxlock':u'', u'\\male':u'♂', + u'\\maltese':u'✠', u'\\mapsfrom':u'↤', u'\\mapsto':u'↦', + u'\\mathcircumflex':u'^', u'\\max':u'max', u'\\measuredangle':u'∡', + u'\\medbullet':u'⚫', u'\\medcirc':u'⚪', u'\\mercury':u'☿', u'\\mho':u'℧', + u'\\mid':u'∣', u'\\min':u'min', u'\\models':u'⊨', u'\\mp':u'∓', + u'\\multimap':u'⊸', u'\\nLeftarrow':u'⇍', u'\\nLeftrightarrow':u'⇎', + u'\\nRightarrow':u'⇏', u'\\nVDash':u'⊯', u'\\nabla':u'∇', + u'\\napprox':u'≉', u'\\natural':u'♮', u'\\ncong':u'≇', u'\\nearrow':u'↗', + u'\\neg':u'¬', u'\\neg)':u'¬', u'\\neptune':u'♆', u'\\nequiv':u'≢', + u'\\newline':u'
      ', u'\\nexists':u'∄', u'\\ngeqslant':u'≱', + u'\\ngtr':u'≯', u'\\ngtrless':u'≹', u'\\ni':u'∋', u'\\ni)':u'∋', + u'\\nleftarrow':u'↚', u'\\nleftrightarrow':u'↮', u'\\nleqslant':u'≰', + u'\\nless':u'≮', u'\\nlessgtr':u'≸', u'\\nmid':u'∤', u'\\nolimits':u'', + u'\\nonumber':u'', u'\\not':u'¬', u'\\not<':u'≮', u'\\not=':u'≠', + u'\\not>':u'≯', u'\\notbackslash':u'⍀', u'\\notin':u'∉', u'\\notni':u'∌', + u'\\notslash':u'⌿', u'\\nparallel':u'∦', u'\\nprec':u'⊀', + u'\\nrightarrow':u'↛', u'\\nsim':u'≁', u'\\nsimeq':u'≄', + u'\\nsqsubset':u'⊏̸', u'\\nsubseteq':u'⊈', u'\\nsucc':u'⊁', + u'\\nsucccurlyeq':u'⋡', u'\\nsupset':u'⊅', u'\\nsupseteq':u'⊉', + u'\\ntriangleleft':u'⋪', u'\\ntrianglelefteq':u'⋬', + u'\\ntriangleright':u'⋫', u'\\ntrianglerighteq':u'⋭', u'\\nvDash':u'⊭', + u'\\nvdash':u'⊬', u'\\nwarrow':u'↖', u'\\odot':u'⊙', + u'\\officialeuro':u'€', u'\\oiiint':u'', + u'\\oiint':u'', + u'\\oint':u'', + u'\\ointclockwise':u'', + u'\\ointctrclockwise':u'', + u'\\ominus':u'⊖', u'\\oplus':u'⊕', u'\\oslash':u'⊘', u'\\otimes':u'⊗', + u'\\owns':u'∋', u'\\parallel':u'∥', u'\\partial':u'∂', u'\\pencil':u'✎', + u'\\perp':u'⊥', u'\\pisces':u'♓', u'\\pitchfork':u'⋔', u'\\pluto':u'♇', + u'\\pm':u'±', u'\\pointer':u'➪', u'\\pointright':u'☞', u'\\pounds':u'£', + u'\\prec':u'≺', u'\\preccurlyeq':u'≼', u'\\preceq':u'≼', + u'\\precsim':u'≾', u'\\prime':u'′', u'\\prompto':u'∝', u'\\qoppa':u'ϙ', + u'\\qquad':u' ', u'\\quad':u' ', u'\\quarternote':u'♩', + u'\\radiation':u'☢', u'\\rang':u'⟫', u'\\rangle':u'⟩', u'\\rblot':u'⦊', + u'\\rbrace':u'}', u'\\rbrace)':u'}', u'\\rbrack':u']', u'\\rceil':u'⌉', + u'\\recycle':u'♻', u'\\rfloor':u'⌋', u'\\rgroup':u'⟯', u'\\rhd':u'⊳', + u'\\rightangle':u'∟', u'\\rightarrow)':u'→', u'\\rightarrowtail':u'↣', + u'\\rightarrowtobar':u'⇥', u'\\rightharpoondown':u'⇁', + u'\\rightharpoonup':u'⇀', u'\\rightharpooondown':u'⇁', + u'\\rightharpooonup':u'⇀', u'\\rightleftarrows':u'⇄', + u'\\rightleftharpoons':u'⇌', u'\\rightmoon':u'☽', + u'\\rightrightarrows':u'⇉', u'\\rightrightharpoons':u'⥤', + u'\\rightthreetimes':u'⋌', u'\\rimg':u'⦈', u'\\risingdotseq':u'≓', + u'\\rrbracket':u'⟧', u'\\rsub':u'⩥', u'\\rtimes':u'⋊', + u'\\sagittarius':u'♐', u'\\saturn':u'♄', u'\\scorpio':u'♏', + u'\\searrow':u'↘', u'\\sec':u'sec', u'\\second':u'″', u'\\setminus':u'∖', + u'\\sharp':u'♯', u'\\simeq':u'≃', u'\\sin':u'sin', u'\\sinh':u'sinh', + u'\\sixteenthnote':u'♬', u'\\skull':u'☠', u'\\slash':u'∕', + u'\\smallsetminus':u'∖', u'\\smalltriangledown':u'▿', + u'\\smalltriangleleft':u'◃', u'\\smalltriangleright':u'▹', + u'\\smalltriangleup':u'▵', u'\\smile':u'⌣', u'\\smiley':u'☺', + u'\\spadesuit':u'♠', u'\\spddot':u'¨', u'\\sphat':u'', + u'\\sphericalangle':u'∢', u'\\spot':u'⦁', u'\\sptilde':u'~', + u'\\sqcap':u'⊓', u'\\sqcup':u'⊔', u'\\sqsubset':u'⊏', + u'\\sqsubseteq':u'⊑', u'\\sqsupset':u'⊐', u'\\sqsupseteq':u'⊒', + u'\\square':u'□', u'\\sslash':u'⫽', u'\\star':u'⋆', u'\\steaming':u'☕', + u'\\subseteqq':u'⫅', u'\\subsetneqq':u'⫋', u'\\succ':u'≻', + u'\\succcurlyeq':u'≽', u'\\succeq':u'≽', u'\\succnsim':u'⋩', + u'\\succsim':u'≿', u'\\sun':u'☼', u'\\sup':u'sup', u'\\supseteqq':u'⫆', + u'\\supsetneqq':u'⫌', u'\\surd':u'√', u'\\swarrow':u'↙', + u'\\swords':u'⚔', u'\\talloblong':u'⫾', u'\\tan':u'tan', + u'\\tanh':u'tanh', u'\\taurus':u'♉', u'\\textasciicircum':u'^', + u'\\textasciitilde':u'~', u'\\textbackslash':u'\\', + u'\\textcopyright':u'©\'', u'\\textdegree':u'°', u'\\textellipsis':u'…', + u'\\textemdash':u'—', u'\\textendash':u'—', u'\\texteuro':u'€', + u'\\textgreater':u'>', u'\\textless':u'<', u'\\textordfeminine':u'ª', + u'\\textordmasculine':u'º', u'\\textquotedblleft':u'“', + u'\\textquotedblright':u'”', u'\\textquoteright':u'’', + u'\\textregistered':u'®', u'\\textrightarrow':u'→', + u'\\textsection':u'§', u'\\texttrademark':u'™', + u'\\texttwosuperior':u'²', u'\\textvisiblespace':u' ', + u'\\therefore':u'∴', u'\\third':u'‴', u'\\top':u'⊤', u'\\triangle':u'△', + u'\\triangleleft':u'⊲', u'\\trianglelefteq':u'⊴', u'\\triangleq':u'≜', + u'\\triangleright':u'▷', u'\\trianglerighteq':u'⊵', + u'\\twoheadleftarrow':u'↞', u'\\twoheadrightarrow':u'↠', + u'\\twonotes':u'♫', u'\\udot':u'⊍', u'\\ulcorner':u'⌜', u'\\unlhd':u'⊴', + u'\\unrhd':u'⊵', u'\\unrhl':u'⊵', u'\\uparrow':u'↑', + u'\\updownarrow':u'↕', u'\\upharpoonleft':u'↿', u'\\upharpoonright':u'↾', + u'\\uplus':u'⊎', u'\\upuparrows':u'⇈', u'\\uranus':u'♅', + u'\\urcorner':u'⌝', u'\\vDash':u'⊨', u'\\varclubsuit':u'♧', + u'\\vardiamondsuit':u'♦', u'\\varheartsuit':u'♥', u'\\varnothing':u'∅', + u'\\varspadesuit':u'♤', u'\\vdash':u'⊢', u'\\vdots':u'⋮', u'\\vee':u'∨', + u'\\vee)':u'∨', u'\\veebar':u'⊻', u'\\vert':u'∣', u'\\virgo':u'♍', + u'\\warning':u'⚠', u'\\wasylozenge':u'⌑', u'\\wedge':u'∧', + u'\\wedge)':u'∧', u'\\wp':u'℘', u'\\wr':u'≀', u'\\yen':u'¥', + u'\\yinyang':u'☯', u'\\{':u'{', u'\\|':u'∥', u'\\}':u'}', + } + + decoratedcommand = { + + } + + decoratingfunctions = { + u'\\overleftarrow':u'⟵', u'\\overrightarrow':u'⟶', u'\\widehat':u'^', + } + + endings = { + u'bracket':u'}', u'complex':u'\\]', u'endafter':u'}', + u'endbefore':u'\\end{', u'squarebracket':u']', + } + + environments = { + u'align':[u'r',u'l',], u'eqnarray':[u'r',u'c',u'l',], + u'gathered':[u'l',u'l',], + } + + fontfunctions = { + u'\\boldsymbol':u'b', u'\\mathbb':u'span class="blackboard"', + u'\\mathbb{A}':u'𝔸', u'\\mathbb{B}':u'𝔹', u'\\mathbb{C}':u'ℂ', + u'\\mathbb{D}':u'𝔻', u'\\mathbb{E}':u'𝔼', u'\\mathbb{F}':u'𝔽', + u'\\mathbb{G}':u'𝔾', u'\\mathbb{H}':u'ℍ', u'\\mathbb{J}':u'𝕁', + u'\\mathbb{K}':u'𝕂', u'\\mathbb{L}':u'𝕃', u'\\mathbb{N}':u'ℕ', + u'\\mathbb{O}':u'𝕆', u'\\mathbb{P}':u'ℙ', u'\\mathbb{Q}':u'ℚ', + u'\\mathbb{R}':u'ℝ', u'\\mathbb{S}':u'𝕊', u'\\mathbb{T}':u'𝕋', + u'\\mathbb{W}':u'𝕎', u'\\mathbb{Z}':u'ℤ', u'\\mathbf':u'b', + u'\\mathcal':u'span class="scriptfont"', u'\\mathcal{B}':u'ℬ', + u'\\mathcal{E}':u'ℰ', u'\\mathcal{F}':u'ℱ', u'\\mathcal{H}':u'ℋ', + u'\\mathcal{I}':u'ℐ', u'\\mathcal{L}':u'ℒ', u'\\mathcal{M}':u'ℳ', + u'\\mathcal{R}':u'ℛ', u'\\mathfrak':u'span class="fraktur"', + u'\\mathfrak{C}':u'ℭ', u'\\mathfrak{F}':u'𝔉', u'\\mathfrak{H}':u'ℌ', + u'\\mathfrak{I}':u'ℑ', u'\\mathfrak{R}':u'ℜ', u'\\mathfrak{Z}':u'ℨ', + u'\\mathit':u'i', u'\\mathring{A}':u'Å', u'\\mathring{U}':u'Ů', + u'\\mathring{a}':u'å', u'\\mathring{u}':u'ů', u'\\mathring{w}':u'ẘ', + u'\\mathring{y}':u'ẙ', u'\\mathrm':u'span class="mathrm"', + u'\\mathscr':u'span class="scriptfont"', u'\\mathscr{B}':u'ℬ', + u'\\mathscr{E}':u'ℰ', u'\\mathscr{F}':u'ℱ', u'\\mathscr{H}':u'ℋ', + u'\\mathscr{I}':u'ℐ', u'\\mathscr{L}':u'ℒ', u'\\mathscr{M}':u'ℳ', + u'\\mathscr{R}':u'ℛ', u'\\mathsf':u'span class="mathsf"', + u'\\mathtt':u'tt', + } + + hybridfunctions = { + u'\\addcontentsline':[u'{$p!}{$q!}{$r!}',u'f0{}',u'ignored',], + u'\\addtocontents':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\backmatter':[u'',u'f0{}',u'ignored',], + u'\\binom':[u'{$1}{$2}',u'f2{(}f0{f1{$1}f1{$2}}f2{)}',u'span class="binom"',u'span class="binomstack"',u'span class="bigsymbol"',], + u'\\boxed':[u'{$1}',u'f0{$1}',u'span class="boxed"',], + u'\\cfrac':[u'[$p!]{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator align-$p"',u'span class="denominator"',u'span class="ignored"',], + u'\\color':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], + u'\\colorbox':[u'{$p!}{$1}',u'f0{$1}',u'span class="colorbox" style="background: $p;"',], + u'\\dbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], + u'\\dfrac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], + u'\\displaystyle':[u'{$1}',u'f0{$1}',u'span class="displaystyle"',], + u'\\fancyfoot':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fancyhead':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fbox':[u'{$1}',u'f0{$1}',u'span class="fbox"',], + u'\\fboxrule':[u'{$p!}',u'f0{}',u'ignored',], + u'\\fboxsep':[u'{$p!}',u'f0{}',u'ignored',], + u'\\fcolorbox':[u'{$p!}{$q!}{$1}',u'f0{$1}',u'span class="boxed" style="border-color: $p; background: $q;"',], + u'\\frac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], + u'\\framebox':[u'[$p!][$q!]{$1}',u'f0{$1}',u'span class="framebox align-$q" style="width: $p;"',], + u'\\frontmatter':[u'',u'f0{}',u'ignored',], + u'\\href':[u'[$o]{$u!}{$t!}',u'f0{$t}',u'a href="$u"',], + u'\\hspace':[u'{$p!}',u'f0{ }',u'span class="hspace" style="width: $p;"',], + u'\\leftroot':[u'{$p!}',u'f0{ }',u'span class="leftroot" style="width: $p;px"',], + u'\\mainmatter':[u'',u'f0{}',u'ignored',], + u'\\markboth':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\markright':[u'{$p!}',u'f0{}',u'ignored',], + u'\\nicefrac':[u'{$1}{$2}',u'f0{f1{$1}⁄f2{$2}}',u'span class="fraction"',u'sup class="numerator"',u'sub class="denominator"',u'span class="ignored"',], + u'\\parbox':[u'[$p!]{$w!}{$1}',u'f0{1}',u'div class="Boxed" style="width: $w;"',], + u'\\raisebox':[u'{$p!}{$1}',u'f0{$1.font}',u'span class="raisebox" style="vertical-align: $p;"',], + u'\\renewenvironment':[u'{$1!}{$2!}{$3!}',u'',], + u'\\rule':[u'[$v!]{$w!}{$h!}',u'f0/',u'hr class="line" style="width: $w; height: $h;"',], + u'\\scriptscriptstyle':[u'{$1}',u'f0{$1}',u'span class="scriptscriptstyle"',], + u'\\scriptstyle':[u'{$1}',u'f0{$1}',u'span class="scriptstyle"',], + u'\\sqrt':[u'[$0]{$1}',u'f0{f1{$0}f2{√}f4{(}f3{$1}f4{)}}',u'span class="sqrt"',u'sup class="root"',u'span class="radical"',u'span class="root"',u'span class="ignored"',], + u'\\stackrel':[u'{$1}{$2}',u'f0{f1{$1}f2{$2}}',u'span class="stackrel"',u'span class="upstackrel"',u'span class="downstackrel"',], + u'\\tbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], + u'\\textcolor':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], + u'\\textstyle':[u'{$1}',u'f0{$1}',u'span class="textstyle"',], + u'\\thispagestyle':[u'{$p!}',u'f0{}',u'ignored',], + u'\\unit':[u'[$0]{$1}',u'$0f0{$1.font}',u'span class="unit"',], + u'\\unitfrac':[u'[$0]{$1}{$2}',u'$0f0{f1{$1.font}⁄f2{$2.font}}',u'span class="fraction"',u'sup class="unit"',u'sub class="unit"',], + u'\\uproot':[u'{$p!}',u'f0{ }',u'span class="uproot" style="width: $p;px"',], + u'\\url':[u'{$u!}',u'f0{$u}',u'a href="$u"',], + u'\\vspace':[u'{$p!}',u'f0{ }',u'span class="vspace" style="height: $p;"',], + } + + hybridsizes = { + u'\\binom':u'$1+$2', u'\\cfrac':u'$1+$2', u'\\dbinom':u'$1+$2+1', + u'\\dfrac':u'$1+$2', u'\\frac':u'$1+$2', u'\\tbinom':u'$1+$2+1', + } + + labelfunctions = { + u'\\label':u'a name="#"', + } + + limitcommands = { + u'\\biginterleave':u'⫼', u'\\bigsqcap':u'⨅', u'\\fint':u'⨏', + u'\\iiiint':u'⨌', u'\\int':u'∫', u'\\intop':u'∫', u'\\lim':u'lim', + u'\\prod':u'∏', u'\\smallint':u'∫', u'\\sqint':u'⨖', u'\\sum':u'∑', + u'\\varointclockwise':u'∲', u'\\varprod':u'⨉', u'\\zcmp':u'⨟', + u'\\zhide':u'⧹', u'\\zpipe':u'⨠', u'\\zproject':u'⨡', + } + + misccommands = { + u'\\limits':u'LimitPreviousCommand', u'\\newcommand':u'MacroDefinition', + u'\\renewcommand':u'MacroDefinition', + u'\\setcounter':u'SetCounterFunction', u'\\tag':u'FormulaTag', + u'\\tag*':u'FormulaTag', u'\\today':u'TodayCommand', + } + + modified = { + u'\n':u'', u' ':u'', u'$':u'', u'&':u' ', u'\'':u'’', u'+':u' + ', + u',':u', ', u'-':u' − ', u'/':u' ⁄ ', u'<':u' < ', u'=':u' = ', + u'>':u' > ', u'@':u'', u'~':u'', + } + + onefunctions = { + u'\\Big':u'span class="bigsymbol"', u'\\Bigg':u'span class="hugesymbol"', + u'\\bar':u'span class="bar"', u'\\begin{array}':u'span class="arraydef"', + u'\\big':u'span class="symbol"', u'\\bigg':u'span class="largesymbol"', + u'\\bigl':u'span class="bigsymbol"', u'\\bigr':u'span class="bigsymbol"', + u'\\centering':u'span class="align-center"', + u'\\ensuremath':u'span class="ensuremath"', + u'\\hphantom':u'span class="phantom"', + u'\\noindent':u'span class="noindent"', + u'\\overbrace':u'span class="overbrace"', + u'\\overline':u'span class="overline"', + u'\\phantom':u'span class="phantom"', + u'\\underbrace':u'span class="underbrace"', u'\\underline':u'u', + u'\\vphantom':u'span class="phantom"', + } + + spacedcommands = { + u'\\Bot':u'⫫', u'\\Doteq':u'≑', u'\\DownArrowBar':u'⤓', + u'\\DownLeftTeeVector':u'⥞', u'\\DownLeftVectorBar':u'⥖', + u'\\DownRightTeeVector':u'⥟', u'\\DownRightVectorBar':u'⥗', + u'\\Equal':u'⩵', u'\\LeftArrowBar':u'⇤', u'\\LeftDownTeeVector':u'⥡', + u'\\LeftDownVectorBar':u'⥙', u'\\LeftTeeVector':u'⥚', + u'\\LeftTriangleBar':u'⧏', u'\\LeftUpTeeVector':u'⥠', + u'\\LeftUpVectorBar':u'⥘', u'\\LeftVectorBar':u'⥒', + u'\\Leftrightarrow':u'⇔', u'\\Longmapsfrom':u'⟽', u'\\Longmapsto':u'⟾', + u'\\MapsDown':u'↧', u'\\MapsUp':u'↥', u'\\Nearrow':u'⇗', + u'\\NestedGreaterGreater':u'⪢', u'\\NestedLessLess':u'⪡', + u'\\NotGreaterLess':u'≹', u'\\NotGreaterTilde':u'≵', + u'\\NotLessTilde':u'≴', u'\\Nwarrow':u'⇖', u'\\Proportion':u'∷', + u'\\RightArrowBar':u'⇥', u'\\RightDownTeeVector':u'⥝', + u'\\RightDownVectorBar':u'⥕', u'\\RightTeeVector':u'⥛', + u'\\RightTriangleBar':u'⧐', u'\\RightUpTeeVector':u'⥜', + u'\\RightUpVectorBar':u'⥔', u'\\RightVectorBar':u'⥓', + u'\\Rightarrow':u'⇒', u'\\Same':u'⩶', u'\\Searrow':u'⇘', + u'\\Swarrow':u'⇙', u'\\Top':u'⫪', u'\\UpArrowBar':u'⤒', u'\\VDash':u'⊫', + u'\\approx':u'≈', u'\\approxeq':u'≊', u'\\backsim':u'∽', u'\\barin':u'⋶', + u'\\barleftharpoon':u'⥫', u'\\barrightharpoon':u'⥭', u'\\bij':u'⤖', + u'\\coloneq':u'≔', u'\\corresponds':u'≙', u'\\curlyeqprec':u'⋞', + u'\\curlyeqsucc':u'⋟', u'\\dashrightarrow':u'⇢', u'\\dlsh':u'↲', + u'\\downdownharpoons':u'⥥', u'\\downuparrows':u'⇵', + u'\\downupharpoons':u'⥯', u'\\drsh':u'↳', u'\\eqslantgtr':u'⪖', + u'\\eqslantless':u'⪕', u'\\equiv':u'≡', u'\\ffun':u'⇻', u'\\finj':u'⤕', + u'\\ge':u'≥', u'\\geq':u'≥', u'\\ggcurly':u'⪼', u'\\gnapprox':u'⪊', + u'\\gneq':u'⪈', u'\\gtrapprox':u'⪆', u'\\hash':u'⋕', u'\\iddots':u'⋰', + u'\\implies':u' ⇒ ', u'\\in':u'∈', u'\\le':u'≤', u'\\leftarrow':u'←', + u'\\leftarrowtriangle':u'⇽', u'\\leftbarharpoon':u'⥪', + u'\\leftrightarrowtriangle':u'⇿', u'\\leftrightharpoon':u'⥊', + u'\\leftrightharpoondown':u'⥐', u'\\leftrightharpoonup':u'⥎', + u'\\leftrightsquigarrow':u'↭', u'\\leftslice':u'⪦', + u'\\leftsquigarrow':u'⇜', u'\\leftupdownharpoon':u'⥑', u'\\leq':u'≤', + u'\\lessapprox':u'⪅', u'\\llcurly':u'⪻', u'\\lnapprox':u'⪉', + u'\\lneq':u'⪇', u'\\longmapsfrom':u'⟻', u'\\multimapboth':u'⧟', + u'\\multimapdotbothA':u'⊶', u'\\multimapdotbothB':u'⊷', + u'\\multimapinv':u'⟜', u'\\nVdash':u'⊮', u'\\ne':u'≠', u'\\neq':u'≠', + u'\\ngeq':u'≱', u'\\nleq':u'≰', u'\\nni':u'∌', u'\\not\\in':u'∉', + u'\\notasymp':u'≭', u'\\npreceq':u'⋠', u'\\nsqsubseteq':u'⋢', + u'\\nsqsupseteq':u'⋣', u'\\nsubset':u'⊄', u'\\nsucceq':u'⋡', + u'\\pfun':u'⇸', u'\\pinj':u'⤔', u'\\precapprox':u'⪷', u'\\preceqq':u'⪳', + u'\\precnapprox':u'⪹', u'\\precnsim':u'⋨', u'\\propto':u'∝', + u'\\psur':u'⤀', u'\\rightarrow':u'→', u'\\rightarrowtriangle':u'⇾', + u'\\rightbarharpoon':u'⥬', u'\\rightleftharpoon':u'⥋', + u'\\rightslice':u'⪧', u'\\rightsquigarrow':u'⇝', + u'\\rightupdownharpoon':u'⥏', u'\\sim':u'~', u'\\strictfi':u'⥼', + u'\\strictif':u'⥽', u'\\subset':u'⊂', u'\\subseteq':u'⊆', + u'\\subsetneq':u'⊊', u'\\succapprox':u'⪸', u'\\succeqq':u'⪴', + u'\\succnapprox':u'⪺', u'\\supset':u'⊃', u'\\supseteq':u'⊇', + u'\\supsetneq':u'⊋', u'\\times':u'×', u'\\to':u'→', + u'\\updownarrows':u'⇅', u'\\updownharpoons':u'⥮', u'\\upupharpoons':u'⥣', + u'\\vartriangleleft':u'⊲', u'\\vartriangleright':u'⊳', + } + + starts = { + u'beginafter':u'}', u'beginbefore':u'\\begin{', u'bracket':u'{', + u'command':u'\\', u'comment':u'%', u'complex':u'\\[', u'simple':u'$', + u'squarebracket':u'[', u'unnumbered':u'*', + } + + symbolfunctions = { + u'^':u'sup', u'_':u'sub', + } + + textfunctions = { + u'\\mbox':u'span class="mbox"', u'\\text':u'span class="text"', + u'\\textbf':u'b', u'\\textipa':u'span class="textipa"', u'\\textit':u'i', + u'\\textnormal':u'span class="textnormal"', + u'\\textrm':u'span class="textrm"', + u'\\textsc':u'span class="versalitas"', + u'\\textsf':u'span class="textsf"', u'\\textsl':u'i', u'\\texttt':u'tt', + u'\\textup':u'span class="normal"', + } + + unmodified = { + + u'characters':[u'.',u'*',u'€',u'(',u')',u'[',u']',u':',u'·',u'!',u';',u'|',u'§',u'"',], + } + + urls = { + u'googlecharts':u'http://chart.googleapis.com/chart?cht=tx&chl=', + } + +class GeneralConfig(object): + "Configuration class from elyxer.config file" + + version = { + u'date':u'2013-03-10', u'lyxformat':u'413', u'number':u'1.2.4', + } + +class HeaderConfig(object): + "Configuration class from elyxer.config file" + + parameters = { + u'beginpreamble':u'\\begin_preamble', u'branch':u'\\branch', + u'documentclass':u'\\textclass', u'endbranch':u'\\end_branch', + u'endpreamble':u'\\end_preamble', u'language':u'\\language', + u'lstset':u'\\lstset', u'outputchanges':u'\\output_changes', + u'paragraphseparation':u'\\paragraph_separation', + u'pdftitle':u'\\pdf_title', u'secnumdepth':u'\\secnumdepth', + u'tocdepth':u'\\tocdepth', + } + + styles = { + + u'article':[u'article',u'aastex',u'aapaper',u'acmsiggraph',u'sigplanconf',u'achemso',u'amsart',u'apa',u'arab-article',u'armenian-article',u'article-beamer',u'chess',u'dtk',u'elsarticle',u'heb-article',u'IEEEtran',u'iopart',u'kluwer',u'scrarticle-beamer',u'scrartcl',u'extarticle',u'paper',u'mwart',u'revtex4',u'spie',u'svglobal3',u'ltugboat',u'agu-dtd',u'jgrga',u'agums',u'entcs',u'egs',u'ijmpc',u'ijmpd',u'singlecol-new',u'doublecol-new',u'isprs',u'tarticle',u'jsarticle',u'jarticle',u'jss',u'literate-article',u'siamltex',u'cl2emult',u'llncs',u'svglobal',u'svjog',u'svprobth',], + u'book':[u'book',u'amsbook',u'scrbook',u'extbook',u'tufte-book',u'report',u'extreport',u'scrreprt',u'memoir',u'tbook',u'jsbook',u'jbook',u'mwbk',u'svmono',u'svmult',u'treport',u'jreport',u'mwrep',], + } + +class ImageConfig(object): + "Configuration class from elyxer.config file" + + converters = { + + u'imagemagick':u'convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output"', + u'inkscape':u'inkscape "$input" --export-png="$output"', + u'lyx':u'lyx -C "$input" "$output"', + } + + cropboxformats = { + u'.eps':u'ps', u'.pdf':u'pdf', u'.ps':u'ps', + } + + formats = { + u'default':u'.png', u'vector':[u'.svg',u'.eps',], + } + +class LayoutConfig(object): + "Configuration class from elyxer.config file" + + groupable = { + + u'allowed':[u'StringContainer',u'Constant',u'TaggedText',u'Align',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + } + +class NewfangleConfig(object): + "Configuration class from elyxer.config file" + + constants = { + u'chunkref':u'chunkref{', u'endcommand':u'}', u'endmark':u'>', + u'startcommand':u'\\', u'startmark':u'=<', + } + +class NumberingConfig(object): + "Configuration class from elyxer.config file" + + layouts = { + + u'ordered':[u'Chapter',u'Section',u'Subsection',u'Subsubsection',u'Paragraph',], + u'roman':[u'Part',u'Book',], + } + + sequence = { + u'symbols':[u'*',u'**',u'†',u'‡',u'§',u'§§',u'¶',u'¶¶',u'#',u'##',], + } + +class StyleConfig(object): + "Configuration class from elyxer.config file" + + hspaces = { + u'\\enskip{}':u' ', u'\\hfill{}':u' ', + u'\\hspace*{\\fill}':u' ', u'\\hspace*{}':u'', u'\\hspace{}':u' ', + u'\\negthinspace{}':u'', u'\\qquad{}':u'  ', u'\\quad{}':u' ', + u'\\space{}':u' ', u'\\thinspace{}':u' ', u'~':u' ', + } + + quotes = { + u'ald':u'»', u'als':u'›', u'ard':u'«', u'ars':u'‹', u'eld':u'“', + u'els':u'‘', u'erd':u'”', u'ers':u'’', u'fld':u'«', + u'fls':u'‹', u'frd':u'»', u'frs':u'›', u'gld':u'„', u'gls':u'‚', + u'grd':u'“', u'grs':u'‘', u'pld':u'„', u'pls':u'‚', u'prd':u'”', + u'prs':u'’', u'sld':u'”', u'srd':u'”', + } + + referenceformats = { + u'eqref':u'(@↕)', u'formatted':u'¶↕', u'nameref':u'$↕', u'pageref':u'#↕', + u'ref':u'@↕', u'vpageref':u'on-page#↕', u'vref':u'@on-page#↕', + } + + size = { + u'ignoredtexts':[u'col',u'text',u'line',u'page',u'theight',u'pheight',], + } + + vspaces = { + u'bigskip':u'
      ', + u'defskip':u'
      ', + u'medskip':u'
      ', + u'smallskip':u'
      ', + u'vfill':u'
      ', + } + +class TOCConfig(object): + "Configuration class from elyxer.config file" + + extractplain = { + + u'allowed':[u'StringContainer',u'Constant',u'TaggedText',u'Align',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + u'cloned':[u'',], u'extracted':[u'',], + } + + extracttitle = { + u'allowed':[u'StringContainer',u'Constant',u'Space',], + u'cloned':[u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + u'extracted':[u'PlainLayout',u'TaggedText',u'Align',u'Caption',u'StandardLayout',u'FlexInset',], + } + +class TagConfig(object): + "Configuration class from elyxer.config file" + + barred = { + u'under':u'u', + } + + family = { + u'sans':u'span class="sans"', u'typewriter':u'tt', + } + + flex = { + u'CharStyle:Code':u'span class="code"', + u'CharStyle:MenuItem':u'span class="menuitem"', + u'Code':u'span class="code"', u'MenuItem':u'span class="menuitem"', + u'Noun':u'span class="noun"', u'Strong':u'span class="strong"', + } + + group = { + u'layouts':[u'Quotation',u'Quote',], + } + + layouts = { + u'Center':u'div', u'Chapter':u'h?', u'Date':u'h2', u'Paragraph':u'div', + u'Part':u'h1', u'Quotation':u'blockquote', u'Quote':u'blockquote', + u'Section':u'h?', u'Subsection':u'h?', u'Subsubsection':u'h?', + } + + listitems = { + u'Enumerate':u'ol', u'Itemize':u'ul', + } + + notes = { + u'Comment':u'', u'Greyedout':u'span class="greyedout"', u'Note':u'', + } + + script = { + u'subscript':u'sub', u'superscript':u'sup', + } + + shaped = { + u'italic':u'i', u'slanted':u'i', u'smallcaps':u'span class="versalitas"', + } + +class TranslationConfig(object): + "Configuration class from elyxer.config file" + + constants = { + u'Appendix':u'Appendix', u'Book':u'Book', u'Chapter':u'Chapter', + u'Paragraph':u'Paragraph', u'Part':u'Part', u'Section':u'Section', + u'Subsection':u'Subsection', u'Subsubsection':u'Subsubsection', + u'abstract':u'Abstract', u'bibliography':u'Bibliography', + u'figure':u'figure', u'float-algorithm':u'Algorithm ', + u'float-figure':u'Figure ', u'float-listing':u'Listing ', + u'float-table':u'Table ', u'float-tableau':u'Tableau ', + u'footnotes':u'Footnotes', u'generated-by':u'Document generated by ', + u'generated-on':u' on ', u'index':u'Index', + u'jsmath-enable':u'Please enable JavaScript on your browser.', + u'jsmath-requires':u' requires JavaScript to correctly process the mathematics on this page. ', + u'jsmath-warning':u'Warning: ', u'list-algorithm':u'List of Algorithms', + u'list-figure':u'List of Figures', u'list-table':u'List of Tables', + u'list-tableau':u'List of Tableaux', u'main-page':u'Main page', + u'next':u'Next', u'nomenclature':u'Nomenclature', + u'on-page':u' on page ', u'prev':u'Prev', u'references':u'References', + u'toc':u'Table of Contents', u'toc-for':u'Contents for ', u'up':u'Up', + } + + languages = { + u'american':u'en', u'british':u'en', u'deutsch':u'de', u'dutch':u'nl', + u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'russian':u'ru', + u'spanish':u'es', + } + + + + + + +class Globable(object): + """A bit of text which can be globbed (lumped together in bits). + Methods current(), skipcurrent(), checkfor() and isout() have to be + implemented by subclasses.""" + + leavepending = False + + def __init__(self): + self.endinglist = EndingList() + + def checkbytemark(self): + "Check for a Unicode byte mark and skip it." + if self.finished(): + return + if ord(self.current()) == 0xfeff: + self.skipcurrent() + + def isout(self): + "Find out if we are out of the position yet." + Trace.error('Unimplemented isout()') + return True + + def current(self): + "Return the current character." + Trace.error('Unimplemented current()') + return '' + + def checkfor(self, string): + "Check for the given string in the current position." + Trace.error('Unimplemented checkfor()') + return False + + def finished(self): + "Find out if the current text has finished." + if self.isout(): + if not self.leavepending: + self.endinglist.checkpending() + return True + return self.endinglist.checkin(self) + + def skipcurrent(self): + "Return the current character and skip it." + Trace.error('Unimplemented skipcurrent()') + return '' + + def glob(self, currentcheck): + "Glob a bit of text that satisfies a check on the current char." + glob = '' + while not self.finished() and currentcheck(): + glob += self.skipcurrent() + return glob + + def globalpha(self): + "Glob a bit of alpha text" + return self.glob(lambda: self.current().isalpha()) + + def globnumber(self): + "Glob a row of digits." + return self.glob(lambda: self.current().isdigit()) + + def isidentifier(self): + "Return if the current character is alphanumeric or _." + if self.current().isalnum() or self.current() == '_': + return True + return False + + def globidentifier(self): + "Glob alphanumeric and _ symbols." + return self.glob(self.isidentifier) + + def isvalue(self): + "Return if the current character is a value character:" + "not a bracket or a space." + if self.current().isspace(): + return False + if self.current() in '{}()': + return False + return True + + def globvalue(self): + "Glob a value: any symbols but brackets." + return self.glob(self.isvalue) + + def skipspace(self): + "Skip all whitespace at current position." + return self.glob(lambda: self.current().isspace()) + + def globincluding(self, magicchar): + "Glob a bit of text up to (including) the magic char." + glob = self.glob(lambda: self.current() != magicchar) + magicchar + self.skip(magicchar) + return glob + + def globexcluding(self, excluded): + "Glob a bit of text up until (excluding) any excluded character." + return self.glob(lambda: self.current() not in excluded) + + def pushending(self, ending, optional = False): + "Push a new ending to the bottom" + self.endinglist.add(ending, optional) + + def popending(self, expected = None): + "Pop the ending found at the current position" + if self.isout() and self.leavepending: + return expected + ending = self.endinglist.pop(self) + if expected and expected != ending: + Trace.error('Expected ending ' + expected + ', got ' + ending) + self.skip(ending) + return ending + + def nextending(self): + "Return the next ending in the queue." + nextending = self.endinglist.findending(self) + if not nextending: + return None + return nextending.ending + +class EndingList(object): + "A list of position endings" + + def __init__(self): + self.endings = [] + + def add(self, ending, optional = False): + "Add a new ending to the list" + self.endings.append(PositionEnding(ending, optional)) + + def pickpending(self, pos): + "Pick any pending endings from a parse position." + self.endings += pos.endinglist.endings + + def checkin(self, pos): + "Search for an ending" + if self.findending(pos): + return True + return False + + def pop(self, pos): + "Remove the ending at the current position" + if pos.isout(): + Trace.error('No ending out of bounds') + return '' + ending = self.findending(pos) + if not ending: + Trace.error('No ending at ' + pos.current()) + return '' + for each in reversed(self.endings): + self.endings.remove(each) + if each == ending: + return each.ending + elif not each.optional: + Trace.error('Removed non-optional ending ' + each) + Trace.error('No endings left') + return '' + + def findending(self, pos): + "Find the ending at the current position" + if len(self.endings) == 0: + return None + for index, ending in enumerate(reversed(self.endings)): + if ending.checkin(pos): + return ending + if not ending.optional: + return None + return None + + def checkpending(self): + "Check if there are any pending endings" + if len(self.endings) != 0: + Trace.error('Pending ' + unicode(self) + ' left open') + + def __unicode__(self): + "Printable representation" + string = 'endings [' + for ending in self.endings: + string += unicode(ending) + ',' + if len(self.endings) > 0: + string = string[:-1] + return string + ']' + +class PositionEnding(object): + "An ending for a parsing position" + + def __init__(self, ending, optional): + self.ending = ending + self.optional = optional + + def checkin(self, pos): + "Check for the ending" + return pos.checkfor(self.ending) + + def __unicode__(self): + "Printable representation" + string = 'Ending ' + self.ending + if self.optional: + string += ' (optional)' + return string + + + +class Position(Globable): + """A position in a text to parse. + Including those in Globable, functions to implement by subclasses are: + skip(), identifier(), extract(), isout() and current().""" + + def __init__(self): + Globable.__init__(self) + + def skip(self, string): + "Skip a string" + Trace.error('Unimplemented skip()') + + def identifier(self): + "Return an identifier for the current position." + Trace.error('Unimplemented identifier()') + return 'Error' + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text," + "without advancing the parse position." + Trace.error('Unimplemented extract()') + return None + + def checkfor(self, string): + "Check for a string at the given position." + return string == self.extract(len(string)) + + def checkforlower(self, string): + "Check for a string in lower case." + extracted = self.extract(len(string)) + if not extracted: + return False + return string.lower() == self.extract(len(string)).lower() + + def skipcurrent(self): + "Return the current character and skip it." + current = self.current() + self.skip(current) + return current + + def next(self): + "Advance the position and return the next character." + self.skipcurrent() + return self.current() + + def checkskip(self, string): + "Check for a string at the given position; if there, skip it" + if not self.checkfor(string): + return False + self.skip(string) + return True + + def error(self, message): + "Show an error message and the position identifier." + Trace.error(message + ': ' + self.identifier()) + +class TextPosition(Position): + "A parse position based on a raw text." + + def __init__(self, text): + "Create the position from elyxer.some text." + Position.__init__(self) + self.pos = 0 + self.text = text + self.checkbytemark() + + def skip(self, string): + "Skip a string of characters." + self.pos += len(string) + + def identifier(self): + "Return a sample of the remaining text." + length = 30 + if self.pos + length > len(self.text): + length = len(self.text) - self.pos + return '*' + self.text[self.pos:self.pos + length] + '*' + + def isout(self): + "Find out if we are out of the text yet." + return self.pos >= len(self.text) + + def current(self): + "Return the current character, assuming we are not out." + return self.text[self.pos] + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text." + if self.pos + length > len(self.text): + return None + return self.text[self.pos : self.pos + length] + +class FilePosition(Position): + "A parse position based on an underlying file." + + def __init__(self, filename): + "Create the position from a file." + Position.__init__(self) + self.reader = LineReader(filename) + self.pos = 0 + self.checkbytemark() + + def skip(self, string): + "Skip a string of characters." + length = len(string) + while self.pos + length > len(self.reader.currentline()): + length -= len(self.reader.currentline()) - self.pos + 1 + self.nextline() + self.pos += length + + def currentline(self): + "Get the current line of the underlying file." + return self.reader.currentline() + + def nextline(self): + "Go to the next line." + self.reader.nextline() + self.pos = 0 + + def linenumber(self): + "Return the line number of the file." + return self.reader.linenumber + 1 + + def identifier(self): + "Return the current line and line number in the file." + before = self.reader.currentline()[:self.pos - 1] + after = self.reader.currentline()[self.pos:] + return 'line ' + unicode(self.getlinenumber()) + ': ' + before + '*' + after + + def isout(self): + "Find out if we are out of the text yet." + if self.pos > len(self.reader.currentline()): + if self.pos > len(self.reader.currentline()) + 1: + Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos)) + self.nextline() + return self.reader.finished() + + def current(self): + "Return the current character, assuming we are not out." + if self.pos == len(self.reader.currentline()): + return '\n' + if self.pos > len(self.reader.currentline()): + Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos)) + return '*' + return self.reader.currentline()[self.pos] + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text." + if self.pos + length > len(self.reader.currentline()): + return None + return self.reader.currentline()[self.pos : self.pos + length] + + + +files = list() + +def getreader(filename): + "Get a reader for lines" + if filename in files: + # already parsed; skip + return None + files.append(filename) + return LineReader(filename) + +def readargs(args): + "Read arguments from the command line" + del args[0] + if len(args) == 0: + usage() + return None, None + if args[0] == '-h' or args[0] == '--help': + usage() + return None, None + reader = getreader(args[0]) + del args[0] + fileout = sys.stdout + if len(args) > 0: + fileout = args[0] + del args[0] + if len(args) > 0: + usage() + return + writer = LineWriter(fileout) + return reader, writer + +def usage(): + "Show command line help." + Trace.error('Usage: loremipsumize.py filein [fileout]') + Trace.error('Mask your document using nonsensical words (Lorem Ipsum).') + Trace.error('Part of the eLyXer package (http://elyxer.nongnu.org/).') + Trace.error(' Options:') + Trace.error(' --help: show this message and quit.') + return + +class LoremIpsumizer(object): + + starts = '@\\' + + def loremipsumize(self, reader, writer): + "Convert all texts longer than two words to 'lorem ipsum'." + if not reader: + return + while not reader.finished(): + line = self.processline(reader.currentline()) + writer.writeline(line) + reader.nextline() + reader.close() + + def processline(self, line): + "Process a single line and return the result." + if len(line) == 0: + return '' + if line[0] in LoremIpsumizer.starts: + return line + pos = TextPosition(line) + result = '' + while not pos.finished(): + result += self.parsepos(pos) + return result + + def parsepos(self, pos): + "Parse the current position, return the result." + if pos.current().isalpha() or pos.current().isdigit(): + alpha = pos.glob(lambda current: current.isalpha() or current.isspace() or current.isdigit()) + if len(alpha.split()) > 2: + return "lorem ipsum" + return alpha + if pos.current().isspace(): + return pos.skipspace() + return pos.skipcurrent() + +reader, writer = readargs(sys.argv) +if reader: + LoremIpsumizer().loremipsumize(reader, writer) + writer.close() + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/make elyxer-1.2.5/forks/jras-elyxer/make --- elyxer-1.2.3/forks/jras-elyxer/make 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/make 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,80 @@ +#!/bin/bash + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Alex 20090310: make script to generate "binary" + +# create executable files +cd src +./exportconfig.py py +./coalesce.py load-elyxer.py ../elyxer.py +./coalesce.py loremipsumize.py ../loremipsumize.py +./coalesce.py math2html.py ../math2html.py +./licensify.py freebsd-license ../math2html.py +cd .. +chmod 755 elyxer.py +chmod 755 loremipsumize.py +chmod 755 math2html.py + +# create CSS files +cd src +./coalesce.py css/master.css ../docs/lyx.css +./coalesce.py css/math.css ../docs/math.css +./licensify.py css/freebsd-license.css ../docs/math.css +cd .. + +# internationalize +cd src +./exportconfig.py po +cd ../po +for file in *.po; do + lang=$(basename "$file" .po) + mkdir -p locale/$lang/LC_MESSAGES + msgfmt -o locale/$lang/LC_MESSAGES/elyxer.mo $lang.po +done +cd .. + +# remove artifacts +rm -f docs/*.lyx~ +rm -f test/*.lyx~ +rm -f test/subdir/*.lyx~ + +# prepare documentation +./elyxer.py --title "eLyXer User Guide" --css "lyx.css" docs/userguide.lyx docs/userguide.html +./elyxer.py --tocfor "userguide.html" --target "contents" --css "toc.css" docs/userguide.lyx docs/userguide-toc.html +./elyxer.py --title="eLyxer Developer Guide" --css "lyx.css" docs/devguide.lyx docs/devguide.html +./elyxer.py --title=eLyXer --css "lyx.css" docs/index.lyx docs/index.html +./elyxer.py --title="eLyXer changelog" --css "lyx.css" docs/changelog.lyx docs/changelog.html +./elyxer.py --title="eLyxer Math Showcase (non-Unicode edition)" --css "lyx.css" docs/math.lyx docs/math.html +./elyxer.py --title="eLyxer Math Showcase (Unicode edition)" --unicode --css "lyx.css" docs/math.lyx docs/math-unicode.html +./elyxer.py --title="eLyxer Math Showcase (ISO-8859-15 edition)" --iso885915 --css "lyx.css" docs/math.lyx docs/math-iso885915.html +./elyxer.py --title="eLyxer Math Showcase (HTML edition)" --html --css "lyx.css" docs/math.lyx docs/math-html.html +./elyxer.py --title="eLyxer Math Showcase (MathJax remote edition)" --mathjax remote --css "lyx.css" docs/math.lyx docs/math-mathjax.html +./elyxer.py --title="eLyxer Math Showcase (MathJax local edition)" --mathjax "./MathJax" --css "lyx.css" docs/math.lyx docs/math-mathjax-local.html +./elyxer.py --title="eLyxer Math Showcase (Google Charts edition)" --googlecharts --css "lyx.css" docs/math.lyx docs/math-googlecharts.html + +# insert current version +VERSION=$(./elyxer.py --hardversion) +DATE=$(./elyxer.py --versiondate) +cd src +./textchange.py "the latest version" "the latest version $VERSION, created on $DATE," ../docs/index.html +cd .. + +# run the test suite +./run-tests + diff -Nru elyxer-1.2.3/forks/jras-elyxer/math2html.py elyxer-1.2.5/forks/jras-elyxer/math2html.py --- elyxer-1.2.3/forks/jras-elyxer/math2html.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/math2html.py 2013-03-10 10:39:36.000000000 +0000 @@ -0,0 +1,5365 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# math2html: convert LaTeX equations to HTML output. +# +# Copyright (C) 2009-2011 Alex Fernández +# +# Released under the terms of the `2-Clause BSD license'_, in short: +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +# This file is offered as-is, without any warranty. +# +# .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause + +# Based on eLyXer: convert LyX source files to HTML output. +# http://elyxer.nongnu.org/ + +# --end-- +# Alex 20101110 +# eLyXer standalone formula conversion to HTML. + + + + +import sys + +class Trace(object): + "A tracing class" + + debugmode = False + quietmode = False + showlinesmode = False + + prefix = None + + def debug(cls, message): + "Show a debug message" + if not Trace.debugmode or Trace.quietmode: + return + Trace.show(message, sys.stdout) + + def message(cls, message): + "Show a trace message" + if Trace.quietmode: + return + if Trace.prefix and Trace.showlinesmode: + message = Trace.prefix + message + Trace.show(message, sys.stdout) + + def error(cls, message): + "Show an error message" + message = '* ' + message + if Trace.prefix and Trace.showlinesmode: + message = Trace.prefix + message + Trace.show(message, sys.stderr) + + def fatal(cls, message): + "Show an error message and terminate" + Trace.error('FATAL: ' + message) + exit(-1) + + def show(cls, message, channel): + "Show a message out of a channel" + if sys.version_info < (3,0): + message = message.encode('utf-8') + channel.write(message + '\n') + + debug = classmethod(debug) + message = classmethod(message) + error = classmethod(error) + fatal = classmethod(fatal) + show = classmethod(show) + + + + +import os.path +import sys + + +class BibStylesConfig(object): + "Configuration class from elyxer.config file" + + abbrvnat = { + + u'@article':u'$authors. $title. $journal,{ {$volume:}$pages,} $month $year.{ doi: $doi.}{ URL $url.}{ $note.}', + u'cite':u'$surname($year)', + u'default':u'$authors. $title. $publisher, $year.{ URL $url.}{ $note.}', + } + + alpha = { + + u'@article':u'$authors. $title.{ $journal{, {$volume}{($number)}}{: $pages}{, $year}.}{ $url.}{ $filename.}{ $note.}', + u'cite':u'$Sur$YY', + u'default':u'$authors. $title.{ $journal,} $year.{ $url.}{ $filename.}{ $note.}', + } + + authordate2 = { + + u'@article':u'$authors. $year. $title. $journal, $volume($number), $pages.{ URL $url.}{ $note.}', + u'@book':u'$authors. $year. $title. $publisher.{ URL $url.}{ $note.}', + u'cite':u'$surname, $year', + u'default':u'$authors. $year. $title. $publisher.{ URL $url.}{ $note.}', + } + + default = { + + u'@article':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@book':u'{$authors: }$title{ ($editor, ed.)}.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@booklet':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@conference':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@inbook':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@incollection':u'$authors: $title{ in $booktitle{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@inproceedings':u'$authors: “$title”, $booktitle,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@manual':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@mastersthesis':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@misc':u'$authors: $title.{{ $publisher,}{ $howpublished,} $year.}{ URL $url.}{ $note.}', + u'@phdthesis':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + u'@proceedings':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@techreport':u'$authors: $title, $year.{ URL $url.}{ $note.}', + u'@unpublished':u'$authors: “$title”, $journal, $year.{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + } + + defaulttags = { + u'YY':u'??', u'authors':u'', u'surname':u'', + } + + ieeetr = { + + u'@article':u'$authors, “$title”, $journal, vol. $volume, no. $number, pp. $pages, $year.{ URL $url.}{ $note.}', + u'@book':u'$authors, $title. $publisher, $year.{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors, “$title”. $year.{ URL $url.}{ $note.}', + } + + plain = { + + u'@article':u'$authors. $title.{ $journal{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL $url.}{ $note.}', + u'@book':u'$authors. $title. $publisher,{ $month} $year.{ URL $url.}{ $note.}', + u'@incollection':u'$authors. $title.{ In $booktitle {($editor, ed.)}.} $publisher,{ $month} $year.{ URL $url.}{ $note.}', + u'@inproceedings':u'$authors. $title. { $booktitle{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL $url.}{ $note.}', + u'cite':u'$index', + u'default':u'{$authors. }$title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', + } + + vancouver = { + + u'@article':u'$authors. $title. $journal, $year{;{$volume}{($number)}{:$pages}}.{ URL: $url.}{ $note.}', + u'@book':u'$authors. $title. {$publisher, }$year.{ URL: $url.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors. $title; {$publisher, }$year.{ $howpublished.}{ URL: $url.}{ $note.}', + } + +class BibTeXConfig(object): + "Configuration class from elyxer.config file" + + replaced = { + u'--':u'—', u'..':u'.', + } + +class ContainerConfig(object): + "Configuration class from elyxer.config file" + + endings = { + u'Align':u'\\end_layout', u'BarredText':u'\\bar', + u'BoldText':u'\\series', u'Cell':u'':u'>', + } + + html = { + u'/>':u'>', + } + + iso885915 = { + u' ':u' ', u' ':u' ', u' ':u' ', + } + + nonunicode = { + u' ':u' ', + } + +class FormulaConfig(object): + "Configuration class from elyxer.config file" + + alphacommands = { + u'\\AA':u'Å', u'\\AE':u'Æ', + u'\\AmS':u'AmS', u'\\Angstroem':u'Å', + u'\\DH':u'Ð', u'\\Koppa':u'Ϟ', u'\\L':u'Ł', u'\\Micro':u'µ', u'\\O':u'Ø', + u'\\OE':u'Œ', u'\\Sampi':u'Ϡ', u'\\Stigma':u'Ϛ', u'\\TH':u'Þ', + u'\\aa':u'å', u'\\ae':u'æ', u'\\alpha':u'α', u'\\beta':u'β', + u'\\delta':u'δ', u'\\dh':u'ð', u'\\digamma':u'ϝ', u'\\epsilon':u'ϵ', + u'\\eta':u'η', u'\\eth':u'ð', u'\\gamma':u'γ', u'\\i':u'ı', + u'\\imath':u'ı', u'\\iota':u'ι', u'\\j':u'ȷ', u'\\jmath':u'ȷ', + u'\\kappa':u'κ', u'\\koppa':u'ϟ', u'\\l':u'ł', u'\\lambda':u'λ', + u'\\mu':u'μ', u'\\nu':u'ν', u'\\o':u'ø', u'\\oe':u'œ', u'\\omega':u'ω', + u'\\phi':u'φ', u'\\pi':u'π', u'\\psi':u'ψ', u'\\rho':u'ρ', + u'\\sampi':u'ϡ', u'\\sigma':u'σ', u'\\ss':u'ß', u'\\stigma':u'ϛ', + u'\\tau':u'τ', u'\\tcohm':u'Ω', u'\\textcrh':u'ħ', u'\\th':u'þ', + u'\\theta':u'θ', u'\\upsilon':u'υ', u'\\varDelta':u'∆', + u'\\varGamma':u'Γ', u'\\varLambda':u'Λ', u'\\varOmega':u'Ω', + u'\\varPhi':u'Φ', u'\\varPi':u'Π', u'\\varPsi':u'Ψ', u'\\varSigma':u'Σ', + u'\\varTheta':u'Θ', u'\\varUpsilon':u'Υ', u'\\varXi':u'Ξ', + u'\\varbeta':u'ϐ', u'\\varepsilon':u'ε', u'\\varkappa':u'ϰ', + u'\\varphi':u'φ', u'\\varpi':u'ϖ', u'\\varrho':u'ϱ', u'\\varsigma':u'ς', + u'\\vartheta':u'ϑ', u'\\xi':u'ξ', u'\\zeta':u'ζ', + } + + array = { + u'begin':u'\\begin', u'cellseparator':u'&', u'end':u'\\end', + u'rowseparator':u'\\\\', + } + + bigbrackets = { + u'(':[u'⎛',u'⎜',u'⎝',], u')':[u'⎞',u'⎟',u'⎠',], u'[':[u'⎡',u'⎢',u'⎣',], + u']':[u'⎤',u'⎥',u'⎦',], u'{':[u'⎧',u'⎪',u'⎨',u'⎩',], u'|':[u'|',], + u'}':[u'⎫',u'⎪',u'⎬',u'⎭',], u'∥':[u'∥',], + } + + bigsymbols = { + u'∑':[u'⎲',u'⎳',], u'∫':[u'⌠',u'⌡',], + } + + bracketcommands = { + u'\\left':u'span class="symbol"', + u'\\left.':u'', + u'\\middle':u'span class="symbol"', u'\\right':u'span class="symbol"', + u'\\right.':u'', + } + + combiningfunctions = { + u'\\"':u'̈', u'\\\'':u'́', u'\\^':u'̂', u'\\`':u'̀', u'\\acute':u'́', + u'\\bar':u'̄', u'\\breve':u'̆', u'\\c':u'̧', u'\\check':u'̌', + u'\\dddot':u'⃛', u'\\ddot':u'̈', u'\\dot':u'̇', u'\\grave':u'̀', + u'\\hat':u'̂', u'\\mathring':u'̊', u'\\overleftarrow':u'⃖', + u'\\overrightarrow':u'⃗', u'\\r':u'̊', u'\\s':u'̩', + u'\\textcircled':u'⃝', u'\\textsubring':u'̥', u'\\tilde':u'̃', + u'\\v':u'̌', u'\\vec':u'⃗', u'\\~':u'̃', + } + + commands = { + u'\\ ':u' ', u'\\!':u'', u'\\#':u'#', u'\\$':u'$', u'\\%':u'%', + u'\\&':u'&', u'\\,':u' ', u'\\:':u' ', u'\\;':u' ', u'\\AC':u'∿', + u'\\APLcomment':u'⍝', u'\\APLdownarrowbox':u'⍗', u'\\APLinput':u'⍞', + u'\\APLinv':u'⌹', u'\\APLleftarrowbox':u'⍇', u'\\APLlog':u'⍟', + u'\\APLrightarrowbox':u'⍈', u'\\APLuparrowbox':u'⍐', u'\\Box':u'□', + u'\\Bumpeq':u'≎', u'\\CIRCLE':u'●', u'\\Cap':u'⋒', + u'\\CapitalDifferentialD':u'ⅅ', u'\\CheckedBox':u'☑', u'\\Circle':u'○', + u'\\Coloneqq':u'⩴', u'\\ComplexI':u'ⅈ', u'\\ComplexJ':u'ⅉ', + u'\\Corresponds':u'≙', u'\\Cup':u'⋓', u'\\Delta':u'Δ', u'\\Diamond':u'◇', + u'\\Diamondblack':u'◆', u'\\Diamonddot':u'⟐', u'\\DifferentialD':u'ⅆ', + u'\\Downarrow':u'⇓', u'\\EUR':u'€', u'\\Euler':u'ℇ', + u'\\ExponetialE':u'ⅇ', u'\\Finv':u'Ⅎ', u'\\Game':u'⅁', u'\\Gamma':u'Γ', + u'\\Im':u'ℑ', u'\\Join':u'⨝', u'\\LEFTCIRCLE':u'◖', u'\\LEFTcircle':u'◐', + u'\\LHD':u'◀', u'\\Lambda':u'Λ', u'\\Lbag':u'⟅', u'\\Leftarrow':u'⇐', + u'\\Lleftarrow':u'⇚', u'\\Longleftarrow':u'⟸', + u'\\Longleftrightarrow':u'⟺', u'\\Longrightarrow':u'⟹', u'\\Lparen':u'⦅', + u'\\Lsh':u'↰', u'\\Mapsfrom':u'⇐|', u'\\Mapsto':u'|⇒', u'\\Omega':u'Ω', + u'\\P':u'¶', u'\\Phi':u'Φ', u'\\Pi':u'Π', u'\\Pr':u'Pr', u'\\Psi':u'Ψ', + u'\\Qoppa':u'Ϙ', u'\\RHD':u'▶', u'\\RIGHTCIRCLE':u'◗', + u'\\RIGHTcircle':u'◑', u'\\Rbag':u'⟆', u'\\Re':u'ℜ', u'\\Rparen':u'⦆', + u'\\Rrightarrow':u'⇛', u'\\Rsh':u'↱', u'\\S':u'§', u'\\Sigma':u'Σ', + u'\\Square':u'☐', u'\\Subset':u'⋐', u'\\Sun':u'☉', u'\\Supset':u'⋑', + u'\\Theta':u'Θ', u'\\Uparrow':u'⇑', u'\\Updownarrow':u'⇕', + u'\\Upsilon':u'Υ', u'\\Vdash':u'⊩', u'\\Vert':u'∥', u'\\Vvdash':u'⊪', + u'\\XBox':u'☒', u'\\Xi':u'Ξ', u'\\Yup':u'⅄', u'\\\\':u'
      ', + u'\\_':u'_', u'\\aleph':u'ℵ', u'\\amalg':u'∐', u'\\anchor':u'⚓', + u'\\angle':u'∠', u'\\aquarius':u'♒', u'\\arccos':u'arccos', + u'\\arcsin':u'arcsin', u'\\arctan':u'arctan', u'\\arg':u'arg', + u'\\aries':u'♈', u'\\arrowbullet':u'➢', u'\\ast':u'∗', u'\\asymp':u'≍', + u'\\backepsilon':u'∍', u'\\backprime':u'‵', u'\\backsimeq':u'⋍', + u'\\backslash':u'\\', u'\\ballotx':u'✗', u'\\barwedge':u'⊼', + u'\\because':u'∵', u'\\beth':u'ℶ', u'\\between':u'≬', u'\\bigcap':u'∩', + u'\\bigcirc':u'○', u'\\bigcup':u'∪', u'\\bigodot':u'⊙', + u'\\bigoplus':u'⊕', u'\\bigotimes':u'⊗', u'\\bigsqcup':u'⊔', + u'\\bigstar':u'★', u'\\bigtriangledown':u'▽', u'\\bigtriangleup':u'△', + u'\\biguplus':u'⊎', u'\\bigvee':u'∨', u'\\bigwedge':u'∧', + u'\\biohazard':u'☣', u'\\blacklozenge':u'⧫', u'\\blacksmiley':u'☻', + u'\\blacksquare':u'■', u'\\blacktriangle':u'▲', + u'\\blacktriangledown':u'▼', u'\\blacktriangleleft':u'◂', + u'\\blacktriangleright':u'▶', u'\\blacktriangleup':u'▴', u'\\bot':u'⊥', + u'\\bowtie':u'⋈', u'\\box':u'▫', u'\\boxast':u'⧆', u'\\boxbar':u'◫', + u'\\boxbox':u'⧈', u'\\boxbslash':u'⧅', u'\\boxcircle':u'⧇', + u'\\boxdot':u'⊡', u'\\boxminus':u'⊟', u'\\boxplus':u'⊞', + u'\\boxslash':u'⧄', u'\\boxtimes':u'⊠', u'\\bullet':u'•', + u'\\bumpeq':u'≏', u'\\cancer':u'♋', u'\\cap':u'∩', u'\\capricornus':u'♑', + u'\\cat':u'⁀', u'\\cdot':u'⋅', u'\\cdots':u'⋯', u'\\cent':u'¢', + u'\\centerdot':u'∙', u'\\checkmark':u'✓', u'\\chi':u'χ', u'\\circ':u'○', + u'\\circeq':u'≗', u'\\circlearrowleft':u'↺', u'\\circlearrowright':u'↻', + u'\\circledR':u'®', u'\\circledast':u'⊛', u'\\circledbslash':u'⦸', + u'\\circledcirc':u'⊚', u'\\circleddash':u'⊝', u'\\circledgtr':u'⧁', + u'\\circledless':u'⧀', u'\\clubsuit':u'♣', u'\\coloneqq':u'≔', + u'\\complement':u'∁', u'\\cong':u'≅', u'\\coprod':u'∐', + u'\\copyright':u'©', u'\\cos':u'cos', u'\\cosh':u'cosh', u'\\cot':u'cot', + u'\\coth':u'coth', u'\\csc':u'csc', u'\\cup':u'∪', u'\\curlyvee':u'⋎', + u'\\curlywedge':u'⋏', u'\\curvearrowleft':u'↶', + u'\\curvearrowright':u'↷', u'\\dag':u'†', u'\\dagger':u'†', + u'\\daleth':u'ℸ', u'\\dashleftarrow':u'⇠', u'\\dashv':u'⊣', + u'\\ddag':u'‡', u'\\ddagger':u'‡', u'\\ddots':u'⋱', u'\\deg':u'deg', + u'\\det':u'det', u'\\diagdown':u'╲', u'\\diagup':u'╱', + u'\\diameter':u'⌀', u'\\diamond':u'◇', u'\\diamondsuit':u'♦', + u'\\dim':u'dim', u'\\div':u'÷', u'\\divideontimes':u'⋇', + u'\\dotdiv':u'∸', u'\\doteq':u'≐', u'\\doteqdot':u'≑', u'\\dotplus':u'∔', + u'\\dots':u'…', u'\\doublebarwedge':u'⌆', u'\\downarrow':u'↓', + u'\\downdownarrows':u'⇊', u'\\downharpoonleft':u'⇃', + u'\\downharpoonright':u'⇂', u'\\dsub':u'⩤', u'\\earth':u'♁', + u'\\eighthnote':u'♪', u'\\ell':u'ℓ', u'\\emptyset':u'∅', + u'\\eqcirc':u'≖', u'\\eqcolon':u'≕', u'\\eqsim':u'≂', u'\\euro':u'€', + u'\\exists':u'∃', u'\\exp':u'exp', u'\\fallingdotseq':u'≒', + u'\\fcmp':u'⨾', u'\\female':u'♀', u'\\flat':u'♭', u'\\forall':u'∀', + u'\\fourth':u'⁗', u'\\frown':u'⌢', u'\\frownie':u'☹', u'\\gcd':u'gcd', + u'\\gemini':u'♊', u'\\geq)':u'≥', u'\\geqq':u'≧', u'\\geqslant':u'≥', + u'\\gets':u'←', u'\\gg':u'≫', u'\\ggg':u'⋙', u'\\gimel':u'ℷ', + u'\\gneqq':u'≩', u'\\gnsim':u'⋧', u'\\gtrdot':u'⋗', u'\\gtreqless':u'⋚', + u'\\gtreqqless':u'⪌', u'\\gtrless':u'≷', u'\\gtrsim':u'≳', + u'\\guillemotleft':u'«', u'\\guillemotright':u'»', u'\\hbar':u'ℏ', + u'\\heartsuit':u'♥', u'\\hfill':u' ', + u'\\hom':u'hom', u'\\hookleftarrow':u'↩', u'\\hookrightarrow':u'↪', + u'\\hslash':u'ℏ', u'\\idotsint':u'∫⋯∫', + u'\\iiint':u'', + u'\\iint':u'', u'\\imath':u'ı', + u'\\inf':u'inf', u'\\infty':u'∞', u'\\intercal':u'⊺', + u'\\interleave':u'⫴', u'\\invamp':u'⅋', u'\\invneg':u'⌐', + u'\\jmath':u'ȷ', u'\\jupiter':u'♃', u'\\ker':u'ker', u'\\land':u'∧', + u'\\landupint':u'', u'\\lang':u'⟪', + u'\\langle':u'⟨', u'\\lblot':u'⦉', u'\\lbrace':u'{', u'\\lbrace)':u'{', + u'\\lbrack':u'[', u'\\lceil':u'⌈', u'\\ldots':u'…', u'\\leadsto':u'⇝', + u'\\leftarrow)':u'←', u'\\leftarrowtail':u'↢', u'\\leftarrowtobar':u'⇤', + u'\\leftharpoondown':u'↽', u'\\leftharpoonup':u'↼', + u'\\leftleftarrows':u'⇇', u'\\leftleftharpoons':u'⥢', u'\\leftmoon':u'☾', + u'\\leftrightarrow':u'↔', u'\\leftrightarrows':u'⇆', + u'\\leftrightharpoons':u'⇋', u'\\leftthreetimes':u'⋋', u'\\leo':u'♌', + u'\\leq)':u'≤', u'\\leqq':u'≦', u'\\leqslant':u'≤', u'\\lessdot':u'⋖', + u'\\lesseqgtr':u'⋛', u'\\lesseqqgtr':u'⪋', u'\\lessgtr':u'≶', + u'\\lesssim':u'≲', u'\\lfloor':u'⌊', u'\\lg':u'lg', u'\\lgroup':u'⟮', + u'\\lhd':u'⊲', u'\\libra':u'♎', u'\\lightning':u'↯', u'\\limg':u'⦇', + u'\\liminf':u'liminf', u'\\limsup':u'limsup', u'\\ll':u'≪', + u'\\llbracket':u'⟦', u'\\llcorner':u'⌞', u'\\lll':u'⋘', u'\\ln':u'ln', + u'\\lneqq':u'≨', u'\\lnot':u'¬', u'\\lnsim':u'⋦', u'\\log':u'log', + u'\\longleftarrow':u'⟵', u'\\longleftrightarrow':u'⟷', + u'\\longmapsto':u'⟼', u'\\longrightarrow':u'⟶', u'\\looparrowleft':u'↫', + u'\\looparrowright':u'↬', u'\\lor':u'∨', u'\\lozenge':u'◊', + u'\\lrcorner':u'⌟', u'\\ltimes':u'⋉', u'\\lyxlock':u'', u'\\male':u'♂', + u'\\maltese':u'✠', u'\\mapsfrom':u'↤', u'\\mapsto':u'↦', + u'\\mathcircumflex':u'^', u'\\max':u'max', u'\\measuredangle':u'∡', + u'\\medbullet':u'⚫', u'\\medcirc':u'⚪', u'\\mercury':u'☿', u'\\mho':u'℧', + u'\\mid':u'∣', u'\\min':u'min', u'\\models':u'⊨', u'\\mp':u'∓', + u'\\multimap':u'⊸', u'\\nLeftarrow':u'⇍', u'\\nLeftrightarrow':u'⇎', + u'\\nRightarrow':u'⇏', u'\\nVDash':u'⊯', u'\\nabla':u'∇', + u'\\napprox':u'≉', u'\\natural':u'♮', u'\\ncong':u'≇', u'\\nearrow':u'↗', + u'\\neg':u'¬', u'\\neg)':u'¬', u'\\neptune':u'♆', u'\\nequiv':u'≢', + u'\\newline':u'
      ', u'\\nexists':u'∄', u'\\ngeqslant':u'≱', + u'\\ngtr':u'≯', u'\\ngtrless':u'≹', u'\\ni':u'∋', u'\\ni)':u'∋', + u'\\nleftarrow':u'↚', u'\\nleftrightarrow':u'↮', u'\\nleqslant':u'≰', + u'\\nless':u'≮', u'\\nlessgtr':u'≸', u'\\nmid':u'∤', u'\\nolimits':u'', + u'\\nonumber':u'', u'\\not':u'¬', u'\\not<':u'≮', u'\\not=':u'≠', + u'\\not>':u'≯', u'\\notbackslash':u'⍀', u'\\notin':u'∉', u'\\notni':u'∌', + u'\\notslash':u'⌿', u'\\nparallel':u'∦', u'\\nprec':u'⊀', + u'\\nrightarrow':u'↛', u'\\nsim':u'≁', u'\\nsimeq':u'≄', + u'\\nsqsubset':u'⊏̸', u'\\nsubseteq':u'⊈', u'\\nsucc':u'⊁', + u'\\nsucccurlyeq':u'⋡', u'\\nsupset':u'⊅', u'\\nsupseteq':u'⊉', + u'\\ntriangleleft':u'⋪', u'\\ntrianglelefteq':u'⋬', + u'\\ntriangleright':u'⋫', u'\\ntrianglerighteq':u'⋭', u'\\nvDash':u'⊭', + u'\\nvdash':u'⊬', u'\\nwarrow':u'↖', u'\\odot':u'⊙', + u'\\officialeuro':u'€', u'\\oiiint':u'', + u'\\oiint':u'', + u'\\oint':u'', + u'\\ointclockwise':u'', + u'\\ointctrclockwise':u'', + u'\\ominus':u'⊖', u'\\oplus':u'⊕', u'\\oslash':u'⊘', u'\\otimes':u'⊗', + u'\\owns':u'∋', u'\\parallel':u'∥', u'\\partial':u'∂', u'\\pencil':u'✎', + u'\\perp':u'⊥', u'\\pisces':u'♓', u'\\pitchfork':u'⋔', u'\\pluto':u'♇', + u'\\pm':u'±', u'\\pointer':u'➪', u'\\pointright':u'☞', u'\\pounds':u'£', + u'\\prec':u'≺', u'\\preccurlyeq':u'≼', u'\\preceq':u'≼', + u'\\precsim':u'≾', u'\\prime':u'′', u'\\prompto':u'∝', u'\\qoppa':u'ϙ', + u'\\qquad':u' ', u'\\quad':u' ', u'\\quarternote':u'♩', + u'\\radiation':u'☢', u'\\rang':u'⟫', u'\\rangle':u'⟩', u'\\rblot':u'⦊', + u'\\rbrace':u'}', u'\\rbrace)':u'}', u'\\rbrack':u']', u'\\rceil':u'⌉', + u'\\recycle':u'♻', u'\\rfloor':u'⌋', u'\\rgroup':u'⟯', u'\\rhd':u'⊳', + u'\\rightangle':u'∟', u'\\rightarrow)':u'→', u'\\rightarrowtail':u'↣', + u'\\rightarrowtobar':u'⇥', u'\\rightharpoondown':u'⇁', + u'\\rightharpoonup':u'⇀', u'\\rightharpooondown':u'⇁', + u'\\rightharpooonup':u'⇀', u'\\rightleftarrows':u'⇄', + u'\\rightleftharpoons':u'⇌', u'\\rightmoon':u'☽', + u'\\rightrightarrows':u'⇉', u'\\rightrightharpoons':u'⥤', + u'\\rightthreetimes':u'⋌', u'\\rimg':u'⦈', u'\\risingdotseq':u'≓', + u'\\rrbracket':u'⟧', u'\\rsub':u'⩥', u'\\rtimes':u'⋊', + u'\\sagittarius':u'♐', u'\\saturn':u'♄', u'\\scorpio':u'♏', + u'\\searrow':u'↘', u'\\sec':u'sec', u'\\second':u'″', u'\\setminus':u'∖', + u'\\sharp':u'♯', u'\\simeq':u'≃', u'\\sin':u'sin', u'\\sinh':u'sinh', + u'\\sixteenthnote':u'♬', u'\\skull':u'☠', u'\\slash':u'∕', + u'\\smallsetminus':u'∖', u'\\smalltriangledown':u'▿', + u'\\smalltriangleleft':u'◃', u'\\smalltriangleright':u'▹', + u'\\smalltriangleup':u'▵', u'\\smile':u'⌣', u'\\smiley':u'☺', + u'\\spadesuit':u'♠', u'\\spddot':u'¨', u'\\sphat':u'', + u'\\sphericalangle':u'∢', u'\\spot':u'⦁', u'\\sptilde':u'~', + u'\\sqcap':u'⊓', u'\\sqcup':u'⊔', u'\\sqsubset':u'⊏', + u'\\sqsubseteq':u'⊑', u'\\sqsupset':u'⊐', u'\\sqsupseteq':u'⊒', + u'\\square':u'□', u'\\sslash':u'⫽', u'\\star':u'⋆', u'\\steaming':u'☕', + u'\\subseteqq':u'⫅', u'\\subsetneqq':u'⫋', u'\\succ':u'≻', + u'\\succcurlyeq':u'≽', u'\\succeq':u'≽', u'\\succnsim':u'⋩', + u'\\succsim':u'≿', u'\\sun':u'☼', u'\\sup':u'sup', u'\\supseteqq':u'⫆', + u'\\supsetneqq':u'⫌', u'\\surd':u'√', u'\\swarrow':u'↙', + u'\\swords':u'⚔', u'\\talloblong':u'⫾', u'\\tan':u'tan', + u'\\tanh':u'tanh', u'\\taurus':u'♉', u'\\textasciicircum':u'^', + u'\\textasciitilde':u'~', u'\\textbackslash':u'\\', + u'\\textcopyright':u'©\'', u'\\textdegree':u'°', u'\\textellipsis':u'…', + u'\\textemdash':u'—', u'\\textendash':u'—', u'\\texteuro':u'€', + u'\\textgreater':u'>', u'\\textless':u'<', u'\\textordfeminine':u'ª', + u'\\textordmasculine':u'º', u'\\textquotedblleft':u'“', + u'\\textquotedblright':u'”', u'\\textquoteright':u'’', + u'\\textregistered':u'®', u'\\textrightarrow':u'→', + u'\\textsection':u'§', u'\\texttrademark':u'™', + u'\\texttwosuperior':u'²', u'\\textvisiblespace':u' ', + u'\\therefore':u'∴', u'\\third':u'‴', u'\\top':u'⊤', u'\\triangle':u'△', + u'\\triangleleft':u'⊲', u'\\trianglelefteq':u'⊴', u'\\triangleq':u'≜', + u'\\triangleright':u'▷', u'\\trianglerighteq':u'⊵', + u'\\twoheadleftarrow':u'↞', u'\\twoheadrightarrow':u'↠', + u'\\twonotes':u'♫', u'\\udot':u'⊍', u'\\ulcorner':u'⌜', u'\\unlhd':u'⊴', + u'\\unrhd':u'⊵', u'\\unrhl':u'⊵', u'\\uparrow':u'↑', + u'\\updownarrow':u'↕', u'\\upharpoonleft':u'↿', u'\\upharpoonright':u'↾', + u'\\uplus':u'⊎', u'\\upuparrows':u'⇈', u'\\uranus':u'♅', + u'\\urcorner':u'⌝', u'\\vDash':u'⊨', u'\\varclubsuit':u'♧', + u'\\vardiamondsuit':u'♦', u'\\varheartsuit':u'♥', u'\\varnothing':u'∅', + u'\\varspadesuit':u'♤', u'\\vdash':u'⊢', u'\\vdots':u'⋮', u'\\vee':u'∨', + u'\\vee)':u'∨', u'\\veebar':u'⊻', u'\\vert':u'∣', u'\\virgo':u'♍', + u'\\warning':u'⚠', u'\\wasylozenge':u'⌑', u'\\wedge':u'∧', + u'\\wedge)':u'∧', u'\\wp':u'℘', u'\\wr':u'≀', u'\\yen':u'¥', + u'\\yinyang':u'☯', u'\\{':u'{', u'\\|':u'∥', u'\\}':u'}', + } + + decoratedcommand = { + + } + + decoratingfunctions = { + u'\\overleftarrow':u'⟵', u'\\overrightarrow':u'⟶', u'\\widehat':u'^', + } + + endings = { + u'bracket':u'}', u'complex':u'\\]', u'endafter':u'}', + u'endbefore':u'\\end{', u'squarebracket':u']', + } + + environments = { + u'align':[u'r',u'l',], u'eqnarray':[u'r',u'c',u'l',], + u'gathered':[u'l',u'l',], + } + + fontfunctions = { + u'\\boldsymbol':u'b', u'\\mathbb':u'span class="blackboard"', + u'\\mathbb{A}':u'𝔸', u'\\mathbb{B}':u'𝔹', u'\\mathbb{C}':u'ℂ', + u'\\mathbb{D}':u'𝔻', u'\\mathbb{E}':u'𝔼', u'\\mathbb{F}':u'𝔽', + u'\\mathbb{G}':u'𝔾', u'\\mathbb{H}':u'ℍ', u'\\mathbb{J}':u'𝕁', + u'\\mathbb{K}':u'𝕂', u'\\mathbb{L}':u'𝕃', u'\\mathbb{N}':u'ℕ', + u'\\mathbb{O}':u'𝕆', u'\\mathbb{P}':u'ℙ', u'\\mathbb{Q}':u'ℚ', + u'\\mathbb{R}':u'ℝ', u'\\mathbb{S}':u'𝕊', u'\\mathbb{T}':u'𝕋', + u'\\mathbb{W}':u'𝕎', u'\\mathbb{Z}':u'ℤ', u'\\mathbf':u'b', + u'\\mathcal':u'span class="scriptfont"', u'\\mathcal{B}':u'ℬ', + u'\\mathcal{E}':u'ℰ', u'\\mathcal{F}':u'ℱ', u'\\mathcal{H}':u'ℋ', + u'\\mathcal{I}':u'ℐ', u'\\mathcal{L}':u'ℒ', u'\\mathcal{M}':u'ℳ', + u'\\mathcal{R}':u'ℛ', u'\\mathfrak':u'span class="fraktur"', + u'\\mathfrak{C}':u'ℭ', u'\\mathfrak{F}':u'𝔉', u'\\mathfrak{H}':u'ℌ', + u'\\mathfrak{I}':u'ℑ', u'\\mathfrak{R}':u'ℜ', u'\\mathfrak{Z}':u'ℨ', + u'\\mathit':u'i', u'\\mathring{A}':u'Å', u'\\mathring{U}':u'Ů', + u'\\mathring{a}':u'å', u'\\mathring{u}':u'ů', u'\\mathring{w}':u'ẘ', + u'\\mathring{y}':u'ẙ', u'\\mathrm':u'span class="mathrm"', + u'\\mathscr':u'span class="scriptfont"', u'\\mathscr{B}':u'ℬ', + u'\\mathscr{E}':u'ℰ', u'\\mathscr{F}':u'ℱ', u'\\mathscr{H}':u'ℋ', + u'\\mathscr{I}':u'ℐ', u'\\mathscr{L}':u'ℒ', u'\\mathscr{M}':u'ℳ', + u'\\mathscr{R}':u'ℛ', u'\\mathsf':u'span class="mathsf"', + u'\\mathtt':u'tt', + } + + hybridfunctions = { + u'\\addcontentsline':[u'{$p!}{$q!}{$r!}',u'f0{}',u'ignored',], + u'\\addtocontents':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\backmatter':[u'',u'f0{}',u'ignored',], + u'\\binom':[u'{$1}{$2}',u'f2{(}f0{f1{$1}f1{$2}}f2{)}',u'span class="binom"',u'span class="binomstack"',u'span class="bigsymbol"',], + u'\\boxed':[u'{$1}',u'f0{$1}',u'span class="boxed"',], + u'\\cfrac':[u'[$p!]{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator align-$p"',u'span class="denominator"',u'span class="ignored"',], + u'\\color':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], + u'\\colorbox':[u'{$p!}{$1}',u'f0{$1}',u'span class="colorbox" style="background: $p;"',], + u'\\dbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], + u'\\dfrac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], + u'\\displaystyle':[u'{$1}',u'f0{$1}',u'span class="displaystyle"',], + u'\\fancyfoot':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fancyhead':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fbox':[u'{$1}',u'f0{$1}',u'span class="fbox"',], + u'\\fboxrule':[u'{$p!}',u'f0{}',u'ignored',], + u'\\fboxsep':[u'{$p!}',u'f0{}',u'ignored',], + u'\\fcolorbox':[u'{$p!}{$q!}{$1}',u'f0{$1}',u'span class="boxed" style="border-color: $p; background: $q;"',], + u'\\frac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], + u'\\framebox':[u'[$p!][$q!]{$1}',u'f0{$1}',u'span class="framebox align-$q" style="width: $p;"',], + u'\\frontmatter':[u'',u'f0{}',u'ignored',], + u'\\href':[u'[$o]{$u!}{$t!}',u'f0{$t}',u'a href="$u"',], + u'\\hspace':[u'{$p!}',u'f0{ }',u'span class="hspace" style="width: $p;"',], + u'\\leftroot':[u'{$p!}',u'f0{ }',u'span class="leftroot" style="width: $p;px"',], + u'\\mainmatter':[u'',u'f0{}',u'ignored',], + u'\\markboth':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\markright':[u'{$p!}',u'f0{}',u'ignored',], + u'\\nicefrac':[u'{$1}{$2}',u'f0{f1{$1}⁄f2{$2}}',u'span class="fraction"',u'sup class="numerator"',u'sub class="denominator"',u'span class="ignored"',], + u'\\parbox':[u'[$p!]{$w!}{$1}',u'f0{1}',u'div class="Boxed" style="width: $w;"',], + u'\\raisebox':[u'{$p!}{$1}',u'f0{$1.font}',u'span class="raisebox" style="vertical-align: $p;"',], + u'\\renewenvironment':[u'{$1!}{$2!}{$3!}',u'',], + u'\\rule':[u'[$v!]{$w!}{$h!}',u'f0/',u'hr class="line" style="width: $w; height: $h;"',], + u'\\scriptscriptstyle':[u'{$1}',u'f0{$1}',u'span class="scriptscriptstyle"',], + u'\\scriptstyle':[u'{$1}',u'f0{$1}',u'span class="scriptstyle"',], + u'\\sqrt':[u'[$0]{$1}',u'f0{f1{$0}f2{√}f4{(}f3{$1}f4{)}}',u'span class="sqrt"',u'sup class="root"',u'span class="radical"',u'span class="root"',u'span class="ignored"',], + u'\\stackrel':[u'{$1}{$2}',u'f0{f1{$1}f2{$2}}',u'span class="stackrel"',u'span class="upstackrel"',u'span class="downstackrel"',], + u'\\tbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], + u'\\textcolor':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], + u'\\textstyle':[u'{$1}',u'f0{$1}',u'span class="textstyle"',], + u'\\thispagestyle':[u'{$p!}',u'f0{}',u'ignored',], + u'\\unit':[u'[$0]{$1}',u'$0f0{$1.font}',u'span class="unit"',], + u'\\unitfrac':[u'[$0]{$1}{$2}',u'$0f0{f1{$1.font}⁄f2{$2.font}}',u'span class="fraction"',u'sup class="unit"',u'sub class="unit"',], + u'\\uproot':[u'{$p!}',u'f0{ }',u'span class="uproot" style="width: $p;px"',], + u'\\url':[u'{$u!}',u'f0{$u}',u'a href="$u"',], + u'\\vspace':[u'{$p!}',u'f0{ }',u'span class="vspace" style="height: $p;"',], + } + + hybridsizes = { + u'\\binom':u'$1+$2', u'\\cfrac':u'$1+$2', u'\\dbinom':u'$1+$2+1', + u'\\dfrac':u'$1+$2', u'\\frac':u'$1+$2', u'\\tbinom':u'$1+$2+1', + } + + labelfunctions = { + u'\\label':u'a name="#"', + } + + limitcommands = { + u'\\biginterleave':u'⫼', u'\\bigsqcap':u'⨅', u'\\fint':u'⨏', + u'\\iiiint':u'⨌', u'\\int':u'∫', u'\\intop':u'∫', u'\\lim':u'lim', + u'\\prod':u'∏', u'\\smallint':u'∫', u'\\sqint':u'⨖', u'\\sum':u'∑', + u'\\varointclockwise':u'∲', u'\\varprod':u'⨉', u'\\zcmp':u'⨟', + u'\\zhide':u'⧹', u'\\zpipe':u'⨠', u'\\zproject':u'⨡', + } + + misccommands = { + u'\\limits':u'LimitPreviousCommand', u'\\newcommand':u'MacroDefinition', + u'\\renewcommand':u'MacroDefinition', + u'\\setcounter':u'SetCounterFunction', u'\\tag':u'FormulaTag', + u'\\tag*':u'FormulaTag', u'\\today':u'TodayCommand', + } + + modified = { + u'\n':u'', u' ':u'', u'$':u'', u'&':u' ', u'\'':u'’', u'+':u' + ', + u',':u', ', u'-':u' − ', u'/':u' ⁄ ', u'<':u' < ', u'=':u' = ', + u'>':u' > ', u'@':u'', u'~':u'', + } + + onefunctions = { + u'\\Big':u'span class="bigsymbol"', u'\\Bigg':u'span class="hugesymbol"', + u'\\bar':u'span class="bar"', u'\\begin{array}':u'span class="arraydef"', + u'\\big':u'span class="symbol"', u'\\bigg':u'span class="largesymbol"', + u'\\bigl':u'span class="bigsymbol"', u'\\bigr':u'span class="bigsymbol"', + u'\\centering':u'span class="align-center"', + u'\\ensuremath':u'span class="ensuremath"', + u'\\hphantom':u'span class="phantom"', + u'\\noindent':u'span class="noindent"', + u'\\overbrace':u'span class="overbrace"', + u'\\overline':u'span class="overline"', + u'\\phantom':u'span class="phantom"', + u'\\underbrace':u'span class="underbrace"', u'\\underline':u'u', + u'\\vphantom':u'span class="phantom"', + } + + spacedcommands = { + u'\\Bot':u'⫫', u'\\Doteq':u'≑', u'\\DownArrowBar':u'⤓', + u'\\DownLeftTeeVector':u'⥞', u'\\DownLeftVectorBar':u'⥖', + u'\\DownRightTeeVector':u'⥟', u'\\DownRightVectorBar':u'⥗', + u'\\Equal':u'⩵', u'\\LeftArrowBar':u'⇤', u'\\LeftDownTeeVector':u'⥡', + u'\\LeftDownVectorBar':u'⥙', u'\\LeftTeeVector':u'⥚', + u'\\LeftTriangleBar':u'⧏', u'\\LeftUpTeeVector':u'⥠', + u'\\LeftUpVectorBar':u'⥘', u'\\LeftVectorBar':u'⥒', + u'\\Leftrightarrow':u'⇔', u'\\Longmapsfrom':u'⟽', u'\\Longmapsto':u'⟾', + u'\\MapsDown':u'↧', u'\\MapsUp':u'↥', u'\\Nearrow':u'⇗', + u'\\NestedGreaterGreater':u'⪢', u'\\NestedLessLess':u'⪡', + u'\\NotGreaterLess':u'≹', u'\\NotGreaterTilde':u'≵', + u'\\NotLessTilde':u'≴', u'\\Nwarrow':u'⇖', u'\\Proportion':u'∷', + u'\\RightArrowBar':u'⇥', u'\\RightDownTeeVector':u'⥝', + u'\\RightDownVectorBar':u'⥕', u'\\RightTeeVector':u'⥛', + u'\\RightTriangleBar':u'⧐', u'\\RightUpTeeVector':u'⥜', + u'\\RightUpVectorBar':u'⥔', u'\\RightVectorBar':u'⥓', + u'\\Rightarrow':u'⇒', u'\\Same':u'⩶', u'\\Searrow':u'⇘', + u'\\Swarrow':u'⇙', u'\\Top':u'⫪', u'\\UpArrowBar':u'⤒', u'\\VDash':u'⊫', + u'\\approx':u'≈', u'\\approxeq':u'≊', u'\\backsim':u'∽', u'\\barin':u'⋶', + u'\\barleftharpoon':u'⥫', u'\\barrightharpoon':u'⥭', u'\\bij':u'⤖', + u'\\coloneq':u'≔', u'\\corresponds':u'≙', u'\\curlyeqprec':u'⋞', + u'\\curlyeqsucc':u'⋟', u'\\dashrightarrow':u'⇢', u'\\dlsh':u'↲', + u'\\downdownharpoons':u'⥥', u'\\downuparrows':u'⇵', + u'\\downupharpoons':u'⥯', u'\\drsh':u'↳', u'\\eqslantgtr':u'⪖', + u'\\eqslantless':u'⪕', u'\\equiv':u'≡', u'\\ffun':u'⇻', u'\\finj':u'⤕', + u'\\ge':u'≥', u'\\geq':u'≥', u'\\ggcurly':u'⪼', u'\\gnapprox':u'⪊', + u'\\gneq':u'⪈', u'\\gtrapprox':u'⪆', u'\\hash':u'⋕', u'\\iddots':u'⋰', + u'\\implies':u' ⇒ ', u'\\in':u'∈', u'\\le':u'≤', u'\\leftarrow':u'←', + u'\\leftarrowtriangle':u'⇽', u'\\leftbarharpoon':u'⥪', + u'\\leftrightarrowtriangle':u'⇿', u'\\leftrightharpoon':u'⥊', + u'\\leftrightharpoondown':u'⥐', u'\\leftrightharpoonup':u'⥎', + u'\\leftrightsquigarrow':u'↭', u'\\leftslice':u'⪦', + u'\\leftsquigarrow':u'⇜', u'\\leftupdownharpoon':u'⥑', u'\\leq':u'≤', + u'\\lessapprox':u'⪅', u'\\llcurly':u'⪻', u'\\lnapprox':u'⪉', + u'\\lneq':u'⪇', u'\\longmapsfrom':u'⟻', u'\\multimapboth':u'⧟', + u'\\multimapdotbothA':u'⊶', u'\\multimapdotbothB':u'⊷', + u'\\multimapinv':u'⟜', u'\\nVdash':u'⊮', u'\\ne':u'≠', u'\\neq':u'≠', + u'\\ngeq':u'≱', u'\\nleq':u'≰', u'\\nni':u'∌', u'\\not\\in':u'∉', + u'\\notasymp':u'≭', u'\\npreceq':u'⋠', u'\\nsqsubseteq':u'⋢', + u'\\nsqsupseteq':u'⋣', u'\\nsubset':u'⊄', u'\\nsucceq':u'⋡', + u'\\pfun':u'⇸', u'\\pinj':u'⤔', u'\\precapprox':u'⪷', u'\\preceqq':u'⪳', + u'\\precnapprox':u'⪹', u'\\precnsim':u'⋨', u'\\propto':u'∝', + u'\\psur':u'⤀', u'\\rightarrow':u'→', u'\\rightarrowtriangle':u'⇾', + u'\\rightbarharpoon':u'⥬', u'\\rightleftharpoon':u'⥋', + u'\\rightslice':u'⪧', u'\\rightsquigarrow':u'⇝', + u'\\rightupdownharpoon':u'⥏', u'\\sim':u'~', u'\\strictfi':u'⥼', + u'\\strictif':u'⥽', u'\\subset':u'⊂', u'\\subseteq':u'⊆', + u'\\subsetneq':u'⊊', u'\\succapprox':u'⪸', u'\\succeqq':u'⪴', + u'\\succnapprox':u'⪺', u'\\supset':u'⊃', u'\\supseteq':u'⊇', + u'\\supsetneq':u'⊋', u'\\times':u'×', u'\\to':u'→', + u'\\updownarrows':u'⇅', u'\\updownharpoons':u'⥮', u'\\upupharpoons':u'⥣', + u'\\vartriangleleft':u'⊲', u'\\vartriangleright':u'⊳', + } + + starts = { + u'beginafter':u'}', u'beginbefore':u'\\begin{', u'bracket':u'{', + u'command':u'\\', u'comment':u'%', u'complex':u'\\[', u'simple':u'$', + u'squarebracket':u'[', u'unnumbered':u'*', + } + + symbolfunctions = { + u'^':u'sup', u'_':u'sub', + } + + textfunctions = { + u'\\mbox':u'span class="mbox"', u'\\text':u'span class="text"', + u'\\textbf':u'b', u'\\textipa':u'span class="textipa"', u'\\textit':u'i', + u'\\textnormal':u'span class="textnormal"', + u'\\textrm':u'span class="textrm"', + u'\\textsc':u'span class="versalitas"', + u'\\textsf':u'span class="textsf"', u'\\textsl':u'i', u'\\texttt':u'tt', + u'\\textup':u'span class="normal"', + } + + unmodified = { + + u'characters':[u'.',u'*',u'€',u'(',u')',u'[',u']',u':',u'·',u'!',u';',u'|',u'§',u'"',], + } + + urls = { + u'googlecharts':u'http://chart.googleapis.com/chart?cht=tx&chl=', + } + +class GeneralConfig(object): + "Configuration class from elyxer.config file" + + version = { + u'date':u'2013-03-10', u'lyxformat':u'413', u'number':u'1.2.4', + } + +class HeaderConfig(object): + "Configuration class from elyxer.config file" + + parameters = { + u'beginpreamble':u'\\begin_preamble', u'branch':u'\\branch', + u'documentclass':u'\\textclass', u'endbranch':u'\\end_branch', + u'endpreamble':u'\\end_preamble', u'language':u'\\language', + u'lstset':u'\\lstset', u'outputchanges':u'\\output_changes', + u'paragraphseparation':u'\\paragraph_separation', + u'pdftitle':u'\\pdf_title', u'secnumdepth':u'\\secnumdepth', + u'tocdepth':u'\\tocdepth', + } + + styles = { + + u'article':[u'article',u'aastex',u'aapaper',u'acmsiggraph',u'sigplanconf',u'achemso',u'amsart',u'apa',u'arab-article',u'armenian-article',u'article-beamer',u'chess',u'dtk',u'elsarticle',u'heb-article',u'IEEEtran',u'iopart',u'kluwer',u'scrarticle-beamer',u'scrartcl',u'extarticle',u'paper',u'mwart',u'revtex4',u'spie',u'svglobal3',u'ltugboat',u'agu-dtd',u'jgrga',u'agums',u'entcs',u'egs',u'ijmpc',u'ijmpd',u'singlecol-new',u'doublecol-new',u'isprs',u'tarticle',u'jsarticle',u'jarticle',u'jss',u'literate-article',u'siamltex',u'cl2emult',u'llncs',u'svglobal',u'svjog',u'svprobth',], + u'book':[u'book',u'amsbook',u'scrbook',u'extbook',u'tufte-book',u'report',u'extreport',u'scrreprt',u'memoir',u'tbook',u'jsbook',u'jbook',u'mwbk',u'svmono',u'svmult',u'treport',u'jreport',u'mwrep',], + } + +class ImageConfig(object): + "Configuration class from elyxer.config file" + + converters = { + + u'imagemagick':u'convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output"', + u'inkscape':u'inkscape "$input" --export-png="$output"', + u'lyx':u'lyx -C "$input" "$output"', + } + + cropboxformats = { + u'.eps':u'ps', u'.pdf':u'pdf', u'.ps':u'ps', + } + + formats = { + u'default':u'.png', u'vector':[u'.svg',u'.eps',], + } + +class LayoutConfig(object): + "Configuration class from elyxer.config file" + + groupable = { + + u'allowed':[u'StringContainer',u'Constant',u'TaggedText',u'Align',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + } + +class NewfangleConfig(object): + "Configuration class from elyxer.config file" + + constants = { + u'chunkref':u'chunkref{', u'endcommand':u'}', u'endmark':u'>', + u'startcommand':u'\\', u'startmark':u'=<', + } + +class NumberingConfig(object): + "Configuration class from elyxer.config file" + + layouts = { + + u'ordered':[u'Chapter',u'Section',u'Subsection',u'Subsubsection',u'Paragraph',], + u'roman':[u'Part',u'Book',], + } + + sequence = { + u'symbols':[u'*',u'**',u'†',u'‡',u'§',u'§§',u'¶',u'¶¶',u'#',u'##',], + } + +class StyleConfig(object): + "Configuration class from elyxer.config file" + + hspaces = { + u'\\enskip{}':u' ', u'\\hfill{}':u' ', + u'\\hspace*{\\fill}':u' ', u'\\hspace*{}':u'', u'\\hspace{}':u' ', + u'\\negthinspace{}':u'', u'\\qquad{}':u'  ', u'\\quad{}':u' ', + u'\\space{}':u' ', u'\\thinspace{}':u' ', u'~':u' ', + } + + quotes = { + u'ald':u'»', u'als':u'›', u'ard':u'«', u'ars':u'‹', u'eld':u'“', + u'els':u'‘', u'erd':u'”', u'ers':u'’', u'fld':u'«', + u'fls':u'‹', u'frd':u'»', u'frs':u'›', u'gld':u'„', u'gls':u'‚', + u'grd':u'“', u'grs':u'‘', u'pld':u'„', u'pls':u'‚', u'prd':u'”', + u'prs':u'’', u'sld':u'”', u'srd':u'”', + } + + referenceformats = { + u'eqref':u'(@↕)', u'formatted':u'¶↕', u'nameref':u'$↕', u'pageref':u'#↕', + u'ref':u'@↕', u'vpageref':u'on-page#↕', u'vref':u'@on-page#↕', + } + + size = { + u'ignoredtexts':[u'col',u'text',u'line',u'page',u'theight',u'pheight',], + } + + vspaces = { + u'bigskip':u'
      ', + u'defskip':u'
      ', + u'medskip':u'
      ', + u'smallskip':u'
      ', + u'vfill':u'
      ', + } + +class TOCConfig(object): + "Configuration class from elyxer.config file" + + extractplain = { + + u'allowed':[u'StringContainer',u'Constant',u'TaggedText',u'Align',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + u'cloned':[u'',], u'extracted':[u'',], + } + + extracttitle = { + u'allowed':[u'StringContainer',u'Constant',u'Space',], + u'cloned':[u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + u'extracted':[u'PlainLayout',u'TaggedText',u'Align',u'Caption',u'StandardLayout',u'FlexInset',], + } + +class TagConfig(object): + "Configuration class from elyxer.config file" + + barred = { + u'under':u'u', + } + + family = { + u'sans':u'span class="sans"', u'typewriter':u'tt', + } + + flex = { + u'CharStyle:Code':u'span class="code"', + u'CharStyle:MenuItem':u'span class="menuitem"', + u'Code':u'span class="code"', u'MenuItem':u'span class="menuitem"', + u'Noun':u'span class="noun"', u'Strong':u'span class="strong"', + } + + group = { + u'layouts':[u'Quotation',u'Quote',], + } + + layouts = { + u'Center':u'div', u'Chapter':u'h?', u'Date':u'h2', u'Paragraph':u'div', + u'Part':u'h1', u'Quotation':u'blockquote', u'Quote':u'blockquote', + u'Section':u'h?', u'Subsection':u'h?', u'Subsubsection':u'h?', + } + + listitems = { + u'Enumerate':u'ol', u'Itemize':u'ul', + } + + notes = { + u'Comment':u'', u'Greyedout':u'span class="greyedout"', u'Note':u'', + } + + script = { + u'subscript':u'sub', u'superscript':u'sup', + } + + shaped = { + u'italic':u'i', u'slanted':u'i', u'smallcaps':u'span class="versalitas"', + } + +class TranslationConfig(object): + "Configuration class from elyxer.config file" + + constants = { + u'Appendix':u'Appendix', u'Book':u'Book', u'Chapter':u'Chapter', + u'Paragraph':u'Paragraph', u'Part':u'Part', u'Section':u'Section', + u'Subsection':u'Subsection', u'Subsubsection':u'Subsubsection', + u'abstract':u'Abstract', u'bibliography':u'Bibliography', + u'figure':u'figure', u'float-algorithm':u'Algorithm ', + u'float-figure':u'Figure ', u'float-listing':u'Listing ', + u'float-table':u'Table ', u'float-tableau':u'Tableau ', + u'footnotes':u'Footnotes', u'generated-by':u'Document generated by ', + u'generated-on':u' on ', u'index':u'Index', + u'jsmath-enable':u'Please enable JavaScript on your browser.', + u'jsmath-requires':u' requires JavaScript to correctly process the mathematics on this page. ', + u'jsmath-warning':u'Warning: ', u'list-algorithm':u'List of Algorithms', + u'list-figure':u'List of Figures', u'list-table':u'List of Tables', + u'list-tableau':u'List of Tableaux', u'main-page':u'Main page', + u'next':u'Next', u'nomenclature':u'Nomenclature', + u'on-page':u' on page ', u'prev':u'Prev', u'references':u'References', + u'toc':u'Table of Contents', u'toc-for':u'Contents for ', u'up':u'Up', + } + + languages = { + u'american':u'en', u'british':u'en', u'deutsch':u'de', u'dutch':u'nl', + u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'russian':u'ru', + u'spanish':u'es', + } + + + + + + +class CommandLineParser(object): + "A parser for runtime options" + + def __init__(self, options): + self.options = options + + def parseoptions(self, args): + "Parse command line options" + if len(args) == 0: + return None + while len(args) > 0 and args[0].startswith('--'): + key, value = self.readoption(args) + if not key: + return 'Option ' + value + ' not recognized' + if not value: + return 'Option ' + key + ' needs a value' + setattr(self.options, key, value) + return None + + def readoption(self, args): + "Read the key and value for an option" + arg = args[0][2:] + del args[0] + if '=' in arg: + key = self.readequalskey(arg, args) + else: + key = arg.replace('-', '') + if not hasattr(self.options, key): + return None, key + current = getattr(self.options, key) + if isinstance(current, bool): + return key, True + # read value + if len(args) == 0: + return key, None + if args[0].startswith('"'): + initial = args[0] + del args[0] + return key, self.readquoted(args, initial) + value = args[0].decode('utf-8') + del args[0] + if isinstance(current, list): + current.append(value) + return key, current + return key, value + + def readquoted(self, args, initial): + "Read a value between quotes" + Trace.error('Oops') + value = initial[1:] + while len(args) > 0 and not args[0].endswith('"') and not args[0].startswith('--'): + Trace.error('Appending ' + args[0]) + value += ' ' + args[0] + del args[0] + if len(args) == 0 or args[0].startswith('--'): + return None + value += ' ' + args[0:-1] + return value + + def readequalskey(self, arg, args): + "Read a key using equals" + split = arg.split('=', 1) + key = split[0] + value = split[1] + args.insert(0, value) + return key + + + +class Options(object): + "A set of runtime options" + + instance = None + + location = None + nocopy = False + copyright = False + debug = False + quiet = False + version = False + hardversion = False + versiondate = False + html = False + help = False + showlines = True + unicode = False + iso885915 = False + css = [] + title = None + directory = None + destdirectory = None + toc = False + toctarget = '' + tocfor = None + forceformat = None + lyxformat = False + target = None + splitpart = None + memory = True + lowmem = False + nobib = False + converter = 'imagemagick' + raw = False + jsmath = None + mathjax = None + nofooter = False + simplemath = False + template = None + noconvert = False + notoclabels = False + letterfoot = True + numberfoot = False + symbolfoot = False + hoverfoot = True + marginfoot = False + endfoot = False + supfoot = True + alignfoot = False + footnotes = None + imageformat = None + copyimages = False + googlecharts = False + embedcss = [] + + branches = dict() + + def parseoptions(self, args): + "Parse command line options" + Options.location = args[0] + del args[0] + parser = CommandLineParser(Options) + result = parser.parseoptions(args) + if result: + Trace.error(result) + self.usage() + self.processoptions() + + def processoptions(self): + "Process all options parsed." + if Options.help: + self.usage() + if Options.version: + self.showversion() + if Options.hardversion: + self.showhardversion() + if Options.versiondate: + self.showversiondate() + if Options.lyxformat: + self.showlyxformat() + if Options.splitpart: + try: + Options.splitpart = int(Options.splitpart) + if Options.splitpart <= 0: + Trace.error('--splitpart requires a number bigger than zero') + self.usage() + except: + Trace.error('--splitpart needs a numeric argument, not ' + Options.splitpart) + self.usage() + if Options.lowmem or Options.toc or Options.tocfor: + Options.memory = False + self.parsefootnotes() + if Options.forceformat and not Options.imageformat: + Options.imageformat = Options.forceformat + if Options.imageformat == 'copy': + Options.copyimages = True + if Options.css == []: + Options.css = ['http://elyxer.nongnu.org/lyx.css'] + if Options.html: + Options.simplemath = True + if Options.toc and not Options.tocfor: + Trace.error('Option --toc is deprecated; use --tocfor "page" instead') + Options.tocfor = Options.toctarget + if Options.nocopy: + Trace.error('Option --nocopy is deprecated; it is no longer needed') + if Options.jsmath: + Trace.error('Option --jsmath is deprecated; use --mathjax instead') + # set in Trace if necessary + for param in dir(Trace): + if param.endswith('mode'): + setattr(Trace, param, getattr(self, param[:-4])) + + def usage(self): + "Show correct usage" + Trace.error('Usage: ' + os.path.basename(Options.location) + ' [options] [filein] [fileout]') + Trace.error('Convert LyX input file "filein" to HTML file "fileout".') + Trace.error('If filein (or fileout) is not given use standard input (or output).') + Trace.error('Main program of the eLyXer package (http://elyxer.nongnu.org/).') + self.showoptions() + + def parsefootnotes(self): + "Parse footnotes options." + if not Options.footnotes: + return + Options.marginfoot = False + Options.letterfoot = False + Options.hoverfoot = False + options = Options.footnotes.split(',') + for option in options: + footoption = option + 'foot' + if hasattr(Options, footoption): + setattr(Options, footoption, True) + else: + Trace.error('Unknown footnotes option: ' + option) + if not Options.endfoot and not Options.marginfoot and not Options.hoverfoot: + Options.hoverfoot = True + if not Options.numberfoot and not Options.symbolfoot: + Options.letterfoot = True + + def showoptions(self): + "Show all possible options" + Trace.error(' Common options:') + Trace.error(' --help: show this online help') + Trace.error(' --quiet: disables all runtime messages') + Trace.error('') + Trace.error(' Advanced options:') + Trace.error(' --debug: enable debugging messages (for developers)') + Trace.error(' --version: show version number and release date') + Trace.error(' --lyxformat: return the highest LyX version supported') + Trace.error(' Options for HTML output:') + Trace.error(' --title "title": set the generated page title') + Trace.error(' --css "file.css": use a custom CSS file') + Trace.error(' --embedcss "file.css": embed styles from a CSS file into the output') + Trace.error(' --html: output HTML 4.0 instead of the default XHTML') + Trace.error(' --unicode: full Unicode output') + Trace.error(' --iso885915: output a document with ISO-8859-15 encoding') + Trace.error(' --nofooter: remove the footer "generated by eLyXer"') + Trace.error(' --simplemath: do not generate fancy math constructions') + Trace.error(' Options for image output:') + Trace.error(' --directory "img_dir": look for images in the specified directory') + Trace.error(' --destdirectory "dest": put converted images into this directory') + Trace.error(' --imageformat ".ext": image output format, or "copy" to copy images') + Trace.error(' --noconvert: do not convert images, use in original locations') + Trace.error(' --converter "inkscape": use an alternative program to convert images') + Trace.error(' Options for footnote display:') + Trace.error(' --numberfoot: mark footnotes with numbers instead of letters') + Trace.error(' --symbolfoot: mark footnotes with symbols (*, **...)') + Trace.error(' --hoverfoot: show footnotes as hovering text (default)') + Trace.error(' --marginfoot: show footnotes on the page margin') + Trace.error(' --endfoot: show footnotes at the end of the page') + Trace.error(' --supfoot: use superscript for footnote markers (default)') + Trace.error(' --alignfoot: use aligned text for footnote markers') + Trace.error(' --footnotes "options": specify several comma-separated footnotes options') + Trace.error(' Available options are: "number", "symbol", "hover", "margin", "end",') + Trace.error(' "sup", "align"') + Trace.error(' Advanced output options:') + Trace.error(' --splitpart "depth": split the resulting webpage at the given depth') + Trace.error(' --tocfor "page": generate a TOC that points to the given page') + Trace.error(' --target "frame": make all links point to the given frame') + Trace.error(' --notoclabels: omit the part labels in the TOC, such as Chapter') + Trace.error(' --lowmem: do the conversion on the fly (conserve memory)') + Trace.error(' --raw: generate HTML without header or footer.') + Trace.error(' --mathjax remote: use MathJax remotely to display equations') + Trace.error(' --mathjax "URL": use MathJax from the given URL to display equations') + Trace.error(' --googlecharts: use Google Charts to generate formula images') + Trace.error(' --template "file": use a template, put everything in ') + Trace.error(' --copyright: add a copyright notice at the bottom') + Trace.error(' Deprecated options:') + Trace.error(' --toc: (deprecated) create a table of contents') + Trace.error(' --toctarget "page": (deprecated) generate a TOC for the given page') + Trace.error(' --nocopy: (deprecated) maintained for backwards compatibility') + Trace.error(' --jsmath "URL": use jsMath from the given URL to display equations') + sys.exit() + + def showversion(self): + "Return the current eLyXer version string" + string = 'eLyXer version ' + GeneralConfig.version['number'] + string += ' (' + GeneralConfig.version['date'] + ')' + Trace.error(string) + sys.exit() + + def showhardversion(self): + "Return just the version string" + Trace.message(GeneralConfig.version['number']) + sys.exit() + + def showversiondate(self): + "Return just the version dte" + Trace.message(GeneralConfig.version['date']) + sys.exit() + + def showlyxformat(self): + "Return just the lyxformat parameter" + Trace.message(GeneralConfig.version['lyxformat']) + sys.exit() + +class BranchOptions(object): + "A set of options for a branch" + + def __init__(self, name): + self.name = name + self.options = {'color':'#ffffff'} + + def set(self, key, value): + "Set a branch option" + if not key.startswith(ContainerConfig.string['startcommand']): + Trace.error('Invalid branch option ' + key) + return + key = key.replace(ContainerConfig.string['startcommand'], '') + self.options[key] = value + + def isselected(self): + "Return if the branch is selected" + if not 'selected' in self.options: + return False + return self.options['selected'] == '1' + + def __unicode__(self): + "String representation" + return 'options for ' + self.name + ': ' + unicode(self.options) + + + + +import urllib + + + + + + + + +class Cloner(object): + "An object used to clone other objects." + + def clone(cls, original): + "Return an exact copy of an object." + "The original object must have an empty constructor." + return cls.create(original.__class__) + + def create(cls, type): + "Create an object of a given class." + clone = type.__new__(type) + clone.__init__() + return clone + + clone = classmethod(clone) + create = classmethod(create) + +class ContainerExtractor(object): + "A class to extract certain containers." + + def __init__(self, config): + "The config parameter is a map containing three lists: allowed, copied and extracted." + "Each of the three is a list of class names for containers." + "Allowed containers are included as is into the result." + "Cloned containers are cloned and placed into the result." + "Extracted containers are looked into." + "All other containers are silently ignored." + self.allowed = config['allowed'] + self.cloned = config['cloned'] + self.extracted = config['extracted'] + + def extract(self, container): + "Extract a group of selected containers from elyxer.a container." + list = [] + locate = lambda c: c.__class__.__name__ in self.allowed + self.cloned + recursive = lambda c: c.__class__.__name__ in self.extracted + process = lambda c: self.process(c, list) + container.recursivesearch(locate, recursive, process) + return list + + def process(self, container, list): + "Add allowed containers, clone cloned containers and add the clone." + name = container.__class__.__name__ + if name in self.allowed: + list.append(container) + elif name in self.cloned: + list.append(self.safeclone(container)) + else: + Trace.error('Unknown container class ' + name) + + def safeclone(self, container): + "Return a new container with contents only in a safe list, recursively." + clone = Cloner.clone(container) + clone.output = container.output + clone.contents = self.extract(container) + return clone + + + + + + +class Parser(object): + "A generic parser" + + def __init__(self): + self.begin = 0 + self.parameters = dict() + + def parseheader(self, reader): + "Parse the header" + header = reader.currentline().split() + reader.nextline() + self.begin = reader.linenumber + return header + + def parseparameter(self, reader): + "Parse a parameter" + if reader.currentline().strip().startswith('<'): + key, value = self.parsexml(reader) + self.parameters[key] = value + return + split = reader.currentline().strip().split(' ', 1) + reader.nextline() + if len(split) == 0: + return + key = split[0] + if len(split) == 1: + self.parameters[key] = True + return + if not '"' in split[1]: + self.parameters[key] = split[1].strip() + return + doublesplit = split[1].split('"') + self.parameters[key] = doublesplit[1] + + def parsexml(self, reader): + "Parse a parameter in xml form: " + strip = reader.currentline().strip() + reader.nextline() + if not strip.endswith('>'): + Trace.error('XML parameter ' + strip + ' should be <...>') + split = strip[1:-1].split() + if len(split) == 0: + Trace.error('Empty XML parameter <>') + return None, None + key = split[0] + del split[0] + if len(split) == 0: + return key, dict() + attrs = dict() + for attr in split: + if not '=' in attr: + Trace.error('Erroneous attribute for ' + key + ': ' + attr) + attr += '="0"' + parts = attr.split('=') + attrkey = parts[0] + value = parts[1].split('"')[1] + attrs[attrkey] = value + return key, attrs + + def parseending(self, reader, process): + "Parse until the current ending is found" + if not self.ending: + Trace.error('No ending for ' + unicode(self)) + return + while not reader.currentline().startswith(self.ending): + process() + + def parsecontainer(self, reader, contents): + container = self.factory.createcontainer(reader) + if container: + container.parent = self.parent + contents.append(container) + + def __unicode__(self): + "Return a description" + return self.__class__.__name__ + ' (' + unicode(self.begin) + ')' + +class LoneCommand(Parser): + "A parser for just one command line" + + def parse(self,reader): + "Read nothing" + return [] + +class TextParser(Parser): + "A parser for a command and a bit of text" + + stack = [] + + def __init__(self, container): + Parser.__init__(self) + self.ending = None + if container.__class__.__name__ in ContainerConfig.endings: + self.ending = ContainerConfig.endings[container.__class__.__name__] + self.endings = [] + + def parse(self, reader): + "Parse lines as long as they are text" + TextParser.stack.append(self.ending) + self.endings = TextParser.stack + [ContainerConfig.endings['Layout'], + ContainerConfig.endings['Inset'], self.ending] + contents = [] + while not self.isending(reader): + self.parsecontainer(reader, contents) + return contents + + def isending(self, reader): + "Check if text is ending" + current = reader.currentline().split() + if len(current) == 0: + return False + if current[0] in self.endings: + if current[0] in TextParser.stack: + TextParser.stack.remove(current[0]) + else: + TextParser.stack = [] + return True + return False + +class ExcludingParser(Parser): + "A parser that excludes the final line" + + def parse(self, reader): + "Parse everything up to (and excluding) the final line" + contents = [] + self.parseending(reader, lambda: self.parsecontainer(reader, contents)) + return contents + +class BoundedParser(ExcludingParser): + "A parser bound by a final line" + + def parse(self, reader): + "Parse everything, including the final line" + contents = ExcludingParser.parse(self, reader) + # skip last line + reader.nextline() + return contents + +class BoundedDummy(Parser): + "A bound parser that ignores everything" + + def parse(self, reader): + "Parse the contents of the container" + self.parseending(reader, lambda: reader.nextline()) + # skip last line + reader.nextline() + return [] + +class StringParser(Parser): + "Parses just a string" + + def parseheader(self, reader): + "Do nothing, just take note" + self.begin = reader.linenumber + 1 + return [] + + def parse(self, reader): + "Parse a single line" + contents = reader.currentline() + reader.nextline() + return contents + +class InsetParser(BoundedParser): + "Parses a LyX inset" + + def parse(self, reader): + "Parse inset parameters into a dictionary" + startcommand = ContainerConfig.string['startcommand'] + while reader.currentline() != '' and not reader.currentline().startswith(startcommand): + self.parseparameter(reader) + return BoundedParser.parse(self, reader) + + + + + + +class ContainerOutput(object): + "The generic HTML output for a container." + + def gethtml(self, container): + "Show an error." + Trace.error('gethtml() not implemented for ' + unicode(self)) + + def isempty(self): + "Decide if the output is empty: by default, not empty." + return False + +class EmptyOutput(ContainerOutput): + + def gethtml(self, container): + "Return empty HTML code." + return [] + + def isempty(self): + "This output is particularly empty." + return True + +class FixedOutput(ContainerOutput): + "Fixed output" + + def gethtml(self, container): + "Return constant HTML code" + return container.html + +class ContentsOutput(ContainerOutput): + "Outputs the contents converted to HTML" + + def gethtml(self, container): + "Return the HTML code" + html = [] + if container.contents == None: + return html + for element in container.contents: + if not hasattr(element, 'gethtml'): + Trace.error('No html in ' + element.__class__.__name__ + ': ' + unicode(element)) + return html + html += element.gethtml() + return html + +class TaggedOutput(ContentsOutput): + "Outputs an HTML tag surrounding the contents." + + tag = None + breaklines = False + empty = False + + def settag(self, tag, breaklines=False, empty=False): + "Set the value for the tag and other attributes." + self.tag = tag + if breaklines: + self.breaklines = breaklines + if empty: + self.empty = empty + return self + + def setbreaklines(self, breaklines): + "Set the value for breaklines." + self.breaklines = breaklines + return self + + def gethtml(self, container): + "Return the HTML code." + if self.empty: + return [self.selfclosing(container)] + html = [self.open(container)] + html += ContentsOutput.gethtml(self, container) + html.append(self.close(container)) + return html + + def open(self, container): + "Get opening line." + if not self.checktag(): + return '' + open = '<' + self.tag + '>' + if self.breaklines: + return open + '\n' + return open + + def close(self, container): + "Get closing line." + if not self.checktag(): + return '' + close = '' + if self.breaklines: + return '\n' + close + '\n' + return close + + def selfclosing(self, container): + "Get self-closing line." + if not self.checktag(): + return '' + selfclosing = '<' + self.tag + '/>' + if self.breaklines: + return selfclosing + '\n' + return selfclosing + + def checktag(self): + "Check that the tag is valid." + if not self.tag: + Trace.error('No tag in ' + unicode(container)) + return False + if self.tag == '': + return False + return True + +class FilteredOutput(ContentsOutput): + "Returns the output in the contents, but filtered:" + "some strings are replaced by others." + + def __init__(self): + "Initialize the filters." + self.filters = [] + + def addfilter(self, original, replacement): + "Add a new filter: replace the original by the replacement." + self.filters.append((original, replacement)) + + def gethtml(self, container): + "Return the HTML code" + result = [] + html = ContentsOutput.gethtml(self, container) + for line in html: + result.append(self.filter(line)) + return result + + def filter(self, line): + "Filter a single line with all available filters." + for original, replacement in self.filters: + if original in line: + line = line.replace(original, replacement) + return line + +class StringOutput(ContainerOutput): + "Returns a bare string as output" + + def gethtml(self, container): + "Return a bare string" + return [container.string] + + + + + + + +import sys +import codecs + + +class LineReader(object): + "Reads a file line by line" + + def __init__(self, filename): + if isinstance(filename, file): + self.file = filename + else: + self.file = codecs.open(filename, 'rU', 'utf-8') + self.linenumber = 1 + self.lastline = None + self.current = None + self.mustread = True + self.depleted = False + try: + self.readline() + except UnicodeDecodeError: + # try compressed file + import gzip + self.file = gzip.open(filename, 'rb') + self.readline() + + def setstart(self, firstline): + "Set the first line to read." + for i in range(firstline): + self.file.readline() + self.linenumber = firstline + + def setend(self, lastline): + "Set the last line to read." + self.lastline = lastline + + def currentline(self): + "Get the current line" + if self.mustread: + self.readline() + return self.current + + def nextline(self): + "Go to next line" + if self.depleted: + Trace.fatal('Read beyond file end') + self.mustread = True + + def readline(self): + "Read a line from elyxer.file" + self.current = self.file.readline() + if not isinstance(self.file, codecs.StreamReaderWriter): + self.current = self.current.decode('utf-8') + if len(self.current) == 0: + self.depleted = True + self.current = self.current.rstrip('\n\r') + self.linenumber += 1 + self.mustread = False + Trace.prefix = 'Line ' + unicode(self.linenumber) + ': ' + if self.linenumber % 1000 == 0: + Trace.message('Parsing') + + def finished(self): + "Find out if the file is finished" + if self.lastline and self.linenumber == self.lastline: + return True + if self.mustread: + self.readline() + return self.depleted + + def close(self): + self.file.close() + +class LineWriter(object): + "Writes a file as a series of lists" + + file = False + + def __init__(self, filename): + if isinstance(filename, file): + self.file = filename + self.filename = None + else: + self.filename = filename + + def write(self, strings): + "Write a list of strings" + for string in strings: + if not isinstance(string, basestring): + Trace.error('Not a string: ' + unicode(string) + ' in ' + unicode(strings)) + return + self.writestring(string) + + def writestring(self, string): + "Write a string" + if not self.file: + self.file = codecs.open(self.filename, 'w', "utf-8") + if self.file == sys.stdout and sys.version_info < (3,0): + string = string.encode('utf-8') + self.file.write(string) + + def writeline(self, line): + "Write a line to file" + self.writestring(line + '\n') + + def close(self): + self.file.close() + + + + + + +class Globable(object): + """A bit of text which can be globbed (lumped together in bits). + Methods current(), skipcurrent(), checkfor() and isout() have to be + implemented by subclasses.""" + + leavepending = False + + def __init__(self): + self.endinglist = EndingList() + + def checkbytemark(self): + "Check for a Unicode byte mark and skip it." + if self.finished(): + return + if ord(self.current()) == 0xfeff: + self.skipcurrent() + + def isout(self): + "Find out if we are out of the position yet." + Trace.error('Unimplemented isout()') + return True + + def current(self): + "Return the current character." + Trace.error('Unimplemented current()') + return '' + + def checkfor(self, string): + "Check for the given string in the current position." + Trace.error('Unimplemented checkfor()') + return False + + def finished(self): + "Find out if the current text has finished." + if self.isout(): + if not self.leavepending: + self.endinglist.checkpending() + return True + return self.endinglist.checkin(self) + + def skipcurrent(self): + "Return the current character and skip it." + Trace.error('Unimplemented skipcurrent()') + return '' + + def glob(self, currentcheck): + "Glob a bit of text that satisfies a check on the current char." + glob = '' + while not self.finished() and currentcheck(): + glob += self.skipcurrent() + return glob + + def globalpha(self): + "Glob a bit of alpha text" + return self.glob(lambda: self.current().isalpha()) + + def globnumber(self): + "Glob a row of digits." + return self.glob(lambda: self.current().isdigit()) + + def isidentifier(self): + "Return if the current character is alphanumeric or _." + if self.current().isalnum() or self.current() == '_': + return True + return False + + def globidentifier(self): + "Glob alphanumeric and _ symbols." + return self.glob(self.isidentifier) + + def isvalue(self): + "Return if the current character is a value character:" + "not a bracket or a space." + if self.current().isspace(): + return False + if self.current() in '{}()': + return False + return True + + def globvalue(self): + "Glob a value: any symbols but brackets." + return self.glob(self.isvalue) + + def skipspace(self): + "Skip all whitespace at current position." + return self.glob(lambda: self.current().isspace()) + + def globincluding(self, magicchar): + "Glob a bit of text up to (including) the magic char." + glob = self.glob(lambda: self.current() != magicchar) + magicchar + self.skip(magicchar) + return glob + + def globexcluding(self, excluded): + "Glob a bit of text up until (excluding) any excluded character." + return self.glob(lambda: self.current() not in excluded) + + def pushending(self, ending, optional = False): + "Push a new ending to the bottom" + self.endinglist.add(ending, optional) + + def popending(self, expected = None): + "Pop the ending found at the current position" + if self.isout() and self.leavepending: + return expected + ending = self.endinglist.pop(self) + if expected and expected != ending: + Trace.error('Expected ending ' + expected + ', got ' + ending) + self.skip(ending) + return ending + + def nextending(self): + "Return the next ending in the queue." + nextending = self.endinglist.findending(self) + if not nextending: + return None + return nextending.ending + +class EndingList(object): + "A list of position endings" + + def __init__(self): + self.endings = [] + + def add(self, ending, optional = False): + "Add a new ending to the list" + self.endings.append(PositionEnding(ending, optional)) + + def pickpending(self, pos): + "Pick any pending endings from a parse position." + self.endings += pos.endinglist.endings + + def checkin(self, pos): + "Search for an ending" + if self.findending(pos): + return True + return False + + def pop(self, pos): + "Remove the ending at the current position" + if pos.isout(): + Trace.error('No ending out of bounds') + return '' + ending = self.findending(pos) + if not ending: + Trace.error('No ending at ' + pos.current()) + return '' + for each in reversed(self.endings): + self.endings.remove(each) + if each == ending: + return each.ending + elif not each.optional: + Trace.error('Removed non-optional ending ' + each) + Trace.error('No endings left') + return '' + + def findending(self, pos): + "Find the ending at the current position" + if len(self.endings) == 0: + return None + for index, ending in enumerate(reversed(self.endings)): + if ending.checkin(pos): + return ending + if not ending.optional: + return None + return None + + def checkpending(self): + "Check if there are any pending endings" + if len(self.endings) != 0: + Trace.error('Pending ' + unicode(self) + ' left open') + + def __unicode__(self): + "Printable representation" + string = 'endings [' + for ending in self.endings: + string += unicode(ending) + ',' + if len(self.endings) > 0: + string = string[:-1] + return string + ']' + +class PositionEnding(object): + "An ending for a parsing position" + + def __init__(self, ending, optional): + self.ending = ending + self.optional = optional + + def checkin(self, pos): + "Check for the ending" + return pos.checkfor(self.ending) + + def __unicode__(self): + "Printable representation" + string = 'Ending ' + self.ending + if self.optional: + string += ' (optional)' + return string + + + +class Position(Globable): + """A position in a text to parse. + Including those in Globable, functions to implement by subclasses are: + skip(), identifier(), extract(), isout() and current().""" + + def __init__(self): + Globable.__init__(self) + + def skip(self, string): + "Skip a string" + Trace.error('Unimplemented skip()') + + def identifier(self): + "Return an identifier for the current position." + Trace.error('Unimplemented identifier()') + return 'Error' + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text," + "without advancing the parse position." + Trace.error('Unimplemented extract()') + return None + + def checkfor(self, string): + "Check for a string at the given position." + return string == self.extract(len(string)) + + def checkforlower(self, string): + "Check for a string in lower case." + extracted = self.extract(len(string)) + if not extracted: + return False + return string.lower() == self.extract(len(string)).lower() + + def skipcurrent(self): + "Return the current character and skip it." + current = self.current() + self.skip(current) + return current + + def next(self): + "Advance the position and return the next character." + self.skipcurrent() + return self.current() + + def checkskip(self, string): + "Check for a string at the given position; if there, skip it" + if not self.checkfor(string): + return False + self.skip(string) + return True + + def error(self, message): + "Show an error message and the position identifier." + Trace.error(message + ': ' + self.identifier()) + +class TextPosition(Position): + "A parse position based on a raw text." + + def __init__(self, text): + "Create the position from elyxer.some text." + Position.__init__(self) + self.pos = 0 + self.text = text + self.checkbytemark() + + def skip(self, string): + "Skip a string of characters." + self.pos += len(string) + + def identifier(self): + "Return a sample of the remaining text." + length = 30 + if self.pos + length > len(self.text): + length = len(self.text) - self.pos + return '*' + self.text[self.pos:self.pos + length] + '*' + + def isout(self): + "Find out if we are out of the text yet." + return self.pos >= len(self.text) + + def current(self): + "Return the current character, assuming we are not out." + return self.text[self.pos] + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text." + if self.pos + length > len(self.text): + return None + return self.text[self.pos : self.pos + length] + +class FilePosition(Position): + "A parse position based on an underlying file." + + def __init__(self, filename): + "Create the position from a file." + Position.__init__(self) + self.reader = LineReader(filename) + self.pos = 0 + self.checkbytemark() + + def skip(self, string): + "Skip a string of characters." + length = len(string) + while self.pos + length > len(self.reader.currentline()): + length -= len(self.reader.currentline()) - self.pos + 1 + self.nextline() + self.pos += length + + def currentline(self): + "Get the current line of the underlying file." + return self.reader.currentline() + + def nextline(self): + "Go to the next line." + self.reader.nextline() + self.pos = 0 + + def linenumber(self): + "Return the line number of the file." + return self.reader.linenumber + 1 + + def identifier(self): + "Return the current line and line number in the file." + before = self.reader.currentline()[:self.pos - 1] + after = self.reader.currentline()[self.pos:] + return 'line ' + unicode(self.getlinenumber()) + ': ' + before + '*' + after + + def isout(self): + "Find out if we are out of the text yet." + if self.pos > len(self.reader.currentline()): + if self.pos > len(self.reader.currentline()) + 1: + Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos)) + self.nextline() + return self.reader.finished() + + def current(self): + "Return the current character, assuming we are not out." + if self.pos == len(self.reader.currentline()): + return '\n' + if self.pos > len(self.reader.currentline()): + Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos)) + return '*' + return self.reader.currentline()[self.pos] + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text." + if self.pos + length > len(self.reader.currentline()): + return None + return self.reader.currentline()[self.pos : self.pos + length] + + + +class Container(object): + "A container for text and objects in a lyx file" + + partkey = None + parent = None + begin = None + + def __init__(self): + self.contents = list() + + def process(self): + "Process contents" + pass + + def gethtml(self): + "Get the resulting HTML" + html = self.output.gethtml(self) + if isinstance(html, basestring): + Trace.error('Raw string ' + html) + html = [html] + return self.escapeall(html) + + def escapeall(self, lines): + "Escape all lines in an array according to the output options." + result = [] + for line in lines: + if Options.html: + line = self.escape(line, EscapeConfig.html) + if Options.iso885915: + line = self.escape(line, EscapeConfig.iso885915) + line = self.escapeentities(line) + elif not Options.unicode: + line = self.escape(line, EscapeConfig.nonunicode) + result.append(line) + return result + + def escape(self, line, replacements = EscapeConfig.entities): + "Escape a line with replacements from elyxer.a map" + pieces = replacements.keys() + # do them in order + pieces.sort() + for piece in pieces: + if piece in line: + line = line.replace(piece, replacements[piece]) + return line + + def escapeentities(self, line): + "Escape all Unicode characters to HTML entities." + result = '' + pos = TextPosition(line) + while not pos.finished(): + if ord(pos.current()) > 128: + codepoint = hex(ord(pos.current())) + if codepoint == '0xd835': + codepoint = hex(ord(pos.next()) + 0xf800) + result += '&#' + codepoint[1:] + ';' + else: + result += pos.current() + pos.skipcurrent() + return result + + def searchall(self, type): + "Search for all embedded containers of a given type" + list = [] + self.searchprocess(type, lambda container: list.append(container)) + return list + + def searchremove(self, type): + "Search for all containers of a type and remove them" + list = self.searchall(type) + for container in list: + container.parent.contents.remove(container) + return list + + def searchprocess(self, type, process): + "Search for elements of a given type and process them" + self.locateprocess(lambda container: isinstance(container, type), process) + + def locateprocess(self, locate, process): + "Search for all embedded containers and process them" + for container in self.contents: + container.locateprocess(locate, process) + if locate(container): + process(container) + + def recursivesearch(self, locate, recursive, process): + "Perform a recursive search in the container." + for container in self.contents: + if recursive(container): + container.recursivesearch(locate, recursive, process) + if locate(container): + process(container) + + def extracttext(self): + "Extract all text from elyxer.allowed containers." + result = '' + constants = ContainerExtractor(ContainerConfig.extracttext).extract(self) + for constant in constants: + result += constant.string + return result + + def group(self, index, group, isingroup): + "Group some adjoining elements into a group" + if index >= len(self.contents): + return + if hasattr(self.contents[index], 'grouped'): + return + while index < len(self.contents) and isingroup(self.contents[index]): + self.contents[index].grouped = True + group.contents.append(self.contents[index]) + self.contents.pop(index) + self.contents.insert(index, group) + + def remove(self, index): + "Remove a container but leave its contents" + container = self.contents[index] + self.contents.pop(index) + while len(container.contents) > 0: + self.contents.insert(index, container.contents.pop()) + + def tree(self, level = 0): + "Show in a tree" + Trace.debug(" " * level + unicode(self)) + for container in self.contents: + container.tree(level + 1) + + def getparameter(self, name): + "Get the value of a parameter, if present." + if not name in self.parameters: + return None + return self.parameters[name] + + def getparameterlist(self, name): + "Get the value of a comma-separated parameter as a list." + paramtext = self.getparameter(name) + if not paramtext: + return [] + return paramtext.split(',') + + def hasemptyoutput(self): + "Check if the parent's output is empty." + current = self.parent + while current: + if current.output.isempty(): + return True + current = current.parent + return False + + def __unicode__(self): + "Get a description" + if not self.begin: + return self.__class__.__name__ + return self.__class__.__name__ + '@' + unicode(self.begin) + +class BlackBox(Container): + "A container that does not output anything" + + def __init__(self): + self.parser = LoneCommand() + self.output = EmptyOutput() + self.contents = [] + +class LyXFormat(BlackBox): + "Read the lyxformat command" + + def process(self): + "Show warning if version < 276" + version = int(self.header[1]) + if version < 276: + Trace.error('Warning: unsupported old format version ' + str(version)) + if version > int(GeneralConfig.version['lyxformat']): + Trace.error('Warning: unsupported new format version ' + str(version)) + +class StringContainer(Container): + "A container for a single string" + + parsed = None + + def __init__(self): + self.parser = StringParser() + self.output = StringOutput() + self.string = '' + + def process(self): + "Replace special chars from elyxer.the contents." + if self.parsed: + self.string = self.replacespecial(self.parsed) + self.parsed = None + + def replacespecial(self, line): + "Replace all special chars from elyxer.a line" + replaced = self.escape(line, EscapeConfig.entities) + replaced = self.changeline(replaced) + if ContainerConfig.string['startcommand'] in replaced and len(replaced) > 1: + # unprocessed commands + if self.begin: + message = 'Unknown command at ' + unicode(self.begin) + ': ' + else: + message = 'Unknown command: ' + Trace.error(message + replaced.strip()) + return replaced + + def changeline(self, line): + line = self.escape(line, EscapeConfig.chars) + if not ContainerConfig.string['startcommand'] in line: + return line + line = self.escape(line, EscapeConfig.commands) + return line + + def extracttext(self): + "Return all text." + return self.string + + def __unicode__(self): + "Return a printable representation." + result = 'StringContainer' + if self.begin: + result += '@' + unicode(self.begin) + ellipsis = '...' + if len(self.string.strip()) <= 15: + ellipsis = '' + return result + ' (' + self.string.strip()[:15] + ellipsis + ')' + +class Constant(StringContainer): + "A constant string" + + def __init__(self, text): + self.contents = [] + self.string = text + self.output = StringOutput() + + def __unicode__(self): + return 'Constant: ' + self.string + +class TaggedText(Container): + "Text inside a tag" + + output = None + + def __init__(self): + self.parser = TextParser(self) + self.output = TaggedOutput() + + def complete(self, contents, tag, breaklines=False): + "Complete the tagged text and return it" + self.contents = contents + self.output.tag = tag + self.output.breaklines = breaklines + return self + + def constant(self, text, tag, breaklines=False): + "Complete the tagged text with a constant" + constant = Constant(text) + return self.complete([constant], tag, breaklines) + + def __unicode__(self): + "Return a printable representation." + if not hasattr(self.output, 'tag'): + return 'Emtpy tagged text' + if not self.output.tag: + return 'Tagged ' + return 'Tagged <' + self.output.tag + '>' + + + + + + +class DocumentParameters(object): + "Global parameters for the document." + + pdftitle = None + indentstandard = False + tocdepth = 10 + startinglevel = 0 + maxdepth = 10 + language = None + bibliography = None + outputchanges = False + displaymode = False + + + + + + +class FormulaParser(Parser): + "Parses a formula" + + def parseheader(self, reader): + "See if the formula is inlined" + self.begin = reader.linenumber + 1 + type = self.parsetype(reader) + if not type: + reader.nextline() + type = self.parsetype(reader) + if not type: + Trace.error('Unknown formula type in ' + reader.currentline().strip()) + return ['unknown'] + return [type] + + def parsetype(self, reader): + "Get the formula type from the first line." + if reader.currentline().find(FormulaConfig.starts['simple']) >= 0: + return 'inline' + if reader.currentline().find(FormulaConfig.starts['complex']) >= 0: + return 'block' + if reader.currentline().find(FormulaConfig.starts['unnumbered']) >= 0: + return 'block' + if reader.currentline().find(FormulaConfig.starts['beginbefore']) >= 0: + return 'numbered' + return None + + def parse(self, reader): + "Parse the formula until the end" + formula = self.parseformula(reader) + while not reader.currentline().startswith(self.ending): + stripped = reader.currentline().strip() + if len(stripped) > 0: + Trace.error('Unparsed formula line ' + stripped) + reader.nextline() + reader.nextline() + return formula + + def parseformula(self, reader): + "Parse the formula contents" + simple = FormulaConfig.starts['simple'] + if simple in reader.currentline(): + rest = reader.currentline().split(simple, 1)[1] + if simple in rest: + # formula is $...$ + return self.parsesingleliner(reader, simple, simple) + # formula is multiline $...$ + return self.parsemultiliner(reader, simple, simple) + if FormulaConfig.starts['complex'] in reader.currentline(): + # formula of the form \[...\] + return self.parsemultiliner(reader, FormulaConfig.starts['complex'], + FormulaConfig.endings['complex']) + beginbefore = FormulaConfig.starts['beginbefore'] + beginafter = FormulaConfig.starts['beginafter'] + if beginbefore in reader.currentline(): + if reader.currentline().strip().endswith(beginafter): + current = reader.currentline().strip() + endsplit = current.split(beginbefore)[1].split(beginafter) + startpiece = beginbefore + endsplit[0] + beginafter + endbefore = FormulaConfig.endings['endbefore'] + endafter = FormulaConfig.endings['endafter'] + endpiece = endbefore + endsplit[0] + endafter + return startpiece + self.parsemultiliner(reader, startpiece, endpiece) + endpiece + Trace.error('Missing ' + beginafter + ' in ' + reader.currentline()) + return '' + begincommand = FormulaConfig.starts['command'] + beginbracket = FormulaConfig.starts['bracket'] + if begincommand in reader.currentline() and beginbracket in reader.currentline(): + endbracket = FormulaConfig.endings['bracket'] + return self.parsemultiliner(reader, beginbracket, endbracket) + Trace.error('Formula beginning ' + reader.currentline() + ' is unknown') + return '' + + def parsesingleliner(self, reader, start, ending): + "Parse a formula in one line" + line = reader.currentline().strip() + if not start in line: + Trace.error('Line ' + line + ' does not contain formula start ' + start) + return '' + if not line.endswith(ending): + Trace.error('Formula ' + line + ' does not end with ' + ending) + return '' + index = line.index(start) + rest = line[index + len(start):-len(ending)] + reader.nextline() + return rest + + def parsemultiliner(self, reader, start, ending): + "Parse a formula in multiple lines" + formula = '' + line = reader.currentline() + if not start in line: + Trace.error('Line ' + line.strip() + ' does not contain formula start ' + start) + return '' + index = line.index(start) + line = line[index + len(start):].strip() + while not line.endswith(ending): + formula += line + '\n' + reader.nextline() + line = reader.currentline() + formula += line[:-len(ending)] + reader.nextline() + return formula + +class MacroParser(FormulaParser): + "A parser for a formula macro." + + def parseheader(self, reader): + "See if the formula is inlined" + self.begin = reader.linenumber + 1 + return ['inline'] + + def parse(self, reader): + "Parse the formula until the end" + formula = self.parsemultiliner(reader, self.parent.start, self.ending) + reader.nextline() + return formula + + + + + + + + + +class FormulaBit(Container): + "A bit of a formula" + + type = None + size = 1 + original = '' + + def __init__(self): + "The formula bit type can be 'alpha', 'number', 'font'." + self.contents = [] + self.output = ContentsOutput() + + def setfactory(self, factory): + "Set the internal formula factory." + self.factory = factory + return self + + def add(self, bit): + "Add any kind of formula bit already processed" + self.contents.append(bit) + self.original += bit.original + bit.parent = self + + def skiporiginal(self, string, pos): + "Skip a string and add it to the original formula" + self.original += string + if not pos.checkskip(string): + Trace.error('String ' + string + ' not at ' + pos.identifier()) + + def computesize(self): + "Compute the size of the bit as the max of the sizes of all contents." + if len(self.contents) == 0: + return 1 + self.size = max([element.size for element in self.contents]) + return self.size + + def clone(self): + "Return a copy of itself." + return self.factory.parseformula(self.original) + + def __unicode__(self): + "Get a string representation" + return self.__class__.__name__ + ' read in ' + self.original + +class TaggedBit(FormulaBit): + "A tagged string in a formula" + + def constant(self, constant, tag): + "Set the constant and the tag" + self.output = TaggedOutput().settag(tag) + self.add(FormulaConstant(constant)) + return self + + def complete(self, contents, tag, breaklines = False): + "Set the constant and the tag" + self.contents = contents + self.output = TaggedOutput().settag(tag, breaklines) + return self + + def selfcomplete(self, tag): + "Set the self-closing tag, no contents (as in
      )." + self.output = TaggedOutput().settag(tag, empty = True) + return self + +class FormulaConstant(Constant): + "A constant string in a formula" + + def __init__(self, string): + "Set the constant string" + Constant.__init__(self, string) + self.original = string + self.size = 1 + self.type = None + + def computesize(self): + "Compute the size of the constant: always 1." + return self.size + + def clone(self): + "Return a copy of itself." + return FormulaConstant(self.original) + + def __unicode__(self): + "Return a printable representation." + return 'Formula constant: ' + self.string + +class RawText(FormulaBit): + "A bit of text inside a formula" + + def detect(self, pos): + "Detect a bit of raw text" + return pos.current().isalpha() + + def parsebit(self, pos): + "Parse alphabetic text" + alpha = pos.globalpha() + self.add(FormulaConstant(alpha)) + self.type = 'alpha' + +class FormulaSymbol(FormulaBit): + "A symbol inside a formula" + + modified = FormulaConfig.modified + unmodified = FormulaConfig.unmodified['characters'] + + def detect(self, pos): + "Detect a symbol" + if pos.current() in FormulaSymbol.unmodified: + return True + if pos.current() in FormulaSymbol.modified: + return True + return False + + def parsebit(self, pos): + "Parse the symbol" + if pos.current() in FormulaSymbol.unmodified: + self.addsymbol(pos.current(), pos) + return + if pos.current() in FormulaSymbol.modified: + self.addsymbol(FormulaSymbol.modified[pos.current()], pos) + return + Trace.error('Symbol ' + pos.current() + ' not found') + + def addsymbol(self, symbol, pos): + "Add a symbol" + self.skiporiginal(pos.current(), pos) + self.contents.append(FormulaConstant(symbol)) + +class FormulaNumber(FormulaBit): + "A string of digits in a formula" + + def detect(self, pos): + "Detect a digit" + return pos.current().isdigit() + + def parsebit(self, pos): + "Parse a bunch of digits" + digits = pos.glob(lambda: pos.current().isdigit()) + self.add(FormulaConstant(digits)) + self.type = 'number' + +class Comment(FormulaBit): + "A LaTeX comment: % to the end of the line." + + start = FormulaConfig.starts['comment'] + + def detect(self, pos): + "Detect the %." + return pos.current() == self.start + + def parsebit(self, pos): + "Parse to the end of the line." + self.original += pos.globincluding('\n') + +class WhiteSpace(FormulaBit): + "Some white space inside a formula." + + def detect(self, pos): + "Detect the white space." + return pos.current().isspace() + + def parsebit(self, pos): + "Parse all whitespace." + self.original += pos.skipspace() + + def __unicode__(self): + "Return a printable representation." + return 'Whitespace: *' + self.original + '*' + +class Bracket(FormulaBit): + "A {} bracket inside a formula" + + start = FormulaConfig.starts['bracket'] + ending = FormulaConfig.endings['bracket'] + + def __init__(self): + "Create a (possibly literal) new bracket" + FormulaBit.__init__(self) + self.inner = None + + def detect(self, pos): + "Detect the start of a bracket" + return pos.checkfor(self.start) + + def parsebit(self, pos): + "Parse the bracket" + self.parsecomplete(pos, self.innerformula) + return self + + def parsetext(self, pos): + "Parse a text bracket" + self.parsecomplete(pos, self.innertext) + return self + + def parseliteral(self, pos): + "Parse a literal bracket" + self.parsecomplete(pos, self.innerliteral) + return self + + def parsecomplete(self, pos, innerparser): + "Parse the start and end marks" + if not pos.checkfor(self.start): + Trace.error('Bracket should start with ' + self.start + ' at ' + pos.identifier()) + return None + self.skiporiginal(self.start, pos) + pos.pushending(self.ending) + innerparser(pos) + self.original += pos.popending(self.ending) + self.computesize() + + def innerformula(self, pos): + "Parse a whole formula inside the bracket" + while not pos.finished(): + self.add(self.factory.parseany(pos)) + + def innertext(self, pos): + "Parse some text inside the bracket, following textual rules." + specialchars = FormulaConfig.symbolfunctions.keys() + specialchars.append(FormulaConfig.starts['command']) + specialchars.append(FormulaConfig.starts['bracket']) + specialchars.append(Comment.start) + while not pos.finished(): + if pos.current() in specialchars: + self.add(self.factory.parseany(pos)) + if pos.checkskip(' '): + self.original += ' ' + else: + self.add(FormulaConstant(pos.skipcurrent())) + + def innerliteral(self, pos): + "Parse a literal inside the bracket, which does not generate HTML." + self.literal = '' + while not pos.finished() and not pos.current() == self.ending: + if pos.current() == self.start: + self.parseliteral(pos) + else: + self.literal += pos.skipcurrent() + self.original += self.literal + +class SquareBracket(Bracket): + "A [] bracket inside a formula" + + start = FormulaConfig.starts['squarebracket'] + ending = FormulaConfig.endings['squarebracket'] + + def clone(self): + "Return a new square bracket with the same contents." + bracket = SquareBracket() + bracket.contents = self.contents + return bracket + + + +class MathsProcessor(object): + "A processor for a maths construction inside the FormulaProcessor." + + def process(self, contents, index): + "Process an element inside a formula." + Trace.error('Unimplemented process() in ' + unicode(self)) + + def __unicode__(self): + "Return a printable description." + return 'Maths processor ' + self.__class__.__name__ + +class FormulaProcessor(object): + "A processor specifically for formulas." + + processors = [] + + def process(self, bit): + "Process the contents of every formula bit, recursively." + self.processcontents(bit) + self.processinsides(bit) + self.traversewhole(bit) + + def processcontents(self, bit): + "Process the contents of a formula bit." + if not isinstance(bit, FormulaBit): + return + bit.process() + for element in bit.contents: + self.processcontents(element) + + def processinsides(self, bit): + "Process the insides (limits, brackets) in a formula bit." + if not isinstance(bit, FormulaBit): + return + for index, element in enumerate(bit.contents): + for processor in self.processors: + processor.process(bit.contents, index) + # continue with recursive processing + self.processinsides(element) + + def traversewhole(self, formula): + "Traverse over the contents to alter variables and space units." + last = None + for bit, contents in self.traverse(formula): + if bit.type == 'alpha': + self.italicize(bit, contents) + elif bit.type == 'font' and last and last.type == 'number': + bit.contents.insert(0, FormulaConstant(u' ')) + last = bit + + def traverse(self, bit): + "Traverse a formula and yield a flattened structure of (bit, list) pairs." + for element in bit.contents: + if hasattr(element, 'type') and element.type: + yield (element, bit.contents) + elif isinstance(element, FormulaBit): + for pair in self.traverse(element): + yield pair + + def italicize(self, bit, contents): + "Italicize the given bit of text." + index = contents.index(bit) + contents[index] = TaggedBit().complete([bit], 'i') + + + + +class Formula(Container): + "A LaTeX formula" + + def __init__(self): + self.parser = FormulaParser() + self.output = TaggedOutput().settag('span class="formula"') + + def process(self): + "Convert the formula to tags" + if self.header[0] == 'inline': + DocumentParameters.displaymode = False + else: + DocumentParameters.displaymode = True + self.output.settag('div class="formula"', True) + if Options.jsmath: + self.jsmath() + elif Options.mathjax: + self.mathjax() + elif Options.googlecharts: + self.googlecharts() + else: + self.classic() + + def jsmath(self): + "Make the contents for jsMath." + if self.header[0] != 'inline': + self.output = TaggedOutput().settag('div class="math"') + else: + self.output = TaggedOutput().settag('span class="math"') + self.contents = [Constant(self.parsed)] + + def mathjax(self): + "Make the contents for MathJax." + self.output.tag = 'span class="MathJax_Preview"' + tag = 'script type="math/tex' + if self.header[0] != 'inline': + tag += ';mode=display' + self.contents = [TaggedText().constant(self.parsed, tag + '"', True)] + + def googlecharts(self): + "Make the contents using Google Charts http://code.google.com/apis/chart/." + url = FormulaConfig.urls['googlecharts'] + urllib.quote_plus(self.parsed) + img = '' + self.parsed + '' + self.contents = [Constant(img)] + + def classic(self): + "Make the contents using classic output generation with XHTML and CSS." + whole = FormulaFactory().parseformula(self.parsed) + FormulaProcessor().process(whole) + whole.parent = self + self.contents = [whole] + + def parse(self, pos): + "Parse using a parse position instead of self.parser." + if pos.checkskip('$$'): + self.parsedollarblock(pos) + elif pos.checkskip('$'): + self.parsedollarinline(pos) + elif pos.checkskip('\\('): + self.parseinlineto(pos, '\\)') + elif pos.checkskip('\\['): + self.parseblockto(pos, '\\]') + else: + pos.error('Unparseable formula') + self.process() + return self + + def parsedollarinline(self, pos): + "Parse a $...$ formula." + self.header = ['inline'] + self.parsedollar(pos) + + def parsedollarblock(self, pos): + "Parse a $$...$$ formula." + self.header = ['block'] + self.parsedollar(pos) + if not pos.checkskip('$'): + pos.error('Formula should be $$...$$, but last $ is missing.') + + def parsedollar(self, pos): + "Parse to the next $." + pos.pushending('$') + self.parsed = pos.globexcluding('$') + pos.popending('$') + + def parseinlineto(self, pos, limit): + "Parse a \\(...\\) formula." + self.header = ['inline'] + self.parseupto(pos, limit) + + def parseblockto(self, pos, limit): + "Parse a \\[...\\] formula." + self.header = ['block'] + self.parseupto(pos, limit) + + def parseupto(self, pos, limit): + "Parse a formula that ends with the given command." + pos.pushending(limit) + self.parsed = pos.glob(lambda: True) + pos.popending(limit) + + def __unicode__(self): + "Return a printable representation." + if self.partkey and self.partkey.number: + return 'Formula (' + self.partkey.number + ')' + return 'Unnumbered formula' + +class WholeFormula(FormulaBit): + "Parse a whole formula" + + def detect(self, pos): + "Not outside the formula is enough." + return not pos.finished() + + def parsebit(self, pos): + "Parse with any formula bit" + while not pos.finished(): + self.add(self.factory.parseany(pos)) + +class FormulaFactory(object): + "Construct bits of formula" + + # bit types will be appended later + types = [FormulaSymbol, RawText, FormulaNumber, Bracket, Comment, WhiteSpace] + skippedtypes = [Comment, WhiteSpace] + defining = False + + def __init__(self): + "Initialize the map of instances." + self.instances = dict() + + def detecttype(self, type, pos): + "Detect a bit of a given type." + if pos.finished(): + return False + return self.instance(type).detect(pos) + + def instance(self, type): + "Get an instance of the given type." + if not type in self.instances or not self.instances[type]: + self.instances[type] = self.create(type) + return self.instances[type] + + def create(self, type): + "Create a new formula bit of the given type." + return Cloner.create(type).setfactory(self) + + def clearskipped(self, pos): + "Clear any skipped types." + while not pos.finished(): + if not self.skipany(pos): + return + return + + def skipany(self, pos): + "Skip any skipped types." + for type in self.skippedtypes: + if self.instance(type).detect(pos): + return self.parsetype(type, pos) + return None + + def parseany(self, pos): + "Parse any formula bit at the current location." + for type in self.types + self.skippedtypes: + if self.detecttype(type, pos): + return self.parsetype(type, pos) + Trace.error('Unrecognized formula at ' + pos.identifier()) + return FormulaConstant(pos.skipcurrent()) + + def parsetype(self, type, pos): + "Parse the given type and return it." + bit = self.instance(type) + self.instances[type] = None + returnedbit = bit.parsebit(pos) + if returnedbit: + return returnedbit.setfactory(self) + return bit + + def parseformula(self, formula): + "Parse a string of text that contains a whole formula." + pos = TextPosition(formula) + whole = self.create(WholeFormula) + if whole.detect(pos): + whole.parsebit(pos) + return whole + # no formula found + if not pos.finished(): + Trace.error('Unknown formula at: ' + pos.identifier()) + whole.add(TaggedBit().constant(formula, 'span class="unknown"')) + return whole + + + + +import unicodedata + + + + + + + + + + + + +import gettext + + +class Translator(object): + "Reads the configuration file and tries to find a translation." + "Otherwise falls back to the messages in the config file." + + instance = None + + def translate(cls, key): + "Get the translated message for a key." + return cls.instance.getmessage(key) + + translate = classmethod(translate) + + def __init__(self): + self.translation = None + self.first = True + + def findtranslation(self): + "Find the translation for the document language." + self.langcodes = None + if not DocumentParameters.language: + Trace.error('No language in document') + return + if not DocumentParameters.language in TranslationConfig.languages: + Trace.error('Unknown language ' + DocumentParameters.language) + return + if TranslationConfig.languages[DocumentParameters.language] == 'en': + return + langcodes = [TranslationConfig.languages[DocumentParameters.language]] + try: + self.translation = gettext.translation('elyxer', None, langcodes) + except IOError: + Trace.error('No translation for ' + unicode(langcodes)) + + def getmessage(self, key): + "Get the translated message for the given key." + if self.first: + self.findtranslation() + self.first = False + message = self.getuntranslated(key) + if not self.translation: + return message + try: + message = self.translation.ugettext(message) + except IOError: + pass + return message + + def getuntranslated(self, key): + "Get the untranslated message." + if not key in TranslationConfig.constants: + Trace.error('Cannot translate ' + key) + return key + return TranslationConfig.constants[key] + +Translator.instance = Translator() + + + +class NumberCounter(object): + "A counter for numbers (by default)." + "The type can be changed to return letters, roman numbers..." + + name = None + value = None + mode = None + master = None + + letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + symbols = NumberingConfig.sequence['symbols'] + romannumerals = [ + ('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), + ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), + ('IV', 4), ('I', 1) + ] + + def __init__(self, name): + "Give a name to the counter." + self.name = name + + def setmode(self, mode): + "Set the counter mode. Can be changed at runtime." + self.mode = mode + return self + + def init(self, value): + "Set an initial value." + self.value = value + + def gettext(self): + "Get the next value as a text string." + return unicode(self.value) + + def getletter(self): + "Get the next value as a letter." + return self.getsequence(self.letters) + + def getsymbol(self): + "Get the next value as a symbol." + return self.getsequence(self.symbols) + + def getsequence(self, sequence): + "Get the next value from elyxer.a sequence." + return sequence[(self.value - 1) % len(sequence)] + + def getroman(self): + "Get the next value as a roman number." + result = '' + number = self.value + for numeral, value in self.romannumerals: + if number >= value: + result += numeral * (number / value) + number = number % value + return result + + def getvalue(self): + "Get the current value as configured in the current mode." + if not self.mode or self.mode in ['text', '1']: + return self.gettext() + if self.mode == 'A': + return self.getletter() + if self.mode == 'a': + return self.getletter().lower() + if self.mode == 'I': + return self.getroman() + if self.mode == '*': + return self.getsymbol() + Trace.error('Unknown counter mode ' + self.mode) + return self.gettext() + + def getnext(self): + "Increase the current value and get the next value as configured." + if not self.value: + self.value = 0 + self.value += 1 + return self.getvalue() + + def reset(self): + "Reset the counter." + self.value = 0 + + def __unicode__(self): + "Return a printable representation." + result = 'Counter ' + self.name + if self.mode: + result += ' in mode ' + self.mode + return result + +class DependentCounter(NumberCounter): + "A counter which depends on another one (the master)." + + def setmaster(self, master): + "Set the master counter." + self.master = master + self.last = self.master.getvalue() + return self + + def getnext(self): + "Increase or, if the master counter has changed, restart." + if self.last != self.master.getvalue(): + self.reset() + value = NumberCounter.getnext(self) + self.last = self.master.getvalue() + return value + + def getvalue(self): + "Get the value of the combined counter: master.dependent." + return self.master.getvalue() + '.' + NumberCounter.getvalue(self) + +class NumberGenerator(object): + "A number generator for unique sequences and hierarchical structures. Used in:" + " * ordered part numbers: Chapter 3, Section 5.3." + " * unique part numbers: Footnote 15, Bibliography cite [15]." + " * chaptered part numbers: Figure 3.15, Equation (8.3)." + " * unique roman part numbers: Part I, Book IV." + + chaptered = None + generator = None + + romanlayouts = [x.lower() for x in NumberingConfig.layouts['roman']] + orderedlayouts = [x.lower() for x in NumberingConfig.layouts['ordered']] + + counters = dict() + appendix = None + + def deasterisk(self, type): + "Remove the possible asterisk in a layout type." + return type.replace('*', '') + + def isunique(self, type): + "Find out if the layout type corresponds to a unique part." + return self.isroman(type) + + def isroman(self, type): + "Find out if the layout type should have roman numeration." + return self.deasterisk(type).lower() in self.romanlayouts + + def isinordered(self, type): + "Find out if the layout type corresponds to an (un)ordered part." + return self.deasterisk(type).lower() in self.orderedlayouts + + def isnumbered(self, type): + "Find out if the type for a layout corresponds to a numbered layout." + if '*' in type: + return False + if self.isroman(type): + return True + if not self.isinordered(type): + return False + if self.getlevel(type) > DocumentParameters.maxdepth: + return False + return True + + def isunordered(self, type): + "Find out if the type contains an asterisk, basically." + return '*' in type + + def getlevel(self, type): + "Get the level that corresponds to a layout type." + if self.isunique(type): + return 0 + if not self.isinordered(type): + Trace.error('Unknown layout type ' + type) + return 0 + type = self.deasterisk(type).lower() + level = self.orderedlayouts.index(type) + 1 + return level - DocumentParameters.startinglevel + + def getparttype(self, type): + "Obtain the type for the part: without the asterisk, " + "and switched to Appendix if necessary." + if NumberGenerator.appendix and self.getlevel(type) == 1: + return 'Appendix' + return self.deasterisk(type) + + def generate(self, type): + "Generate a number for a layout type." + "Unique part types such as Part or Book generate roman numbers: Part I." + "Ordered part types return dot-separated tuples: Chapter 5, Subsection 2.3.5." + "Everything else generates unique numbers: Bibliography [1]." + "Each invocation results in a new number." + return self.getcounter(type).getnext() + + def getcounter(self, type): + "Get the counter for the given type." + type = type.lower() + if not type in self.counters: + self.counters[type] = self.create(type) + return self.counters[type] + + def create(self, type): + "Create a counter for the given type." + if self.isnumbered(type) and self.getlevel(type) > 1: + index = self.orderedlayouts.index(type) + above = self.orderedlayouts[index - 1] + master = self.getcounter(above) + return self.createdependent(type, master) + counter = NumberCounter(type) + if self.isroman(type): + counter.setmode('I') + return counter + + def getdependentcounter(self, type, master): + "Get (or create) a counter of the given type that depends on another." + if not type in self.counters or not self.counters[type].master: + self.counters[type] = self.createdependent(type, master) + return self.counters[type] + + def createdependent(self, type, master): + "Create a dependent counter given the master." + return DependentCounter(type).setmaster(master) + + def startappendix(self): + "Start appendices here." + firsttype = self.orderedlayouts[DocumentParameters.startinglevel] + counter = self.getcounter(firsttype) + counter.setmode('A').reset() + NumberGenerator.appendix = True + +class ChapteredGenerator(NumberGenerator): + "Generate chaptered numbers, as in Chapter.Number." + "Used in equations, figures: Equation (5.3), figure 8.15." + + def generate(self, type): + "Generate a number which goes with first-level numbers (chapters). " + "For the article classes a unique number is generated." + if DocumentParameters.startinglevel > 0: + return NumberGenerator.generator.generate(type) + chapter = self.getcounter('Chapter') + return self.getdependentcounter(type, chapter).getnext() + + +NumberGenerator.chaptered = ChapteredGenerator() +NumberGenerator.generator = NumberGenerator() + + + + + + +class ContainerSize(object): + "The size of a container." + + width = None + height = None + maxwidth = None + maxheight = None + scale = None + + def set(self, width = None, height = None): + "Set the proper size with width and height." + self.setvalue('width', width) + self.setvalue('height', height) + return self + + def setmax(self, maxwidth = None, maxheight = None): + "Set max width and/or height." + self.setvalue('maxwidth', maxwidth) + self.setvalue('maxheight', maxheight) + return self + + def readparameters(self, container): + "Read some size parameters off a container." + self.setparameter(container, 'width') + self.setparameter(container, 'height') + self.setparameter(container, 'scale') + self.checkvalidheight(container) + return self + + def setparameter(self, container, name): + "Read a size parameter off a container, and set it if present." + value = container.getparameter(name) + self.setvalue(name, value) + + def setvalue(self, name, value): + "Set the value of a parameter name, only if it's valid." + value = self.processparameter(value) + if value: + setattr(self, name, value) + + def checkvalidheight(self, container): + "Check if the height parameter is valid; otherwise erase it." + heightspecial = container.getparameter('height_special') + if self.height and self.extractnumber(self.height) == '1' and heightspecial == 'totalheight': + self.height = None + + def processparameter(self, value): + "Do the full processing on a parameter." + if not value: + return None + if self.extractnumber(value) == '0': + return None + for ignored in StyleConfig.size['ignoredtexts']: + if ignored in value: + value = value.replace(ignored, '') + return value + + def extractnumber(self, text): + "Extract the first number in the given text." + result = '' + decimal = False + for char in text: + if char.isdigit(): + result += char + elif char == '.' and not decimal: + result += char + decimal = True + else: + return result + return result + + def checkimage(self, width, height): + "Check image dimensions, set them if possible." + if width: + self.maxwidth = unicode(width) + 'px' + if self.scale and not self.width: + self.width = self.scalevalue(width) + if height: + self.maxheight = unicode(height) + 'px' + if self.scale and not self.height: + self.height = self.scalevalue(height) + if self.width and not self.height: + self.height = 'auto' + if self.height and not self.width: + self.width = 'auto' + + def scalevalue(self, value): + "Scale the value according to the image scale and return it as unicode." + scaled = value * int(self.scale) / 100 + return unicode(int(scaled)) + 'px' + + def removepercentwidth(self): + "Remove percent width if present, to set it at the figure level." + if not self.width: + return None + if not '%' in self.width: + return None + width = self.width + self.width = None + if self.height == 'auto': + self.height = None + return width + + def addstyle(self, container): + "Add the proper style attribute to the output tag." + if not isinstance(container.output, TaggedOutput): + Trace.error('No tag to add style, in ' + unicode(container)) + if not self.width and not self.height and not self.maxwidth and not self.maxheight: + # nothing to see here; move along + return + tag = ' style="' + tag += self.styleparameter('width') + tag += self.styleparameter('maxwidth') + tag += self.styleparameter('height') + tag += self.styleparameter('maxheight') + if tag[-1] == ' ': + tag = tag[:-1] + tag += '"' + container.output.tag += tag + + def styleparameter(self, name): + "Get the style for a single parameter." + value = getattr(self, name) + if value: + return name.replace('max', 'max-') + ': ' + value + '; ' + return '' + + + +class QuoteContainer(Container): + "A container for a pretty quote" + + def __init__(self): + self.parser = BoundedParser() + self.output = FixedOutput() + + def process(self): + "Process contents" + self.type = self.header[2] + if not self.type in StyleConfig.quotes: + Trace.error('Quote type ' + self.type + ' not found') + self.html = ['"'] + return + self.html = [StyleConfig.quotes[self.type]] + +class LyXLine(Container): + "A Lyx line" + + def __init__(self): + self.parser = LoneCommand() + self.output = FixedOutput() + + def process(self): + self.html = ['
      '] + +class EmphaticText(TaggedText): + "Text with emphatic mode" + + def process(self): + self.output.tag = 'i' + +class ShapedText(TaggedText): + "Text shaped (italic, slanted)" + + def process(self): + self.type = self.header[1] + if not self.type in TagConfig.shaped: + Trace.error('Unrecognized shape ' + self.header[1]) + self.output.tag = 'span' + return + self.output.tag = TagConfig.shaped[self.type] + +class VersalitasText(TaggedText): + "Text in versalitas" + + def process(self): + self.output.tag = 'span class="versalitas"' + +class ColorText(TaggedText): + "Colored text" + + def process(self): + self.color = self.header[1] + self.output.tag = 'span class="' + self.color + '"' + +class SizeText(TaggedText): + "Sized text" + + def process(self): + self.size = self.header[1] + self.output.tag = 'span class="' + self.size + '"' + +class BoldText(TaggedText): + "Bold text" + + def process(self): + self.output.tag = 'b' + +class TextFamily(TaggedText): + "A bit of text from elyxer.a different family" + + def process(self): + "Parse the type of family" + self.type = self.header[1] + if not self.type in TagConfig.family: + Trace.error('Unrecognized family ' + type) + self.output.tag = 'span' + return + self.output.tag = TagConfig.family[self.type] + +class Hfill(TaggedText): + "Horizontall fill" + + def process(self): + self.output.tag = 'span class="hfill"' + +class BarredText(TaggedText): + "Text with a bar somewhere" + + def process(self): + "Parse the type of bar" + self.type = self.header[1] + if not self.type in TagConfig.barred: + Trace.error('Unknown bar type ' + self.type) + self.output.tag = 'span' + return + self.output.tag = TagConfig.barred[self.type] + +class LangLine(TaggedText): + "A line with language information" + + def process(self): + "Only generate a span with lang info when the language is recognized." + lang = self.header[1] + if not lang in TranslationConfig.languages: + self.output = ContentsOutput() + return + isolang = TranslationConfig.languages[lang] + self.output = TaggedOutput().settag('span lang="' + isolang + '"', False) + +class InsetLength(BlackBox): + "A length measure inside an inset." + + def process(self): + self.length = self.header[1] + +class Space(Container): + "A space of several types" + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + + def process(self): + self.type = self.header[2] + if self.type not in StyleConfig.hspaces: + Trace.error('Unknown space type ' + self.type) + self.html = [' '] + return + self.html = [StyleConfig.hspaces[self.type]] + length = self.getlength() + if not length: + return + self.output = TaggedOutput().settag('span class="hspace"', False) + ContainerSize().set(length).addstyle(self) + + def getlength(self): + "Get the space length from elyxer.the contents or parameters." + if len(self.contents) == 0 or not isinstance(self.contents[0], InsetLength): + return None + return self.contents[0].length + +class VerticalSpace(Container): + "An inset that contains a vertical space." + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + + def process(self): + "Set the correct tag" + self.type = self.header[2] + if self.type not in StyleConfig.vspaces: + self.output = TaggedOutput().settag('div class="vspace" style="height: ' + self.type + ';"', True) + return + self.html = [StyleConfig.vspaces[self.type]] + +class Align(Container): + "Bit of aligned text" + + def __init__(self): + self.parser = ExcludingParser() + self.output = TaggedOutput().setbreaklines(True) + + def process(self): + self.output.tag = 'div class="' + self.header[1] + '"' + +class Newline(Container): + "A newline" + + def __init__(self): + self.parser = LoneCommand() + self.output = FixedOutput() + + def process(self): + "Process contents" + self.html = ['
      \n'] + +class NewPage(Newline): + "A new page" + + def process(self): + "Process contents" + self.html = ['


      \n

      \n'] + +class Separator(Container): + "A separator string which is not extracted by extracttext()." + + def __init__(self, constant): + self.output = FixedOutput() + self.contents = [] + self.html = [constant] + +class StrikeOut(TaggedText): + "Striken out text." + + def process(self): + "Set the output tag to strike." + self.output.tag = 'strike' + +class StartAppendix(BlackBox): + "Mark to start an appendix here." + "From this point on, all chapters become appendices." + + def process(self): + "Activate the special numbering scheme for appendices, using letters." + NumberGenerator.generator.startappendix() + + + + + + +class Link(Container): + "A link to another part of the document" + + anchor = None + url = None + type = None + page = None + target = None + destination = None + title = None + + def __init__(self): + "Initialize the link, add target if configured." + self.contents = [] + self.parser = InsetParser() + self.output = LinkOutput() + if Options.target: + self.target = Options.target + + def complete(self, text, anchor = None, url = None, type = None, title = None): + "Complete the link." + self.contents = [Constant(text)] + if anchor: + self.anchor = anchor + if url: + self.url = url + if type: + self.type = type + if title: + self.title = title + return self + + def computedestination(self): + "Use the destination link to fill in the destination URL." + if not self.destination: + return + self.url = '' + if self.destination.anchor: + self.url = '#' + self.destination.anchor + if self.destination.page: + self.url = self.destination.page + self.url + + def setmutualdestination(self, destination): + "Set another link as destination, and set its destination to this one." + self.destination = destination + destination.destination = self + + def __unicode__(self): + "Return a printable representation." + result = 'Link' + if self.anchor: + result += ' #' + self.anchor + if self.url: + result += ' to ' + self.url + return result + +class URL(Link): + "A clickable URL" + + def process(self): + "Read URL from elyxer.parameters" + target = self.escape(self.getparameter('target')) + self.url = target + type = self.getparameter('type') + if type: + self.url = self.escape(type) + target + name = self.getparameter('name') + if not name: + name = target + self.contents = [Constant(name)] + +class FlexURL(URL): + "A flexible URL" + + def process(self): + "Read URL from elyxer.contents" + self.url = self.extracttext() + +class LinkOutput(ContainerOutput): + "A link pointing to some destination" + "Or an anchor (destination)" + + def gethtml(self, link): + "Get the HTML code for the link" + type = link.__class__.__name__ + if link.type: + type = link.type + tag = 'a class="' + type + '"' + if link.anchor: + tag += ' name="' + link.anchor + '"' + if link.destination: + link.computedestination() + if link.url: + tag += ' href="' + link.url + '"' + if link.target: + tag += ' target="' + link.target + '"' + if link.title: + tag += ' title="' + link.title + '"' + return TaggedOutput().settag(tag).gethtml(link) + + + + + +class Postprocessor(object): + "Postprocess a container keeping some context" + + stages = [] + + def __init__(self): + self.stages = StageDict(Postprocessor.stages, self) + self.current = None + self.last = None + + def postprocess(self, next): + "Postprocess a container and its contents." + self.postrecursive(self.current) + result = self.postcurrent(next) + self.last = self.current + self.current = next + return result + + def postrecursive(self, container): + "Postprocess the container contents recursively" + if not hasattr(container, 'contents'): + return + if len(container.contents) == 0: + return + if hasattr(container, 'postprocess'): + if not container.postprocess: + return + postprocessor = Postprocessor() + contents = [] + for element in container.contents: + post = postprocessor.postprocess(element) + if post: + contents.append(post) + # two rounds to empty the pipeline + for i in range(2): + post = postprocessor.postprocess(None) + if post: + contents.append(post) + container.contents = contents + + def postcurrent(self, next): + "Postprocess the current element taking into account next and last." + stage = self.stages.getstage(self.current) + if not stage: + return self.current + return stage.postprocess(self.last, self.current, next) + +class StageDict(object): + "A dictionary of stages corresponding to classes" + + def __init__(self, classes, postprocessor): + "Instantiate an element from elyxer.each class and store as a dictionary" + instances = self.instantiate(classes, postprocessor) + self.stagedict = dict([(x.processedclass, x) for x in instances]) + + def instantiate(self, classes, postprocessor): + "Instantiate an element from elyxer.each class" + stages = [x.__new__(x) for x in classes] + for element in stages: + element.__init__() + element.postprocessor = postprocessor + return stages + + def getstage(self, element): + "Get the stage for a given element, if the type is in the dict" + if not element.__class__ in self.stagedict: + return None + return self.stagedict[element.__class__] + + + +class Label(Link): + "A label to be referenced" + + names = dict() + lastlayout = None + + def __init__(self): + Link.__init__(self) + self.lastnumbered = None + + def process(self): + "Process a label container." + key = self.getparameter('name') + self.create(' ', key) + self.lastnumbered = Label.lastlayout + + def create(self, text, key, type = 'Label'): + "Create the label for a given key." + self.key = key + self.complete(text, anchor = key, type = type) + Label.names[key] = self + if key in Reference.references: + for reference in Reference.references[key]: + reference.destination = self + return self + + def findpartkey(self): + "Get the part key for the latest numbered container seen." + numbered = self.numbered(self) + if numbered and numbered.partkey: + return numbered.partkey + return '' + + def numbered(self, container): + "Get the numbered container for the label." + if container.partkey: + return container + if not container.parent: + if self.lastnumbered: + return self.lastnumbered + return None + return self.numbered(container.parent) + + def __unicode__(self): + "Return a printable representation." + if not hasattr(self, 'key'): + return 'Unnamed label' + return 'Label ' + self.key + +class Reference(Link): + "A reference to a label." + + references = dict() + key = 'none' + + def process(self): + "Read the reference and set the arrow." + self.key = self.getparameter('reference') + if self.key in Label.names: + self.direction = u'↑' + label = Label.names[self.key] + else: + self.direction = u'↓' + label = Label().complete(' ', self.key, 'preref') + self.destination = label + self.formatcontents() + if not self.key in Reference.references: + Reference.references[self.key] = [] + Reference.references[self.key].append(self) + + def formatcontents(self): + "Format the reference contents." + formatkey = self.getparameter('LatexCommand') + if not formatkey: + formatkey = 'ref' + self.formatted = u'↕' + if formatkey in StyleConfig.referenceformats: + self.formatted = StyleConfig.referenceformats[formatkey] + else: + Trace.error('Unknown reference format ' + formatkey) + self.replace(u'↕', self.direction) + self.replace('#', '1') + self.replace('on-page', Translator.translate('on-page')) + partkey = self.destination.findpartkey() + # only if partkey and partkey.number are not null, send partkey.number + self.replace('@', partkey and partkey.number) + self.replace(u'¶', partkey and partkey.tocentry) + if not '$' in self.formatted or not partkey or not partkey.titlecontents: + # there is a $ left, but it should go away on preprocessing + self.contents = [Constant(self.formatted)] + return + pieces = self.formatted.split('$') + self.contents = [Constant(pieces[0])] + for piece in pieces[1:]: + self.contents += partkey.titlecontents + self.contents.append(Constant(piece)) + + def replace(self, key, value): + "Replace a key in the format template with a value." + if not key in self.formatted: + return + if not value: + value = '' + self.formatted = self.formatted.replace(key, value) + + def __unicode__(self): + "Return a printable representation." + return 'Reference ' + self.key + + + +class FormulaCommand(FormulaBit): + "A LaTeX command inside a formula" + + types = [] + start = FormulaConfig.starts['command'] + commandmap = None + + def detect(self, pos): + "Find the current command." + return pos.checkfor(FormulaCommand.start) + + def parsebit(self, pos): + "Parse the command." + command = self.extractcommand(pos) + bit = self.parsewithcommand(command, pos) + if bit: + return bit + if command.startswith('\\up') or command.startswith('\\Up'): + upgreek = self.parseupgreek(command, pos) + if upgreek: + return upgreek + if not self.factory.defining: + Trace.error('Unknown command ' + command) + self.output = TaggedOutput().settag('span class="unknown"') + self.add(FormulaConstant(command)) + return None + + def parsewithcommand(self, command, pos): + "Parse the command type once we have the command." + for type in FormulaCommand.types: + if command in type.commandmap: + return self.parsecommandtype(command, type, pos) + return None + + def parsecommandtype(self, command, type, pos): + "Parse a given command type." + bit = self.factory.create(type) + bit.setcommand(command) + returned = bit.parsebit(pos) + if returned: + return returned + return bit + + def extractcommand(self, pos): + "Extract the command from elyxer.the current position." + if not pos.checkskip(FormulaCommand.start): + pos.error('Missing command start ' + FormulaCommand.start) + return + if pos.finished(): + return self.emptycommand(pos) + if pos.current().isalpha(): + # alpha command + command = FormulaCommand.start + pos.globalpha() + # skip mark of short command + pos.checkskip('*') + return command + # symbol command + return FormulaCommand.start + pos.skipcurrent() + + def emptycommand(self, pos): + """Check for an empty command: look for command disguised as ending. + Special case against '{ \{ \} }' situation.""" + command = '' + if not pos.isout(): + ending = pos.nextending() + if ending and pos.checkskip(ending): + command = ending + return FormulaCommand.start + command + + def parseupgreek(self, command, pos): + "Parse the Greek \\up command.." + if len(command) < 4: + return None + if command.startswith('\\up'): + upcommand = '\\' + command[3:] + elif pos.checkskip('\\Up'): + upcommand = '\\' + command[3:4].upper() + command[4:] + else: + Trace.error('Impossible upgreek command: ' + command) + return + upgreek = self.parsewithcommand(upcommand, pos) + if upgreek: + upgreek.type = 'font' + return upgreek + +class CommandBit(FormulaCommand): + "A formula bit that includes a command" + + def setcommand(self, command): + "Set the command in the bit" + self.command = command + if self.commandmap: + self.original += command + self.translated = self.commandmap[self.command] + + def parseparameter(self, pos): + "Parse a parameter at the current position" + self.factory.clearskipped(pos) + if pos.finished(): + return None + parameter = self.factory.parseany(pos) + self.add(parameter) + return parameter + + def parsesquare(self, pos): + "Parse a square bracket" + self.factory.clearskipped(pos) + if not self.factory.detecttype(SquareBracket, pos): + return None + bracket = self.factory.parsetype(SquareBracket, pos) + self.add(bracket) + return bracket + + def parseliteral(self, pos): + "Parse a literal bracket." + self.factory.clearskipped(pos) + if not self.factory.detecttype(Bracket, pos): + if not pos.isvalue(): + Trace.error('No literal parameter found at: ' + pos.identifier()) + return None + return pos.globvalue() + bracket = Bracket().setfactory(self.factory) + self.add(bracket.parseliteral(pos)) + return bracket.literal + + def parsesquareliteral(self, pos): + "Parse a square bracket literally." + self.factory.clearskipped(pos) + if not self.factory.detecttype(SquareBracket, pos): + return None + bracket = SquareBracket().setfactory(self.factory) + self.add(bracket.parseliteral(pos)) + return bracket.literal + + def parsetext(self, pos): + "Parse a text parameter." + self.factory.clearskipped(pos) + if not self.factory.detecttype(Bracket, pos): + Trace.error('No text parameter for ' + self.command) + return None + bracket = Bracket().setfactory(self.factory).parsetext(pos) + self.add(bracket) + return bracket + +class EmptyCommand(CommandBit): + "An empty command (without parameters)" + + commandmap = FormulaConfig.commands + + def parsebit(self, pos): + "Parse a command without parameters" + self.contents = [FormulaConstant(self.translated)] + +class SpacedCommand(CommandBit): + "An empty command which should have math spacing in formulas." + + commandmap = FormulaConfig.spacedcommands + + def parsebit(self, pos): + "Place as contents the command translated and spaced." + self.contents = [FormulaConstant(u' ' + self.translated + u' ')] + +class AlphaCommand(EmptyCommand): + "A command without paramters whose result is alphabetical" + + commandmap = FormulaConfig.alphacommands + + def parsebit(self, pos): + "Parse the command and set type to alpha" + EmptyCommand.parsebit(self, pos) + self.type = 'alpha' + +class OneParamFunction(CommandBit): + "A function of one parameter" + + commandmap = FormulaConfig.onefunctions + simplified = False + + def parsebit(self, pos): + "Parse a function with one parameter" + self.output = TaggedOutput().settag(self.translated) + self.parseparameter(pos) + self.simplifyifpossible() + + def simplifyifpossible(self): + "Try to simplify to a single character." + if self.original in self.commandmap: + self.output = FixedOutput() + self.html = [self.commandmap[self.original]] + self.simplified = True + +class SymbolFunction(CommandBit): + "Find a function which is represented by a symbol (like _ or ^)" + + commandmap = FormulaConfig.symbolfunctions + + def detect(self, pos): + "Find the symbol" + return pos.current() in SymbolFunction.commandmap + + def parsebit(self, pos): + "Parse the symbol" + self.setcommand(pos.current()) + pos.skip(self.command) + self.output = TaggedOutput().settag(self.translated) + self.parseparameter(pos) + +class TextFunction(CommandBit): + "A function where parameters are read as text." + + commandmap = FormulaConfig.textfunctions + + def parsebit(self, pos): + "Parse a text parameter" + self.output = TaggedOutput().settag(self.translated) + self.parsetext(pos) + + def process(self): + "Set the type to font" + self.type = 'font' + +class LabelFunction(CommandBit): + "A function that acts as a label" + + commandmap = FormulaConfig.labelfunctions + + def parsebit(self, pos): + "Parse a literal parameter" + self.key = self.parseliteral(pos) + + def process(self): + "Add an anchor with the label contents." + self.type = 'font' + self.label = Label().create(' ', self.key, type = 'eqnumber') + self.contents = [self.label] + # store as a Label so we know it's been seen + Label.names[self.key] = self.label + +class FontFunction(OneParamFunction): + "A function of one parameter that changes the font" + + commandmap = FormulaConfig.fontfunctions + + def process(self): + "Simplify if possible using a single character." + self.type = 'font' + self.simplifyifpossible() + +FormulaFactory.types += [FormulaCommand, SymbolFunction] +FormulaCommand.types = [ + AlphaCommand, EmptyCommand, OneParamFunction, FontFunction, LabelFunction, + TextFunction, SpacedCommand, + ] + + + + + + + + + + + + +class BigSymbol(object): + "A big symbol generator." + + symbols = FormulaConfig.bigsymbols + + def __init__(self, symbol): + "Create the big symbol." + self.symbol = symbol + + def getpieces(self): + "Get an array with all pieces." + if not self.symbol in self.symbols: + return [self.symbol] + if self.smalllimit(): + return [self.symbol] + return self.symbols[self.symbol] + + def smalllimit(self): + "Decide if the limit should be a small, one-line symbol." + if not DocumentParameters.displaymode: + return True + if len(self.symbols[self.symbol]) == 1: + return True + return Options.simplemath + +class BigBracket(BigSymbol): + "A big bracket generator." + + def __init__(self, size, bracket, alignment='l'): + "Set the size and symbol for the bracket." + self.size = size + self.original = bracket + self.alignment = alignment + self.pieces = None + if bracket in FormulaConfig.bigbrackets: + self.pieces = FormulaConfig.bigbrackets[bracket] + + def getpiece(self, index): + "Return the nth piece for the bracket." + function = getattr(self, 'getpiece' + unicode(len(self.pieces))) + return function(index) + + def getpiece1(self, index): + "Return the only piece for a single-piece bracket." + return self.pieces[0] + + def getpiece3(self, index): + "Get the nth piece for a 3-piece bracket: parenthesis or square bracket." + if index == 0: + return self.pieces[0] + if index == self.size - 1: + return self.pieces[-1] + return self.pieces[1] + + def getpiece4(self, index): + "Get the nth piece for a 4-piece bracket: curly bracket." + if index == 0: + return self.pieces[0] + if index == self.size - 1: + return self.pieces[3] + if index == (self.size - 1)/2: + return self.pieces[2] + return self.pieces[1] + + def getcell(self, index): + "Get the bracket piece as an array cell." + piece = self.getpiece(index) + span = 'span class="bracket align-' + self.alignment + '"' + return TaggedBit().constant(piece, span) + + def getcontents(self): + "Get the bracket as an array or as a single bracket." + if self.size == 1 or not self.pieces: + return self.getsinglebracket() + rows = [] + for index in range(self.size): + cell = self.getcell(index) + rows.append(TaggedBit().complete([cell], 'span class="arrayrow"')) + return [TaggedBit().complete(rows, 'span class="array"')] + + def getsinglebracket(self): + "Return the bracket as a single sign." + if self.original == '.': + return [TaggedBit().constant('', 'span class="emptydot"')] + return [TaggedBit().constant(self.original, 'span class="symbol"')] + + + + + + +class FormulaEquation(CommandBit): + "A simple numbered equation." + + piece = 'equation' + + def parsebit(self, pos): + "Parse the array" + self.output = ContentsOutput() + self.add(self.factory.parsetype(WholeFormula, pos)) + +class FormulaCell(FormulaCommand): + "An array cell inside a row" + + def setalignment(self, alignment): + self.alignment = alignment + self.output = TaggedOutput().settag('span class="arraycell align-' + alignment +'"', True) + return self + + def parsebit(self, pos): + self.factory.clearskipped(pos) + if pos.finished(): + return + self.add(self.factory.parsetype(WholeFormula, pos)) + +class FormulaRow(FormulaCommand): + "An array row inside an array" + + cellseparator = FormulaConfig.array['cellseparator'] + + def setalignments(self, alignments): + self.alignments = alignments + self.output = TaggedOutput().settag('span class="arrayrow"', True) + return self + + def parsebit(self, pos): + "Parse a whole row" + index = 0 + pos.pushending(self.cellseparator, optional=True) + while not pos.finished(): + cell = self.createcell(index) + cell.parsebit(pos) + self.add(cell) + index += 1 + pos.checkskip(self.cellseparator) + if len(self.contents) == 0: + self.output = EmptyOutput() + + def createcell(self, index): + "Create the cell that corresponds to the given index." + alignment = self.alignments[index % len(self.alignments)] + return self.factory.create(FormulaCell).setalignment(alignment) + +class MultiRowFormula(CommandBit): + "A formula with multiple rows." + + def parserows(self, pos): + "Parse all rows, finish when no more row ends" + self.rows = [] + first = True + for row in self.iteraterows(pos): + if first: + first = False + else: + # intersparse empty rows + self.addempty() + row.parsebit(pos) + self.addrow(row) + self.size = len(self.rows) + + def iteraterows(self, pos): + "Iterate over all rows, end when no more row ends" + rowseparator = FormulaConfig.array['rowseparator'] + while True: + pos.pushending(rowseparator, True) + row = self.factory.create(FormulaRow) + yield row.setalignments(self.alignments) + if pos.checkfor(rowseparator): + self.original += pos.popending(rowseparator) + else: + return + + def addempty(self): + "Add an empty row." + row = self.factory.create(FormulaRow).setalignments(self.alignments) + for index, originalcell in enumerate(self.rows[-1].contents): + cell = row.createcell(index) + cell.add(FormulaConstant(u' ')) + row.add(cell) + self.addrow(row) + + def addrow(self, row): + "Add a row to the contents and to the list of rows." + self.rows.append(row) + self.add(row) + +class FormulaArray(MultiRowFormula): + "An array within a formula" + + piece = 'array' + + def parsebit(self, pos): + "Parse the array" + self.output = TaggedOutput().settag('span class="array"', False) + self.parsealignments(pos) + self.parserows(pos) + + def parsealignments(self, pos): + "Parse the different alignments" + # vertical + self.valign = 'c' + literal = self.parsesquareliteral(pos) + if literal: + self.valign = literal + # horizontal + literal = self.parseliteral(pos) + self.alignments = [] + for l in literal: + self.alignments.append(l) + +class FormulaMatrix(MultiRowFormula): + "A matrix (array with center alignment)." + + piece = 'matrix' + + def parsebit(self, pos): + "Parse the matrix, set alignments to 'c'." + self.output = TaggedOutput().settag('span class="array"', False) + self.valign = 'c' + self.alignments = ['c'] + self.parserows(pos) + +class FormulaCases(MultiRowFormula): + "A cases statement" + + piece = 'cases' + + def parsebit(self, pos): + "Parse the cases" + self.output = ContentsOutput() + self.alignments = ['l', 'l'] + self.parserows(pos) + for row in self.contents: + for cell in row.contents: + cell.output.settag('span class="case align-l"', True) + cell.contents.append(FormulaConstant(u' ')) + array = TaggedBit().complete(self.contents, 'span class="bracketcases"', True) + brace = BigBracket(len(self.contents), '{', 'l') + self.contents = brace.getcontents() + [array] + +class EquationEnvironment(MultiRowFormula): + "A \\begin{}...\\end equation environment with rows and cells." + + def parsebit(self, pos): + "Parse the whole environment." + self.output = TaggedOutput().settag('span class="environment"', False) + environment = self.piece.replace('*', '') + if environment in FormulaConfig.environments: + self.alignments = FormulaConfig.environments[environment] + else: + Trace.error('Unknown equation environment ' + self.piece) + self.alignments = ['l'] + self.parserows(pos) + +class BeginCommand(CommandBit): + "A \\begin{}...\end command and what it entails (array, cases, aligned)" + + commandmap = {FormulaConfig.array['begin']:''} + + types = [FormulaEquation, FormulaArray, FormulaCases, FormulaMatrix] + + def parsebit(self, pos): + "Parse the begin command" + command = self.parseliteral(pos) + bit = self.findbit(command) + ending = FormulaConfig.array['end'] + '{' + command + '}' + pos.pushending(ending) + bit.parsebit(pos) + self.add(bit) + self.original += pos.popending(ending) + self.size = bit.size + + def findbit(self, piece): + "Find the command bit corresponding to the \\begin{piece}" + for type in BeginCommand.types: + if piece.replace('*', '') == type.piece: + return self.factory.create(type) + bit = self.factory.create(EquationEnvironment) + bit.piece = piece + return bit + +FormulaCommand.types += [BeginCommand] + + +import datetime + + +class CombiningFunction(OneParamFunction): + + commandmap = FormulaConfig.combiningfunctions + + def parsebit(self, pos): + "Parse a combining function." + self.type = 'alpha' + combining = self.translated + parameter = self.parsesingleparameter(pos) + if not parameter: + Trace.error('Empty parameter for combining function ' + self.command) + elif len(parameter.extracttext()) != 1: + Trace.error('Applying combining function ' + self.command + ' to invalid string "' + parameter.extracttext() + '"') + self.contents.append(Constant(combining)) + + def parsesingleparameter(self, pos): + "Parse a parameter, or a single letter." + self.factory.clearskipped(pos) + if pos.finished(): + Trace.error('Error while parsing single parameter at ' + pos.identifier()) + return None + if self.factory.detecttype(Bracket, pos) \ + or self.factory.detecttype(FormulaCommand, pos): + return self.parseparameter(pos) + letter = FormulaConstant(pos.skipcurrent()) + self.add(letter) + return letter + +class DecoratingFunction(OneParamFunction): + "A function that decorates some bit of text" + + commandmap = FormulaConfig.decoratingfunctions + + def parsebit(self, pos): + "Parse a decorating function" + self.type = 'alpha' + symbol = self.translated + self.symbol = TaggedBit().constant(symbol, 'span class="symbolover"') + self.parameter = self.parseparameter(pos) + self.output = TaggedOutput().settag('span class="withsymbol"') + self.contents.insert(0, self.symbol) + self.parameter.output = TaggedOutput().settag('span class="undersymbol"') + self.simplifyifpossible() + +class LimitCommand(EmptyCommand): + "A command which accepts limits above and below, in display mode." + + commandmap = FormulaConfig.limitcommands + + def parsebit(self, pos): + "Parse a limit command." + pieces = BigSymbol(self.translated).getpieces() + self.output = TaggedOutput().settag('span class="limits"') + for piece in pieces: + self.contents.append(TaggedBit().constant(piece, 'span class="limit"')) + +class LimitPreviousCommand(LimitCommand): + "A command to limit the previous command." + + commandmap = None + + def parsebit(self, pos): + "Do nothing." + self.output = TaggedOutput().settag('span class="limits"') + self.factory.clearskipped(pos) + + def __unicode__(self): + "Return a printable representation." + return 'Limit previous command' + +class LimitsProcessor(MathsProcessor): + "A processor for limits inside an element." + + def process(self, contents, index): + "Process the limits for an element." + if Options.simplemath: + return + if self.checklimits(contents, index): + self.modifylimits(contents, index) + if self.checkscript(contents, index) and self.checkscript(contents, index + 1): + self.modifyscripts(contents, index) + + def checklimits(self, contents, index): + "Check if the current position has a limits command." + if not DocumentParameters.displaymode: + return False + if self.checkcommand(contents, index + 1, LimitPreviousCommand): + self.limitsahead(contents, index) + return False + if not isinstance(contents[index], LimitCommand): + return False + return self.checkscript(contents, index + 1) + + def limitsahead(self, contents, index): + "Limit the current element based on the next." + contents[index + 1].add(contents[index].clone()) + contents[index].output = EmptyOutput() + + def modifylimits(self, contents, index): + "Modify a limits commands so that the limits appear above and below." + limited = contents[index] + subscript = self.getlimit(contents, index + 1) + limited.contents.append(subscript) + if self.checkscript(contents, index + 1): + superscript = self.getlimit(contents, index + 1) + else: + superscript = TaggedBit().constant(u' ', 'sup class="limit"') + limited.contents.insert(0, superscript) + + def getlimit(self, contents, index): + "Get the limit for a limits command." + limit = self.getscript(contents, index) + limit.output.tag = limit.output.tag.replace('script', 'limit') + return limit + + def modifyscripts(self, contents, index): + "Modify the super- and subscript to appear vertically aligned." + subscript = self.getscript(contents, index) + # subscript removed so instead of index + 1 we get index again + superscript = self.getscript(contents, index) + scripts = TaggedBit().complete([superscript, subscript], 'span class="scripts"') + contents.insert(index, scripts) + + def checkscript(self, contents, index): + "Check if the current element is a sub- or superscript." + return self.checkcommand(contents, index, SymbolFunction) + + def checkcommand(self, contents, index, type): + "Check for the given type as the current element." + if len(contents) <= index: + return False + return isinstance(contents[index], type) + + def getscript(self, contents, index): + "Get the sub- or superscript." + bit = contents[index] + bit.output.tag += ' class="script"' + del contents[index] + return bit + +class BracketCommand(OneParamFunction): + "A command which defines a bracket." + + commandmap = FormulaConfig.bracketcommands + + def parsebit(self, pos): + "Parse the bracket." + OneParamFunction.parsebit(self, pos) + + def create(self, direction, character): + "Create the bracket for the given character." + self.original = character + self.command = '\\' + direction + self.contents = [FormulaConstant(character)] + return self + +class BracketProcessor(MathsProcessor): + "A processor for bracket commands." + + def process(self, contents, index): + "Convert the bracket using Unicode pieces, if possible." + if Options.simplemath: + return + if self.checkleft(contents, index): + return self.processleft(contents, index) + + def processleft(self, contents, index): + "Process a left bracket." + rightindex = self.findright(contents, index + 1) + if not rightindex: + return + size = self.findmax(contents, index, rightindex) + self.resize(contents[index], size) + self.resize(contents[rightindex], size) + + def checkleft(self, contents, index): + "Check if the command at the given index is left." + return self.checkdirection(contents[index], '\\left') + + def checkright(self, contents, index): + "Check if the command at the given index is right." + return self.checkdirection(contents[index], '\\right') + + def checkdirection(self, bit, command): + "Check if the given bit is the desired bracket command." + if not isinstance(bit, BracketCommand): + return False + return bit.command == command + + def findright(self, contents, index): + "Find the right bracket starting at the given index, or 0." + depth = 1 + while index < len(contents): + if self.checkleft(contents, index): + depth += 1 + if self.checkright(contents, index): + depth -= 1 + if depth == 0: + return index + index += 1 + return None + + def findmax(self, contents, leftindex, rightindex): + "Find the max size of the contents between the two given indices." + sliced = contents[leftindex:rightindex] + return max([element.size for element in sliced]) + + def resize(self, command, size): + "Resize a bracket command to the given size." + character = command.extracttext() + alignment = command.command.replace('\\', '') + bracket = BigBracket(size, character, alignment) + command.output = ContentsOutput() + command.contents = bracket.getcontents() + +class TodayCommand(EmptyCommand): + "Shows today's date." + + commandmap = None + + def parsebit(self, pos): + "Parse a command without parameters" + self.output = FixedOutput() + self.html = [datetime.date.today().strftime('%b %d, %Y')] + + +FormulaCommand.types += [ + DecoratingFunction, CombiningFunction, LimitCommand, BracketCommand, + ] + +FormulaProcessor.processors += [ + LimitsProcessor(), BracketProcessor(), + ] + + + +class ParameterDefinition(object): + "The definition of a parameter in a hybrid function." + "[] parameters are optional, {} parameters are mandatory." + "Each parameter has a one-character name, like {$1} or {$p}." + "A parameter that ends in ! like {$p!} is a literal." + "Example: [$1]{$p!} reads an optional parameter $1 and a literal mandatory parameter p." + + parambrackets = [('[', ']'), ('{', '}')] + + def __init__(self): + self.name = None + self.literal = False + self.optional = False + self.value = None + self.literalvalue = None + + def parse(self, pos): + "Parse a parameter definition: [$0], {$x}, {$1!}..." + for (opening, closing) in ParameterDefinition.parambrackets: + if pos.checkskip(opening): + if opening == '[': + self.optional = True + if not pos.checkskip('$'): + Trace.error('Wrong parameter name, did you mean $' + pos.current() + '?') + return None + self.name = pos.skipcurrent() + if pos.checkskip('!'): + self.literal = True + if not pos.checkskip(closing): + Trace.error('Wrong parameter closing ' + pos.skipcurrent()) + return None + return self + Trace.error('Wrong character in parameter template: ' + pos.skipcurrent()) + return None + + def read(self, pos, function): + "Read the parameter itself using the definition." + if self.literal: + if self.optional: + self.literalvalue = function.parsesquareliteral(pos) + else: + self.literalvalue = function.parseliteral(pos) + if self.literalvalue: + self.value = FormulaConstant(self.literalvalue) + elif self.optional: + self.value = function.parsesquare(pos) + else: + self.value = function.parseparameter(pos) + + def __unicode__(self): + "Return a printable representation." + result = 'param ' + self.name + if self.value: + result += ': ' + unicode(self.value) + else: + result += ' (empty)' + return result + +class ParameterFunction(CommandBit): + "A function with a variable number of parameters defined in a template." + "The parameters are defined as a parameter definition." + + def readparams(self, readtemplate, pos): + "Read the params according to the template." + self.params = dict() + for paramdef in self.paramdefs(readtemplate): + paramdef.read(pos, self) + self.params['$' + paramdef.name] = paramdef + + def paramdefs(self, readtemplate): + "Read each param definition in the template" + pos = TextPosition(readtemplate) + while not pos.finished(): + paramdef = ParameterDefinition().parse(pos) + if paramdef: + yield paramdef + + def getparam(self, name): + "Get a parameter as parsed." + if not name in self.params: + return None + return self.params[name] + + def getvalue(self, name): + "Get the value of a parameter." + return self.getparam(name).value + + def getliteralvalue(self, name): + "Get the literal value of a parameter." + param = self.getparam(name) + if not param or not param.literalvalue: + return None + return param.literalvalue + +class HybridFunction(ParameterFunction): + """ + A parameter function where the output is also defined using a template. + The template can use a number of functions; each function has an associated + tag. + Example: [f0{$1},span class="fbox"] defines a function f0 which corresponds + to a span of class fbox, yielding $1. + Literal parameters can be used in tags definitions: + [f0{$1},span style="color: $p;"] + yields $1, where $p is a literal parameter. + Sizes can be specified in hybridsizes, e.g. adding parameter sizes. By + default the resulting size is the max of all arguments. Sizes are used + to generate the right parameters. + A function followed by a single / is output as a self-closing XHTML tag: + [f0/,hr] + will generate
      . + """ + + commandmap = FormulaConfig.hybridfunctions + + def parsebit(self, pos): + "Parse a function with [] and {} parameters" + readtemplate = self.translated[0] + writetemplate = self.translated[1] + self.readparams(readtemplate, pos) + self.contents = self.writeparams(writetemplate) + self.computehybridsize() + + def writeparams(self, writetemplate): + "Write all params according to the template" + return self.writepos(TextPosition(writetemplate)) + + def writepos(self, pos): + "Write all params as read in the parse position." + result = [] + while not pos.finished(): + if pos.checkskip('$'): + param = self.writeparam(pos) + if param: + result.append(param) + elif pos.checkskip('f'): + function = self.writefunction(pos) + if function: + function.type = None + result.append(function) + elif pos.checkskip('('): + result.append(self.writebracket('left', '(')) + elif pos.checkskip(')'): + result.append(self.writebracket('right', ')')) + else: + result.append(FormulaConstant(pos.skipcurrent())) + return result + + def writeparam(self, pos): + "Write a single param of the form $0, $x..." + name = '$' + pos.skipcurrent() + if not name in self.params: + Trace.error('Unknown parameter ' + name) + return None + if not self.params[name]: + return None + if pos.checkskip('.'): + self.params[name].value.type = pos.globalpha() + return self.params[name].value + + def writefunction(self, pos): + "Write a single function f0,...,fn." + tag = self.readtag(pos) + if not tag: + return None + if pos.checkskip('/'): + # self-closing XHTML tag, such as
      + return TaggedBit().selfcomplete(tag) + if not pos.checkskip('{'): + Trace.error('Function should be defined in {}') + return None + pos.pushending('}') + contents = self.writepos(pos) + pos.popending() + if len(contents) == 0: + return None + return TaggedBit().complete(contents, tag) + + def readtag(self, pos): + "Get the tag corresponding to the given index. Does parameter substitution." + if not pos.current().isdigit(): + Trace.error('Function should be f0,...,f9: f' + pos.current()) + return None + index = int(pos.skipcurrent()) + if 2 + index > len(self.translated): + Trace.error('Function f' + unicode(index) + ' is not defined') + return None + tag = self.translated[2 + index] + if not '$' in tag: + return tag + for variable in self.params: + if variable in tag: + param = self.params[variable] + if not param.literal: + Trace.error('Parameters in tag ' + tag + ' should be literal: {' + variable + '!}') + continue + if param.literalvalue: + value = param.literalvalue + else: + value = '' + tag = tag.replace(variable, value) + return tag + + def writebracket(self, direction, character): + "Return a new bracket looking at the given direction." + return self.factory.create(BracketCommand).create(direction, character) + + def computehybridsize(self): + "Compute the size of the hybrid function." + if not self.command in HybridSize.configsizes: + self.computesize() + return + self.size = HybridSize().getsize(self) + # set the size in all elements at first level + for element in self.contents: + element.size = self.size + +class HybridSize(object): + "The size associated with a hybrid function." + + configsizes = FormulaConfig.hybridsizes + + def getsize(self, function): + "Read the size for a function and parse it." + sizestring = self.configsizes[function.command] + for name in function.params: + if name in sizestring: + size = function.params[name].value.computesize() + sizestring = sizestring.replace(name, unicode(size)) + if '$' in sizestring: + Trace.error('Unconverted variable in hybrid size: ' + sizestring) + return 1 + return eval(sizestring) + + +FormulaCommand.types += [HybridFunction] + + + + + + + + + +class HeaderParser(Parser): + "Parses the LyX header" + + def parse(self, reader): + "Parse header parameters into a dictionary, return the preamble." + contents = [] + self.parseending(reader, lambda: self.parseline(reader, contents)) + # skip last line + reader.nextline() + return contents + + def parseline(self, reader, contents): + "Parse a single line as a parameter or as a start" + line = reader.currentline() + if line.startswith(HeaderConfig.parameters['branch']): + self.parsebranch(reader) + return + elif line.startswith(HeaderConfig.parameters['lstset']): + LstParser().parselstset(reader) + return + elif line.startswith(HeaderConfig.parameters['beginpreamble']): + contents.append(self.factory.createcontainer(reader)) + return + # no match + self.parseparameter(reader) + + def parsebranch(self, reader): + "Parse all branch definitions." + branch = reader.currentline().split()[1] + reader.nextline() + subparser = HeaderParser().complete(HeaderConfig.parameters['endbranch']) + subparser.parse(reader) + options = BranchOptions(branch) + for key in subparser.parameters: + options.set(key, subparser.parameters[key]) + Options.branches[branch] = options + + def complete(self, ending): + "Complete the parser with the given ending." + self.ending = ending + return self + +class PreambleParser(Parser): + "A parser for the LyX preamble." + + preamble = [] + + def parse(self, reader): + "Parse the full preamble with all statements." + self.ending = HeaderConfig.parameters['endpreamble'] + self.parseending(reader, lambda: self.parsepreambleline(reader)) + return [] + + def parsepreambleline(self, reader): + "Parse a single preamble line." + PreambleParser.preamble.append(reader.currentline()) + reader.nextline() + +class LstParser(object): + "Parse global and local lstparams." + + globalparams = dict() + + def parselstset(self, reader): + "Parse a declaration of lstparams in lstset." + paramtext = self.extractlstset(reader) + if not '{' in paramtext: + Trace.error('Missing opening bracket in lstset: ' + paramtext) + return + lefttext = paramtext.split('{')[1] + croppedtext = lefttext[:-1] + LstParser.globalparams = self.parselstparams(croppedtext) + + def extractlstset(self, reader): + "Extract the global lstset parameters." + paramtext = '' + while not reader.finished(): + paramtext += reader.currentline() + reader.nextline() + if paramtext.endswith('}'): + return paramtext + Trace.error('Could not find end of \\lstset settings; aborting') + + def parsecontainer(self, container): + "Parse some lstparams from elyxer.a container." + container.lstparams = LstParser.globalparams.copy() + paramlist = container.getparameterlist('lstparams') + container.lstparams.update(self.parselstparams(paramlist)) + + def parselstparams(self, paramlist): + "Process a number of lstparams from elyxer.a list." + paramdict = dict() + for param in paramlist: + if not '=' in param: + if len(param.strip()) > 0: + Trace.error('Invalid listing parameter ' + param) + else: + key, value = param.split('=', 1) + paramdict[key] = value + return paramdict + + + + +class MacroDefinition(CommandBit): + "A function that defines a new command (a macro)." + + macros = dict() + + def parsebit(self, pos): + "Parse the function that defines the macro." + self.output = EmptyOutput() + self.parameternumber = 0 + self.defaults = [] + self.factory.defining = True + self.parseparameters(pos) + self.factory.defining = False + Trace.debug('New command ' + self.newcommand + ' (' + \ + unicode(self.parameternumber) + ' parameters)') + self.macros[self.newcommand] = self + + def parseparameters(self, pos): + "Parse all optional parameters (number of parameters, default values)" + "and the mandatory definition." + self.newcommand = self.parsenewcommand(pos) + # parse number of parameters + literal = self.parsesquareliteral(pos) + if literal: + self.parameternumber = int(literal) + # parse all default values + bracket = self.parsesquare(pos) + while bracket: + self.defaults.append(bracket) + bracket = self.parsesquare(pos) + # parse mandatory definition + self.definition = self.parseparameter(pos) + + def parsenewcommand(self, pos): + "Parse the name of the new command." + self.factory.clearskipped(pos) + if self.factory.detecttype(Bracket, pos): + return self.parseliteral(pos) + if self.factory.detecttype(FormulaCommand, pos): + return self.factory.create(FormulaCommand).extractcommand(pos) + Trace.error('Unknown formula bit in defining function at ' + pos.identifier()) + return 'unknown' + + def instantiate(self): + "Return an instance of the macro." + return self.definition.clone() + +class MacroParameter(FormulaBit): + "A parameter from elyxer.a macro." + + def detect(self, pos): + "Find a macro parameter: #n." + return pos.checkfor('#') + + def parsebit(self, pos): + "Parse the parameter: #n." + if not pos.checkskip('#'): + Trace.error('Missing parameter start #.') + return + self.number = int(pos.skipcurrent()) + self.original = '#' + unicode(self.number) + self.contents = [TaggedBit().constant('#' + unicode(self.number), 'span class="unknown"')] + +class MacroFunction(CommandBit): + "A function that was defined using a macro." + + commandmap = MacroDefinition.macros + + def parsebit(self, pos): + "Parse a number of input parameters." + self.output = FilteredOutput() + self.values = [] + macro = self.translated + self.parseparameters(pos, macro) + self.completemacro(macro) + + def parseparameters(self, pos, macro): + "Parse as many parameters as are needed." + self.parseoptional(pos, list(macro.defaults)) + self.parsemandatory(pos, macro.parameternumber - len(macro.defaults)) + if len(self.values) < macro.parameternumber: + Trace.error('Missing parameters in macro ' + unicode(self)) + + def parseoptional(self, pos, defaults): + "Parse optional parameters." + optional = [] + while self.factory.detecttype(SquareBracket, pos): + optional.append(self.parsesquare(pos)) + if len(optional) > len(defaults): + break + for value in optional: + default = defaults.pop() + if len(value.contents) > 0: + self.values.append(value) + else: + self.values.append(default) + self.values += defaults + + def parsemandatory(self, pos, number): + "Parse a number of mandatory parameters." + for index in range(number): + parameter = self.parsemacroparameter(pos, number - index) + if not parameter: + return + self.values.append(parameter) + + def parsemacroparameter(self, pos, remaining): + "Parse a macro parameter. Could be a bracket or a single letter." + "If there are just two values remaining and there is a running number," + "parse as two separater numbers." + self.factory.clearskipped(pos) + if pos.finished(): + return None + if self.factory.detecttype(FormulaNumber, pos): + return self.parsenumbers(pos, remaining) + return self.parseparameter(pos) + + def parsenumbers(self, pos, remaining): + "Parse the remaining parameters as a running number." + "For example, 12 would be {1}{2}." + number = self.factory.parsetype(FormulaNumber, pos) + if not len(number.original) == remaining: + return number + for digit in number.original: + value = self.factory.create(FormulaNumber) + value.add(FormulaConstant(digit)) + value.type = number + self.values.append(value) + return None + + def completemacro(self, macro): + "Complete the macro with the parameters read." + self.contents = [macro.instantiate()] + replaced = [False] * len(self.values) + for parameter in self.searchall(MacroParameter): + index = parameter.number - 1 + if index >= len(self.values): + Trace.error('Macro parameter index out of bounds: ' + unicode(index)) + return + replaced[index] = True + parameter.contents = [self.values[index].clone()] + for index in range(len(self.values)): + if not replaced[index]: + self.addfilter(index, self.values[index]) + + def addfilter(self, index, value): + "Add a filter for the given parameter number and parameter value." + original = '#' + unicode(index + 1) + value = ''.join(self.values[0].gethtml()) + self.output.addfilter(original, value) + +class FormulaMacro(Formula): + "A math macro defined in an inset." + + def __init__(self): + self.parser = MacroParser() + self.output = EmptyOutput() + + def __unicode__(self): + "Return a printable representation." + return 'Math macro' + +FormulaFactory.types += [ MacroParameter ] + +FormulaCommand.types += [ + MacroFunction, + ] + + + +def math2html(formula): + "Convert some TeX math to HTML." + factory = FormulaFactory() + whole = factory.parseformula(formula) + FormulaProcessor().process(whole) + whole.process() + return ''.join(whole.gethtml()) + +def main(): + "Main function, called if invoked from elyxer.the command line" + args = sys.argv + Options().parseoptions(args) + if len(args) != 1: + Trace.error('Usage: math2html.py escaped_string') + exit() + result = math2html(args[0]) + Trace.message(result) + +if __name__ == '__main__': + main() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/po/createlocale.sh elyxer-1.2.5/forks/jras-elyxer/po/createlocale.sh --- elyxer-1.2.3/forks/jras-elyxer/po/createlocale.sh 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/po/createlocale.sh 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,30 @@ +#!/bin/bash + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Alex 20100218: create locale file + +# create executable + +if test -z "$1" +then + echo "Usage: ./createlocale.sh my, creates my.po for locale my." + exit +fi +msginit --locale=$1 --input=../src/conf/elyxer.pot + diff -Nru elyxer-1.2.3/forks/jras-elyxer/po/de.po elyxer-1.2.5/forks/jras-elyxer/po/de.po --- elyxer-1.2.3/forks/jras-elyxer/po/de.po 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/po/de.po 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,162 @@ +# German translations for eLyXer package +# Deutsch. +# eLyXer version 0.40 +# Released on 2010-01-12 +# Contact: Alex Fernández +# This file is distributed under the same license as the eLyXer package. +# (C) 2010 Uwe Stöhr . +# +msgid "" +msgstr "" +"Project-Id-Version: eLyXer 0.40\n" +"PO-Revision-Date: 2010-01-12 02:37+0100\n" +"Last-Translator: Uwe Stöhr \n" +"Language-Team: Deutsch de>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"POT-Creation-Date: \n" +"X-Poedit-Language: German\n" +"X-Poedit-Country: GERMANY\n" + +#: Subsubsection +msgid "Subsubsection" +msgstr "Unterunterabschnitt" + +#: figure +msgid "figure" +msgstr "Abbildung" + +#: abstract +msgid "Abstract" +msgstr "Abstract" + +#: jsmath-warning +msgid "Warning: " +msgstr "Warnung: " + +#: up +msgid "Up" +msgstr "Oben" + +#: Book +msgid "Book" +msgstr "Buck" + +#: jsmath-enable +msgid "Please enable JavaScript on your browser." +msgstr "Bitte aktivieren Sie JavaScript in Ihrem Browser." + +#: Subsection +msgid "Subsection" +msgstr "Unterabschnitt" + +#: list-algorithm +msgid "List of Algorithms" +msgstr "Verzeichnis der Algorithmen" + +#: index +msgid "Index" +msgstr "Stichwortverzeichnis" + +#: bibliography +msgid "Bibliography" +msgstr "Bibliografie" + +#: references +msgid "References" +msgstr "Literatur" + +#: float-algorithm +msgid "Algorithm" +msgstr "Algorithmus" + +#: next +msgid "Next" +msgstr "Weiter" + +#: list-table +msgid "List of Tables" +msgstr "Tabellenverzeichnis" + +#: Part +msgid "Part" +msgstr "Teil" + +#: toc +msgid "Table of Contents" +msgstr "Inhaltsverzeichnis" + +#: prev +msgid "Prev" +msgstr "Zurück" + +#: Section +msgid "Section" +msgstr "Abschnitt" + +#: Chapter +msgid "Chapter" +msgstr "Kapitel" + +#: list-tableau +msgid "List of Tableaux" +msgstr "Tabellenverzeichnis" + +#: float-tableau +msgid "Tableau " +msgstr "Tabelle" + +#: Paragraph +msgid "Paragraph" +msgstr "Paragraph" + +#: list-figure +msgid "List of Figures" +msgstr "Abbildungsverzeichnis" + +#: float-listing +msgid "Listing " +msgstr "Listing " + +#: nomenclature +msgid "Nomenclature" +msgstr "Nomenklatur" + +#: on-page +msgid " on page " +msgstr " auf Seite " + +#: float-table +msgid "Table " +msgstr "Tabelle" + +#: float-figure +msgid "Figure " +msgstr "Abbildung " + +#: jsmath-requires +msgid " requires JavaScript to correctly process the mathematics on this page. " +msgstr " Benötigt JavaScript um die Formeln auf dieser Seite darstellen zu können. " + +#: generated-by +msgid "Document generated by " +msgstr "Dokument wurde erzeugt von " + +#: generated-on +msgid " on " +msgstr " am " + +#: toc-for +msgid "Contents for " +msgstr "Inhalt für " + +#: main-page +msgid "Main page" +msgstr "Hauptseite" + +#: Appendix +msgid "Appendix" +msgstr "Anhang" + diff -Nru elyxer-1.2.3/forks/jras-elyxer/po/en.po elyxer-1.2.5/forks/jras-elyxer/po/en.po --- elyxer-1.2.3/forks/jras-elyxer/po/en.po 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/po/en.po 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,154 @@ +# English translations for PACKAGE package. +# eLyXer version 1.0.4 +# Released on 2010-10-16 +# Contact: Alex Fernández +# This file is distributed under the same license as the eLyXer package. +# (C) 2010 chenno . +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2010-10-16 19:04+0200\n" +"Last-Translator: chenno \n" +"Language-Team: English\n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ASCII\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: Subsubsection +msgid "Subsubsection" +msgstr "Subsubsection" + +#: figure +msgid "figure" +msgstr "figure" + +#: abstract +msgid "Abstract" +msgstr "Abstract" + +#: jsmath-warning +msgid "Warning: " +msgstr "Warning: " + +#: up +msgid "Up" +msgstr "Up" + +#: Book +msgid "Book" +msgstr "Book" + +#: jsmath-enable +msgid "Please enable JavaScript on your browser." +msgstr "Please enable JavaScript on your browser." + +#: Subsection +msgid "Subsection" +msgstr "Subsection" + +#: list-algorithm +msgid "List of Algorithms" +msgstr "List of Algorithms" + +#: Appendix +msgid "Appendix" +msgstr "Appendix" + +#: index +msgid "Index" +msgstr "Index" + +#: bibliography +msgid "Bibliography" +msgstr "Bibliography" + +#: float-algorithm +msgid "Algorithm " +msgstr "Algorithm " + +#: next +msgid "Next" +msgstr "Next" + +#: list-table +msgid "List of Tables" +msgstr "List of Tables" + +#: Part +msgid "Part" +msgstr "Part" + +#: generated-by +msgid "Document generated by " +msgstr "Document generated by " + +#: toc +msgid "Table of Contents" +msgstr "Table of Contents" + +#: prev +msgid "Prev" +msgstr "Prev" + +#: Section +msgid "Section" +msgstr "Section" + +#: Chapter +msgid "Chapter" +msgstr "Chapter" + +#: list-tableau +msgid "List of Tableaux" +msgstr "List of Tableaux" + +#: generated-on +msgid " on " +msgstr " on " + +#: float-tableau +msgid "Tableau " +msgstr "Tableau " + +#: Paragraph +msgid "Paragraph" +msgstr "Paragraph" + +#: list-figure +msgid "List of Figures" +msgstr "List of Figures" + +#: main-page +msgid "Main page" +msgstr "Main page" + +#: float-listing +msgid "Listing " +msgstr "Listing " + +#: on-page +msgid " on page " +msgstr " on page " + +#: nomenclature +msgid "Nomenclature" +msgstr "Nomenclature" + +#: float-table +msgid "Table " +msgstr "Table " + +#: float-figure +msgid "Figure " +msgstr "Figure " + +#: toc-for +msgid "Contents for " +msgstr "Contents for " + +#: jsmath-requires +msgid " requires JavaScript to correctly process the mathematics on this page. " +msgstr " requires JavaScript to correctly process the mathematics on this page. " diff -Nru elyxer-1.2.3/forks/jras-elyxer/po/es.po elyxer-1.2.5/forks/jras-elyxer/po/es.po --- elyxer-1.2.3/forks/jras-elyxer/po/es.po 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/po/es.po 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,159 @@ +# Spanish translations for eLyXer package +# Traducciones al español para el paquete eLyXer. +# eLyXer version 0.40 +# Released on 2010-01-12 +# Contact: Alex Fernández +# This file is distributed under the same license as the eLyXer package. +# (C) 2010 chenno . +# +msgid "" +msgstr "" +"Project-Id-Version: eLyXer 0.40\n" +"PO-Revision-Date: 2010-01-12 23:50+0100\n" +"Last-Translator: chenno \n" +"Language-Team: Spanish\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: Subsubsection +msgid "Subsubsection" +msgstr "Subsubsección" + +#: figure +msgid "figure" +msgstr "figura" + +#: abstract +msgid "Abstract" +msgstr "Resumen" + +#: jsmath-warning +msgid "Warning: " +msgstr "Aviso: " + +#: up +msgid "Up" +msgstr "Arriba" + +#: Book +msgid "Book" +msgstr "Libro" + +#: jsmath-enable +msgid "Please enable JavaScript on your browser." +msgstr "Por favor, habilite JavaScript en su navegador." + +#: Subsection +msgid "Subsection" +msgstr "Subsección" + +#: list-algorithm +msgid "List of Algorithms" +msgstr "Índice de algoritmos" + +#: index +msgid "Index" +msgstr "Índice alfabético" + +#: bibliography +msgid "Bibliography" +msgstr "Bibliografía" + +#: references +msgid "References" +msgstr "Referencias" + +#: float-algorithm +msgid "Algorithm " +msgstr "Algoritmo " + +#: next +msgid "Next" +msgstr "Siguiente" + +#: list-table +msgid "List of Tables" +msgstr "Índice de tablas" + +#: Part +msgid "Part" +msgstr "Parte" + +#: toc +msgid "Table of Contents" +msgstr "Índice general" + +#: prev +msgid "Prev" +msgstr "Anterior" + +#: Section +msgid "Section" +msgstr "Sección" + +#: Chapter +msgid "Chapter" +msgstr "Capítulo" + +#: list-tableau +msgid "List of Tableaux" +msgstr "Lista de tablas" + +#: float-tableau +msgid "Tableau " +msgstr "Tabla " + +#: Paragraph +msgid "Paragraph" +msgstr "Párrafo" + +#: list-figure +msgid "List of Figures" +msgstr "Índice de figuras" + +#: float-listing +msgid "Listing " +msgstr "Listado " + +#: on-page +msgid " on page " +msgstr " en la página " + +#: nomenclature +msgid "Nomenclature" +msgstr "Nomenclatura" + +#: float-table +msgid "Table " +msgstr "Tabla " + +#: float-figure +msgid "Figure " +msgstr "Figura " + +#: jsmath-requires +msgid " requires JavaScript to correctly process the mathematics on this page. " +msgstr " requiere JavaScript para procesar las fórmulas matemáticas de la página. " + +#: generated-by +msgid "Document generated by " +msgstr "Documento generado con " + +#: generated-on +msgid " on " +msgstr " en " + +#: toc-for +msgid "Contents for " +msgstr "Contenido de " + +#: main-page +msgid "Main page" +msgstr "Página principal" + +#: Appendix +msgid "Appendix" +msgstr "Apéndice" + diff -Nru elyxer-1.2.3/forks/jras-elyxer/po/fr.po elyxer-1.2.5/forks/jras-elyxer/po/fr.po --- elyxer-1.2.3/forks/jras-elyxer/po/fr.po 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/po/fr.po 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,158 @@ +# French translations for PACKAGE package. +# eLyXer version 0.42 +# Released on 2010-02-15 +# Contact: Alex Fernández +# This file is distributed under the same license as the eLyXer package. +# (C) 2010 Sara Teinturier, Alex Fernández. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2010-02-18 00:13+0100\n" +"Last-Translator: Sara Teinturier\n" +"Language-Team: French\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: Subsubsection +msgid "Subsubsection" +msgstr "SousSousSection" + +#: figure +msgid "figure" +msgstr "Figure" + +#: abstract +msgid "Abstract" +msgstr "Résumé" + +#: jsmath-warning +msgid "Warning: " +msgstr "Erreur: Javascript est nécessaire pour afficher correctement les fonctionnalités de " + +#: up +msgid "Up" +msgstr "Monter d'un niveau" + +#: Book +msgid "Book" +msgstr "Livre" + +#: jsmath-enable +msgid "Please enable JavaScript on your browser." +msgstr "Merci d'activer JavaScript dans votre navigateur." + +#: Subsection +msgid "Subsection" +msgstr "SousSection" + +#: list-algorithm +msgid "List of Algorithms" +msgstr "Liste des algorithmes" + +#: index +msgid "Index" +msgstr "Index" + +#: bibliography +msgid "Bibliography" +msgstr "Bibliographie" + +#: references +msgid "References" +msgstr "Références" + +#: float-algorithm +msgid "Algorithm " +msgstr "Algorithme " + +#: next +msgid "Next" +msgstr "Suivant" + +#: list-table +msgid "List of Tables" +msgstr "List des tables" + +#: Part +msgid "Part" +msgstr "Partie" + +#: toc +msgid "Table of Contents" +msgstr "Table des matières" + +#: prev +msgid "Prev" +msgstr "Précédent" + +#: Section +msgid "Section" +msgstr "Section" + +#: Chapter +msgid "Chapter" +msgstr "Chapitre" + +#: list-tableau +msgid "List of Tableaux" +msgstr "Liste des tableaux" + +#: float-tableau +msgid "Tableau " +msgstr "Tableau " + +#: Paragraph +msgid "Paragraph" +msgstr "Paragraphe" + +#: list-figure +msgid "List of Figures" +msgstr "Table des figures" + +#: float-listing +msgid "Listing " +msgstr "Listing " + +#: on-page +msgid " on page " +msgstr " page " + +#: nomenclature +msgid "Nomenclature" +msgstr "Glossaire" + +#: float-table +msgid "Table " +msgstr "Table " + +#: float-figure +msgid "Figure " +msgstr "Figure " + +#: jsmath-requires +msgid " requires JavaScript to correctly process the mathematics on this page. " +msgstr ". " + +#: generated-by +msgid "Document generated by " +msgstr "Document generated by " + +#: generated-on +msgid " on " +msgstr " le " + +#: toc-for +msgid "Contents for " +msgstr "Tables des matières du " + +#: main-page +msgid "Main page" +msgstr "Page principale" + +#: Appendix +msgid "Appendix" +msgstr "Annexe" + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/po/locale/de/LC_MESSAGES/elyxer.mo and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/po/locale/de/LC_MESSAGES/elyxer.mo differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/po/locale/en/LC_MESSAGES/elyxer.mo and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/po/locale/en/LC_MESSAGES/elyxer.mo differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/po/locale/es/LC_MESSAGES/elyxer.mo and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/po/locale/es/LC_MESSAGES/elyxer.mo differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/po/locale/fr/LC_MESSAGES/elyxer.mo and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/po/locale/fr/LC_MESSAGES/elyxer.mo differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/po/locale/nl/LC_MESSAGES/elyxer.mo and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/po/locale/nl/LC_MESSAGES/elyxer.mo differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/po/locale/ru/LC_MESSAGES/elyxer.mo and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/po/locale/ru/LC_MESSAGES/elyxer.mo differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/po/nl.po elyxer-1.2.5/forks/jras-elyxer/po/nl.po --- elyxer-1.2.3/forks/jras-elyxer/po/nl.po 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/po/nl.po 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,158 @@ +# Dutch translations for PACKAGE package. +# eLyXer version 0.42 +# Released on 2010-02-15 +# Contact: Alex Fernández +# This file is distributed under the same license as the eLyXer package. +# (C) 2010 Hans Bezemer, Alex Fernández. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2010-03-12 21:17+0100\n" +"Last-Translator: Hans Bezemer\n" +"Language-Team: Dutch\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ASCII\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: Subsubsection +msgid "Subsubsection" +msgstr "Subsubsectie" + +#: figure +msgid "figure" +msgstr "figuur" + +#: abstract +msgid "Abstract" +msgstr "Samenvatting" + +#: jsmath-warning +msgid "Warning: " +msgstr "Waarschuwing: " + +#: up +msgid "Up" +msgstr "Terug" + +#: Book +msgid "Book" +msgstr "Boek" + +#: jsmath-enable +msgid "Please enable JavaScript on your browser." +msgstr "Activeer Javascript in uw browser." + +#: Subsection +msgid "Subsection" +msgstr "Subsectie" + +#: list-algorithm +msgid "List of Algorithms" +msgstr "Lijst van algoritmen" + +#: index +msgid "Index" +msgstr "Index" + +#: bibliography +msgid "Bibliography" +msgstr "Bibliografie" + +#: references +msgid "References" +msgstr "Referenties" + +#: float-algorithm +msgid "Algorithm " +msgstr "Algoritme " + +#: next +msgid "Next" +msgstr "Volgende" + +#: list-table +msgid "List of Tables" +msgstr "Lijst van tabellen" + +#: Part +msgid "Part" +msgstr "Deel" + +#: toc +msgid "Table of Contents" +msgstr "Inhoudsopgave" + +#: prev +msgid "Prev" +msgstr "Vorige" + +#: Section +msgid "Section" +msgstr "Sectie" + +#: Chapter +msgid "Chapter" +msgstr "Hoofdstuk" + +#: list-tableau +msgid "List of Tableaux" +msgstr "Lijst van Tableaux" + +#: float-tableau +msgid "Tableau " +msgstr "Tableau " + +#: Paragraph +msgid "Paragraph" +msgstr "Paragraaf" + +#: list-figure +msgid "List of Figures" +msgstr "Lijst van figuren" + +#: float-listing +msgid "Listing " +msgstr "Listing " + +#: on-page +msgid " on page " +msgstr " op pagina " + +#: nomenclature +msgid "Nomenclature" +msgstr "Verklaring van symbolen" + +#: float-table +msgid "Table " +msgstr "Tabel " + +#: float-figure +msgid "Figure " +msgstr "Figuur " + +#: jsmath-requires +msgid " requires JavaScript to correctly process the mathematics on this page. " +msgstr " om de formules op deze bladzijde correct weer te geven is Javascript benodigd. " + +#: generated-by +msgid "Document generated by " +msgstr "Document gegenereerd door " + +#: generated-on +msgid " on " +msgstr " op " + +#: toc-for +msgid "Contents for " +msgstr "Inhoud van " + +#: main-page +msgid "Main page" +msgstr "Hoofdpagina" + +#: Appendix +msgid "Appendix" +msgstr "Appendix" + diff -Nru elyxer-1.2.3/forks/jras-elyxer/po/ru.po elyxer-1.2.5/forks/jras-elyxer/po/ru.po --- elyxer-1.2.3/forks/jras-elyxer/po/ru.po 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/po/ru.po 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,164 @@ +msgid "" +msgstr "" +"Project-Id-Version: elyxer 1.2.3\n" +"PO-Revision-Date: 2011-11-11 16:24+0300\n" +"Last-Translator: Vladimir Ermakov \n" +"Language-Team: Russian\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"POT-Creation-Date: \n" + +# eLyXer internationalization file. +# Created on 2011-08-31 +# Contact: Alex Fernandez +# http://elyxer.nongnu.org/ +# This file is distributed under the same license as the eLyXer package. +# (C) 2010 Alex Fernandez . +# +#: Subsubsection +msgid "Subsubsection" +msgstr "Подподраздел" + +#: figure +msgid "figure" +msgstr "рисунок" + +#: abstract +msgid "Abstract" +msgstr "Аннотация" + +#: jsmath-warning +msgid "Warning: " +msgstr "" + +#: up +msgid "Up" +msgstr "Вверх" + +#: Book +msgid "Book" +msgstr "" + +#: references +msgid "References" +msgstr "Список литературы" + +#: Subsection +msgid "Subsection" +msgstr "Подраздел" + +#: list-algorithm +msgid "List of Algorithms" +msgstr "Список алгоритмов" + +#: Appendix +msgid "Appendix" +msgstr "Приложение" + +#: index +msgid "Index" +msgstr "Предметный указатель" + +#: bibliography +msgid "Bibliography" +msgstr "Библиография" + +#: list-table +msgid "List of Tables" +msgstr "Список таблиц" + +#: next +msgid "Next" +msgstr "След." + +#: float-algorithm +msgid "Algorithm " +msgstr "Алгоритм" + +#: Part +msgid "Part" +msgstr "Часть" + +#: generated-by +msgid "Document generated by " +msgstr "" + +#: toc +msgid "Table of Contents" +msgstr "Содержание" + +#: prev +msgid "Prev" +msgstr "Пред." + +#: Section +msgid "Section" +msgstr "Раздел" + +#: Chapter +msgid "Chapter" +msgstr "Глава" + +#: list-tableau +msgid "List of Tableaux" +msgstr "" + +#: generated-on +msgid " on " +msgstr "" + +#: float-tableau +msgid "Tableau " +msgstr "" + +#: Paragraph +msgid "Paragraph" +msgstr "Абзац" + +#: list-figure +msgid "List of Figures" +msgstr "Список рисунков" + +#: main-page +msgid "Main page" +msgstr "Главная" + +#: float-listing +msgid "Listing " +msgstr "Листинг " + +#: on-page +msgid " on page " +msgstr " на странице " + +#: nomenclature +msgid "Nomenclature" +msgstr "Список обозначений" + +#: float-table +msgid "Table " +msgstr "Таблица " + +#: float-figure +msgid "Figure " +msgstr "Рисунок " + +#: toc-for +msgid "Contents for " +msgstr "Содержание " + +#: jsmath-enable +msgid "Please enable JavaScript on your browser." +msgstr "Пожалуйста включите JavaScript." + +#: footnotes +msgid "Footnotes" +msgstr "Список сносок" + +#: jsmath-requires +msgid " requires JavaScript to correctly process the mathematics on this page. " +msgstr "Для формул необходим JavaScript." + diff -Nru elyxer-1.2.3/forks/jras-elyxer/run-tests elyxer-1.2.5/forks/jras-elyxer/run-tests --- elyxer-1.2.3/forks/jras-elyxer/run-tests 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/run-tests 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,143 @@ +#!/bin/bash + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Alex 20090319: run all tests + +# remove result files from previous test runs +rm -f "test/*-test.html" +rm -f "test/subdir/*-test.html" + +# first from the current directory +echo "Testing eLyXer -- any text below this line signals an error" +for file in test/*.lyx; do + name=$(dirname "$file")/$(basename "$file" .lyx) + ./elyxer.py --quiet --css ../docs/lyx.css "$name.lyx" "$name-test.html" + diff -u --ignore-matching-lines="create-date" "$name-good.html" "$name-test.html" +done + +# now a limited subset of tests from within the directory +cd test +name="with images-1-5" +../elyxer.py --quiet --css=../docs/lyx.css "$name.lyx" "$name-test.html" +diff -u --ignore-matching-lines="create-date" "$name-good.html" "$name-test.html" +../elyxer.py --html --quiet --css ../docs/lyx.css "$name.lyx" "$name-html-test.html" +diff -u --ignore-matching-lines="create-date" "$name-html-good.html" "$name-html-test.html" +../elyxer.py --quiet --css ../docs/lyx.css --imageformat ".jpg" "$name.lyx" "$name-jpg-test.html" +diff -u --ignore-matching-lines="create-date" "$name-jpg-good.html" "$name-jpg-test.html" +../elyxer.py --quiet --css ../docs/lyx.css --noconvert "$name.lyx" "$name-noconvert-test.html" +diff -u --ignore-matching-lines="create-date" "$name-noconvert-good.html" "$name-noconvert-test.html" +# test --imageformat copy +cd copyimages +../../elyxer.py --quiet --css ../../docs/lyx.css --imageformat "copy" "../$name.lyx" "$name-test.html" +diff -u --ignore-matching-lines="create-date" "$name-good.html" "$name-test.html" +cd .. + +# directory tests +cd subdir +name="image-directory" +image="mourning.png" +rm -f $image +../../elyxer.py --directory .. --quiet --css ../../docs/lyx.css "$name.lyx" "$name-test.html" +diff -u --ignore-matching-lines="create-date" "$name-good.html" "$name-test.html" +if [ ! -e $image ]; then echo "$image is missing; bad conversion."; fi +name="appendix-1-6" +cp -f ../$name.lyx . +../../elyxer.py --copyright --directory .. --quiet --css ../../docs/lyx.css "$name.lyx" "$name-test.html" +diff -u --ignore-matching-lines="create-date" "$name-good.html" "$name-test.html" +cd .. + +# test TOC generation +name="appendix-1-6" +../elyxer.py --quiet --tocfor "$name-test.html" --css ../docs/toc.css --target contents "$name.lyx" "$name-toc-test.html" +diff -u --ignore-matching-lines="create-date" "$name-toc-good.html" "$name-toc-test.html" + +# test --notoclabels +name="toc-book" +../elyxer.py --quiet --notoclabels --css ../docs/lyx.css "$name.lyx" "$name-notoclabels-test.html" +diff -u --ignore-matching-lines="create-date" "$name-notoclabels-good.html" "$name-notoclabels-test.html" + +# test raw generation +name="helloworld" +../elyxer.py --quiet --raw "$name.lyx" "$name-raw-test.html" +diff -u --ignore-matching-lines="create-date" "$name-raw-good.html" "$name-raw-test.html" + +# test --css and --embedcss +name="helloworld" +../elyxer.py --quiet --css "http://elyxer.nongnu.org/lyx.css" --css ../docs/math.css \ + --embedcss test.css "$name.lyx" "$name-embedcss-test.html" +diff -u --ignore-matching-lines="create-date" "$name-embedcss-good.html" "$name-embedcss-test.html" + +# test lowmem generation +name="index-1-6" +../elyxer.py --quiet --lowmem --css ../docs/lyx.css "$name.lyx" "$name-lowmem-test.html" +diff -u --ignore-matching-lines="create-date" "$name-lowmem-good.html" "$name-lowmem-test.html" + +# test Python 2.4 generation +name="index-1-6" +type -P python2.4 &> /dev/null +if [ $? = 0 ] ; then + python2.4 ../elyxer.py --quiet --css ../docs/lyx.css "$name.lyx" "$name-py2.4-test.html" + diff -u --ignore-matching-lines="create-date" "$name-good.html" "$name-py2.4-test.html" +else + echo "python2.4 not found, cannot test it" +fi + +# test stdin + stdout generation +name="footnotes-1-6" +cat "$name.lyx" | ../elyxer.py --css ../docs/lyx.css > "$name-stdio-test.html" +diff -u --ignore-matching-lines="create-date" "$name-good.html" "$name-stdio-test.html" + +# test --splitpart generation +name="index-1-6" +testfiles="parts/$name-part-test*.html" +rm -f $testfiles +../elyxer.py --quiet --splitpart 1 --css ../../docs/lyx.css "$name.lyx" "parts/$name-part-test.html" +for file in $testfiles; do + goodname=${file/"-test"/"-good"} + diff -u --ignore-matching-lines="create-date" "$goodname" "$file" +done + +# test TOC generation for --splitpart +name="index-1-6" +../elyxer.py --quiet --tocfor "$name-part-test.html" --target "contents" --splitpart 1 --css ../../docs/toc.css "$name.lyx" "parts/$name-toc-test.html" +diff -u --ignore-matching-lines="create-date" "parts/$name-toc-good.html" "parts/$name-toc-test.html" + +# test template generation +name="helloworld" +../elyxer.py --quiet --template template.html "$name.lyx" "$name-template-test.html" +diff -u --ignore-matching-lines="create-date" "$name-template-good.html" "$name-template-test.html" + +# test math2html +result=$(../math2html.py 'N = \frac{\text{number of apples}}{7}') +good='N = (number of apples)/(7)' +if [ "$result" != "$good" ] ; then + echo "Error in math2html: $result != $good" +fi + +# test title with non-ASCII characters, Debian bug 639712 +# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=639712 +name="helloworld" +../elyxer.py --quiet --css ../docs/lyx.css --title "By Fernández" "$name.lyx" "$name-test.html" +diff -u --ignore-matching-lines="create-date" --ignore-matching-lines="" "$name-good.html" "$name-test.html" + +# test simultaneous hover and end in footnotes +name="footnotes-1-6" +../elyxer.py --quiet --footnotes hover,end,number --css ../docs/lyx.css "$name.lyx" "$name-hover-end-test.html" +diff -u --ignore-matching-lines="create-date" "$name-hover-end-good.html" "$name-hover-end-test.html" + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/coalesce.py elyxer-1.2.5/forks/jras-elyxer/src/coalesce.py --- elyxer-1.2.3/forks/jras-elyxer/src/coalesce.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/coalesce.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,136 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090309 +# Coalesces (unifies) all into one file to generate a distributable file. + +import sys +import os.path +from elyxer.io.fileline import * +from elyxer.util.trace import Trace + + +class Coalescer(object): + "Coalesce a set of files into a single file," + "so that it can be distributed." + "Currently works for Python (.py) and CSS (.css) files." + + def __init__(self): + self.comments = True + self.files = [] + self.directory = '' + self.writer = None + self.python = False + + def convert(self, filename, directory = ''): + "Convert the filename adding the appropriate directories." + if os.path.exists(filename): + return filename + newname = os.path.join(self.directory, filename) + if os.path.exists(newname): + return newname + newname = os.path.join(directory, filename) + if os.path.exists(newname): + return newname + Trace.error('Missing file ' + filename) + return None + + def getreader(self, filename): + "Get a line reader." + if filename in self.files: + # already parsed; skip + return None + self.files.append(filename) + return LineReader(filename) + + def readargs(self, args): + "Read arguments from the command line" + del args[0] + if len(args) == 0: + self.usage() + return + self.filename = self.convert(args[0]) + self.directory = os.path.dirname(args[0]) + del args[0] + fileout = sys.stdout + if len(args) > 0: + fileout = args[0] + del args[0] + if len(args) > 0: + usage() + return + self.writer = LineWriter(fileout) + + def usage(self): + Trace.error('Usage: coalesce.py filein [fileout]') + return + + def coalesceall(self): + "Coalesce all files from the root reader." + if not self.writer: + return + self.coalesce(self.filename) + self.writer.close() + + def coalesce(self, filename): + "Coalesce all files used in filein to fileout" + if filename.endswith('.py'): + self.python = True + reader = self.getreader(filename) + if not reader: + return + while not reader.finished(): + line = reader.currentline() + included = self.getincluded(line) + if included: + self.comments = False + newname = self.convert(included, os.path.dirname(filename)) + if newname: + self.coalesce(newname) + else: + # make imports with no target file work + self.writer.writeline(line) + elif self.iscomment(line): + if self.comments: + self.writer.writeline(line) + else: + self.writer.writeline(line) + reader.nextline() + reader.close() + + def getincluded(self, line): + "Get the name of the included file, or None." + if line.startswith('from'): + return line.split()[1].replace('.', '/') + '.py' + if line.startswith('@import'): + return line.split()[1].replace('"', '').rstrip(';') + return None + + def iscomment(self, line): + "Find out if the line is a comment. Only removes Python comments." + if self.python and line.startswith('#'): + return True + return False + +coalescer = Coalescer() +coalescer.readargs(sys.argv) +coalescer.coalesceall() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/conf/base.cfg elyxer-1.2.5/forks/jras-elyxer/src/conf/base.cfg --- elyxer-1.2.3/forks/jras-elyxer/src/conf/base.cfg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/conf/base.cfg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1648 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009-2010 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- + + +[BibTeXConfig.replaced] +--:— +..:. + +[BibStylesConfig.defaulttags] +surname: +authors: +YY:?? + +[BibStylesConfig.default] +cite:$index +default:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@article:$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.} +@book:{$authors: }<i>$title</i>{ ($editor, ed.)}.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@booklet:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@conference:$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.} +@inbook:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@incollection:$authors: <i>$title</i>{ in <i>$booktitle</i>{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@inproceedings:$authors: “$title”, <i>$booktitle</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.} +@manual:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@mastersthesis:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@misc:$authors: <i>$title</i>.{{ $publisher,}{ $howpublished,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@phdthesis:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@proceedings:$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.} +@techreport:$authors: <i>$title</i>, $year.{ URL <a href="$url">$url</a>.}{ $note.} +@unpublished:$authors: “$title”, <i>$journal</i>, $year.{ URL <a href="$url">$url</a>.}{ $note.} + +[BibStylesConfig.abbrvnat] +cite:$surname($year) +default:$authors. <i>$title</i>. $publisher, $year.{ URL <a href="$url">$url</a>.}{ $note.} +@article:$authors. $title. <i>$journal</i>,{ {$volume:}$pages,} $month $year.{ doi: $doi.}{ URL <a href="$url">$url</a>.}{ $note.} + +[BibStylesConfig.alpha] +cite:$Sur$YY +default:$authors. $title.{ <i>$journal</i>,} $year.{ <a href="$url">$url</a>.}{ <a href="$filename">$filename</a>.}{ $note.} +@article:$authors. $title.{ <i>$journal</i>{, {$volume}{($number)}}{: $pages}{, $year}.}{ <a href="$url">$url</a>.}{ <a href="$filename">$filename</a>.}{ $note.} + +[BibStylesConfig.authordate2] +cite:$surname, $year +default:$authors. $year. <i>$title</i>. $publisher.{ URL <a href="$url">$url</a>.}{ $note.} +@article:$authors. $year. $title. <i>$journal</i>, <b>$volume</b>($number), $pages.{ URL <a href="$url">$url</a>.}{ $note.} +@book:$authors. $year. <i>$title</i>. $publisher.{ URL <a href="$url">$url</a>.}{ $note.} + +[BibStylesConfig.plain] +cite:$index +default:{$authors. }$title.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} +@article:$authors. $title.{ <i>$journal</i>{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL <a href="$url">$url</a>.}{ $note.} +@book:$authors. <i>$title</i>. $publisher,{ $month} $year.{ URL <a href="$url">$url</a>.}{ $note.} +@incollection:$authors. $title.{ In <i>$booktitle</i> {($editor, ed.)}.} $publisher,{ $month} $year.{ URL <a href="$url">$url</a>.}{ $note.} +@inproceedings:$authors. $title. { <i>$booktitle</i>{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL <a href="$url">$url</a>.}{ $note.} + +[BibStylesConfig.ieeetr] +cite:$index +default:$authors, “$title”. $year.{ URL <a href="$url">$url</a>.}{ $note.} +@article:$authors, “$title”, <i>$journal</i>, vol. $volume, no. $number, pp. $pages, $year.{ URL <a href="$url">$url</a>.}{ $note.} +@book:$authors, <i>$title</i>. $publisher, $year.{ URL <a href="$url">$url</a>.}{ $note.} + +[BibStylesConfig.vancouver] +cite:$index +default:$authors. $title; {$publisher, }$year.{ $howpublished.}{ URL: <a href="$url">$url</a>.}{ $note.} +@article:$authors. $title. <i>$journal</i>, $year{;{<b>$volume</b>}{($number)}{:$pages}}.{ URL: <a href="$url">$url</a>.}{ $note.} +@book:$authors. $title. {$publisher, }$year.{ URL: <a href="$url">$url</a>.}{ $note.} + +[ContainerConfig.endings] +Align:\end_layout +BarredText:\bar +BoldText:\series +Cell:</cell +ChangeInserted:\change_unchanged +ChangeDeleted:\change_unchanged +ColorText:\color +EmphaticText:\emph +Hfill:\hfill +Inset:\end_inset +Layout:\end_layout +LyXFooter:\end_document +LyXHeader:\end_header +Row:</row +ShapedText:\shape +SizeText:\size +TextFamily:\family +VersalitasText:\noun +StrikeOut:\strikeout + +[ContainerConfig.startendings] +\begin_deeper:\end_deeper +\begin_inset:\end_inset +\begin_layout:\end_layout + +[ContainerConfig.starts] +:StringContainer +#LyX:BlackBox +</lyxtabular:BlackBox +<cell:Cell +<column:Column +<row:Row +\align:Align +\bar:BarredText +\bar default:BlackBox +\bar no:BlackBox +\begin_body:BlackBox +\begin_deeper:DeeperList +\begin_document:BlackBox +\begin_header:LyXHeader +#\begin_inset:Inset +\begin_inset Argument:ShortTitle +\begin_inset Box:BoxInset +\begin_inset Branch:Branch +\begin_inset Caption:Caption +\begin_inset CommandInset bibitem:BiblioEntry +\begin_inset CommandInset bibtex:BibTeX +\begin_inset LatexCommand bibtex:BibTeX +\begin_inset CommandInset citation:BiblioCitation +\begin_inset LatexCommand citet:BiblioCitation +\begin_inset LatexCommand citep:BiblioCitation +\begin_inset LatexCommand citealt:BiblioCitation +\begin_inset CommandInset href:URL +\begin_inset CommandInset index_print:PrintIndex +\begin_inset CommandInset include:IncludeInset +\begin_inset CommandInset line:LineInset +\begin_inset CommandInset label:Label +\begin_inset CommandInset nomencl_print:PrintNomenclature +\begin_inset CommandInset nomenclature:NomenclatureEntry +\begin_inset CommandInset ref:Reference +\begin_inset LatexCommand prettyref:Reference +\begin_inset CommandInset toc:TableOfContents +\begin_inset ERT:ERT +\begin_inset Flex:FlexInset +\begin_inset Flex URL:FlexURL +\begin_inset Flex Marginnote:SideNote +\begin_inset Flex Sidenote:SideNote +\begin_inset Flex Chunkref:NewfangledChunkRef +\begin_inset Float:Float +\begin_inset FloatList:ListOf +\begin_inset Foot:Footnote +\begin_inset Formula:Formula +\begin_inset FormulaMacro:FormulaMacro +\begin_inset Graphics:Image +\begin_inset Index:IndexReference +\begin_inset Info:InfoInset +\begin_inset LatexCommand bibitem:BiblioEntry +\begin_inset LatexCommand cite:BiblioCitation +\begin_inset LatexCommand htmlurl:URL +\begin_inset LatexCommand index:IndexReference +\begin_inset LatexCommand label:Label +\begin_inset LatexCommand nomenclature:NomenclatureEntry +\begin_inset LatexCommand printindex:PrintIndex +\begin_inset LatexCommand printnomenclature:PrintNomenclature +\begin_inset LatexCommand ref:Reference +\begin_inset LatexCommand tableofcontents:TableOfContents +\begin_inset LatexCommand url:URL +\begin_inset LatexCommand vref:Reference +\begin_inset Marginal:SideNote +\begin_inset Newline:NewlineInset +\begin_inset Newpage:NewPageInset +\begin_inset Note:Note +\begin_inset OptArg:ShortTitle +\begin_inset Phantom:PhantomText +\begin_inset Quotes:QuoteContainer +\begin_inset script:ScriptInset +\begin_inset Tabular:Table +\begin_inset Text:InsetText +\begin_inset VSpace:VerticalSpace +\begin_inset Wrap:Wrap +\begin_inset listings:Listing +\begin_inset space:Space +\begin_layout:Layout +\begin_layout Abstract:Abstract +\begin_layout Author:Author +\begin_layout Chunk:NewfangledChunk +\begin_layout Bibliography:Bibliography +\begin_layout Description:Description +\begin_layout Enumerate:ListItem +\begin_layout Itemize:ListItem +\begin_layout List:List +\begin_layout LyX-Code:LyXCode +\begin_layout Plain:PlainLayout +\begin_layout Standard:StandardLayout +\begin_layout Title:Title +\begin_preamble:LyXPreamble +\change_inserted:ChangeInserted +\change_deleted:ChangeDeleted +\change_unchanged:BlackBox +\color:ColorText +\color inherit:BlackBox +\color none:BlackBox +\emph default:BlackBox +\emph off:BlackBox +\emph on:EmphaticText +\emph toggle:EmphaticText +\end_body:LyXFooter +\family:TextFamily +\family default:BlackBox +\family roman:BlackBox +\hfill:Hfill +\labelwidthstring:BlackBox +\lang:LangLine +\length:InsetLength +\lyxformat:LyXFormat +\lyxline:LyXLine +\newline:Newline +\newpage:NewPage +\noindent:BlackBox +\noun default:BlackBox +\noun off:BlackBox +\noun on:VersalitasText +\paragraph_spacing:BlackBox +\series bold:BoldText +\series default:BlackBox +\series medium:BlackBox +\shape:ShapedText +\shape default:BlackBox +\shape up:BlackBox +\size:SizeText +\size normal:BlackBox +\start_of_appendix:StartAppendix +\strikeout on:StrikeOut +\strikeout default:BlackBox + +[ContainerConfig.string] +startcommand:\ + +[ContainerConfig.table] +headers:[<lyxtabular,<features] + +[ContainerConfig.extracttext] +allowed:[StringContainer,Constant,FormulaConstant] +cloned:[] +extracted:[PlainLayout,TaggedText,Align,Caption,TextFamily,EmphaticText,VersalitasText,BarredText,SizeText,ColorText,LangLine,Formula,Bracket,RawText,BibTag,FormulaNumber,AlphaCommand,EmptyCommand,OneParamFunction,SymbolFunction,TextFunction,FontFunction,CombiningFunction,DecoratingFunction,FormulaSymbol,BracketCommand,TeXCode] + +[EscapeConfig.chars] + : + --- : — + -- : — +':’ +`:‘ + +[EscapeConfig.commands] +\InsetSpace \space{}:  +\InsetSpace \thinspace{}:  +\InsetSpace ~:  +\SpecialChar \-: +\SpecialChar \@.:. +\SpecialChar \ldots{}:… +\SpecialChar \menuseparator: ▷  +\SpecialChar \nobreakdash-:- +\SpecialChar \slash{}:/ +\SpecialChar \textcompwordmark{}: +\backslash:\ + +[EscapeConfig.entities] +&:& +<:< +>:> + +[EscapeConfig.html] +/>:> + +[EscapeConfig.nonunicode] + :  + +[EscapeConfig.iso885915] + :&#8197; + :  + :  + +[FormulaConfig.alphacommands] +# italic Greek alphabet +\varGamma:Γ +\varDelta:∆ +\varTheta:Θ +\varLambda:Λ +\varXi:Ξ +\varPi:Π +\varSigma:Σ +\varUpsilon:Υ +\varPhi:Φ +\varPsi:Ψ +\varOmega:Ω +\alpha:α +\beta:β +\delta:δ +\epsilon:ϵ +\gamma:γ +\eta:η +\iota:ι +\kappa:κ +\lambda:λ +\mu:μ +\nu:ν +\omega:ω +\phi:φ +\pi:π +\psi:ψ +\rho:ρ +\sigma:σ +\tau:τ +\theta:θ +\upsilon:υ +\varepsilon:ε +\varkappa:ϰ +\varphi:φ +\varpi:ϖ +\varrho:ϱ +\varsigma:ς +\vartheta:ϑ +\xi:ξ +\zeta:ζ +# MarkusKuhn +\oe:œ +\OE:Œ +\ae:æ +\AE:Æ +\aa:å +\AA:Å +\o:ø +\O:Ø +\l:ł +\L:Ł +\ss:ß +\textcrh:ħ +# GünterMilde +\i:ı +\j:ȷ +\imath:ı +\jmath:ȷ +# 20101130 from BibTeXConfig.escaped +\DH:Ð +\TH:Þ +\dh:ð +\th:þ +# 20110108 +\AmS:<span class="versalitas">AmS</span> +# Milde 20110709 (http://milde.users.sourceforge.net/LUCR/Math/) +\Koppa:Ϟ +\Stigma:Ϛ +\sampi:ϡ +\Sampi:Ϡ +\koppa:ϟ +\digamma:ϝ +\stigma:ϛ +\varbeta:ϐ +\eth:ð +\Angstroem:Å +\Micro:µ +\tcohm:Ω + +[FormulaConfig.array] +begin:\begin +cellseparator:& +end:\end +rowseparator:\\ + +[FormulaConfig.bigbrackets] +(:[⎛,⎜,⎝] +):[⎞,⎟,⎠] +[:[⎡,⎢,⎣] +]:[⎤,⎥,⎦] +{:[⎧,⎪,⎨,⎩] +}:[⎫,⎪,⎬,⎭] +|:[|] +∥:[∥] + +[FormulaConfig.commands] +\!: +\%:% +\,: +\;:  +\::  +\CIRCLE:● +\CheckedBox:☑ +\Circle:○ +\Downarrow:⇓ +\Im:ℑ +\LEFTCIRCLE:◖ +\LEFTcircle:◐ +\Leftarrow:⇐ +\Longleftarrow:⟸ +\Longrightarrow:⟹ +\Pr:Pr +\RIGHTCIRCLE:◗ +\RIGHTcircle:◑ +\Re:ℜ +\Square:☐ +\Uparrow:⇑ +\Updownarrow:⇕ +\XBox:☒ +\\:<br/> +\_:_ +\aleph:ℵ +\amalg:∐ +\angle:∠ +\aquarius:♒ +\arccos:arccos +\arcsin:arcsin +\arctan:arctan +\arg:arg +\aries:♈ +\ast:∗ +\asymp:≍ +\backslash:\ +\beth:ℶ +\bigcap:∩ +\bigcirc:○ +\bigcup:∪ +\bigodot:⊙ +\bigoplus:⊕ +\bigotimes:⊗ +\bigsqcup:⊔ +\bigstar:★ +\biguplus:⊎ +\bigvee:∨ +\bigwedge:∧ +\blacksmiley:☻ +\blacktriangleright:▶ +\bot:⊥ +\bowtie:⋈ +\box:▫ +\bullet:• +\cancer:♋ +\cap:∩ +\capricornus:♑ +\cdot:⋅ +\cdots:⋯ +\centerdot:∙ +\chi:χ +\circ:○ +\clubsuit:♣ +\cong:≅ +\coprod:∐ +\cos:cos +\cosh:cosh +\cot:cot +\coth:coth +\csc:csc +\cup:∪ +\dagger:† +\daleth:ℸ +\dashv:⊣ +\ddagger:‡ +\ddots:⋱ +\deg:deg +\det:det +\diamond:◇ +\diamondsuit:♦ +\dim:dim +\div:÷ +\doteq:≐ +\dots:… +\downarrow:↓ +\earth:♁ +\ell:ℓ +\emptyset:∅ +\exists:∃ +\exp:exp +\female:♀ +\forall:∀ +\frownie:☹ +\gcd:gcd +\gemini:♊ +\gets:← +\gg:≫ +\gimel:ℷ +\hbar:ℏ +\heartsuit:♥ +\hom:hom +\hookleftarrow:↩ +\hookrightarrow:↪ +\imath:ı +\inf:inf +\infty:∞ +\invneg:⌐ +\jmath:ȷ +\jupiter:♃ +\ker:ker +\langle:⟨ +\ldots:… +\leadsto:⇝ +\leftharpoondown:↽ +\leftharpoonup:↼ +\leftmoon:☾ +\leftrightarrow:↔ +\leo:♌ +\lg:lg +\libra:♎ +\liminf:liminf +\limsup:limsup +\ll:≪ +\ln:ln +\log:log +\longleftarrow:⟵ +\longrightarrow:⟶ +\lozenge:◊ +\lyxlock: +\male:♂ +\mapsto:↦ +\maltese:✠ +\max:max +\mercury:☿ +\mho:℧ +\mid:∣ +\min:min +\models:⊨ +\mp:∓ +\nabla:∇ +\nearrow:↗ +\neg:¬ +\neptune:♆ +\ni:∋ +\nonumber: +\not:¬ +\nwarrow:↖ +\odot:⊙ +\oint:<span class="bigsymbol">∮</span> +\ominus:⊖ +\oplus:⊕ +\oslash:⊘ +\otimes:⊗ +\parallel:∥ +\partial:∂ +\perp:⊥ +\pisces:♓ +\pluto:♇ +\pm:± +\prec:≺ +\preceq:≼ +\prime:′ +\prompto:∝ +\qquad: +\quad: +\quarternote:♩ +\rangle:⟩ +\rightharpooondown:⇁ +\rightharpooonup:⇀ +\rightleftharpoons:⇌ +\rightmoon:☽ +\sagittarius:♐ +\saturn:♄ +\scorpio:♏ +\searrow:↘ +\sec:sec +\setminus:∖ +\simeq:≃ +\sin:sin +\sinh:sinh +\slash:∕ +\smiley:☺ +\spadesuit:♠ +\sqcap:⊓ +\sqcup:⊔ +\sqsubset:⊏ +\sqsubseteq:⊑ +\sqsupset:⊐ +\sqsupseteq:⊒ +\square:□ +\star:⋆ +\succ:≻ +\succeq:≽ +\sun:☼ +\sup:sup +\surd:√ +\swarrow:↙ +\tan:tan +\tanh:tanh +\taurus:♉ +\textbackslash:\ +\top:⊤ +\triangleleft:⊲ +\triangleright:▷ +\twonotes:♫ +\unlhd:⊴ +\unrhl:⊵ +\uparrow:↑ +\updownarrow:↕ +\uplus:⊎ +\uranus:♅ +\varclubsuit:♧ +\vardiamondsuit:♦ +\varheartsuit:♥ +\varspadesuit:♤ +\vdash:⊢ +\vee:∨ +\virgo:♍ +\wedge:∧ +\wp:℘ +\wr:≀ +\{:{ +\}:} +# MarkusKuhn +\Box:□ +\|:∥ +\triangle:△ +\Diamond:◇ +\flat:♭ +\natural:♮ +\sharp:♯ +\lhd:⊲ +\bigtriangleup:△ +\bigtriangledown:▽ +\rhd:⊳ +\unrhd:⊵ +\smile:⌣ +\frown:⌢ +\Join:⨝ +\not<:≮ +\not>:≯ +\not=:≠ +\longleftrightarrow:⟷ +\Longleftrightarrow:⟺ +\longmapsto:⟼ +\rightharpoonup:⇀ +\rightharpoondown:⇁ +\lbrack:[ +\lbrace:{ +\lfloor:⌊ +\lceil:⌈ +\rbrack:] +\rbrace:} +\rfloor:⌋ +\rceil:⌉ +\owns:∋ +\land:∧ +\lor:∨ +\lnot:¬ +\vert:∣ +\Vert:∥ +\leq):≤ +\geq):≥ +\lbrace):{ +\rbrace):} +\rightarrow):→ +\leftarrow):← +\ni):∋ +\wedge):∧ +\vee):∨ +\neg):¬ +\vdots:⋮ +\S:§ +\P:¶ +\dag:† +\ddag:‡ +\copyright:© +# financial +\pounds:£ +\euro:€ +\yen:¥ +\$:$ +# 20091028 +\checkmark:✓ +\blacklozenge:⧫ +\blacktriangle:▲ +\blacktriangledown:▼ +\nexists:∄ +\mathcircumflex:^ +# 20091128 +\varnothing:∅ +\backprime:‵ +\notin:∉ +\hfill:<span class="hfill"> </span> +\circledR:® +\hslash:ℏ +# 20091203 +\gtrless:≷ +\complement:∁ +\measuredangle:∡ +\sphericalangle:∢ +\nmid:∤ +\circeq:≗ +\lessgtr:≶ +\nparallel:∦ +# Jens Nöckel +\leftthreetimes:⋋ +\rightthreetimes:⋌ +\ltimes:⋉ +\rtimes:⋊ +\divideontimes:⋇ +\dotplus:∔ +\dotdiv:∸ +\oiint:<span class="bigsymbol">∯</span> +\oiiint:<span class="bigsymbol">∰</span> +\ointclockwise:<span class="bigsymbol">∲</span> +\landupint:<span class="bigsymbol">∱</span> +\ointctrclockwise:<span class="bigsymbol">∳</span> +\iint:<span class="bigsymbol">∬</span> +\iiint:<span class="bigsymbol">∭</span> +\idotsint:<span class="bigsymbol">∫⋯∫</span> +\barwedge:⊼ +\veebar:⊻ +\doublebarwedge:⌆ +\backepsilon:∍ +\therefore:∴ +\because:∵ +\boxdot:⊡ +\circledast:⊛ +\circledcirc:⊚ +\circleddash:⊝ +\EUR:€ +\nvdash:⊬ +\vDash:⊨ +\nvDash:⊭ +\Vdash:⊩ +\nVDash:⊯ +\Vvdash:⊪ +\multimap:⊸ +\Cup:⋓ +\udot:⊍ +\Cap:⋒ +\Yup:⅄ +\nequiv:≢ +\triangleq:≜ +\Corresponds:≙ +\coloneqq:≔ +\Coloneqq:⩴ +\eqcolon:≕ +\eqcirc:≖ +\doteqdot:≑ +\risingdotseq:≓ +\fallingdotseq:≒ +\nsimeq:≄ +\backsimeq:⋍ +\ncong:≇ +\nsim:≁ +\napprox:≉ +\eqsim:≂ +\bumpeq:≏ +\Bumpeq:≎ +\nless:≮ +\ngtr:≯ +\lll:⋘ +\ggg:⋙ +\nleqslant:≰ +\leqslant:≤ +\geqslant:≥ +\ngeqslant:≱ +\nlessgtr:≸ +\ngtrless:≹ +\lneqq:≨ +\leqq:≦ +\geqq:≧ +\gneqq:≩ +\lnsim:⋦ +\lesssim:≲ +\gtrsim:≳ +\gnsim:⋧ +\nprec:⊀ +\nsucc:⊁ +\ntriangleleft:⋪ +\ntriangleright:⋫ +\trianglelefteq:⊴ +\trianglerighteq:⊵ +\ntrianglelefteq:⋬ +\ntrianglerighteq:⋭ +\preccurlyeq:≼ +\succcurlyeq:≽ +\nsucccurlyeq:⋡ +\precsim:≾ +\succsim:≿ +\succnsim:⋩ +\lesseqgtr:⋛ +\gtreqless:⋚ +\gtreqqless:⪌ +\lesseqqgtr:⪋ +\gtrdot:⋗ +\lessdot:⋖ +\Subset:⋐ +\Supset:⋑ +\nsupset:⊅ +\nsubseteq:⊈ +\subseteqq:⫅ +\supseteqq:⫆ +\subsetneqq:⫋ +\supsetneqq:⫌ +\nsupseteq:⊉ +\nsqsubset:⊏̸ +\notni:∌ +\pitchfork:⋔ +\between:≬ +\notslash:⌿ +\notbackslash:⍀ +\nleftarrow:↚ +\nrightarrow:↛ +\nleftrightarrow:↮ +\lightning:↯ +\nLeftrightarrow:⇎ +\APLuparrowbox:⍐ +\APLdownarrowbox:⍗ +\APLleftarrowbox:⍇ +\APLrightarrowbox:⍈ +\pointer:➪ +\nLeftarrow:⇍ +\nRightarrow:⇏ +\Lleftarrow:⇚ +\Rrightarrow:⇛ +\Lsh:↰ +\Rsh:↱ +\curvearrowleft:↶ +\curvearrowright:↷ +\leftrightarrows:⇆ +\rightleftarrows:⇄ +\upharpoonleft:↿ +\downharpoonleft:⇃ +\downharpoonright:⇂ +\upharpoonright:↾ +\leftarrowtobar:⇤ +\rightarrowtobar:⇥ +\leftrightharpoons:⇋ +\leftleftharpoons:⥢ +\rightrightharpoons:⥤ +\Mapsfrom:⇐| +\Mapsto:|⇒ +\mapsfrom:↤ +\dashleftarrow:⇠ +\upuparrows:⇈ +\downdownarrows:⇊ +\leftleftarrows:⇇ +\rightrightarrows:⇉ +\leftarrowtail:↢ +\rightarrowtail:↣ +\twoheadleftarrow:↞ +\twoheadrightarrow:↠ +\looparrowleft:↫ +\looparrowright:↬ +# 20100124 +\blacksquare:■ +\ :  +# non-italic Greek symbols +\Gamma:Γ +\Delta:Δ +\Theta:Θ +\Lambda:Λ +\Xi:Ξ +\Pi:Π +\Sigma:Σ +\Upsilon:Υ +\Phi:Φ +\Psi:Ψ +\Omega:Ω +# 20100509 +\diagup:╱ +\diagdown:╲ +# 20100520 +\officialeuro:€ +# 20100823 +\textasciitilde:~ +\textasciicircum:^ +\textendash:— +\textquotedblleft:“ +\textquotedblright:” +# 20100912 +\textless:< +\textgreater:> +# 20101130 from BibTeXConfig.escaped +\textordfeminine:ª +\textregistered:® +\textordmasculine:º +\texttrademark:™ +\&:& +\#:# +# 20101214 +\newline:<br/> +# 2011-01-03 from Günther Milde +\Game:⅁ +# 20110107 +\textvisiblespace: +# 20110120 +\nolimits: +# Pascal Francq +\textsection:§ +\textdegree:° +\guillemotleft:« +\guillemotright:» +\texteuro:€ +\textellipsis:… +\textquoteright:’ +\textrightarrow:→ +\texttwosuperior:² +\textcopyright:©' +\textemdash:— +# Milde 20110709 (http://milde.users.sourceforge.net/LUCR/Math/) +\rblot:⦊ +\rsub:⩥ +\sphat: +\medbullet:⚫ +\biohazard:☣ +\Lbag:⟅ +\llcorner:⌞ +\ExponetialE:ⅇ +\sslash:⫽ +\boxcircle:⧇ +\recycle:♻ +\blacktriangleup:▴ +\talloblong:⫾ +\anchor:⚓ +\interleave:⫴ +\APLcomment:⍝ +\smalltriangleleft:◃ +\Lparen:⦅ +\AC:∿ +\smalltriangleright:▹ +\RHD:▶ +\circledbslash:⦸ +\lblot:⦉ +\circledless:⧀ +\dsub:⩤ +\yinyang:☯ +\sixteenthnote:♬ +\intercal:⊺ +\cat:⁀ +\lang:⟪ +\APLlog:⍟ +\Sun:☉ +\curlywedge:⋏ +\rimg:⦈ +\boxbslash:⧅ +\circledgtr:⧁ +\boxbar:◫ +\Qoppa:Ϙ +\ulcorner:⌜ +\wasylozenge:⌑ +\sptilde:~ +\cent:¢ +\smallsetminus:∖ +\warning:⚠ +\APLinv:⌹ +\smalltriangleup:▵ +\qoppa:ϙ +\swords:⚔ +\circlearrowright:↻ +\diameter:⌀ +\Diamonddot:⟐ +\eighthnote:♪ +\urcorner:⌝ +\CapitalDifferentialD:ⅅ +\lrcorner:⌟ +\boxast:⧆ +\boxplus:⊞ +\DifferentialD:ⅆ +\boxminus:⊟ +\Diamondblack:◆ +\lgroup:⟮ +\fcmp:⨾ +\boxtimes:⊠ +\limg:⦇ +\Finv:Ⅎ +\Rbag:⟆ +\radiation:☢ +\circlearrowleft:↺ +\llbracket:⟦ +\arrowbullet:➢ +\pencil:✎ +\LHD:◀ +\pointright:☞ +\blacktriangleleft:◂ +\medcirc:⚪ +\boxbox:⧈ +\spot:⦁ +\Rparen:⦆ +\ballotx:✗ +\second:″ +\ComplexI:ⅈ +\Euler:ℇ +\ComplexJ:ⅉ +\rightangle:∟ +\rgroup:⟯ +\spddot:¨ +\invamp:⅋ +\rrbracket:⟧ +\third:‴ +\smalltriangledown:▿ +\curlyvee:⋎ +\skull:☠ +\fourth:⁗ +\steaming:☕ +\APLinput:⍞ +\rang:⟫ +\boxslash:⧄ + +[FormulaConfig.spacedcommands] +\Leftrightarrow:⇔ +\Rightarrow:⇒ +\approx:≈ +\dashrightarrow:⇢ +\equiv:≡ +\ge:≥ +\geq:≥ +\implies: ⇒  +\in:∈ +\le:≤ +\leftarrow:← +\leq:≤ +\ne:≠ +\neq:≠ +\not\in:∉ +\propto:∝ +\rightarrow:→ +\rightsquigarrow:⇝ +\sim:~ +\subset:⊂ +\subseteq:⊆ +\supset:⊃ +\supseteq:⊇ +\times:× +\to:→ +# Milde 20110709 (http://milde.users.sourceforge.net/LUCR/Math/) +\nsqsupseteq:⋣ +\bij:⤖ +\nsqsubseteq:⋢ +\subsetneq:⊊ +\finj:⤕ +\llcurly:⪻ +\RightArrowBar:⇥ +\NestedLessLess:⪡ +\curlyeqprec:⋞ +\LeftDownTeeVector:⥡ +\pfun:⇸ +\Doteq:≑ +\downuparrows:⇵ +\precnsim:⋨ +\lnapprox:⪉ +\nsubset:⊄ +\lneq:⪇ +\Equal:⩵ +\coloneq:≔ +\hash:⋕ +\vartriangleleft:⊲ +\leftupdownharpoon:⥑ +\precnapprox:⪹ +\rightslice:⪧ +\updownharpoons:⥮ +\multimapboth:⧟ +\RightTeeVector:⥛ +\npreceq:⋠ +\Longmapsto:⟾ +\leftrightharpoonup:⥎ +\Bot:⫫ +\dlsh:↲ +\Top:⫪ +\downupharpoons:⥯ +\backsim:∽ +\rightleftharpoon:⥋ +\nleq:≰ +\RightVectorBar:⥓ +\NotGreaterTilde:≵ +\NestedGreaterGreater:⪢ +\MapsUp:↥ +\DownLeftVectorBar:⥖ +\lessapprox:⪅ +\eqslantgtr:⪖ +\barrightharpoon:⥭ +\barleftharpoon:⥫ +\strictif:⥽ +\leftarrowtriangle:⇽ +\supsetneq:⊋ +\gnapprox:⪊ +\Swarrow:⇙ +\LeftDownVectorBar:⥙ +\notasymp:≭ +\LeftUpVectorBar:⥘ +\gtrapprox:⪆ +\nni:∌ +\Proportion:∷ +\eqslantless:⪕ +\succnapprox:⪺ +\leftrightharpoondown:⥐ +\VDash:⊫ +\downdownharpoons:⥥ +\approxeq:≊ +\ffun:⇻ +\leftrightarrowtriangle:⇿ +\NotLessTilde:≴ +\DownLeftTeeVector:⥞ +\updownarrows:⇅ +\Nearrow:⇗ +\Nwarrow:⇖ +\DownArrowBar:⤓ +\barin:⋶ +\Longmapsfrom:⟽ +\multimapdotbothA:⊶ +\LeftVectorBar:⥒ +\Same:⩶ +\RightUpTeeVector:⥜ +\succeqq:⪴ +\strictfi:⥼ +\iddots:⋰ +\pinj:⤔ +\RightTriangleBar:⧐ +\leftbarharpoon:⥪ +\ggcurly:⪼ +\nsucceq:⋡ +\nVdash:⊮ +\leftsquigarrow:⇜ +\LeftUpTeeVector:⥠ +\Searrow:⇘ +\multimapdotbothB:⊷ +\DownRightTeeVector:⥟ +\leftrightsquigarrow:↭ +\LeftArrowBar:⇤ +\UpArrowBar:⤒ +\psur:⤀ +\DownRightVectorBar:⥗ +\drsh:↳ +\LeftTriangleBar:⧏ +\RightUpVectorBar:⥔ +\LeftTeeVector:⥚ +\rightbarharpoon:⥬ +\leftslice:⪦ +\preceqq:⪳ +\gneq:⪈ +\rightarrowtriangle:⇾ +\precapprox:⪷ +\NotGreaterLess:≹ +\longmapsfrom:⟻ +\vartriangleright:⊳ +\rightupdownharpoon:⥏ +\ngeq:≱ +\RightDownTeeVector:⥝ +\RightDownVectorBar:⥕ +\leftrightharpoon:⥊ +\curlyeqsucc:⋟ +\multimapinv:⟜ +\succapprox:⪸ +\corresponds:≙ +\upupharpoons:⥣ +\MapsDown:↧ + +[FormulaConfig.decoratedcommand] +# 20101130 from BibTeXConfig.escaped +#!`:¡ +#?`:¿ + +[FormulaConfig.decoratingfunctions] +\overleftarrow:⟵ +\overrightarrow:⟶ +\widehat:^ + +[FormulaConfig.combiningfunctions] +\acute:́ +\bar:̄ +\breve:̆ +\c:̧ +\check:̌ +\dot:̇ +\ddot:̈ +\dddot:⃛ +\grave:̀ +\hat:̂ +\mathring:̊ +\overleftarrow:⃖ +\overrightarrow:⃗ +\r:̊ +\s:̩ +\textsubring:̥ +\tilde:̃ +\vec:⃗ +# 20101130 from BibTeXConfig.escaped +\`:̀ +\':́ +\^:̂ +\~:̃ +\":̈ +\textcircled:⃝ +\v:̌ + +[FormulaConfig.environments] +align:[r,l] +eqnarray:[r,c,l] +gathered:[l,l] + +[FormulaConfig.endings] +bracket:} +complex:\] +endafter:} +endbefore:\end{ +squarebracket:] + +[FormulaConfig.fontfunctions] +\boldsymbol:b +\mathbb:span class="blackboard" +\mathbf:b +\mathcal:span class="scriptfont" +\mathfrak:span class="fraktur" +\mathit:i +\mathrm:span class="mathrm" +\mathsf:span class="mathsf" +\mathtt:tt +\mathscr:span class="scriptfont" +# simplified fonts +\mathbb{A}:𝔸 +\mathbb{B}:𝔹 +\mathbb{C}:ℂ +\mathbb{D}:𝔻 +\mathbb{E}:𝔼 +\mathbb{F}:𝔽 +\mathbb{G}:𝔾 +\mathbb{H}:ℍ +\mathbb{J}:𝕁 +\mathbb{K}:𝕂 +\mathbb{L}:𝕃 +\mathbb{N}:ℕ +\mathbb{O}:𝕆 +\mathbb{P}:ℙ +\mathbb{Q}:ℚ +\mathbb{R}:ℝ +\mathbb{S}:𝕊 +\mathbb{T}:𝕋 +\mathbb{W}:𝕎 +\mathbb{Z}:ℤ +\mathfrak{C}:ℭ +\mathfrak{F}:𝔉 +\mathfrak{H}:ℌ +\mathfrak{I}:ℑ +\mathfrak{R}:ℜ +\mathfrak{Z}:ℨ +\mathring{A}:Å +\mathring{U}:Ů +\mathring{a}:å +\mathring{u}:ů +\mathring{w}:ẘ +\mathring{y}:ẙ +\mathscr{B}:ℬ +\mathscr{E}:ℰ +\mathscr{F}:ℱ +\mathscr{H}:ℋ +\mathscr{I}:ℐ +\mathscr{L}:ℒ +\mathscr{M}:ℳ +\mathscr{R}:ℛ +\mathcal{B}:ℬ +\mathcal{E}:ℰ +\mathcal{F}:ℱ +\mathcal{H}:ℋ +\mathcal{I}:ℐ +\mathcal{L}:ℒ +\mathcal{M}:ℳ +\mathcal{R}:ℛ + +[FormulaConfig.hybridfunctions] +\sqrt:[[$0]{$1},f0{f1{$0}f2{√}f4{(}f3{$1}f4{)}},span class="sqrt",sup class="root",span class="radical",span class="root",span class="ignored"] +\unit:[[$0]{$1},$0f0{$1.font},span class="unit"] +\frac:[{$1}{$2},f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}},span class="fraction",span class="numerator",span class="denominator",span class="ignored"] +\cfrac:[[$p!]{$1}{$2},f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}},span class="fullfraction",span class="numerator align-$p",span class="denominator",span class="ignored"] +\dfrac:[{$1}{$2},f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}},span class="fullfraction",span class="numerator",span class="denominator",span class="ignored"] +\nicefrac:[{$1}{$2},f0{f1{$1}⁄f2{$2}},span class="fraction",sup class="numerator",sub class="denominator",span class="ignored"] +\unitfrac:[[$0]{$1}{$2},$0f0{f1{$1.font}⁄f2{$2.font}},span class="fraction",sup class="unit",sub class="unit"] +\binom:[{$1}{$2},f2{(}f0{f1{$1}f1{$2}}f2{)},span class="binom",span class="binomstack",span class="bigsymbol"] +\dbinom:[{$1}{$2},(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}}),span class="binomial",span class="binomrow",span class="binomcell"] +\tbinom:[{$1}{$2},(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}}),span class="binomial",span class="binomrow",span class="binomcell"] +\hspace:[{$p!},f0{ },span class="hspace" style="width: $p;"] +\vspace:[{$p!},f0{ },span class="vspace" style="height: $p;"] +\raisebox:[{$p!}{$1},f0{$1.font},span class="raisebox" style="vertical-align: $p;"] +\leftroot:[{$p!},f0{ },span class="leftroot" style="width: $p;px"] +\uproot:[{$p!},f0{ },span class="uproot" style="width: $p;px"] +\renewenvironment:[{$1!}{$2!}{$3!},] +\color:[{$p!}{$1},f0{$1},span style="color: $p;"] +\textcolor:[{$p!}{$1},f0{$1},span style="color: $p;"] +\colorbox:[{$p!}{$1},f0{$1},span class="colorbox" style="background: $p;"] +\stackrel:[{$1}{$2},f0{f1{$1}f2{$2}},span class="stackrel",span class="upstackrel",span class="downstackrel"] +\fbox:[{$1},f0{$1},span class="fbox"] +\boxed:[{$1},f0{$1},span class="boxed"] +\framebox:[[$p!][$q!]{$1},f0{$1},span class="framebox align-$q" style="width: $p;"] +\fcolorbox:[{$p!}{$q!}{$1},f0{$1},span class="boxed" style="border-color: $p; background: $q;"] +\url:[{$u!},f0{$u},a href="$u"] +\href:[[$o]{$u!}{$t!},f0{$t},a href="$u"] +\parbox:[[$p!]{$w!}{$1},f0{1},div class="Boxed" style="width: $w;"] +\rule:[[$v!]{$w!}{$h!},f0/,hr class="line" style="width: $w; height: $h;"] +\fboxrule:[{$p!},f0{},ignored] +\fboxsep:[{$p!},f0{},ignored] +\scriptscriptstyle:[{$1},f0{$1},span class="scriptscriptstyle"] +\scriptstyle:[{$1},f0{$1},span class="scriptstyle"] +\displaystyle:[{$1},f0{$1},span class="displaystyle"] +\textstyle:[{$1},f0{$1},span class="textstyle"] +\thispagestyle:[{$p!},f0{},ignored] +\frontmatter:[,f0{},ignored] +\mainmatter:[,f0{},ignored] +\backmatter:[,f0{},ignored] +\markboth:[{$p!}{$q!},f0{},ignored] +\markright:[{$p!},f0{},ignored] +\fancyfoot:[[$p!]{$q!},f0{},ignored] +\fancyhead:[[$p!]{$q!},f0{},ignored] +\addcontentsline:[{$p!}{$q!}{$r!},f0{},ignored] +\addtocontents:[{$p!}{$q!},f0{},ignored] + +[FormulaConfig.hybridsizes] +\frac:$1+$2 +\cfrac:$1+$2 +\dfrac:$1+$2 +\binom:$1+$2 +\dbinom:$1+$2+1 +\tbinom:$1+$2+1 + +[FormulaConfig.misccommands] +\newcommand:MacroDefinition +\renewcommand:MacroDefinition +\setcounter:SetCounterFunction +\tag:FormulaTag +\tag*:FormulaTag +\limits:LimitPreviousCommand +\today:TodayCommand + +[FormulaConfig.limitcommands] +\sum:∑ +\int:∫ +\intop:∫ +\prod:∏ +\smallint:∫ +\lim:lim +# Milde 20110709 (http://milde.users.sourceforge.net/LUCR/Math/) +\zproject:⨡ +\bigsqcap:⨅ +\varprod:⨉ +\sqint:⨖ +\fint:⨏ +\zcmp:⨟ +\zpipe:⨠ +\zhide:⧹ +\biginterleave:⫼ +\iiiint:⨌ +\varointclockwise:∲ + +[FormulaConfig.bigsymbols] +∑:[⎲,⎳] +∫:[⌠,⌡] + +[FormulaConfig.labelfunctions] +\label:a name="#" + +[FormulaConfig.textfunctions] +\mbox:span class="mbox" +\text:span class="text" +\textipa:span class="textipa" +\textnormal:span class="textnormal" +\textrm:span class="textrm" +\textsf:span class="textsf" +\texttt:tt +\textit:i +\textbf:b +\textsl:i +\textsc:span class="versalitas" +\textup:span class="normal" + +[FormulaConfig.modified] + : + : +&: +':’ ++: +  +,:,  +-: −  +/: ⁄  +<: <  +=: =  +>: >  +@: +~: +$: + +[FormulaConfig.onefunctions] +\bar:span class="bar" +\begin{array}:span class="arraydef" +\big:span class="symbol" +\Big:span class="bigsymbol" +\bigg:span class="largesymbol" +\Bigg:span class="hugesymbol" +\bigl:span class="bigsymbol" +\bigr:span class="bigsymbol" +\hphantom:span class="phantom" +\overline:span class="overline" +\phantom:span class="phantom" +\underline:u +\vphantom:span class="phantom" +\underbrace:span class="underbrace" +\overbrace:span class="overbrace" +\ensuremath:span class="ensuremath" +\noindent:span class="noindent" +\centering:span class="align-center" + +[FormulaConfig.bracketcommands] +\left:span class="symbol" +\middle:span class="symbol" +\right:span class="symbol" +# simplified matched brackets +\left.:<span class="leftdot"></span> +\right.:<span class="rightdot"></span> + +[FormulaConfig.starts] +beginafter:} +beginbefore:\begin{ +bracket:{ +command:\ +complex:\[ +simple:$ +squarebracket:[ +unnumbered:* +comment:% + +[FormulaConfig.symbolfunctions] +^:sup +_:sub + +[FormulaConfig.unmodified] +characters:[.,*,€,(,),[,],:,·,!,;,|,§,"] + +[FormulaConfig.urls] +googlecharts:http://chart.googleapis.com/chart?cht=tx&chl= + +[GeneralConfig.version] +date:2011-11-22 +number:1.2.4 +lyxformat:413 + +[HeaderConfig.parameters] +branch:\branch +endbranch:\end_branch +lstset:\lstset +pdftitle:\pdf_title +documentclass:\textclass +paragraphseparation:\paragraph_separation +tocdepth:\tocdepth +secnumdepth:\secnumdepth +language:\language +beginpreamble:\begin_preamble +endpreamble:\end_preamble +outputchanges:\output_changes + +[HeaderConfig.styles] +article:[article,aastex,aapaper,acmsiggraph,sigplanconf,achemso,amsart,apa,arab-article,armenian-article,article-beamer,chess,dtk,elsarticle,heb-article,IEEEtran,iopart,kluwer,scrarticle-beamer,scrartcl,extarticle,paper,mwart,revtex4,spie,svglobal3,ltugboat,agu-dtd,jgrga,agums,entcs,egs,ijmpc,ijmpd,singlecol-new,doublecol-new,isprs,tarticle,jsarticle,jarticle,jss,literate-article,siamltex,cl2emult,llncs,svglobal,svjog,svprobth] +book:[book,amsbook,scrbook,extbook,tufte-book,report,extreport,scrreprt,memoir,tbook,jsbook,jbook,mwbk,svmono,svmult,treport,jreport,mwrep] + +[ImageConfig.converters] +imagemagick:convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output" +inkscape:inkscape "$input" --export-png="$output" +lyx:lyx -C "$input" "$output" + +[ImageConfig.cropboxformats] +.pdf:pdf +.eps:ps +.ps:ps + +[ImageConfig.formats] +vector:[.svg,.eps] +default:.png + +[LayoutConfig.groupable] +allowed:[StringContainer,Constant,TaggedText,Align,TextFamily,EmphaticText,VersalitasText,BarredText,SizeText,ColorText,LangLine,Formula] + +[NewfangleConfig.constants] +startmark:=< +startcommand:\ +endmark:> +chunkref:chunkref{ +endcommand:} + +[NumberingConfig.layouts] +ordered:[Chapter,Section,Subsection,Subsubsection,Paragraph] +roman:[Part,Book] + +[NumberingConfig.sequence] +symbols:[*,**,†,‡,§,§§,¶,¶¶,#,##] + +[StyleConfig.quotes] +ald:» +als:› +ard:« +ars:‹ +eld:“ +els:‘ +erd:” +ers:’ +fld:« +fls:‹ +frd:» +frs:› +gld:„ +gls:‚ +grd:“ +grs:‘ +pld:„ +pls:‚ +prd:” +prs:’ +sld:” +srd:” + +[StyleConfig.hspaces] +\enskip{}:  +\hfill{}:<span class="hfill"> </span> +\hspace*{\fill}:  +\hspace*{}: +\hspace{}:  +\negthinspace{}: +\qquad{}:   +\quad{}:  +\space{}:  +\thinspace{}:  +~:  + +[StyleConfig.vspaces] +defskip:<div class="defskip"> </div> +smallskip:<div class="smallskip"> </div> +medskip:<div class="medskip"> </div> +bigskip:<div class="bigskip"> </div> +vfill:<div class="vfill"> </div> + +[StyleConfig.size] +ignoredtexts:[col,text,line,page,theight,pheight] + +[StyleConfig.referenceformats] +# @ is the label number, # is page number (always 1), ↕ a direction arrow, +# $ the title, and ¶ is the part name (like Chapter) +# on-page is the string " on page " internationalized. +ref:@↕ +eqref:(@↕) +pageref:#↕ +vref:@on-page#↕ +vpageref:on-page#↕ +formatted:¶↕ +nameref:$↕ + +[TagConfig.barred] +under:u + +[TagConfig.family] +sans:span class="sans" +typewriter:tt + +[TagConfig.flex] +CharStyle:Code:span class="code" +Code:span class="code" +CharStyle:MenuItem:span class="menuitem" +MenuItem:span class="menuitem" +Noun:span class="noun" +Strong:span class="strong" + +[TagConfig.layouts] +Center:div +Chapter:h? +Date:h2 +Paragraph:div +Part:h1 +Quotation:blockquote +Quote:blockquote +Section:h? +Subsection:h? +Subsubsection:h? + +[TagConfig.group] +layouts:[Quotation,Quote] + +[TagConfig.listitems] +Enumerate:ol +Itemize:ul + +[TagConfig.notes] +Comment: +Greyedout:span class="greyedout" +Note: + +[TagConfig.shaped] +italic:i +slanted:i +smallcaps:span class="versalitas" + +[TagConfig.script] +superscript:sup +subscript:sub + +[TOCConfig.extracttitle] +allowed:[StringContainer,Constant,Space] +cloned:[TextFamily,EmphaticText,VersalitasText,BarredText,SizeText,ColorText,LangLine,Formula] +extracted:[PlainLayout,TaggedText,Align,Caption,StandardLayout,FlexInset] + +[TOCConfig.extractplain] +allowed:[StringContainer,Constant,TaggedText,Align,TextFamily,EmphaticText,VersalitasText,BarredText,SizeText,ColorText,LangLine,Formula] +cloned:[] +extracted:[] + +[TranslationConfig.constants] +abstract:Abstract +bibliography:Bibliography +references:References +index:Index +nomenclature:Nomenclature +toc:Table of Contents +toc-for:Contents for +Part:Part +Book:Book +Chapter:Chapter +Section:Section +Subsection:Subsection +Subsubsection:Subsubsection +Paragraph:Paragraph +figure:figure +float-algorithm:Algorithm +float-figure:Figure +float-listing:Listing +float-table:Table +float-tableau:Tableau +list-algorithm:List of Algorithms +list-figure:List of Figures +list-table:List of Tables +list-tableau:List of Tableaux +on-page: on page +jsmath-warning:Warning: +jsmath-requires: requires JavaScript to correctly process the mathematics on this page. +jsmath-enable:Please enable JavaScript on your browser. +next:Next +prev:Prev +up:Up +generated-by:Document generated by +generated-on: on +main-page:Main page +Appendix:Appendix +footnotes:Footnotes + +[TranslationConfig.languages] +english:en +spanish:es +deutsch:de +ngerman:de +dutch:nl +french:fr +british:en +american:en +russian:ru + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/conf/elyxer.pot elyxer-1.2.5/forks/jras-elyxer/src/conf/elyxer.pot --- elyxer-1.2.3/forks/jras-elyxer/src/conf/elyxer.pot 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/conf/elyxer.pot 2013-03-10 10:39:36.000000000 +0000 @@ -0,0 +1,152 @@ +# eLyXer internationalization file. +# Created on 2013-03-10 +# Contact: Alex Fernandez <elyxer@gmail.com> +# http://elyxer.nongnu.org/ +# This file is distributed under the same license as the eLyXer package. +# (C) 2010 Alex Fernandez <elyxer@gmail.com>. +# + + +#: Subsubsection +msgid "Subsubsection" +msgstr "Subsubsection" + +#: figure +msgid "figure" +msgstr "figure" + +#: abstract +msgid "Abstract" +msgstr "Abstract" + +#: jsmath-warning +msgid "Warning: " +msgstr "Warning: " + +#: up +msgid "Up" +msgstr "Up" + +#: Book +msgid "Book" +msgstr "Book" + +#: references +msgid "References" +msgstr "References" + +#: Subsection +msgid "Subsection" +msgstr "Subsection" + +#: list-algorithm +msgid "List of Algorithms" +msgstr "List of Algorithms" + +#: Appendix +msgid "Appendix" +msgstr "Appendix" + +#: index +msgid "Index" +msgstr "Index" + +#: bibliography +msgid "Bibliography" +msgstr "Bibliography" + +#: list-table +msgid "List of Tables" +msgstr "List of Tables" + +#: next +msgid "Next" +msgstr "Next" + +#: float-algorithm +msgid "Algorithm " +msgstr "Algorithm " + +#: Part +msgid "Part" +msgstr "Part" + +#: generated-by +msgid "Document generated by " +msgstr "Document generated by " + +#: toc +msgid "Table of Contents" +msgstr "Table of Contents" + +#: prev +msgid "Prev" +msgstr "Prev" + +#: Section +msgid "Section" +msgstr "Section" + +#: Chapter +msgid "Chapter" +msgstr "Chapter" + +#: list-tableau +msgid "List of Tableaux" +msgstr "List of Tableaux" + +#: generated-on +msgid " on " +msgstr " on " + +#: float-tableau +msgid "Tableau " +msgstr "Tableau " + +#: Paragraph +msgid "Paragraph" +msgstr "Paragraph" + +#: list-figure +msgid "List of Figures" +msgstr "List of Figures" + +#: main-page +msgid "Main page" +msgstr "Main page" + +#: float-listing +msgid "Listing " +msgstr "Listing " + +#: on-page +msgid " on page " +msgstr " on page " + +#: nomenclature +msgid "Nomenclature" +msgstr "Nomenclature" + +#: float-table +msgid "Table " +msgstr "Table " + +#: float-figure +msgid "Figure " +msgstr "Figure " + +#: toc-for +msgid "Contents for " +msgstr "Contents for " + +#: jsmath-enable +msgid "Please enable JavaScript on your browser." +msgstr "Please enable JavaScript on your browser." + +#: footnotes +msgid "Footnotes" +msgstr "Footnotes" + +#: jsmath-requires +msgid " requires JavaScript to correctly process the mathematics on this page. " +msgstr " requires JavaScript to correctly process the mathematics on this page. " diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/conf/unimathsymbols.txt elyxer-1.2.5/forks/jras-elyxer/src/conf/unimathsymbols.txt --- elyxer-1.2.3/forks/jras-elyxer/src/conf/unimathsymbols.txt 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/conf/unimathsymbols.txt 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,2861 @@ +# Unicode characters and corresponding LaTeX math mode commands +# ************************************************************* +# +# :Copyright: © 2011 Günter Milde +# :Date: Last revised 2011-03-14 +# :Licence: This work may be distributed and/or modified under the +# conditions of the `LaTeX Project Public License`_, +# either version 1.3 of this license or (at your option) +# any later version. +# +# .. _LaTeX Project Public License: http://www.latex-project.org/lppl.txt +# +# This is a mapping of mathematical Unicode characters to corresponding +# (La)TeX commands. +# +# While the contents of this file represent the best information +# available to the author as of the date referenced above, it +# contains omissions and maybe errors. It is likely that the +# information in this file will change from time to time. +# +# The character encoding of the file is UTF-8. +# +# Each data record consists of 8 fields. Fields are delimited by “^”. +# Spaces adjacent to the delimiter are not significant. The number and +# type of fields in this file may change in future versions. +# +# 1. code point (Unicode character number) +# +# The code point field is unique. +# +# 2. literal character (UTF-8 encoded) +# +# 3. (La)TeX _`command` +# +# Preferred representation of the character in TeX. +# Alternative commands are listed in the comments_ field. +# +# 4. command used by the `unicode-math`_ package +# +# .. _unicode-math: +# http://mirror.ctan.org/help/Catalogue/entries/unicode-math.html +# +# 5. Unicode math character class (after MathClassEx_). +# +# .. _MathClassEx: +# http://www.unicode.org/Public/math/revision-11/MathClassEx-11.txt +# +# The class can be one of: +# +# :N: Normal- includes all digits and symbols requiring only one form +# :A: Alphabetic +# :B: Binary +# :C: Closing – usually paired with opening delimiter +# :D: Diacritic +# :F: Fence - unpaired delimiter (often used as opening or closing) +# :G: Glyph_Part- piece of large operator +# :L: Large -n-ary or Large operator, often takes limits +# :O: Opening – usually paired with closing delimiter +# :P: Punctuation +# :R: Relation- includes arrows +# :S: Space +# :U: Unary – operators that are only unary +# :V: Vary – operators that can be unary or binary depending on context +# :X: Special –characters not covered by other classes +# +# C, O, and F operators are stretchy. In addition some binary +# operators, such as 002F are stretchy as noted in the descriptive +# comments. The classes are also useful in determining extra spacing +# around the operators as discussed in UTR#25. +# +# 6. TeX math category (after unimath-symbols_) +# +# .. _unimath-symbols: +# http://mirror.ctan.org/macros/latex/contrib/unicode-math/unimath-symbols.pdf +# +# 7. requirements and conflicts +# +# Space delimited list of LaTeX packages or features [1]_ providing +# the LaTeX command_ or conflicting with it. +# +# Packages/features preceded by a HYPHEN-MINUS (-) use the command +# for a different symbol. +# +# To save space, packages providing/modifying (almost) all commands +# of a feature or another package are not listed here but in the +# ``packages.txt`` file. +# +# .. [1] A feature can be a set of commands common to several packages, +# (e.g. ``mathbb`` or ``slantedGreek``) or a constraint (e.g. +# ``literal`` mapping plain characters to upright face). +# +# 8. descriptive _`comments` +# +# The descriptive comments provide more information about the +# character, or its specific appearance or use. +# +# Some descriptions contain references to related commands, +# marked by a character describing the relation +# +# :=: equals (alias commands), +# :#: approx (similar, different character with same glyph), +# :x: not (false friends and name clashes), +# :t: text (text mode command), +# +# followed by requirements in parantheses, and +# delimited by commas. +# +# Comments in UPPERCASE are Unicode character names +# +# no.^chr^LaTeX^unicode-math^cls^category^requirements^comments +00021^!^!^\exclam^N^mathpunct^^EXCLAMATION MARK +00023^#^\#^\octothorpe^N^mathord^^NUMBER SIGN +00024^$^\$^\mathdollar^N^mathord^^= \mathdollar, DOLLAR SIGN +00025^%^\%^\percent^N^mathord^^PERCENT SIGN +00026^&^\&^\ampersand^N^mathord^^# \binampersand (stmaryrd) +00028^(^(^\lparen^O^mathopen^^LEFT PARENTHESIS +00029^)^)^\rparen^C^mathclose^^RIGHT PARENTHESIS +0002A^*^*^^N^mathord^^# \ast, (high) ASTERISK, star +0002B^+^+^\plus^V^mathbin^^PLUS SIGN +0002C^,^,^\comma^P^mathpunct^^COMMA +0002D^-^^^N^mathbin^^t -, HYPHEN-MINUS (deprecated for math) +0002E^.^.^\period^P^mathalpha^^FULL STOP, period +0002F^/^/^\mathslash^B^mathord^^# \slash, SOLIDUS +00030^0^0^^N^mathord^^DIGIT ZERO +00031^1^1^^N^mathord^^DIGIT ONE +00032^2^2^^N^mathord^^DIGIT TWO +00033^3^3^^N^mathord^^DIGIT THREE +00034^4^4^^N^mathord^^DIGIT FOUR +00035^5^5^^N^mathord^^DIGIT FIVE +00036^6^6^^N^mathord^^DIGIT SIX +00037^7^7^^N^mathord^^DIGIT SEVEN +00038^8^8^^N^mathord^^DIGIT EIGHT +00039^9^9^^N^mathord^^DIGIT NINE +0003A^:^:^\mathcolon^P^mathpunct^-literal^= \colon (literal), COLON (not ratio) +0003B^;^;^\semicolon^P^mathpunct^^SEMICOLON p: +0003C^<^<^\less^R^mathrel^^LESS-THAN SIGN r: +0003D^=^=^\equal^R^mathrel^^EQUALS SIGN r: +0003E^>^>^\greater^R^mathrel^^GREATER-THAN SIGN r: +0003F^?^?^\question^P^mathord^^QUESTION MARK +00040^@^@^\atsign^N^mathord^^at +00041^A^A^^A^mathalpha^-literal^= \mathrm{A}, LATIN CAPITAL LETTER A +00042^B^B^^A^mathalpha^-literal^= \mathrm{B}, LATIN CAPITAL LETTER B +00043^C^C^^A^mathalpha^-literal^= \mathrm{C}, LATIN CAPITAL LETTER C +00044^D^D^^A^mathalpha^-literal^= \mathrm{D}, LATIN CAPITAL LETTER D +00045^E^E^^A^mathalpha^-literal^= \mathrm{E}, LATIN CAPITAL LETTER E +00046^F^F^^A^mathalpha^-literal^= \mathrm{F}, LATIN CAPITAL LETTER F +00047^G^G^^A^mathalpha^-literal^= \mathrm{G}, LATIN CAPITAL LETTER G +00048^H^H^^A^mathalpha^-literal^= \mathrm{H}, LATIN CAPITAL LETTER H +00049^I^I^^A^mathalpha^-literal^= \mathrm{I}, LATIN CAPITAL LETTER I +0004A^J^J^^A^mathalpha^-literal^= \mathrm{J}, LATIN CAPITAL LETTER J +0004B^K^K^^A^mathalpha^-literal^= \mathrm{K}, LATIN CAPITAL LETTER K +0004C^L^L^^A^mathalpha^-literal^= \mathrm{L}, LATIN CAPITAL LETTER L +0004D^M^M^^A^mathalpha^-literal^= \mathrm{M}, LATIN CAPITAL LETTER M +0004E^N^N^^A^mathalpha^-literal^= \mathrm{N}, LATIN CAPITAL LETTER N +0004F^O^O^^A^mathalpha^-literal^= \mathrm{O}, LATIN CAPITAL LETTER O +00050^P^P^^A^mathalpha^-literal^= \mathrm{P}, LATIN CAPITAL LETTER P +00051^Q^Q^^A^mathalpha^-literal^= \mathrm{Q}, LATIN CAPITAL LETTER Q +00052^R^R^^A^mathalpha^-literal^= \mathrm{R}, LATIN CAPITAL LETTER R +00053^S^S^^A^mathalpha^-literal^= \mathrm{S}, LATIN CAPITAL LETTER S +00054^T^T^^A^mathalpha^-literal^= \mathrm{T}, LATIN CAPITAL LETTER T +00055^U^U^^A^mathalpha^-literal^= \mathrm{U}, LATIN CAPITAL LETTER U +00056^V^V^^A^mathalpha^-literal^= \mathrm{V}, LATIN CAPITAL LETTER V +00057^W^W^^A^mathalpha^-literal^= \mathrm{W}, LATIN CAPITAL LETTER W +00058^X^X^^A^mathalpha^-literal^= \mathrm{X}, LATIN CAPITAL LETTER X +00059^Y^Y^^A^mathalpha^-literal^= \mathrm{Y}, LATIN CAPITAL LETTER Y +0005A^Z^Z^^A^mathalpha^-literal^= \mathrm{Z}, LATIN CAPITAL LETTER Z +0005B^[^\lbrack^\lbrack^O^mathopen^^LEFT SQUARE BRACKET +0005C^\^\backslash^\backslash^B^mathord^^REVERSE SOLIDUS +0005D^]^\rbrack^\rbrack^C^mathclose^^RIGHT SQUARE BRACKET +0005E^^\sphat^^N^mathord^amsxtra^CIRCUMFLEX ACCENT, TeX superscript operator +0005F^_^\_^^N^mathord^^LOW LINE, TeX subscript operator +00060^`^^^D^mathord^^grave, alias for 0300 +00061^a^a^^A^mathalpha^-literal^= \mathrm{a}, LATIN SMALL LETTER A +00062^b^b^^A^mathalpha^-literal^= \mathrm{b}, LATIN SMALL LETTER B +00063^c^c^^A^mathalpha^-literal^= \mathrm{c}, LATIN SMALL LETTER C +00064^d^d^^A^mathalpha^-literal^= \mathrm{d}, LATIN SMALL LETTER D +00065^e^e^^A^mathalpha^-literal^= \mathrm{e}, LATIN SMALL LETTER E +00066^f^f^^A^mathalpha^-literal^= \mathrm{f}, LATIN SMALL LETTER F +00067^g^g^^A^mathalpha^-literal^= \mathrm{g}, LATIN SMALL LETTER G +00068^h^h^^A^mathalpha^-literal^= \mathrm{h}, LATIN SMALL LETTER H +00069^i^i^^A^mathalpha^-literal^= \mathrm{i}, LATIN SMALL LETTER I +0006A^j^j^^A^mathalpha^-literal^= \mathrm{j}, LATIN SMALL LETTER J +0006B^k^k^^A^mathalpha^-literal^= \mathrm{k}, LATIN SMALL LETTER K +0006C^l^l^^A^mathalpha^-literal^= \mathrm{l}, LATIN SMALL LETTER L +0006D^m^m^^A^mathalpha^-literal^= \mathrm{m}, LATIN SMALL LETTER M +0006E^n^n^^A^mathalpha^-literal^= \mathrm{n}, LATIN SMALL LETTER N +0006F^o^o^^A^mathalpha^-literal^= \mathrm{o}, LATIN SMALL LETTER O +00070^p^p^^A^mathalpha^-literal^= \mathrm{p}, LATIN SMALL LETTER P +00071^q^q^^A^mathalpha^-literal^= \mathrm{q}, LATIN SMALL LETTER Q +00072^r^r^^A^mathalpha^-literal^= \mathrm{r}, LATIN SMALL LETTER R +00073^s^s^^A^mathalpha^-literal^= \mathrm{s}, LATIN SMALL LETTER S +00074^t^t^^A^mathalpha^-literal^= \mathrm{t}, LATIN SMALL LETTER T +00075^u^u^^A^mathalpha^-literal^= \mathrm{u}, LATIN SMALL LETTER U +00076^v^v^^A^mathalpha^-literal^= \mathrm{v}, LATIN SMALL LETTER V +00077^w^w^^A^mathalpha^-literal^= \mathrm{w}, LATIN SMALL LETTER W +00078^x^x^^A^mathalpha^-literal^= \mathrm{x}, LATIN SMALL LETTER X +00079^y^y^^A^mathalpha^-literal^= \mathrm{y}, LATIN SMALL LETTER Y +0007A^z^z^^A^mathalpha^-literal^= \mathrm{z}, LATIN SMALL LETTER Z +0007B^{^\{^\lbrace^O^mathopen^^= \lbrace, LEFT CURLY BRACKET +0007C^|^|^\vert^F^mathfence^^= \vert, vertical bar +0007D^}^\}^\rbrace^C^mathclose^^= \rbrace, RIGHT CURLY BRACKET +0007E^~^\sptilde^^N^mathord^amsxtra^# \sim, TILDE +000A0^ ^~^^S^^^nbsp +000A1^¡^^^P^^^iexcl +000A2^¢^\cent^^N^mathord^wasysym^= \mathcent (txfonts), cent +000A3^£^\pounds^\sterling^N^mathord^-fourier -omlmathit^= \mathsterling (txfonts), POUND SIGN, fourier prints a dollar sign +000A4^¤^^^N^mathord^^t \currency (wasysym), curren +000A5^¥^\yen^\yen^N^mathord^amsfonts^YEN SIGN +000A6^¦^^^N^mathord^^brvbar (vertical) +000A7^§^^^N^mathord^^sect +000A8^¨^\spddot^^D^mathord^amsxtra^Dot /die, alias for 0308 +000AC^¬^\neg^\neg^U^mathord^^= \lnot, NOT SIGN +000AE^®^\circledR^^X^mathord^amsfonts^REGISTERED SIGN +000AF^¯^^^D^mathord^^macr, alias for 0304 +000B0^°^^^N^mathord^^deg +000B1^±^\pm^\pm^V^mathbin^^plus-or-minus sign +000B2^²^^^N^mathord^^sup2 +000B3^³^^^N^mathord^^sup3 +000B4^´^^^N^mathord^^acute, alias for 0301 +000B5^µ^\Micro^^N^mathalpha^wrisym^= \tcmu (mathcomp), t \textmu (textcomp), # \mathrm{\mu} (omlmathrm), # \muup (kpfonts mathdesign), MICRO SIGN +000B6^¶^^^N^mathord^^para (paragraph sign, pilcrow) +000B7^·^^\cdotp^B^mathbin^^# \cdot, x \centerdot, b: MIDDLE DOT +000B9^¹^^^N^mathord^^sup1 +000BC^¼^^^N^mathord^^frac14 +000BD^½^^^N^mathord^^frac12 +000BE^¾^^^N^mathord^^frac34 +000BF^¿^^^P^^^iquest +000D7^×^\times^\times^B^mathbin^^MULTIPLICATION SIGN, z notation Cartesian product +000F0^ð^\eth^\matheth^^mathalpha^amssymb arevmath^eth +000F7^÷^\div^\div^B^mathbin^^divide sign +00131^ı^\imath^^A^mathalpha^-literal^imath +001B5^Ƶ^^\Zbar^^mathord^^impedance +00237^ȷ^\jmath^^A^mathalpha^-literal^jmath +002C6^ˆ^^^D^mathalpha^^circ, alias for 0302 +002C7^ˇ^^^D^mathalpha^^CARON, alias for 030C +002D8^˘^^^D^mathord^^BREVE, alias for 0306 +002D9^˙^^^D^mathord^^dot, alias for 0307 +002DA^˚^^^D^mathord^^ring, alias for 030A +002DC^˜^^^D^mathord^^tilde, alias for 0303 +00300^x̀^\grave^\grave^D^mathaccent^^grave accent +00301^x́^\acute^\acute^D^mathaccent^^acute accent +00302^x̂^\hat^\hat^D^mathaccent^^# \widehat (amssymb), circumflex accent +00303^x̃^\tilde^\tilde^D^mathaccent^^# \widetilde (yhmath, fourier), tilde +00304^x̄^\bar^\bar^D^mathaccent^^macron +00305^x̅^\overline^\overbar^D^mathaccent^^overbar embellishment +00306^x̆^\breve^\breve^D^mathaccent^^breve +00307^ẋ^\dot^\dot^D^mathaccent^-oz^= \Dot (wrisym), dot above +00308^ẍ^\ddot^\ddot^D^mathaccent^^= \DDot (wrisym), dieresis +00309^x̉^^\ovhook^^mathaccent^^COMBINING HOOK ABOVE +0030A^x̊^\mathring^\ocirc^D^mathaccent^amssymb^= \ring (yhmath), ring +0030C^x̌^\check^\check^D^mathaccent^^caron +00310^x̐^^\candra^^mathaccent^^candrabindu (non-spacing) +00311^x̑^^^D^mathaccent^^COMBINING INVERTED BREVE +00312^x̒^^\oturnedcomma^^mathaccent^^COMBINING TURNED COMMA ABOVE +00315^x̕^^\ocommatopright^^mathaccent^^COMBINING COMMA ABOVE RIGHT +0031A^x̚^^\droang^^mathaccent^^left angle above (non-spacing) +00323^x̣^^^D^mathaccent^^COMBINING DOT BELOW +0032C^x̬^^^D^mathaccent^^COMBINING CARON BELOW +0032D^x̭^^^D^mathaccent^^COMBINING CIRCUMFLEX ACCENT BELOW +0032E^x̮^^^D^mathaccent^^COMBINING BREVE BELOW +0032F^x̯^^^D^mathaccent^^COMBINING INVERTED BREVE BELOW +00330^x̰^\utilde^\wideutilde^D^mathaccent^undertilde^under tilde accent (multiple characters and non-spacing) +00331^x̱^\underbar^\underbar^D^mathaccent^^COMBINING MACRON BELOW +00332^x̲^\underline^^D^mathaccent^^COMBINING LOW LINE +00333^x̳^^^D^mathaccent^^2lowbar +00338^x̸^\not^\not^D^mathaccent^^COMBINING LONG SOLIDUS OVERLAY +0033A^x̺^^^D^mathaccent^^COMBINING INVERTED BRIDGE BELOW +0033F^x̿^^^D^mathaccent^^COMBINING DOUBLE OVERLINE +00346^x͆^^^D^mathaccent^^COMBINING BRIDGE ABOVE +00391^Α^^\upAlpha^A^mathalpha^^capital alpha, greek +00392^Β^^\upBeta^A^mathalpha^^capital beta, greek +00393^Γ^\Gamma^\upGamma^A^mathalpha^-literal^= \Gamma (-slantedGreek), = \mathrm{\Gamma}, capital gamma, greek +00394^Δ^\Delta^\upDelta^A^mathalpha^-literal^= \Delta (-slantedGreek), = \mathrm{\Delta}, capital delta, greek +00395^Ε^^\upEpsilon^A^mathalpha^^capital epsilon, greek +00396^Ζ^^\upZeta^A^mathalpha^^capital zeta, greek +00397^Η^^\upEta^A^mathalpha^^capital eta, greek +00398^Θ^\Theta^\upTheta^A^mathalpha^-literal^= \Theta (-slantedGreek), = \mathrm{\Theta}, capital theta, greek +00399^Ι^^\upIota^A^mathalpha^^capital iota, greek +0039A^Κ^^\upKappa^A^mathalpha^^capital kappa, greek +0039B^Λ^\Lambda^\upLambda^A^mathalpha^-literal^= \Lambda (-slantedGreek), = \mathrm{\Lambda}, capital lambda, greek +0039C^Μ^^\upMu^A^mathalpha^^capital mu, greek +0039D^Ν^^\upNu^A^mathalpha^^capital nu, greek +0039E^Ξ^\Xi^\upXi^A^mathalpha^-literal^= \Xi (-slantedGreek), = \mathrm{\Xi}, capital xi, greek +0039F^Ο^^\upOmicron^A^mathalpha^^capital omicron, greek +003A0^Π^\Pi^\upPi^A^mathalpha^-literal^= \Pi (-slantedGreek), = \mathrm{\Pi}, capital pi, greek +003A1^Ρ^^\upRho^A^mathalpha^^capital rho, greek +003A3^Σ^\Sigma^\upSigma^A^mathalpha^-literal^= \Sigma (-slantedGreek), = \mathrm{\Sigma}, capital sigma, greek +003A4^Τ^^\upTau^A^mathalpha^^capital tau, greek +003A5^Υ^\Upsilon^\upUpsilon^A^mathalpha^-literal^= \Upsilon (-slantedGreek), = \mathrm{\Upsilon}, capital upsilon, greek +003A6^Φ^\Phi^\upPhi^A^mathalpha^-literal^= \Phi (-slantedGreek), = \mathrm{\Phi}, capital phi, greek +003A7^Χ^^\upChi^A^mathalpha^^capital chi, greek +003A8^Ψ^\Psi^\upPsi^A^mathalpha^-literal^= \Psi (-slantedGreek), = \mathrm{\Psi}, capital psi, greek +003A9^Ω^\Omega^\upOmega^A^mathalpha^-literal^= \Omega (-slantedGreek), = \mathrm{\Omega}, capital omega, greek +003B1^α^\alpha^\upalpha^A^mathalpha^-literal^= \mathrm{\alpha} (omlmathrm), = \alphaup (kpfonts mathdesign), = \upalpha (upgreek), alpha, greek +003B2^β^\beta^\upbeta^A^mathalpha^-literal^= \mathrm{\beta} (omlmathrm), = \betaup (kpfonts mathdesign), = \upbeta (upgreek), beta, greek +003B3^γ^\gamma^\upgamma^A^mathalpha^-literal^= \mathrm{\gamma} (omlmathrm), = \gammaup (kpfonts mathdesign), = \upgamma (upgreek), gamma, greek +003B4^δ^\delta^\updelta^A^mathalpha^-literal^= \mathrm{\delta} (omlmathrm), = \deltaup (kpfonts mathdesign), = \updelta (upgreek), delta, greek +003B5^ε^\varepsilon^\upepsilon^A^mathalpha^-literal^= \mathrm{\varepsilon} (omlmathrm), = \varepsilonup (kpfonts mathdesign), = \upepsilon (upgreek), rounded epsilon, greek +003B6^ζ^\zeta^\upzeta^A^mathalpha^-literal^= \mathrm{\zeta} (omlmathrm), = \zetaup (kpfonts mathdesign), = \upzeta (upgreek), zeta, greek +003B7^η^\eta^\upeta^A^mathalpha^-literal^= \mathrm{\eta} (omlmathrm), = \etaup (kpfonts mathdesign), = \upeta (upgreek), eta, greek +003B8^θ^\theta^\uptheta^A^mathalpha^-literal^= \mathrm{\theta} (omlmathrm), = \thetaup (kpfonts mathdesign), straight theta, = \uptheta (upgreek), theta, greek +003B9^ι^\iota^\upiota^A^mathalpha^-literal^= \mathrm{\iota} (omlmathrm), = \iotaup (kpfonts mathdesign), = \upiota (upgreek), iota, greek +003BA^κ^\kappa^\upkappa^A^mathalpha^-literal^= \mathrm{\kappa} (omlmathrm), = \kappaup (kpfonts mathdesign), = \upkappa (upgreek), kappa, greek +003BB^λ^\lambda^\uplambda^A^mathalpha^-literal^= \mathrm{\lambda} (omlmathrm), = \lambdaup (kpfonts mathdesign), = \uplambda (upgreek), lambda, greek +003BC^μ^\mu^\upmu^A^mathalpha^-literal^= \mathrm{\mu} (omlmathrm), = \muup (kpfonts mathdesign), = \upmu (upgreek), mu, greek +003BD^ν^\nu^\upnu^A^mathalpha^-literal^= \mathrm{\nu} (omlmathrm), = \nuup (kpfonts mathdesign), = \upnu (upgreek), nu, greek +003BE^ξ^\xi^\upxi^A^mathalpha^-literal^= \mathrm{\xi} (omlmathrm), = \xiup (kpfonts mathdesign), = \upxi (upgreek), xi, greek +003BF^ο^^\upomicron^A^mathalpha^^small omicron, greek +003C0^π^\pi^\uppi^A^mathalpha^-literal^= \mathrm{\pi} (omlmathrm), = \piup (kpfonts mathdesign), = \uppi (upgreek), pi, greek +003C1^ρ^\rho^\uprho^A^mathalpha^-literal^= \mathrm{\rho} (omlmathrm), = \rhoup (kpfonts mathdesign), = \uprho (upgreek), rho, greek +003C2^ς^\varsigma^\upvarsigma^^mathalpha^-literal^= \mathrm{\varsigma} (omlmathrm), = \varsigmaup (kpfonts mathdesign), = \upvarsigma (upgreek), terminal sigma, greek +003C3^σ^\sigma^\upsigma^A^mathalpha^-literal^= \mathrm{\sigma} (omlmathrm), = \sigmaup (kpfonts mathdesign), = \upsigma (upgreek), sigma, greek +003C4^τ^\tau^\uptau^A^mathalpha^-literal^= \mathrm{\tau} (omlmathrm), = \tauup (kpfonts mathdesign), = \uptau (upgreek), tau, greek +003C5^υ^\upsilon^\upupsilon^A^mathalpha^-literal^= \mathrm{\upsilon} (omlmathrm), = \upsilonup (kpfonts mathdesign), = \upupsilon (upgreek), upsilon, greek +003C6^φ^\varphi^\upvarphi^A^mathalpha^-literal^= \mathrm{\varphi} (omlmathrm), = \varphiup (kpfonts mathdesign), = \upvarphi (upgreek), curly or open phi, greek +003C7^χ^\chi^\upchi^A^mathalpha^-literal^= \mathrm{\chi} (omlmathrm), = \chiup (kpfonts mathdesign), = \upchi (upgreek), chi, greek +003C8^ψ^\psi^\uppsi^A^mathalpha^-literal^= \mathrm{\psi} (omlmathrm), = \psiup (kpfonts mathdesign), = \uppsi (upgreek), psi, greek +003C9^ω^\omega^\upomega^A^mathalpha^-literal^= \mathrm{\omega} (omlmathrm), = \omegaup (kpfonts mathdesign), = \upomega (upgreek), omega, greek +003D0^ϐ^\varbeta^\upvarbeta^A^mathalpha^arevmath^rounded beta, greek +003D1^ϑ^\vartheta^\upvartheta^A^mathalpha^-literal^= \mathrm{\vartheta} (omlmathrm), = \varthetaup (kpfonts mathdesign), curly or open theta +003D2^ϒ^^\upUpsilon^A^mathalpha^^# \mathrm{\Upsilon}, GREEK UPSILON WITH HOOK SYMBOL +003D5^ϕ^\phi^\upphi^A^mathalpha^-literal^= \mathrm{\phi} (omlmathrm), = \phiup (kpfonts mathdesign), GREEK PHI SYMBOL (straight) +003D6^ϖ^\varpi^\upvarpi^A^mathalpha^-literal^= \mathrm{\varpi} (omlmathrm), = \varpiup (kpfonts mathdesign), GREEK PI SYMBOL (pomega) +003D8^Ϙ^\Qoppa^\upoldKoppa^N^mathord^arevmath^= \Koppa (wrisym), t \Qoppa (LGR), GREEK LETTER ARCHAIC KOPPA +003D9^ϙ^\qoppa^\upoldkoppa^N^mathord^arevmath^= \koppa (wrisym), t \qoppa (LGR), GREEK SMALL LETTER ARCHAIC KOPPA +003DA^Ϛ^\Stigma^\upStigma^A^mathalpha^arevmath wrisym^capital stigma +003DB^ϛ^\stigma^\upstigma^A^mathalpha^arevmath wrisym^GREEK SMALL LETTER STIGMA +003DC^Ϝ^\digamma^\upDigamma^A^mathalpha^amssymb -wrisym^= \Digamma (wrisym), capital digamma +003DD^ϝ^\digamma^\updigamma^A^mathalpha^arevmath wrisym -amssymb^GREEK SMALL LETTER DIGAMMA +003DE^Ϟ^\Koppa^\upKoppa^^mathalpha^arevmath^capital koppa +003DF^ϟ^\koppa^\upkoppa^^mathalpha^arevmath^GREEK SMALL LETTER KOPPA +003E0^Ϡ^\Sampi^\upSampi^A^mathalpha^arevmath wrisym^capital sampi +003E1^ϡ^\sampi^\upsampi^A^mathalpha^arevmath^# \sampi (wrisym), GREEK SMALL LETTER SAMPI +003F0^ϰ^^\upvarkappa^A^mathalpha^^GREEK KAPPA SYMBOL (round) +003F1^ϱ^\varrho^\upvarrho^A^mathalpha^omlmathrm -literal^= \mathrm{\varrho} (omlmathrm), = \varrhoup (kpfonts mathdesign), GREEK RHO SYMBOL (round) +003F4^ϴ^^\upvarTheta^A^mathalpha^^x \varTheta (amssymb), GREEK CAPITAL THETA SYMBOL +003F5^ϵ^\epsilon^\upvarepsilon^A^mathalpha^omlmathrm -literal^= \mathrm{\epsilon} (omlmathrm), = \epsilonup (kpfonts mathdesign), GREEK LUNATE EPSILON SYMBOL +003F6^϶^\backepsilon^\upbackepsilon^N^mathord^amssymb wrisym^GREEK REVERSED LUNATE EPSILON SYMBOL +00428^Ш^^^A^mathalpha^^t \CYRSHHA (T2A), Shcy, CYRILLIC CAPITAL LETTER SHA +02000^ ^^^S^^^enquad +02001^ ^\quad^^S^^^emquad +02002^ ^^^S^^^ensp (half an em) +02003^ ^^^S^^^emsp +02004^ ^^^S^^^THREE-PER-EM SPACE +02005^ ^^^S^^^FOUR-PER-EM SPACE, mid space +02006^ ^^^S^^^SIX-PER-EM SPACE +02007^ ^^^S^^^FIGURE SPACE +02009^ ^^^S^^^THIN SPACE +0200A^ ^^^S^^^HAIR SPACE +0200B^​^^^S^^^# \hspace{0pt}, zwsp +02010^‐^^^P^mathord^^HYPHEN (true graphic) +02012^‒^^^P^mathord^^dash +02013^–^^^P^mathord^^ndash +02014^—^^^P^mathord^^mdash +02015^―^^\horizbar^^mathord^^HORIZONTAL BAR +02016^‖^\|^\Vert^F^mathfence^^= \Vert, double vertical bar +02017^‗^^\twolowline^^mathord^^DOUBLE LOW LINE (spacing) +02020^†^\dagger^\dagger^N^mathbin^^DAGGER relation +02021^‡^\ddagger^\ddagger^N^mathbin^^DOUBLE DAGGER relation +02022^•^^\smblkcircle^B^mathbin^^# \bullet, b: round BULLET, filled +02025^‥^^\enleadertwodots^^mathord^^double baseline dot (en leader) +02026^…^\ldots^\unicodeellipsis^N^mathord^^ellipsis (horizontal) +02032^′^\prime^\prime^N^mathord^^PRIME or minute, not superscripted +02033^″^\second^\dprime^N^mathord^mathabx^DOUBLE PRIME or second, not superscripted +02034^‴^\third^\trprime^N^mathord^mathabx^TRIPLE PRIME (not superscripted) +02035^‵^\backprime^\backprime^N^mathord^amssymb^reverse prime, not superscripted +02036^‶^^\backdprime^N^mathord^^double reverse prime, not superscripted +02037^‷^^\backtrprime^N^mathord^^triple reverse prime, not superscripted +02038^‸^^\caretinsert^^mathord^^CARET (insertion mark) +0203B^※^^^N^^^REFERENCE MARK, Japanese kome jirushi +0203C^‼^^\Exclam^N^mathord^^# !!, DOUBLE EXCLAMATION MARK +02040^⁀^\cat^\tieconcat^B^mathbin^oz^CHARACTER TIE, z notation sequence concatenation +02043^⁃^^\hyphenbullet^^mathord^^rectangle, filled (HYPHEN BULLET) +02044^⁄^^\fracslash^B^mathbin^^# /, FRACTION SLASH +02047^⁇^^\Question^^mathord^^# ??, DOUBLE QUESTION MARK +0204E^⁎^^^B^mathbin^^# \ast, lowast, LOW ASTERISK +0204F^⁏^^^R^^^bsemi, REVERSED SEMICOLON +02050^⁐^^\closure^R^mathrel^^CLOSE UP (editing mark) +02051^⁑^^^N^^^Ast +02052^⁒^^^N^mathord^^# ./., COMMERCIAL MINUS SIGN +02057^⁗^\fourth^\qprime^N^mathord^mathabx^QUADRUPLE PRIME, not superscripted +0205F^ ^\:^^S^^^= \medspace (amsmath), MEDIUM MATHEMATICAL SPACE, four-eighteenths of an em +02061^⁡^^^B^^^FUNCTION APPLICATION +02062^⁢^^^B^^^INVISIBLE TIMES +02063^⁣^^^P^^^INVISIBLE SEPARATOR +02064^⁤^^^X^^^INVISIBLE PLUS +0207A^⁺^^^N^mathord^^SUPERSCRIPT PLUS SIGN subscript operators +0207B^⁻^^^N^mathord^^SUPERSCRIPT MINUS subscript operators +0207C^⁼^^^N^mathord^^SUPERSCRIPT EQUALS SIGN subscript operators +0207D^⁽^^^N^mathopen^^SUPERSCRIPT LEFT PARENTHESIS subscript operators +0207E^⁾^^^N^mathclose^^SUPERSCRIPT RIGHT PARENTHESIS subscript operators +0208A^₊^^^N^mathord^^SUBSCRIPT PLUS SIGN superscript operators +0208B^₋^^^N^mathord^^SUBSCRIPT MINUS superscript operators +0208C^₌^^^N^mathord^^SUBSCRIPT EQUALS SIGN superscript operators +0208D^₍^^^N^mathopen^^SUBSCRIPT LEFT PARENTHESIS superscript operators +0208E^₎^^^N^mathclose^^SUBSCRIPT RIGHT PARENTHESIS superscript operators +020AC^€^^\euro^^mathord^^EURO SIGN +020D0^x⃐^\lvec^\leftharpoonaccent^D^mathaccent^wrisym^COMBINING LEFT HARPOON ABOVE +020D1^x⃑^\vec^\rightharpoonaccent^D^mathaccent^wrisym^COMBINING RIGHT HARPOON ABOVE +020D2^x⃒^^\vertoverlay^D^mathaccent^^COMBINING LONG VERTICAL LINE OVERLAY +020D3^x⃓^^^X^mathaccent^^COMBINING SHORT VERTICAL LINE OVERLAY +020D4^x⃔^^^D^mathaccent^^COMBINING ANTICLOCKWISE ARROW ABOVE +020D6^x⃖^\LVec^\overleftarrow^D^mathaccent^wrisym^# \overleftarrow, COMBINING LEFT ARROW ABOVE +020D7^x⃗^\vec^\vec^D^mathaccent^-wrisym^= \Vec (wrisym), # \overrightarrow, COMBINING RIGHT ARROW ABOVE +020D8^x⃘^^^D^mathaccent^^COMBINING RING OVERLAY +020D9^x⃙^^^D^mathaccent^^COMBINING CLOCKWISE RING OVERLAY +020DA^x⃚^^^D^mathaccent^^COMBINING ANTICLOCKWISE RING OVERLAY +020DB^x⃛^\dddot^\dddot^D^mathaccent^amsmath^= \DDDot (wrisym), COMBINING THREE DOTS ABOVE +020DC^x⃜^\ddddot^\ddddot^D^mathaccent^amsmath^COMBINING FOUR DOTS ABOVE +020DD^x⃝^^\enclosecircle^D^mathaccent^^COMBINING ENCLOSING CIRCLE +020DE^x⃞^^\enclosesquare^D^mathaccent^^COMBINING ENCLOSING SQUARE +020DF^x⃟^^\enclosediamond^D^mathaccent^^COMBINING ENCLOSING DIAMOND +020E1^x⃡^\overleftrightarrow^\overleftrightarrow^D^mathaccent^amsmath^COMBINING LEFT RIGHT ARROW ABOVE +020E4^x⃤^^\enclosetriangle^D^mathaccent^^COMBINING ENCLOSING UPWARD POINTING TRIANGLE +020E5^x⃥^^^D^mathaccent^^COMBINING REVERSE SOLIDUS OVERLAY +020E6^x⃦^^^D^mathaccent^^COMBINING DOUBLE VERTICAL STROKE OVERLAY, z notation finite function diacritic +020E7^x⃧^^\annuity^D^mathaccent^^COMBINING ANNUITY SYMBOL +020E8^x⃨^^\threeunderdot^D^mathaccent^^COMBINING TRIPLE UNDERDOT +020E9^x⃩^^\widebridgeabove^D^mathaccent^^COMBINING WIDE BRIDGE ABOVE +020EA^x⃪^^^D^mathaccent^^COMBINING LEFTWARDS ARROW OVERLAY +020EB^x⃫^^^D^mathaccent^^COMBINING LONG DOUBLE SOLIDUS OVERLAY +020EC^x⃬^^\underrightharpoondown^D^mathaccent^^COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS +020ED^x⃭^^\underleftharpoondown^D^mathaccent^^COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS +020EE^x⃮^\underleftarrow^\underleftarrow^D^mathaccent^amsmath^COMBINING LEFT ARROW BELOW +020EF^x⃯^\underrightarrow^\underrightarrow^D^mathaccent^amsmath^COMBINING RIGHT ARROW BELOW +020F0^x⃰^^\asteraccent^^mathaccent^^COMBINING ASTERISK ABOVE +02102^ℂ^\mathbb{C}^\BbbC^A^mathalpha^mathbb^= \mathds{C} (dsfont), open face C +02107^ℇ^\Euler^\Eulerconst^N^mathord^wrisym^EULER CONSTANT +0210A^ℊ^\mathcal{g}^\mscrg^A^mathalpha^urwchancal^/scr g, script small letter g +0210B^ℋ^\mathcal{H}^\mscrH^A^mathalpha^^hamiltonian (script capital H) +0210C^ℌ^\mathfrak{H}^\mfrakH^A^mathalpha^eufrak^/frak H, black-letter capital H +0210D^ℍ^\mathbb{H}^\BbbH^A^mathalpha^mathbb^= \mathds{H} (dsfont), open face capital H +0210E^ℎ^^\Planckconst^N^mathord^^# h, Planck constant +0210F^ℏ^\hslash^\hslash^N^mathalpha^amssymb fourier arevmath^=\HBar (wrisym), Planck's h over 2pi +02110^ℐ^\mathcal{I}^\mscrI^A^mathalpha^^/scr I, script capital I +02111^ℑ^\Im^\Im^A^mathalpha^^= \mathfrak{I} (eufrak), imaginary part +02112^ℒ^\mathcal{L}^\mscrL^A^mathalpha^^lagrangian (script capital L) +02113^ℓ^\ell^\ell^A^mathalpha^^cursive small l +02115^ℕ^\mathbb{N}^\BbbN^A^mathalpha^mathbb^= \mathds{N} (dsfont), open face N +02118^℘^\wp^\wp^A^mathalpha^amssymb^weierstrass p +02119^ℙ^\mathbb{P}^\BbbP^A^mathalpha^mathbb^= \mathds{P} (dsfont), open face P +0211A^ℚ^\mathbb{Q}^\BbbQ^A^mathalpha^mathbb^= \mathds{Q} (dsfont), open face Q +0211B^ℛ^\mathcal{R}^\mscrR^A^mathalpha^^/scr R, script capital R +0211C^ℜ^\Re^\Re^A^mathalpha^^= \mathfrak{R} (eufrak), real part +0211D^ℝ^\mathbb{R}^\BbbR^A^mathalpha^mathbb^= \mathds{R} (dsfont), open face R +02124^ℤ^\mathbb{Z}^\BbbZ^A^mathalpha^mathbb^= \mathds{Z} (dsfont), open face Z +02126^Ω^\tcohm^^N^mathalpha^mathcomp^# \mathrm{\Omega}, ohm (deprecated in math, use greek letter) +02127^℧^\mho^\mho^N^mathord^amsfonts arevmath^= \Mho (wrisym), t \agemO (wasysym), conductance +02128^ℨ^\mathfrak{Z}^\mfrakZ^A^mathalpha^eufrak^/frak Z, black-letter capital Z +02129^℩^^\turnediota^N^mathalpha^^turned iota +0212B^Å^\Angstroem^\Angstrom^A^mathalpha^wrisym^# \mathring{\mathrm{A}}, Ångström capital A with ring +0212C^ℬ^\mathcal{B}^\mscrB^A^mathalpha^^bernoulli function (script capital B) +0212D^ℭ^\mathfrak{C}^\mfrakC^A^mathalpha^eufrak^black-letter capital C +0212F^ℯ^\mathcal{e}^\mscre^A^mathalpha^urwchancal^/scr e, script small letter e +02130^ℰ^\mathcal{E}^\mscrE^A^mathalpha^^/scr E, script capital E +02131^ℱ^\mathcal{F}^\mscrF^A^mathalpha^^/scr F, script capital F +02132^Ⅎ^\Finv^\Finv^N^mathord^amssymb^TURNED CAPITAL F +02133^ℳ^\mathcal{M}^\mscrM^A^mathalpha^^physics m-matrix (SCRIPT CAPITAL M) +02134^ℴ^\mathcal{o}^\mscro^A^mathalpha^urwchancal^order of (SCRIPT SMALL O) +02135^ℵ^\aleph^\aleph^A^mathalpha^^aleph, hebrew +02136^ℶ^\beth^\beth^A^mathalpha^amssymb wrisym^beth, hebrew +02137^ℷ^\gimel^\gimel^A^mathalpha^amssymb wrisym^gimel, hebrew +02138^ℸ^\daleth^\daleth^A^mathalpha^amssymb wrisym^daleth, hebrew +0213C^ℼ^\mathbb{\pi}^\Bbbpi^A^mathord^bbold^\DoublePi (wrisym), DOUBLE-STRUCK SMALL PI +0213D^ℽ^\mathbb{\gamma}^\Bbbgamma^A^mathalpha^bbold^\EulerGamma (wrisym), DOUBLE-STRUCK SMALL GAMMA +0213E^ℾ^\mathbb{\Gamma}^\BbbGamma^N^mathalpha^bbold^DOUBLE-STRUCK CAPITAL GAMMA +0213F^ℿ^\mathbb{\Pi}^\BbbPi^A^mathalpha^bbold^DOUBLE-STRUCK CAPITAL PI +02140^⅀^\mathbb{\Sigma}^\Bbbsum^L^mathop^bbold^DOUBLE-STRUCK N-ARY SUMMATION +02141^⅁^^\Game^N^mathord^^# \Game (amssymb), TURNED SANS-SERIF CAPITAL G (amssymb has mirrored G) +02142^⅂^^\sansLturned^N^mathord^^TURNED SANS-SERIF CAPITAL L +02143^⅃^^\sansLmirrored^N^mathord^^REVERSED SANS-SERIF CAPITAL L +02144^⅄^\Yup^\Yup^N^mathord^stmaryrd^TURNED SANS-SERIF CAPITAL Y +02145^ⅅ^\CapitalDifferentialD^\mitBbbD^N^mathord^wrisym^= \DD (wrisym), DOUBLE-STRUCK ITALIC CAPITAL D +02146^ⅆ^\DifferentialD^\mitBbbd^N^mathord^wrisym^= \dd (wrisym), DOUBLE-STRUCK ITALIC SMALL D +02147^ⅇ^\ExponetialE^\mitBbbe^N^mathord^wrisym^= \ee (wrisym), DOUBLE-STRUCK ITALIC SMALL E +02148^ⅈ^\ComplexI^\mitBbbi^N^mathord^wrisym^= \ii (wrisym), DOUBLE-STRUCK ITALIC SMALL I +02149^ⅉ^\ComplexJ^\mitBbbj^N^mathord^wrisym^= \jj (wrisym), DOUBLE-STRUCK ITALIC SMALL J +0214A^⅊^^\PropertyLine^^mathord^^PROPERTY LINE +0214B^⅋^\invamp^\upand^N^mathbin^txfonts^# \bindnasrepma (stmaryrd), TURNED AMPERSAND +02190^←^\leftarrow^\leftarrow^R^mathrel^^= \gets, a: leftward arrow +02191^↑^\uparrow^\uparrow^R^mathrel^^upward arrow +02192^→^\rightarrow^\rightarrow^R^mathrel^^= \to, = \tfun (oz), = \fun (oz), rightward arrow, z notation total function +02193^↓^\downarrow^\downarrow^R^mathrel^^downward arrow +02194^↔^\leftrightarrow^\leftrightarrow^R^mathrel^-wrisym^= \rel (oz), LEFT RIGHT ARROW, z notation relation +02195^↕^\updownarrow^\updownarrow^R^mathrel^^up and down arrow +02196^↖^\nwarrow^\nwarrow^R^mathrel^amssymb^nw pointing arrow +02197^↗^\nearrow^\nearrow^R^mathrel^^ne pointing arrow +02198^↘^\searrow^\searrow^R^mathrel^^se pointing arrow +02199^↙^\swarrow^\swarrow^R^mathrel^^sw pointing arrow +0219A^↚^\nleftarrow^\nleftarrow^R^mathrel^amssymb^not left arrow +0219B^↛^\nrightarrow^\nrightarrow^R^mathrel^amssymb^not right arrow +0219C^↜^^\leftwavearrow^R^mathrel^^left arrow-wavy +0219D^↝^^\rightwavearrow^R^mathrel^^right arrow-wavy +0219E^↞^\twoheadleftarrow^\twoheadleftarrow^R^mathrel^amssymb^left two-headed arrow +0219F^↟^^\twoheaduparrow^R^mathrel^^up two-headed arrow +021A0^↠^\twoheadrightarrow^\twoheadrightarrow^R^mathrel^amssymb^= \tsur (oz), = \surj (oz), right two-headed arrow, z notation total surjection +021A1^↡^^\twoheaddownarrow^R^mathrel^^down two-headed arrow +021A2^↢^\leftarrowtail^\leftarrowtail^R^mathrel^amssymb^left arrow-tailed +021A3^↣^\rightarrowtail^\rightarrowtail^R^mathrel^amssymb^= \tinj (oz), = \inj (oz), right arrow-tailed, z notation total injection +021A4^↤^\mapsfrom^\mapsfrom^R^mathrel^stmaryrd^= \mappedfrom (kpfonts), maps to, leftward +021A5^↥^\MapsUp^\mapsup^R^mathrel^wrisym^maps to, upward +021A6^↦^\mapsto^\mapsto^R^mathrel^^maps to, rightward, z notation maplet +021A7^↧^\MapsDown^\mapsdown^R^mathrel^wrisym^maps to, downward +021A8^↨^^\updownarrowbar^R^mathord^^UP DOWN ARROW WITH BASE (perpendicular) +021A9^↩^\hookleftarrow^\hookleftarrow^R^mathrel^^left arrow-hooked +021AA^↪^\hookrightarrow^\hookrightarrow^R^mathrel^^right arrow-hooked +021AB^↫^\looparrowleft^\looparrowleft^R^mathrel^amssymb^left arrow-looped +021AC^↬^\looparrowright^\looparrowright^R^mathrel^amssymb^right arrow-looped +021AD^↭^\leftrightsquigarrow^\leftrightsquigarrow^R^mathrel^amssymb^left and right arr-wavy +021AE^↮^\nleftrightarrow^\nleftrightarrow^R^mathrel^amssymb^not left and right arrow +021AF^↯^\lightning^\downzigzagarrow^R^mathrel^stmaryrd^t \Lightning (marvosym), DOWNWARDS ZIGZAG ARROW +021B0^↰^\Lsh^\Lsh^R^mathrel^amssymb^a: UPWARDS ARROW WITH TIP LEFTWARDS +021B1^↱^\Rsh^\Rsh^R^mathrel^amssymb^a: UPWARDS ARROW WITH TIP RIGHTWARDS +021B2^↲^\dlsh^\Ldsh^R^mathrel^mathabx^left down angled arrow +021B3^↳^\drsh^\Rdsh^R^mathrel^mathabx^right down angled arrow +021B4^↴^^\linefeed^^mathord^^RIGHTWARDS ARROW WITH CORNER DOWNWARDS +021B5^↵^^\carriagereturn^^mathord^^downwards arrow with corner leftward = carriage return +021B6^↶^\curvearrowleft^\curvearrowleft^R^mathrel^amssymb fourier^left curved arrow +021B7^↷^\curvearrowright^\curvearrowright^R^mathrel^amssymb fourier^right curved arrow +021B8^↸^^\barovernorthwestarrow^^mathord^^NORTH WEST ARROW TO LONG BAR +021B9^↹^^\barleftarrowrightarrowba^^mathord^^LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR +021BA^↺^\circlearrowleft^\acwopencirclearrow^R^mathord^amssymb^= \leftturn (wasysym), ANTICLOCKWISE OPEN CIRCLE ARROW +021BB^↻^\circlearrowright^\cwopencirclearrow^R^mathord^amssymb^= \rightturn (wasysym), CLOCKWISE OPEN CIRCLE ARROW +021BC^↼^\leftharpoonup^\leftharpoonup^R^mathrel^^left harpoon-up +021BD^↽^\leftharpoondown^\leftharpoondown^R^mathrel^^left harpoon-down +021BE^↾^\upharpoonright^\upharpoonright^R^mathrel^amssymb^= \restriction (amssymb), = \upharpoonrightup (wrisym), a: up harpoon-right +021BF^↿^\upharpoonleft^\upharpoonleft^R^mathrel^amssymb^= \upharpoonleftup (wrisym), up harpoon-left +021C0^⇀^\rightharpoonup^\rightharpoonup^R^mathrel^^right harpoon-up +021C1^⇁^\rightharpoondown^\rightharpoondown^R^mathrel^^right harpoon-down +021C2^⇂^\downharpoonright^\downharpoonright^R^mathrel^amssymb^= \upharpoonrightdown (wrisym), down harpoon-right +021C3^⇃^\downharpoonleft^\downharpoonleft^R^mathrel^amssymb^= \upharpoonleftdown (wrisym), down harpoon-left +021C4^⇄^\rightleftarrows^\rightleftarrows^R^mathrel^amssymb^= \rightleftarrow (wrisym), right arrow over left arrow +021C5^⇅^\updownarrows^\updownarrows^R^mathrel^mathabx^= \uparrowdownarrow (wrisym), up arrow, down arrow +021C6^⇆^\leftrightarrows^\leftrightarrows^R^mathrel^amssymb^= \leftrightarrow (wrisym), left arrow over right arrow +021C7^⇇^\leftleftarrows^\leftleftarrows^R^mathrel^amssymb fourier^two left arrows +021C8^⇈^\upuparrows^\upuparrows^R^mathrel^amssymb^two up arrows +021C9^⇉^\rightrightarrows^\rightrightarrows^R^mathrel^amssymb fourier^two right arrows +021CA^⇊^\downdownarrows^\downdownarrows^R^mathrel^amssymb^two down arrows +021CB^⇋^\leftrightharpoons^\leftrightharpoons^R^mathrel^amssymb^= \revequilibrium (wrisym), left harpoon over right +021CC^⇌^\rightleftharpoons^\rightleftharpoons^R^mathrel^^= \equilibrium (wrisym), right harpoon over left +021CD^⇍^\nLeftarrow^\nLeftarrow^R^mathrel^amssymb^not implied by +021CE^⇎^\nLeftrightarrow^\nLeftrightarrow^R^mathrel^amssymb^not left and right double arrows +021CF^⇏^\nRightarrow^\nRightarrow^R^mathrel^amssymb^not implies +021D0^⇐^\Leftarrow^\Leftarrow^R^mathrel^^left double arrow +021D1^⇑^\Uparrow^\Uparrow^R^mathrel^^up double arrow +021D2^⇒^\Rightarrow^\Rightarrow^R^mathrel^-marvosym^right double arrow +021D3^⇓^\Downarrow^\Downarrow^R^mathrel^^down double arrow +021D4^⇔^\Leftrightarrow^\Leftrightarrow^R^mathrel^^left and right double arrow +021D5^⇕^\Updownarrow^\Updownarrow^R^mathrel^^up and down double arrow +021D6^⇖^\Nwarrow^\Nwarrow^R^mathrel^txfonts^nw pointing double arrow +021D7^⇗^\Nearrow^\Nearrow^R^mathrel^txfonts^ne pointing double arrow +021D8^⇘^\Searrow^\Searrow^R^mathrel^txfonts^se pointing double arrow +021D9^⇙^\Swarrow^\Swarrow^R^mathrel^txfonts^sw pointing double arrow +021DA^⇚^\Lleftarrow^\Lleftarrow^R^mathrel^amssymb^left triple arrow +021DB^⇛^\Rrightarrow^\Rrightarrow^R^mathrel^amssymb^right triple arrow +021DC^⇜^\leftsquigarrow^\leftsquigarrow^R^mathrel^mathabx txfonts^LEFTWARDS SQUIGGLE ARROW +021DD^⇝^\rightsquigarrow^\rightsquigarrow^R^mathrel^amssymb^RIGHTWARDS SQUIGGLE ARROW +021DE^⇞^^\nHuparrow^R^mathord^^UPWARDS ARROW WITH DOUBLE STROKE +021DF^⇟^^\nHdownarrow^R^mathord^^DOWNWARDS ARROW WITH DOUBLE STROKE +021E0^⇠^\dashleftarrow^\leftdasharrow^R^mathord^amsfonts^LEFTWARDS DASHED ARROW +021E1^⇡^^\updasharrow^R^mathord^^UPWARDS DASHED ARROW +021E2^⇢^\dashrightarrow^\rightdasharrow^R^mathord^amsfonts^= \dasharrow (amsfonts), RIGHTWARDS DASHED ARROW +021E3^⇣^^\downdasharrow^R^mathord^^DOWNWARDS DASHED ARROW +021E4^⇤^\LeftArrowBar^\barleftarrow^R^mathrel^wrisym^LEFTWARDS ARROW TO BAR +021E5^⇥^\RightArrowBar^\rightarrowbar^R^mathrel^wrisym^RIGHTWARDS ARROW TO BAR +021E6^⇦^^\leftwhitearrow^R^mathord^^LEFTWARDS WHITE ARROW +021E7^⇧^^\upwhitearrow^R^mathord^^UPWARDS WHITE ARROW +021E8^⇨^^\rightwhitearrow^R^mathord^^RIGHTWARDS WHITE ARROW +021E9^⇩^^\downwhitearrow^R^mathord^^DOWNWARDS WHITE ARROW +021EA^⇪^^\whitearrowupfrombar^^mathord^^UPWARDS WHITE ARROW FROM BAR +021EB^⇫^^^^mathord^^UPWARDS WHITE ARROW ON PEDESTAL +021EC^⇬^^^^mathord^^UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR +021ED^⇭^^^^mathord^^UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR +021EE^⇮^^^^mathord^^UPWARDS WHITE DOUBLE ARROW +021EF^⇯^^^^mathord^^UPWARDS WHITE DOUBLE ARROW ON PEDESTAL +021F0^⇰^^^^mathord^^RIGHTWARDS WHITE ARROW FROM WALL +021F1^⇱^^^^mathord^^NORTH WEST ARROW TO CORNER +021F2^⇲^^^^mathord^^SOUTH EAST ARROW TO CORNER +021F3^⇳^^^^mathord^^UP DOWN WHITE ARROW +021F4^⇴^^\circleonrightarrow^R^mathrel^^RIGHT ARROW WITH SMALL CIRCLE +021F5^⇵^\downuparrows^\downuparrows^R^mathrel^mathabx^= \downarrowuparrow (wrisym), DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW +021F6^⇶^^\rightthreearrows^R^mathrel^^THREE RIGHTWARDS ARROWS +021F7^⇷^^\nvleftarrow^R^mathrel^^LEFTWARDS ARROW WITH VERTICAL STROKE +021F8^⇸^\pfun^\nvrightarrow^R^mathrel^oz^RIGHTWARDS ARROW WITH VERTICAL STROKE, z notation partial function +021F9^⇹^^\nvleftrightarrow^R^mathrel^^LEFT RIGHT ARROW WITH VERTICAL STROKE, z notation partial relation +021FA^⇺^^\nVleftarrow^R^mathrel^^LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE +021FB^⇻^\ffun^\nVrightarrow^R^mathrel^oz^RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE, z notation finite function +021FC^⇼^^\nVleftrightarrow^R^mathrel^^LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE, z notation finite relation +021FD^⇽^\leftarrowtriangle^\leftarrowtriangle^R^mathrel^stmaryrd^LEFTWARDS OPEN-HEADED ARROW +021FE^⇾^\rightarrowtriangle^\rightarrowtriangle^R^mathrel^stmaryrd^RIGHTWARDS OPEN-HEADED ARROW +021FF^⇿^\leftrightarrowtriangle^\leftrightarrowtriangle^R^mathrel^stmaryrd^LEFT RIGHT OPEN-HEADED ARROW +02200^∀^\forall^\forall^U^mathord^^FOR ALL +02201^∁^\complement^\complement^U^mathord^amssymb fourier^COMPLEMENT sign +02202^∂^\partial^\partial^N^mathord^-literal^= \partialup (kpfonts), PARTIAL DIFFERENTIAL +02203^∃^\exists^\exists^U^mathord^^= \exi (oz), at least one exists +02204^∄^\nexists^\nexists^U^mathord^amssymb fourier^= \nexi (oz), negated exists +02205^∅^\varnothing^\varnothing^N^mathord^amssymb^circle, slash +02206^∆^^\increment^U^mathord^^# \mathrm{\Delta}, laplacian (Delta; nabla square) +02207^∇^\nabla^\nabla^U^mathord^^NABLA, del, hamilton operator +02208^∈^\in^\in^R^mathrel^^set membership, variant +02209^∉^\notin^\notin^R^mathrel^^= \nin (wrisym), negated set membership +0220A^∊^^\smallin^R^mathrel^^set membership (small set membership) +0220B^∋^\ni^\ni^R^mathrel^^= \owns, contains, variant +0220C^∌^\nni^\nni^R^mathrel^wrisym^= \notni (txfonts), = \notowner (mathabx), = \notowns (fourier), negated contains, variant +0220D^∍^^\smallni^R^mathrel^^r: contains (SMALL CONTAINS AS MEMBER) +0220E^∎^^\QED^N^mathord^^# \blacksquare (amssymb), END OF PROOF +0220F^∏^\prod^\prod^L^mathop^^product operator +02210^∐^\coprod^\coprod^L^mathop^^coproduct operator +02211^∑^\sum^\sum^L^mathop^^summation operator +02212^−^-^\minus^V^mathbin^^MINUS SIGN +02213^∓^\mp^\mp^V^mathbin^^MINUS-OR-PLUS SIGN +02214^∔^\dotplus^\dotplus^B^mathbin^amssymb^plus sign, dot above +02215^∕^\slash^\divslash^B^mathbin^^DIVISION SLASH +02216^∖^\smallsetminus^\smallsetminus^B^mathbin^amssymb fourier^small SET MINUS (cf. reverse solidus) +02217^∗^\ast^\ast^B^mathbin^^ASTERISK OPERATOR (Hodge star operator) +02218^∘^\circ^\vysmwhtcircle^B^mathbin^^composite function (small circle) +02219^∙^\bullet^\vysmblkcircle^B^mathbin^^BULLET OPERATOR +0221A^√^\sqrt^\sqrt^L^mathradical^^radical +0221B^∛^\sqrt[3]^\cuberoot^L^mathradical^^CUBE ROOT +0221C^∜^\sqrt[4]^\fourthroot^L^mathradical^^FOURTH ROOT +0221D^∝^\propto^\propto^R^mathrel^^# \varpropto (amssymb), is PROPORTIONAL TO +0221E^∞^\infty^\infty^N^mathord^^INFINITY +0221F^∟^\rightangle^\rightangle^N^mathord^wrisym^right (90 degree) angle +02220^∠^\angle^\angle^N^mathord^^ANGLE +02221^∡^\measuredangle^\measuredangle^N^mathord^amssymb wrisym^MEASURED ANGLE +02222^∢^\sphericalangle^\sphericalangle^N^mathord^amssymb wrisym^SPHERICAL ANGLE +02223^∣^\mid^\mid^R^mathrel^^r: DIVIDES +02224^∤^\nmid^\nmid^R^mathrel^amssymb^negated mid, DOES NOT DIVIDE +02225^∥^\parallel^\parallel^R^mathrel^^parallel +02226^∦^\nparallel^\nparallel^R^mathrel^amssymb fourier^not parallel +02227^∧^\wedge^\wedge^B^mathbin^amssymb^= \land, b: LOGICAL AND +02228^∨^\vee^\vee^B^mathbin^^= \lor, b: LOGICAL OR +02229^∩^\cap^\cap^B^mathbin^^INTERSECTION +0222A^∪^\cup^\cup^B^mathbin^^UNION or logical sum +0222B^∫^\int^\int^L^mathop^^INTEGRAL operator +0222C^∬^\iint^\iint^L^mathop^amsmath fourier esint wasysym^DOUBLE INTEGRAL operator +0222D^∭^\iiint^\iiint^L^mathop^amsmath fourier esint wasysym^TRIPLE INTEGRAL operator +0222E^∮^\oint^\oint^L^mathop^^CONTOUR INTEGRAL operator +0222F^∯^\oiint^\oiint^L^mathop^esint wasysym fourier^= \dbloint (wrisym), double contour integral operator +02230^∰^\oiiint^\oiiint^L^mathop^txfonts fourier^triple contour integral operator +02231^∱^^\intclockwise^L^mathop^^CLOCKWISE INTEGRAL +02232^∲^\varointclockwise^\varointclockwise^L^mathop^esint^= \clockoint (wrisym), contour integral, clockwise +02233^∳^\ointctrclockwise^\ointctrclockwise^L^mathop^esint^= \cntclockoint (wrisym), contour integral, anticlockwise +02234^∴^\therefore^\therefore^R^mathord^amssymb wrisym^= \wasytherefore (wasysym), THEREFORE +02235^∵^\because^\because^R^mathord^amssymb wrisym^BECAUSE +02236^∶^:^\mathratio^R^mathrel^^x \colon, RATIO +02237^∷^\Proportion^\Colon^R^mathrel^wrisym^# ::, two colons +02238^∸^^\dotminus^B^mathbin^^minus sign, dot above +02239^∹^\eqcolon^\dashcolon^R^mathrel^txfonts -mathabx^# -: ,EXCESS +0223A^∺^^\dotsminusdots^R^mathrel^^minus with four dots, GEOMETRIC PROPORTION +0223B^∻^^\kernelcontraction^R^mathrel^^HOMOTHETIC +0223C^∼^\sim^\sim^R^mathrel^^similar to, TILDE OPERATOR +0223D^∽^\backsim^\backsim^R^mathrel^amssymb^reverse similar +0223E^∾^^\invlazys^B^mathbin^^most positive, INVERTED LAZY S +0223F^∿^\AC^\sinewave^N^mathord^wasysym^SINE WAVE, alternating current +02240^≀^\wr^\wr^B^mathbin^amssymb^WREATH PRODUCT +02241^≁^\nsim^\nsim^R^mathrel^amssymb wrisym^not similar +02242^≂^\eqsim^\eqsim^R^mathrel^amssymb^equals, similar +02243^≃^\simeq^\simeq^R^mathrel^^similar, equals +02244^≄^\nsimeq^\nsime^R^mathrel^txfonts^not similar, equals +02245^≅^\cong^\cong^R^mathrel^^congruent with +02246^≆^^\simneqq^R^mathrel^^similar, not equals [vert only for 9573 entity] +02247^≇^\ncong^\ncong^R^mathrel^amssymb wrisym^not congruent with +02248^≈^\approx^\approx^R^mathrel^^approximate +02249^≉^\napprox^\napprox^R^mathrel^wrisym^not approximate +0224A^≊^\approxeq^\approxeq^R^mathrel^amssymb^approximate, equals +0224B^≋^^\approxident^R^mathrel^^approximately identical to +0224C^≌^^\backcong^R^mathrel^^ALL EQUAL TO +0224D^≍^\asymp^\asymp^R^mathrel^^asymptotically equal to +0224E^≎^\Bumpeq^\Bumpeq^R^mathrel^amssymb wrisym^bumpy equals +0224F^≏^\bumpeq^\bumpeq^R^mathrel^amssymb wrisym^bumpy equals, equals +02250^≐^\doteq^\doteq^R^mathrel^^= \dotequal (wrisym), equals, single dot above +02251^≑^\Doteq^\Doteq^R^mathrel^amssymb^= \doteqdot (amssymb), /doteq r: equals, even dots +02252^≒^\fallingdotseq^\fallingdotseq^R^mathrel^amssymb^equals, falling dots +02253^≓^\risingdotseq^\risingdotseq^R^mathrel^amssymb^equals, rising dots +02254^≔^\coloneq^\coloneq^R^mathrel^mathabx -txfonts^= \coloneqq (txfonts), = \SetDelayed (wrisym), # := colon, equals +02255^≕^\eqcolon^\eqcolon^R^mathrel^mathabx -txfonts^= \eqqcolon (txfonts), # =:, equals, colon +02256^≖^\eqcirc^\eqcirc^R^mathrel^amssymb^circle on equals sign +02257^≗^\circeq^\circeq^R^mathrel^amssymb^circle, equals +02258^≘^^\arceq^R^mathrel^^arc, equals; CORRESPONDS TO +02259^≙^\corresponds^\wedgeq^R^mathrel^mathabx^= \sdef (oz), t \Corresponds (marvosym), corresponds to (wedge over equals) +0225A^≚^^\veeeq^R^mathrel^^logical or, equals +0225B^≛^^\stareq^R^mathrel^^STAR EQUALS +0225C^≜^\triangleq^\triangleq^R^mathrel^amssymb^= \varsdef (oz), triangle, equals +0225D^≝^^\eqdef^R^mathrel^^equals by definition +0225E^≞^^\measeq^R^mathrel^^MEASURED BY (m over equals) +0225F^≟^^\questeq^R^mathrel^^equal with questionmark +02260^≠^\neq^\ne^R^mathrel^^= \ne, r: not equal +02261^≡^\equiv^\equiv^R^mathrel^^identical with +02262^≢^\nequiv^\nequiv^R^mathrel^wrisym^not identical with +02263^≣^^\Equiv^R^mathrel^^strict equivalence (4 lines) +02264^≤^\leq^\leq^R^mathrel^^= \le, r: less-than-or-equal +02265^≥^\geq^\geq^R^mathrel^^= \ge, r: greater-than-or-equal +02266^≦^\leqq^\leqq^R^mathrel^amssymb^less, double equals +02267^≧^\geqq^\geqq^R^mathrel^amssymb^greater, double equals +02268^≨^\lneqq^\lneqq^R^mathrel^amssymb^less, not double equals +02269^≩^\gneqq^\gneqq^R^mathrel^amssymb^greater, not double equals +0226A^≪^\ll^\ll^R^mathrel^^much less than, type 2 +0226B^≫^\gg^\gg^R^mathrel^^much greater than, type 2 +0226C^≬^\between^\between^R^mathrel^amssymb^BETWEEN +0226D^≭^\notasymp^\nasymp^R^mathrel^mathabx^= \nasymp (wrisym), not asymptotically equal to +0226E^≮^\nless^\nless^R^mathrel^amssymb^NOT LESS-THAN +0226F^≯^\ngtr^\ngtr^R^mathrel^amssymb^NOT GREATER-THAN +02270^≰^\nleq^\nleq^R^mathrel^amssymb wrisym^= \nleqslant (fourier), not less-than-or-equal +02271^≱^\ngeq^\ngeq^R^mathrel^amssymb wrisym^= \ngeqslant (fourier), not greater-than-or-equal +02272^≲^\lesssim^\lesssim^R^mathrel^amssymb^= \apprle (wasysym), = \LessTilde (wrisym), less, similar +02273^≳^\gtrsim^\gtrsim^R^mathrel^amssymb^= \apprge (wasysym), = \GreaterTilde (wrisym), greater, similar +02274^≴^\NotLessTilde^\nlesssim^R^mathrel^wrisym^not less, similar +02275^≵^\NotGreaterTilde^\ngtrsim^R^mathrel^wrisym^not greater, similar +02276^≶^\lessgtr^\lessgtr^R^mathrel^amssymb^less, greater +02277^≷^\gtrless^\gtrless^R^mathrel^amssymb^= \GreaterLess (wrisym), greater, less +02278^≸^^\nlessgtr^R^mathrel^wrisym^not less, greater +02279^≹^\NotGreaterLess^\ngtrless^R^mathrel^wrisym^not greater, less +0227A^≺^\prec^\prec^R^mathrel^^PRECEDES +0227B^≻^\succ^\succ^R^mathrel^^SUCCEEDS +0227C^≼^\preccurlyeq^\preccurlyeq^R^mathrel^amssymb^= \PrecedesSlantEqual (wrisym), precedes, curly equals +0227D^≽^\succcurlyeq^\succcurlyeq^R^mathrel^amssymb^= \SucceedsSlantEqual (wrisym), succeeds, curly equals +0227E^≾^\precsim^\precsim^R^mathrel^amssymb^= \PrecedesTilde (wrisym), precedes, similar +0227F^≿^\succsim^\succsim^R^mathrel^amssymb^= \SucceedsTilde (wrisym), succeeds, similar +02280^⊀^\nprec^\nprec^R^mathrel^amssymb wrisym^not precedes +02281^⊁^\nsucc^\nsucc^R^mathrel^amssymb wrisym^not succeeds +02282^⊂^\subset^\subset^R^mathrel^^subset or is implied by +02283^⊃^\supset^\supset^R^mathrel^^superset or implies +02284^⊄^\nsubset^\nsubset^R^mathrel^wrisym^not subset, variant [slash negation] +02285^⊅^\nsupset^\nsupset^R^mathrel^wrisym^not superset, variant [slash negation] +02286^⊆^\subseteq^\subseteq^R^mathrel^^subset, equals +02287^⊇^\supseteq^\supseteq^R^mathrel^^superset, equals +02288^⊈^\nsubseteq^\nsubseteq^R^mathrel^amssymb wrisym^not subset, equals +02289^⊉^\nsupseteq^\nsupseteq^R^mathrel^amssymb wrisym^not superset, equals +0228A^⊊^\subsetneq^\subsetneq^R^mathrel^amssymb^= \varsubsetneq (fourier), subset, not equals +0228B^⊋^\supsetneq^\supsetneq^R^mathrel^amssymb^superset, not equals +0228C^⊌^^\cupleftarrow^B^mathbin^^MULTISET +0228D^⊍^^\cupdot^B^mathbin^^union, with dot +0228E^⊎^\uplus^\uplus^B^mathbin^^= \buni (oz), plus sign in union +0228F^⊏^\sqsubset^\sqsubset^R^mathrel^amsfonts^square subset +02290^⊐^\sqsupset^\sqsupset^R^mathrel^amsfonts^square superset +02291^⊑^\sqsubseteq^\sqsubseteq^R^mathrel^^square subset, equals +02292^⊒^\sqsupseteq^\sqsupseteq^R^mathrel^^square superset, equals +02293^⊓^\sqcap^\sqcap^B^mathbin^^square intersection +02294^⊔^\sqcup^\sqcup^B^mathbin^^square union +02295^⊕^\oplus^\oplus^B^mathbin^^plus sign in circle +02296^⊖^\ominus^\ominus^B^mathbin^^minus sign in circle +02297^⊗^\otimes^\otimes^B^mathbin^^multiply sign in circle +02298^⊘^\oslash^\oslash^B^mathbin^^solidus in circle +02299^⊙^\odot^\odot^B^mathbin^^middle dot in circle +0229A^⊚^\circledcirc^\circledcirc^B^mathbin^amssymb^small circle in circle +0229B^⊛^\circledast^\circledast^B^mathbin^amssymb^asterisk in circle +0229C^⊜^^\circledequal^B^mathbin^^equal in circle +0229D^⊝^\circleddash^\circleddash^B^mathbin^amssymb^hyphen in circle +0229E^⊞^\boxplus^\boxplus^B^mathbin^amssymb^plus sign in box +0229F^⊟^\boxminus^\boxminus^B^mathbin^amssymb^minus sign in box +022A0^⊠^\boxtimes^\boxtimes^B^mathbin^amssymb^multiply sign in box +022A1^⊡^\boxdot^\boxdot^B^mathbin^amssymb stmaryrd^/dotsquare /boxdot b: small dot in box +022A2^⊢^\vdash^\vdash^R^mathrel^^RIGHT TACK, proves, implies, yields, (vertical, dash) +022A3^⊣^\dashv^\dashv^R^mathrel^amssymb^LEFT TACK, non-theorem, does not yield, (dash, vertical) +022A4^⊤^\top^\top^N^mathord^^DOWN TACK, top +022A5^⊥^\bot^\bot^R^mathord^^UP TACK, bottom +022A6^⊦^^\assert^R^mathrel^^# \vdash, ASSERTION (vertical, short dash) +022A7^⊧^\models^\models^R^mathrel^^MODELS (vertical, short double dash) +022A8^⊨^\vDash^\vDash^R^mathrel^amssymb fourier^TRUE (vertical, double dash) +022A9^⊩^\Vdash^\Vdash^R^mathrel^amssymb^double vertical, dash +022AA^⊪^\Vvdash^\Vvdash^R^mathrel^amssymb^triple vertical, dash +022AB^⊫^\VDash^\VDash^R^mathrel^mathabx txfonts^double vert, double dash +022AC^⊬^\nvdash^\nvdash^R^mathrel^amssymb^not vertical, dash +022AD^⊭^\nvDash^\nvDash^R^mathrel^amssymb fourier^not vertical, double dash +022AE^⊮^\nVdash^\nVdash^R^mathrel^amssymb^not double vertical, dash +022AF^⊯^\nVDash^\nVDash^R^mathrel^amssymb^not double vert, double dash +022B0^⊰^^\prurel^R^mathrel^^element PRECEDES UNDER RELATION +022B1^⊱^^\scurel^R^mathrel^^SUCCEEDS UNDER RELATION +022B2^⊲^\vartriangleleft^\vartriangleleft^R^mathrel^amssymb^left triangle, open, variant +022B3^⊳^\vartriangleright^\vartriangleright^R^mathrel^amssymb^right triangle, open, variant +022B4^⊴^\trianglelefteq^\trianglelefteq^R^mathrel^amssymb^= \unlhd (wrisym), left triangle, equals +022B5^⊵^\trianglerighteq^\trianglerighteq^R^mathrel^amssymb^= \unrhd (wrisym), right triangle, equals +022B6^⊶^\multimapdotbothA^\origof^R^mathrel^txfonts^ORIGINAL OF +022B7^⊷^\multimapdotbothB^\imageof^R^mathrel^txfonts^IMAGE OF +022B8^⊸^\multimap^\multimap^R^mathrel^amssymb^/MULTIMAP a: +022B9^⊹^^\hermitmatrix^B^mathord^^HERMITIAN CONJUGATE MATRIX +022BA^⊺^\intercal^\intercal^B^mathbin^amssymb fourier^intercal +022BB^⊻^\veebar^\veebar^B^mathbin^amssymb^logical or, bar below (large vee); exclusive disjunction +022BC^⊼^\barwedge^\barwedge^B^mathbin^amssymb^logical NAND (bar over wedge) +022BD^⊽^^\barvee^B^mathbin^^bar, vee (large vee) +022BE^⊾^^\measuredrightangle^N^mathord^^right angle-measured [with arc] +022BF^⊿^^\varlrtriangle^N^mathord^^RIGHT TRIANGLE +022C0^⋀^\bigwedge^\bigwedge^L^mathop^^logical or operator +022C1^⋁^\bigvee^\bigvee^L^mathop^^logical and operator +022C2^⋂^\bigcap^\bigcap^L^mathop^^= \dint (oz), \dinter (oz), intersection operator +022C3^⋃^\bigcup^\bigcup^L^mathop^^= \duni (oz), \dunion (oz), union operator +022C4^⋄^\diamond^\smwhtdiamond^B^mathbin^^DIAMOND OPERATOR (white diamond) +022C5^⋅^\cdot^\cdot^B^mathbin^^DOT OPERATOR (small middle dot) +022C6^⋆^\star^\star^B^mathbin^^small star, filled, low +022C7^⋇^\divideontimes^\divideontimes^B^mathbin^amssymb^division on times +022C8^⋈^\bowtie^\bowtie^R^mathrel^^= \lrtimes (txfonts), BOWTIE +022C9^⋉^\ltimes^\ltimes^B^mathbin^amssymb^times sign, left closed +022CA^⋊^\rtimes^\rtimes^B^mathbin^amssymb^times sign, right closed +022CB^⋋^\leftthreetimes^\leftthreetimes^B^mathbin^amssymb^LEFT SEMIDIRECT PRODUCT +022CC^⋌^\rightthreetimes^\rightthreetimes^B^mathbin^amssymb^RIGHT SEMIDIRECT PRODUCT +022CD^⋍^\backsimeq^\backsimeq^R^mathrel^amssymb^reverse similar, equals +022CE^⋎^\curlyvee^\curlyvee^B^mathbin^amssymb^CURLY LOGICAL OR +022CF^⋏^\curlywedge^\curlywedge^B^mathbin^amssymb^CURLY LOGICAL AND +022D0^⋐^\Subset^\Subset^R^mathrel^amssymb^DOUBLE SUBSET +022D1^⋑^\Supset^\Supset^R^mathrel^amssymb^DOUBLE SUPERSET +022D2^⋒^\Cap^\Cap^B^mathbin^amssymb^/cap /doublecap b: DOUBLE INTERSECTION +022D3^⋓^\Cup^\Cup^B^mathbin^amssymb^/cup /doublecup b: DOUBLE UNION +022D4^⋔^\pitchfork^\pitchfork^R^mathrel^amssymb^PITCHFORK +022D5^⋕^\hash^\equalparallel^R^mathrel^mathabx^parallel, equal; equal or parallel +022D6^⋖^\lessdot^\lessdot^R^mathrel^amssymb^less than, with dot +022D7^⋗^\gtrdot^\gtrdot^R^mathrel^amssymb^greater than, with dot +022D8^⋘^\lll^\lll^R^mathrel^amssymb -mathabx^triple less-than +022D9^⋙^\ggg^\ggg^R^mathrel^amssymb -mathabx^triple greater-than +022DA^⋚^\lesseqgtr^\lesseqgtr^R^mathrel^amssymb^less, equals, greater +022DB^⋛^\gtreqless^\gtreqless^R^mathrel^amssymb^greater, equals, less +022DC^⋜^^\eqless^R^mathrel^^equal-or-less +022DD^⋝^^\eqgtr^R^mathrel^^equal-or-greater +022DE^⋞^\curlyeqprec^\curlyeqprec^R^mathrel^amssymb^curly equals, precedes +022DF^⋟^\curlyeqsucc^\curlyeqsucc^R^mathrel^amssymb^curly equals, succeeds +022E0^⋠^\npreceq^\npreccurlyeq^R^mathrel^amssymb wrisym^DOES NOT PRECEDE OR EQUAL +022E1^⋡^\nsucceq^\nsucccurlyeq^R^mathrel^amssymb wrisym^not succeeds, curly equals +022E2^⋢^\nsqsubseteq^\nsqsubseteq^R^mathrel^wrisym^not, square subset, equals +022E3^⋣^\nsqsupseteq^\nsqsupseteq^R^mathrel^wrisym^not, square superset, equals +022E4^⋤^^\sqsubsetneq^R^mathrel^^square subset, not equals +022E5^⋥^^\sqsupsetneq^R^mathrel^^square superset, not equals +022E6^⋦^\lnsim^\lnsim^R^mathrel^amssymb^less, not similar +022E7^⋧^\gnsim^\gnsim^R^mathrel^amssymb^greater, not similar +022E8^⋨^\precnsim^\precnsim^R^mathrel^amssymb^precedes, not similar +022E9^⋩^\succnsim^\succnsim^R^mathrel^amssymb^succeeds, not similar +022EA^⋪^\ntriangleleft^\ntriangleleft^R^mathrel^amssymb^= \NotLeftTriangle (wrisym), not left triangle +022EB^⋫^\ntriangleright^\ntriangleright^R^mathrel^amssymb^= \NotRightTriangle (wrisym), not right triangle +022EC^⋬^\ntrianglelefteq^\ntrianglelefteq^R^mathrel^amssymb^= \nunlhd (wrisym), not left triangle, equals +022ED^⋭^\ntrianglerighteq^\ntrianglerighteq^R^mathrel^amssymb^= \nunrhd (wrisym), not right triangle, equals +022EE^⋮^\vdots^\vdots^R^mathrel^^VERTICAL ELLIPSIS +022EF^⋯^\cdots^\unicodecdots^R^mathord^^three dots, centered +022F0^⋰^\iddots^\adots^R^mathrel^mathdots^= \adots (yhmath), three dots, ascending +022F1^⋱^\ddots^\ddots^R^mathrel^^three dots, descending +022F2^⋲^^\disin^R^mathrel^^ELEMENT OF WITH LONG HORIZONTAL STROKE +022F3^⋳^^\varisins^R^mathrel^^ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE +022F4^⋴^^\isins^R^mathrel^^SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE +022F5^⋵^^\isindot^R^mathrel^^ELEMENT OF WITH DOT ABOVE +022F6^⋶^\barin^\varisinobar^R^mathrel^mathabx^ELEMENT OF WITH OVERBAR +022F7^⋷^^\isinobar^R^mathrel^^SMALL ELEMENT OF WITH OVERBAR +022F8^⋸^^\isinvb^R^mathrel^^ELEMENT OF WITH UNDERBAR +022F9^⋹^^\isinE^R^mathrel^^ELEMENT OF WITH TWO HORIZONTAL STROKES +022FA^⋺^^\nisd^R^mathrel^^CONTAINS WITH LONG HORIZONTAL STROKE +022FB^⋻^^\varnis^R^mathrel^^CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE +022FC^⋼^^\nis^R^mathrel^^SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE +022FD^⋽^^\varniobar^R^mathrel^^CONTAINS WITH OVERBAR +022FE^⋾^^\niobar^R^mathrel^^SMALL CONTAINS WITH OVERBAR +022FF^⋿^^\bagmember^R^mathrel^^# \mathsf{E}, Z NOTATION BAG MEMBERSHIP +02300^⌀^\diameter^\diameter^N^mathord^mathabx^# \varnothing (amssymb), DIAMETER SIGN +02302^⌂^^\house^N^mathord^^HOUSE +02305^⌅^^\varbarwedge^B^mathbin^^# \barwedge (amssymb), PROJECTIVE (bar over small wedge) not nand +02306^⌆^^\vardoublebarwedge^B^mathbin^^# \doublebarwedge (amssymb), PERSPECTIVE (double bar over small wedge) +02308^⌈^\lceil^\lceil^O^mathopen^^LEFT CEILING +02309^⌉^\rceil^\rceil^C^mathclose^^RIGHT CEILING +0230A^⌊^\lfloor^\lfloor^O^mathopen^^LEFT FLOOR +0230B^⌋^\rfloor^\rfloor^C^mathclose^^RIGHT FLOOR +02310^⌐^\invneg^\invnot^N^mathord^wasysym^reverse not +02311^⌑^\wasylozenge^\sqlozenge^N^mathord^wasysym^SQUARE LOZENGE +02312^⌒^^\profline^^mathord^^profile of a line +02313^⌓^^\profsurf^^mathord^^profile of a surface +02317^⌗^^\viewdata^^mathord^^VIEWDATA SQUARE +02319^⌙^^\turnednot^N^mathord^^TURNED NOT SIGN +0231C^⌜^\ulcorner^\ulcorner^O^mathopen^amsfonts^upper left corner +0231D^⌝^\urcorner^\urcorner^C^mathclose^amsfonts^upper right corner +0231E^⌞^\llcorner^\llcorner^O^mathopen^amsfonts^lower left corner +0231F^⌟^\lrcorner^\lrcorner^C^mathclose^amsfonts^lower right corner +02320^⌠^^\inttop^G^mathord^^TOP HALF INTEGRAL +02321^⌡^^\intbottom^G^mathord^^BOTTOM HALF INTEGRAL +02322^⌢^\frown^\frown^R^mathrel^^# \smallFROWN, down curve +02323^⌣^\smile^\smile^R^mathrel^^# \smallSMILE, up curve +0232C^⌬^^\varhexagonlrbonds^^mathord^^six carbon ring, corner down, double bonds lower right etc +02332^⌲^^\conictaper^^mathord^^CONICAL TAPER +02336^⌶^^\topbot^N^mathord^^APL FUNCTIONAL SYMBOL I-BEAM, top and bottom +02337^⌷^^^^mathord^^APL FUNCTIONAL SYMBOL SQUISH QUAD +02338^⌸^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD EQUAL +02339^⌹^\APLinv^^^mathord^wasysym^APL FUNCTIONAL SYMBOL QUAD DIVIDE +0233A^⌺^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD DIAMOND +0233B^⌻^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD JOT +0233C^⌼^^^^mathord^^# \APLcirc{\APLbox} (wasysym), APL FUNCTIONAL SYMBOL QUAD CIRCLE +0233D^⌽^^\obar^B^mathbin^^# \APLvert{\Circle} (wasysym), x \obar (stmaryrd), APL FUNCTIONAL SYMBOL CIRCLE STILE, circle with vertical bar +0233E^⌾^^^^mathord^^# \APLcirc{\Circle} (wasysym), APL FUNCTIONAL SYMBOL CIRCLE JOT +0233F^⌿^\notslash^\APLnotslash^R^mathrel^wasysym^APL FUNCTIONAL SYMBOL SLASH BAR, solidus, bar through +02340^⍀^\notbackslash^\APLnotbackslash^^mathord^wasysym^APL FUNCTIONAL SYMBOL BACKSLASH BAR +02341^⍁^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD SLASH +02342^⍂^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD BACKSLASH +02343^⍃^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD LESS-THAN +02344^⍄^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD GREATER-THAN +02345^⍅^^^^mathord^^APL FUNCTIONAL SYMBOL LEFTWARDS VANE +02346^⍆^^^^mathord^^APL FUNCTIONAL SYMBOL RIGHTWARDS VANE +02347^⍇^\APLleftarrowbox^^^mathord^wasysym^APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW +02348^⍈^\APLrightarrowbox^^^mathord^wasysym^APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW +02349^⍉^^^^mathord^^APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH +0234A^⍊^^^^mathord^^APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR +0234B^⍋^^^^mathord^^# \APLvert{\APLup} (wasysym), APL FUNCTIONAL SYMBOL DELTA STILE +0234C^⍌^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD DOWN CARET +0234D^⍍^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD DELTA +0234E^⍎^^^^mathord^^APL FUNCTIONAL SYMBOL DOWN TACK JOT +0234F^⍏^^^^mathord^^APL FUNCTIONAL SYMBOL UPWARDS VANE +02350^⍐^\APLuparrowbox^^^mathord^wasysym^APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW +02351^⍑^^^^mathord^^APL FUNCTIONAL SYMBOL UP TACK OVERBAR +02352^⍒^^^^mathord^wasysym^# \APLvert{\APLdown} (wasysym), APL FUNCTIONAL SYMBOL DEL STILE +02353^⍓^^\APLboxupcaret^^mathord^^APL FUNCTIONAL SYMBOL QUAD UP CARET +02354^⍔^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD DEL +02355^⍕^^^^mathord^^APL FUNCTIONAL SYMBOL UP TACK JOT +02356^⍖^^^^mathord^^APL FUNCTIONAL SYMBOL DOWNWARDS VANE +02357^⍗^\APLdownarrowbox^^^mathord^wasysym^APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW +02358^⍘^^^^mathord^^APL FUNCTIONAL SYMBOL QUOTE UNDERBAR +02359^⍙^^^^mathord^^APL FUNCTIONAL SYMBOL DELTA UNDERBAR +0235A^⍚^^^^mathord^^APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR +0235B^⍛^^^^mathord^^APL FUNCTIONAL SYMBOL JOT UNDERBAR +0235C^⍜^^^^mathord^^APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR +0235D^⍝^\APLcomment^^^mathord^wasysym^APL FUNCTIONAL SYMBOL UP SHOE JOT +0235E^⍞^\APLinput^^^mathord^wasysym^APL FUNCTIONAL SYMBOL QUOTE QUAD +0235F^⍟^\APLlog^^^mathord^wasysym^APL FUNCTIONAL SYMBOL CIRCLE STAR +02360^⍠^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD COLON +02361^⍡^^^^mathord^^APL FUNCTIONAL SYMBOL UP TACK DIAERESIS +02362^⍢^^^^mathord^^APL FUNCTIONAL SYMBOL DEL DIAERESIS +02363^⍣^^^^mathord^^APL FUNCTIONAL SYMBOL STAR DIAERESIS +02364^⍤^^^^mathord^^APL FUNCTIONAL SYMBOL JOT DIAERESIS +02365^⍥^^^^mathord^^APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS +02366^⍦^^^^mathord^^APL FUNCTIONAL SYMBOL DOWN SHOE STILE +02367^⍧^^^^mathord^^APL FUNCTIONAL SYMBOL LEFT SHOE STILE +02368^⍨^^^^mathord^^APL FUNCTIONAL SYMBOL TILDE DIAERESIS +02369^⍩^^^^mathord^^APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS +0236A^⍪^^^^mathord^^APL FUNCTIONAL SYMBOL COMMA BAR +0236B^⍫^^^^mathord^^# \APLnot{\APLdown} (wasysym), APL FUNCTIONAL SYMBOL DEL TILDE +0236C^⍬^^^^mathord^^APL FUNCTIONAL SYMBOL ZILDE +0236D^⍭^^^^mathord^^APL FUNCTIONAL SYMBOL STILE TILDE +0236E^⍮^^^^mathord^^APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR +0236F^⍯^^^^mathord^^APL FUNCTIONAL SYMBOL QUAD NOT EQUAL +02370^⍰^^\APLboxquestion^^mathord^^APL FUNCTIONAL SYMBOL QUAD QUESTION +02371^⍱^^^^mathord^^APL FUNCTIONAL SYMBOL DOWN CARET TILDE +02372^⍲^^^^mathord^^APL FUNCTIONAL SYMBOL UP CARET TILDE +02373^⍳^^^^mathord^^APL FUNCTIONAL SYMBOL IOTA +02374^⍴^^^^mathord^^APL FUNCTIONAL SYMBOL RHO +02375^⍵^^^^mathord^^APL FUNCTIONAL SYMBOL OMEGA +02376^⍶^^^^mathord^^APL FUNCTIONAL SYMBOL ALPHA UNDERBAR +02377^⍷^^^^mathord^^APL FUNCTIONAL SYMBOL EPSILON UNDERBAR +02378^⍸^^^^mathord^^APL FUNCTIONAL SYMBOL IOTA UNDERBAR +02379^⍹^^^^mathord^^APL FUNCTIONAL SYMBOL OMEGA UNDERBAR +0237C^⍼^^\rangledownzigzagarrow^^mathord^^RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW +02394^⎔^^\hexagon^N^mathord^^horizontal benzene ring [hexagon flat open] +0239B^⎛^^\lparenuend^G^mathord^^LEFT PARENTHESIS UPPER HOOK +0239C^⎜^^\lparenextender^G^mathord^^LEFT PARENTHESIS EXTENSION +0239D^⎝^^\lparenlend^G^mathord^^LEFT PARENTHESIS LOWER HOOK +0239E^⎞^^\rparenuend^G^mathord^^RIGHT PARENTHESIS UPPER HOOK +0239F^⎟^^\rparenextender^G^mathord^^RIGHT PARENTHESIS EXTENSION +023A0^⎠^^\rparenlend^G^mathord^^RIGHT PARENTHESIS LOWER HOOK +023A1^⎡^^\lbrackuend^G^mathord^^LEFT SQUARE BRACKET UPPER CORNER +023A2^⎢^^\lbrackextender^G^mathord^^LEFT SQUARE BRACKET EXTENSION +023A3^⎣^^\lbracklend^G^mathord^^LEFT SQUARE BRACKET LOWER CORNER +023A4^⎤^^\rbrackuend^G^mathord^^RIGHT SQUARE BRACKET UPPER CORNER +023A5^⎥^^\rbrackextender^G^mathord^^RIGHT SQUARE BRACKET EXTENSION +023A6^⎦^^\rbracklend^G^mathord^^RIGHT SQUARE BRACKET LOWER CORNER +023A7^⎧^^\lbraceuend^G^mathord^^LEFT CURLY BRACKET UPPER HOOK +023A8^⎨^^\lbracemid^G^mathord^^LEFT CURLY BRACKET MIDDLE PIECE +023A9^⎩^^\lbracelend^G^mathord^^LEFT CURLY BRACKET LOWER HOOK +023AA^⎪^^\vbraceextender^G^mathord^^CURLY BRACKET EXTENSION +023AB^⎫^^\rbraceuend^G^mathord^^RIGHT CURLY BRACKET UPPER HOOK +023AC^⎬^^\rbracemid^G^mathord^^RIGHT CURLY BRACKET MIDDLE PIECE +023AD^⎭^^\rbracelend^G^mathord^^RIGHT CURLY BRACKET LOWER HOOK +023AE^⎮^^\intextender^G^mathord^^INTEGRAL EXTENSION +023AF^⎯^^\harrowextender^G^mathord^^HORIZONTAL LINE EXTENSION (used to extend arrows) +023B0^⎰^^\lmoustache^R^mathord^^? \lmoustache, UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION +023B1^⎱^^\rmoustache^R^mathord^^? \rmoustache, UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION +023B2^⎲^^\sumtop^G^mathord^^SUMMATION TOP +023B3^⎳^^\sumbottom^G^mathord^^SUMMATION BOTTOM +023B4^⎴^^\overbracket^N^mathover^^TOP SQUARE BRACKET +023B5^⎵^^\underbracket^N^mathunder^^BOTTOM SQUARE BRACKET +023B6^⎶^^\bbrktbrk^N^mathord^^BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET +023B7^⎷^^\sqrtbottom^G^mathord^^RADICAL SYMBOL BOTTOM +023B8^⎸^^\lvboxline^^mathord^^LEFT VERTICAL BOX LINE +023B9^⎹^^\rvboxline^^mathord^^RIGHT VERTICAL BOX LINE +023CE^⏎^^\varcarriagereturn^^mathord^^RETURN SYMBOL +023D0^⏐^^^G^mathord^^VERTICAL LINE EXTENSION (VERTICAL LINE EXTENSION) +023DC^⏜^\overparen^\overparen^N^mathover^wrisym^= \wideparen (yhmath mathabx fourier), TOP PARENTHESIS (mathematical use) +023DD^⏝^\underparen^\underparen^N^mathunder^wrisym^BOTTOM PARENTHESIS (mathematical use) +023DE^⏞^\overbrace^\overbrace^N^mathover^^TOP CURLY BRACKET (mathematical use) +023DF^⏟^\underbrace^\underbrace^N^mathunder^^BOTTOM CURLY BRACKET (mathematical use) +023E0^⏠^^\obrbrak^N^mathord^^TOP TORTOISE SHELL BRACKET (mathematical use) +023E1^⏡^^\ubrbrak^N^mathord^^BOTTOM TORTOISE SHELL BRACKET (mathematical use) +023E2^⏢^^\trapezium^N^mathord^^WHITE TRAPEZIUM +023E3^⏣^^\benzenr^N^mathord^^BENZENE RING WITH CIRCLE +023E4^⏤^^\strns^N^mathord^^STRAIGHTNESS +023E5^⏥^^\fltns^N^mathord^^FLATNESS +023E6^⏦^^\accurrent^N^mathord^^# \AC (wasysym), AC CURRENT +023E7^⏧^^\elinters^N^mathord^^ELECTRICAL INTERSECTION +024C8^Ⓢ^^^N^mathord^^oS capital S in circle +02506^┆^^\bdtriplevdash^^mathord^^doubly broken vert +02580^▀^^\blockuphalf^^mathord^^UPPER HALF BLOCK +02584^▄^^\blocklowhalf^^mathord^^LOWER HALF BLOCK +02588^█^^\blockfull^^mathord^^FULL BLOCK +0258C^▌^^\blocklefthalf^^mathord^^LEFT HALF BLOCK +02590^▐^^\blockrighthalf^^mathord^^RIGHT HALF BLOCK +02591^░^^\blockqtrshaded^^mathord^^25\% shaded block +02592^▒^^\blockhalfshaded^^mathord^^50\% shaded block +02593^▓^^\blockthreeqtrshaded^^mathord^^75\% shaded block +025A0^■^^\mdlgblksquare^N^mathord^^square, filled +025A1^□^^\mdlgwhtsquare^N^mathord^^square, open +025A2^▢^^\squoval^^mathord^^WHITE SQUARE WITH ROUNDED CORNERS +025A3^▣^^\blackinwhitesquare^^mathord^^WHITE SQUARE CONTAINING BLACK SMALL SQUARE +025A4^▤^^\squarehfill^^mathord^^square, horizontal rule filled +025A5^▥^^\squarevfill^^mathord^^square, vertical rule filled +025A6^▦^^\squarehvfill^^mathord^^SQUARE WITH ORTHOGONAL CROSSHATCH FILL +025A7^▧^^\squarenwsefill^^mathord^^square, nw-to-se rule filled +025A8^▨^^\squareneswfill^^mathord^^square, ne-to-sw rule filled +025A9^▩^^\squarecrossfill^^mathord^^SQUARE WITH DIAGONAL CROSSHATCH FILL +025AA^▪^^\smblksquare^N^mathord^^sq bullet, filled +025AB^▫^^\smwhtsquare^N^mathord^^WHITE SMALL SQUARE +025AC^▬^^\hrectangleblack^^mathord^^BLACK RECTANGLE +025AD^▭^^\hrectangle^N^mathord^^horizontal rectangle, open +025AE^▮^^\vrectangleblack^N^mathord^^BLACK VERTICAL RECTANGLE +025AF^▯^^\vrectangle^N^mathord^^rectangle, white (vertical) +025B0^▰^^\parallelogramblack^^mathord^^BLACK PARALLELOGRAM +025B1^▱^^\parallelogram^N^mathord^^parallelogram, open +025B2^▲^^\bigblacktriangleup^B^mathord^^BLACK UP-POINTING TRIANGLE +025B3^△^\bigtriangleup^\bigtriangleup^B^mathbin^-stmaryrd^= \triangle (amsfonts), # \vartriangle (amssymb), big up triangle, open +025B4^▴^\blacktriangleup^\blacktriangle^B^mathbin^mathabx^up triangle, filled +025B5^▵^\smalltriangleup^\vartriangle^B^mathbin^mathabx^# \vartriangle (amssymb), small up triangle, open +025B6^▶^\RHD^\blacktriangleright^B^mathbin^wasysym^= \blacktriangleright (fourier -mathabx), (large) right triangle, filled +025B7^▷^\rhd^\triangleright^B^mathbin^amssymb wasysym^= \rres (oz), = \RightTriangle (wrisym), (large) right triangle, open; z notation range restriction +025B8^▸^\blacktriangleright^\smallblacktriangleright^B^mathbin^mathabx -fourier^right triangle, filled +025B9^▹^\smalltriangleright^\smalltriangleright^B^mathbin^mathabx^# \triangleright, x \triangleright (mathabx), right triangle, open +025BA^►^^\blackpointerright^^mathord^^BLACK RIGHT-POINTING POINTER +025BB^▻^^\whitepointerright^^mathord^^# \triangleright (mathabx), WHITE RIGHT-POINTING POINTER +025BC^▼^^\bigblacktriangledown^B^mathord^^big down triangle, filled +025BD^▽^\bigtriangledown^\bigtriangledown^B^mathbin^-stmaryrd^big down triangle, open +025BE^▾^\blacktriangledown^\blacktriangledown^B^mathbin^mathabx^BLACK DOWN-POINTING SMALL TRIANGLE +025BF^▿^\smalltriangledown^\triangledown^B^mathbin^mathabx^# \triangledown (amssymb), WHITE DOWN-POINTING SMALL TRIANGLE +025C0^◀^\LHD^\blacktriangleleft^B^mathbin^wasysym^= \blacktriangleleft (fourier -mathabx), (large) left triangle, filled +025C1^◁^\lhd^\triangleleft^B^mathbin^amssymb wasysym^= \dres (oz), = \LeftTriangle (wrisym), (large) left triangle, open; z notation domain restriction +025C2^◂^\blacktriangleleft^\smallblacktriangleleft^B^mathbin^mathabx -fourier^left triangle, filled +025C3^◃^\smalltriangleleft^\smalltriangleleft^B^mathbin^mathabx^# \triangleleft, x \triangleleft (mathabx), left triangle, open +025C4^◄^^\blackpointerleft^B^mathord^^BLACK LEFT-POINTING POINTER +025C5^◅^^\whitepointerleft^B^mathord^^# \triangleleft (mathabx), WHITE LEFT-POINTING POINTER +025C6^◆^\Diamondblack^\mdlgblkdiamond^N^mathord^txfonts^BLACK DIAMOND +025C7^◇^\Diamond^\mdlgwhtdiamond^N^mathord^amssymb^WHITE DIAMOND; diamond, open +025C8^◈^^\blackinwhitediamond^N^mathord^^WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND +025C9^◉^^\fisheye^N^mathord^^FISHEYE +025CA^◊^\lozenge^\mdlgwhtlozenge^B^mathord^amssymb^LOZENGE or total mark +025CB^○^\Circle^\mdlgwhtcircle^B^mathbin^wasysym^medium large circle +025CC^◌^^\dottedcircle^^mathord^^DOTTED CIRCLE +025CD^◍^^\circlevertfill^^mathord^^CIRCLE WITH VERTICAL FILL +025CE^◎^^\bullseye^N^mathord^^# \circledcirc (amssymb), BULLSEYE +025CF^●^\CIRCLE^\mdlgblkcircle^N^mathord^wasysym^circle, filled +025D0^◐^\LEFTcircle^\circlelefthalfblack^^mathord^wasysym^circle, filled left half [harvey ball] +025D1^◑^\RIGHTcircle^\circlerighthalfblack^^mathord^wasysym^circle, filled right half +025D2^◒^^\circlebottomhalfblack^^mathord^^circle, filled bottom half +025D3^◓^^\circletophalfblack^^mathord^^circle, filled top half +025D4^◔^^\circleurquadblack^^mathord^^CIRCLE WITH UPPER RIGHT QUADRANT BLACK +025D5^◕^^\blackcircleulquadwhite^^mathord^^CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK +025D6^◖^\LEFTCIRCLE^\blacklefthalfcircle^N^mathord^wasysym^LEFT HALF BLACK CIRCLE +025D7^◗^\RIGHTCIRCLE^\blackrighthalfcircle^N^mathord^wasysym^RIGHT HALF BLACK CIRCLE +025D8^◘^^\inversebullet^^mathord^^INVERSE BULLET +025D9^◙^^\inversewhitecircle^^mathord^^INVERSE WHITE CIRCLE +025DA^◚^^\invwhiteupperhalfcircle^^mathord^^UPPER HALF INVERSE WHITE CIRCLE +025DB^◛^^\invwhitelowerhalfcircle^^mathord^^LOWER HALF INVERSE WHITE CIRCLE +025DC^◜^^\ularc^^mathord^^UPPER LEFT QUADRANT CIRCULAR ARC +025DD^◝^^\urarc^^mathord^^UPPER RIGHT QUADRANT CIRCULAR ARC +025DE^◞^^\lrarc^^mathord^^LOWER RIGHT QUADRANT CIRCULAR ARC +025DF^◟^^\llarc^^mathord^^LOWER LEFT QUADRANT CIRCULAR ARC +025E0^◠^^\topsemicircle^^mathord^^UPPER HALF CIRCLE +025E1^◡^^\botsemicircle^^mathord^^LOWER HALF CIRCLE +025E2^◢^^\lrblacktriangle^N^mathord^^lower right triangle, filled +025E3^◣^^\llblacktriangle^N^mathord^^lower left triangle, filled +025E4^◤^^\ulblacktriangle^N^mathord^^upper left triangle, filled +025E5^◥^^\urblacktriangle^N^mathord^^upper right triangle, filled +025E6^◦^^\smwhtcircle^B^mathord^^WHITE BULLET +025E7^◧^^\squareleftblack^^mathord^^square, filled left half +025E8^◨^^\squarerightblack^^mathord^^square, filled right half +025E9^◩^^\squareulblack^^mathord^^square, filled top left corner +025EA^◪^^\squarelrblack^^mathord^^square, filled bottom right corner +025EB^◫^\boxbar^\boxbar^B^mathbin^stmaryrd txfonts^vertical bar in box +025EC^◬^^\trianglecdot^B^mathord^^triangle with centered dot +025ED^◭^^\triangleleftblack^^mathord^^UP-POINTING TRIANGLE WITH LEFT HALF BLACK +025EE^◮^^\trianglerightblack^^mathord^^UP-POINTING TRIANGLE WITH RIGHT HALF BLACK +025EF^◯^^\lgwhtcircle^N^mathord^^LARGE CIRCLE +025F0^◰^^\squareulquad^^mathord^^WHITE SQUARE WITH UPPER LEFT QUADRANT +025F1^◱^^\squarellquad^^mathord^^WHITE SQUARE WITH LOWER LEFT QUADRANT +025F2^◲^^\squarelrquad^^mathord^^WHITE SQUARE WITH LOWER RIGHT QUADRANT +025F3^◳^^\squareurquad^^mathord^^WHITE SQUARE WITH UPPER RIGHT QUADRANT +025F4^◴^^\circleulquad^^mathord^^WHITE CIRCLE WITH UPPER LEFT QUADRANT +025F5^◵^^\circlellquad^^mathord^^WHITE CIRCLE WITH LOWER LEFT QUADRANT +025F6^◶^^\circlelrquad^^mathord^^WHITE CIRCLE WITH LOWER RIGHT QUADRANT +025F7^◷^^\circleurquad^^mathord^^WHITE CIRCLE WITH UPPER RIGHT QUADRANT +025F8^◸^^\ultriangle^B^mathord^^UPPER LEFT TRIANGLE +025F9^◹^^\urtriangle^B^mathord^^UPPER RIGHT TRIANGLE +025FA^◺^^\lltriangle^B^mathord^^LOWER LEFT TRIANGLE +025FB^◻^\square^\mdwhtsquare^B^mathord^amssymb -fourier^WHITE MEDIUM SQUARE +025FC^◼^\blacksquare^\mdblksquare^B^mathord^amssymb -fourier^BLACK MEDIUM SQUARE +025FD^◽^^\mdsmwhtsquare^B^mathord^^WHITE MEDIUM SMALL SQUARE +025FE^◾^^\mdsmblksquare^B^mathord^^BLACK MEDIUM SMALL SQUARE +025FF^◿^^\lrtriangle^B^mathord^^LOWER RIGHT TRIANGLE +02605^★^\bigstar^\bigstar^B^mathord^amssymb^star, filled +02606^☆^^\bigwhitestar^B^mathord^^star, open +02609^☉^\Sun^\astrosun^N^mathord^mathabx^SUN +0260C^☌^^^N^mathord^wasysym^text \CONJUNCTION (wasysym), CONJUNCTION +02610^☐^\Square^^^mathord^wasysym^BALLOT BOX +02611^☑^\CheckedBox^^^mathord^wasysym^t \Checkedbox (marvosym), BALLOT BOX WITH CHECK +02612^☒^\XBox^^N^mathord^wasysym^t \Crossedbox (marvosym), BALLOT BOX WITH X +02615^☕^\steaming^^^mathord^arevmath^HOT BEVERAGE +0261E^☞^\pointright^^^mathord^arevmath^WHITE RIGHT POINTING INDEX +02620^☠^\skull^^^mathord^arevmath^SKULL AND CROSSBONES +02621^☡^^\danger^^mathord^^CAUTION SIGN, dangerous bend +02622^☢^\radiation^^^mathord^arevmath^RADIOACTIVE SIGN +02623^☣^\biohazard^^^mathord^arevmath^BIOHAZARD SIGN +0262F^☯^\yinyang^^^mathord^arevmath^YIN YANG +02639^☹^\frownie^^^mathord^wasysym^= \sadface (arevmath), WHITE FROWNING FACE +0263A^☺^\smiley^^^mathord^wasysym^= \smileface (arevmath), WHITE SMILING FACE +0263B^☻^\blacksmiley^\blacksmiley^^mathord^wasysym^= \invsmileface (arevmath), BLACK SMILING FACE +0263C^☼^\sun^\sun^^mathord^wasysym^WHITE SUN WITH RAYS +0263D^☽^\rightmoon^\rightmoon^N^mathord^wasysym mathabx^FIRST QUARTER MOON +0263E^☾^\leftmoon^\leftmoon^N^mathord^wasysym mathabx^LAST QUARTER MOON +0263F^☿^\mercury^^N^mathord^wasysym^= \Mercury (mathabx), MERCURY +02640^♀^\female^\female^N^mathord^wasysym^= \Venus (mathabx), = \girl (mathabx), venus, female +02641^♁^\earth^^N^mathord^wasysym^= \varEarth (mathabx), EARTH +02642^♂^\male^\male^N^mathord^wasysym^= \Mars (mathabx), = \boy (mathabx), mars, male +02643^♃^\jupiter^^N^mathord^wasysym^= \Jupiter (mathabx), JUPITER +02644^♄^\saturn^^N^mathord^wasysym^= \Saturn (mathabx), SATURN +02645^♅^\uranus^^^mathord^wasysym^= \Uranus (mathabx), URANUS +02646^♆^\neptune^^N^mathord^wasysym^= \Neptune (mathabx), NEPTUNE +02647^♇^\pluto^^N^mathord^wasysym^= \Pluto (mathabx), PLUTO +02648^♈^\aries^^N^mathord^wasysym^= \Aries (mathabx), ARIES +02649^♉^\taurus^^N^mathord^wasysym^= \Taurus (mathabx), TAURUS +0264A^♊^\gemini^^^mathord^wasysym^= \Gemini (mathabx), GEMINI +0264B^♋^\cancer^^^mathord^wasysym^CANCER +0264C^♌^\leo^^^mathord^wasysym^= \Leo (mathabx), LEO +0264D^♍^\virgo^^^mathord^wasysym^VIRGO +0264E^♎^\libra^^^mathord^wasysym^= \Libra (mathabx), LIBRA +0264F^♏^\scorpio^^^mathord^wasysym^= \Scorpio (mathabx), SCORPIUS +02650^♐^\sagittarius^^^mathord^wasysym^SAGITTARIUS +02651^♑^\capricornus^^^mathord^wasysym^CAPRICORN +02652^♒^\aquarius^^^mathord^wasysym^AQUARIUS +02653^♓^\pisces^^^mathord^wasysym^PISCES +02660^♠^\spadesuit^\spadesuit^N^mathord^^spades suit symbol +02661^♡^\heartsuit^\heartsuit^N^mathord^^heart suit symbol +02662^♢^\diamondsuit^\diamondsuit^N^mathord^^diamond suit symbol +02663^♣^\clubsuit^\clubsuit^N^mathord^^club suit symbol +02664^♤^\varspadesuit^\varspadesuit^N^mathord^txfonts^= \varspade (arevmath), spade, white (card suit) +02665^♥^\varheartsuit^\varheartsuit^N^mathord^txfonts^= \varheart (arevmath), filled heart (card suit) +02666^♦^\vardiamondsuit^\vardiamondsuit^N^mathord^txfonts^= \vardiamond (arevmath), filled diamond (card suit) +02667^♧^\varclubsuit^\varclubsuit^N^mathord^txfonts^= \varclub (arevmath), club, white (card suit) +02669^♩^\quarternote^\quarternote^N^mathord^arevmath wasysym^music note (sung text sign) +0266A^♪^\eighthnote^\eighthnote^^mathord^arevmath^EIGHTH NOTE +0266B^♫^\twonotes^\twonotes^^mathord^wasysym^BEAMED EIGHTH NOTES +0266C^♬^\sixteenthnote^^^mathord^arevmath^BEAMED SIXTEENTH NOTES +0266D^♭^\flat^\flat^N^mathord^^musical flat +0266E^♮^\natural^\natural^N^mathord^^music natural +0266F^♯^\sharp^\sharp^N^mathord^^# \# (oz), musical sharp, z notation infix bag count +0267B^♻^\recycle^^^mathord^arevmath^BLACK UNIVERSAL RECYCLING SYMBOL +0267E^♾^^\acidfree^^mathord^^PERMANENT PAPER SIGN +02680^⚀^^\dicei^N^mathord^^DIE FACE-1 +02681^⚁^^\diceii^N^mathord^^DIE FACE-2 +02682^⚂^^\diceiii^N^mathord^^DIE FACE-3 +02683^⚃^^\diceiv^N^mathord^^DIE FACE-4 +02684^⚄^^\dicev^N^mathord^^DIE FACE-5 +02685^⚅^^\dicevi^N^mathord^^DIE FACE-6 +02686^⚆^^\circledrightdot^N^mathord^^WHITE CIRCLE WITH DOT RIGHT +02687^⚇^^\circledtwodots^N^mathord^^WHITE CIRCLE WITH TWO DOTS +02688^⚈^^\blackcircledrightdot^N^mathord^^BLACK CIRCLE WITH WHITE DOT RIGHT +02689^⚉^^\blackcircledtwodots^N^mathord^^BLACK CIRCLE WITH TWO WHITE DOTS +02693^⚓^\anchor^^^mathord^arevmath^ANCHOR +02694^⚔^\swords^^^mathord^arevmath^CROSSED SWORDS +026A0^⚠^\warning^^^mathord^arevmath^WARNING SIGN +026A5^⚥^^\Hermaphrodite^^mathord^^MALE AND FEMALE SIGN +026AA^⚪^\medcirc^\mdwhtcircle^N^mathord^txfonts^MEDIUM WHITE CIRCLE +026AB^⚫^\medbullet^\mdblkcircle^N^mathord^txfonts^MEDIUM BLACK CIRCLE +026AC^⚬^^\mdsmwhtcircle^N^mathord^^MEDIUM SMALL WHITE CIRCLE +026B2^⚲^^\neuter^N^mathord^^NEUTER +0270E^✎^\pencil^^^mathord^arevmath^LOWER RIGHT PENCIL +02713^✓^\checkmark^\checkmark^N^mathord^amsfonts^= \ballotcheck (arevmath), tick, CHECK MARK +02717^✗^\ballotx^^^mathord^arevmath^BALLOT X +02720^✠^\maltese^\maltese^N^mathord^amsfonts^MALTESE CROSS +0272A^✪^^\circledstar^N^mathord^^CIRCLED WHITE STAR +02736^✶^^\varstar^N^mathord^^SIX POINTED BLACK STAR +0273D^✽^^\dingasterisk^^mathord^^HEAVY TEARDROP-SPOKED ASTERISK +02772^❲^^\lbrbrak^O^mathopen^^LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT +02773^❳^^\rbrbrak^C^mathclose^^LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT +0279B^➛^^\draftingarrow^^mathord^^right arrow with bold head (drafting) +027A2^➢^\arrowbullet^^^mathord^arevmath^THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD +027C0^⟀^^\threedangle^N^mathord^^THREE DIMENSIONAL ANGLE +027C1^⟁^^\whiteinwhitetriangle^N^mathord^^WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE +027C2^⟂^\perp^\perp^R^mathrel^^PERPENDICULAR +027C3^⟃^^\subsetcirc^R^mathord^^OPEN SUBSET +027C4^⟄^^\supsetcirc^R^mathord^^OPEN SUPERSET +027C5^⟅^\Lbag^\lbag^R^mathopen^stmaryrd txfonts^= \lbag (stmaryrd -oz), LEFT S-SHAPED BAG DELIMITER +027C6^⟆^\Rbag^\rbag^R^mathclose^stmaryrd txfonts^= \rbag (stmaryrd -oz), RIGHT S-SHAPED BAG DELIMITER +027C7^⟇^^\veedot^R^mathbin^^OR WITH DOT INSIDE +027C8^⟈^^\bsolhsub^R^mathrel^^REVERSE SOLIDUS PRECEDING SUBSET +027C9^⟉^^\suphsol^R^mathrel^^SUPERSET PRECEDING SOLIDUS +027CC^⟌^^\longdivision^^mathopen^^LONG DIVISION +027D0^⟐^\Diamonddot^\diamondcdot^N^mathord^txfonts^WHITE DIAMOND WITH CENTRED DOT +027D1^⟑^^\wedgedot^B^mathbin^^AND WITH DOT +027D2^⟒^^\upin^R^mathrel^^ELEMENT OF OPENING UPWARDS +027D3^⟓^^\pullback^R^mathrel^^LOWER RIGHT CORNER WITH DOT +027D4^⟔^^\pushout^R^mathrel^^UPPER LEFT CORNER WITH DOT +027D5^⟕^^\leftouterjoin^L^mathop^^LEFT OUTER JOIN +027D6^⟖^^\rightouterjoin^L^mathop^^RIGHT OUTER JOIN +027D7^⟗^^\fullouterjoin^L^mathop^^FULL OUTER JOIN +027D8^⟘^^\bigbot^L^mathop^^LARGE UP TACK +027D9^⟙^^\bigtop^L^mathop^^LARGE DOWN TACK +027DA^⟚^^\DashVDash^R^mathrel^^LEFT AND RIGHT DOUBLE TURNSTILE +027DB^⟛^^\dashVdash^R^mathrel^^LEFT AND RIGHT TACK +027DC^⟜^\multimapinv^\multimapinv^R^mathrel^txfonts^LEFT MULTIMAP +027DD^⟝^^\vlongdash^R^mathrel^^long left tack +027DE^⟞^^\longdashv^R^mathrel^^long right tack +027DF^⟟^^\cirbot^R^mathrel^^UP TACK WITH CIRCLE ABOVE +027E0^⟠^^\lozengeminus^B^mathbin^^LOZENGE DIVIDED BY HORIZONTAL RULE +027E1^⟡^^\concavediamond^B^mathbin^^WHITE CONCAVE-SIDED DIAMOND +027E2^⟢^^\concavediamondtickleft^B^mathbin^^WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK +027E3^⟣^^\concavediamondtickright^B^mathbin^^WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK +027E4^⟤^^\whitesquaretickleft^B^mathbin^^WHITE SQUARE WITH LEFTWARDS TICK +027E5^⟥^^\whitesquaretickright^B^mathbin^^WHITE SQUARE WITH RIGHTWARDS TICK +027E6^⟦^\llbracket^\lBrack^O^mathopen^stmaryrd wrisym kpfonts fourier^= \Lbrack (mathbbol), = \lbag (oz -stmaryrd), MATHEMATICAL LEFT WHITE SQUARE BRACKET +027E7^⟧^\rrbracket^\rBrack^C^mathclose^stmaryrd wrisym kpfonts fourier^= \Rbrack (mathbbol), = \rbag (oz -stmaryrd), MATHEMATICAL RIGHT WHITE SQUARE BRACKET +027E8^⟨^\langle^\langle^O^mathopen^^MATHEMATICAL LEFT ANGLE BRACKET +027E9^⟩^\rangle^\rangle^C^mathclose^^MATHEMATICAL RIGHT ANGLE BRACKET +027EA^⟪^\lang^\lAngle^O^mathopen^oz^MATHEMATICAL LEFT DOUBLE ANGLE BRACKET, z notation left chevron bracket +027EB^⟫^\rang^\rAngle^C^mathclose^oz^MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET, z notation right chevron bracket +027EC^⟬^^\Lbrbrak^O^mathopen^^MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET +027ED^⟭^^\Rbrbrak^C^mathclose^^MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET +027EE^⟮^\lgroup^^O^mathopen^^MATHEMATICAL LEFT FLATTENED PARENTHESIS +027EF^⟯^\rgroup^^C^mathclose^^MATHEMATICAL RIGHT FLATTENED PARENTHESIS +027F0^⟰^^\UUparrow^R^mathrel^^UPWARDS QUADRUPLE ARROW +027F1^⟱^^\DDownarrow^R^mathrel^^DOWNWARDS QUADRUPLE ARROW +027F2^⟲^^\acwgapcirclearrow^R^mathrel^^ANTICLOCKWISE GAPPED CIRCLE ARROW +027F3^⟳^^\cwgapcirclearrow^R^mathrel^^CLOCKWISE GAPPED CIRCLE ARROW +027F4^⟴^^\rightarrowonoplus^R^mathrel^^RIGHT ARROW WITH CIRCLED PLUS +027F5^⟵^\longleftarrow^\longleftarrow^R^mathrel^^LONG LEFTWARDS ARROW +027F6^⟶^\longrightarrow^\longrightarrow^R^mathrel^^LONG RIGHTWARDS ARROW +027F7^⟷^\longleftrightarrow^\longleftrightarrow^R^mathrel^^LONG LEFT RIGHT ARROW +027F8^⟸^\Longleftarrow^\Longleftarrow^R^mathrel^^= \impliedby (amsmath), LONG LEFTWARDS DOUBLE ARROW +027F9^⟹^\Longrightarrow^\Longrightarrow^R^mathrel^^= \implies (amsmath), LONG RIGHTWARDS DOUBLE ARROW +027FA^⟺^\Longleftrightarrow^\Longleftrightarrow^R^mathrel^^= \iff (oz), LONG LEFT RIGHT DOUBLE ARROW +027FB^⟻^\longmapsfrom^\longmapsfrom^R^mathrel^stmaryrd^= \longmappedfrom (kpfonts), LONG LEFTWARDS ARROW FROM BAR +027FC^⟼^\longmapsto^\longmapsto^R^mathrel^^LONG RIGHTWARDS ARROW FROM BAR +027FD^⟽^\Longmapsfrom^\Longmapsfrom^R^mathrel^stmaryrd^= \Longmappedfrom (kpfonts), LONG LEFTWARDS DOUBLE ARROW FROM BAR +027FE^⟾^\Longmapsto^\Longmapsto^R^mathrel^stmaryrd^LONG RIGHTWARDS DOUBLE ARROW FROM BAR +027FF^⟿^^\longrightsquigarrow^R^mathrel^^LONG RIGHTWARDS SQUIGGLE ARROW +02900^⤀^\psur^\nvtwoheadrightarrow^R^mathrel^oz^= \psurj (oz), RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE, z notation partial surjection +02901^⤁^^\nVtwoheadrightarrow^R^mathrel^^RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE, z notation finite surjection +02902^⤂^^\nvLeftarrow^R^mathrel^^LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE +02903^⤃^^\nvRightarrow^R^mathrel^^RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE +02904^⤄^^\nvLeftrightarrow^R^mathrel^^LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE +02905^⤅^^\twoheadmapsto^R^mathrel^^RIGHTWARDS TWO-HEADED ARROW FROM BAR +02906^⤆^\Mapsfrom^\Mapsfrom^R^mathrel^stmaryrd^= \Mappedfrom (kpfonts), LEFTWARDS DOUBLE ARROW FROM BAR +02907^⤇^\Mapsto^\Mapsto^R^mathrel^stmaryrd^RIGHTWARDS DOUBLE ARROW FROM BAR +02908^⤈^^\downarrowbarred^R^mathrel^^DOWNWARDS ARROW WITH HORIZONTAL STROKE +02909^⤉^^\uparrowbarred^R^mathrel^^UPWARDS ARROW WITH HORIZONTAL STROKE +0290A^⤊^^\Uuparrow^R^mathrel^^UPWARDS TRIPLE ARROW +0290B^⤋^^\Ddownarrow^R^mathrel^^DOWNWARDS TRIPLE ARROW +0290C^⤌^^\leftbkarrow^R^mathrel^^LEFTWARDS DOUBLE DASH ARROW +0290D^⤍^^\rightbkarrow^R^mathrel^^RIGHTWARDS DOUBLE DASH ARROW +0290E^⤎^^\leftdbkarrow^R^mathrel^^LEFTWARDS TRIPLE DASH ARROW +0290F^⤏^^\dbkarow^R^mathrel^^RIGHTWARDS TRIPLE DASH ARROW +02910^⤐^^\drbkarow^R^mathrel^^RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW +02911^⤑^^\rightdotarrow^R^mathrel^^RIGHTWARDS ARROW WITH DOTTED STEM +02912^⤒^\UpArrowBar^\baruparrow^R^mathrel^wrisym^UPWARDS ARROW TO BAR +02913^⤓^\DownArrowBar^\downarrowbar^R^mathrel^wrisym^DOWNWARDS ARROW TO BAR +02914^⤔^\pinj^\nvrightarrowtail^R^mathrel^oz^RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE, z notation partial injection +02915^⤕^\finj^\nVrightarrowtail^R^mathrel^oz^RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE, z notation finite injection +02916^⤖^\bij^\twoheadrightarrowtail^R^mathrel^oz^RIGHTWARDS TWO-HEADED ARROW WITH TAIL, z notation bijection +02917^⤗^^\nvtwoheadrightarrowtail^R^mathrel^^RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE, z notation surjective injection +02918^⤘^^\nVtwoheadrightarrowtail^R^mathrel^^RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE, z notation finite surjective injection +02919^⤙^^\lefttail^R^mathrel^^LEFTWARDS ARROW-TAIL +0291A^⤚^^\righttail^R^mathrel^^RIGHTWARDS ARROW-TAIL +0291B^⤛^^\leftdbltail^R^mathrel^^LEFTWARDS DOUBLE ARROW-TAIL +0291C^⤜^^\rightdbltail^R^mathrel^^RIGHTWARDS DOUBLE ARROW-TAIL +0291D^⤝^^\diamondleftarrow^R^mathrel^^LEFTWARDS ARROW TO BLACK DIAMOND +0291E^⤞^^\rightarrowdiamond^R^mathrel^^RIGHTWARDS ARROW TO BLACK DIAMOND +0291F^⤟^^\diamondleftarrowbar^R^mathrel^^LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND +02920^⤠^^\barrightarrowdiamond^R^mathrel^^RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND +02921^⤡^^\nwsearrow^R^mathrel^^NORTH WEST AND SOUTH EAST ARROW +02922^⤢^^\neswarrow^R^mathrel^^NORTH EAST AND SOUTH WEST ARROW +02923^⤣^^\hknwarrow^R^mathrel^^NORTH WEST ARROW WITH HOOK +02924^⤤^^\hknearrow^R^mathrel^^NORTH EAST ARROW WITH HOOK +02925^⤥^^\hksearow^R^mathrel^^SOUTH EAST ARROW WITH HOOK +02926^⤦^^\hkswarow^R^mathrel^^SOUTH WEST ARROW WITH HOOK +02927^⤧^^\tona^R^mathrel^^NORTH WEST ARROW AND NORTH EAST ARROW +02928^⤨^^\toea^R^mathrel^^NORTH EAST ARROW AND SOUTH EAST ARROW +02929^⤩^^\tosa^R^mathrel^^SOUTH EAST ARROW AND SOUTH WEST ARROW +0292A^⤪^^\towa^R^mathrel^^SOUTH WEST ARROW AND NORTH WEST ARROW +0292B^⤫^^\rdiagovfdiag^R^mathord^^RISING DIAGONAL CROSSING FALLING DIAGONAL +0292C^⤬^^\fdiagovrdiag^R^mathord^^FALLING DIAGONAL CROSSING RISING DIAGONAL +0292D^⤭^^\seovnearrow^R^mathord^^SOUTH EAST ARROW CROSSING NORTH EAST ARROW +0292E^⤮^^\neovsearrow^R^mathord^^NORTH EAST ARROW CROSSING SOUTH EAST ARROW +0292F^⤯^^\fdiagovnearrow^R^mathord^^FALLING DIAGONAL CROSSING NORTH EAST ARROW +02930^⤰^^\rdiagovsearrow^R^mathord^^RISING DIAGONAL CROSSING SOUTH EAST ARROW +02931^⤱^^\neovnwarrow^R^mathord^^NORTH EAST ARROW CROSSING NORTH WEST ARROW +02932^⤲^^\nwovnearrow^R^mathord^^NORTH WEST ARROW CROSSING NORTH EAST ARROW +02933^⤳^\leadsto^\rightcurvedarrow^R^mathrel^txfonts^WAVE ARROW POINTING DIRECTLY RIGHT +02934^⤴^^\uprightcurvearrow^R^mathord^^ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS +02935^⤵^^\downrightcurvedarrow^R^mathord^^ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS +02936^⤶^^\leftdowncurvedarrow^R^mathrel^^ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS +02937^⤷^^\rightdowncurvedarrow^R^mathrel^^ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS +02938^⤸^^\cwrightarcarrow^R^mathrel^^RIGHT-SIDE ARC CLOCKWISE ARROW +02939^⤹^^\acwleftarcarrow^R^mathrel^^LEFT-SIDE ARC ANTICLOCKWISE ARROW +0293A^⤺^^\acwoverarcarrow^R^mathrel^^TOP ARC ANTICLOCKWISE ARROW +0293B^⤻^^\acwunderarcarrow^R^mathrel^^BOTTOM ARC ANTICLOCKWISE ARROW +0293C^⤼^^\curvearrowrightminus^R^mathrel^^TOP ARC CLOCKWISE ARROW WITH MINUS +0293D^⤽^^\curvearrowleftplus^R^mathrel^^TOP ARC ANTICLOCKWISE ARROW WITH PLUS +0293E^⤾^^\cwundercurvearrow^R^mathrel^^LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW +0293F^⤿^^\ccwundercurvearrow^R^mathrel^^LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW +02940^⥀^^\acwcirclearrow^R^mathrel^^ANTICLOCKWISE CLOSED CIRCLE ARROW +02941^⥁^^\cwcirclearrow^R^mathrel^^CLOCKWISE CLOSED CIRCLE ARROW +02942^⥂^^\rightarrowshortleftarrow^R^mathrel^^RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW +02943^⥃^^\leftarrowshortrightarrow^R^mathrel^^LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW +02944^⥄^^\shortrightarrowleftarrow^R^mathrel^^SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW +02945^⥅^^\rightarrowplus^R^mathrel^^RIGHTWARDS ARROW WITH PLUS BELOW +02946^⥆^^\leftarrowplus^R^mathrel^^LEFTWARDS ARROW WITH PLUS BELOW +02947^⥇^^\rightarrowx^R^mathrel^^RIGHTWARDS ARROW THROUGH X +02948^⥈^^\leftrightarrowcircle^R^mathrel^^LEFT RIGHT ARROW THROUGH SMALL CIRCLE +02949^⥉^^\twoheaduparrowcircle^R^mathrel^^UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE +0294A^⥊^\leftrightharpoon^\leftrightharpoonupdown^R^mathrel^mathabx^LEFT BARB UP RIGHT BARB DOWN HARPOON +0294B^⥋^\rightleftharpoon^\leftrightharpoondownup^R^mathrel^mathabx^LEFT BARB DOWN RIGHT BARB UP HARPOON +0294C^⥌^^\updownharpoonrightleft^R^mathrel^^UP BARB RIGHT DOWN BARB LEFT HARPOON +0294D^⥍^^\updownharpoonleftright^R^mathrel^^UP BARB LEFT DOWN BARB RIGHT HARPOON +0294E^⥎^\leftrightharpoonup^\leftrightharpoonupup^R^mathrel^wrisym^LEFT BARB UP RIGHT BARB UP HARPOON +0294F^⥏^\rightupdownharpoon^\updownharpoonrightright^R^mathrel^wrisym^UP BARB RIGHT DOWN BARB RIGHT HARPOON +02950^⥐^\leftrightharpoondown^\leftrightharpoondowndown^R^mathrel^wrisym^LEFT BARB DOWN RIGHT BARB DOWN HARPOON +02951^⥑^\leftupdownharpoon^\updownharpoonleftleft^R^mathrel^wrisym^UP BARB LEFT DOWN BARB LEFT HARPOON +02952^⥒^\LeftVectorBar^\barleftharpoonup^R^mathrel^wrisym^LEFTWARDS HARPOON WITH BARB UP TO BAR +02953^⥓^\RightVectorBar^\rightharpoonupbar^R^mathrel^wrisym^RIGHTWARDS HARPOON WITH BARB UP TO BAR +02954^⥔^\RightUpVectorBar^\barupharpoonright^R^mathrel^wrisym^UPWARDS HARPOON WITH BARB RIGHT TO BAR +02955^⥕^\RightDownVectorBar^\downharpoonrightbar^R^mathrel^wrisym^DOWNWARDS HARPOON WITH BARB RIGHT TO BAR +02956^⥖^\DownLeftVectorBar^\barleftharpoondown^R^mathrel^wrisym^LEFTWARDS HARPOON WITH BARB DOWN TO BAR +02957^⥗^\DownRightVectorBar^\rightharpoondownbar^R^mathrel^wrisym^RIGHTWARDS HARPOON WITH BARB DOWN TO BAR +02958^⥘^\LeftUpVectorBar^\barupharpoonleft^R^mathrel^wrisym^UPWARDS HARPOON WITH BARB LEFT TO BAR +02959^⥙^\LeftDownVectorBar^\downharpoonleftbar^R^mathrel^wrisym^DOWNWARDS HARPOON WITH BARB LEFT TO BAR +0295A^⥚^\LeftTeeVector^\leftharpoonupbar^R^mathrel^wrisym^LEFTWARDS HARPOON WITH BARB UP FROM BAR +0295B^⥛^\RightTeeVector^\barrightharpoonup^R^mathrel^wrisym^RIGHTWARDS HARPOON WITH BARB UP FROM BAR +0295C^⥜^\RightUpTeeVector^\upharpoonrightbar^R^mathrel^wrisym^UPWARDS HARPOON WITH BARB RIGHT FROM BAR +0295D^⥝^\RightDownTeeVector^\bardownharpoonright^R^mathrel^wrisym^DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR +0295E^⥞^\DownLeftTeeVector^\leftharpoondownbar^R^mathrel^wrisym^LEFTWARDS HARPOON WITH BARB DOWN FROM BAR +0295F^⥟^\DownRightTeeVector^\barrightharpoondown^R^mathrel^wrisym^RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR +02960^⥠^\LeftUpTeeVector^\upharpoonleftbar^R^mathrel^wrisym^UPWARDS HARPOON WITH BARB LEFT FROM BAR +02961^⥡^\LeftDownTeeVector^\bardownharpoonleft^R^mathrel^wrisym^DOWNWARDS HARPOON WITH BARB LEFT FROM BAR +02962^⥢^\leftleftharpoons^\leftharpoonsupdown^R^mathrel^mathabx^LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN +02963^⥣^\upupharpoons^\upharpoonsleftright^R^mathrel^mathabx^UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT +02964^⥤^\rightrightharpoons^\rightharpoonsupdown^R^mathrel^mathabx^RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN +02965^⥥^\downdownharpoons^\downharpoonsleftright^R^mathrel^mathabx^DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT +02966^⥦^^\leftrightharpoonsup^R^mathrel^^LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP +02967^⥧^^\leftrightharpoonsdown^R^mathrel^^LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN +02968^⥨^^\rightleftharpoonsup^R^mathrel^^RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP +02969^⥩^^\rightleftharpoonsdown^R^mathrel^^RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN +0296A^⥪^\leftbarharpoon^\leftharpoonupdash^R^mathrel^mathabx^LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH +0296B^⥫^\barleftharpoon^\dashleftharpoondown^R^mathrel^mathabx^LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH +0296C^⥬^\rightbarharpoon^\rightharpoonupdash^R^mathrel^mathabx^RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH +0296D^⥭^\barrightharpoon^\dashrightharpoondown^R^mathrel^mathabx^RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH +0296E^⥮^\updownharpoons^\updownharpoonsleftright^R^mathrel^mathabx^= \upequilibrium (wrisym), UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT +0296F^⥯^\downupharpoons^\downupharpoonsleftright^R^mathrel^mathabx^= \uprevequilibrium (wrisym), DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT +02970^⥰^^\rightimply^R^mathrel^^RIGHT DOUBLE ARROW WITH ROUNDED HEAD +02971^⥱^^\equalrightarrow^R^mathrel^^EQUALS SIGN ABOVE RIGHTWARDS ARROW +02972^⥲^^\similarrightarrow^R^mathrel^^TILDE OPERATOR ABOVE RIGHTWARDS ARROW +02973^⥳^^\leftarrowsimilar^R^mathrel^^LEFTWARDS ARROW ABOVE TILDE OPERATOR +02974^⥴^^\rightarrowsimilar^R^mathrel^^RIGHTWARDS ARROW ABOVE TILDE OPERATOR +02975^⥵^^\rightarrowapprox^R^mathrel^^RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO +02976^⥶^^\ltlarr^R^mathrel^^LESS-THAN ABOVE LEFTWARDS ARROW +02977^⥷^^\leftarrowless^R^mathrel^^LEFTWARDS ARROW THROUGH LESS-THAN +02978^⥸^^\gtrarr^R^mathrel^^GREATER-THAN ABOVE RIGHTWARDS ARROW +02979^⥹^^\subrarr^R^mathrel^^SUBSET ABOVE RIGHTWARDS ARROW +0297A^⥺^^\leftarrowsubset^R^mathrel^^LEFTWARDS ARROW THROUGH SUBSET +0297B^⥻^^\suplarr^R^mathrel^^SUPERSET ABOVE LEFTWARDS ARROW +0297C^⥼^\strictfi^\leftfishtail^R^mathrel^txfonts^LEFT FISH TAIL +0297D^⥽^\strictif^\rightfishtail^R^mathrel^txfonts^RIGHT FISH TAIL +0297E^⥾^^\upfishtail^R^mathrel^^UP FISH TAIL +0297F^⥿^^\downfishtail^R^mathrel^^DOWN FISH TAIL +02980^⦀^\VERT^\Vvert^F^mathfence^fourier^TRIPLE VERTICAL BAR DELIMITER +02981^⦁^\spot^\mdsmblkcircle^N^mathord^oz^= \dot (oz), Z NOTATION SPOT +02982^⦂^^\typecolon^F^mathbin^^Z NOTATION TYPE COLON, (present in bbold font but no command) +02983^⦃^^\lBrace^O^mathopen^^LEFT WHITE CURLY BRACKET +02984^⦄^^\rBrace^C^mathclose^^RIGHT WHITE CURLY BRACKET +02985^⦅^\Lparen^\lParen^O^mathopen^mathbbol^LEFT WHITE PARENTHESIS +02986^⦆^\Rparen^\rParen^C^mathclose^mathbbol^RIGHT WHITE PARENTHESIS +02987^⦇^\limg^\llparenthesis^O^mathopen^oz^= \llparenthesis (stmaryrd), Z NOTATION LEFT IMAGE BRACKET +02988^⦈^\rimg^\rrparenthesis^C^mathclose^oz^= \rrparenthesis (stmaryrd), Z NOTATION RIGHT IMAGE BRACKET +02989^⦉^\lblot^\llangle^O^mathopen^oz^Z NOTATION LEFT BINDING BRACKET +0298A^⦊^\rblot^\rrangle^C^mathclose^oz^Z NOTATION RIGHT BINDING BRACKET +0298B^⦋^^\lbrackubar^O^mathopen^^LEFT SQUARE BRACKET WITH UNDERBAR +0298C^⦌^^\rbrackubar^C^mathclose^^RIGHT SQUARE BRACKET WITH UNDERBAR +0298D^⦍^^\lbrackultick^O^mathopen^^LEFT SQUARE BRACKET WITH TICK IN TOP CORNER +0298E^⦎^^\rbracklrtick^C^mathclose^^RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER +0298F^⦏^^\lbracklltick^O^mathopen^^LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER +02990^⦐^^\rbrackurtick^C^mathclose^^RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER +02991^⦑^^\langledot^O^mathopen^^LEFT ANGLE BRACKET WITH DOT +02992^⦒^^\rangledot^C^mathclose^^RIGHT ANGLE BRACKET WITH DOT +02993^⦓^^\lparenless^O^mathopen^^LEFT ARC LESS-THAN BRACKET +02994^⦔^^\rparengtr^C^mathclose^^RIGHT ARC GREATER-THAN BRACKET +02995^⦕^^\Lparengtr^O^mathopen^^DOUBLE LEFT ARC GREATER-THAN BRACKET +02996^⦖^^\Rparenless^C^mathclose^^DOUBLE RIGHT ARC LESS-THAN BRACKET +02997^⦗^^\lblkbrbrak^O^mathopen^^LEFT BLACK TORTOISE SHELL BRACKET +02998^⦘^^\rblkbrbrak^C^mathclose^^RIGHT BLACK TORTOISE SHELL BRACKET +02999^⦙^^\fourvdots^F^mathord^^DOTTED FENCE +0299A^⦚^^\vzigzag^F^mathord^^VERTICAL ZIGZAG LINE +0299B^⦛^^\measuredangleleft^N^mathord^^MEASURED ANGLE OPENING LEFT +0299C^⦜^^\rightanglesqr^N^mathord^^RIGHT ANGLE VARIANT WITH SQUARE +0299D^⦝^^\rightanglemdot^N^mathord^^MEASURED RIGHT ANGLE WITH DOT +0299E^⦞^^\angles^N^mathord^^ANGLE WITH S INSIDE +0299F^⦟^^\angdnr^N^mathord^^ACUTE ANGLE +029A0^⦠^^\gtlpar^N^mathord^^SPHERICAL ANGLE OPENING LEFT +029A1^⦡^^\sphericalangleup^N^mathord^^SPHERICAL ANGLE OPENING UP +029A2^⦢^^\turnangle^N^mathord^^TURNED ANGLE +029A3^⦣^^\revangle^N^mathord^^REVERSED ANGLE +029A4^⦤^^\angleubar^N^mathord^^ANGLE WITH UNDERBAR +029A5^⦥^^\revangleubar^N^mathord^^REVERSED ANGLE WITH UNDERBAR +029A6^⦦^^\wideangledown^N^mathord^^OBLIQUE ANGLE OPENING UP +029A7^⦧^^\wideangleup^N^mathord^^OBLIQUE ANGLE OPENING DOWN +029A8^⦨^^\measanglerutone^N^mathord^^MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT +029A9^⦩^^\measanglelutonw^N^mathord^^MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT +029AA^⦪^^\measanglerdtose^N^mathord^^MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT +029AB^⦫^^\measangleldtosw^N^mathord^^MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT +029AC^⦬^^\measangleurtone^N^mathord^^MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP +029AD^⦭^^\measangleultonw^N^mathord^^MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP +029AE^⦮^^\measangledrtose^N^mathord^^MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN +029AF^⦯^^\measangledltosw^N^mathord^^MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN +029B0^⦰^^\revemptyset^N^mathord^^REVERSED EMPTY SET +029B1^⦱^^\emptysetobar^N^mathord^^EMPTY SET WITH OVERBAR +029B2^⦲^^\emptysetocirc^N^mathord^^EMPTY SET WITH SMALL CIRCLE ABOVE +029B3^⦳^^\emptysetoarr^N^mathord^^EMPTY SET WITH RIGHT ARROW ABOVE +029B4^⦴^^\emptysetoarrl^N^mathord^^EMPTY SET WITH LEFT ARROW ABOVE +029B5^⦵^^\circlehbar^N^mathbin^^CIRCLE WITH HORIZONTAL BAR +029B6^⦶^^\circledvert^B^mathbin^^CIRCLED VERTICAL BAR +029B7^⦷^^\circledparallel^B^mathbin^^CIRCLED PARALLEL +029B8^⦸^\circledbslash^\obslash^B^mathbin^txfonts^CIRCLED REVERSE SOLIDUS +029B9^⦹^^\operp^B^mathbin^^CIRCLED PERPENDICULAR +029BA^⦺^^\obot^N^mathord^^CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR +029BB^⦻^^\olcross^N^mathord^^CIRCLE WITH SUPERIMPOSED X +029BC^⦼^^\odotslashdot^N^mathord^^CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN +029BD^⦽^^\uparrowoncircle^N^mathord^^UP ARROW THROUGH CIRCLE +029BE^⦾^^\circledwhitebullet^N^mathord^^CIRCLED WHITE BULLET +029BF^⦿^^\circledbullet^N^mathord^^CIRCLED BULLET +029C0^⧀^\circledless^\olessthan^B^mathbin^txfonts^CIRCLED LESS-THAN +029C1^⧁^\circledgtr^\ogreaterthan^B^mathbin^txfonts^CIRCLED GREATER-THAN +029C2^⧂^^\cirscir^N^mathord^^CIRCLE WITH SMALL CIRCLE TO THE RIGHT +029C3^⧃^^\cirE^N^mathord^^CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT +029C4^⧄^\boxslash^\boxdiag^B^mathbin^stmaryrd txfonts^SQUARED RISING DIAGONAL SLASH +029C5^⧅^\boxbslash^\boxbslash^B^mathbin^stmaryrd txfonts^SQUARED FALLING DIAGONAL SLASH +029C6^⧆^\boxast^\boxast^B^mathbin^stmaryrd txfonts^SQUARED ASTERISK +029C7^⧇^\boxcircle^\boxcircle^B^mathbin^stmaryrd^SQUARED SMALL CIRCLE +029C8^⧈^\boxbox^\boxbox^B^mathbin^stmaryrd^SQUARED SQUARE +029C9^⧉^^\boxonbox^N^mathord^^TWO JOINED SQUARES +029CA^⧊^^\triangleodot^N^mathord^^TRIANGLE WITH DOT ABOVE +029CB^⧋^^\triangleubar^N^mathord^^TRIANGLE WITH UNDERBAR +029CC^⧌^^\triangles^N^mathord^^S IN TRIANGLE +029CD^⧍^^\triangleserifs^N^mathbin^^TRIANGLE WITH SERIFS AT BOTTOM +029CE^⧎^^\rtriltri^R^mathrel^^RIGHT TRIANGLE ABOVE LEFT TRIANGLE +029CF^⧏^\LeftTriangleBar^\ltrivb^R^mathrel^wrisym^LEFT TRIANGLE BESIDE VERTICAL BAR +029D0^⧐^\RightTriangleBar^\vbrtri^R^mathrel^wrisym^VERTICAL BAR BESIDE RIGHT TRIANGLE +029D1^⧑^^\lfbowtie^R^mathrel^^left black bowtie +029D2^⧒^^\rfbowtie^R^mathrel^^right black bowtie +029D3^⧓^^\fbowtie^R^mathrel^^BLACK BOWTIE +029D4^⧔^^\lftimes^R^mathrel^^left black times +029D5^⧕^^\rftimes^R^mathrel^^right black times +029D6^⧖^^\hourglass^B^mathbin^^WHITE HOURGLASS +029D7^⧗^^\blackhourglass^B^mathbin^^BLACK HOURGLASS +029D8^⧘^^\lvzigzag^O^mathopen^^LEFT WIGGLY FENCE +029D9^⧙^^\rvzigzag^C^mathclose^^RIGHT WIGGLY FENCE +029DA^⧚^^\Lvzigzag^O^mathopen^^LEFT DOUBLE WIGGLY FENCE +029DB^⧛^^\Rvzigzag^C^mathclose^^RIGHT DOUBLE WIGGLY FENCE +029DC^⧜^^\iinfin^N^mathord^^INCOMPLETE INFINITY +029DD^⧝^^\tieinfty^N^mathord^^TIE OVER INFINITY +029DE^⧞^^\nvinfty^N^mathord^^INFINITY NEGATED WITH VERTICAL BAR +029DF^⧟^\multimapboth^\dualmap^R^mathrel^txfonts^DOUBLE-ENDED MULTIMAP +029E0^⧠^^\laplac^N^mathord^^SQUARE WITH CONTOURED OUTLINE +029E1^⧡^^\lrtriangleeq^R^mathrel^^INCREASES AS +029E2^⧢^^\shuffle^B^mathbin^^SHUFFLE PRODUCT +029E3^⧣^^\eparsl^R^mathrel^^EQUALS SIGN AND SLANTED PARALLEL +029E4^⧤^^\smeparsl^R^mathrel^^EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE +029E5^⧥^^\eqvparsl^R^mathrel^^IDENTICAL TO AND SLANTED PARALLEL +029E6^⧦^^\gleichstark^R^mathrel^^GLEICH STARK +029E7^⧧^^\thermod^N^mathord^^THERMODYNAMIC +029E8^⧨^^\downtriangleleftblack^N^mathord^^DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK +029E9^⧩^^\downtrianglerightblack^N^mathord^^DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK +029EA^⧪^^\blackdiamonddownarrow^N^mathord^^BLACK DIAMOND WITH DOWN ARROW +029EB^⧫^\blacklozenge^\mdlgblklozenge^B^mathbin^amssymb^BLACK LOZENGE +029EC^⧬^^\circledownarrow^N^mathord^^WHITE CIRCLE WITH DOWN ARROW +029ED^⧭^^\blackcircledownarrow^N^mathord^^BLACK CIRCLE WITH DOWN ARROW +029EE^⧮^^\errbarsquare^N^mathord^^ERROR-BARRED WHITE SQUARE +029EF^⧯^^\errbarblacksquare^N^mathord^^ERROR-BARRED BLACK SQUARE +029F0^⧰^^\errbardiamond^N^mathord^^ERROR-BARRED WHITE DIAMOND +029F1^⧱^^\errbarblackdiamond^N^mathord^^ERROR-BARRED BLACK DIAMOND +029F2^⧲^^\errbarcircle^N^mathord^^ERROR-BARRED WHITE CIRCLE +029F3^⧳^^\errbarblackcircle^N^mathord^^ERROR-BARRED BLACK CIRCLE +029F4^⧴^^\ruledelayed^R^mathrel^^RULE-DELAYED +029F5^⧵^\setminus^\setminus^B^mathbin^^REVERSE SOLIDUS OPERATOR +029F6^⧶^^\dsol^B^mathbin^^SOLIDUS WITH OVERBAR +029F7^⧷^^\rsolbar^B^mathbin^^REVERSE SOLIDUS WITH HORIZONTAL STROKE +029F8^⧸^^\xsol^L^mathop^^BIG SOLIDUS +029F9^⧹^\zhide^\xbsol^L^mathop^oz^= \hide (oz), BIG REVERSE SOLIDUS, z notation schema hiding +029FA^⧺^^\doubleplus^B^mathbin^^DOUBLE PLUS +029FB^⧻^^\tripleplus^B^mathbin^^TRIPLE PLUS +029FC^⧼^^\lcurvyangle^O^mathopen^^left pointing curved angle bracket +029FD^⧽^^\rcurvyangle^C^mathclose^^right pointing curved angle bracket +029FE^⧾^^\tplus^B^mathbin^^TINY +029FF^⧿^^\tminus^B^mathbin^^MINY +02A00^⨀^\bigodot^\bigodot^L^mathop^^N-ARY CIRCLED DOT OPERATOR +02A01^⨁^\bigoplus^\bigoplus^L^mathop^^N-ARY CIRCLED PLUS OPERATOR +02A02^⨂^\bigotimes^\bigotimes^L^mathop^^N-ARY CIRCLED TIMES OPERATOR +02A03^⨃^^\bigcupdot^L^mathop^^N-ARY UNION OPERATOR WITH DOT +02A04^⨄^\biguplus^\biguplus^L^mathop^^N-ARY UNION OPERATOR WITH PLUS +02A05^⨅^\bigsqcap^\bigsqcap^L^mathop^txfonts^N-ARY SQUARE INTERSECTION OPERATOR +02A06^⨆^\bigsqcup^\bigsqcup^L^mathop^^N-ARY SQUARE UNION OPERATOR +02A07^⨇^^\conjquant^L^mathop^^TWO LOGICAL AND OPERATOR +02A08^⨈^^\disjquant^L^mathop^^TWO LOGICAL OR OPERATOR +02A09^⨉^\varprod^\bigtimes^L^mathop^txfonts^N-ARY TIMES OPERATOR +02A0A^⨊^^\modtwosum^L^mathord^^MODULO TWO SUM +02A0B^⨋^^\sumint^L^mathop^^SUMMATION WITH INTEGRAL +02A0C^⨌^\iiiint^\iiiint^L^mathop^amsmath esint^QUADRUPLE INTEGRAL OPERATOR +02A0D^⨍^^\intbar^L^mathop^^FINITE PART INTEGRAL +02A0E^⨎^^\intBar^L^mathop^^INTEGRAL WITH DOUBLE STROKE +02A0F^⨏^\fint^\fint^L^mathop^esint wrisym^INTEGRAL AVERAGE WITH SLASH +02A10^⨐^^\cirfnint^L^mathop^^CIRCULATION FUNCTION +02A11^⨑^^\awint^L^mathop^^ANTICLOCKWISE INTEGRATION +02A12^⨒^^\rppolint^L^mathop^^LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE +02A13^⨓^^\scpolint^L^mathop^^LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE +02A14^⨔^^\npolint^L^mathop^^LINE INTEGRATION NOT INCLUDING THE POLE +02A15^⨕^^\pointint^L^mathop^^INTEGRAL AROUND A POINT OPERATOR +02A16^⨖^\sqint^\sqint^L^mathop^esint^= \sqrint (wrisym), QUATERNION INTEGRAL OPERATOR +02A17^⨗^^\intlarhk^L^mathop^^INTEGRAL WITH LEFTWARDS ARROW WITH HOOK +02A18^⨘^^\intx^L^mathop^^INTEGRAL WITH TIMES SIGN +02A19^⨙^^\intcap^L^mathop^^INTEGRAL WITH INTERSECTION +02A1A^⨚^^\intcup^L^mathop^^INTEGRAL WITH UNION +02A1B^⨛^^\upint^L^mathop^^INTEGRAL WITH OVERBAR +02A1C^⨜^^\lowint^L^mathop^^INTEGRAL WITH UNDERBAR +02A1D^⨝^\Join^\Join^L^mathop^amssymb^JOIN +02A1E^⨞^^\bigtriangleleft^L^mathop^^LARGE LEFT TRIANGLE OPERATOR +02A1F^⨟^\zcmp^\zcmp^L^mathop^oz^= \semi (oz), = \fatsemi (stmaryrd), Z NOTATION SCHEMA COMPOSITION +02A20^⨠^\zpipe^\zpipe^L^mathop^oz^Z NOTATION SCHEMA PIPING +02A21^⨡^\zproject^\zproject^L^mathop^oz^= \project (oz), Z NOTATION SCHEMA PROJECTION +02A22^⨢^^\ringplus^B^mathbin^^PLUS SIGN WITH SMALL CIRCLE ABOVE +02A23^⨣^^\plushat^B^mathbin^^PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE +02A24^⨤^^\simplus^B^mathbin^^PLUS SIGN WITH TILDE ABOVE +02A25^⨥^^\plusdot^B^mathbin^^PLUS SIGN WITH DOT BELOW +02A26^⨦^^\plussim^B^mathbin^^PLUS SIGN WITH TILDE BELOW +02A27^⨧^^\plussubtwo^B^mathbin^^PLUS SIGN WITH SUBSCRIPT TWO +02A28^⨨^^\plustrif^B^mathbin^^PLUS SIGN WITH BLACK TRIANGLE +02A29^⨩^^\commaminus^B^mathbin^^MINUS SIGN WITH COMMA ABOVE +02A2A^⨪^^\minusdot^B^mathbin^^MINUS SIGN WITH DOT BELOW +02A2B^⨫^^\minusfdots^B^mathbin^^MINUS SIGN WITH FALLING DOTS +02A2C^⨬^^\minusrdots^B^mathbin^^MINUS SIGN WITH RISING DOTS +02A2D^⨭^^\opluslhrim^B^mathbin^^PLUS SIGN IN LEFT HALF CIRCLE +02A2E^⨮^^\oplusrhrim^B^mathbin^^PLUS SIGN IN RIGHT HALF CIRCLE +02A2F^⨯^^\vectimes^B^mathbin^^# \times, VECTOR OR CROSS PRODUCT +02A30^⨰^^\dottimes^B^mathbin^^MULTIPLICATION SIGN WITH DOT ABOVE +02A31^⨱^^\timesbar^B^mathbin^^MULTIPLICATION SIGN WITH UNDERBAR +02A32^⨲^^\btimes^B^mathbin^^SEMIDIRECT PRODUCT WITH BOTTOM CLOSED +02A33^⨳^^\smashtimes^B^mathbin^^SMASH PRODUCT +02A34^⨴^^\otimeslhrim^B^mathbin^^MULTIPLICATION SIGN IN LEFT HALF CIRCLE +02A35^⨵^^\otimesrhrim^B^mathbin^^MULTIPLICATION SIGN IN RIGHT HALF CIRCLE +02A36^⨶^^\otimeshat^B^mathbin^^CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT +02A37^⨷^^\Otimes^B^mathbin^^MULTIPLICATION SIGN IN DOUBLE CIRCLE +02A38^⨸^^\odiv^B^mathbin^^CIRCLED DIVISION SIGN +02A39^⨹^^\triangleplus^B^mathbin^^PLUS SIGN IN TRIANGLE +02A3A^⨺^^\triangleminus^B^mathbin^^MINUS SIGN IN TRIANGLE +02A3B^⨻^^\triangletimes^B^mathbin^^MULTIPLICATION SIGN IN TRIANGLE +02A3C^⨼^^\intprod^B^mathbin^^INTERIOR PRODUCT +02A3D^⨽^^\intprodr^B^mathbin^^RIGHTHAND INTERIOR PRODUCT +02A3E^⨾^\fcmp^\fcmp^B^mathbin^oz^= \comp (oz), Z NOTATION RELATIONAL COMPOSITION +02A3F^⨿^\amalg^\amalg^B^mathbin^^AMALGAMATION OR COPRODUCT +02A40^⩀^^\capdot^B^mathbin^^INTERSECTION WITH DOT +02A41^⩁^^\uminus^B^mathbin^^UNION WITH MINUS SIGN, z notation bag subtraction +02A42^⩂^^\barcup^B^mathbin^^UNION WITH OVERBAR +02A43^⩃^^\barcap^B^mathbin^^INTERSECTION WITH OVERBAR +02A44^⩄^^\capwedge^B^mathbin^^INTERSECTION WITH LOGICAL AND +02A45^⩅^^\cupvee^B^mathbin^^UNION WITH LOGICAL OR +02A46^⩆^^\cupovercap^B^mathbin^^UNION ABOVE INTERSECTION +02A47^⩇^^\capovercup^B^mathbin^^INTERSECTION ABOVE UNION +02A48^⩈^^\cupbarcap^B^mathbin^^UNION ABOVE BAR ABOVE INTERSECTION +02A49^⩉^^\capbarcup^B^mathbin^^INTERSECTION ABOVE BAR ABOVE UNION +02A4A^⩊^^\twocups^B^mathbin^^UNION BESIDE AND JOINED WITH UNION +02A4B^⩋^^\twocaps^B^mathbin^^INTERSECTION BESIDE AND JOINED WITH INTERSECTION +02A4C^⩌^^\closedvarcup^B^mathbin^^CLOSED UNION WITH SERIFS +02A4D^⩍^^\closedvarcap^B^mathbin^^CLOSED INTERSECTION WITH SERIFS +02A4E^⩎^^\Sqcap^B^mathbin^^DOUBLE SQUARE INTERSECTION +02A4F^⩏^^\Sqcup^B^mathbin^^DOUBLE SQUARE UNION +02A50^⩐^^\closedvarcupsmashprod^B^mathbin^^CLOSED UNION WITH SERIFS AND SMASH PRODUCT +02A51^⩑^^\wedgeodot^B^mathbin^^LOGICAL AND WITH DOT ABOVE +02A52^⩒^^\veeodot^B^mathbin^^LOGICAL OR WITH DOT ABOVE +02A53^⩓^^\Wedge^B^mathbin^^DOUBLE LOGICAL AND +02A54^⩔^^\Vee^B^mathbin^^DOUBLE LOGICAL OR +02A55^⩕^^\wedgeonwedge^B^mathbin^^TWO INTERSECTING LOGICAL AND +02A56^⩖^^\veeonvee^B^mathbin^^TWO INTERSECTING LOGICAL OR +02A57^⩗^^\bigslopedvee^B^mathbin^^SLOPING LARGE OR +02A58^⩘^^\bigslopedwedge^B^mathbin^^SLOPING LARGE AND +02A59^⩙^^\veeonwedge^R^mathrel^^LOGICAL OR OVERLAPPING LOGICAL AND +02A5A^⩚^^\wedgemidvert^B^mathbin^^LOGICAL AND WITH MIDDLE STEM +02A5B^⩛^^\veemidvert^B^mathbin^^LOGICAL OR WITH MIDDLE STEM +02A5C^⩜^^\midbarwedge^B^mathbin^^ogical and with horizontal dash +02A5D^⩝^^\midbarvee^B^mathbin^^LOGICAL OR WITH HORIZONTAL DASH +02A5E^⩞^\doublebarwedge^\doublebarwedge^B^mathbin^amssymb^LOGICAL AND WITH DOUBLE OVERBAR +02A5F^⩟^^\wedgebar^B^mathbin^^LOGICAL AND WITH UNDERBAR +02A60^⩠^^\wedgedoublebar^B^mathbin^^LOGICAL AND WITH DOUBLE UNDERBAR +02A61^⩡^^\varveebar^B^mathbin^^SMALL VEE WITH UNDERBAR +02A62^⩢^^\doublebarvee^B^mathbin^^LOGICAL OR WITH DOUBLE OVERBAR +02A63^⩣^^\veedoublebar^B^mathbin^^LOGICAL OR WITH DOUBLE UNDERBAR +02A64^⩤^\dsub^\dsub^B^mathbin^oz^= \ndres (oz), Z NOTATION DOMAIN ANTIRESTRICTION +02A65^⩥^\rsub^\rsub^B^mathbin^oz^= \nrres (oz), Z NOTATION RANGE ANTIRESTRICTION +02A66^⩦^^\eqdot^R^mathrel^^EQUALS SIGN WITH DOT BELOW +02A67^⩧^^\dotequiv^R^mathrel^^IDENTICAL WITH DOT ABOVE +02A68^⩨^^\equivVert^R^mathrel^^TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE +02A69^⩩^^\equivVvert^R^mathrel^^TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE +02A6A^⩪^^\dotsim^R^mathrel^^TILDE OPERATOR WITH DOT ABOVE +02A6B^⩫^^\simrdots^R^mathrel^^TILDE OPERATOR WITH RISING DOTS +02A6C^⩬^^\simminussim^R^mathrel^^SIMILAR MINUS SIMILAR +02A6D^⩭^^\congdot^R^mathrel^^CONGRUENT WITH DOT ABOVE +02A6E^⩮^^\asteq^R^mathrel^^EQUALS WITH ASTERISK +02A6F^⩯^^\hatapprox^R^mathrel^^ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT +02A70^⩰^^\approxeqq^R^mathrel^^APPROXIMATELY EQUAL OR EQUAL TO +02A71^⩱^^\eqqplus^B^mathbin^^EQUALS SIGN ABOVE PLUS SIGN +02A72^⩲^^\pluseqq^B^mathbin^^PLUS SIGN ABOVE EQUALS SIGN +02A73^⩳^^\eqqsim^R^mathrel^^EQUALS SIGN ABOVE TILDE OPERATOR +02A74^⩴^\Coloneqq^\Coloneq^R^mathrel^txfonts^# ::=, x \Coloneq (txfonts), DOUBLE COLON EQUAL +02A75^⩵^\Equal^\eqeq^R^mathrel^wrisym^# ==, TWO CONSECUTIVE EQUALS SIGNS +02A76^⩶^\Same^\eqeqeq^R^mathrel^wrisym^# ===, THREE CONSECUTIVE EQUALS SIGNS +02A77^⩷^^\ddotseq^R^mathrel^^EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW +02A78^⩸^^\equivDD^R^mathrel^^EQUIVALENT WITH FOUR DOTS ABOVE +02A79^⩹^^\ltcir^R^mathrel^^LESS-THAN WITH CIRCLE INSIDE +02A7A^⩺^^\gtcir^R^mathrel^^GREATER-THAN WITH CIRCLE INSIDE +02A7B^⩻^^\ltquest^R^mathrel^^LESS-THAN WITH QUESTION MARK ABOVE +02A7C^⩼^^\gtquest^R^mathrel^^GREATER-THAN WITH QUESTION MARK ABOVE +02A7D^⩽^\leqslant^\leqslant^R^mathrel^amssymb fourier^LESS-THAN OR SLANTED EQUAL TO +02A7E^⩾^\geqslant^\geqslant^R^mathrel^amssymb fourier^GREATER-THAN OR SLANTED EQUAL TO +02A7F^⩿^^\lesdot^R^mathrel^^LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE +02A80^⪀^^\gesdot^R^mathrel^^GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE +02A81^⪁^^\lesdoto^R^mathrel^^LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE +02A82^⪂^^\gesdoto^R^mathrel^^GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE +02A83^⪃^^\lesdotor^R^mathrel^^LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT +02A84^⪄^^\gesdotol^R^mathrel^^GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT +02A85^⪅^\lessapprox^\lessapprox^R^mathrel^amssymb^LESS-THAN OR APPROXIMATE +02A86^⪆^\gtrapprox^\gtrapprox^R^mathrel^amssymb^GREATER-THAN OR APPROXIMATE +02A87^⪇^\lneq^\lneq^R^mathrel^amssymb^LESS-THAN AND SINGLE-LINE NOT EQUAL TO +02A88^⪈^\gneq^\gneq^R^mathrel^amssymb^GREATER-THAN AND SINGLE-LINE NOT EQUAL TO +02A89^⪉^\lnapprox^\lnapprox^R^mathrel^amssymb^LESS-THAN AND NOT APPROXIMATE +02A8A^⪊^\gnapprox^\gnapprox^R^mathrel^amssymb^GREATER-THAN AND NOT APPROXIMATE +02A8B^⪋^\lesseqqgtr^\lesseqqgtr^R^mathrel^amssymb^LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN +02A8C^⪌^\gtreqqless^\gtreqqless^R^mathrel^amssymb^GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN +02A8D^⪍^^\lsime^R^mathrel^^LESS-THAN ABOVE SIMILAR OR EQUAL +02A8E^⪎^^\gsime^R^mathrel^^GREATER-THAN ABOVE SIMILAR OR EQUAL +02A8F^⪏^^\lsimg^R^mathrel^^LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN +02A90^⪐^^\gsiml^R^mathrel^^GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN +02A91^⪑^^\lgE^R^mathrel^^LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL +02A92^⪒^^\glE^R^mathrel^^GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL +02A93^⪓^^\lesges^R^mathrel^^LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL +02A94^⪔^^\gesles^R^mathrel^^GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL +02A95^⪕^\eqslantless^\eqslantless^R^mathrel^amssymb^SLANTED EQUAL TO OR LESS-THAN +02A96^⪖^\eqslantgtr^\eqslantgtr^R^mathrel^amssymb^SLANTED EQUAL TO OR GREATER-THAN +02A97^⪗^^\elsdot^R^mathrel^^SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE +02A98^⪘^^\egsdot^R^mathrel^^SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE +02A99^⪙^^\eqqless^R^mathrel^^DOUBLE-LINE EQUAL TO OR LESS-THAN +02A9A^⪚^^\eqqgtr^R^mathrel^^DOUBLE-LINE EQUAL TO OR GREATER-THAN +02A9B^⪛^^\eqqslantless^R^mathrel^^DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN +02A9C^⪜^^\eqqslantgtr^R^mathrel^^DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN +02A9D^⪝^^\simless^R^mathrel^^SIMILAR OR LESS-THAN +02A9E^⪞^^\simgtr^R^mathrel^^SIMILAR OR GREATER-THAN +02A9F^⪟^^\simlE^R^mathrel^^SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN +02AA0^⪠^^\simgE^R^mathrel^^SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN +02AA1^⪡^\NestedLessLess^\Lt^R^mathrel^wrisym^= \lll (mathabx -amssymb), DOUBLE NESTED LESS-THAN +02AA2^⪢^\NestedGreaterGreater^\Gt^R^mathrel^wrisym^= \ggg (mathabx -amssymb), DOUBLE NESTED GREATER-THAN +02AA3^⪣^^\partialmeetcontraction^R^mathrel^^double less-than with underbar +02AA4^⪤^^\glj^R^mathrel^^GREATER-THAN OVERLAPPING LESS-THAN +02AA5^⪥^^\gla^R^mathrel^^GREATER-THAN BESIDE LESS-THAN +02AA6^⪦^\leftslice^\ltcc^R^mathrel^stmaryrd^LESS-THAN CLOSED BY CURVE +02AA7^⪧^\rightslice^\gtcc^R^mathrel^stmaryrd^GREATER-THAN CLOSED BY CURVE +02AA8^⪨^^\lescc^R^mathrel^^LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL +02AA9^⪩^^\gescc^R^mathrel^^GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL +02AAA^⪪^^\smt^R^mathrel^^SMALLER THAN +02AAB^⪫^^\lat^R^mathrel^^LARGER THAN +02AAC^⪬^^\smte^R^mathrel^^SMALLER THAN OR EQUAL TO +02AAD^⪭^^\late^R^mathrel^^LARGER THAN OR EQUAL TO +02AAE^⪮^^\bumpeqq^R^mathrel^^EQUALS SIGN WITH BUMPY ABOVE +02AAF^⪯^\preceq^\preceq^R^mathrel^^PRECEDES ABOVE SINGLE-LINE EQUALS SIGN +02AB0^⪰^\succeq^\succeq^R^mathrel^^SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN +02AB1^⪱^^\precneq^R^mathrel^^PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO +02AB2^⪲^^\succneq^R^mathrel^^SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO +02AB3^⪳^\preceqq^\preceqq^R^mathrel^txfonts^PRECEDES ABOVE EQUALS SIGN +02AB4^⪴^\succeqq^\succeqq^R^mathrel^txfonts^SUCCEEDS ABOVE EQUALS SIGN +02AB5^⪵^^\precneqq^R^mathrel^amssymb^PRECEDES ABOVE NOT EQUAL TO +02AB6^⪶^^\succneqq^R^mathrel^amssymb^SUCCEEDS ABOVE NOT EQUAL TO +02AB7^⪷^\precapprox^\precapprox^R^mathrel^amssymb^PRECEDES ABOVE ALMOST EQUAL TO +02AB8^⪸^\succapprox^\succapprox^R^mathrel^amssymb^SUCCEEDS ABOVE ALMOST EQUAL TO +02AB9^⪹^\precnapprox^\precnapprox^R^mathrel^amssymb^PRECEDES ABOVE NOT ALMOST EQUAL TO +02ABA^⪺^\succnapprox^\succnapprox^R^mathrel^amssymb^SUCCEEDS ABOVE NOT ALMOST EQUAL TO +02ABB^⪻^\llcurly^\Prec^R^mathrel^mathabx^DOUBLE PRECEDES +02ABC^⪼^\ggcurly^\Succ^R^mathrel^mathabx^DOUBLE SUCCEEDS +02ABD^⪽^^\subsetdot^R^mathrel^^SUBSET WITH DOT +02ABE^⪾^^\supsetdot^R^mathrel^^SUPERSET WITH DOT +02ABF^⪿^^\subsetplus^R^mathrel^^SUBSET WITH PLUS SIGN BELOW +02AC0^⫀^^\supsetplus^R^mathrel^^SUPERSET WITH PLUS SIGN BELOW +02AC1^⫁^^\submult^R^mathrel^^SUBSET WITH MULTIPLICATION SIGN BELOW +02AC2^⫂^^\supmult^R^mathrel^^SUPERSET WITH MULTIPLICATION SIGN BELOW +02AC3^⫃^^\subedot^R^mathrel^^SUBSET OF OR EQUAL TO WITH DOT ABOVE +02AC4^⫄^^\supedot^R^mathrel^^SUPERSET OF OR EQUAL TO WITH DOT ABOVE +02AC5^⫅^\subseteqq^\subseteqq^R^mathrel^amssymb^SUBSET OF ABOVE EQUALS SIGN +02AC6^⫆^\supseteqq^\supseteqq^R^mathrel^amssymb^SUPERSET OF ABOVE EQUALS SIGN +02AC7^⫇^^\subsim^R^mathrel^^SUBSET OF ABOVE TILDE OPERATOR +02AC8^⫈^^\supsim^R^mathrel^^SUPERSET OF ABOVE TILDE OPERATOR +02AC9^⫉^^\subsetapprox^R^mathrel^^SUBSET OF ABOVE ALMOST EQUAL TO +02ACA^⫊^^\supsetapprox^R^mathrel^^SUPERSET OF ABOVE ALMOST EQUAL TO +02ACB^⫋^\subsetneqq^\subsetneqq^R^mathrel^amssymb^SUBSET OF ABOVE NOT EQUAL TO +02ACC^⫌^\supsetneqq^\supsetneqq^R^mathrel^amssymb^SUPERSET OF ABOVE NOT EQUAL TO +02ACD^⫍^^\lsqhook^R^mathrel^^SQUARE LEFT OPEN BOX OPERATOR +02ACE^⫎^^\rsqhook^R^mathrel^^SQUARE RIGHT OPEN BOX OPERATOR +02ACF^⫏^^\csub^R^mathrel^^CLOSED SUBSET +02AD0^⫐^^\csup^R^mathrel^^CLOSED SUPERSET +02AD1^⫑^^\csube^R^mathrel^^CLOSED SUBSET OR EQUAL TO +02AD2^⫒^^\csupe^R^mathrel^^CLOSED SUPERSET OR EQUAL TO +02AD3^⫓^^\subsup^R^mathrel^^SUBSET ABOVE SUPERSET +02AD4^⫔^^\supsub^R^mathrel^^SUPERSET ABOVE SUBSET +02AD5^⫕^^\subsub^R^mathrel^^SUBSET ABOVE SUBSET +02AD6^⫖^^\supsup^R^mathrel^^SUPERSET ABOVE SUPERSET +02AD7^⫗^^\suphsub^R^mathrel^^SUPERSET BESIDE SUBSET +02AD8^⫘^^\supdsub^R^mathrel^^SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET +02AD9^⫙^^\forkv^R^mathrel^^ELEMENT OF OPENING DOWNWARDS +02ADA^⫚^^\topfork^R^mathrel^^PITCHFORK WITH TEE TOP +02ADB^⫛^^\mlcp^R^mathrel^^TRANSVERSAL INTERSECTION +02ADC^⫝̸^^\forks^R^mathrel^^FORKING +02ADD^⫝^^\forksnot^R^mathrel^^NONFORKING +02ADE^⫞^^\shortlefttack^R^mathrel^^SHORT LEFT TACK +02ADF^⫟^^\shortdowntack^R^mathrel^^SHORT DOWN TACK +02AE0^⫠^^\shortuptack^R^mathrel^^SHORT UP TACK +02AE1^⫡^^\perps^N^mathord^^PERPENDICULAR WITH S +02AE2^⫢^^\vDdash^R^mathrel^^VERTICAL BAR TRIPLE RIGHT TURNSTILE +02AE3^⫣^^\dashV^R^mathrel^^DOUBLE VERTICAL BAR LEFT TURNSTILE +02AE4^⫤^^\Dashv^R^mathrel^^VERTICAL BAR DOUBLE LEFT TURNSTILE +02AE5^⫥^^\DashV^R^mathrel^^DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE +02AE6^⫦^^\varVdash^R^mathrel^^LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL +02AE7^⫧^^\Barv^R^mathrel^^SHORT DOWN TACK WITH OVERBAR +02AE8^⫨^^\vBar^R^mathrel^^SHORT UP TACK WITH UNDERBAR +02AE9^⫩^^\vBarv^R^mathrel^^SHORT UP TACK ABOVE SHORT DOWN TACK +02AEA^⫪^\Top^\barV^R^mathrel^txfonts^DOUBLE DOWN TACK +02AEB^⫫^\Bot^\Vbar^R^mathrel^txfonts^= \Perp (txfonts), DOUBLE UP TACK +02AEC^⫬^^\Not^R^mathrel^^DOUBLE STROKE NOT SIGN +02AED^⫭^^\bNot^R^mathrel^^REVERSED DOUBLE STROKE NOT SIGN +02AEE^⫮^^\revnmid^R^mathrel^^DOES NOT DIVIDE WITH REVERSED NEGATION SLASH +02AEF^⫯^^\cirmid^R^mathrel^^VERTICAL LINE WITH CIRCLE ABOVE +02AF0^⫰^^\midcir^R^mathrel^^VERTICAL LINE WITH CIRCLE BELOW +02AF1^⫱^^\topcir^N^mathord^^DOWN TACK WITH CIRCLE BELOW +02AF2^⫲^^\nhpar^R^mathrel^^PARALLEL WITH HORIZONTAL STROKE +02AF3^⫳^^\parsim^R^mathrel^^PARALLEL WITH TILDE OPERATOR +02AF4^⫴^\interleave^\interleave^B^mathbin^stmaryrd^TRIPLE VERTICAL BAR BINARY RELATION +02AF5^⫵^^\nhVvert^B^mathbin^^TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE +02AF6^⫶^^\threedotcolon^B^mathbin^^TRIPLE COLON OPERATOR +02AF7^⫷^^\lllnest^R^mathrel^^TRIPLE NESTED LESS-THAN +02AF8^⫸^^\gggnest^R^mathrel^^TRIPLE NESTED GREATER-THAN +02AF9^⫹^^\leqqslant^R^mathrel^^DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO +02AFA^⫺^^\geqqslant^R^mathrel^^DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO +02AFB^⫻^^\trslash^B^mathbin^^TRIPLE SOLIDUS BINARY RELATION +02AFC^⫼^\biginterleave^\biginterleave^L^mathop^stmaryrd^LARGE TRIPLE VERTICAL BAR OPERATOR +02AFD^⫽^\sslash^\sslash^B^mathbin^stmaryrd^# \varparallel (txfonts), DOUBLE SOLIDUS OPERATOR +02AFE^⫾^\talloblong^\talloblong^B^mathbin^stmaryrd^WHITE VERTICAL BAR +02AFF^⫿^^\bigtalloblong^L^mathop^^N-ARY WHITE VERTICAL BAR +02B00^⬀^^^R?^mathord^^NORTH EAST WHITE ARROW +02B01^⬁^^^R?^mathord^^NORTH WEST WHITE ARROW +02B02^⬂^^^R?^mathord^^SOUTH EAST WHITE ARROW +02B03^⬃^^^R?^mathord^^SOUTH WEST WHITE ARROW +02B04^⬄^^^R?^mathord^^LEFT RIGHT WHITE ARROW +02B05^⬅^^^R?^mathord^^LEFTWARDS BLACK ARROW +02B06^⬆^^^R?^mathord^^UPWARDS BLACK ARROW +02B07^⬇^^^R?^mathord^^DOWNWARDS BLACK ARROW +02B08^⬈^^^R?^mathord^^NORTH EAST BLACK ARROW +02B09^⬉^^^R?^mathord^^NORTH WEST BLACK ARROW +02B0A^⬊^^^R?^mathord^^SOUTH EAST BLACK ARROW +02B0B^⬋^^^R?^mathord^^SOUTH WEST BLACK ARROW +02B0C^⬌^^^R?^mathord^^LEFT RIGHT BLACK ARROW +02B0D^⬍^^^R?^mathord^^UP DOWN BLACK ARROW +02B0E^⬎^^^R?^mathord^^RIGHTWARDS ARROW WITH TIP DOWNWARDS +02B0F^⬏^^^R?^mathord^^RIGHTWARDS ARROW WITH TIP UPWARDS +02B10^⬐^^^R?^mathord^^LEFTWARDS ARROW WITH TIP DOWNWARDS +02B11^⬑^^^R?^mathord^^LEFTWARDS ARROW WITH TIP UPWARDS +02B12^⬒^^\squaretopblack^N^mathord^^SQUARE WITH TOP HALF BLACK +02B13^⬓^^\squarebotblack^N^mathord^^SQUARE WITH BOTTOM HALF BLACK +02B14^⬔^^\squareurblack^N^mathord^^SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK +02B15^⬕^^\squarellblack^N^mathord^^SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK +02B16^⬖^^\diamondleftblack^N^mathord^^DIAMOND WITH LEFT HALF BLACK +02B17^⬗^^\diamondrightblack^N^mathord^^DIAMOND WITH RIGHT HALF BLACK +02B18^⬘^^\diamondtopblack^N^mathord^^DIAMOND WITH TOP HALF BLACK +02B19^⬙^^\diamondbotblack^N^mathord^^DIAMOND WITH BOTTOM HALF BLACK +02B1A^⬚^^\dottedsquare^^mathord^^DOTTED SQUARE +02B1B^⬛^\blacksquare^\lgblksquare^^mathord^fourier -amssymb^BLACK LARGE SQUARE +02B1C^⬜^\square^\lgwhtsquare^^mathord^fourier -amssymb^WHITE LARGE SQUARE +02B1D^⬝^^\vysmblksquare^^mathord^^# \centerdot (amssymb), t \Squaredot (marvosym), BLACK VERY SMALL SQUARE +02B1E^⬞^^\vysmwhtsquare^^mathord^^WHITE VERY SMALL SQUARE +02B1F^⬟^^\pentagonblack^^mathord^^BLACK PENTAGON +02B20^⬠^^\pentagon^N^mathord^^WHITE PENTAGON +02B21^⬡^^\varhexagon^N^mathord^^WHITE HEXAGON +02B22^⬢^^\varhexagonblack^N^mathord^^BLACK HEXAGON +02B23^⬣^^\hexagonblack^N^mathord^^HORIZONTAL BLACK HEXAGON +02B24^⬤^^\lgblkcircle^^mathord^^BLACK LARGE CIRCLE +02B25^⬥^^\mdblkdiamond^^mathord^^BLACK MEDIUM DIAMOND +02B26^⬦^^\mdwhtdiamond^^mathord^^WHITE MEDIUM DIAMOND +02B27^⬧^^\mdblklozenge^^mathord^^# \blacklozenge (amssymb), BLACK MEDIUM LOZENGE +02B28^⬨^^\mdwhtlozenge^^mathord^^# \lozenge (amssymb), WHITE MEDIUM LOZENGE +02B29^⬩^^\smblkdiamond^^mathord^^BLACK SMALL DIAMOND +02B2A^⬪^^\smblklozenge^^mathord^^BLACK SMALL LOZENGE +02B2B^⬫^^\smwhtlozenge^^mathord^^WHITE SMALL LOZENGE +02B2C^⬬^^\blkhorzoval^^mathord^^BLACK HORIZONTAL ELLIPSE +02B2D^⬭^^\whthorzoval^^mathord^^WHITE HORIZONTAL ELLIPSE +02B2E^⬮^^\blkvertoval^^mathord^^BLACK VERTICAL ELLIPSE +02B2F^⬯^^\whtvertoval^^mathord^^WHITE VERTICAL ELLIPSE +02B30^⬰^^\circleonleftarrow^^mathrel^^LEFT ARROW WITH SMALL CIRCLE +02B31^⬱^^\leftthreearrows^^mathrel^^THREE LEFTWARDS ARROWS +02B32^⬲^^\leftarrowonoplus^^mathrel^^LEFT ARROW WITH CIRCLED PLUS +02B33^⬳^^\longleftsquigarrow^^mathrel^^LONG LEFTWARDS SQUIGGLE ARROW +02B34^⬴^^\nvtwoheadleftarrow^^mathrel^^LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE +02B35^⬵^^\nVtwoheadleftarrow^^mathrel^^LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE +02B36^⬶^^\twoheadmapsfrom^^mathrel^^LEFTWARDS TWO-HEADED ARROW FROM BAR +02B37^⬷^^\twoheadleftdbkarrow^^mathrel^^leftwards two-headed triple-dash arrow +02B38^⬸^^\leftdotarrow^^mathrel^^LEFTWARDS ARROW WITH DOTTED STEM +02B39^⬹^^\nvleftarrowtail^^mathrel^^LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE +02B3A^⬺^^\nVleftarrowtail^^mathrel^^LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE +02B3B^⬻^^\twoheadleftarrowtail^^mathrel^^LEFTWARDS TWO-HEADED ARROW WITH TAIL +02B3C^⬼^^\nvtwoheadleftarrowtail^^mathrel^^LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE +02B3D^⬽^^\nVtwoheadleftarrowtail^^mathrel^^LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE +02B3E^⬾^^\leftarrowx^^mathrel^^LEFTWARDS ARROW THROUGH X +02B3F^⬿^^\leftcurvedarrow^^mathrel^^WAVE ARROW POINTING DIRECTLY LEFT +02B40^⭀^^\equalleftarrow^^mathrel^^EQUALS SIGN ABOVE LEFTWARDS ARROW +02B41^⭁^^\bsimilarleftarrow^^mathrel^^REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW +02B42^⭂^^\leftarrowbackapprox^^mathrel^^LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO +02B43^⭃^^\rightarrowgtr^^mathrel^^rightwards arrow through less-than +02B44^⭄^^\rightarrowsupset^^mathrel^^rightwards arrow through subset +02B45^⭅^^\LLeftarrow^^mathrel^^LEFTWARDS QUADRUPLE ARROW +02B46^⭆^^\RRightarrow^^mathrel^^RIGHTWARDS QUADRUPLE ARROW +02B47^⭇^^\bsimilarrightarrow^^mathrel^^REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW +02B48^⭈^^\rightarrowbackapprox^^mathrel^^RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO +02B49^⭉^^\similarleftarrow^^mathrel^^TILDE OPERATOR ABOVE LEFTWARDS ARROW +02B4A^⭊^^\leftarrowapprox^^mathrel^^LEFTWARDS ARROW ABOVE ALMOST EQUAL TO +02B4B^⭋^^\leftarrowbsimilar^^mathrel^^LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR +02B4C^⭌^^\rightarrowbsimilar^^mathrel^^righttwards arrow above reverse tilde operator +02B50^⭐^^\medwhitestar^^mathord^^WHITE MEDIUM STAR +02B51^⭑^^\medblackstar^^mathord^^black medium star +02B52^⭒^^\smwhitestar^^mathord^^WHITE SMALL STAR +02B53^⭓^^\rightpentagonblack^^mathord^^BLACK RIGHT-POINTING PENTAGON +02B54^⭔^^\rightpentagon^^mathord^^WHITE RIGHT-POINTING PENTAGON +03008^〈^^^X^mathopen^^# \langle, LEFT ANGLE BRACKET (deprecated for math use) +03009^〉^^^X^mathclose^^# \rangle, RIGHT ANGLE BRACKET (deprecated for math use) +03012^〒^^\postalmark^^mathord^^POSTAL MARK +03014^〔^^\lbrbrak^^mathopen^^left broken bracket +03015^〕^^\rbrbrak^^mathclose^^right broken bracket +03018^〘^^\Lbrbrak^^mathopen^^LEFT WHITE TORTOISE SHELL BRACKET +03019^〙^^\Rbrbrak^^mathclose^^RIGHT WHITE TORTOISE SHELL BRACKET +0301A^〚^^^X^mathopen^^# \llbracket (stmaryrd), LEFT WHITE SQUARE BRACKET (deprecated for math use) +0301B^〛^^^X^mathclose^^# \rrbracket (stmaryrd), RIGHT WHITE SQUARE BRACKET (deprecated for math use) +03030^〰^^\hzigzag^^mathord^^zigzag +0306E^の^^^N^mathalpha^^HIRAGANA LETTER NO +0FB29^﬩^^^X^mathord^^HEBREW LETTER ALTERNATIVE PLUS SIGN (doesn't have cross shape) +0FE00^︀^^^D^mathaccent^^VARIATION SELECTOR-1 +0FE61^﹡^^^X^^^SMALL ASTERISK +0FE62^﹢^^^X^mathord^^SMALL PLUS SIGN +0FE63^﹣^^^X^mathord^^SMALL HYPHEN-MINUS +0FE64^﹤^^^X^mathord^^SMALL LESS-THAN SIGN +0FE65^﹥^^^X^mathord^^SMALL GREATER-THAN SIGN +0FE66^﹦^^^X^mathord^^SMALL EQUALS SIGN +0FE68^﹨^^^X^^^SMALL REVERSE SOLIDUS +0FF0B^+^^^X^mathord^^FULLWIDTH PLUS SIGN +0FF1C^<^^^X^mathord^^FULLWIDTH LESS-THAN SIGN +0FF1D^=^^^X^mathord^^FULLWIDTH EQUALS SIGN +0FF1E^>^^^X^mathord^^FULLWIDTH GREATER-THAN SIGN +0FF3C^\^^^X^^^FULLWIDTH REVERSE SOLIDUS +0FF3E^^^^^X^mathord^^FULLWIDTH CIRCUMFLEX ACCENT +0FF5C^|^^^X^mathord^^FULLWIDTH VERTICAL LINE +0FF5E^~^^^X^mathord^^FULLWIDTH TILDE +0FFE2^¬^^^X^mathord^^FULLWIDTH NOT SIGN +0FFE9^←^^^X^mathord^^HALFWIDTH LEFTWARDS ARROW +0FFEA^↑^^^X^mathord^^HALFWIDTH UPWARDS ARROW +0FFEB^→^^^X^mathord^^HALFWIDTH RIGHTWARDS ARROW +0FFEC^↓^^^X^mathord^^HALFWIDTH DOWNWARDS ARROW +1D400^𝐀^\mathbf{A}^\mbfA^A^mathalpha^^MATHEMATICAL BOLD CAPITAL A +1D401^𝐁^\mathbf{B}^\mbfB^A^mathalpha^^MATHEMATICAL BOLD CAPITAL B +1D402^𝐂^\mathbf{C}^\mbfC^A^mathalpha^^MATHEMATICAL BOLD CAPITAL C +1D403^𝐃^\mathbf{D}^\mbfD^A^mathalpha^^MATHEMATICAL BOLD CAPITAL D +1D404^𝐄^\mathbf{E}^\mbfE^A^mathalpha^^MATHEMATICAL BOLD CAPITAL E +1D405^𝐅^\mathbf{F}^\mbfF^A^mathalpha^^MATHEMATICAL BOLD CAPITAL F +1D406^𝐆^\mathbf{G}^\mbfG^A^mathalpha^^MATHEMATICAL BOLD CAPITAL G +1D407^𝐇^\mathbf{H}^\mbfH^A^mathalpha^^MATHEMATICAL BOLD CAPITAL H +1D408^𝐈^\mathbf{I}^\mbfI^A^mathalpha^^MATHEMATICAL BOLD CAPITAL I +1D409^𝐉^\mathbf{J}^\mbfJ^A^mathalpha^^MATHEMATICAL BOLD CAPITAL J +1D40A^𝐊^\mathbf{K}^\mbfK^A^mathalpha^^MATHEMATICAL BOLD CAPITAL K +1D40B^𝐋^\mathbf{L}^\mbfL^A^mathalpha^^MATHEMATICAL BOLD CAPITAL L +1D40C^𝐌^\mathbf{M}^\mbfM^A^mathalpha^^MATHEMATICAL BOLD CAPITAL M +1D40D^𝐍^\mathbf{N}^\mbfN^A^mathalpha^^MATHEMATICAL BOLD CAPITAL N +1D40E^𝐎^\mathbf{O}^\mbfO^A^mathalpha^^MATHEMATICAL BOLD CAPITAL O +1D40F^𝐏^\mathbf{P}^\mbfP^A^mathalpha^^MATHEMATICAL BOLD CAPITAL P +1D410^𝐐^\mathbf{Q}^\mbfQ^A^mathalpha^^MATHEMATICAL BOLD CAPITAL Q +1D411^𝐑^\mathbf{R}^\mbfR^A^mathalpha^^MATHEMATICAL BOLD CAPITAL R +1D412^𝐒^\mathbf{S}^\mbfS^A^mathalpha^^MATHEMATICAL BOLD CAPITAL S +1D413^𝐓^\mathbf{T}^\mbfT^A^mathalpha^^MATHEMATICAL BOLD CAPITAL T +1D414^𝐔^\mathbf{U}^\mbfU^A^mathalpha^^MATHEMATICAL BOLD CAPITAL U +1D415^𝐕^\mathbf{V}^\mbfV^A^mathalpha^^MATHEMATICAL BOLD CAPITAL V +1D416^𝐖^\mathbf{W}^\mbfW^A^mathalpha^^MATHEMATICAL BOLD CAPITAL W +1D417^𝐗^\mathbf{X}^\mbfX^A^mathalpha^^MATHEMATICAL BOLD CAPITAL X +1D418^𝐘^\mathbf{Y}^\mbfY^A^mathalpha^^MATHEMATICAL BOLD CAPITAL Y +1D419^𝐙^\mathbf{Z}^\mbfZ^A^mathalpha^^MATHEMATICAL BOLD CAPITAL Z +1D41A^𝐚^\mathbf{a}^\mbfa^A^mathalpha^^MATHEMATICAL BOLD SMALL A +1D41B^𝐛^\mathbf{b}^\mbfb^A^mathalpha^^MATHEMATICAL BOLD SMALL B +1D41C^𝐜^\mathbf{c}^\mbfc^A^mathalpha^^MATHEMATICAL BOLD SMALL C +1D41D^𝐝^\mathbf{d}^\mbfd^A^mathalpha^^MATHEMATICAL BOLD SMALL D +1D41E^𝐞^\mathbf{e}^\mbfe^A^mathalpha^^MATHEMATICAL BOLD SMALL E +1D41F^𝐟^\mathbf{f}^\mbff^A^mathalpha^^MATHEMATICAL BOLD SMALL F +1D420^𝐠^\mathbf{g}^\mbfg^A^mathalpha^^MATHEMATICAL BOLD SMALL G +1D421^𝐡^\mathbf{h}^\mbfh^A^mathalpha^^MATHEMATICAL BOLD SMALL H +1D422^𝐢^\mathbf{i}^\mbfi^A^mathalpha^^MATHEMATICAL BOLD SMALL I +1D423^𝐣^\mathbf{j}^\mbfj^A^mathalpha^^MATHEMATICAL BOLD SMALL J +1D424^𝐤^\mathbf{k}^\mbfk^A^mathalpha^^MATHEMATICAL BOLD SMALL K +1D425^𝐥^\mathbf{l}^\mbfl^A^mathalpha^^MATHEMATICAL BOLD SMALL L +1D426^𝐦^\mathbf{m}^\mbfm^A^mathalpha^^MATHEMATICAL BOLD SMALL M +1D427^𝐧^\mathbf{n}^\mbfn^A^mathalpha^^MATHEMATICAL BOLD SMALL N +1D428^𝐨^\mathbf{o}^\mbfo^A^mathalpha^^MATHEMATICAL BOLD SMALL O +1D429^𝐩^\mathbf{p}^\mbfp^A^mathalpha^^MATHEMATICAL BOLD SMALL P +1D42A^𝐪^\mathbf{q}^\mbfq^A^mathalpha^^MATHEMATICAL BOLD SMALL Q +1D42B^𝐫^\mathbf{r}^\mbfr^A^mathalpha^^MATHEMATICAL BOLD SMALL R +1D42C^𝐬^\mathbf{s}^\mbfs^A^mathalpha^^MATHEMATICAL BOLD SMALL S +1D42D^𝐭^\mathbf{t}^\mbft^A^mathalpha^^MATHEMATICAL BOLD SMALL T +1D42E^𝐮^\mathbf{u}^\mbfu^A^mathalpha^^MATHEMATICAL BOLD SMALL U +1D42F^𝐯^\mathbf{v}^\mbfv^A^mathalpha^^MATHEMATICAL BOLD SMALL V +1D430^𝐰^\mathbf{w}^\mbfw^A^mathalpha^^MATHEMATICAL BOLD SMALL W +1D431^𝐱^\mathbf{x}^\mbfx^A^mathalpha^^MATHEMATICAL BOLD SMALL X +1D432^𝐲^\mathbf{y}^\mbfy^A^mathalpha^^MATHEMATICAL BOLD SMALL Y +1D433^𝐳^\mathbf{z}^\mbfz^A^mathalpha^^MATHEMATICAL BOLD SMALL Z +1D434^𝐴^A^\mitA^A^mathalpha^-frenchstyle^= \mathit{A}, MATHEMATICAL ITALIC CAPITAL A +1D435^𝐵^B^\mitB^A^mathalpha^-frenchstyle^= \mathit{B}, MATHEMATICAL ITALIC CAPITAL B +1D436^𝐶^C^\mitC^A^mathalpha^-frenchstyle^= \mathit{C}, MATHEMATICAL ITALIC CAPITAL C +1D437^𝐷^D^\mitD^A^mathalpha^-frenchstyle^= \mathit{D}, MATHEMATICAL ITALIC CAPITAL D +1D438^𝐸^E^\mitE^A^mathalpha^-frenchstyle^= \mathit{E}, MATHEMATICAL ITALIC CAPITAL E +1D439^𝐹^F^\mitF^A^mathalpha^-frenchstyle^= \mathit{F}, MATHEMATICAL ITALIC CAPITAL F +1D43A^𝐺^G^\mitG^A^mathalpha^-frenchstyle^= \mathit{G}, MATHEMATICAL ITALIC CAPITAL G +1D43B^𝐻^H^\mitH^A^mathalpha^-frenchstyle^= \mathit{H}, MATHEMATICAL ITALIC CAPITAL H +1D43C^𝐼^I^\mitI^A^mathalpha^-frenchstyle^= \mathit{I}, MATHEMATICAL ITALIC CAPITAL I +1D43D^𝐽^J^\mitJ^A^mathalpha^-frenchstyle^= \mathit{J}, MATHEMATICAL ITALIC CAPITAL J +1D43E^𝐾^K^\mitK^A^mathalpha^-frenchstyle^= \mathit{K}, MATHEMATICAL ITALIC CAPITAL K +1D43F^𝐿^L^\mitL^A^mathalpha^-frenchstyle^= \mathit{L}, MATHEMATICAL ITALIC CAPITAL L +1D440^𝑀^M^\mitM^A^mathalpha^-frenchstyle^= \mathit{M}, MATHEMATICAL ITALIC CAPITAL M +1D441^𝑁^N^\mitN^A^mathalpha^-frenchstyle^= \mathit{N}, MATHEMATICAL ITALIC CAPITAL N +1D442^𝑂^O^\mitO^A^mathalpha^-frenchstyle^= \mathit{O}, MATHEMATICAL ITALIC CAPITAL O +1D443^𝑃^P^\mitP^A^mathalpha^-frenchstyle^= \mathit{P}, MATHEMATICAL ITALIC CAPITAL P +1D444^𝑄^Q^\mitQ^A^mathalpha^-frenchstyle^= \mathit{Q}, MATHEMATICAL ITALIC CAPITAL Q +1D445^𝑅^R^\mitR^A^mathalpha^-frenchstyle^= \mathit{R}, MATHEMATICAL ITALIC CAPITAL R +1D446^𝑆^S^\mitS^A^mathalpha^-frenchstyle^= \mathit{S}, MATHEMATICAL ITALIC CAPITAL S +1D447^𝑇^T^\mitT^A^mathalpha^-frenchstyle^= \mathit{T}, MATHEMATICAL ITALIC CAPITAL T +1D448^𝑈^U^\mitU^A^mathalpha^-frenchstyle^= \mathit{U}, MATHEMATICAL ITALIC CAPITAL U +1D449^𝑉^V^\mitV^A^mathalpha^-frenchstyle^= \mathit{V}, MATHEMATICAL ITALIC CAPITAL V +1D44A^𝑊^W^\mitW^A^mathalpha^-frenchstyle^= \mathit{W}, MATHEMATICAL ITALIC CAPITAL W +1D44B^𝑋^X^\mitX^A^mathalpha^-frenchstyle^= \mathit{X}, MATHEMATICAL ITALIC CAPITAL X +1D44C^𝑌^Y^\mitY^A^mathalpha^-frenchstyle^= \mathit{Y}, MATHEMATICAL ITALIC CAPITAL Y +1D44D^𝑍^Z^\mitZ^A^mathalpha^-frenchstyle^= \mathit{Z}, MATHEMATICAL ITALIC CAPITAL Z +1D44E^𝑎^a^\mita^A^mathalpha^-uprightstyle^= \mathit{a}, MATHEMATICAL ITALIC SMALL A +1D44F^𝑏^b^\mitb^A^mathalpha^-uprightstyle^= \mathit{b}, MATHEMATICAL ITALIC SMALL B +1D450^𝑐^c^\mitc^A^mathalpha^-uprightstyle^= \mathit{c}, MATHEMATICAL ITALIC SMALL C +1D451^𝑑^d^\mitd^A^mathalpha^-uprightstyle^= \mathit{d}, MATHEMATICAL ITALIC SMALL D +1D452^𝑒^e^\mite^A^mathalpha^-uprightstyle^= \mathit{e}, MATHEMATICAL ITALIC SMALL E +1D453^𝑓^f^\mitf^A^mathalpha^-uprightstyle^= \mathit{f}, MATHEMATICAL ITALIC SMALL F +1D454^𝑔^g^\mitg^A^mathalpha^-uprightstyle^= \mathit{g}, MATHEMATICAL ITALIC SMALL G +1D456^𝑖^i^\miti^A^mathalpha^-uprightstyle^= \mathit{i}, MATHEMATICAL ITALIC SMALL I +1D457^𝑗^j^\mitj^A^mathalpha^-uprightstyle^= \mathit{j}, MATHEMATICAL ITALIC SMALL J +1D458^𝑘^k^\mitk^A^mathalpha^-uprightstyle^= \mathit{k}, MATHEMATICAL ITALIC SMALL K +1D459^𝑙^l^\mitl^A^mathalpha^-uprightstyle^= \mathit{l}, MATHEMATICAL ITALIC SMALL L +1D45A^𝑚^m^\mitm^A^mathalpha^-uprightstyle^= \mathit{m}, MATHEMATICAL ITALIC SMALL M +1D45B^𝑛^n^\mitn^A^mathalpha^-uprightstyle^= \mathit{n}, MATHEMATICAL ITALIC SMALL N +1D45C^𝑜^o^\mito^A^mathalpha^-uprightstyle^= \mathit{o}, MATHEMATICAL ITALIC SMALL O +1D45D^𝑝^p^\mitp^A^mathalpha^-uprightstyle^= \mathit{p}, MATHEMATICAL ITALIC SMALL P +1D45E^𝑞^q^\mitq^A^mathalpha^-uprightstyle^= \mathit{q}, MATHEMATICAL ITALIC SMALL Q +1D45F^𝑟^r^\mitr^A^mathalpha^-uprightstyle^= \mathit{r}, MATHEMATICAL ITALIC SMALL R +1D460^𝑠^s^\mits^A^mathalpha^-uprightstyle^= \mathit{s}, MATHEMATICAL ITALIC SMALL S +1D461^𝑡^t^\mitt^A^mathalpha^-uprightstyle^= \mathit{t}, MATHEMATICAL ITALIC SMALL T +1D462^𝑢^u^\mitu^A^mathalpha^-uprightstyle^= \mathit{u}, MATHEMATICAL ITALIC SMALL U +1D463^𝑣^v^\mitv^A^mathalpha^-uprightstyle^= \mathit{v}, MATHEMATICAL ITALIC SMALL V +1D464^𝑤^w^\mitw^A^mathalpha^-uprightstyle^= \mathit{w}, MATHEMATICAL ITALIC SMALL W +1D465^𝑥^x^\mitx^A^mathalpha^-uprightstyle^= \mathit{x}, MATHEMATICAL ITALIC SMALL X +1D466^𝑦^y^\mity^A^mathalpha^-uprightstyle^= \mathit{y}, MATHEMATICAL ITALIC SMALL Y +1D467^𝑧^z^\mitz^A^mathalpha^-uprightstyle^= \mathit{z}, MATHEMATICAL ITALIC SMALL Z +1D468^𝑨^\mathbfit{A}^\mbfitA^A^mathalpha^isomath^= \mathbold{A} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL A +1D469^𝑩^\mathbfit{B}^\mbfitB^A^mathalpha^isomath^= \mathbold{B} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL B +1D46A^𝑪^\mathbfit{C}^\mbfitC^A^mathalpha^isomath^= \mathbold{C} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL C +1D46B^𝑫^\mathbfit{D}^\mbfitD^A^mathalpha^isomath^= \mathbold{D} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL D +1D46C^𝑬^\mathbfit{E}^\mbfitE^A^mathalpha^isomath^= \mathbold{E} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL E +1D46D^𝑭^\mathbfit{F}^\mbfitF^A^mathalpha^isomath^= \mathbold{F} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL F +1D46E^𝑮^\mathbfit{G}^\mbfitG^A^mathalpha^isomath^= \mathbold{G} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL G +1D46F^𝑯^\mathbfit{H}^\mbfitH^A^mathalpha^isomath^= \mathbold{H} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL H +1D470^𝑰^\mathbfit{I}^\mbfitI^A^mathalpha^isomath^= \mathbold{I} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL I +1D471^𝑱^\mathbfit{J}^\mbfitJ^A^mathalpha^isomath^= \mathbold{J} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL J +1D472^𝑲^\mathbfit{K}^\mbfitK^A^mathalpha^isomath^= \mathbold{K} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL K +1D473^𝑳^\mathbfit{L}^\mbfitL^A^mathalpha^isomath^= \mathbold{L} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL L +1D474^𝑴^\mathbfit{M}^\mbfitM^A^mathalpha^isomath^= \mathbold{M} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL M +1D475^𝑵^\mathbfit{N}^\mbfitN^A^mathalpha^isomath^= \mathbold{N} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL N +1D476^𝑶^\mathbfit{O}^\mbfitO^A^mathalpha^isomath^= \mathbold{O} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL O +1D477^𝑷^\mathbfit{P}^\mbfitP^A^mathalpha^isomath^= \mathbold{P} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL P +1D478^𝑸^\mathbfit{Q}^\mbfitQ^A^mathalpha^isomath^= \mathbold{Q} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL Q +1D479^𝑹^\mathbfit{R}^\mbfitR^A^mathalpha^isomath^= \mathbold{R} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL R +1D47A^𝑺^\mathbfit{S}^\mbfitS^A^mathalpha^isomath^= \mathbold{S} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL S +1D47B^𝑻^\mathbfit{T}^\mbfitT^A^mathalpha^isomath^= \mathbold{T} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL T +1D47C^𝑼^\mathbfit{U}^\mbfitU^A^mathalpha^isomath^= \mathbold{U} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL U +1D47D^𝑽^\mathbfit{V}^\mbfitV^A^mathalpha^isomath^= \mathbold{V} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL V +1D47E^𝑾^\mathbfit{W}^\mbfitW^A^mathalpha^isomath^= \mathbold{W} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL W +1D47F^𝑿^\mathbfit{X}^\mbfitX^A^mathalpha^isomath^= \mathbold{X} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL X +1D480^𝒀^\mathbfit{Y}^\mbfitY^A^mathalpha^isomath^= \mathbold{Y} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL Y +1D481^𝒁^\mathbfit{Z}^\mbfitZ^A^mathalpha^isomath^= \mathbold{Z} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL Z +1D482^𝒂^\mathbfit{a}^\mbfita^A^mathalpha^isomath^= \mathbold{a} (fixmath), MATHEMATICAL BOLD ITALIC SMALL A +1D483^𝒃^\mathbfit{b}^\mbfitb^A^mathalpha^isomath^= \mathbold{b} (fixmath), MATHEMATICAL BOLD ITALIC SMALL B +1D484^𝒄^\mathbfit{c}^\mbfitc^A^mathalpha^isomath^= \mathbold{c} (fixmath), MATHEMATICAL BOLD ITALIC SMALL C +1D485^𝒅^\mathbfit{d}^\mbfitd^A^mathalpha^isomath^= \mathbold{d} (fixmath), MATHEMATICAL BOLD ITALIC SMALL D +1D486^𝒆^\mathbfit{e}^\mbfite^A^mathalpha^isomath^= \mathbold{e} (fixmath), MATHEMATICAL BOLD ITALIC SMALL E +1D487^𝒇^\mathbfit{f}^\mbfitf^A^mathalpha^isomath^= \mathbold{f} (fixmath), MATHEMATICAL BOLD ITALIC SMALL F +1D488^𝒈^\mathbfit{g}^\mbfitg^A^mathalpha^isomath^= \mathbold{g} (fixmath), MATHEMATICAL BOLD ITALIC SMALL G +1D489^𝒉^\mathbfit{h}^\mbfith^A^mathalpha^isomath^= \mathbold{h} (fixmath), MATHEMATICAL BOLD ITALIC SMALL H +1D48A^𝒊^\mathbfit{i}^\mbfiti^A^mathalpha^isomath^= \mathbold{i} (fixmath), MATHEMATICAL BOLD ITALIC SMALL I +1D48B^𝒋^\mathbfit{j}^\mbfitj^A^mathalpha^isomath^= \mathbold{j} (fixmath), MATHEMATICAL BOLD ITALIC SMALL J +1D48C^𝒌^\mathbfit{k}^\mbfitk^A^mathalpha^isomath^= \mathbold{k} (fixmath), MATHEMATICAL BOLD ITALIC SMALL K +1D48D^𝒍^\mathbfit{l}^\mbfitl^A^mathalpha^isomath^= \mathbold{l} (fixmath), MATHEMATICAL BOLD ITALIC SMALL L +1D48E^𝒎^\mathbfit{m}^\mbfitm^A^mathalpha^isomath^= \mathbold{m} (fixmath), MATHEMATICAL BOLD ITALIC SMALL M +1D48F^𝒏^\mathbfit{n}^\mbfitn^A^mathalpha^isomath^= \mathbold{n} (fixmath), MATHEMATICAL BOLD ITALIC SMALL N +1D490^𝒐^\mathbfit{o}^\mbfito^A^mathalpha^isomath^= \mathbold{o} (fixmath), MATHEMATICAL BOLD ITALIC SMALL O +1D491^𝒑^\mathbfit{p}^\mbfitp^A^mathalpha^isomath^= \mathbold{p} (fixmath), MATHEMATICAL BOLD ITALIC SMALL P +1D492^𝒒^\mathbfit{q}^\mbfitq^A^mathalpha^isomath^= \mathbold{q} (fixmath), MATHEMATICAL BOLD ITALIC SMALL Q +1D493^𝒓^\mathbfit{r}^\mbfitr^A^mathalpha^isomath^= \mathbold{r} (fixmath), MATHEMATICAL BOLD ITALIC SMALL R +1D494^𝒔^\mathbfit{s}^\mbfits^A^mathalpha^isomath^= \mathbold{s} (fixmath), MATHEMATICAL BOLD ITALIC SMALL S +1D495^𝒕^\mathbfit{t}^\mbfitt^A^mathalpha^isomath^= \mathbold{t} (fixmath), MATHEMATICAL BOLD ITALIC SMALL T +1D496^𝒖^\mathbfit{u}^\mbfitu^A^mathalpha^isomath^= \mathbold{u} (fixmath), MATHEMATICAL BOLD ITALIC SMALL U +1D497^𝒗^\mathbfit{v}^\mbfitv^A^mathalpha^isomath^= \mathbold{v} (fixmath), MATHEMATICAL BOLD ITALIC SMALL V +1D498^𝒘^\mathbfit{w}^\mbfitw^A^mathalpha^isomath^= \mathbold{w} (fixmath), MATHEMATICAL BOLD ITALIC SMALL W +1D499^𝒙^\mathbfit{x}^\mbfitx^A^mathalpha^isomath^= \mathbold{x} (fixmath), MATHEMATICAL BOLD ITALIC SMALL X +1D49A^𝒚^\mathbfit{y}^\mbfity^A^mathalpha^isomath^= \mathbold{y} (fixmath), MATHEMATICAL BOLD ITALIC SMALL Y +1D49B^𝒛^\mathbfit{z}^\mbfitz^A^mathalpha^isomath^= \mathbold{z} (fixmath), MATHEMATICAL BOLD ITALIC SMALL Z +1D49C^𝒜^\mathcal{A}^\mscrA^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL A +1D49E^𝒞^\mathcal{C}^\mscrC^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL C +1D49F^𝒟^\mathcal{D}^\mscrD^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL D +1D4A2^𝒢^\mathcal{G}^\mscrG^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL G +1D4A5^𝒥^\mathcal{J}^\mscrJ^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL J +1D4A6^𝒦^\mathcal{K}^\mscrK^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL K +1D4A9^𝒩^\mathcal{N}^\mscrN^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL N +1D4AA^𝒪^\mathcal{O}^\mscrO^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL O +1D4AB^𝒫^\mathcal{P}^\mscrP^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL P +1D4AC^𝒬^\mathcal{Q}^\mscrQ^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL Q +1D4AE^𝒮^\mathcal{S}^\mscrS^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL S +1D4AF^𝒯^\mathcal{T}^\mscrT^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL T +1D4B0^𝒰^\mathcal{U}^\mscrU^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL U +1D4B1^𝒱^\mathcal{V}^\mscrV^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL V +1D4B2^𝒲^\mathcal{W}^\mscrW^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL W +1D4B3^𝒳^\mathcal{X}^\mscrX^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL X +1D4B4^𝒴^\mathcal{Y}^\mscrY^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL Y +1D4B5^𝒵^\mathcal{Z}^\mscrZ^A^mathalpha^^MATHEMATICAL SCRIPT CAPITAL Z +1D4B6^𝒶^\mathcal{a}^\mscra^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL A +1D4B7^𝒷^\mathcal{b}^\mscrb^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL B +1D4B8^𝒸^\mathcal{c}^\mscrc^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL C +1D4B9^𝒹^\mathcal{d}^\mscrd^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL D +1D4BB^𝒻^\mathcal{f}^\mscrf^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL F +1D4BD^𝒽^\mathcal{h}^\mscrh^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL H +1D4BE^𝒾^\mathcal{i}^\mscri^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL I +1D4BF^𝒿^\mathcal{j}^\mscrj^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL J +1D4C0^𝓀^\mathcal{k}^\mscrk^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL K +1D4C1^𝓁^\mathcal{l}^\mscrl^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL L +1D4C2^𝓂^\mathcal{m}^\mscrm^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL M +1D4C3^𝓃^\mathcal{n}^\mscrn^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL N +1D4C5^𝓅^\mathcal{p}^\mscrp^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL P +1D4C6^𝓆^\mathcal{q}^\mscrq^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL Q +1D4C7^𝓇^\mathcal{r}^\mscrr^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL R +1D4C8^𝓈^\mathcal{s}^\mscrs^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL S +1D4C9^𝓉^\mathcal{t}^\mscrt^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL T +1D4CA^𝓊^\mathcal{u}^\mscru^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL U +1D4CB^𝓋^\mathcal{v}^\mscrv^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL V +1D4CC^𝓌^\mathcal{w}^\mscrw^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL W +1D4CD^𝓍^\mathcal{x}^\mscrx^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL X +1D4CE^𝓎^\mathcal{y}^\mscry^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL Y +1D4CF^𝓏^\mathcal{z}^\mscrz^A^mathalpha^urwchancal^MATHEMATICAL SCRIPT SMALL Z +1D4D0^𝓐^^\mbfscrA^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL A +1D4D1^𝓑^^\mbfscrB^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL B +1D4D2^𝓒^^\mbfscrC^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL C +1D4D3^𝓓^^\mbfscrD^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL D +1D4D4^𝓔^^\mbfscrE^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL E +1D4D5^𝓕^^\mbfscrF^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL F +1D4D6^𝓖^^\mbfscrG^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL G +1D4D7^𝓗^^\mbfscrH^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL H +1D4D8^𝓘^^\mbfscrI^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL I +1D4D9^𝓙^^\mbfscrJ^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL J +1D4DA^𝓚^^\mbfscrK^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL K +1D4DB^𝓛^^\mbfscrL^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL L +1D4DC^𝓜^^\mbfscrM^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL M +1D4DD^𝓝^^\mbfscrN^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL N +1D4DE^𝓞^^\mbfscrO^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL O +1D4DF^𝓟^^\mbfscrP^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL P +1D4E0^𝓠^^\mbfscrQ^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL Q +1D4E1^𝓡^^\mbfscrR^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL R +1D4E2^𝓢^^\mbfscrS^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL S +1D4E3^𝓣^^\mbfscrT^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL T +1D4E4^𝓤^^\mbfscrU^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL U +1D4E5^𝓥^^\mbfscrV^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL V +1D4E6^𝓦^^\mbfscrW^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL W +1D4E7^𝓧^^\mbfscrX^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL X +1D4E8^𝓨^^\mbfscrY^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL Y +1D4E9^𝓩^^\mbfscrZ^A^mathalpha^^MATHEMATICAL BOLD SCRIPT CAPITAL Z +1D4EA^𝓪^^\mbfscra^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL A +1D4EB^𝓫^^\mbfscrb^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL B +1D4EC^𝓬^^\mbfscrc^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL C +1D4ED^𝓭^^\mbfscrd^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL D +1D4EE^𝓮^^\mbfscre^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL E +1D4EF^𝓯^^\mbfscrf^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL F +1D4F0^𝓰^^\mbfscrg^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL G +1D4F1^𝓱^^\mbfscrh^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL H +1D4F2^𝓲^^\mbfscri^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL I +1D4F3^𝓳^^\mbfscrj^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL J +1D4F4^𝓴^^\mbfscrk^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL K +1D4F5^𝓵^^\mbfscrl^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL L +1D4F6^𝓶^^\mbfscrm^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL M +1D4F7^𝓷^^\mbfscrn^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL N +1D4F8^𝓸^^\mbfscro^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL O +1D4F9^𝓹^^\mbfscrp^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL P +1D4FA^𝓺^^\mbfscrq^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL Q +1D4FB^𝓻^^\mbfscrr^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL R +1D4FC^𝓼^^\mbfscrs^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL S +1D4FD^𝓽^^\mbfscrt^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL T +1D4FE^𝓾^^\mbfscru^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL U +1D4FF^𝓿^^\mbfscrv^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL V +1D500^𝔀^^\mbfscrw^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL W +1D501^𝔁^^\mbfscrx^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL X +1D502^𝔂^^\mbfscry^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL Y +1D503^𝔃^^\mbfscrz^A^mathalpha^^MATHEMATICAL BOLD SCRIPT SMALL Z +1D504^𝔄^\mathfrak{A}^\mfrakA^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL A +1D505^𝔅^\mathfrak{B}^\mfrakB^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL B +1D507^𝔇^\mathfrak{D}^\mfrakD^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL D +1D508^𝔈^\mathfrak{E}^\mfrakE^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL E +1D509^𝔉^\mathfrak{F}^\mfrakF^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL F +1D50A^𝔊^\mathfrak{G}^\mfrakG^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL G +1D50D^𝔍^\mathfrak{J}^\mfrakJ^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL J +1D50E^𝔎^\mathfrak{K}^\mfrakK^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL K +1D50F^𝔏^\mathfrak{L}^\mfrakL^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL L +1D510^𝔐^\mathfrak{M}^\mfrakM^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL M +1D511^𝔑^\mathfrak{N}^\mfrakN^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL N +1D512^𝔒^\mathfrak{O}^\mfrakO^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL O +1D513^𝔓^\mathfrak{P}^\mfrakP^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL P +1D514^𝔔^\mathfrak{Q}^\mfrakQ^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL Q +1D516^𝔖^\mathfrak{S}^\mfrakS^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL S +1D517^𝔗^\mathfrak{T}^\mfrakT^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL T +1D518^𝔘^\mathfrak{U}^\mfrakU^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL U +1D519^𝔙^\mathfrak{V}^\mfrakV^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL V +1D51A^𝔚^\mathfrak{W}^\mfrakW^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL W +1D51B^𝔛^\mathfrak{X}^\mfrakX^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL X +1D51C^𝔜^\mathfrak{Y}^\mfrakY^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR CAPITAL Y +1D51E^𝔞^\mathfrak{a}^\mfraka^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL A +1D51F^𝔟^\mathfrak{b}^\mfrakb^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL B +1D520^𝔠^\mathfrak{c}^\mfrakc^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL C +1D521^𝔡^\mathfrak{d}^\mfrakd^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL D +1D522^𝔢^\mathfrak{e}^\mfrake^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL E +1D523^𝔣^\mathfrak{f}^\mfrakf^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL F +1D524^𝔤^\mathfrak{g}^\mfrakg^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL G +1D525^𝔥^\mathfrak{h}^\mfrakh^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL H +1D526^𝔦^\mathfrak{i}^\mfraki^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL I +1D527^𝔧^\mathfrak{j}^\mfrakj^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL J +1D528^𝔨^\mathfrak{k}^\mfrakk^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL K +1D529^𝔩^\mathfrak{l}^\mfrakl^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL L +1D52A^𝔪^\mathfrak{m}^\mfrakm^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL M +1D52B^𝔫^\mathfrak{n}^\mfrakn^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL N +1D52C^𝔬^\mathfrak{o}^\mfrako^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL O +1D52D^𝔭^\mathfrak{p}^\mfrakp^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL P +1D52E^𝔮^\mathfrak{q}^\mfrakq^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL Q +1D52F^𝔯^\mathfrak{r}^\mfrakr^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL R +1D530^𝔰^\mathfrak{s}^\mfraks^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL S +1D531^𝔱^\mathfrak{t}^\mfrakt^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL T +1D532^𝔲^\mathfrak{u}^\mfraku^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL U +1D533^𝔳^\mathfrak{v}^\mfrakv^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL V +1D534^𝔴^\mathfrak{w}^\mfrakw^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL W +1D535^𝔵^\mathfrak{x}^\mfrakx^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL X +1D536^𝔶^\mathfrak{y}^\mfraky^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL Y +1D537^𝔷^\mathfrak{z}^\mfrakz^A^mathalpha^eufrak^MATHEMATICAL FRAKTUR SMALL Z +1D538^𝔸^\mathbb{A}^\BbbA^A^mathalpha^mathbb^= \mathds{A} (dsfont), MATHEMATICAL DOUBLE-STRUCK CAPITAL A +1D539^𝔹^\mathbb{B}^\BbbB^A^mathalpha^mathbb^= \mathds{B} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL B +1D53B^𝔻^\mathbb{D}^\BbbD^A^mathalpha^mathbb^= \mathds{D} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL D +1D53C^𝔼^\mathbb{E}^\BbbE^A^mathalpha^mathbb^= \mathds{E} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL E +1D53D^𝔽^\mathbb{F}^\BbbF^A^mathalpha^mathbb^= \mathds{F} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL F +1D53E^𝔾^\mathbb{G}^\BbbG^A^mathalpha^mathbb^= \mathds{G} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL G +1D540^𝕀^\mathbb{I}^\BbbI^A^mathalpha^mathbb^= \mathds{I} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL I +1D541^𝕁^\mathbb{J}^\BbbJ^A^mathalpha^mathbb^= \mathds{J} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL J +1D542^𝕂^\mathbb{K}^\BbbK^A^mathalpha^mathbb^= \mathds{K} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL K +1D543^𝕃^\mathbb{L}^\BbbL^A^mathalpha^mathbb^= \mathds{L} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL L +1D544^𝕄^\mathbb{M}^\BbbM^A^mathalpha^mathbb^= \mathds{M} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL M +1D546^𝕆^\mathbb{O}^\BbbO^A^mathalpha^mathbb^= \mathds{O} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL O +1D54A^𝕊^\mathbb{S}^\BbbS^A^mathalpha^mathbb^= \mathds{S} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL S +1D54B^𝕋^\mathbb{T}^\BbbT^A^mathalpha^mathbb^= \mathds{T} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL T +1D54C^𝕌^\mathbb{U}^\BbbU^A^mathalpha^mathbb^= \mathds{U} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL U +1D54D^𝕍^\mathbb{V}^\BbbV^A^mathalpha^mathbb^= \mathds{V} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL V +1D54E^𝕎^\mathbb{W}^\BbbW^A^mathalpha^mathbb^= \mathds{W} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL W +1D54F^𝕏^\mathbb{X}^\BbbX^A^mathalpha^mathbb^= \mathds{X} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL X +1D550^𝕐^\mathbb{Y}^\BbbY^A^mathalpha^mathbb^= \mathds{Y} (dsfont), matMATHEMATICAL DOUBLE-STRUCK CAPITAL Y +1D552^𝕒^\mathbb{a}^\Bbba^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL A +1D553^𝕓^\mathbb{b}^\Bbbb^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL B +1D554^𝕔^\mathbb{c}^\Bbbc^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL C +1D555^𝕕^\mathbb{d}^\Bbbd^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL D +1D556^𝕖^\mathbb{e}^\Bbbe^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL E +1D557^𝕗^\mathbb{f}^\Bbbf^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL F +1D558^𝕘^\mathbb{g}^\Bbbg^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL G +1D559^𝕙^\mathbb{h}^\Bbbh^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL H +1D55A^𝕚^\mathbb{i}^\Bbbi^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL I +1D55B^𝕛^\mathbb{j}^\Bbbj^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL J +1D55C^𝕜^\mathbb{k}^\Bbbk^A^mathalpha^bbold fourier^= \Bbbk (amssymb), MATHEMATICAL DOUBLE-STRUCK SMALL K +1D55D^𝕝^\mathbb{l}^\Bbbl^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL L +1D55E^𝕞^\mathbb{m}^\Bbbm^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL M +1D55F^𝕟^\mathbb{n}^\Bbbn^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL N +1D560^𝕠^\mathbb{o}^\Bbbo^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL O +1D561^𝕡^\mathbb{p}^\Bbbp^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL P +1D562^𝕢^\mathbb{q}^\Bbbq^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL Q +1D563^𝕣^\mathbb{r}^\Bbbr^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL R +1D564^𝕤^\mathbb{s}^\Bbbs^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL S +1D565^𝕥^\mathbb{t}^\Bbbt^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL T +1D566^𝕦^\mathbb{u}^\Bbbu^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL U +1D567^𝕧^\mathbb{v}^\Bbbv^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL V +1D568^𝕨^\mathbb{w}^\Bbbw^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL W +1D569^𝕩^\mathbb{x}^\Bbbx^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL X +1D56A^𝕪^\mathbb{y}^\Bbby^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL Y +1D56B^𝕫^\mathbb{z}^\Bbbz^A^mathalpha^bbold^MATHEMATICAL DOUBLE-STRUCK SMALL Z +1D56C^𝕬^^\mbffrakA^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL A +1D56D^𝕭^^\mbffrakB^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL B +1D56E^𝕮^^\mbffrakC^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL C +1D56F^𝕯^^\mbffrakD^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL D +1D570^𝕰^^\mbffrakE^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL E +1D571^𝕱^^\mbffrakF^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL F +1D572^𝕲^^\mbffrakG^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL G +1D573^𝕳^^\mbffrakH^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL H +1D574^𝕴^^\mbffrakI^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL I +1D575^𝕵^^\mbffrakJ^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL J +1D576^𝕶^^\mbffrakK^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL K +1D577^𝕷^^\mbffrakL^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL L +1D578^𝕸^^\mbffrakM^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL M +1D579^𝕹^^\mbffrakN^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL N +1D57A^𝕺^^\mbffrakO^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL O +1D57B^𝕻^^\mbffrakP^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL P +1D57C^𝕼^^\mbffrakQ^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL Q +1D57D^𝕽^^\mbffrakR^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL R +1D57E^𝕾^^\mbffrakS^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL S +1D57F^𝕿^^\mbffrakT^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL T +1D580^𝖀^^\mbffrakU^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL U +1D581^𝖁^^\mbffrakV^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL V +1D582^𝖂^^\mbffrakW^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL W +1D583^𝖃^^\mbffrakX^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL X +1D584^𝖄^^\mbffrakY^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL Y +1D585^𝖅^^\mbffrakZ^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR CAPITAL Z +1D586^𝖆^^\mbffraka^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL A +1D587^𝖇^^\mbffrakb^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL B +1D588^𝖈^^\mbffrakc^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL C +1D589^𝖉^^\mbffrakd^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL D +1D58A^𝖊^^\mbffrake^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL E +1D58B^𝖋^^\mbffrakf^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL F +1D58C^𝖌^^\mbffrakg^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL G +1D58D^𝖍^^\mbffrakh^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL H +1D58E^𝖎^^\mbffraki^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL I +1D58F^𝖏^^\mbffrakj^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL J +1D590^𝖐^^\mbffrakk^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL K +1D591^𝖑^^\mbffrakl^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL L +1D592^𝖒^^\mbffrakm^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL M +1D593^𝖓^^\mbffrakn^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL N +1D594^𝖔^^\mbffrako^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL O +1D595^𝖕^^\mbffrakp^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL P +1D596^𝖖^^\mbffrakq^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL Q +1D597^𝖗^^\mbffrakr^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL R +1D598^𝖘^^\mbffraks^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL S +1D599^𝖙^^\mbffrakt^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL T +1D59A^𝖚^^\mbffraku^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL U +1D59B^𝖛^^\mbffrakv^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL V +1D59C^𝖜^^\mbffrakw^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL W +1D59D^𝖝^^\mbffrakx^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL X +1D59E^𝖞^^\mbffraky^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL Y +1D59F^𝖟^^\mbffrakz^A^mathalpha^^MATHEMATICAL BOLD FRAKTUR SMALL Z +1D5A0^𝖠^\mathsf{A}^\msansA^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL A +1D5A1^𝖡^\mathsf{B}^\msansB^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL B +1D5A2^𝖢^\mathsf{C}^\msansC^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL C +1D5A3^𝖣^\mathsf{D}^\msansD^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL D +1D5A4^𝖤^\mathsf{E}^\msansE^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL E +1D5A5^𝖥^\mathsf{F}^\msansF^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL F +1D5A6^𝖦^\mathsf{G}^\msansG^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL G +1D5A7^𝖧^\mathsf{H}^\msansH^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL H +1D5A8^𝖨^\mathsf{I}^\msansI^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL I +1D5A9^𝖩^\mathsf{J}^\msansJ^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL J +1D5AA^𝖪^\mathsf{K}^\msansK^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL K +1D5AB^𝖫^\mathsf{L}^\msansL^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL L +1D5AC^𝖬^\mathsf{M}^\msansM^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL M +1D5AD^𝖭^\mathsf{N}^\msansN^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL N +1D5AE^𝖮^\mathsf{O}^\msansO^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL O +1D5AF^𝖯^\mathsf{P}^\msansP^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL P +1D5B0^𝖰^\mathsf{Q}^\msansQ^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL Q +1D5B1^𝖱^\mathsf{R}^\msansR^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL R +1D5B2^𝖲^\mathsf{S}^\msansS^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL S +1D5B3^𝖳^\mathsf{T}^\msansT^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL T +1D5B4^𝖴^\mathsf{U}^\msansU^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL U +1D5B5^𝖵^\mathsf{V}^\msansV^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL V +1D5B6^𝖶^\mathsf{W}^\msansW^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL W +1D5B7^𝖷^\mathsf{X}^\msansX^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL X +1D5B8^𝖸^\mathsf{Y}^\msansY^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL Y +1D5B9^𝖹^\mathsf{Z}^\msansZ^A^mathalpha^^MATHEMATICAL SANS-SERIF CAPITAL Z +1D5BA^𝖺^\mathsf{a}^\msansa^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL A +1D5BB^𝖻^\mathsf{b}^\msansb^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL B +1D5BC^𝖼^\mathsf{c}^\msansc^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL C +1D5BD^𝖽^\mathsf{d}^\msansd^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL D +1D5BE^𝖾^\mathsf{e}^\msanse^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL E +1D5BF^𝖿^\mathsf{f}^\msansf^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL F +1D5C0^𝗀^\mathsf{g}^\msansg^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL G +1D5C1^𝗁^\mathsf{h}^\msansh^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL H +1D5C2^𝗂^\mathsf{i}^\msansi^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL I +1D5C3^𝗃^\mathsf{j}^\msansj^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL J +1D5C4^𝗄^\mathsf{k}^\msansk^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL K +1D5C5^𝗅^\mathsf{l}^\msansl^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL L +1D5C6^𝗆^\mathsf{m}^\msansm^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL M +1D5C7^𝗇^\mathsf{n}^\msansn^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL N +1D5C8^𝗈^\mathsf{o}^\msanso^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL O +1D5C9^𝗉^\mathsf{p}^\msansp^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL P +1D5CA^𝗊^\mathsf{q}^\msansq^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL Q +1D5CB^𝗋^\mathsf{r}^\msansr^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL R +1D5CC^𝗌^\mathsf{s}^\msanss^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL S +1D5CD^𝗍^\mathsf{t}^\msanst^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL T +1D5CE^𝗎^\mathsf{u}^\msansu^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL U +1D5CF^𝗏^\mathsf{v}^\msansv^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL V +1D5D0^𝗐^\mathsf{w}^\msansw^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL W +1D5D1^𝗑^\mathsf{x}^\msansx^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL X +1D5D2^𝗒^\mathsf{y}^\msansy^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL Y +1D5D3^𝗓^\mathsf{z}^\msansz^A^mathalpha^^MATHEMATICAL SANS-SERIF SMALL Z +1D5D4^𝗔^\mathsfbf{A}^\mbfsansA^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL A +1D5D5^𝗕^\mathsfbf{B}^\mbfsansB^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL B +1D5D6^𝗖^\mathsfbf{C}^\mbfsansC^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL C +1D5D7^𝗗^\mathsfbf{D}^\mbfsansD^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL D +1D5D8^𝗘^\mathsfbf{E}^\mbfsansE^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL E +1D5D9^𝗙^\mathsfbf{F}^\mbfsansF^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL F +1D5DA^𝗚^\mathsfbf{G}^\mbfsansG^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL G +1D5DB^𝗛^\mathsfbf{H}^\mbfsansH^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL H +1D5DC^𝗜^\mathsfbf{I}^\mbfsansI^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL I +1D5DD^𝗝^\mathsfbf{J}^\mbfsansJ^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL J +1D5DE^𝗞^\mathsfbf{K}^\mbfsansK^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL K +1D5DF^𝗟^\mathsfbf{L}^\mbfsansL^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL L +1D5E0^𝗠^\mathsfbf{M}^\mbfsansM^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL M +1D5E1^𝗡^\mathsfbf{N}^\mbfsansN^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL N +1D5E2^𝗢^\mathsfbf{O}^\mbfsansO^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL O +1D5E3^𝗣^\mathsfbf{P}^\mbfsansP^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL P +1D5E4^𝗤^\mathsfbf{Q}^\mbfsansQ^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL Q +1D5E5^𝗥^\mathsfbf{R}^\mbfsansR^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL R +1D5E6^𝗦^\mathsfbf{S}^\mbfsansS^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL S +1D5E7^𝗧^\mathsfbf{T}^\mbfsansT^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL T +1D5E8^𝗨^\mathsfbf{U}^\mbfsansU^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL U +1D5E9^𝗩^\mathsfbf{V}^\mbfsansV^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL V +1D5EA^𝗪^\mathsfbf{W}^\mbfsansW^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL W +1D5EB^𝗫^\mathsfbf{X}^\mbfsansX^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL X +1D5EC^𝗬^\mathsfbf{Y}^\mbfsansY^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL Y +1D5ED^𝗭^\mathsfbf{Z}^\mbfsansZ^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL Z +1D5EE^𝗮^\mathsfbf{a}^\mbfsansa^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL A +1D5EF^𝗯^\mathsfbf{b}^\mbfsansb^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL B +1D5F0^𝗰^\mathsfbf{c}^\mbfsansc^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL C +1D5F1^𝗱^\mathsfbf{d}^\mbfsansd^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL D +1D5F2^𝗲^\mathsfbf{e}^\mbfsanse^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL E +1D5F3^𝗳^\mathsfbf{f}^\mbfsansf^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL F +1D5F4^𝗴^\mathsfbf{g}^\mbfsansg^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL G +1D5F5^𝗵^\mathsfbf{h}^\mbfsansh^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL H +1D5F6^𝗶^\mathsfbf{i}^\mbfsansi^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL I +1D5F7^𝗷^\mathsfbf{j}^\mbfsansj^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL J +1D5F8^𝗸^\mathsfbf{k}^\mbfsansk^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL K +1D5F9^𝗹^\mathsfbf{l}^\mbfsansl^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL L +1D5FA^𝗺^\mathsfbf{m}^\mbfsansm^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL M +1D5FB^𝗻^\mathsfbf{n}^\mbfsansn^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL N +1D5FC^𝗼^\mathsfbf{o}^\mbfsanso^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL O +1D5FD^𝗽^\mathsfbf{p}^\mbfsansp^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL P +1D5FE^𝗾^\mathsfbf{q}^\mbfsansq^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL Q +1D5FF^𝗿^\mathsfbf{r}^\mbfsansr^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL R +1D600^𝘀^\mathsfbf{s}^\mbfsanss^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL S +1D601^𝘁^\mathsfbf{t}^\mbfsanst^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL T +1D602^𝘂^\mathsfbf{u}^\mbfsansu^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL U +1D603^𝘃^\mathsfbf{v}^\mbfsansv^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL V +1D604^𝘄^\mathsfbf{w}^\mbfsansw^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL W +1D605^𝘅^\mathsfbf{x}^\mbfsansx^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL X +1D606^𝘆^\mathsfbf{y}^\mbfsansy^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL Y +1D607^𝘇^\mathsfbf{z}^\mbfsansz^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL Z +1D608^𝘈^\mathsfit{A}^\mitsansA^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL A +1D609^𝘉^\mathsfit{B}^\mitsansB^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL B +1D60A^𝘊^\mathsfit{C}^\mitsansC^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL C +1D60B^𝘋^\mathsfit{D}^\mitsansD^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL D +1D60C^𝘌^\mathsfit{E}^\mitsansE^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL E +1D60D^𝘍^\mathsfit{F}^\mitsansF^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL F +1D60E^𝘎^\mathsfit{G}^\mitsansG^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL G +1D60F^𝘏^\mathsfit{H}^\mitsansH^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL H +1D610^𝘐^\mathsfit{I}^\mitsansI^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL I +1D611^𝘑^\mathsfit{J}^\mitsansJ^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL J +1D612^𝘒^\mathsfit{K}^\mitsansK^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL K +1D613^𝘓^\mathsfit{L}^\mitsansL^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL L +1D614^𝘔^\mathsfit{M}^\mitsansM^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL M +1D615^𝘕^\mathsfit{N}^\mitsansN^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL N +1D616^𝘖^\mathsfit{O}^\mitsansO^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL O +1D617^𝘗^\mathsfit{P}^\mitsansP^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL P +1D618^𝘘^\mathsfit{Q}^\mitsansQ^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q +1D619^𝘙^\mathsfit{R}^\mitsansR^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL R +1D61A^𝘚^\mathsfit{S}^\mitsansS^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL S +1D61B^𝘛^\mathsfit{T}^\mitsansT^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL T +1D61C^𝘜^\mathsfit{U}^\mitsansU^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL U +1D61D^𝘝^\mathsfit{V}^\mitsansV^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL V +1D61E^𝘞^\mathsfit{W}^\mitsansW^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL W +1D61F^𝘟^\mathsfit{X}^\mitsansX^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL X +1D620^𝘠^\mathsfit{Y}^\mitsansY^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y +1D621^𝘡^\mathsfit{Z}^\mitsansZ^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z +1D622^𝘢^\mathsfit{a}^\mitsansa^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL A +1D623^𝘣^\mathsfit{b}^\mitsansb^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL B +1D624^𝘤^\mathsfit{c}^\mitsansc^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL C +1D625^𝘥^\mathsfit{d}^\mitsansd^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL D +1D626^𝘦^\mathsfit{e}^\mitsanse^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL E +1D627^𝘧^\mathsfit{f}^\mitsansf^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL F +1D628^𝘨^\mathsfit{g}^\mitsansg^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL G +1D629^𝘩^\mathsfit{h}^\mitsansh^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL H +1D62A^𝘪^\mathsfit{i}^\mitsansi^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL I +1D62B^𝘫^\mathsfit{j}^\mitsansj^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL J +1D62C^𝘬^\mathsfit{k}^\mitsansk^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL K +1D62D^𝘭^\mathsfit{l}^\mitsansl^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL L +1D62E^𝘮^\mathsfit{m}^\mitsansm^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL M +1D62F^𝘯^\mathsfit{n}^\mitsansn^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL N +1D630^𝘰^\mathsfit{o}^\mitsanso^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL O +1D631^𝘱^\mathsfit{p}^\mitsansp^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL P +1D632^𝘲^\mathsfit{q}^\mitsansq^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL Q +1D633^𝘳^\mathsfit{r}^\mitsansr^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL R +1D634^𝘴^\mathsfit{s}^\mitsanss^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL S +1D635^𝘵^\mathsfit{t}^\mitsanst^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL T +1D636^𝘶^\mathsfit{u}^\mitsansu^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL U +1D637^𝘷^\mathsfit{v}^\mitsansv^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL V +1D638^𝘸^\mathsfit{w}^\mitsansw^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL W +1D639^𝘹^\mathsfit{x}^\mitsansx^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL X +1D63A^𝘺^\mathsfit{y}^\mitsansy^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL Y +1D63B^𝘻^\mathsfit{z}^\mitsansz^A^mathalpha^omlmathsfit^MATHEMATICAL SANS-SERIF ITALIC SMALL Z +1D63C^𝘼^\mathsfbfit{A}^\mbfitsansA^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A +1D63D^𝘽^\mathsfbfit{B}^\mbfitsansB^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B +1D63E^𝘾^\mathsfbfit{C}^\mbfitsansC^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C +1D63F^𝘿^\mathsfbfit{D}^\mbfitsansD^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D +1D640^𝙀^\mathsfbfit{E}^\mbfitsansE^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E +1D641^𝙁^\mathsfbfit{F}^\mbfitsansF^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F +1D642^𝙂^\mathsfbfit{G}^\mbfitsansG^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G +1D643^𝙃^\mathsfbfit{H}^\mbfitsansH^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H +1D644^𝙄^\mathsfbfit{I}^\mbfitsansI^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I +1D645^𝙅^\mathsfbfit{J}^\mbfitsansJ^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J +1D646^𝙆^\mathsfbfit{K}^\mbfitsansK^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K +1D647^𝙇^\mathsfbfit{L}^\mbfitsansL^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L +1D648^𝙈^\mathsfbfit{M}^\mbfitsansM^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M +1D649^𝙉^\mathsfbfit{N}^\mbfitsansN^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N +1D64A^𝙊^\mathsfbfit{O}^\mbfitsansO^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O +1D64B^𝙋^\mathsfbfit{P}^\mbfitsansP^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P +1D64C^𝙌^\mathsfbfit{Q}^\mbfitsansQ^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q +1D64D^𝙍^\mathsfbfit{R}^\mbfitsansR^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R +1D64E^𝙎^\mathsfbfit{S}^\mbfitsansS^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S +1D64F^𝙏^\mathsfbfit{T}^\mbfitsansT^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T +1D650^𝙐^\mathsfbfit{U}^\mbfitsansU^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U +1D651^𝙑^\mathsfbfit{V}^\mbfitsansV^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V +1D652^𝙒^\mathsfbfit{W}^\mbfitsansW^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W +1D653^𝙓^\mathsfbfit{X}^\mbfitsansX^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X +1D654^𝙔^\mathsfbfit{Y}^\mbfitsansY^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y +1D655^𝙕^\mathsfbfit{Z}^\mbfitsansZ^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z +1D656^𝙖^\mathsfbfit{a}^\mbfitsansa^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A +1D657^𝙗^\mathsfbfit{b}^\mbfitsansb^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B +1D658^𝙘^\mathsfbfit{c}^\mbfitsansc^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C +1D659^𝙙^\mathsfbfit{d}^\mbfitsansd^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D +1D65A^𝙚^\mathsfbfit{e}^\mbfitsanse^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E +1D65B^𝙛^\mathsfbfit{f}^\mbfitsansf^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F +1D65C^𝙜^\mathsfbfit{g}^\mbfitsansg^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G +1D65D^𝙝^\mathsfbfit{h}^\mbfitsansh^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H +1D65E^𝙞^\mathsfbfit{i}^\mbfitsansi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I +1D65F^𝙟^\mathsfbfit{j}^\mbfitsansj^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J +1D660^𝙠^\mathsfbfit{k}^\mbfitsansk^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K +1D661^𝙡^\mathsfbfit{l}^\mbfitsansl^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L +1D662^𝙢^\mathsfbfit{m}^\mbfitsansm^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M +1D663^𝙣^\mathsfbfit{n}^\mbfitsansn^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N +1D664^𝙤^\mathsfbfit{o}^\mbfitsanso^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O +1D665^𝙥^\mathsfbfit{p}^\mbfitsansp^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P +1D666^𝙦^\mathsfbfit{q}^\mbfitsansq^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q +1D667^𝙧^\mathsfbfit{r}^\mbfitsansr^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R +1D668^𝙨^\mathsfbfit{s}^\mbfitsanss^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S +1D669^𝙩^\mathsfbfit{t}^\mbfitsanst^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T +1D66A^𝙪^\mathsfbfit{u}^\mbfitsansu^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U +1D66B^𝙫^\mathsfbfit{v}^\mbfitsansv^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V +1D66C^𝙬^\mathsfbfit{w}^\mbfitsansw^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W +1D66D^𝙭^\mathsfbfit{x}^\mbfitsansx^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X +1D66E^𝙮^\mathsfbfit{y}^\mbfitsansy^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y +1D66F^𝙯^\mathsfbfit{z}^\mbfitsansz^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z +1D670^𝙰^\mathtt{A}^\mttA^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL A +1D671^𝙱^\mathtt{B}^\mttB^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL B +1D672^𝙲^\mathtt{C}^\mttC^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL C +1D673^𝙳^\mathtt{D}^\mttD^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL D +1D674^𝙴^\mathtt{E}^\mttE^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL E +1D675^𝙵^\mathtt{F}^\mttF^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL F +1D676^𝙶^\mathtt{G}^\mttG^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL G +1D677^𝙷^\mathtt{H}^\mttH^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL H +1D678^𝙸^\mathtt{I}^\mttI^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL I +1D679^𝙹^\mathtt{J}^\mttJ^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL J +1D67A^𝙺^\mathtt{K}^\mttK^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL K +1D67B^𝙻^\mathtt{L}^\mttL^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL L +1D67C^𝙼^\mathtt{M}^\mttM^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL M +1D67D^𝙽^\mathtt{N}^\mttN^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL N +1D67E^𝙾^\mathtt{O}^\mttO^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL O +1D67F^𝙿^\mathtt{P}^\mttP^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL P +1D680^𝚀^\mathtt{Q}^\mttQ^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL Q +1D681^𝚁^\mathtt{R}^\mttR^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL R +1D682^𝚂^\mathtt{S}^\mttS^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL S +1D683^𝚃^\mathtt{T}^\mttT^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL T +1D684^𝚄^\mathtt{U}^\mttU^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL U +1D685^𝚅^\mathtt{V}^\mttV^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL V +1D686^𝚆^\mathtt{W}^\mttW^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL W +1D687^𝚇^\mathtt{X}^\mttX^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL X +1D688^𝚈^\mathtt{Y}^\mttY^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL Y +1D689^𝚉^\mathtt{Z}^\mttZ^A^mathalpha^^MATHEMATICAL MONOSPACE CAPITAL Z +1D68A^𝚊^\mathtt{a}^\mtta^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL A +1D68B^𝚋^\mathtt{b}^\mttb^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL B +1D68C^𝚌^\mathtt{c}^\mttc^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL C +1D68D^𝚍^\mathtt{d}^\mttd^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL D +1D68E^𝚎^\mathtt{e}^\mtte^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL E +1D68F^𝚏^\mathtt{f}^\mttf^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL F +1D690^𝚐^\mathtt{g}^\mttg^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL G +1D691^𝚑^\mathtt{h}^\mtth^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL H +1D692^𝚒^\mathtt{i}^\mtti^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL I +1D693^𝚓^\mathtt{j}^\mttj^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL J +1D694^𝚔^\mathtt{k}^\mttk^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL K +1D695^𝚕^\mathtt{l}^\mttl^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL L +1D696^𝚖^\mathtt{m}^\mttm^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL M +1D697^𝚗^\mathtt{n}^\mttn^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL N +1D698^𝚘^\mathtt{o}^\mtto^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL O +1D699^𝚙^\mathtt{p}^\mttp^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL P +1D69A^𝚚^\mathtt{q}^\mttq^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL Q +1D69B^𝚛^\mathtt{r}^\mttr^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL R +1D69C^𝚜^\mathtt{s}^\mtts^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL S +1D69D^𝚝^\mathtt{t}^\mttt^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL T +1D69E^𝚞^\mathtt{u}^\mttu^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL U +1D69F^𝚟^\mathtt{v}^\mttv^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL V +1D6A0^𝚠^\mathtt{w}^\mttw^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL W +1D6A1^𝚡^\mathtt{x}^\mttx^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL X +1D6A2^𝚢^\mathtt{y}^\mtty^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL Y +1D6A3^𝚣^\mathtt{z}^\mttz^A^mathalpha^^MATHEMATICAL MONOSPACE SMALL Z +1D6A4^𝚤^\imath^\imath^A^mathalpha^^MATHEMATICAL ITALIC SMALL DOTLESS I +1D6A5^𝚥^\jmath^\jmath^A^mathalpha^^MATHEMATICAL ITALIC SMALL DOTLESS J +1D6A8^𝚨^^\mbfAlpha^A^mathalpha^^MATHEMATICAL BOLD CAPITAL ALPHA +1D6A9^𝚩^^\mbfBeta^A^mathalpha^^MATHEMATICAL BOLD CAPITAL BETA +1D6AA^𝚪^\mathbf{\Gamma}^\mbfGamma^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL GAMMA +1D6AB^𝚫^\mathbf{\Delta}^\mbfDelta^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL DELTA +1D6AC^𝚬^^\mbfEpsilon^A^mathalpha^^MATHEMATICAL BOLD CAPITAL EPSILON +1D6AD^𝚭^^\mbfZeta^A^mathalpha^^MATHEMATICAL BOLD CAPITAL ZETA +1D6AE^𝚮^^\mbfEta^A^mathalpha^^MATHEMATICAL BOLD CAPITAL ETA +1D6AF^𝚯^\mathbf{\Theta}^\mbfTheta^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL THETA +1D6B0^𝚰^^\mbfIota^A^mathalpha^^MATHEMATICAL BOLD CAPITAL IOTA +1D6B1^𝚱^^\mbfKappa^A^mathalpha^^MATHEMATICAL BOLD CAPITAL KAPPA +1D6B2^𝚲^\mathbf{\Lambda}^\mbfLambda^A^mathalpha^-fourier^mathematical bold capital lambda +1D6B3^𝚳^^\mbfMu^A^mathalpha^^MATHEMATICAL BOLD CAPITAL MU +1D6B4^𝚴^^\mbfNu^A^mathalpha^^MATHEMATICAL BOLD CAPITAL NU +1D6B5^𝚵^\mathbf{\Xi}^\mbfXi^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL XI +1D6B6^𝚶^^\mbfOmicron^A^mathalpha^^MATHEMATICAL BOLD CAPITAL OMICRON +1D6B7^𝚷^\mathbf{\Pi}^\mbfPi^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL PI +1D6B8^𝚸^^\mbfRho^A^mathalpha^^MATHEMATICAL BOLD CAPITAL RHO +1D6B9^𝚹^^\mbfvarTheta^A^mathalpha^^MATHEMATICAL BOLD CAPITAL THETA SYMBOL +1D6BA^𝚺^\mathbf{\Sigma}^\mbfSigma^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL SIGMA +1D6BB^𝚻^^\mbfTau^A^mathalpha^^MATHEMATICAL BOLD CAPITAL TAU +1D6BC^𝚼^\mathbf{\Upsilon}^\mbfUpsilon^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL UPSILON +1D6BD^𝚽^\mathbf{\Phi}^\mbfPhi^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL PHI +1D6BE^𝚾^^\mbfChi^A^mathalpha^^MATHEMATICAL BOLD CAPITAL CHI +1D6BF^𝚿^\mathbf{\Psi}^\mbfPsi^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL PSI +1D6C0^𝛀^\mathbf{\Omega}^\mbfOmega^A^mathalpha^-fourier^MATHEMATICAL BOLD CAPITAL OMEGA +1D6C1^𝛁^^\mbfnabla^A^mathord^^MATHEMATICAL BOLD NABLA +1D6C2^𝛂^\mathbf{\alpha}^\mbfalpha^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL ALPHA +1D6C3^𝛃^\mathbf{\beta}^\mbfbeta^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL BETA +1D6C4^𝛄^\mathbf{\gamma}^\mbfgamma^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL GAMMA +1D6C5^𝛅^\mathbf{\delta}^\mbfdelta^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL DELTA +1D6C6^𝛆^\mathbf{\varepsilon}^\mbfepsilon^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL EPSILON +1D6C7^𝛇^\mathbf{\zeta}^\mbfzeta^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL ZETA +1D6C8^𝛈^\mathbf{\eta}^\mbfeta^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL ETA +1D6C9^𝛉^\mathbf{\theta}^\mbftheta^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL THETA +1D6CA^𝛊^\mathbf{\iota}^\mbfiota^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL IOTA +1D6CB^𝛋^\mathbf{\kappa}^\mbfkappa^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL KAPPA +1D6CC^𝛌^\mathbf{\lambda}^\mbflambda^A^mathalpha^omlmathbf^mathematical bold small lambda +1D6CD^𝛍^\mathbf{\mu}^\mbfmu^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL MU +1D6CE^𝛎^\mathbf{\nu}^\mbfnu^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL NU +1D6CF^𝛏^\mathbf{\xi}^\mbfxi^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL XI +1D6D0^𝛐^^\mbfomicron^A^mathalpha^^MATHEMATICAL BOLD SMALL OMICRON +1D6D1^𝛑^\mathbf{\pi}^\mbfpi^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL PI +1D6D2^𝛒^\mathbf{\rho}^\mbfrho^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL RHO +1D6D3^𝛓^\mathbf{\varsigma}^\mbfvarsigma^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL FINAL SIGMA +1D6D4^𝛔^\mathbf{\sigma}^\mbfsigma^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL SIGMA +1D6D5^𝛕^\mathbf{\tau}^\mbftau^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL TAU +1D6D6^𝛖^\mathbf{\upsilon}^\mbfupsilon^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL UPSILON +1D6D7^𝛗^\mathbf{\varphi}^\mbfvarphi^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL PHI +1D6D8^𝛘^\mathbf{\chi}^\mbfchi^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL CHI +1D6D9^𝛙^\mathbf{\psi}^\mbfpsi^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL PSI +1D6DA^𝛚^\mathbf{\omega}^\mbfomega^A^mathalpha^omlmathbf^MATHEMATICAL BOLD SMALL OMEGA +1D6DB^𝛛^^\mbfpartial^A^mathord^^MATHEMATICAL BOLD PARTIAL DIFFERENTIAL +1D6DC^𝛜^\mathbf{\epsilon}^\mbfvarepsilon^A^mathalpha^omlmathbf^MATHEMATICAL BOLD EPSILON SYMBOL +1D6DD^𝛝^\mathbf{\vartheta}^\mbfvartheta^A^mathalpha^omlmathbf^MATHEMATICAL BOLD THETA SYMBOL +1D6DE^𝛞^^\mbfvarkappa^A^mathalpha^^MATHEMATICAL BOLD KAPPA SYMBOL +1D6DF^𝛟^\mathbf{\phi}^\mbfphi^A^mathalpha^omlmathbf^MATHEMATICAL BOLD PHI SYMBOL +1D6E0^𝛠^\mathbf{\varrho}^\mbfvarrho^A^mathalpha^omlmathbf^MATHEMATICAL BOLD RHO SYMBOL +1D6E1^𝛡^\mathbf{\varpi}^\mbfvarpi^A^mathalpha^omlmathbf^MATHEMATICAL BOLD PI SYMBOL +1D6E2^𝛢^^\mitAlpha^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL ALPHA +1D6E3^𝛣^^\mitBeta^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL BETA +1D6E4^𝛤^\Gamma^\mitGamma^A^mathalpha^slantedGreek^= \mathit{\Gamma} (-fourier), = \varGamma (amsmath fourier), MATHEMATICAL ITALIC CAPITAL GAMMA +1D6E5^𝛥^\Delta^\mitDelta^A^mathalpha^slantedGreek^= \mathit{\Delta} (-fourier), = \varDelta (amsmath fourier), MATHEMATICAL ITALIC CAPITAL DELTA +1D6E6^𝛦^^\mitEpsilon^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL EPSILON +1D6E7^𝛧^^\mitZeta^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL ZETA +1D6E8^𝛨^^\mitEta^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL ETA +1D6E9^𝛩^\Theta^\mitTheta^A^mathalpha^slantedGreek^= \mathit{\Theta} (-fourier), = \varTheta (amsmath fourier), MATHEMATICAL ITALIC CAPITAL THETA +1D6EA^𝛪^^\mitIota^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL IOTA +1D6EB^𝛫^^\mitKappa^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL KAPPA +1D6EC^𝛬^\Lambda^\mitLambda^A^mathalpha^slantedGreek^= \mathit{\Lambda} (-fourier), = \varLambda (amsmath fourier), mathematical italic capital lambda +1D6ED^𝛭^^\mitMu^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL MU +1D6EE^𝛮^^\mitNu^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL NU +1D6EF^𝛯^\Xi^\mitXi^A^mathalpha^slantedGreek^= \mathit{\Xi} (-fourier), = \varXi (amsmath fourier), MATHEMATICAL ITALIC CAPITAL XI +1D6F0^𝛰^^\mitOmicron^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL OMICRON +1D6F1^𝛱^\Pi^\mitPi^A^mathalpha^slantedGreek^= \mathit{\Pi} (-fourier), = \varPi (amsmath fourier), MATHEMATICAL ITALIC CAPITAL PI +1D6F2^𝛲^^\mitRho^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL RHO +1D6F3^𝛳^^\mitvarTheta^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL THETA SYMBOL +1D6F4^𝛴^\Sigma^\mitSigma^A^mathalpha^slantedGreek^= \mathit{\Sigma} (-fourier), = \varSigma (amsmath fourier), MATHEMATICAL ITALIC CAPITAL SIGMA +1D6F5^𝛵^^\mitTau^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL TAU +1D6F6^𝛶^\Upsilon^\mitUpsilon^A^mathalpha^slantedGreek^= \mathit{\Upsilon} (-fourier), = \varUpsilon (amsmath fourier), MATHEMATICAL ITALIC CAPITAL UPSILON +1D6F7^𝛷^\Phi^\mitPhi^A^mathalpha^slantedGreek^= \mathit{\Phi} (-fourier), = \varPhi (amsmath fourier), MATHEMATICAL ITALIC CAPITAL PHI +1D6F8^𝛸^^\mitChi^A^mathalpha^^MATHEMATICAL ITALIC CAPITAL CHI +1D6F9^𝛹^\Psi^\mitPsi^A^mathalpha^slantedGreek^= \mathit{\Psi} (-fourier), = \varPsi (amsmath fourier), MATHEMATICAL ITALIC CAPITAL PSI +1D6FA^𝛺^\Omega^\mitOmega^A^mathalpha^slantedGreek^= \mathit{\Omega} (-fourier), = \varOmega (amsmath fourier), MATHEMATICAL ITALIC CAPITAL OMEGA +1D6FB^𝛻^^\mitnabla^A^mathord^^MATHEMATICAL ITALIC NABLA +1D6FC^𝛼^\alpha^\mitalpha^A^mathalpha^^= \mathit{\alpha} (omlmathit), MATHEMATICAL ITALIC SMALL ALPHA +1D6FD^𝛽^\beta^\mitbeta^A^mathalpha^^= \mathit{\beta} (omlmathit), MATHEMATICAL ITALIC SMALL BETA +1D6FE^𝛾^\gamma^\mitgamma^A^mathalpha^^= \mathit{\gamma} (omlmathit), MATHEMATICAL ITALIC SMALL GAMMA +1D6FF^𝛿^\delta^\mitdelta^A^mathalpha^^= \mathit{\delta} (omlmathit), MATHEMATICAL ITALIC SMALL DELTA +1D700^𝜀^\varepsilon^\mitepsilon^A^mathalpha^^= \mathit{\varepsilon} (omlmathit), MATHEMATICAL ITALIC SMALL EPSILON +1D701^𝜁^\zeta^\mitzeta^A^mathalpha^^= \mathit{\zeta} (omlmathit), MATHEMATICAL ITALIC SMALL ZETA +1D702^𝜂^\eta^\miteta^A^mathalpha^^= \mathit{\eta} (omlmathit), MATHEMATICAL ITALIC SMALL ETA +1D703^𝜃^\theta^\mittheta^A^mathalpha^^= \mathit{\theta} (omlmathit), MATHEMATICAL ITALIC SMALL THETA +1D704^𝜄^\iota^\mitiota^A^mathalpha^^= \mathit{\iota} (omlmathit), MATHEMATICAL ITALIC SMALL IOTA +1D705^𝜅^\kappa^\mitkappa^A^mathalpha^^= \mathit{\kappa} (omlmathit), MATHEMATICAL ITALIC SMALL KAPPA +1D706^𝜆^\lambda^\mitlambda^A^mathalpha^^= \mathit{\lambda} (omlmathit), mathematical italic small lambda +1D707^𝜇^\mu^\mitmu^A^mathalpha^^= \mathit{\mu} (omlmathit), MATHEMATICAL ITALIC SMALL MU +1D708^𝜈^\nu^\mitnu^A^mathalpha^^= \mathit{\nu} (omlmathit), MATHEMATICAL ITALIC SMALL NU +1D709^𝜉^\xi^\mitxi^A^mathalpha^^= \mathit{\xi} (omlmathit), MATHEMATICAL ITALIC SMALL XI +1D70A^𝜊^^\mitomicron^A^mathalpha^^MATHEMATICAL ITALIC SMALL OMICRON +1D70B^𝜋^\pi^\mitpi^A^mathalpha^^= \mathit{\pi} (omlmathit), MATHEMATICAL ITALIC SMALL PI +1D70C^𝜌^\rho^\mitrho^A^mathalpha^^= \mathit{\rho} (omlmathit), MATHEMATICAL ITALIC SMALL RHO +1D70D^𝜍^\varsigma^\mitvarsigma^A^mathalpha^^= \mathit{\varsigma} (omlmathit), MATHEMATICAL ITALIC SMALL FINAL SIGMA +1D70E^𝜎^\sigma^\mitsigma^A^mathalpha^^= \mathit{\sigma} (omlmathit), MATHEMATICAL ITALIC SMALL SIGMA +1D70F^𝜏^\tau^\mittau^A^mathalpha^^= \mathit{\tau} (omlmathit), MATHEMATICAL ITALIC SMALL TAU +1D710^𝜐^\upsilon^\mitupsilon^A^mathalpha^^= \mathit{\upsilon} (omlmathit), MATHEMATICAL ITALIC SMALL UPSILON +1D711^𝜑^\varphi^\mitphi^A^mathalpha^^= \mathit{\varphi} (omlmathit), MATHEMATICAL ITALIC SMALL PHI +1D712^𝜒^\chi^\mitchi^A^mathalpha^^= \mathit{\chi} (omlmathit), MATHEMATICAL ITALIC SMALL CHI +1D713^𝜓^\psi^\mitpsi^A^mathalpha^^= \mathit{\psi} (omlmathit), MATHEMATICAL ITALIC SMALL PSI +1D714^𝜔^\omega^\mitomega^A^mathalpha^^= \mathit{\omega} (omlmathit), MATHEMATICAL ITALIC SMALL OMEGA +1D715^𝜕^\partial^\mitpartial^A^mathord^^= \mathit{\partial} (omlmathit), MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL +1D716^𝜖^\epsilon^\mitvarepsilon^A^mathalpha^^= \mathit{\epsilon} (omlmathit), MATHEMATICAL ITALIC EPSILON SYMBOL +1D717^𝜗^\vartheta^\mitvartheta^A^mathalpha^^= \mathit{\vartheta} (omlmathit), MATHEMATICAL ITALIC THETA SYMBOL +1D718^𝜘^\varkappa^\mitvarkappa^A^mathalpha^amssymb^MATHEMATICAL ITALIC KAPPA SYMBOL +1D719^𝜙^\phi^\mitvarphi^A^mathalpha^^= \mathit{\phi} (omlmathit), MATHEMATICAL ITALIC PHI SYMBOL +1D71A^𝜚^\varrho^\mitvarrho^A^mathalpha^^= \mathit{\varrho} (omlmathit), MATHEMATICAL ITALIC RHO SYMBOL +1D71B^𝜛^\varpi^\mitvarpi^A^mathalpha^^= \mathit{\varpi} (omlmathit), MATHEMATICAL ITALIC PI SYMBOL +1D71C^𝜜^^\mbfitAlpha^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL ALPHA +1D71D^𝜝^^\mbfitBeta^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL BETA +1D71E^𝜞^\mathbfit{\Gamma}^\mbfitGamma^A^mathalpha^isomath^= \mathbold{\Gamma} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL GAMMA +1D71F^𝜟^\mathbfit{\Delta}^\mbfitDelta^A^mathalpha^isomath^= \mathbold{\Delta} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL DELTA +1D720^𝜠^^\mbfitEpsilon^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL EPSILON +1D721^𝜡^^\mbfitZeta^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL ZETA +1D722^𝜢^^\mbfitEta^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL ETA +1D723^𝜣^\mathbfit{\Theta}^\mbfitTheta^A^mathalpha^isomath^= \mathbold{\Theta} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL THETA +1D724^𝜤^^\mbfitIota^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL IOTA +1D725^𝜥^^\mbfitKappa^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL KAPPA +1D726^𝜦^\mathbfit{\Lambda}^\mbfitLambda^A^mathalpha^isomath^= \mathbold{\Lambda} (fixmath), mathematical bold italic capital lambda +1D727^𝜧^^\mbfitMu^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL MU +1D728^𝜨^^\mbfitNu^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL NU +1D729^𝜩^\mathbfit{\Xi}^\mbfitXi^A^mathalpha^isomath^= \mathbold{\Xi} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL XI +1D72A^𝜪^^\mbfitOmicron^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL OMICRON +1D72B^𝜫^\mathbfit{\Pi}^\mbfitPi^A^mathalpha^isomath^= \mathbold{\Pi} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL PI +1D72C^𝜬^^\mbfitRho^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL RHO +1D72D^𝜭^^\mbfitvarTheta^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL +1D72E^𝜮^\mathbfit{\Sigma}^\mbfitSigma^A^mathalpha^isomath^= \mathbold{\Sigma} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL SIGMA +1D72F^𝜯^^\mbfitTau^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL TAU +1D730^𝜰^\mathbfit{\Upsilon}^\mbfitUpsilon^A^mathalpha^isomath^= \mathbold{\Upsilon} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL UPSILON +1D731^𝜱^\mathbfit{\Phi}^\mbfitPhi^A^mathalpha^isomath^= \mathbold{\Phi} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL PHI +1D732^𝜲^^\mbfitChi^A^mathalpha^^MATHEMATICAL BOLD ITALIC CAPITAL CHI +1D733^𝜳^\mathbfit{\Psi}^\mbfitPsi^A^mathalpha^isomath^= \mathbold{\Psi} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL PSI +1D734^𝜴^\mathbfit{\Omega}^\mbfitOmega^A^mathalpha^isomath^= \mathbold{\Omega} (fixmath), MATHEMATICAL BOLD ITALIC CAPITAL OMEGA +1D735^𝜵^^\mbfitnabla^A^mathord^^MATHEMATICAL BOLD ITALIC NABLA +1D736^𝜶^\mathbfit{\alpha}^\mbfitalpha^A^mathalpha^isomath^= \mathbold{\alpha} (fixmath), MATHEMATICAL BOLD ITALIC SMALL ALPHA +1D737^𝜷^\mathbfit{\beta}^\mbfitbeta^A^mathalpha^isomath^= \mathbold{\beta} (fixmath), MATHEMATICAL BOLD ITALIC SMALL BETA +1D738^𝜸^\mathbfit{\gamma}^\mbfitgamma^A^mathalpha^isomath^= \mathbold{\gamma} (fixmath), MATHEMATICAL BOLD ITALIC SMALL GAMMA +1D739^𝜹^\mathbfit{\delta}^\mbfitdelta^A^mathalpha^isomath^= \mathbold{\delta} (fixmath), MATHEMATICAL BOLD ITALIC SMALL DELTA +1D73A^𝜺^\mathbfit{\varepsilon}^\mbfitepsilon^A^mathalpha^isomath^= \mathbold{\varepsilon} (fixmath), MATHEMATICAL BOLD ITALIC SMALL EPSILON +1D73B^𝜻^\mathbfit{\zeta}^\mbfitzeta^A^mathalpha^isomath^= \mathbold{\zeta} (fixmath), MATHEMATICAL BOLD ITALIC SMALL ZETA +1D73C^𝜼^\mathbfit{\eta}^\mbfiteta^A^mathalpha^isomath^= \mathbold{\eta} (fixmath), MATHEMATICAL BOLD ITALIC SMALL ETA +1D73D^𝜽^\mathbfit{\theta}^\mbfittheta^A^mathalpha^isomath^= \mathbold{\theta} (fixmath), MATHEMATICAL BOLD ITALIC SMALL THETA +1D73E^𝜾^\mathbfit{\iota}^\mbfitiota^A^mathalpha^isomath^= \mathbold{\iota} (fixmath), MATHEMATICAL BOLD ITALIC SMALL IOTA +1D73F^𝜿^\mathbfit{\kappa}^\mbfitkappa^A^mathalpha^isomath^= \mathbold{\kappa} (fixmath), MATHEMATICAL BOLD ITALIC SMALL KAPPA +1D740^𝝀^\mathbfit{\lambda}^\mbfitlambda^A^mathalpha^isomath^= \mathbold{\lambda} (fixmath), mathematical bold italic small lambda +1D741^𝝁^\mathbfit{\mu}^\mbfitmu^A^mathalpha^isomath^= \mathbold{\mu} (fixmath), MATHEMATICAL BOLD ITALIC SMALL MU +1D742^𝝂^\mathbfit{\nu}^\mbfitnu^A^mathalpha^isomath^= \mathbold{\nu} (fixmath), MATHEMATICAL BOLD ITALIC SMALL NU +1D743^𝝃^\mathbfit{\xi}^\mbfitxi^A^mathalpha^isomath^= \mathbold{\xi} (fixmath), MATHEMATICAL BOLD ITALIC SMALL XI +1D744^𝝄^^\mbfitomicron^A^mathalpha^^MATHEMATICAL BOLD ITALIC SMALL OMICRON +1D745^𝝅^\mathbfit{\pi}^\mbfitpi^A^mathalpha^isomath^= \mathbold{\pi} (fixmath), MATHEMATICAL BOLD ITALIC SMALL PI +1D746^𝝆^\mathbfit{\rho}^\mbfitrho^A^mathalpha^isomath^= \mathbold{\rho} (fixmath), MATHEMATICAL BOLD ITALIC SMALL RHO +1D747^𝝇^\mathbfit{\varsigma}^\mbfitvarsigma^A^mathalpha^isomath^= \mathbold{\varsigma} (fixmath), MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA +1D748^𝝈^\mathbfit{\sigma}^\mbfitsigma^A^mathalpha^isomath^= \mathbold{\sigma} (fixmath), MATHEMATICAL BOLD ITALIC SMALL SIGMA +1D749^𝝉^\mathbfit{\tau}^\mbfittau^A^mathalpha^isomath^= \mathbold{\tau} (fixmath), MATHEMATICAL BOLD ITALIC SMALL TAU +1D74A^𝝊^\mathbfit{\upsilon}^\mbfitupsilon^A^mathalpha^isomath^= \mathbold{\upsilon} (fixmath), MATHEMATICAL BOLD ITALIC SMALL UPSILON +1D74B^𝝋^\mathbfit{\varphi}^\mbfitphi^A^mathalpha^isomath^= \mathbold{\varphi} (fixmath), MATHEMATICAL BOLD ITALIC SMALL PHI +1D74C^𝝌^\mathbfit{\chi}^\mbfitchi^A^mathalpha^isomath^= \mathbold{\chi} (fixmath), MATHEMATICAL BOLD ITALIC SMALL CHI +1D74D^𝝍^\mathbfit{\psi}^\mbfitpsi^A^mathalpha^isomath^= \mathbold{\psi} (fixmath), MATHEMATICAL BOLD ITALIC SMALL PSI +1D74E^𝝎^\mathbfit{\omega}^\mbfitomega^A^mathalpha^isomath^= \mathbold{\omega} (fixmath), MATHEMATICAL BOLD ITALIC SMALL OMEGA +1D74F^𝝏^^\mbfitpartial^A^mathord^^MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL +1D750^𝝐^\mathbfit{\epsilon}^\mbfitvarepsilon^A^mathalpha^isomath^= \mathbold{\epsilon} (fixmath), MATHEMATICAL BOLD ITALIC EPSILON SYMBOL +1D751^𝝑^\mathbfit{\vartheta}^\mbfitvartheta^A^mathalpha^isomath^= \mathbold{\vartheta} (fixmath), MATHEMATICAL BOLD ITALIC THETA SYMBOL +1D752^𝝒^^\mbfitvarkappa^A^mathalpha^^MATHEMATICAL BOLD ITALIC KAPPA SYMBOL +1D753^𝝓^\mathbfit{\phi}^\mbfitvarphi^A^mathalpha^isomath^= \mathbold{\phi} (fixmath), MATHEMATICAL BOLD ITALIC PHI SYMBOL +1D754^𝝔^\mathbfit{\varrho}^\mbfitvarrho^A^mathalpha^isomath^= \mathbold{\varrho} (fixmath), MATHEMATICAL BOLD ITALIC RHO SYMBOL +1D755^𝝕^\mathbfit{\varpi}^\mbfitvarpi^A^mathalpha^isomath^= \mathbold{\varpi} (fixmath), MATHEMATICAL BOLD ITALIC PI SYMBOL +1D756^𝝖^^\mbfsansAlpha^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA +1D757^𝝗^^\mbfsansBeta^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA +1D758^𝝘^\mathsfbf{\Gamma}^\mbfsansGamma^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA +1D759^𝝙^\mathsfbf{\Delta}^\mbfsansDelta^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA +1D75A^𝝚^^\mbfsansEpsilon^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON +1D75B^𝝛^^\mbfsansZeta^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA +1D75C^𝝜^^\mbfsansEta^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA +1D75D^𝝝^\mathsfbf{\Theta}^\mbfsansTheta^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA +1D75E^𝝞^^\mbfsansIota^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA +1D75F^𝝟^^\mbfsansKappa^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA +1D760^𝝠^\mathsfbf{\Lambda}^\mbfsansLambda^A^mathalpha^mathsfbf^mathematical sans-serif bold capital lambda +1D761^𝝡^^\mbfsansMu^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL MU +1D762^𝝢^^\mbfsansNu^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL NU +1D763^𝝣^\mathsfbf{\Xi}^\mbfsansXi^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL XI +1D764^𝝤^^\mbfsansOmicron^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON +1D765^𝝥^\mathsfbf{\Pi}^\mbfsansPi^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL PI +1D766^𝝦^^\mbfsansRho^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO +1D767^𝝧^^\mbfsansvarTheta^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL +1D768^𝝨^\mathsfbf{\Sigma}^\mbfsansSigma^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA +1D769^𝝩^^\mbfsansTau^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU +1D76A^𝝪^\mathsfbf{\Upsilon}^\mbfsansUpsilon^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON +1D76B^𝝫^\mathsfbf{\Phi}^\mbfsansPhi^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI +1D76C^𝝬^^\mbfsansChi^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI +1D76D^𝝭^\mathsfbf{\Psi}^\mbfsansPsi^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI +1D76E^𝝮^\mathsfbf{\Omega}^\mbfsansOmega^A^mathalpha^mathsfbf^MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA +1D76F^𝝯^^\mbfsansnabla^A^mathord^^MATHEMATICAL SANS-SERIF BOLD NABLA +1D770^𝝰^\mathsfbf{\alpha}^\mbfsansalpha^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA +1D771^𝝱^\mathsfbf{\beta}^\mbfsansbeta^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL BETA +1D772^𝝲^\mathsfbf{\gamma}^\mbfsansgamma^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA +1D773^𝝳^\mathsfbf{\delta}^\mbfsansdelta^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL DELTA +1D774^𝝴^\mathsfbf{\varepsilon}^\mbfsansepsilon^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON +1D775^𝝵^\mathsfbf{\zeta}^\mbfsanszeta^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL ZETA +1D776^𝝶^\mathsfbf{\eta}^\mbfsanseta^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL ETA +1D777^𝝷^\mathsfbf{\theta}^\mbfsanstheta^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL THETA +1D778^𝝸^\mathsfbf{\iota}^\mbfsansiota^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL IOTA +1D779^𝝹^\mathsfbf{\kappa}^\mbfsanskappa^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA +1D77A^𝝺^\mathsfbf{\lambda}^\mbfsanslambda^A^mathalpha^omlmathsfbf^mathematical sans-serif bold small lambda +1D77B^𝝻^\mathsfbf{\mu}^\mbfsansmu^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL MU +1D77C^𝝼^\mathsfbf{\nu}^\mbfsansnu^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL NU +1D77D^𝝽^\mathsfbf{\xi}^\mbfsansxi^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL XI +1D77E^𝝾^^\mbfsansomicron^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON +1D77F^𝝿^\mathsfbf{\pi}^\mbfsanspi^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL PI +1D780^𝞀^\mathsfbf{\rho}^\mbfsansrho^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL RHO +1D781^𝞁^\mathsfbf{\varsigma}^\mbfsansvarsigma^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA +1D782^𝞂^\mathsfbf{\sigma}^\mbfsanssigma^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA +1D783^𝞃^\mathsfbf{\tau}^\mbfsanstau^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL TAU +1D784^𝞄^\mathsfbf{\upsilon}^\mbfsansupsilon^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON +1D785^𝞅^\mathsfbf{\varphi}^\mbfsansphi^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL PHI +1D786^𝞆^\mathsfbf{\chi}^\mbfsanschi^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL CHI +1D787^𝞇^\mathsfbf{\psi}^\mbfsanspsi^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL PSI +1D788^𝞈^\mathsfbf{\omega}^\mbfsansomega^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA +1D789^𝞉^^\mbfsanspartial^A^mathord^^MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL +1D78A^𝞊^\mathsfbf{\epsilon}^\mbfsansvarepsilon^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL +1D78B^𝞋^\mathsfbf{\vartheta}^\mbfsansvartheta^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL +1D78C^𝞌^^\mbfsansvarkappa^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL +1D78D^𝞍^\mathsfbf{\phi}^\mbfsansvarphi^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL +1D78E^𝞎^\mathsfbf{\varrho}^\mbfsansvarrho^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL +1D78F^𝞏^\mathsfbf{\varpi}^\mbfsansvarpi^A^mathalpha^omlmathsfbf^MATHEMATICAL SANS-SERIF BOLD PI SYMBOL +1D790^𝞐^^\mbfitsansAlpha^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA +1D791^𝞑^^\mbfitsansBeta^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA +1D792^𝞒^\mathsfbfit{\Gamma}^\mbfitsansGamma^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA +1D793^𝞓^\mathsfbfit{\Delta}^\mbfitsansDelta^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA +1D794^𝞔^^\mbfitsansEpsilon^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON +1D795^𝞕^^\mbfitsansZeta^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA +1D796^𝞖^^\mbfitsansEta^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA +1D797^𝞗^\mathsfbfit{\Theta}^\mbfitsansTheta^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA +1D798^𝞘^^\mbfitsansIota^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA +1D799^𝞙^^\mbfitsansKappa^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA +1D79A^𝞚^\mathsfbfit{\Lambda}^\mbfitsansLambda^A^mathalpha^isomath^mathematical sans-serif bold italic capital lambda +1D79B^𝞛^^\mbfitsansMu^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU +1D79C^𝞜^^\mbfitsansNu^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU +1D79D^𝞝^\mathsfbfit{\Xi}^\mbfitsansXi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI +1D79E^𝞞^^\mbfitsansOmicron^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON +1D79F^𝞟^\mathsfbfit{\Pi}^\mbfitsansPi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI +1D7A0^𝞠^^\mbfitsansRho^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO +1D7A1^𝞡^^\mbfitsansvarTheta^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL +1D7A2^𝞢^\mathsfbfit{\Sigma}^\mbfitsansSigma^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA +1D7A3^𝞣^^\mbfitsansTau^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU +1D7A4^𝞤^\mathsfbfit{\Upsilon}^\mbfitsansUpsilon^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON +1D7A5^𝞥^\mathsfbfit{\Phi}^\mbfitsansPhi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI +1D7A6^𝞦^^\mbfitsansChi^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI +1D7A7^𝞧^\mathsfbfit{\Psi}^\mbfitsansPsi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI +1D7A8^𝞨^\mathsfbfit{\Omega}^\mbfitsansOmega^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA +1D7A9^𝞩^^\mbfitsansnabla^A^mathord^^MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA +1D7AA^𝞪^\mathsfbfit{\alpha}^\mbfitsansalpha^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA +1D7AB^𝞫^\mathsfbfit{\beta}^\mbfitsansbeta^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA +1D7AC^𝞬^\mathsfbfit{\gamma}^\mbfitsansgamma^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA +1D7AD^𝞭^\mathsfbfit{\delta}^\mbfitsansdelta^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA +1D7AE^𝞮^\mathsfbfit{\varepsilon}^\mbfitsansepsilon^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON +1D7AF^𝞯^\mathsfbfit{\zeta}^\mbfitsanszeta^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA +1D7B0^𝞰^\mathsfbfit{\eta}^\mbfitsanseta^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA +1D7B1^𝞱^\mathsfbfit{\theta}^\mbfitsanstheta^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA +1D7B2^𝞲^\mathsfbfit{\iota}^\mbfitsansiota^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA +1D7B3^𝞳^\mathsfbfit{\kappa}^\mbfitsanskappa^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA +1D7B4^𝞴^\mathsfbfit{\lambda}^\mbfitsanslambda^A^mathalpha^isomath^mathematical sans-serif bold italic small lambda +1D7B5^𝞵^\mathsfbfit{\mu}^\mbfitsansmu^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU +1D7B6^𝞶^\mathsfbfit{\nu}^\mbfitsansnu^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU +1D7B7^𝞷^\mathsfbfit{\xi}^\mbfitsansxi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI +1D7B8^𝞸^^\mbfitsansomicron^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON +1D7B9^𝞹^\mathsfbfit{\pi}^\mbfitsanspi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI +1D7BA^𝞺^\mathsfbfit{\rho}^\mbfitsansrho^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO +1D7BB^𝞻^\mathsfbfit{\varsigma}^\mbfitsansvarsigma^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA +1D7BC^𝞼^\mathsfbfit{\sigma}^\mbfitsanssigma^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA +1D7BD^𝞽^\mathsfbfit{\tau}^\mbfitsanstau^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU +1D7BE^𝞾^\mathsfbfit{\upsilon}^\mbfitsansupsilon^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON +1D7BF^𝞿^\mathsfbfit{\varphi}^\mbfitsansphi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI +1D7C0^𝟀^\mathsfbfit{\chi}^\mbfitsanschi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI +1D7C1^𝟁^\mathsfbfit{\psi}^\mbfitsanspsi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI +1D7C2^𝟂^\mathsfbfit{\omega}^\mbfitsansomega^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA +1D7C3^𝟃^^\mbfitsanspartial^A^mathord^^MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL +1D7C4^𝟄^\mathsfbfit{\epsilon}^\mbfitsansvarepsilon^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL +1D7C5^𝟅^\mathsfbfit{\vartheta}^\mbfitsansvartheta^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL +1D7C6^𝟆^^\mbfitsansvarkappa^A^mathalpha^^MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL +1D7C7^𝟇^\mathsfbfit{\phi}^\mbfitsansvarphi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL +1D7C8^𝟈^\mathsfbfit{\varrho}^\mbfitsansvarrho^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL +1D7C9^𝟉^\mathsfbfit{\varpi}^\mbfitsansvarpi^A^mathalpha^isomath^MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL +1D7CA^𝟊^^\mbfDigamma^A^mathalpha^^MATHEMATICAL BOLD CAPITAL DIGAMMA +1D7CB^𝟋^^\mbfdigamma^A^mathalpha^^MATHEMATICAL BOLD SMALL DIGAMMA +1D7CE^𝟎^\mathbf{0}^^N^mathord^^mathematical bold digit 0 +1D7CF^𝟏^\mathbf{1}^^N^mathord^^mathematical bold digit 1 +1D7D0^𝟐^\mathbf{2}^^N^mathord^^mathematical bold digit 2 +1D7D1^𝟑^\mathbf{3}^^N^mathord^^mathematical bold digit 3 +1D7D2^𝟒^\mathbf{4}^^N^mathord^^mathematical bold digit 4 +1D7D3^𝟓^\mathbf{5}^^N^mathord^^mathematical bold digit 5 +1D7D4^𝟔^\mathbf{6}^^N^mathord^^mathematical bold digit 6 +1D7D5^𝟕^\mathbf{7}^^N^mathord^^mathematical bold digit 7 +1D7D6^𝟖^\mathbf{8}^^N^mathord^^mathematical bold digit 8 +1D7D7^𝟗^\mathbf{9}^^N^mathord^^mathematical bold digit 9 +1D7D8^𝟘^\mathbb{0}^\Bbbzero^N^mathord^bbold^mathematical double-struck digit 0 +1D7D9^𝟙^\mathbb{1}^\Bbbone^N^mathord^bbold fourier^= \mathds{1} (dsfont), mathematical double-struck digit 1 +1D7DA^𝟚^\mathbb{2}^\Bbbtwo^N^mathord^bbold^mathematical double-struck digit 2 +1D7DB^𝟛^\mathbb{3}^\Bbbthree^N^mathord^bbold^mathematical double-struck digit 3 +1D7DC^𝟜^\mathbb{4}^\Bbbfour^N^mathord^bbold^mathematical double-struck digit 4 +1D7DD^𝟝^\mathbb{5}^\Bbbfive^N^mathord^bbold^mathematical double-struck digit 5 +1D7DE^𝟞^\mathbb{6}^\Bbbsix^N^mathord^bbold^mathematical double-struck digit 6 +1D7DF^𝟟^\mathbb{7}^\Bbbseven^N^mathord^bbold^mathematical double-struck digit 7 +1D7E0^𝟠^\mathbb{8}^\Bbbeight^N^mathord^bbold^mathematical double-struck digit 8 +1D7E1^𝟡^\mathbb{9}^\Bbbnine^N^mathord^bbold^mathematical double-struck digit 9 +1D7E2^𝟢^\mathsf{0}^\msanszero^N^mathord^^mathematical sans-serif digit 0 +1D7E3^𝟣^\mathsf{1}^\msansone^N^mathord^^mathematical sans-serif digit 1 +1D7E4^𝟤^\mathsf{2}^\msanstwo^N^mathord^^mathematical sans-serif digit 2 +1D7E5^𝟥^\mathsf{3}^\msansthree^N^mathord^^mathematical sans-serif digit 3 +1D7E6^𝟦^\mathsf{4}^\msansfour^N^mathord^^mathematical sans-serif digit 4 +1D7E7^𝟧^\mathsf{5}^\msansfive^N^mathord^^mathematical sans-serif digit 5 +1D7E8^𝟨^\mathsf{6}^\msanssix^N^mathord^^mathematical sans-serif digit 6 +1D7E9^𝟩^\mathsf{7}^\msansseven^N^mathord^^mathematical sans-serif digit 7 +1D7EA^𝟪^\mathsf{8}^\msanseight^N^mathord^^mathematical sans-serif digit 8 +1D7EB^𝟫^\mathsf{9}^\msansnine^N^mathord^^mathematical sans-serif digit 9 +1D7EC^𝟬^\mathsfbf{0}^\mbfsanszero^N^mathord^mathsfbf^mathematical sans-serif bold digit 0 +1D7ED^𝟭^\mathsfbf{1}^\mbfsansone^N^mathord^mathsfbf^mathematical sans-serif bold digit 1 +1D7EE^𝟮^\mathsfbf{2}^\mbfsanstwo^N^mathord^mathsfbf^mathematical sans-serif bold digit 2 +1D7EF^𝟯^\mathsfbf{3}^\mbfsansthree^N^mathord^mathsfbf^mathematical sans-serif bold digit 3 +1D7F0^𝟰^\mathsfbf{4}^\mbfsansfour^N^mathord^mathsfbf^mathematical sans-serif bold digit 4 +1D7F1^𝟱^\mathsfbf{5}^\mbfsansfive^N^mathord^mathsfbf^mathematical sans-serif bold digit 5 +1D7F2^𝟲^\mathsfbf{6}^\mbfsanssix^N^mathord^mathsfbf^mathematical sans-serif bold digit 6 +1D7F3^𝟳^\mathsfbf{7}^\mbfsansseven^N^mathord^mathsfbf^mathematical sans-serif bold digit 7 +1D7F4^𝟴^\mathsfbf{8}^\mbfsanseight^N^mathord^mathsfbf^mathematical sans-serif bold digit 8 +1D7F5^𝟵^\mathsfbf{9}^\mbfsansnine^N^mathord^mathsfbf^mathematical sans-serif bold digit 9 +1D7F6^𝟶^\mathtt{0}^\mttzero^N^mathord^^mathematical monospace digit 0 +1D7F7^𝟷^\mathtt{1}^\mttone^N^mathord^^mathematical monospace digit 1 +1D7F8^𝟸^\mathtt{2}^\mtttwo^N^mathord^^mathematical monospace digit 2 +1D7F9^𝟹^\mathtt{3}^\mttthree^N^mathord^^mathematical monospace digit 3 +1D7FA^𝟺^\mathtt{4}^\mttfour^N^mathord^^mathematical monospace digit 4 +1D7FB^𝟻^\mathtt{5}^\mttfive^N^mathord^^mathematical monospace digit 5 +1D7FC^𝟼^\mathtt{6}^\mttsix^N^mathord^^mathematical monospace digit 6 +1D7FD^𝟽^\mathtt{7}^\mttseven^N^mathord^^mathematical monospace digit 7 +1D7FE^𝟾^\mathtt{8}^\mtteight^N^mathord^^mathematical monospace digit 8 +1D7FF^𝟿^\mathtt{9}^\mttnine^N^mathord^^mathematical monospace digit 9 diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/css/extras.css elyxer-1.2.5/forks/jras-elyxer/src/css/extras.css --- elyxer-1.2.3/forks/jras-elyxer/src/css/extras.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/css/extras.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,233 @@ +/* +* Extras: colors, footnotes, boxes, spaces... +*/ + +/* Raw colors */ +span.red { + color: #c00000; +} +span.blue { + color: #0000c0; +} +span.green { + color: #00c000; +} +span.magenta { + color: #c000c0; +} +span.cyan { + color: #00c0c0; +} +span.yellow { + color: #c0c000; +} +span.white { + color: #ffffff; +} + +/* Footnotes */ +span.SupFootMarker { + color: #0030c0; + font-size: 0.75em; + line-height: 0.5em; + vertical-align: text-top; +} +span.AlignFootMarker { + color: #0030c0; +} +div.EndFoot { + margin: 0.2ex; + background: #ffffff; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.MarginFoot { + float: right; + clear: right; + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + width: 30%; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.HoverFoot { + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.FootOuter .HoverFoot { + display: none; + position: absolute; +} +span.FootOuter:hover .HoverFoot { + display: inline; + float: none; +} +span.Marginal { + float: right; + clear: right; + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + width: 30%; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.Note { + display: none; +} + +/* Boxes */ +div.framed { + outline-style: solid; +} +div.frameless { +} +div.Frameless { +} +div.Boxed { + outline-width: thin; + outline-style: solid; +} +div.Framed { + outline-width: thin; + outline-style: solid; + line-height: 200%; +} +div.Doublebox { + outline-style: double; +} +div.Shadowbox { + outline-style: outset; +} +div.Shaded { + outline-style: inset; +} +div.ovalbox { + outline-style: groove; +} +div.Ovalbox { + outline-style: ridge; +} +hr.line { + display: inline-block; +} + +/* Spaces */ +span.hspace { + display: inline-block; +} +span.vspace { + display: inline-block; + vertical-align: text-top; +} +span.hfill { + display: inline-block; + margin-left: auto; + margin-right: auto; + min-width: 20mm; + background: #fff0f0; +} +div.defskip { + display: block; + height: 1em; +} +div.smallskip { + display: block; + height: 0.5em; +} +div.medskip { + display: block; + height: 1em; +} +div.bigskip { + display: block; + height: 2em; +} +div.vfill { + display: block; + height: 30em; +} + +/* Sizes */ +span.scriptstyle { + font-size: 0.75em; +} +span.scriptscriptstyle { + font-size: 0.60em; +} + +/* Chunks */ +div.chunk { + width: auto; +} +span.chunkleft span.chunkright { + font-style: normal; +} +span.chunkdecl { + font-style: italic; + padding: 0em 2em; +} +span.chunkref { + font-style: italic; +} + +/* Split Part Navigation */ +div.splitheader { + margin: 0em; + padding: 0.1em; + text-align: center; + background: #f9f9f9; + overflow: auto; +} +span.next { + float: right; + width: 30%; + text-align: right; +} +span.up { + display: inline-block; + width: 30%; + text-align: center; +} +span.prev { + float: left; + width: 30%; + text-align: left; +} +hr.footer { + margin-top: 2em; +} +div.footer { + font-size: 0.90em; + margin: 1em 0; +} + +/* Change Tracking */ +span.inserted { + color: #0000ff; +} +span.deleted { + color: #ff0000; + text-decoration: line-through; +} + +/* Google Charts */ +img.chart { + vertical-align: middle; +} diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/css/freebsd-license.css elyxer-1.2.5/forks/jras-elyxer/src/css/freebsd-license.css --- elyxer-1.2.3/forks/jras-elyxer/src/css/freebsd-license.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/css/freebsd-license.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,16 @@ +/* +* math2html: convert LaTeX equations to HTML output. +* +* Copyright (C) 2009,2010 Alex Fernández +* +* Released under the terms of the `2-Clause BSD license'_, in short: +* Copying and distribution of this file, with or without modification, +* are permitted in any medium without royalty provided the copyright +* notice and this notice are preserved. +* This file is offered as-is, without any warranty. +* +* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause +* +* Based on eLyXer: convert LyX source files to HTML output. +* http://elyxer.nongnu.org/ +*/ diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/css/gpl-license.css elyxer-1.2.5/forks/jras-elyxer/src/css/gpl-license.css --- elyxer-1.2.3/forks/jras-elyxer/src/css/gpl-license.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/css/gpl-license.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,18 @@ +/* +* eLyXer -- convert LyX source files to HTML output. +* +* Copyright (C) 2009-2010 Alex Fernández +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see http://www.gnu.org/licenses/. +*/ diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/css/master.css elyxer-1.2.5/forks/jras-elyxer/src/css/master.css --- elyxer-1.2.3/forks/jras-elyxer/src/css/master.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/css/master.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,372 @@ +/* +* eLyXer -- convert LyX source files to HTML output. +* +* Copyright (C) 2009-2010 Alex Fernández +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see http://www.gnu.org/licenses/. +*/ +/* --end-- +* Global CSS file for LyX documents. +*/ + +body { + font: 90% sans-serif; + background: #f9f9f9; + color: black; + margin: 0; + padding: 0; +} + +#globalWrapper { + margin: 10px 5%; + padding: 20px; + background: #ffffff; + line-height: 1.5em; +} + +/* Basic styles */ +a { + text-decoration: none; + background: none; +} +a:link { + color: #0030c0; +} +a:visited { + color: #603090; +} +a:active { + color: #ffa000; +} +a:hover { + text-decoration: underline; +} +h1 { + margin-top: 1em; + line-height: 1.5em; +} +h1.Part { + text-align: center; +} +h1.Part- { + text-align: center; +} +sup { + font-size: 0.75em; + line-height: 0.5em; + vertical-align: text-top; +} +sub { + font-size: 0.75em; + line-height: 0.5em; + vertical-align: text-bottom; +} +div.Standard { + margin: 1em 0; +} +div.Unindented { + margin: 0; +} +div.Indented { + text-indent: 30pt; + margin: 0; +} +div.Indented * { + text-indent: 0pt; +} +p.dir { + float: right; +} +p.printindex { + font-size: 0.90em; +} +a.printindex { + color: black; +} +table { + display: inline-table; + text-align: center; + border-collapse: collapse; + margin-top: 1em; + margin-bottom: 1em; +} +tr.header { + border-bottom: thin solid #c0c0c0; + background: #ffffff; + font-weight: bold; +} +td { + padding: 1ex; + border: thin solid #f0f0f0; +} +td div.Standard { + margin: 0ex; + padding: 0ex; +} +div.caption div.Standard, div.table div.Standard { + margin: 0ex; + padding: 0ex; +} +td.numeric { + text-align: right; +} +td.empty { + text-align: center; +} +div.right { + text-align: right; +} +div.center { + text-align: center; + margin-left: auto; + margin-right: auto; +} +p.biblio { +} +div.Paragraph, div.Paragraph- { + font-weight: bold; + font-size: 103%; +} +span.versalitas, span.noun { + font-variant: small-caps; +} +span.sans { + font-family: sans-serif; +} +span.code { + font-family: monospace; +} +div.Plain { + display: inline; + width: auto; +} +h2 { + line-height: 1.4em; +} +span.Description-entry { + font-weight: bold; +} +span.List-entry { + display: inline-block; + width: 25%; + vertical-align: text-top; +} +span.List-contents { + display: inline-block; + width: 75%; + vertical-align: text-top; +} +div.Space { + display: none; +} +span.appendix { + display: none; +} +h1.biblio { +} +span.greyedout { + color: #808080; +} +div.Description, div.List, li { + margin: 1em 0; +} +li.nested { + list-style-type: none; +} +span.Info { + background: #f0f0f0; + border: thin solid #c0c0c0; +} +pre { + padding: 0em; + margin: 0em; + width: auto; + font-family: monospace; + line-height: 1.5em; +} +pre.LyX-Code { + margin: 0.5em 3em; +} +a.Label { + text-decoration: none; + color: #000000; +} +span.phantom { + color: #ffffff; +} +a.biblioentry { + color: black; +} +span.menuitem { + font-size: 105%; +} +span.normal { + font-style: normal; +} +div.PlainVisible { + width: auto; +} +div.indexgroup { + margin-left: 2em; +} +span.strong { + font-weight: bold; +} + +/* Figures and Tables */ +img.embedded { + width: 100%; + _width: auto; +} +div.float { + margin-top: 1ex; + margin-bottom: 1ex; + text-align: center; +} +span.float { + margin-top: 1ex; + margin-bottom: 1ex; + text-align: center; +} +div.figure { + display: inline-block; + text-align: left; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.table { + display: inline-block; + text-align: left; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.algorithm { + display: inline-block; + text-align: left; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.caption { + text-align: center; + font-family: sans-serif; + margin-left: auto; + margin-right: auto; + padding: 0.5ex; +} +img.figure { + width: 100%; + _width: auto; +} +div.multifigure { + padding: 1ex; + width: 100%; +} +div.multitable { + display: inline-block; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.multialgorithm { + display: inline-block; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.wrap-l, div.wrap-o, div.wrap-i { + margin: 2ex; + float: left; +} +div.wrap-r { + margin: 2ex; + float: right; +} +div.listing { + display: inline-block; + text-align: left; + margin-left: auto; + margin-right: auto; + padding: 0.5ex; + border: thin solid #c0c0c0; +} +span.number-left { + float: left; + background: #f0f0f0; + width: 3em; + text-align: right; + margin-right: 1em; +} +span.number-right { + float: right; + background: #f0f0f0; + width: 3em; + text-align: right; + margin-left: 1em; +} + +/* Header */ +h1.title { + text-align: center; +} +h2.author { + text-align: center; +} +h2.Date { + text-align: center; +} +div.abstract { + margin: 1em 3em; + text-align: left; + font-size: 0.95em; +} +p.abstract-message { + text-align: center; + font-weight: bold; +} +div.tocheader { + margin: 1em 0; + font-size: large; +} +a.toc { + color: black; +} +div.tocindent { + padding: 0 0 0 2em; +} +div.toc { + margin: 0.5em 0; + font-size: 0.95em; +} +div.fulltoc { + padding: 1em; +} +div.warning { + font-size: 120%; + color:#cc0000; +} +div.Institute { + text-align: center; +} +@import "extras.css"; +@import "math.css"; +@import "obsolete.css"; +@import "print.css"; diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/css/math-extras.css elyxer-1.2.5/forks/jras-elyxer/src/css/math-extras.css --- elyxer-1.2.3/forks/jras-elyxer/src/css/math-extras.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/css/math-extras.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,86 @@ +/* +* CSS file for LaTeX formulas, extra stuff: +* binomials, vertical braces, stackrel, fonts and colors. +*/ + +/* Inline binomials */ +span.binom { + display: inline-block; + vertical-align: middle; + text-align: center; + font-size: 80%; +} +span.binomstack { + display: block; + padding: 0em; +} + +/* Over- and underbraces */ +span.overbrace { + border-top: 2pt solid; +} +span.underbrace { + border-bottom: 2pt solid; +} + +/* Stackrel */ +span.stackrel { + display: inline-block; + text-align: center; +} +span.upstackrel { + display: block; + padding: 0em; + font-size: 80%; + line-height: 64%; + position: relative; + top: 0.15em; + +} +span.downstackrel { + display: block; + vertical-align: bottom; + padding: 0em; +} + +/* Fonts */ +span.mathsf, span.textsf { + font-style: normal; + font-family: sans-serif; +} +span.mathrm, span.textrm { + font-style: normal; + font-family: serif; +} +span.text, span.textnormal { + font-style: normal; +} +span.textipa { + color: #008080; +} +span.fraktur { + font-family: "Lucida Blackletter", eufm10, blackletter; +} +span.blackboard { + font-family: Blackboard, msbm10, serif; +} +span.scriptfont { + font-family: "Monotype Corsiva", "Apple Chancery", "URW Chancery L", cursive; + font-style: italic; +} + +/* Colors */ +span.colorbox { + display: inline-block; + padding: 5px; +} +span.fbox { + display: inline-block; + border: thin solid black; + padding: 2px; +} +span.boxed, span.framebox { + display: inline-block; + border: thin solid black; + padding: 5px; +} diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/css/math.css elyxer-1.2.5/forks/jras-elyxer/src/css/math.css --- elyxer-1.2.3/forks/jras-elyxer/src/css/math.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/css/math.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,173 @@ +/* --end-- +* CSS file for LaTeX formulas. +*/ + +/* Formulas */ +.formula { + text-align: center; + font-family: "DejaVu Serif", serif; + margin: 1.2em 0; +} +span.formula { + white-space: nowrap; +} +div.formula { + padding: 0.5ex; + margin-left: auto; + margin-right: auto; +} + +/* Basic features */ +a.eqnumber { + display: inline-block; + float: right; + clear: right; + font-weight: bold; +} +span.unknown { + color: #800000; +} +span.ignored, span.arraydef { + display: none; +} +.formula i { + letter-spacing: 0.1ex; +} + +/* Alignment */ +.align-left, .align-l { + text-align: left; +} +.align-right, .align-r { + text-align: right; +} +.align-center, .align-c { + text-align: center; +} + +/* Structures */ +span.overline, span.bar { + text-decoration: overline; +} +.fraction, .fullfraction { + display: inline-block; + vertical-align: middle; + text-align: center; +} +.fraction .fraction { + font-size: 80%; + line-height: 100%; +} +span.numerator { + display: block; +} +span.denominator { + display: block; + padding: 0ex; + border-top: thin solid; +} +sup.numerator, sup.unit { + font-size: 70%; + vertical-align: 80%; +} +sub.denominator, sub.unit { + font-size: 70%; + vertical-align: -20%; +} +span.sqrt { + display: inline-block; + vertical-align: middle; + padding: 0.1ex; +} +sup.root { + font-size: 70%; + position: relative; + left: 1.4ex; +} +span.radical { + display: inline-block; + padding: 0ex; + font-size: 150%; + vertical-align: top; +} +span.root { + display: inline-block; + border-top: thin solid; + padding: 0ex; + vertical-align: middle; +} +span.symbol { + font-size: 125%; +} +span.bigsymbol { + font-size: 150%; +} +span.largesymbol { + font-size: 175%; +} +span.hugesymbol { + font-size: 200%; +} +span.scripts { + display: inline-table; + vertical-align: middle; +} +.script { + display: table-row; + text-align: left; + line-height: 150%; +} +span.limits { + display: inline-table; + vertical-align: middle; +} +.limit { + display: table-row; + line-height: 95%; +} +sup.limit, sub.limit { + line-height: 150%; +} +span.symbolover { + display: inline-block; + text-align: center; + position: relative; + float: right; + right: 100%; + bottom: 0.5em; + width: 0px; +} +span.withsymbol { + display: inline-block; +} +span.symbolunder { + display: inline-block; + text-align: center; + position: relative; + float: right; + right: 80%; + top: 0.3em; + width: 0px; +} + +/* Environments */ +span.array, span.bracketcases, span.binomial, span.environment { + display: inline-table; + text-align: center; + border-collapse: collapse; + margin: 0em; + vertical-align: middle; +} +span.arrayrow, span.binomrow { + display: table-row; + padding: 0ex; + border: 0ex; +} +span.arraycell, span.bracket, span.case, span.binomcell, span.environmentcell { + display: table-cell; + padding: 0ex 0.2ex; + line-height: 99%; + border: 0ex; +} +@import "math-extras.css"; + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/css/obsolete.css elyxer-1.2.5/forks/jras-elyxer/src/css/obsolete.css --- elyxer-1.2.3/forks/jras-elyxer/src/css/obsolete.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/css/obsolete.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,148 @@ +/* +* Obsolete definitions, kept for backwards compatibility. +*/ + +/* Footnotes */ +span.FootMarker { + color: #0030c0; + font-size: 0.75em; + line-height: 0.5em; + vertical-align: text-top; +} +span.Foot { + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.FootOuter .Foot { + display: none; + position: absolute; +} +span.FootOuter:hover .Foot { + display: inline; + float: none; +} + +/* Dotted box */ +span.dotted { + border-top: thin dotted; +} + +/* Obsolete aligned structures */ +span.numerator-l { + display: block; + text-align: left; +} +span.numerator-r { + display: block; + text-align: right; +} +span.numeratorl { + display: block; + text-align: left; +} +span.numeratorr { + display: block; + text-align: right; +} +span.framebox- { + display: inline-block; + border: thin solid black; + text-align: center; + padding: 5px; +} +span.framebox-l { + display: inline-block; + border: thin solid black; + text-align: left; + padding: 5px; +} +span.framebox-r { + display: inline-block; + border: thin solid black; + text-align: right; + padding: 5px; +} +td.formula-l { + text-align: left; + padding: 0.2ex; + border: 0ex; +} +td.formula-c { + text-align: center; + padding: 0.2ex; + border: 0ex; +} +td.formula-r { + text-align: right; + padding: 0.2ex; + border: 0ex; +} + +/* Obsolete limits */ +sub.bigsymbol { + display: table-row; + text-align: left; + line-height: 150%; +} +sup.bigsymbol { + display: table-row; + text-align: left; + line-height: 150%; +} + +/* Obsolete cases */ +table.cases { + display: inline-block; + text-align: center; + border-collapse: collapse; + margin: 0.2em; + border-left: thin solid; + vertical-align: middle; +} +table.cases tr td { + padding-left: 1ex; + padding-right: 1em; +} + +/* Obsolete binomials */ +span.fullbinom { + display: inline-block; + vertical-align: middle; + text-align: center; +} +span.upbinom { + display: block; + padding: 0em; +} +span.downbinom { + display: block; + padding: 0em; +} + +/* Obsolete environments */ +table.formula { + display: inline-block; + text-align: center; + border-collapse: collapse; + margin: 0em; + vertical-align: middle; +} +td.formula { + padding: 0.2ex; + border: 0ex; +} +table.environment { + display: inline-block; + text-align: right; + margin: 0; + vertical-align: middle; +} +table.environment tr td { + padding: 0 1em; +} diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/css/print.css elyxer-1.2.5/forks/jras-elyxer/src/css/print.css --- elyxer-1.2.3/forks/jras-elyxer/src/css/print.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/css/print.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,53 @@ +/* +* CSS section for print. +*/ +@media print { +body { + font: 90% serif; + background: #ffffff; + color: black; + margin: 0; + padding: 0; +} +#globalWrapper { + width: 100%; + margin: 0px; + padding: 0px; + background: #ffffff; + line-height: 1.5em; +} +span.FootOuter .Foot { + display: block; + position: relative; + float: right; + clear: right; + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + width: 30%; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.FootOuter .HoverFoot { + display: block; + position: relative; + float: right; + clear: right; + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + width: 30%; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +a:visited { + color: #0030c0; +} +/* end of print CSS */ +} diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/bib/biblio.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/bib/biblio.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/bib/biblio.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/bib/biblio.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,158 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090415 +# eLyXer bibliography + +from elyxer.util.numbering import * +from elyxer.util.docparams import * +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.ref.link import * +from elyxer.gen.layout import * +from elyxer.proc.postprocess import * + + +class BiblioCitation(Container): + "A complete bibliography citation (possibly with many cites)." + + citations = dict() + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="bibcites"') + self.contents = [] + + def process(self): + "Process the complete citation and all cites within." + self.contents = [Constant('[')] + keys = self.getparameterlist('key') + for key in keys: + self.contents += [BiblioCite().create(key), Constant(', ')] + if len(keys) > 0: + # remove trailing , + self.contents.pop() + self.contents.append(Constant(']')) + +class BiblioCite(Link): + "Cite of a bibliography entry" + + cites = dict() + + def create(self, key): + "Create the cite to the given key." + self.key = key + number = NumberGenerator.generator.generate('bibliocite') + ref = BiblioReference().create(key, number) + self.complete(number, 'cite-' + number, type='bibliocite') + self.setmutualdestination(ref) + if not key in BiblioCite.cites: + BiblioCite.cites[key] = [] + BiblioCite.cites[key].append(self) + return self + +class Bibliography(Container): + "A bibliography layout containing an entry" + + def __init__(self): + self.parser = BoundedParser() + self.output = TaggedOutput().settag('p class="biblio"', True) + +class BiblioHeader(Container): + "The header of the bibliography." + + def __init__(self): + "Create the header for the bibliography section." + self.type = 'biblio' + self.output = ContentsOutput() + self.name = Translator.translate(DocumentParameters.bibliography) + self.contents = [TaggedText().constant(self.name, 'h1 class="biblio"', True)] + + def addtotoc(self, parent): + "Add the bibliography header to the TOC." + self.parent = parent + self.partkey = PartKeyGenerator.forindex(self) + if not self.partkey: + return + self.partkey.addtoclabel(self) + while parent: + parent.partkey = self.partkey + parent = parent.parent + +class PostBiblio(object): + "Insert a Bibliography legend before the first item" + + processedclass = Bibliography + + def postprocess(self, last, element, next): + "If we have the first bibliography insert a tag" + if isinstance(last, Bibliography) or Options.nobib: + return element + layout = StandardLayout() + header = BiblioHeader() + header.addtotoc(layout) + layout.complete([header, element]) + return layout + +Postprocessor.stages += [PostBiblio] + +class BiblioReference(Link): + "A reference to a bibliographical entry." + + references = dict() + + def create(self, key, number): + "Create the reference with the given key and number." + self.key = key + self.complete(number, 'biblio-' + number, type='biblioentry') + if not key in BiblioReference.references: + BiblioReference.references[key] = [] + BiblioReference.references[key].append(self) + return self + +class BiblioEntry(Container): + "A bibliography entry" + + entries = dict() + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="entry"') + self.contents = [] + + def process(self): + "Process the cites for the entry's key" + self.citeref = [Constant(NumberGenerator.generator.generate('biblioentry'))] + self.processcites(self.getparameter('key')) + + def processcites(self, key): + "Get all the cites of the entry" + self.key = key + if not key in BiblioReference.references: + self.contents.append(Constant('[-] ')) + return + self.contents = [Constant('[')] + for ref in BiblioReference.references[key]: + self.contents.append(ref) + self.contents.append(Constant(',')) + self.contents.pop(-1) + self.contents.append(Constant('] ')) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/bib/pub.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/bib/pub.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/bib/pub.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/bib/pub.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,222 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20100606 +# eLyXer BibTeX publication entries. + +from elyxer.util.trace import Trace +from elyxer.out.output import * +from elyxer.conf.config import * +from elyxer.parse.position import * +from elyxer.ref.link import * +from elyxer.bib.tex import * +from elyxer.bib.tag import * + + +class PubEntry(BibEntry): + "A publication entry" + + def __init__(self): + self.output = TaggedOutput().settag('p class="biblio"', True) + + def detect(self, pos): + "Detect a publication entry." + return pos.checkfor('@') + + def parse(self, pos): + "Parse the publication entry." + self.parser = BibTagParser() + self.parser.parse(pos) + self.type = self.parser.type + + def isvisible(self): + "A publication entry is always visible." + return True + + def isreferenced(self): + "Check if the entry is referenced." + if not self.parser.key: + return False + return self.parser.key in BiblioReference.references + + def process(self): + "Process the entry." + self.index = NumberGenerator.generator.generate('pubentry') + self.parser.tags['index'] = Constant(self.index) + biblio = BiblioEntry() + biblio.citeref = self.createref() + biblio.processcites(self.parser.key) + self.contents = [biblio, Constant(' ')] + self.contents += self.entrycontents() + + def entrycontents(self): + "Get the contents of the entry." + return self.translatetemplate(self.template) + + def createref(self): + "Create the reference to cite." + return self.translatetemplate(self.citetemplate) + + def translatetemplate(self, template): + "Translate a complete template into a list of contents." + pos = TextPosition(template) + part = BibPart(self.parser.tags).parse(pos) + for variable in part.searchall(BibVariable): + if variable.empty(): + Trace.error('Error parsing BibTeX template for ' + unicode(self) + ': ' + + unicode(variable) + ' is empty') + return [part] + + def __unicode__(self): + "Return a string representation" + string = '' + if 'author' in self.parser.tags: + string += self.parser.gettagtext('author') + ': ' + if 'title' in self.parser.tags: + string += '"' + self.parser.gettagtext('title') + '"' + return string + +class BibPart(Container): + "A part of a BibTeX template." + + def __init__(self, tags): + self.output = ContentsOutput() + self.contents = [] + self.tags = tags + self.quotes = 0 + + def parse(self, pos): + "Parse a part of a template, return a list of contents." + while not pos.finished(): + self.add(self.parsepiece(pos)) + return self + + def parsepiece(self, pos): + "Get the next piece of the template, return if it was empty." + if pos.checkfor('{'): + return self.parsebraces(pos) + elif pos.checkfor('$'): + return self.parsevariable(pos) + result = '' + while not pos.finished() and not pos.current() in '{$': + if pos.current() == '"': + self.quotes += 1 + result += pos.skipcurrent() + return Constant(result) + + def parsebraces(self, pos): + "Parse a pair of curly braces {}." + if not pos.checkskip('{'): + Trace.error('Missing { in braces.') + return None + pos.pushending('}') + part = BibPart(self.tags).parse(pos) + pos.popending('}') + empty = part.emptyvariables() + if empty: + return None + return part + + def parsevariable(self, pos): + "Parse a variable $name." + var = BibVariable(self.tags).parse(pos) + if self.quotes % 2 == 1: + # odd number of quotes; don't add spans in an attribute + var.removetag() + return var + + def emptyvariables(self): + "Find out if there are only empty variables in the part." + for variable in self.searchall(BibVariable): + if not variable.empty(): + return False + return True + + def add(self, piece): + "Add a new piece to the current part." + if not piece: + return + if self.redundantdot(piece): + # remove extra dot + piece.string = piece.string[1:] + self.contents.append(piece) + piece.parent = self + + def redundantdot(self, piece): + "Find out if there is a redundant dot in the next piece." + if not isinstance(piece, Constant): + return False + if not piece.string.startswith('.'): + return False + if len(self.contents) == 0: + return False + if not isinstance(self.contents[-1], BibVariable): + return False + if not self.contents[-1].extracttext().endswith('.'): + return False + return True + +class BibVariable(Container): + "A variable in a BibTeX template." + + def __init__(self, tags): + self.output = TaggedOutput() + self.contents = [] + self.tags = tags + + def parse(self, pos): + "Parse the variable name." + if not pos.checkskip('$'): + Trace.error('Missing $ in variable name.') + return self + self.key = pos.globalpha() + self.output.tag = 'span class="bib-' + self.key + '"' + self.processtags() + return self + + def processtags(self): + "Find the tag with the appropriate key in the list of tags." + if not self.key in self.tags: + return + result = self.tags[self.key] + self.contents = [result] + + def empty(self): + "Find out if the variable is empty." + if not self.contents: + return True + if self.extracttext() == '': + return True + return False + + def removetag(self): + "Remove the output tag and leave just the contents." + self.output = ContentsOutput() + + def __unicode__(self): + "Return a printable representation." + result = 'variable ' + self.key + if not self.empty(): + result += ':' + self.extracttext() + return result + +BibEntry.instances += [PubEntry()] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/bib/tag.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/bib/tag.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/bib/tag.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/bib/tag.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,301 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20101027 +# eLyXer BibTeX tag parsing + +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.conf.config import * +from elyxer.parse.position import * +from elyxer.gen.container import * +from elyxer.maths.formula import * +from elyxer.maths.command import * +from elyxer.tex.texcode import * + + +class BibTagParser(object): + "A parser for BibTeX tags." + + nameseparators = ['{', '=', '"', '#'] + + def __init__(self): + self.key = None + tags = BibStylesConfig.defaulttags + self.tags = dict((x, BibTag().constant(tags[x])) for x in tags) + + def parse(self, pos): + "Parse the entry between {}." + self.type = pos.globexcluding(self.nameseparators).strip() + if not pos.checkskip('{'): + pos.error('Entry should start with {') + return + pos.pushending('}') + self.parsetags(pos) + pos.popending('}') + pos.skipspace() + + def parsetags(self, pos): + "Parse all tags in the entry." + pos.skipspace() + while not pos.finished(): + if pos.checkskip('{'): + pos.error('Unmatched {') + return + pos.pushending(',', True) + self.parsetag(pos) + if pos.checkfor(','): + pos.popending(',') + + def parsetag(self, pos): + "Parse a single tag." + (key, value) = self.getkeyvalue(pos) + if not key: + return + if not value: + self.key = key + return + name = key.lower() + self.tags[name] = value + if hasattr(self, 'dissect' + name): + dissector = getattr(self, 'dissect' + name) + dissector(value.extracttext()) + if not pos.finished(): + remainder = pos.globexcluding(',') + pos.error('Ignored ' + remainder + ' before comma') + + def getkeyvalue(self, pos): + "Parse a string of the form key=value." + piece = pos.globexcluding(self.nameseparators).strip() + if pos.finished(): + return (piece, None) + if not pos.checkskip('='): + pos.error('Undesired character in tag name ' + piece) + pos.skipcurrent() + return (piece, None) + key = piece.lower() + pos.skipspace() + value = self.parsevalue(pos) + return (key, value) + + def parsevalue(self, pos): + "Parse the value for a tag." + tag = BibTag() + pos.skipspace() + if pos.checkfor(','): + pos.error('Unexpected ,') + return tag.error() + tag.parse(pos) + return tag + + def dissectauthor(self, authortag): + "Dissect the author tag into pieces." + authorsplit = authortag.split(' and ') + if len(authorsplit) == 0: + return + authorlist = [] + for authorname in authorsplit: + author = BibAuthor().parse(authorname) + authorlist.append(author) + initials = '' + authors = '' + if len(authorlist) == 1: + initials = authorlist[0].surname[0:3] + authors = unicode(authorlist[0]) + else: + for author in authorlist: + initials += author.surname[0:1] + authors += unicode(author) + ', ' + authors = authors[:-2] + self.tags['surname'] = BibTag().constant(authorlist[0].surname) + self.tags['Sur'] = BibTag().constant(initials) + self.tags['authors'] = BibTag().constant(authors) + + def dissectyear(self, yeartag): + "Dissect the year tag into pieces, looking for 4 digits in a row." + pos = TextPosition(yeartag) + while not pos.finished(): + if pos.current().isdigit(): + number = pos.globnumber() + if len(number) == 4: + self.tags['YY'] = BibTag().constant(number[2:]) + return + else: + pos.skipcurrent() + + def dissectfile(self, filetag): + "Extract the filename from elyxer.the file tag as ':filename:FORMAT'." + if not filetag.startswith(':'): + return + bits = filetag.split(':') + if len(bits) != 3: + return + self.tags['filename'] = BibTag().constant(bits[1]) + self.tags['format'] = BibTag().constant(bits[2]) + + def gettag(self, key): + "Get the tag for a given key." + if not key in self.tags: + return None + return self.tags[key] + + def gettagtext(self, key): + "Get the tag for a key as raw text." + return self.gettag(key).extracttext() + +class BibTag(Container): + "A tag in a BibTeX file." + + valueseparators = ['{', '"', '#', '}'] + stringdefs = dict() + + def __init__(self): + self.contents = [] + self.output = ContentsOutput() + + def constant(self, text): + "Initialize for a single constant." + self.contents = [Constant(text)] + return self + + def error(self): + "To use when parsing resulted in an error." + return self.constant('') + + def parse(self, pos): + "Parse brackets or quotes at the first level." + while not pos.finished(): + self.parsetext(pos) + if pos.finished(): + return + elif pos.checkfor('{'): + self.parsebracket(pos) + elif pos.checkfor('"'): + self.parsequoted(pos) + elif pos.checkfor('#'): + self.parsehash(pos) + else: + pos.error('Unexpected character ' + pos.current()) + pos.skipcurrent() + + def parsetext(self, pos): + "Parse a bit of text, try to substitute strings with string defs." + text = pos.globexcluding(self.valueseparators) + key = text.strip() + if key == '': + return + if key in self.stringdefs: + self.add(self.stringdefs[key]) + return + self.add(Constant(key)) + + def add(self, piece): + "Add a new piece to the tag." + self.contents.append(piece) + + def parsetex(self, pos): + "Parse some TeX code." + tex = TeXCode() + tex.parse(pos) + self.add(tex) + + def parsebracket(self, pos): + "Parse a {} bracket" + if not pos.checkskip('{'): + pos.error('Missing opening { in bracket') + return + pos.pushending('}') + self.parsetex(pos) + pos.popending('}') + + def parsequoted(self, pos): + "Parse a piece of quoted text" + if not pos.checkskip('"'): + pos.error('Missing opening " in quote') + return + pos.pushending('"') + self.parsetex(pos) + pos.popending('"') + pos.skipspace() + + def parsehash(self, pos): + "Parse a hash mark #." + if not pos.checkskip('#'): + pos.error('Missing # in hash') + return + + def __unicode__(self): + "Return a printable representation." + return 'BibTag: ' + self.extracttext() + +class BibAuthor(object): + "A BibTeX individual author." + + def __init__(self): + self.surname = '' + self.firstnames = [] + + def parse(self, tag): + "Parse an individual author tag." + if ',' in tag: + self.parsecomma(tag) + else: + self.parsewithoutcomma(tag) + return self + + def parsecomma(self, tag): + "Parse an author with a comma: Python, M." + bits = tag.split(',') + if len(bits) > 2: + Trace.error('Too many commas in ' + tag) + self.surname = bits[0].strip() + self.parsefirstnames(bits[1].strip()) + + def parsewithoutcomma(self, tag): + "Parse an author without a comma: M. Python." + bits = tag.rsplit(None, 1) + if len(bits) == 0: + Trace.error('Empty author') + ppp() + return + self.surname = bits[-1].strip() + if len(bits) == 1: + return + self.parsefirstnames(bits[0].strip()) + + def parsefirstnames(self, firstnames): + "Parse the first name." + for firstname in firstnames.split(): + self.firstnames.append(firstname) + + def getinitial(self): + "Get the main initial for the author." + if len(self.surname) == 0: + return '' + return self.surname[0].toupper() + + def __unicode__(self): + "Return a printable representation." + result = '' + for firstname in self.firstnames: + result += firstname + ' ' + return result + self.surname + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/bib/tex.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/bib/tex.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/bib/tex.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/bib/tex.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,273 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090905 +# eLyXer BibTeX processing + +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.out.output import * +from elyxer.io.path import * +from elyxer.io.bulk import * +from elyxer.conf.config import * +from elyxer.parse.position import * +from elyxer.ref.link import * +from elyxer.bib.biblio import * +from elyxer.bib.tag import * + + +class BibTeX(Container): + "Show a BibTeX bibliography and all referenced entries" + + def __init__(self): + self.parser = InsetParser() + self.output = ContentsOutput() + + def process(self): + "Read all bibtex files and process them." + self.entries = [] + self.contents = [self.createheader()] + bibliography = Translator.translate('bibliography') + files = self.getparameterlist('bibfiles') + showall = False + if self.getparameter('btprint') == 'btPrintAll': + showall = True + for file in files: + bibfile = BibFile(file, showall) + bibfile.parse() + self.entries += bibfile.entries + Trace.message('Parsed ' + unicode(bibfile)) + self.entries.sort(key = unicode) + self.applystyle() + + def createheader(self): + "Create the header for the bibliography." + header = BiblioHeader() + if 'bibtotoc' in self.getparameterlist('options'): + header.addtotoc(self) + return header + + def applystyle(self): + "Read the style and apply it to all entries" + style = self.readstyle() + for entry in self.entries: + entry.template = style['default'] + entry.citetemplate = style['cite'] + type = entry.type.lower() + if type in style: + entry.template = style[type] + entry.process() + self.contents.append(entry) + + def readstyle(self): + "Read the style from elyxer.the bibliography options" + for option in self.getparameterlist('options'): + if hasattr(BibStylesConfig, option): + return getattr(BibStylesConfig, option) + return BibStylesConfig.default + +class BibFile(object): + "A BibTeX file" + + def __init__(self, filename, showall): + "Create the BibTeX file" + self.filename = filename + '.bib' + self.showall = showall + self.added = 0 + self.ignored = 0 + self.entries = [] + + def parse(self): + "Parse the BibTeX file and extract all entries." + try: + self.parsefile() + except IOError: + Trace.error('Error reading ' + self.filename + '; make sure the file exists and can be read.') + + def parsefile(self): + "Parse the whole file." + bibpath = InputPath(self.filename) + if Options.lowmem: + pos = FilePosition(bibpath.path) + else: + bulkfile = BulkFile(bibpath.path) + text = ''.join(bulkfile.readall()) + pos = TextPosition(text) + while not pos.finished(): + pos.skipspace() + if pos.checkskip(','): + pos.skipspace() + self.parseentry(pos) + + def parseentry(self, pos): + "Parse a single entry" + for entry in BibEntry.instances: + if entry.detect(pos): + newentry = Cloner.clone(entry) + newentry.parse(pos) + if not newentry.isvisible(): + return + if self.showall or newentry.isreferenced(): + self.entries.append(newentry) + self.added += 1 + else: + Trace.debug('Ignored entry ' + unicode(newentry)) + self.ignored += 1 + return + # Skip the whole line since it's a comment outside an entry + pos.globincluding('\n').strip() + + def __unicode__(self): + "String representation" + string = self.filename + ': ' + unicode(self.added) + ' entries added, ' + string += unicode(self.ignored) + ' entries ignored' + return string + +class BibEntry(Container): + "An entry in a BibTeX file" + + instances = [] + + def detect(self, pos): + "Throw an error." + Trace.error('Tried to detect() in ' + unicode(self)) + + def parse(self, pos): + "Throw an error." + Trace.error('Tried to parse() in ' + unicode(self)) + + def isvisible(self): + "Return if the entry should be visible. Throws an error." + Trace.error('Function isvisible() not implemented for ' + unicode(self)) + + def isreferenced(self): + "Return if the entry is referenced. Throws an error." + Trace.error('Function isreferenced() not implemented for ' + unicode(self)) + + def __unicode__(self): + "Return a string representation" + return 'BibTeX entry ' + self.__class__.__name__ + +class CommentEntry(BibEntry): + "A simple comment." + + def detect(self, pos): + "Detect the special entry" + return pos.checkfor('%') + + def parse(self, pos): + "Parse all consecutive comment lines." + while pos.checkfor('%'): + pos.globincluding('\n') + + def isvisible(self): + "A comment entry is never visible." + return False + + def __unicode__(self): + "Return a string representation" + return 'Comment' + +class SpecialEntry(BibEntry): + "A special entry" + + types = ['@preamble', '@comment'] + + def __init__(self): + self.contents = [] + self.output = EmptyOutput() + + def detect(self, pos): + "Detect the special entry" + for type in self.types: + if pos.checkforlower(type): + return True + return False + + def parse(self, pos): + "Parse and ignore." + self.type = 'special' + pos.globincluding('{') + pos.pushending('}') + while not pos.finished(): + if pos.checkfor('{'): + self.parse(pos) + else: + pos.skipcurrent() + pos.popending() + + def isvisible(self): + "A special entry is never visible." + return False + + def __unicode__(self): + "Return a string representation" + return self.type + +class StringEntry(SpecialEntry): + "A string definition. The definition can later be used in other entries." + + parser = BibTagParser() + start = '@string' + key = None + + def detect(self, pos): + "Detect the string definition." + return pos.checkforlower(self.start) + + def parse(self, pos): + "Parse a single tag, which will define a string." + self.type = self.start + if not self.checkstart(pos): + return + pos.skipspace() + if not pos.checkskip('{'): + Trace.error('Missing opening { in ' + unicode(self)) + pos.globincluding('\n') + return + pos.pushending('}') + (self.key, value) = self.parser.getkeyvalue(pos) + BibTag.stringdefs[self.key] = value + pos.popending('}') + + def checkstart(self, pos): + "Check that the entry starts with @string." + if not pos.checkskip('@'): + Trace.error('Missing @ from elyxer.string definition') + return False + name = '@' + pos.globalpha() + if not name.lower() == self.start.lower(): + Trace.error('Invalid start @' + name +', missing ' + self.start + ' from elyxer.' + unicode(self)) + pos.globincluding('\n') + return False + return True + + def __unicode__(self): + "Return a printable representation." + result = 'string definition' + if self.key: + result += ' for ' + self.key + return result + + +# More instances will be added later +BibEntry.instances += [CommentEntry(), SpecialEntry(), StringEntry()] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/config.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/config.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/config.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/config.py 2013-03-10 10:39:35.000000000 +0000 @@ -0,0 +1,912 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer configuration +# autogenerated from elyxer.config file on 2013-03-10 + +class BibStylesConfig(object): + "Configuration class from elyxer.config file" + + abbrvnat = { + + u'@article':u'$authors. $title. <i>$journal</i>,{ {$volume:}$pages,} $month $year.{ doi: $doi.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'cite':u'$surname($year)', + u'default':u'$authors. <i>$title</i>. $publisher, $year.{ URL <a href="$url">$url</a>.}{ $note.}', + } + + alpha = { + + u'@article':u'$authors. $title.{ <i>$journal</i>{, {$volume}{($number)}}{: $pages}{, $year}.}{ <a href="$url">$url</a>.}{ <a href="$filename">$filename</a>.}{ $note.}', + u'cite':u'$Sur$YY', + u'default':u'$authors. $title.{ <i>$journal</i>,} $year.{ <a href="$url">$url</a>.}{ <a href="$filename">$filename</a>.}{ $note.}', + } + + authordate2 = { + + u'@article':u'$authors. $year. $title. <i>$journal</i>, <b>$volume</b>($number), $pages.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@book':u'$authors. $year. <i>$title</i>. $publisher.{ URL <a href="$url">$url</a>.}{ $note.}', + u'cite':u'$surname, $year', + u'default':u'$authors. $year. <i>$title</i>. $publisher.{ URL <a href="$url">$url</a>.}{ $note.}', + } + + default = { + + u'@article':u'$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@book':u'{$authors: }<i>$title</i>{ ($editor, ed.)}.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@booklet':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@conference':u'$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@inbook':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@incollection':u'$authors: <i>$title</i>{ in <i>$booktitle</i>{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@inproceedings':u'$authors: “$title”, <i>$booktitle</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@manual':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@mastersthesis':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@misc':u'$authors: <i>$title</i>.{{ $publisher,}{ $howpublished,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@phdthesis':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@proceedings':u'$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@techreport':u'$authors: <i>$title</i>, $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@unpublished':u'$authors: “$title”, <i>$journal</i>, $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + } + + defaulttags = { + u'YY':u'??', u'authors':u'', u'surname':u'', + } + + ieeetr = { + + u'@article':u'$authors, “$title”, <i>$journal</i>, vol. $volume, no. $number, pp. $pages, $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@book':u'$authors, <i>$title</i>. $publisher, $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors, “$title”. $year.{ URL <a href="$url">$url</a>.}{ $note.}', + } + + plain = { + + u'@article':u'$authors. $title.{ <i>$journal</i>{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'@book':u'$authors. <i>$title</i>. $publisher,{ $month} $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@incollection':u'$authors. $title.{ In <i>$booktitle</i> {($editor, ed.)}.} $publisher,{ $month} $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@inproceedings':u'$authors. $title. { <i>$booktitle</i>{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL <a href="$url">$url</a>.}{ $note.}', + u'cite':u'$index', + u'default':u'{$authors. }$title.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', + } + + vancouver = { + + u'@article':u'$authors. $title. <i>$journal</i>, $year{;{<b>$volume</b>}{($number)}{:$pages}}.{ URL: <a href="$url">$url</a>.}{ $note.}', + u'@book':u'$authors. $title. {$publisher, }$year.{ URL: <a href="$url">$url</a>.}{ $note.}', + u'cite':u'$index', + u'default':u'$authors. $title; {$publisher, }$year.{ $howpublished.}{ URL: <a href="$url">$url</a>.}{ $note.}', + } + +class BibTeXConfig(object): + "Configuration class from elyxer.config file" + + replaced = { + u'--':u'—', u'..':u'.', + } + +class ContainerConfig(object): + "Configuration class from elyxer.config file" + + endings = { + u'Align':u'\\end_layout', u'BarredText':u'\\bar', + u'BoldText':u'\\series', u'Cell':u'</cell', + u'ChangeDeleted':u'\\change_unchanged', + u'ChangeInserted':u'\\change_unchanged', u'ColorText':u'\\color', + u'EmphaticText':u'\\emph', u'Hfill':u'\\hfill', u'Inset':u'\\end_inset', + u'Layout':u'\\end_layout', u'LyXFooter':u'\\end_document', + u'LyXHeader':u'\\end_header', u'Row':u'</row', u'ShapedText':u'\\shape', + u'SizeText':u'\\size', u'StrikeOut':u'\\strikeout', + u'TextFamily':u'\\family', u'VersalitasText':u'\\noun', + } + + extracttext = { + u'allowed':[u'StringContainer',u'Constant',u'FormulaConstant',], + u'cloned':[u'',], + u'extracted':[u'PlainLayout',u'TaggedText',u'Align',u'Caption',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',u'Bracket',u'RawText',u'BibTag',u'FormulaNumber',u'AlphaCommand',u'EmptyCommand',u'OneParamFunction',u'SymbolFunction',u'TextFunction',u'FontFunction',u'CombiningFunction',u'DecoratingFunction',u'FormulaSymbol',u'BracketCommand',u'TeXCode',], + } + + startendings = { + u'\\begin_deeper':u'\\end_deeper', u'\\begin_inset':u'\\end_inset', + u'\\begin_layout':u'\\end_layout', + } + + starts = { + u'':u'StringContainer', u'#LyX':u'BlackBox', u'</lyxtabular':u'BlackBox', + u'<cell':u'Cell', u'<column':u'Column', u'<row':u'Row', + u'\\align':u'Align', u'\\bar':u'BarredText', + u'\\bar default':u'BlackBox', u'\\bar no':u'BlackBox', + u'\\begin_body':u'BlackBox', u'\\begin_deeper':u'DeeperList', + u'\\begin_document':u'BlackBox', u'\\begin_header':u'LyXHeader', + u'\\begin_inset Argument':u'ShortTitle', + u'\\begin_inset Box':u'BoxInset', u'\\begin_inset Branch':u'Branch', + u'\\begin_inset Caption':u'Caption', + u'\\begin_inset CommandInset bibitem':u'BiblioEntry', + u'\\begin_inset CommandInset bibtex':u'BibTeX', + u'\\begin_inset CommandInset citation':u'BiblioCitation', + u'\\begin_inset CommandInset href':u'URL', + u'\\begin_inset CommandInset include':u'IncludeInset', + u'\\begin_inset CommandInset index_print':u'PrintIndex', + u'\\begin_inset CommandInset label':u'Label', + u'\\begin_inset CommandInset line':u'LineInset', + u'\\begin_inset CommandInset nomencl_print':u'PrintNomenclature', + u'\\begin_inset CommandInset nomenclature':u'NomenclatureEntry', + u'\\begin_inset CommandInset ref':u'Reference', + u'\\begin_inset CommandInset toc':u'TableOfContents', + u'\\begin_inset ERT':u'ERT', u'\\begin_inset Flex':u'FlexInset', + u'\\begin_inset Flex Chunkref':u'NewfangledChunkRef', + u'\\begin_inset Flex Marginnote':u'SideNote', + u'\\begin_inset Flex Sidenote':u'SideNote', + u'\\begin_inset Flex URL':u'FlexURL', u'\\begin_inset Float':u'Float', + u'\\begin_inset FloatList':u'ListOf', u'\\begin_inset Foot':u'Footnote', + u'\\begin_inset Formula':u'Formula', + u'\\begin_inset FormulaMacro':u'FormulaMacro', + u'\\begin_inset Graphics':u'Image', + u'\\begin_inset Index':u'IndexReference', + u'\\begin_inset Info':u'InfoInset', + u'\\begin_inset LatexCommand bibitem':u'BiblioEntry', + u'\\begin_inset LatexCommand bibtex':u'BibTeX', + u'\\begin_inset LatexCommand cite':u'BiblioCitation', + u'\\begin_inset LatexCommand citealt':u'BiblioCitation', + u'\\begin_inset LatexCommand citep':u'BiblioCitation', + u'\\begin_inset LatexCommand citet':u'BiblioCitation', + u'\\begin_inset LatexCommand htmlurl':u'URL', + u'\\begin_inset LatexCommand index':u'IndexReference', + u'\\begin_inset LatexCommand label':u'Label', + u'\\begin_inset LatexCommand nomenclature':u'NomenclatureEntry', + u'\\begin_inset LatexCommand prettyref':u'Reference', + u'\\begin_inset LatexCommand printindex':u'PrintIndex', + u'\\begin_inset LatexCommand printnomenclature':u'PrintNomenclature', + u'\\begin_inset LatexCommand ref':u'Reference', + u'\\begin_inset LatexCommand tableofcontents':u'TableOfContents', + u'\\begin_inset LatexCommand url':u'URL', + u'\\begin_inset LatexCommand vref':u'Reference', + u'\\begin_inset Marginal':u'SideNote', + u'\\begin_inset Newline':u'NewlineInset', + u'\\begin_inset Newpage':u'NewPageInset', u'\\begin_inset Note':u'Note', + u'\\begin_inset OptArg':u'ShortTitle', + u'\\begin_inset Phantom':u'PhantomText', + u'\\begin_inset Quotes':u'QuoteContainer', + u'\\begin_inset Tabular':u'Table', u'\\begin_inset Text':u'InsetText', + u'\\begin_inset VSpace':u'VerticalSpace', u'\\begin_inset Wrap':u'Wrap', + u'\\begin_inset listings':u'Listing', + u'\\begin_inset script':u'ScriptInset', u'\\begin_inset space':u'Space', + u'\\begin_layout':u'Layout', u'\\begin_layout Abstract':u'Abstract', + u'\\begin_layout Author':u'Author', + u'\\begin_layout Bibliography':u'Bibliography', + u'\\begin_layout Chunk':u'NewfangledChunk', + u'\\begin_layout Description':u'Description', + u'\\begin_layout Enumerate':u'ListItem', + u'\\begin_layout Itemize':u'ListItem', u'\\begin_layout List':u'List', + u'\\begin_layout LyX-Code':u'LyXCode', + u'\\begin_layout Plain':u'PlainLayout', + u'\\begin_layout Standard':u'StandardLayout', + u'\\begin_layout Title':u'Title', u'\\begin_preamble':u'LyXPreamble', + u'\\change_deleted':u'ChangeDeleted', + u'\\change_inserted':u'ChangeInserted', + u'\\change_unchanged':u'BlackBox', u'\\color':u'ColorText', + u'\\color inherit':u'BlackBox', u'\\color none':u'BlackBox', + u'\\emph default':u'BlackBox', u'\\emph off':u'BlackBox', + u'\\emph on':u'EmphaticText', u'\\emph toggle':u'EmphaticText', + u'\\end_body':u'LyXFooter', u'\\family':u'TextFamily', + u'\\family default':u'BlackBox', u'\\family roman':u'BlackBox', + u'\\hfill':u'Hfill', u'\\labelwidthstring':u'BlackBox', + u'\\lang':u'LangLine', u'\\length':u'InsetLength', + u'\\lyxformat':u'LyXFormat', u'\\lyxline':u'LyXLine', + u'\\newline':u'Newline', u'\\newpage':u'NewPage', + u'\\noindent':u'BlackBox', u'\\noun default':u'BlackBox', + u'\\noun off':u'BlackBox', u'\\noun on':u'VersalitasText', + u'\\paragraph_spacing':u'BlackBox', u'\\series bold':u'BoldText', + u'\\series default':u'BlackBox', u'\\series medium':u'BlackBox', + u'\\shape':u'ShapedText', u'\\shape default':u'BlackBox', + u'\\shape up':u'BlackBox', u'\\size':u'SizeText', + u'\\size normal':u'BlackBox', u'\\start_of_appendix':u'StartAppendix', + u'\\strikeout default':u'BlackBox', u'\\strikeout on':u'StrikeOut', + } + + string = { + u'startcommand':u'\\', + } + + table = { + u'headers':[u'<lyxtabular',u'<features',], + } + +class EscapeConfig(object): + "Configuration class from elyxer.config file" + + chars = { + u'\n':u'', u' -- ':u' — ', u' --- ':u' — ', u'\'':u'’', u'`':u'‘', + } + + commands = { + u'\\InsetSpace \\space{}':u' ', u'\\InsetSpace \\thinspace{}':u' ', + u'\\InsetSpace ~':u' ', u'\\SpecialChar \\-':u'', + u'\\SpecialChar \\@.':u'.', u'\\SpecialChar \\ldots{}':u'…', + u'\\SpecialChar \\menuseparator':u' ▷ ', + u'\\SpecialChar \\nobreakdash-':u'-', u'\\SpecialChar \\slash{}':u'/', + u'\\SpecialChar \\textcompwordmark{}':u'', u'\\backslash':u'\\', + } + + entities = { + u'&':u'&', u'<':u'<', u'>':u'>', + } + + html = { + u'/>':u'>', + } + + iso885915 = { + u' ':u' ', u' ':u' ', u' ':u' ', + } + + nonunicode = { + u' ':u' ', + } + +class FormulaConfig(object): + "Configuration class from elyxer.config file" + + alphacommands = { + u'\\AA':u'Å', u'\\AE':u'Æ', + u'\\AmS':u'<span class="versalitas">AmS</span>', u'\\Angstroem':u'Å', + u'\\DH':u'Ð', u'\\Koppa':u'Ϟ', u'\\L':u'Ł', u'\\Micro':u'µ', u'\\O':u'Ø', + u'\\OE':u'Œ', u'\\Sampi':u'Ϡ', u'\\Stigma':u'Ϛ', u'\\TH':u'Þ', + u'\\aa':u'å', u'\\ae':u'æ', u'\\alpha':u'α', u'\\beta':u'β', + u'\\delta':u'δ', u'\\dh':u'ð', u'\\digamma':u'ϝ', u'\\epsilon':u'ϵ', + u'\\eta':u'η', u'\\eth':u'ð', u'\\gamma':u'γ', u'\\i':u'ı', + u'\\imath':u'ı', u'\\iota':u'ι', u'\\j':u'ȷ', u'\\jmath':u'ȷ', + u'\\kappa':u'κ', u'\\koppa':u'ϟ', u'\\l':u'ł', u'\\lambda':u'λ', + u'\\mu':u'μ', u'\\nu':u'ν', u'\\o':u'ø', u'\\oe':u'œ', u'\\omega':u'ω', + u'\\phi':u'φ', u'\\pi':u'π', u'\\psi':u'ψ', u'\\rho':u'ρ', + u'\\sampi':u'ϡ', u'\\sigma':u'σ', u'\\ss':u'ß', u'\\stigma':u'ϛ', + u'\\tau':u'τ', u'\\tcohm':u'Ω', u'\\textcrh':u'ħ', u'\\th':u'þ', + u'\\theta':u'θ', u'\\upsilon':u'υ', u'\\varDelta':u'∆', + u'\\varGamma':u'Γ', u'\\varLambda':u'Λ', u'\\varOmega':u'Ω', + u'\\varPhi':u'Φ', u'\\varPi':u'Π', u'\\varPsi':u'Ψ', u'\\varSigma':u'Σ', + u'\\varTheta':u'Θ', u'\\varUpsilon':u'Υ', u'\\varXi':u'Ξ', + u'\\varbeta':u'ϐ', u'\\varepsilon':u'ε', u'\\varkappa':u'ϰ', + u'\\varphi':u'φ', u'\\varpi':u'ϖ', u'\\varrho':u'ϱ', u'\\varsigma':u'ς', + u'\\vartheta':u'ϑ', u'\\xi':u'ξ', u'\\zeta':u'ζ', + } + + array = { + u'begin':u'\\begin', u'cellseparator':u'&', u'end':u'\\end', + u'rowseparator':u'\\\\', + } + + bigbrackets = { + u'(':[u'⎛',u'⎜',u'⎝',], u')':[u'⎞',u'⎟',u'⎠',], u'[':[u'⎡',u'⎢',u'⎣',], + u']':[u'⎤',u'⎥',u'⎦',], u'{':[u'⎧',u'⎪',u'⎨',u'⎩',], u'|':[u'|',], + u'}':[u'⎫',u'⎪',u'⎬',u'⎭',], u'∥':[u'∥',], + } + + bigsymbols = { + u'∑':[u'⎲',u'⎳',], u'∫':[u'⌠',u'⌡',], + } + + bracketcommands = { + u'\\left':u'span class="symbol"', + u'\\left.':u'<span class="leftdot"></span>', + u'\\middle':u'span class="symbol"', u'\\right':u'span class="symbol"', + u'\\right.':u'<span class="rightdot"></span>', + } + + combiningfunctions = { + u'\\"':u'̈', u'\\\'':u'́', u'\\^':u'̂', u'\\`':u'̀', u'\\acute':u'́', + u'\\bar':u'̄', u'\\breve':u'̆', u'\\c':u'̧', u'\\check':u'̌', + u'\\dddot':u'⃛', u'\\ddot':u'̈', u'\\dot':u'̇', u'\\grave':u'̀', + u'\\hat':u'̂', u'\\mathring':u'̊', u'\\overleftarrow':u'⃖', + u'\\overrightarrow':u'⃗', u'\\r':u'̊', u'\\s':u'̩', + u'\\textcircled':u'⃝', u'\\textsubring':u'̥', u'\\tilde':u'̃', + u'\\v':u'̌', u'\\vec':u'⃗', u'\\~':u'̃', + } + + commands = { + u'\\ ':u' ', u'\\!':u'', u'\\#':u'#', u'\\$':u'$', u'\\%':u'%', + u'\\&':u'&', u'\\,':u' ', u'\\:':u' ', u'\\;':u' ', u'\\AC':u'∿', + u'\\APLcomment':u'⍝', u'\\APLdownarrowbox':u'⍗', u'\\APLinput':u'⍞', + u'\\APLinv':u'⌹', u'\\APLleftarrowbox':u'⍇', u'\\APLlog':u'⍟', + u'\\APLrightarrowbox':u'⍈', u'\\APLuparrowbox':u'⍐', u'\\Box':u'□', + u'\\Bumpeq':u'≎', u'\\CIRCLE':u'●', u'\\Cap':u'⋒', + u'\\CapitalDifferentialD':u'ⅅ', u'\\CheckedBox':u'☑', u'\\Circle':u'○', + u'\\Coloneqq':u'⩴', u'\\ComplexI':u'ⅈ', u'\\ComplexJ':u'ⅉ', + u'\\Corresponds':u'≙', u'\\Cup':u'⋓', u'\\Delta':u'Δ', u'\\Diamond':u'◇', + u'\\Diamondblack':u'◆', u'\\Diamonddot':u'⟐', u'\\DifferentialD':u'ⅆ', + u'\\Downarrow':u'⇓', u'\\EUR':u'€', u'\\Euler':u'ℇ', + u'\\ExponetialE':u'ⅇ', u'\\Finv':u'Ⅎ', u'\\Game':u'⅁', u'\\Gamma':u'Γ', + u'\\Im':u'ℑ', u'\\Join':u'⨝', u'\\LEFTCIRCLE':u'◖', u'\\LEFTcircle':u'◐', + u'\\LHD':u'◀', u'\\Lambda':u'Λ', u'\\Lbag':u'⟅', u'\\Leftarrow':u'⇐', + u'\\Lleftarrow':u'⇚', u'\\Longleftarrow':u'⟸', + u'\\Longleftrightarrow':u'⟺', u'\\Longrightarrow':u'⟹', u'\\Lparen':u'⦅', + u'\\Lsh':u'↰', u'\\Mapsfrom':u'⇐|', u'\\Mapsto':u'|⇒', u'\\Omega':u'Ω', + u'\\P':u'¶', u'\\Phi':u'Φ', u'\\Pi':u'Π', u'\\Pr':u'Pr', u'\\Psi':u'Ψ', + u'\\Qoppa':u'Ϙ', u'\\RHD':u'▶', u'\\RIGHTCIRCLE':u'◗', + u'\\RIGHTcircle':u'◑', u'\\Rbag':u'⟆', u'\\Re':u'ℜ', u'\\Rparen':u'⦆', + u'\\Rrightarrow':u'⇛', u'\\Rsh':u'↱', u'\\S':u'§', u'\\Sigma':u'Σ', + u'\\Square':u'☐', u'\\Subset':u'⋐', u'\\Sun':u'☉', u'\\Supset':u'⋑', + u'\\Theta':u'Θ', u'\\Uparrow':u'⇑', u'\\Updownarrow':u'⇕', + u'\\Upsilon':u'Υ', u'\\Vdash':u'⊩', u'\\Vert':u'∥', u'\\Vvdash':u'⊪', + u'\\XBox':u'☒', u'\\Xi':u'Ξ', u'\\Yup':u'⅄', u'\\\\':u'<br/>', + u'\\_':u'_', u'\\aleph':u'ℵ', u'\\amalg':u'∐', u'\\anchor':u'⚓', + u'\\angle':u'∠', u'\\aquarius':u'♒', u'\\arccos':u'arccos', + u'\\arcsin':u'arcsin', u'\\arctan':u'arctan', u'\\arg':u'arg', + u'\\aries':u'♈', u'\\arrowbullet':u'➢', u'\\ast':u'∗', u'\\asymp':u'≍', + u'\\backepsilon':u'∍', u'\\backprime':u'‵', u'\\backsimeq':u'⋍', + u'\\backslash':u'\\', u'\\ballotx':u'✗', u'\\barwedge':u'⊼', + u'\\because':u'∵', u'\\beth':u'ℶ', u'\\between':u'≬', u'\\bigcap':u'∩', + u'\\bigcirc':u'○', u'\\bigcup':u'∪', u'\\bigodot':u'⊙', + u'\\bigoplus':u'⊕', u'\\bigotimes':u'⊗', u'\\bigsqcup':u'⊔', + u'\\bigstar':u'★', u'\\bigtriangledown':u'▽', u'\\bigtriangleup':u'△', + u'\\biguplus':u'⊎', u'\\bigvee':u'∨', u'\\bigwedge':u'∧', + u'\\biohazard':u'☣', u'\\blacklozenge':u'⧫', u'\\blacksmiley':u'☻', + u'\\blacksquare':u'■', u'\\blacktriangle':u'▲', + u'\\blacktriangledown':u'▼', u'\\blacktriangleleft':u'◂', + u'\\blacktriangleright':u'▶', u'\\blacktriangleup':u'▴', u'\\bot':u'⊥', + u'\\bowtie':u'⋈', u'\\box':u'▫', u'\\boxast':u'⧆', u'\\boxbar':u'◫', + u'\\boxbox':u'⧈', u'\\boxbslash':u'⧅', u'\\boxcircle':u'⧇', + u'\\boxdot':u'⊡', u'\\boxminus':u'⊟', u'\\boxplus':u'⊞', + u'\\boxslash':u'⧄', u'\\boxtimes':u'⊠', u'\\bullet':u'•', + u'\\bumpeq':u'≏', u'\\cancer':u'♋', u'\\cap':u'∩', u'\\capricornus':u'♑', + u'\\cat':u'⁀', u'\\cdot':u'⋅', u'\\cdots':u'⋯', u'\\cent':u'¢', + u'\\centerdot':u'∙', u'\\checkmark':u'✓', u'\\chi':u'χ', u'\\circ':u'○', + u'\\circeq':u'≗', u'\\circlearrowleft':u'↺', u'\\circlearrowright':u'↻', + u'\\circledR':u'®', u'\\circledast':u'⊛', u'\\circledbslash':u'⦸', + u'\\circledcirc':u'⊚', u'\\circleddash':u'⊝', u'\\circledgtr':u'⧁', + u'\\circledless':u'⧀', u'\\clubsuit':u'♣', u'\\coloneqq':u'≔', + u'\\complement':u'∁', u'\\cong':u'≅', u'\\coprod':u'∐', + u'\\copyright':u'©', u'\\cos':u'cos', u'\\cosh':u'cosh', u'\\cot':u'cot', + u'\\coth':u'coth', u'\\csc':u'csc', u'\\cup':u'∪', u'\\curlyvee':u'⋎', + u'\\curlywedge':u'⋏', u'\\curvearrowleft':u'↶', + u'\\curvearrowright':u'↷', u'\\dag':u'†', u'\\dagger':u'†', + u'\\daleth':u'ℸ', u'\\dashleftarrow':u'⇠', u'\\dashv':u'⊣', + u'\\ddag':u'‡', u'\\ddagger':u'‡', u'\\ddots':u'⋱', u'\\deg':u'deg', + u'\\det':u'det', u'\\diagdown':u'╲', u'\\diagup':u'╱', + u'\\diameter':u'⌀', u'\\diamond':u'◇', u'\\diamondsuit':u'♦', + u'\\dim':u'dim', u'\\div':u'÷', u'\\divideontimes':u'⋇', + u'\\dotdiv':u'∸', u'\\doteq':u'≐', u'\\doteqdot':u'≑', u'\\dotplus':u'∔', + u'\\dots':u'…', u'\\doublebarwedge':u'⌆', u'\\downarrow':u'↓', + u'\\downdownarrows':u'⇊', u'\\downharpoonleft':u'⇃', + u'\\downharpoonright':u'⇂', u'\\dsub':u'⩤', u'\\earth':u'♁', + u'\\eighthnote':u'♪', u'\\ell':u'ℓ', u'\\emptyset':u'∅', + u'\\eqcirc':u'≖', u'\\eqcolon':u'≕', u'\\eqsim':u'≂', u'\\euro':u'€', + u'\\exists':u'∃', u'\\exp':u'exp', u'\\fallingdotseq':u'≒', + u'\\fcmp':u'⨾', u'\\female':u'♀', u'\\flat':u'♭', u'\\forall':u'∀', + u'\\fourth':u'⁗', u'\\frown':u'⌢', u'\\frownie':u'☹', u'\\gcd':u'gcd', + u'\\gemini':u'♊', u'\\geq)':u'≥', u'\\geqq':u'≧', u'\\geqslant':u'≥', + u'\\gets':u'←', u'\\gg':u'≫', u'\\ggg':u'⋙', u'\\gimel':u'ℷ', + u'\\gneqq':u'≩', u'\\gnsim':u'⋧', u'\\gtrdot':u'⋗', u'\\gtreqless':u'⋚', + u'\\gtreqqless':u'⪌', u'\\gtrless':u'≷', u'\\gtrsim':u'≳', + u'\\guillemotleft':u'«', u'\\guillemotright':u'»', u'\\hbar':u'ℏ', + u'\\heartsuit':u'♥', u'\\hfill':u'<span class="hfill"> </span>', + u'\\hom':u'hom', u'\\hookleftarrow':u'↩', u'\\hookrightarrow':u'↪', + u'\\hslash':u'ℏ', u'\\idotsint':u'<span class="bigsymbol">∫⋯∫</span>', + u'\\iiint':u'<span class="bigsymbol">∭</span>', + u'\\iint':u'<span class="bigsymbol">∬</span>', u'\\imath':u'ı', + u'\\inf':u'inf', u'\\infty':u'∞', u'\\intercal':u'⊺', + u'\\interleave':u'⫴', u'\\invamp':u'⅋', u'\\invneg':u'⌐', + u'\\jmath':u'ȷ', u'\\jupiter':u'♃', u'\\ker':u'ker', u'\\land':u'∧', + u'\\landupint':u'<span class="bigsymbol">∱</span>', u'\\lang':u'⟪', + u'\\langle':u'⟨', u'\\lblot':u'⦉', u'\\lbrace':u'{', u'\\lbrace)':u'{', + u'\\lbrack':u'[', u'\\lceil':u'⌈', u'\\ldots':u'…', u'\\leadsto':u'⇝', + u'\\leftarrow)':u'←', u'\\leftarrowtail':u'↢', u'\\leftarrowtobar':u'⇤', + u'\\leftharpoondown':u'↽', u'\\leftharpoonup':u'↼', + u'\\leftleftarrows':u'⇇', u'\\leftleftharpoons':u'⥢', u'\\leftmoon':u'☾', + u'\\leftrightarrow':u'↔', u'\\leftrightarrows':u'⇆', + u'\\leftrightharpoons':u'⇋', u'\\leftthreetimes':u'⋋', u'\\leo':u'♌', + u'\\leq)':u'≤', u'\\leqq':u'≦', u'\\leqslant':u'≤', u'\\lessdot':u'⋖', + u'\\lesseqgtr':u'⋛', u'\\lesseqqgtr':u'⪋', u'\\lessgtr':u'≶', + u'\\lesssim':u'≲', u'\\lfloor':u'⌊', u'\\lg':u'lg', u'\\lgroup':u'⟮', + u'\\lhd':u'⊲', u'\\libra':u'♎', u'\\lightning':u'↯', u'\\limg':u'⦇', + u'\\liminf':u'liminf', u'\\limsup':u'limsup', u'\\ll':u'≪', + u'\\llbracket':u'⟦', u'\\llcorner':u'⌞', u'\\lll':u'⋘', u'\\ln':u'ln', + u'\\lneqq':u'≨', u'\\lnot':u'¬', u'\\lnsim':u'⋦', u'\\log':u'log', + u'\\longleftarrow':u'⟵', u'\\longleftrightarrow':u'⟷', + u'\\longmapsto':u'⟼', u'\\longrightarrow':u'⟶', u'\\looparrowleft':u'↫', + u'\\looparrowright':u'↬', u'\\lor':u'∨', u'\\lozenge':u'◊', + u'\\lrcorner':u'⌟', u'\\ltimes':u'⋉', u'\\lyxlock':u'', u'\\male':u'♂', + u'\\maltese':u'✠', u'\\mapsfrom':u'↤', u'\\mapsto':u'↦', + u'\\mathcircumflex':u'^', u'\\max':u'max', u'\\measuredangle':u'∡', + u'\\medbullet':u'⚫', u'\\medcirc':u'⚪', u'\\mercury':u'☿', u'\\mho':u'℧', + u'\\mid':u'∣', u'\\min':u'min', u'\\models':u'⊨', u'\\mp':u'∓', + u'\\multimap':u'⊸', u'\\nLeftarrow':u'⇍', u'\\nLeftrightarrow':u'⇎', + u'\\nRightarrow':u'⇏', u'\\nVDash':u'⊯', u'\\nabla':u'∇', + u'\\napprox':u'≉', u'\\natural':u'♮', u'\\ncong':u'≇', u'\\nearrow':u'↗', + u'\\neg':u'¬', u'\\neg)':u'¬', u'\\neptune':u'♆', u'\\nequiv':u'≢', + u'\\newline':u'<br/>', u'\\nexists':u'∄', u'\\ngeqslant':u'≱', + u'\\ngtr':u'≯', u'\\ngtrless':u'≹', u'\\ni':u'∋', u'\\ni)':u'∋', + u'\\nleftarrow':u'↚', u'\\nleftrightarrow':u'↮', u'\\nleqslant':u'≰', + u'\\nless':u'≮', u'\\nlessgtr':u'≸', u'\\nmid':u'∤', u'\\nolimits':u'', + u'\\nonumber':u'', u'\\not':u'¬', u'\\not<':u'≮', u'\\not=':u'≠', + u'\\not>':u'≯', u'\\notbackslash':u'⍀', u'\\notin':u'∉', u'\\notni':u'∌', + u'\\notslash':u'⌿', u'\\nparallel':u'∦', u'\\nprec':u'⊀', + u'\\nrightarrow':u'↛', u'\\nsim':u'≁', u'\\nsimeq':u'≄', + u'\\nsqsubset':u'⊏̸', u'\\nsubseteq':u'⊈', u'\\nsucc':u'⊁', + u'\\nsucccurlyeq':u'⋡', u'\\nsupset':u'⊅', u'\\nsupseteq':u'⊉', + u'\\ntriangleleft':u'⋪', u'\\ntrianglelefteq':u'⋬', + u'\\ntriangleright':u'⋫', u'\\ntrianglerighteq':u'⋭', u'\\nvDash':u'⊭', + u'\\nvdash':u'⊬', u'\\nwarrow':u'↖', u'\\odot':u'⊙', + u'\\officialeuro':u'€', u'\\oiiint':u'<span class="bigsymbol">∰</span>', + u'\\oiint':u'<span class="bigsymbol">∯</span>', + u'\\oint':u'<span class="bigsymbol">∮</span>', + u'\\ointclockwise':u'<span class="bigsymbol">∲</span>', + u'\\ointctrclockwise':u'<span class="bigsymbol">∳</span>', + u'\\ominus':u'⊖', u'\\oplus':u'⊕', u'\\oslash':u'⊘', u'\\otimes':u'⊗', + u'\\owns':u'∋', u'\\parallel':u'∥', u'\\partial':u'∂', u'\\pencil':u'✎', + u'\\perp':u'⊥', u'\\pisces':u'♓', u'\\pitchfork':u'⋔', u'\\pluto':u'♇', + u'\\pm':u'±', u'\\pointer':u'➪', u'\\pointright':u'☞', u'\\pounds':u'£', + u'\\prec':u'≺', u'\\preccurlyeq':u'≼', u'\\preceq':u'≼', + u'\\precsim':u'≾', u'\\prime':u'′', u'\\prompto':u'∝', u'\\qoppa':u'ϙ', + u'\\qquad':u' ', u'\\quad':u' ', u'\\quarternote':u'♩', + u'\\radiation':u'☢', u'\\rang':u'⟫', u'\\rangle':u'⟩', u'\\rblot':u'⦊', + u'\\rbrace':u'}', u'\\rbrace)':u'}', u'\\rbrack':u']', u'\\rceil':u'⌉', + u'\\recycle':u'♻', u'\\rfloor':u'⌋', u'\\rgroup':u'⟯', u'\\rhd':u'⊳', + u'\\rightangle':u'∟', u'\\rightarrow)':u'→', u'\\rightarrowtail':u'↣', + u'\\rightarrowtobar':u'⇥', u'\\rightharpoondown':u'⇁', + u'\\rightharpoonup':u'⇀', u'\\rightharpooondown':u'⇁', + u'\\rightharpooonup':u'⇀', u'\\rightleftarrows':u'⇄', + u'\\rightleftharpoons':u'⇌', u'\\rightmoon':u'☽', + u'\\rightrightarrows':u'⇉', u'\\rightrightharpoons':u'⥤', + u'\\rightthreetimes':u'⋌', u'\\rimg':u'⦈', u'\\risingdotseq':u'≓', + u'\\rrbracket':u'⟧', u'\\rsub':u'⩥', u'\\rtimes':u'⋊', + u'\\sagittarius':u'♐', u'\\saturn':u'♄', u'\\scorpio':u'♏', + u'\\searrow':u'↘', u'\\sec':u'sec', u'\\second':u'″', u'\\setminus':u'∖', + u'\\sharp':u'♯', u'\\simeq':u'≃', u'\\sin':u'sin', u'\\sinh':u'sinh', + u'\\sixteenthnote':u'♬', u'\\skull':u'☠', u'\\slash':u'∕', + u'\\smallsetminus':u'∖', u'\\smalltriangledown':u'▿', + u'\\smalltriangleleft':u'◃', u'\\smalltriangleright':u'▹', + u'\\smalltriangleup':u'▵', u'\\smile':u'⌣', u'\\smiley':u'☺', + u'\\spadesuit':u'♠', u'\\spddot':u'¨', u'\\sphat':u'', + u'\\sphericalangle':u'∢', u'\\spot':u'⦁', u'\\sptilde':u'~', + u'\\sqcap':u'⊓', u'\\sqcup':u'⊔', u'\\sqsubset':u'⊏', + u'\\sqsubseteq':u'⊑', u'\\sqsupset':u'⊐', u'\\sqsupseteq':u'⊒', + u'\\square':u'□', u'\\sslash':u'⫽', u'\\star':u'⋆', u'\\steaming':u'☕', + u'\\subseteqq':u'⫅', u'\\subsetneqq':u'⫋', u'\\succ':u'≻', + u'\\succcurlyeq':u'≽', u'\\succeq':u'≽', u'\\succnsim':u'⋩', + u'\\succsim':u'≿', u'\\sun':u'☼', u'\\sup':u'sup', u'\\supseteqq':u'⫆', + u'\\supsetneqq':u'⫌', u'\\surd':u'√', u'\\swarrow':u'↙', + u'\\swords':u'⚔', u'\\talloblong':u'⫾', u'\\tan':u'tan', + u'\\tanh':u'tanh', u'\\taurus':u'♉', u'\\textasciicircum':u'^', + u'\\textasciitilde':u'~', u'\\textbackslash':u'\\', + u'\\textcopyright':u'©\'', u'\\textdegree':u'°', u'\\textellipsis':u'…', + u'\\textemdash':u'—', u'\\textendash':u'—', u'\\texteuro':u'€', + u'\\textgreater':u'>', u'\\textless':u'<', u'\\textordfeminine':u'ª', + u'\\textordmasculine':u'º', u'\\textquotedblleft':u'“', + u'\\textquotedblright':u'”', u'\\textquoteright':u'’', + u'\\textregistered':u'®', u'\\textrightarrow':u'→', + u'\\textsection':u'§', u'\\texttrademark':u'™', + u'\\texttwosuperior':u'²', u'\\textvisiblespace':u' ', + u'\\therefore':u'∴', u'\\third':u'‴', u'\\top':u'⊤', u'\\triangle':u'△', + u'\\triangleleft':u'⊲', u'\\trianglelefteq':u'⊴', u'\\triangleq':u'≜', + u'\\triangleright':u'▷', u'\\trianglerighteq':u'⊵', + u'\\twoheadleftarrow':u'↞', u'\\twoheadrightarrow':u'↠', + u'\\twonotes':u'♫', u'\\udot':u'⊍', u'\\ulcorner':u'⌜', u'\\unlhd':u'⊴', + u'\\unrhd':u'⊵', u'\\unrhl':u'⊵', u'\\uparrow':u'↑', + u'\\updownarrow':u'↕', u'\\upharpoonleft':u'↿', u'\\upharpoonright':u'↾', + u'\\uplus':u'⊎', u'\\upuparrows':u'⇈', u'\\uranus':u'♅', + u'\\urcorner':u'⌝', u'\\vDash':u'⊨', u'\\varclubsuit':u'♧', + u'\\vardiamondsuit':u'♦', u'\\varheartsuit':u'♥', u'\\varnothing':u'∅', + u'\\varspadesuit':u'♤', u'\\vdash':u'⊢', u'\\vdots':u'⋮', u'\\vee':u'∨', + u'\\vee)':u'∨', u'\\veebar':u'⊻', u'\\vert':u'∣', u'\\virgo':u'♍', + u'\\warning':u'⚠', u'\\wasylozenge':u'⌑', u'\\wedge':u'∧', + u'\\wedge)':u'∧', u'\\wp':u'℘', u'\\wr':u'≀', u'\\yen':u'¥', + u'\\yinyang':u'☯', u'\\{':u'{', u'\\|':u'∥', u'\\}':u'}', + } + + decoratedcommand = { + + } + + decoratingfunctions = { + u'\\overleftarrow':u'⟵', u'\\overrightarrow':u'⟶', u'\\widehat':u'^', + } + + endings = { + u'bracket':u'}', u'complex':u'\\]', u'endafter':u'}', + u'endbefore':u'\\end{', u'squarebracket':u']', + } + + environments = { + u'align':[u'r',u'l',], u'eqnarray':[u'r',u'c',u'l',], + u'gathered':[u'l',u'l',], + } + + fontfunctions = { + u'\\boldsymbol':u'b', u'\\mathbb':u'span class="blackboard"', + u'\\mathbb{A}':u'𝔸', u'\\mathbb{B}':u'𝔹', u'\\mathbb{C}':u'ℂ', + u'\\mathbb{D}':u'𝔻', u'\\mathbb{E}':u'𝔼', u'\\mathbb{F}':u'𝔽', + u'\\mathbb{G}':u'𝔾', u'\\mathbb{H}':u'ℍ', u'\\mathbb{J}':u'𝕁', + u'\\mathbb{K}':u'𝕂', u'\\mathbb{L}':u'𝕃', u'\\mathbb{N}':u'ℕ', + u'\\mathbb{O}':u'𝕆', u'\\mathbb{P}':u'ℙ', u'\\mathbb{Q}':u'ℚ', + u'\\mathbb{R}':u'ℝ', u'\\mathbb{S}':u'𝕊', u'\\mathbb{T}':u'𝕋', + u'\\mathbb{W}':u'𝕎', u'\\mathbb{Z}':u'ℤ', u'\\mathbf':u'b', + u'\\mathcal':u'span class="scriptfont"', u'\\mathcal{B}':u'ℬ', + u'\\mathcal{E}':u'ℰ', u'\\mathcal{F}':u'ℱ', u'\\mathcal{H}':u'ℋ', + u'\\mathcal{I}':u'ℐ', u'\\mathcal{L}':u'ℒ', u'\\mathcal{M}':u'ℳ', + u'\\mathcal{R}':u'ℛ', u'\\mathfrak':u'span class="fraktur"', + u'\\mathfrak{C}':u'ℭ', u'\\mathfrak{F}':u'𝔉', u'\\mathfrak{H}':u'ℌ', + u'\\mathfrak{I}':u'ℑ', u'\\mathfrak{R}':u'ℜ', u'\\mathfrak{Z}':u'ℨ', + u'\\mathit':u'i', u'\\mathring{A}':u'Å', u'\\mathring{U}':u'Ů', + u'\\mathring{a}':u'å', u'\\mathring{u}':u'ů', u'\\mathring{w}':u'ẘ', + u'\\mathring{y}':u'ẙ', u'\\mathrm':u'span class="mathrm"', + u'\\mathscr':u'span class="scriptfont"', u'\\mathscr{B}':u'ℬ', + u'\\mathscr{E}':u'ℰ', u'\\mathscr{F}':u'ℱ', u'\\mathscr{H}':u'ℋ', + u'\\mathscr{I}':u'ℐ', u'\\mathscr{L}':u'ℒ', u'\\mathscr{M}':u'ℳ', + u'\\mathscr{R}':u'ℛ', u'\\mathsf':u'span class="mathsf"', + u'\\mathtt':u'tt', + } + + hybridfunctions = { + u'\\addcontentsline':[u'{$p!}{$q!}{$r!}',u'f0{}',u'ignored',], + u'\\addtocontents':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\backmatter':[u'',u'f0{}',u'ignored',], + u'\\binom':[u'{$1}{$2}',u'f2{(}f0{f1{$1}f1{$2}}f2{)}',u'span class="binom"',u'span class="binomstack"',u'span class="bigsymbol"',], + u'\\boxed':[u'{$1}',u'f0{$1}',u'span class="boxed"',], + u'\\cfrac':[u'[$p!]{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator align-$p"',u'span class="denominator"',u'span class="ignored"',], + u'\\color':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], + u'\\colorbox':[u'{$p!}{$1}',u'f0{$1}',u'span class="colorbox" style="background: $p;"',], + u'\\dbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], + u'\\dfrac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], + u'\\displaystyle':[u'{$1}',u'f0{$1}',u'span class="displaystyle"',], + u'\\fancyfoot':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fancyhead':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fbox':[u'{$1}',u'f0{$1}',u'span class="fbox"',], + u'\\fboxrule':[u'{$p!}',u'f0{}',u'ignored',], + u'\\fboxsep':[u'{$p!}',u'f0{}',u'ignored',], + u'\\fcolorbox':[u'{$p!}{$q!}{$1}',u'f0{$1}',u'span class="boxed" style="border-color: $p; background: $q;"',], + u'\\frac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], + u'\\framebox':[u'[$p!][$q!]{$1}',u'f0{$1}',u'span class="framebox align-$q" style="width: $p;"',], + u'\\frontmatter':[u'',u'f0{}',u'ignored',], + u'\\href':[u'[$o]{$u!}{$t!}',u'f0{$t}',u'a href="$u"',], + u'\\hspace':[u'{$p!}',u'f0{ }',u'span class="hspace" style="width: $p;"',], + u'\\leftroot':[u'{$p!}',u'f0{ }',u'span class="leftroot" style="width: $p;px"',], + u'\\mainmatter':[u'',u'f0{}',u'ignored',], + u'\\markboth':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\markright':[u'{$p!}',u'f0{}',u'ignored',], + u'\\nicefrac':[u'{$1}{$2}',u'f0{f1{$1}⁄f2{$2}}',u'span class="fraction"',u'sup class="numerator"',u'sub class="denominator"',u'span class="ignored"',], + u'\\parbox':[u'[$p!]{$w!}{$1}',u'f0{1}',u'div class="Boxed" style="width: $w;"',], + u'\\raisebox':[u'{$p!}{$1}',u'f0{$1.font}',u'span class="raisebox" style="vertical-align: $p;"',], + u'\\renewenvironment':[u'{$1!}{$2!}{$3!}',u'',], + u'\\rule':[u'[$v!]{$w!}{$h!}',u'f0/',u'hr class="line" style="width: $w; height: $h;"',], + u'\\scriptscriptstyle':[u'{$1}',u'f0{$1}',u'span class="scriptscriptstyle"',], + u'\\scriptstyle':[u'{$1}',u'f0{$1}',u'span class="scriptstyle"',], + u'\\sqrt':[u'[$0]{$1}',u'f0{f1{$0}f2{√}f4{(}f3{$1}f4{)}}',u'span class="sqrt"',u'sup class="root"',u'span class="radical"',u'span class="root"',u'span class="ignored"',], + u'\\stackrel':[u'{$1}{$2}',u'f0{f1{$1}f2{$2}}',u'span class="stackrel"',u'span class="upstackrel"',u'span class="downstackrel"',], + u'\\tbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], + u'\\textcolor':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], + u'\\textstyle':[u'{$1}',u'f0{$1}',u'span class="textstyle"',], + u'\\thispagestyle':[u'{$p!}',u'f0{}',u'ignored',], + u'\\unit':[u'[$0]{$1}',u'$0f0{$1.font}',u'span class="unit"',], + u'\\unitfrac':[u'[$0]{$1}{$2}',u'$0f0{f1{$1.font}⁄f2{$2.font}}',u'span class="fraction"',u'sup class="unit"',u'sub class="unit"',], + u'\\uproot':[u'{$p!}',u'f0{ }',u'span class="uproot" style="width: $p;px"',], + u'\\url':[u'{$u!}',u'f0{$u}',u'a href="$u"',], + u'\\vspace':[u'{$p!}',u'f0{ }',u'span class="vspace" style="height: $p;"',], + } + + hybridsizes = { + u'\\binom':u'$1+$2', u'\\cfrac':u'$1+$2', u'\\dbinom':u'$1+$2+1', + u'\\dfrac':u'$1+$2', u'\\frac':u'$1+$2', u'\\tbinom':u'$1+$2+1', + } + + labelfunctions = { + u'\\label':u'a name="#"', + } + + limitcommands = { + u'\\biginterleave':u'⫼', u'\\bigsqcap':u'⨅', u'\\fint':u'⨏', + u'\\iiiint':u'⨌', u'\\int':u'∫', u'\\intop':u'∫', u'\\lim':u'lim', + u'\\prod':u'∏', u'\\smallint':u'∫', u'\\sqint':u'⨖', u'\\sum':u'∑', + u'\\varointclockwise':u'∲', u'\\varprod':u'⨉', u'\\zcmp':u'⨟', + u'\\zhide':u'⧹', u'\\zpipe':u'⨠', u'\\zproject':u'⨡', + } + + misccommands = { + u'\\limits':u'LimitPreviousCommand', u'\\newcommand':u'MacroDefinition', + u'\\renewcommand':u'MacroDefinition', + u'\\setcounter':u'SetCounterFunction', u'\\tag':u'FormulaTag', + u'\\tag*':u'FormulaTag', u'\\today':u'TodayCommand', + } + + modified = { + u'\n':u'', u' ':u'', u'$':u'', u'&':u' ', u'\'':u'’', u'+':u' + ', + u',':u', ', u'-':u' − ', u'/':u' ⁄ ', u'<':u' < ', u'=':u' = ', + u'>':u' > ', u'@':u'', u'~':u'', + } + + onefunctions = { + u'\\Big':u'span class="bigsymbol"', u'\\Bigg':u'span class="hugesymbol"', + u'\\bar':u'span class="bar"', u'\\begin{array}':u'span class="arraydef"', + u'\\big':u'span class="symbol"', u'\\bigg':u'span class="largesymbol"', + u'\\bigl':u'span class="bigsymbol"', u'\\bigr':u'span class="bigsymbol"', + u'\\centering':u'span class="align-center"', + u'\\ensuremath':u'span class="ensuremath"', + u'\\hphantom':u'span class="phantom"', + u'\\noindent':u'span class="noindent"', + u'\\overbrace':u'span class="overbrace"', + u'\\overline':u'span class="overline"', + u'\\phantom':u'span class="phantom"', + u'\\underbrace':u'span class="underbrace"', u'\\underline':u'u', + u'\\vphantom':u'span class="phantom"', + } + + spacedcommands = { + u'\\Bot':u'⫫', u'\\Doteq':u'≑', u'\\DownArrowBar':u'⤓', + u'\\DownLeftTeeVector':u'⥞', u'\\DownLeftVectorBar':u'⥖', + u'\\DownRightTeeVector':u'⥟', u'\\DownRightVectorBar':u'⥗', + u'\\Equal':u'⩵', u'\\LeftArrowBar':u'⇤', u'\\LeftDownTeeVector':u'⥡', + u'\\LeftDownVectorBar':u'⥙', u'\\LeftTeeVector':u'⥚', + u'\\LeftTriangleBar':u'⧏', u'\\LeftUpTeeVector':u'⥠', + u'\\LeftUpVectorBar':u'⥘', u'\\LeftVectorBar':u'⥒', + u'\\Leftrightarrow':u'⇔', u'\\Longmapsfrom':u'⟽', u'\\Longmapsto':u'⟾', + u'\\MapsDown':u'↧', u'\\MapsUp':u'↥', u'\\Nearrow':u'⇗', + u'\\NestedGreaterGreater':u'⪢', u'\\NestedLessLess':u'⪡', + u'\\NotGreaterLess':u'≹', u'\\NotGreaterTilde':u'≵', + u'\\NotLessTilde':u'≴', u'\\Nwarrow':u'⇖', u'\\Proportion':u'∷', + u'\\RightArrowBar':u'⇥', u'\\RightDownTeeVector':u'⥝', + u'\\RightDownVectorBar':u'⥕', u'\\RightTeeVector':u'⥛', + u'\\RightTriangleBar':u'⧐', u'\\RightUpTeeVector':u'⥜', + u'\\RightUpVectorBar':u'⥔', u'\\RightVectorBar':u'⥓', + u'\\Rightarrow':u'⇒', u'\\Same':u'⩶', u'\\Searrow':u'⇘', + u'\\Swarrow':u'⇙', u'\\Top':u'⫪', u'\\UpArrowBar':u'⤒', u'\\VDash':u'⊫', + u'\\approx':u'≈', u'\\approxeq':u'≊', u'\\backsim':u'∽', u'\\barin':u'⋶', + u'\\barleftharpoon':u'⥫', u'\\barrightharpoon':u'⥭', u'\\bij':u'⤖', + u'\\coloneq':u'≔', u'\\corresponds':u'≙', u'\\curlyeqprec':u'⋞', + u'\\curlyeqsucc':u'⋟', u'\\dashrightarrow':u'⇢', u'\\dlsh':u'↲', + u'\\downdownharpoons':u'⥥', u'\\downuparrows':u'⇵', + u'\\downupharpoons':u'⥯', u'\\drsh':u'↳', u'\\eqslantgtr':u'⪖', + u'\\eqslantless':u'⪕', u'\\equiv':u'≡', u'\\ffun':u'⇻', u'\\finj':u'⤕', + u'\\ge':u'≥', u'\\geq':u'≥', u'\\ggcurly':u'⪼', u'\\gnapprox':u'⪊', + u'\\gneq':u'⪈', u'\\gtrapprox':u'⪆', u'\\hash':u'⋕', u'\\iddots':u'⋰', + u'\\implies':u' ⇒ ', u'\\in':u'∈', u'\\le':u'≤', u'\\leftarrow':u'←', + u'\\leftarrowtriangle':u'⇽', u'\\leftbarharpoon':u'⥪', + u'\\leftrightarrowtriangle':u'⇿', u'\\leftrightharpoon':u'⥊', + u'\\leftrightharpoondown':u'⥐', u'\\leftrightharpoonup':u'⥎', + u'\\leftrightsquigarrow':u'↭', u'\\leftslice':u'⪦', + u'\\leftsquigarrow':u'⇜', u'\\leftupdownharpoon':u'⥑', u'\\leq':u'≤', + u'\\lessapprox':u'⪅', u'\\llcurly':u'⪻', u'\\lnapprox':u'⪉', + u'\\lneq':u'⪇', u'\\longmapsfrom':u'⟻', u'\\multimapboth':u'⧟', + u'\\multimapdotbothA':u'⊶', u'\\multimapdotbothB':u'⊷', + u'\\multimapinv':u'⟜', u'\\nVdash':u'⊮', u'\\ne':u'≠', u'\\neq':u'≠', + u'\\ngeq':u'≱', u'\\nleq':u'≰', u'\\nni':u'∌', u'\\not\\in':u'∉', + u'\\notasymp':u'≭', u'\\npreceq':u'⋠', u'\\nsqsubseteq':u'⋢', + u'\\nsqsupseteq':u'⋣', u'\\nsubset':u'⊄', u'\\nsucceq':u'⋡', + u'\\pfun':u'⇸', u'\\pinj':u'⤔', u'\\precapprox':u'⪷', u'\\preceqq':u'⪳', + u'\\precnapprox':u'⪹', u'\\precnsim':u'⋨', u'\\propto':u'∝', + u'\\psur':u'⤀', u'\\rightarrow':u'→', u'\\rightarrowtriangle':u'⇾', + u'\\rightbarharpoon':u'⥬', u'\\rightleftharpoon':u'⥋', + u'\\rightslice':u'⪧', u'\\rightsquigarrow':u'⇝', + u'\\rightupdownharpoon':u'⥏', u'\\sim':u'~', u'\\strictfi':u'⥼', + u'\\strictif':u'⥽', u'\\subset':u'⊂', u'\\subseteq':u'⊆', + u'\\subsetneq':u'⊊', u'\\succapprox':u'⪸', u'\\succeqq':u'⪴', + u'\\succnapprox':u'⪺', u'\\supset':u'⊃', u'\\supseteq':u'⊇', + u'\\supsetneq':u'⊋', u'\\times':u'×', u'\\to':u'→', + u'\\updownarrows':u'⇅', u'\\updownharpoons':u'⥮', u'\\upupharpoons':u'⥣', + u'\\vartriangleleft':u'⊲', u'\\vartriangleright':u'⊳', + } + + starts = { + u'beginafter':u'}', u'beginbefore':u'\\begin{', u'bracket':u'{', + u'command':u'\\', u'comment':u'%', u'complex':u'\\[', u'simple':u'$', + u'squarebracket':u'[', u'unnumbered':u'*', + } + + symbolfunctions = { + u'^':u'sup', u'_':u'sub', + } + + textfunctions = { + u'\\mbox':u'span class="mbox"', u'\\text':u'span class="text"', + u'\\textbf':u'b', u'\\textipa':u'span class="textipa"', u'\\textit':u'i', + u'\\textnormal':u'span class="textnormal"', + u'\\textrm':u'span class="textrm"', + u'\\textsc':u'span class="versalitas"', + u'\\textsf':u'span class="textsf"', u'\\textsl':u'i', u'\\texttt':u'tt', + u'\\textup':u'span class="normal"', + } + + unmodified = { + + u'characters':[u'.',u'*',u'€',u'(',u')',u'[',u']',u':',u'·',u'!',u';',u'|',u'§',u'"',], + } + + urls = { + u'googlecharts':u'http://chart.googleapis.com/chart?cht=tx&chl=', + } + +class GeneralConfig(object): + "Configuration class from elyxer.config file" + + version = { + u'date':u'2013-03-10', u'lyxformat':u'413', u'number':u'1.2.4', + } + +class HeaderConfig(object): + "Configuration class from elyxer.config file" + + parameters = { + u'beginpreamble':u'\\begin_preamble', u'branch':u'\\branch', + u'documentclass':u'\\textclass', u'endbranch':u'\\end_branch', + u'endpreamble':u'\\end_preamble', u'language':u'\\language', + u'lstset':u'\\lstset', u'outputchanges':u'\\output_changes', + u'paragraphseparation':u'\\paragraph_separation', + u'pdftitle':u'\\pdf_title', u'secnumdepth':u'\\secnumdepth', + u'tocdepth':u'\\tocdepth', + } + + styles = { + + u'article':[u'article',u'aastex',u'aapaper',u'acmsiggraph',u'sigplanconf',u'achemso',u'amsart',u'apa',u'arab-article',u'armenian-article',u'article-beamer',u'chess',u'dtk',u'elsarticle',u'heb-article',u'IEEEtran',u'iopart',u'kluwer',u'scrarticle-beamer',u'scrartcl',u'extarticle',u'paper',u'mwart',u'revtex4',u'spie',u'svglobal3',u'ltugboat',u'agu-dtd',u'jgrga',u'agums',u'entcs',u'egs',u'ijmpc',u'ijmpd',u'singlecol-new',u'doublecol-new',u'isprs',u'tarticle',u'jsarticle',u'jarticle',u'jss',u'literate-article',u'siamltex',u'cl2emult',u'llncs',u'svglobal',u'svjog',u'svprobth',], + u'book':[u'book',u'amsbook',u'scrbook',u'extbook',u'tufte-book',u'report',u'extreport',u'scrreprt',u'memoir',u'tbook',u'jsbook',u'jbook',u'mwbk',u'svmono',u'svmult',u'treport',u'jreport',u'mwrep',], + } + +class ImageConfig(object): + "Configuration class from elyxer.config file" + + converters = { + + u'imagemagick':u'convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output"', + u'inkscape':u'inkscape "$input" --export-png="$output"', + u'lyx':u'lyx -C "$input" "$output"', + } + + cropboxformats = { + u'.eps':u'ps', u'.pdf':u'pdf', u'.ps':u'ps', + } + + formats = { + u'default':u'.png', u'vector':[u'.svg',u'.eps',], + } + +class LayoutConfig(object): + "Configuration class from elyxer.config file" + + groupable = { + + u'allowed':[u'StringContainer',u'Constant',u'TaggedText',u'Align',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + } + +class NewfangleConfig(object): + "Configuration class from elyxer.config file" + + constants = { + u'chunkref':u'chunkref{', u'endcommand':u'}', u'endmark':u'>', + u'startcommand':u'\\', u'startmark':u'=<', + } + +class NumberingConfig(object): + "Configuration class from elyxer.config file" + + layouts = { + + u'ordered':[u'Chapter',u'Section',u'Subsection',u'Subsubsection',u'Paragraph',], + u'roman':[u'Part',u'Book',], + } + + sequence = { + u'symbols':[u'*',u'**',u'†',u'‡',u'§',u'§§',u'¶',u'¶¶',u'#',u'##',], + } + +class StyleConfig(object): + "Configuration class from elyxer.config file" + + hspaces = { + u'\\enskip{}':u' ', u'\\hfill{}':u'<span class="hfill"> </span>', + u'\\hspace*{\\fill}':u' ', u'\\hspace*{}':u'', u'\\hspace{}':u' ', + u'\\negthinspace{}':u'', u'\\qquad{}':u'  ', u'\\quad{}':u' ', + u'\\space{}':u' ', u'\\thinspace{}':u' ', u'~':u' ', + } + + quotes = { + u'ald':u'»', u'als':u'›', u'ard':u'«', u'ars':u'‹', u'eld':u'“', + u'els':u'‘', u'erd':u'”', u'ers':u'’', u'fld':u'«', + u'fls':u'‹', u'frd':u'»', u'frs':u'›', u'gld':u'„', u'gls':u'‚', + u'grd':u'“', u'grs':u'‘', u'pld':u'„', u'pls':u'‚', u'prd':u'”', + u'prs':u'’', u'sld':u'”', u'srd':u'”', + } + + referenceformats = { + u'eqref':u'(@↕)', u'formatted':u'¶↕', u'nameref':u'$↕', u'pageref':u'#↕', + u'ref':u'@↕', u'vpageref':u'on-page#↕', u'vref':u'@on-page#↕', + } + + size = { + u'ignoredtexts':[u'col',u'text',u'line',u'page',u'theight',u'pheight',], + } + + vspaces = { + u'bigskip':u'<div class="bigskip"> </div>', + u'defskip':u'<div class="defskip"> </div>', + u'medskip':u'<div class="medskip"> </div>', + u'smallskip':u'<div class="smallskip"> </div>', + u'vfill':u'<div class="vfill"> </div>', + } + +class TOCConfig(object): + "Configuration class from elyxer.config file" + + extractplain = { + + u'allowed':[u'StringContainer',u'Constant',u'TaggedText',u'Align',u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + u'cloned':[u'',], u'extracted':[u'',], + } + + extracttitle = { + u'allowed':[u'StringContainer',u'Constant',u'Space',], + u'cloned':[u'TextFamily',u'EmphaticText',u'VersalitasText',u'BarredText',u'SizeText',u'ColorText',u'LangLine',u'Formula',], + u'extracted':[u'PlainLayout',u'TaggedText',u'Align',u'Caption',u'StandardLayout',u'FlexInset',], + } + +class TagConfig(object): + "Configuration class from elyxer.config file" + + barred = { + u'under':u'u', + } + + family = { + u'sans':u'span class="sans"', u'typewriter':u'tt', + } + + flex = { + u'CharStyle:Code':u'span class="code"', + u'CharStyle:MenuItem':u'span class="menuitem"', + u'Code':u'span class="code"', u'MenuItem':u'span class="menuitem"', + u'Noun':u'span class="noun"', u'Strong':u'span class="strong"', + } + + group = { + u'layouts':[u'Quotation',u'Quote',], + } + + layouts = { + u'Center':u'div', u'Chapter':u'h?', u'Date':u'h2', u'Paragraph':u'div', + u'Part':u'h1', u'Quotation':u'blockquote', u'Quote':u'blockquote', + u'Section':u'h?', u'Subsection':u'h?', u'Subsubsection':u'h?', + } + + listitems = { + u'Enumerate':u'ol', u'Itemize':u'ul', + } + + notes = { + u'Comment':u'', u'Greyedout':u'span class="greyedout"', u'Note':u'', + } + + script = { + u'subscript':u'sub', u'superscript':u'sup', + } + + shaped = { + u'italic':u'i', u'slanted':u'i', u'smallcaps':u'span class="versalitas"', + } + +class TranslationConfig(object): + "Configuration class from elyxer.config file" + + constants = { + u'Appendix':u'Appendix', u'Book':u'Book', u'Chapter':u'Chapter', + u'Paragraph':u'Paragraph', u'Part':u'Part', u'Section':u'Section', + u'Subsection':u'Subsection', u'Subsubsection':u'Subsubsection', + u'abstract':u'Abstract', u'bibliography':u'Bibliography', + u'figure':u'figure', u'float-algorithm':u'Algorithm ', + u'float-figure':u'Figure ', u'float-listing':u'Listing ', + u'float-table':u'Table ', u'float-tableau':u'Tableau ', + u'footnotes':u'Footnotes', u'generated-by':u'Document generated by ', + u'generated-on':u' on ', u'index':u'Index', + u'jsmath-enable':u'Please enable JavaScript on your browser.', + u'jsmath-requires':u' requires JavaScript to correctly process the mathematics on this page. ', + u'jsmath-warning':u'Warning: ', u'list-algorithm':u'List of Algorithms', + u'list-figure':u'List of Figures', u'list-table':u'List of Tables', + u'list-tableau':u'List of Tableaux', u'main-page':u'Main page', + u'next':u'Next', u'nomenclature':u'Nomenclature', + u'on-page':u' on page ', u'prev':u'Prev', u'references':u'References', + u'toc':u'Table of Contents', u'toc-for':u'Contents for ', u'up':u'Up', + } + + languages = { + u'american':u'en', u'british':u'en', u'deutsch':u'de', u'dutch':u'nl', + u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'russian':u'ru', + u'spanish':u'es', + } + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/fileconfig.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/fileconfig.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/fileconfig.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/fileconfig.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,254 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090203 +# eLyXer parsers + +import datetime +from elyxer.util.trace import Trace +from elyxer.io.fileline import * + + +class ConfigReader(object): + "Read a configuration file" + + escapes = [ + ('\n', ' '), (':', ':'), ('#', '#'), + ('[', '['), (']', ']'), ('&', '&'), + ] + + def __init__(self, filename): + self.reader = LineReader(filename) + self.objects = dict() + self.section = None + self.serializer = ConfigSerializer(ConfigReader.escapes) + + def parse(self): + "Parse the whole file" + while not self.reader.finished(): + self.parseline(self.reader.currentline()) + self.reader.nextline() + return self + + def parseline(self, line): + "Parse a single line" + if line == '': + return + if line.startswith('#'): + return + if line.startswith('['): + self.parsesection(line) + else: + self.parseparam(line) + + def parsesection(self, line): + "Parse a section header" + if not line.endswith(']'): + Trace.error('Incorrect section header ' + line) + return + name = line[1:-1] + self.section = name + self.objects[name] = dict() + + def parseparam(self, line): + "Parse a parameter line" + if len(line.strip()) == 0: + return + if not ':' in line: + Trace.error('Invalid configuration parameter ' + line) + return + pieces = line.split(':', 1) + key = self.serializer.unescape(pieces[0]) + value = self.serializer.deserialize(pieces[1]) + object = self.objects[self.section] + if key in object: + Trace.error('Repeated key ' + key + ' for ' + value) + object[key] = value + +class ConfigWriter(object): + "Write a configuration file" + + def __init__(self, writer): + self.writer = writer + self.serializer = ConfigSerializer(ConfigReader.escapes) + + def writeall(self, types): + "Write a list of configuration objects given their class names" + for type in types: + object = type.__new__(type) + self.write(object) + + def write(self, object): + "Write a configuration object" + for attr in dir(object): + self.writeattr(object, attr) + + def writeattr(self, object, attr): + "Write an attribute" + if attr.startswith('__'): + return + self.writesection(object, attr) + valuedict = getattr(object, attr) + if not isinstance(valuedict, dict): + Trace.error('Unknown config type ' + valuedict.__class__.__name__ + + ' in ' + attr) + return + names = valuedict.keys() + names.sort() + for name in names: + value = self.serializer.serialize(valuedict[name]) + self.writer.writeline(self.serializer.escape(name) + ':' + value) + + def writesection(self, object, attr): + "Write a new section" + self.writer.writeline('') + header = '[' + object.__class__.__name__ + '.' + attr + ']' + self.writer.writeline(header) + +class ConfigToPython(ConfigWriter): + "Exports a number of dictionaries from elyxer.a config file to a Python class" + + escapes = [ ('\\', '\\\\'), ('\n', '\\n'), ('\'', '\\\'') ] + + def __init__(self, writer): + self.writer = writer + self.serializer = ConfigSerializer(ConfigToPython.escapes) + + def write(self, objects): + "Write the whole set of objects" + self.writer.writeline('#! /usr/bin/env python') + self.writer.writeline('# -*- coding: utf-8 -*-') + self.writer.writeline('') + self.writer.writeline('# eLyXer configuration') + self.writer.writeline('# autogenerated from elyxer.config file on ' + + datetime.date.today().isoformat()) + self.writer.writeline('') + classes = self.sort(objects) + names = classes.keys() + names.sort() + for classname in names: + self.writeclass(classname, classes[classname]) + + def writeclass(self, name, current): + "Write an object class" + self.writer.writeline('class ' + name + '(object):') + self.writer.writeline(' "Configuration class from elyxer.config file"') + self.writer.writeline('') + names = current.keys() + names.sort() + for attrname in names: + self.writeattr(attrname, current[attrname]) + + def writeattr(self, name, contents): + "Write a dictionary attribute" + if not isinstance(contents, dict): + Trace.error('Unknown config type ' + contents.__class__.__name__) + return + self.writer.writestring(' ' + name + ' = ') + self.writer.writeline('{') + string = ' ' + names = contents.keys() + names.sort() + for name in names: + value = self.serializer.pyserialize(contents[name]) + piece = 'u\'' + self.serializer.escape(name) + '\':' + value + ', ' + string = self.append(string, piece) + self.writer.writeline(string) + self.writer.writeline(' }') + self.writer.writeline('') + + def append(self, string, piece): + "Write a piece to the string or to disk" + if len(string + piece) > 80: + self.writer.writeline(string) + string = ' ' + return string + piece + + def sort(self, objects): + "Sort the objects into classes" + classes = dict() + for name, object in objects.iteritems(): + pieces = name.split('.') + if len(pieces) != 2: + Trace.error('Wrong method name ' + name) + return + classname = pieces[0] + methodname = pieces[1] + if not classname in classes: + classes[classname] = dict() + currentclass = classes[classname] + currentclass[methodname] = object + return classes + +class ConfigSerializer(object): + "Serialize and deserialize config object" + + def __init__(self, escapes): + self.escapes = escapes + + def serialize(self, object): + "Convert an object to a string" + if not isinstance(object, list): + return self.escape(object) + result = '' + for value in object: + result += self.escape(value) + ',' + if len(object) > 0: + result = result[:-1] + return '[' + result + ']' + + def pyserialize(self, object): + "Convert an object to a Python definition" + if not isinstance(object, list): + return 'u\'' + self.escape(object) + '\'' + result = '[u\'' + for value in object: + result += self.escape(value) + '\',u\'' + if len(object) > 0: + result = result[:-2] + return result + ']' + + def escape(self, string): + "Escape a string or a list" + for escape, value in self.escapes: + if escape in string: + string = string.replace(escape, value) + return string + + def deserialize(self, string): + "Parse a string into an object (string or list)" + if not string.startswith('[') or not string.endswith(']'): + return self.unescape(string) + result = [] + contents = string[1:-1].split(',') + for piece in contents: + result.append(self.unescape(piece)) + return result + + def unescape(self, string): + "Remove the escaping from elyxer.a string." + if string.startswith('&#x') and string.endswith(';'): + # single unicode character + return unichr(int('0x' + string[3:-1], 16)) + for escape, value in self.escapes: + string = string.replace(value, escape) + return string + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/importconfig.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/importconfig.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/importconfig.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/importconfig.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,173 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090617 +# eLyXer import configuration file + +from elyxer.util.trace import Trace +from elyxer.io.fileline import * +from elyxer.conf.fileconfig import * + + +class ImportFile(object): + "Generic import file." + + def __init__(self, filename): + self.reader = LineReader(filename) + self.objects = dict() + self.section = 'FormulaConfig.commands' + self.objects[self.section] = dict() + self.sectionobject = self.objects[self.section] + self.serializer = ConfigSerializer(ImportCommands.escapes) + self.existing = dict() + self.existing.update(FormulaConfig.commands) + self.existing.update(FormulaConfig.alphacommands) + self.existing.update(FormulaConfig.spacedcommands) + + def parsewhole(self, parseline): + "Parse the whole file line by line." + while not self.reader.finished(): + line = self.convertline(self.reader.currentline()) + if line: + parseline(line) + self.reader.nextline() + + def convertline(self, line): + "Convert a single line removing comments." + if line == '': + return None + if line.startswith('#'): + return None + if '#' in line: + line = line.split('#')[0] + return line + + def setsymbol(self, command, unicodesymbol): + "Set the unicode symbol for a command." + if not command.startswith('\\'): + Trace.error('Invalid command ' + command) + return + if command.count('\\') > 1: + Trace.error('Too many commands ' + command) + return + if command in self.existing: + return + self.sectionobject[command] = unicodesymbol + +class ImportCommands(ImportFile): + "Import a LyX unicodesymbols file" + + escapes = [ + ('\\', '\\\\') + ] + + def parse(self): + "Parse the whole LyX commands file." + self.parsewhole(self.parseparam) + return self + + def parseparam(self, line): + "Parse a parameter line" + line = line.strip() + if len(line) == 0: + return + pieces = line.split() + if len(pieces) < 5: + return + unicode = pieces[0] + if not unicode.startswith('0x'): + Trace.error('Invalid unicode ' + unicode) + return + unicode = unicode.replace('0x', '') + unicodechar = unichr(int(unicode, 16)) + command = pieces[4].replace('"', '') + command = self.serializer.unescape(command) + self.setsymbol(command, unicodechar) + +class ImportCsv(ImportFile): + "Import a file with comma-separated values of the form: \command,unicode." + + def parse(self): + "Parse the whole CSV file." + self.parsewhole(self.parsecsv) + return self + + def parsecsv(self, line): + "Parse a line \command,unicode." + line = line.strip() + if len(line) == 0: + return + pieces = line.split(',') + if len(pieces) != 2: + return + self.setsymbol(pieces[0],pieces[1]) + +class ImportUnimath(ImportFile): + "Import a file in unimath format." + "See http://milde.users.sourceforge.net/LUCR/Math/" + + def parse(self): + "Parse the whole unimath file." + self.parsewhole(self.parseunimath) + return self + + def parseunimath(self, line): + "Parse a line \command,unicode." + line = line.strip() + if len(line) == 0: + return + pieces = line.split('^') + if len(pieces) != 8: + Trace.error('Weird line: ' + line) + return + symbol = pieces[1] + command = pieces[2] + if command == '' or not command.startswith('\\'): + return + mathclass = pieces[4] + mathcategory = pieces[5] + if mathcategory in ['mathord', 'mathbin', 'mathopen', 'mathclose']: + # plain old command + self.add(symbol, command, 'FormulaConfig.commands') + elif mathcategory in ['mathalpha']: + # alpha command + self.add(symbol, command, 'FormulaConfig.alphacommands') + elif mathcategory in ['mathaccent', 'mathfence', 'mathradical', 'mathover', 'mathunder', '']: + # ignore + Trace.error('Ignoring ' + symbol + ' with category ' + mathcategory) + elif mathcategory in ['mathop']: + self.add(symbol, command, 'FormulaConfig.limitcommands') + elif mathcategory in ['mathrel']: + self.add(symbol, command, 'FormulaConfig.spacedcommands') + else: + Trace.error('Unknown math category ' + mathcategory + ' for ' + symbol) + + def add(self, symbol, command, category): + "Add a symbol to a category." + if not category in self.objects: + self.objects[category] = dict() + self.sectionobject = self.objects[category] + if command == '': + return + if '{' in command or '}' in command or '[' in command or ']' in command: + return + self.setsymbol(command, symbol) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/javatopyconf.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/javatopyconf.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/javatopyconf.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/javatopyconf.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,50 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer configuration +# autogenerated from elyxer.config file on 2010-03-15 + +class GeneralConfig(object): + "Configuration class from elyxer.config file" + + version = { + u'date':u'2010-03-15', u'number':u'0.1', + } + +class JavaToPyConfig(object): + "Configuration class from elyxer.config file" + + declarations = { + u'$andvalue':u'$value && $value', + u'$arithmeticexpression':u'$value + $value', + u'$assignment':u'$variablename = $value;', u'$block':u'[$statement]*', + u'$class':u'$scope class $classname $inheritance { [$method]* }', + u'$classlist':u'[$classname]?[, $classname]*', u'$classname':u'$$', + u'$condition':u'$value|$logicalvalue', + u'$conditional':u'if ($condition) $block', + u'$declaration':u'$simpledeclaration|$declarationassignment', + u'$declarationassignment':u'$type $variablename = $value;', + u'$file':u'[$class]+', + u'$inheritance':u'[extends $classlist]? [implements $classlist]?', + u'$logicalvalue':u'$orvalue|$andvalue', + u'$method':u'$scope [$qualifier]* $type $methodname ( $paramsdeclaration ) { $block }', + u'$methodcall':u'$variablename[.$methodname($params)]+', + u'$methodname':u'$$', u'$orvalue':u'$value || $value', + u'$paramdeclaration':u'$type $variablename', + u'$params':u'[$value]?[,$value]+', + u'$paramsdeclaration':u'[$paramdeclaration]?[,$paramdeclaration]*', + u'$qualifier':u'static|final', u'$scope':u'public|private|protected', + u'$simpledeclaration':u'$type $variablename;', + u'$statement':u'$conditional|$declaration|$assignment|$methodcall', + u'$type':u'int|String|$classname', + u'$value':u'$variablename|$methodcall|$arithmeticexpression', + u'$variablename':u'$$', + } + + output = { + u'$class':u'class $classname(object):\\n\\t[$method]*', + u'$classname':u'$classname', + u'$conditional':u'if $condition:\\n\\t$block', + u'$method':u'def $methodname:\\n\\t$block', + } + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/jtp.cfg elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/jtp.cfg --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/conf/jtp.cfg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/conf/jtp.cfg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,62 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009-2010 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- + +[GeneralConfig.version] +date:2010-03-11 +number:0.1 + +[JavaToPyConfig.declarations] +$file:[$class]+ +$class:$scope class $classname $inheritance { [$method]* } +$scope:public|private|protected +$classname:$$ +$inheritance:[extends $classlist]? [implements $classlist]? +$classlist:[$classname]?[, $classname]* +$method:$scope [$qualifier]* $type $methodname ( $paramsdeclaration ) { $block } +$methodname:$$ +$paramsdeclaration:[$paramdeclaration]?[,$paramdeclaration]* +$paramdeclaration:$type $variablename +$variablename:$$ +$qualifier:static|final +$type:int|String|$classname +$conditional:if ($condition) $block +$condition:$value|$logicalvalue +$logicalvalue:$orvalue|$andvalue +$orvalue:$value || $value +$andvalue:$value && $value +$block:[$statement]* +$statement:$conditional|$declaration|$assignment|$methodcall +$methodcall:$variablename[.$methodname($params)]+ +$params:[$value]?[,$value]+ +$value:$variablename|$methodcall|$arithmeticexpression +$arithmeticexpression:$value + $value +$declaration:$simpledeclaration|$declarationassignment +$simpledeclaration:$type $variablename; +$declarationassignment:$type $variablename = $value; +$assignment:$variablename = $value; + +[JavaToPyConfig.output] +$class:class $classname(object):\n\t[$method]* +$classname:$classname +$method:def $methodname:\n\t$block +$conditional:if $condition:\n\t$block + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/basket.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/basket.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/basket.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/basket.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,92 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20091101 +# eLyXer output baskets +# http://www.nongnu.org/elyxer/ + + +from elyxer.util.options import * +from elyxer.util.clone import * +from elyxer.gen.toc import * + + +class Basket(object): + "A basket to place a set of containers. Can write them, store them..." + + def setwriter(self, writer): + self.writer = writer + return self + +class WriterBasket(Basket): + "A writer of containers. Just writes them out to a writer." + + def write(self, container): + "Write a container to the line writer." + self.writer.write(container.gethtml()) + + def finish(self): + "Mark as finished." + self.writer.close() + +class KeeperBasket(Basket): + "Keeps all containers stored." + + def __init__(self): + self.contents = [] + + def write(self, container): + "Keep the container." + self.contents.append(container) + + def finish(self): + "Finish the basket by flushing to disk." + self.flush() + + def flush(self): + "Flush the contents to the writer." + for container in self.contents: + self.writer.write(container.gethtml()) + self.writer.close() + +class TOCBasket(Basket): + "A basket to place the TOC of a document." + + def __init__(self): + self.converter = TOCConverter() + + def setwriter(self, writer): + Basket.setwriter(self, writer) + Options.nocopy = True + self.writer.write(LyXHeader().gethtml()) + return self + + def write(self, container): + "Write the table of contents for a container." + entry = self.converter.convertindented(container) + if entry: + self.writer.write(entry.gethtml()) + + def finish(self): + "Mark as finished." + self.writer.write(LyXFooter().gethtml()) + self.writer.close() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/change.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/change.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/change.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/change.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,49 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20100829 +# Change tracking + +from elyxer.util.trace import Trace +from elyxer.util.docparams import * +from elyxer.gen.container import * + + +class ChangeInserted(Container): + "A change which consists of an insertion." + + def __init__(self): + self.parser = TextParser(self) + if DocumentParameters.outputchanges: + self.output = TaggedOutput().settag('span class="inserted"') + else: + self.output = ContentsOutput() + +class ChangeDeleted(TaggedText): + "A change which consists of a deletion." + + def __init__(self): + self.parser = TextParser(self) + if DocumentParameters.outputchanges: + self.output = TaggedOutput().settag('span class="deleted"') + else: + self.output = EmptyOutput() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/container.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/container.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/container.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/container.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,295 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090131 +# eLyXer containers for Lyx data that output HTML + +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.conf.config import * +from elyxer.parse.position import * + + +class Container(object): + "A container for text and objects in a lyx file" + + partkey = None + parent = None + begin = None + + def __init__(self): + self.contents = list() + + def process(self): + "Process contents" + pass + + def gethtml(self): + "Get the resulting HTML" + html = self.output.gethtml(self) + if isinstance(html, basestring): + Trace.error('Raw string ' + html) + html = [html] + return self.escapeall(html) + + def escapeall(self, lines): + "Escape all lines in an array according to the output options." + result = [] + for line in lines: + if Options.html: + line = self.escape(line, EscapeConfig.html) + if Options.iso885915: + line = self.escape(line, EscapeConfig.iso885915) + line = self.escapeentities(line) + elif not Options.unicode: + line = self.escape(line, EscapeConfig.nonunicode) + result.append(line) + return result + + def escape(self, line, replacements = EscapeConfig.entities): + "Escape a line with replacements from elyxer.a map" + pieces = replacements.keys() + # do them in order + pieces.sort() + for piece in pieces: + if piece in line: + line = line.replace(piece, replacements[piece]) + return line + + def escapeentities(self, line): + "Escape all Unicode characters to HTML entities." + result = '' + pos = TextPosition(line) + while not pos.finished(): + if ord(pos.current()) > 128: + codepoint = hex(ord(pos.current())) + if codepoint == '0xd835': + codepoint = hex(ord(pos.next()) + 0xf800) + result += '&#' + codepoint[1:] + ';' + else: + result += pos.current() + pos.skipcurrent() + return result + + def searchall(self, type): + "Search for all embedded containers of a given type" + list = [] + self.searchprocess(type, lambda container: list.append(container)) + return list + + def searchremove(self, type): + "Search for all containers of a type and remove them" + list = self.searchall(type) + for container in list: + container.parent.contents.remove(container) + return list + + def searchprocess(self, type, process): + "Search for elements of a given type and process them" + self.locateprocess(lambda container: isinstance(container, type), process) + + def locateprocess(self, locate, process): + "Search for all embedded containers and process them" + for container in self.contents: + container.locateprocess(locate, process) + if locate(container): + process(container) + + def recursivesearch(self, locate, recursive, process): + "Perform a recursive search in the container." + for container in self.contents: + if recursive(container): + container.recursivesearch(locate, recursive, process) + if locate(container): + process(container) + + def extracttext(self): + "Extract all text from elyxer.allowed containers." + result = '' + constants = ContainerExtractor(ContainerConfig.extracttext).extract(self) + for constant in constants: + result += constant.string + return result + + def group(self, index, group, isingroup): + "Group some adjoining elements into a group" + if index >= len(self.contents): + return + if hasattr(self.contents[index], 'grouped'): + return + while index < len(self.contents) and isingroup(self.contents[index]): + self.contents[index].grouped = True + group.contents.append(self.contents[index]) + self.contents.pop(index) + self.contents.insert(index, group) + + def remove(self, index): + "Remove a container but leave its contents" + container = self.contents[index] + self.contents.pop(index) + while len(container.contents) > 0: + self.contents.insert(index, container.contents.pop()) + + def tree(self, level = 0): + "Show in a tree" + Trace.debug(" " * level + unicode(self)) + for container in self.contents: + container.tree(level + 1) + + def getparameter(self, name): + "Get the value of a parameter, if present." + if not name in self.parameters: + return None + return self.parameters[name] + + def getparameterlist(self, name): + "Get the value of a comma-separated parameter as a list." + paramtext = self.getparameter(name) + if not paramtext: + return [] + return paramtext.split(',') + + def hasemptyoutput(self): + "Check if the parent's output is empty." + current = self.parent + while current: + if current.output.isempty(): + return True + current = current.parent + return False + + def __unicode__(self): + "Get a description" + if not self.begin: + return self.__class__.__name__ + return self.__class__.__name__ + '@' + unicode(self.begin) + +class BlackBox(Container): + "A container that does not output anything" + + def __init__(self): + self.parser = LoneCommand() + self.output = EmptyOutput() + self.contents = [] + +class LyXFormat(BlackBox): + "Read the lyxformat command" + + def process(self): + "Show warning if version < 276" + version = int(self.header[1]) + if version < 276: + Trace.error('Warning: unsupported old format version ' + str(version)) + if version > int(GeneralConfig.version['lyxformat']): + Trace.error('Warning: unsupported new format version ' + str(version)) + +class StringContainer(Container): + "A container for a single string" + + parsed = None + + def __init__(self): + self.parser = StringParser() + self.output = StringOutput() + self.string = '' + + def process(self): + "Replace special chars from elyxer.the contents." + if self.parsed: + self.string = self.replacespecial(self.parsed) + self.parsed = None + + def replacespecial(self, line): + "Replace all special chars from elyxer.a line" + replaced = self.escape(line, EscapeConfig.entities) + replaced = self.changeline(replaced) + if ContainerConfig.string['startcommand'] in replaced and len(replaced) > 1: + # unprocessed commands + if self.begin: + message = 'Unknown command at ' + unicode(self.begin) + ': ' + else: + message = 'Unknown command: ' + Trace.error(message + replaced.strip()) + return replaced + + def changeline(self, line): + line = self.escape(line, EscapeConfig.chars) + if not ContainerConfig.string['startcommand'] in line: + return line + line = self.escape(line, EscapeConfig.commands) + return line + + def extracttext(self): + "Return all text." + return self.string + + def __unicode__(self): + "Return a printable representation." + result = 'StringContainer' + if self.begin: + result += '@' + unicode(self.begin) + ellipsis = '...' + if len(self.string.strip()) <= 15: + ellipsis = '' + return result + ' (' + self.string.strip()[:15] + ellipsis + ')' + +class Constant(StringContainer): + "A constant string" + + def __init__(self, text): + self.contents = [] + self.string = text + self.output = StringOutput() + + def __unicode__(self): + return 'Constant: ' + self.string + +class TaggedText(Container): + "Text inside a tag" + + output = None + + def __init__(self): + self.parser = TextParser(self) + self.output = TaggedOutput() + + def complete(self, contents, tag, breaklines=False): + "Complete the tagged text and return it" + self.contents = contents + self.output.tag = tag + self.output.breaklines = breaklines + return self + + def constant(self, text, tag, breaklines=False): + "Complete the tagged text with a constant" + constant = Constant(text) + return self.complete([constant], tag, breaklines) + + def __unicode__(self): + "Return a printable representation." + if not hasattr(self.output, 'tag'): + return 'Emtpy tagged text' + if not self.output.tag: + return 'Tagged <unknown tag>' + return 'Tagged <' + self.output.tag + '>' + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/factory.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/factory.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/factory.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/factory.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,155 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090509 +# eLyXer factory to create and parse containers + +from elyxer.util.trace import Trace +from elyxer.conf.config import * +from elyxer.gen.styles import * +from elyxer.ref.link import * +from elyxer.ref.label import * +from elyxer.bib.biblio import * +from elyxer.ref.index import * +from elyxer.maths.formula import * +from elyxer.maths.command import * +from elyxer.maths.hybrid import * +from elyxer.gen.table import * +from elyxer.gen.image import * +from elyxer.gen.layout import * +from elyxer.gen.list import * +from elyxer.gen.inset import * +from elyxer.gen.include import * +from elyxer.gen.notes import * +from elyxer.gen.float import * +from elyxer.gen.header import * +from elyxer.gen.change import * +from elyxer.maths.array import * +from elyxer.bib.tex import * +from elyxer.bib.pub import * +from elyxer.xtra.newfangle import * +from elyxer.maths.macro import * +from elyxer.maths.extracommand import * +from elyxer.tex.texcode import * +from elyxer.maths.misc import * + + +class ContainerFactory(object): + "Creates containers depending on the first line" + + def __init__(self): + "Read table that convert start lines to containers" + types = dict() + for start, typename in ContainerConfig.starts.iteritems(): + types[start] = globals()[typename] + self.tree = ParseTree(types) + + def createcontainer(self, reader): + "Parse a single container." + #Trace.debug('processing "' + reader.currentline().strip() + '"') + if reader.currentline() == '': + reader.nextline() + return None + container = Cloner.create(self.tree.find(reader)) + container.start = reader.currentline().strip() + self.parse(container, reader) + return container + + def parse(self, container, reader): + "Parse a container" + parser = container.parser + parser.parent = container + parser.ending = self.getending(container) + parser.factory = self + container.header = parser.parseheader(reader) + container.begin = parser.begin + self.parsecontents(container, reader) + container.parameters = parser.parameters + container.parser = None + + def parsecontents(self, container, reader): + "Parse the contents of a container." + contents = container.parser.parse(reader) + if isinstance(contents, basestring): + # read a string, set as parsed + container.parsed = contents + container.contents = [] + else: + container.contents = contents + + def getending(self, container): + "Get the ending for a container" + split = container.start.split() + if len(split) == 0: + return None + start = split[0] + if start in ContainerConfig.startendings: + return ContainerConfig.startendings[start] + classname = container.__class__.__name__ + if classname in ContainerConfig.endings: + return ContainerConfig.endings[classname] + if hasattr(container, 'ending'): + Trace.error('Pending ending in ' + container.__class__.__name__) + return container.ending + return None + +class ParseTree(object): + "A parsing tree" + + default = '~~default~~' + + def __init__(self, types): + "Create the parse tree" + self.root = dict() + for start, type in types.iteritems(): + self.addstart(type, start) + + def addstart(self, type, start): + "Add a start piece to the tree" + tree = self.root + for piece in start.split(): + if not piece in tree: + tree[piece] = dict() + tree = tree[piece] + if ParseTree.default in tree: + Trace.error('Start ' + start + ' duplicated') + tree[ParseTree.default] = type + + def find(self, reader): + "Find the current sentence in the tree" + branches = self.matchline(reader.currentline()) + while not ParseTree.default in branches[-1]: + branches.pop() + last = branches[-1] + return last[ParseTree.default] + + def matchline(self, line): + "Match a given line against the tree, as deep as possible." + branches = [self.root] + for piece in line.split(' '): + current = branches[-1] + piece = piece.rstrip('>') + if piece in current: + branches.append(current[piece]) + else: + return branches + return branches + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/float.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/float.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/float.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/float.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,272 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090518 +# LyX floats + +from elyxer.util.trace import Trace +from elyxer.util.numbering import * +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.gen.layout import * +from elyxer.gen.image import * +from elyxer.ref.label import * +from elyxer.ref.partkey import * +from elyxer.proc.postprocess import * + + +class Float(Container): + "A floating inset" + + type = 'none' + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('div class="float"', True) + + def process(self): + "Get the float type." + self.type = self.header[2] + self.processnumber() + self.processfloats() + self.processtags() + + def isparent(self): + "Find out whether the float is the parent float or is contained in another float." + current = self.parent + while current: + if isinstance(current, Float): + return False + current = current.parent + return True + + def processnumber(self): + "Number a float if it isn't numbered." + if not self.isparent(): + # do nothing; parent will take care of numbering + return + self.partkey = PartKey().createfloat(self) + + def processtags(self): + "Process the HTML tags." + tagged = self.embed() + self.applywideningtag(tagged) + + def embed(self): + "Embed the whole contents in a div." + embeddedtag = self.getembeddedtag() + tagged = TaggedText().complete(self.contents, embeddedtag, True) + self.contents = [tagged] + return tagged + + def processfloats(self): + "Process all floats contained inside." + floats = self.searchall(Float) + counter = NumberCounter('subfloat').setmode('a') + for subfloat in floats: + subfloat.output.tag = subfloat.output.tag.replace('div', 'span') + subfloat.partkey = PartKey().createsubfloat(counter.getnext()) + + def getembeddedtag(self): + "Get the tag for the embedded object." + floats = self.searchall(Float) + if len(floats) > 0: + return 'div class="multi' + self.type + '"' + return 'div class="' + self.type + '"' + + def applywideningtag(self, container): + "Apply the tag to set float width, if present." + images = self.searchall(Image) + if len(images) != 1: + return '' + image = images[0] + if not image.size: + return + width = image.size.removepercentwidth() + if not width: + return + image.type = 'figure' + ContainerSize().setmax(width).addstyle(container) + image.settag() + + def searchinside(self, type): + "Search for a given type in the contents" + return self.searchincontents(self.contents, type) + + def searchincontents(self, contents, type): + "Search in the given contents for the required type." + list = [] + for element in contents: + list += self.searchinelement(element, type) + return list + + def searchinelement(self, element, type): + "Search for a given type outside floats" + if isinstance(element, Float): + return [] + if isinstance(element, type): + return [element] + return self.searchincontents(element.contents, type) + + def __unicode__(self): + "Return a printable representation" + return 'Floating inset of type ' + self.type + +class Wrap(Float): + "A wrapped (floating) float" + + def processtags(self): + "Add the widening tag to the parent tag." + self.embed() + placement = self.getparameter('placement') + if not placement: + placement = 'o' + self.output.tag = 'div class="wrap-' + placement + '"' + self.applywideningtag(self) + +class Listing(Container): + "A code listing" + + processor = None + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('div class="listing"', True) + self.numbered = None + + def process(self): + "Remove all layouts" + self.counter = 0 + self.type = 'listing' + self.processparams() + if Listing.processor: + Listing.processor.preprocess(self) + for container in self.extractcontents(): + if container: + self.contents.append(container) + if 'caption' in self.lstparams: + text = self.lstparams['caption'][1:-1] + self.contents.insert(0, Caption().create(text)) + if Listing.processor: + Listing.processor.postprocess(self) + + def extractcontents(self): + "Extract all contents one container at a time." + oldcontents = self.contents + self.contents = [] + inpre = [] + for container in oldcontents: + if self.iscaption(container): + yield self.completepre(inpre) + inpre = [] + yield container + else: + inpre += self.extract(container) + yield self.completepre(inpre) + + def processparams(self): + "Process listing parameteres." + LstParser().parsecontainer(self) + if 'numbers' in self.lstparams: + self.numbered = self.lstparams['numbers'] + + def iscaption(self, container): + "Find out if the container has a caption (which should not be in <pre>)." + return (len(container.searchall(Caption)) > 0) + + def completepre(self, listinpre): + "Complete the <pre> tag with whatever has already been added." + if len(listinpre) == 0: + return None + return TaggedText().complete(listinpre, 'pre class="listing"', False) + + def extract(self, container): + "Extract the container's contents and return them" + if isinstance(container, StringContainer): + return self.modifystring(container) + if isinstance(container, StandardLayout): + return self.modifylayout(container) + if isinstance(container, PlainLayout): + return self.modifylayout(container) + Trace.error('Unexpected container ' + container.__class__.__name__ + + ' in listing') + container.tree() + return [] + + def modifystring(self, string): + "Modify a listing string" + if string.string == '': + string.string = u'​' + return self.modifycontainer(string) + + def modifylayout(self, layout): + "Modify a standard layout" + if len(layout.contents) == 0: + layout.contents = [Constant(u'​')] + return self.modifycontainer(layout) + + def modifycontainer(self, container): + "Modify a listing container" + contents = [container, Constant('\n')] + if self.numbered: + self.counter += 1 + tag = 'span class="number-' + self.numbered + '"' + contents.insert(0, TaggedText().constant(unicode(self.counter), tag)) + return contents + +class FloatNumber(Container): + "Holds the number for a float in the caption." + + def __init__(self): + self.output = ContentsOutput() + + def create(self, float): + "Create the float number." + self.contents = [Constant(float.partkey.partkey)] + return self + +class PostFloat(object): + "Postprocess a float: number it and move the label" + + processedclass = Float + + def postprocess(self, last, float, next): + "Move the label to the top and number the caption" + number = FloatNumber().create(float) + for caption in float.searchinside(Caption): + self.postlabels(float, caption) + caption.contents = [number, Separator(u' ')] + caption.contents + return float + + def postlabels(self, float, caption): + "Search for labels and move them to the top" + labels = caption.searchremove(Label) + if len(labels) == 0 and float.partkey.tocentry: + labels = [Label().create(' ', float.partkey.partkey.replace(' ', '-'))] + float.contents = labels + float.contents + +class PostWrap(PostFloat): + "For a wrap: exactly like a float" + + processedclass = Wrap + +Postprocessor.stages += [PostFloat, PostWrap] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/header.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/header.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/header.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/header.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,128 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090312 +# LyX structure in containers + +from elyxer.util.docparams import * +from elyxer.parse.parser import * +from elyxer.parse.headerparse import * +from elyxer.out.output import * +from elyxer.out.template import * +from elyxer.gen.container import * +from elyxer.ref.partkey import * +from elyxer.maths.command import * +from elyxer.maths.macro import * +from elyxer.gen.notes import * + + +class LyXHeader(Container): + "Reads the header, outputs the HTML header" + + def __init__(self): + self.contents = [] + self.parser = HeaderParser() + self.output = HeaderOutput() + self.parameters = dict() + self.partkey = PartKey().createheader('header') + + def process(self): + "Find pdf title" + DocumentParameters.pdftitle = self.getheaderparameter('pdftitle') + documentclass = self.getheaderparameter('documentclass') + if documentclass in HeaderConfig.styles['article']: + DocumentParameters.startinglevel = 1 + if documentclass in HeaderConfig.styles['book']: + DocumentParameters.bibliography = 'bibliography' + else: + DocumentParameters.bibliography = 'references' + if self.getheaderparameter('paragraphseparation') == 'indent': + DocumentParameters.indentstandard = True + DocumentParameters.tocdepth = self.getlevel('tocdepth') + DocumentParameters.maxdepth = self.getlevel('secnumdepth') + DocumentParameters.language = self.getheaderparameter('language') + if self.getheaderparameter('outputchanges') == 'true': + DocumentParameters.outputchanges = True + return self + + def getheaderparameter(self, configparam): + "Get a parameter configured in HeaderConfig." + key = HeaderConfig.parameters[configparam] + if not key in self.parameters: + return None + return self.parameters[key] + + def getlevel(self, configparam): + "Get a level read as a parameter from elyxer.HeaderConfig." + paramvalue = self.getheaderparameter(configparam) + if not paramvalue: + return 0 + value = int(paramvalue) + if DocumentParameters.startinglevel == 1: + return value + return value + 1 + +class LyXPreamble(Container): + "The preamble at the beginning of a LyX file. Parsed for macros." + + def __init__(self): + self.parser = PreambleParser() + self.output = EmptyOutput() + self.factory = FormulaFactory() + + def process(self): + "Parse the LyX preamble, if needed." + if len(PreambleParser.preamble) == 0: + return + pos = TextPosition('\n'.join(PreambleParser.preamble)) + while not pos.finished(): + if self.detectfunction(pos): + self.parsefunction(pos) + else: + pos.globincluding('\n') + PreambleParser.preamble = [] + + def detectfunction(self, pos): + "Detect a macro definition or a preamble function." + for function in FormulaConfig.misccommands: + if pos.checkfor(function): + return True + return False + + def parsefunction(self, pos): + "Parse a single command." + self.factory.parsetype(FormulaCommand, pos) + +class LyXFooter(Container): + "Reads the footer, outputs the HTML footer" + + def __init__(self): + self.contents = [] + self.parser = BoundedDummy() + self.output = FooterOutput() + self.partkey = PartKey().createheader('footer') + + def process(self): + "Include any footnotes at the end." + if EndFootnotes.footnotes: + endnotes = EndFootnotes() + self.contents = [endnotes] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/image.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/image.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/image.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/image.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,277 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090308 +# eLyXer image treatment + +import struct +import sys +import os +import shutil +from elyxer.util.trace import Trace +from elyxer.util.translate import * +from elyxer.gen.container import * +from elyxer.gen.size import * +from elyxer.io.path import * + + +class Image(Container): + "An embedded image" + + defaultformat = ImageConfig.formats['default'] + size = None + copy = None + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput() + self.type = 'embedded' + + def process(self): + "Place the url, convert the image if necessary." + self.origin = InputPath(self.getparameter('filename')) + self.destination = self.getdestination(self.origin) + self.size = ContainerSize().readparameters(self) + if self.origin.exists(): + ImageConverter.instance.convert(self) + else: + Trace.error('Image ' + unicode(self.origin) + ' not found') + self.setsize() + self.settag() + + def getdestination(self, origin): + "Convert origin path to destination path." + "Changes extension of destination to output image format." + destination = OutputPath(origin) + if Options.noconvert: + return destination + self.convertformat(destination) + destination.removebackdirs() + return destination + + def convertformat(self, destination): + "Convert the format of the destination image." + if Options.copyimages: + return + imageformat = '.jpg' + forcedest = Image.defaultformat + if Options.imageformat: + imageformat = Options.imageformat + forcedest = Options.imageformat + if not destination.hasext(imageformat): + destination.changeext(forcedest) + + def setsize(self): + "Set the size attributes width and height." + width, height = ImageFile(self.destination).getdimensions() + self.size.checkimage(width, height) + + def scalevalue(self, value): + "Scale the value according to the image scale and return it as unicode." + scaled = value * int(self.size.scale) / 100 + return unicode(int(scaled)) + 'px' + + def settag(self): + "Set the output tag for the image." + tag = 'img class="' + self.type + '"' + if self.origin.exists(): + url = self.destination.url + else: + url = self.origin.url + alt = Translator.translate('figure') + ' ' + url + tag += ' src="' + url + '" alt="' + alt + '"' + emptytag = True + if self.destination.hasext('.svg'): + self.contents = [Constant(alt)] + tag = 'object class="' + self.type + '" data="' + url + '"' + emptytag = False + self.output.settag(tag, True, empty=emptytag) + self.size.addstyle(self) + +class ImageConverter(object): + "A converter from elyxer.one image file to another." + + vectorformats = ImageConfig.formats['vector'] + cropboxformats = ImageConfig.cropboxformats + + active = True + instance = None + + def convert(self, image): + "Convert an image to PNG" + if not ImageConverter.active or Options.noconvert: + return + if image.origin.path == image.destination.path: + return + if image.destination.exists(): + if image.origin.getmtime() <= image.destination.getmtime(): + # file has not changed; do not convert + return + image.destination.createdirs() + if Options.copyimages: + Trace.debug('Copying ' + image.origin.path + ' to ' + image.destination.path) + shutil.copy2(image.origin.path, image.destination.path) + return + converter, command = self.buildcommand(image) + try: + Trace.debug(converter + ' command: "' + command + '"') + result = os.system(command.encode(sys.getfilesystemencoding())) + if result != 0: + Trace.error(converter + ' not installed; images will not be processed') + ImageConverter.active = False + return + Trace.message('Converted ' + unicode(image.origin) + ' to ' + + unicode(image.destination)) + except OSError, exception: + Trace.error('Error while converting image ' + unicode(image.origin) + + ': ' + unicode(exception)) + + def buildcommand(self, image): + "Build the command to convert the image." + if Options.converter in ImageConfig.converters: + command = ImageConfig.converters[Options.converter] + else: + command = Options.converter; + params = self.getparams(image) + for param in params: + command = command.replace('$' + param, unicode(params[param])) + # remove unwanted options + while '[' in command and ']' in command: + command = self.removeparam(command) + return Options.converter, command + + def removeparam(self, command): + "Remove an unwanted param." + if command.index('[') > command.index(']'): + Trace.error('Converter command should be [...$...]: ' + command) + exit() + before = command[:command.index('[')] + after = command[command.index(']') + 1:] + between = command[command.index('[') + 1:command.index(']')] + if '$' in between: + return before + after + return before + between + after + + def getparams(self, image): + "Get the parameters for ImageMagick conversion" + params = dict() + params['input'] = image.origin + params['output'] = image.destination + if image.origin.hasexts(self.vectorformats): + scale = 100 + if image.size.scale: + scale = image.size.scale + # descale + image.size.scale = None + params['scale'] = scale + if image.origin.getext() in self.cropboxformats: + params['format'] = self.cropboxformats[image.origin.getext()] + return params + +ImageConverter.instance = ImageConverter() + +class ImageFile(object): + "A file corresponding to an image (JPG or PNG)" + + dimensions = dict() + + def __init__(self, path): + "Create the file based on its path" + self.path = path + + def getdimensions(self): + "Get the dimensions of a JPG or PNG image" + if not self.path.exists(): + return None, None + if unicode(self.path) in ImageFile.dimensions: + return ImageFile.dimensions[unicode(self.path)] + dimensions = (None, None) + if self.path.hasext('.png'): + dimensions = self.getpngdimensions() + elif self.path.hasext('.jpg'): + dimensions = self.getjpgdimensions() + elif self.path.hasext('.svg'): + dimensions = self.getsvgdimensions() + ImageFile.dimensions[unicode(self.path)] = dimensions + return dimensions + + def getpngdimensions(self): + "Get the dimensions of a PNG image" + pngfile = self.path.open() + pngfile.seek(16) + width = self.readlong(pngfile) + height = self.readlong(pngfile) + pngfile.close() + return (width, height) + + def getjpgdimensions(self): + "Get the dimensions of a JPEG image" + jpgfile = self.path.open() + start = self.readword(jpgfile) + if start != int('ffd8', 16): + Trace.error(unicode(self.path) + ' not a JPEG file') + return (None, None) + self.skipheaders(jpgfile, ['ffc0', 'ffc2']) + self.seek(jpgfile, 3) + height = self.readword(jpgfile) + width = self.readword(jpgfile) + jpgfile.close() + return (width, height) + + def getsvgdimensions(self): + "Get the dimensions of a SVG image." + return (None, None) + + def skipheaders(self, file, hexvalues): + "Skip JPEG headers until one of the parameter headers is found" + headervalues = [int(value, 16) for value in hexvalues] + header = self.readword(file) + safetycounter = 0 + while header not in headervalues and safetycounter < 30: + length = self.readword(file) + if length == 0: + Trace.error('End of file ' + file.name) + return + self.seek(file, length - 2) + header = self.readword(file) + safetycounter += 1 + + def readlong(self, file): + "Read a long (32-bit) value from elyxer.file" + return self.readformat(file, '>L', 4) + + def readword(self, file): + "Read a 16-bit value from elyxer.file" + return self.readformat(file, '>H', 2) + + def readformat(self, file, format, bytes): + "Read any format from elyxer.file" + read = file.read(bytes) + if read == '' or len(read) < bytes: + Trace.error('EOF reached') + return 0 + tuple = struct.unpack(format, read) + return tuple[0] + + def seek(self, file, bytes): + "Seek forward, just by reading the given number of bytes" + file.read(bytes) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/include.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/include.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/include.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/include.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,111 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20110201 +# LyX child documents (included insets). + +from elyxer.util.trace import Trace +from elyxer.parse.parser import * +from elyxer.parse.headerparse import * +from elyxer.out.output import * +from elyxer.io.bulk import * +from elyxer.gen.container import * +from elyxer.gen.styles import * +from elyxer.gen.layout import * +from elyxer.gen.float import * + + +class IncludeInset(Container): + "A child document included within another." + + # the converter factory will be set in converter.py + converterfactory = None + filename = None + + def __init__(self): + self.parser = InsetParser() + self.output = ContentsOutput() + + def process(self): + "Include the provided child document" + self.filename = os.path.join(Options.directory, self.getparameter('filename')) + Trace.debug('Child document: ' + self.filename) + LstParser().parsecontainer(self) + command = self.getparameter('LatexCommand') + if command == 'verbatiminput': + self.readverbatim() + return + elif command == 'lstinputlisting': + self.readlisting() + return + self.processinclude() + + def processinclude(self): + "Process a regular include: standard child document." + self.contents = [] + olddir = Options.directory + newdir = os.path.dirname(self.getparameter('filename')) + if newdir != '': + Trace.debug('Child dir: ' + newdir) + Options.directory = os.path.join(Options.directory, newdir) + try: + self.convertinclude() + finally: + Options.directory = olddir + + def convertinclude(self): + "Convert an included document." + try: + converter = IncludeInset.converterfactory.create(self) + except: + Trace.error('Could not read ' + self.filename + ', please check that the file exists and has read permissions.') + return + if self.hasemptyoutput(): + return + converter.convert() + self.contents = converter.getcontents() + + def readverbatim(self): + "Read a verbatim document." + self.contents = [TaggedText().complete(self.readcontents(), 'pre', True)] + + def readlisting(self): + "Read a document as a listing." + listing = Listing() + listing.contents = self.readcontents() + listing.parameters = self.parameters + listing.process() + self.contents = [listing] + + def readcontents(self): + "Read the contents of a complete file." + contents = list() + lines = BulkFile(self.filename).readall() + for line in lines: + contents.append(Constant(line)) + return contents + + def __unicode__(self): + "Return a printable description." + if not self.filename: + return 'Included unnamed file' + return 'Included "' + self.filename + '"' + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/inset.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/inset.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/inset.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/inset.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,180 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090506 +# LyX insets + +from elyxer.util.trace import Trace +from elyxer.parse.parser import * +from elyxer.parse.headerparse import * +from elyxer.out.output import * +from elyxer.io.bulk import * +from elyxer.gen.container import * +from elyxer.gen.styles import * +from elyxer.gen.layout import * + + +class InsetText(Container): + "An inset of text in a lyx file" + + def __init__(self): + self.parser = BoundedParser() + self.output = ContentsOutput() + +class Inset(Container): + "A generic inset in a LyX document" + + def __init__(self): + self.contents = list() + self.parser = InsetParser() + self.output = TaggedOutput().setbreaklines(True) + + def process(self): + self.type = self.header[1] + self.output.tag = 'span class="' + self.type + '"' + + def __unicode__(self): + return 'Inset of type ' + self.type + +class NewlineInset(Newline): + "A newline or line break in an inset" + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + +class NewPageInset(NewPage): + "A new page command." + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + +class Branch(Container): + "A branch within a LyX document" + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="branch"', True) + + def process(self): + "Disable inactive branches" + self.branch = self.header[2] + if not self.isactive(): + Trace.debug('Branch ' + self.branch + ' not active') + self.output = EmptyOutput() + + def isactive(self): + "Check if the branch is active" + if not self.branch in Options.branches: + Trace.error('Invalid branch ' + self.branch) + return True + branch = Options.branches[self.branch] + return branch.isselected() + +class ShortTitle(Container): + "A short title to display (always hidden)" + + def __init__(self): + self.parser = InsetParser() + self.output = EmptyOutput() + +class FlexInset(Container): + "A flexible inset, generic version." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span', False) + + def process(self): + "Set the correct flex tag." + self.type = self.header[2] + if self.type in TagConfig.flex: + self.output.settag(TagConfig.flex[self.type], False) + else: + self.output.settag('span class="' + self.type + '"', False) + +class InfoInset(Container): + "A LyX Info inset" + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="Info"', False) + + def process(self): + "Set the shortcut as text" + self.type = self.getparameter('type') + self.contents = [Constant(self.getparameter('arg'))] + +class BoxInset(Container): + "A box inset" + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('div', True) + + def process(self): + "Set the correct tag" + self.type = self.header[2] + self.output.settag('div class="' + self.type + '"', True) + ContainerSize().readparameters(self).addstyle(self) + +class PhantomText(Container): + "A line of invisible text (white over white)." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="phantom"', False) + +class LineInset(LyXLine): + "A LaTeX ruler, but parsed as an inset." + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + +class Caption(Container): + "A caption for a figure or a table" + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('div class="caption"', True) + + def create(self, message): + "Create a caption with a given message." + self.contents = [Constant(message)] + return self + +class ScriptInset(Container): + "Sub- or super-script in an inset." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span', False) + + def process(self): + "Set the correct script tag." + self.type = self.header[2] + if not self.type in TagConfig.script: + Trace.error('Unknown script type ' + self.type) + return + self.output.settag(TagConfig.script[self.type], False) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/integral.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/integral.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/integral.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/integral.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,174 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20091109 +# eLyXer integral processing +# http://www.nongnu.org/elyxer/ + +from elyxer.gen.layout import * +from elyxer.gen.float import * +from elyxer.ref.index import * +from elyxer.bib.biblio import * +from elyxer.gen.basket import * + + +class IntegralProcessor(object): + "A processor for an integral document." + + def __init__(self): + "Create the processor for the integral contents." + self.storage = [] + + def locate(self, container): + "Locate only containers of the processed type." + return isinstance(container, self.processedtype) + + def store(self, container): + "Store a new container." + self.storage.append(container) + + def process(self): + "Process the whole storage." + for container in self.storage: + self.processeach(container) + +class IntegralTOC(IntegralProcessor): + "A processor for an integral TOC." + + processedtype = TableOfContents + tocentries = [] + + def processeach(self, toc): + "Fill in a Table of Contents." + converter = TOCConverter() + for container in PartKeyGenerator.partkeyed: + toc.add(converter.convertindented(container)) + # finish off with the footer to align indents + toc.add(converter.convertindented(LyXFooter())) + + def writetotoc(self, entries, toc): + "Write some entries to the TOC." + for entry in entries: + toc.contents.append(entry) + +class IntegralBiblioEntry(IntegralProcessor): + "A processor for an integral bibliography entry." + + processedtype = BiblioEntry + + def processeach(self, entry): + "Process each entry." + number = NumberGenerator.generator.generate('integralbib') + link = Link().complete('cite', 'biblio-' + number, type='biblioentry') + link.contents = entry.citeref + entry.contents = [Constant('['), link, Constant('] ')] + if entry.key in BiblioCite.cites: + for cite in BiblioCite.cites[entry.key]: + cite.contents = entry.citeref + cite.anchor = 'cite-' + number + cite.destination = link + +class IntegralFloat(IntegralProcessor): + "Store all floats in the document by type." + + processedtype = Float + bytype = dict() + + def processeach(self, float): + "Store each float by type." + if not float.type in IntegralFloat.bytype: + IntegralFloat.bytype[float.type] = [] + IntegralFloat.bytype[float.type].append(float) + +class IntegralListOf(IntegralProcessor): + "A processor for an integral list of floats." + + processedtype = ListOf + + def processeach(self, listof): + "Fill in a list of floats." + listof.output = TaggedOutput().settag('div class="fulltoc"', True) + if not listof.type in IntegralFloat.bytype: + Trace.message('No floats of type ' + listof.type) + return + for float in IntegralFloat.bytype[listof.type]: + entry = self.processfloat(float) + if entry: + listof.contents.append(entry) + + def processfloat(self, float): + "Get an entry for the list of floats." + if not float.isparent(): + return None + return TOCEntry().create(float) + +class IntegralReference(IntegralProcessor): + "A processor for a reference to a label." + + processedtype = Reference + + def processeach(self, reference): + "Extract the text of the original label." + reference.formatcontents() + +class MemoryBasket(KeeperBasket): + "A basket which stores everything in memory, processes it and writes it." + + def __init__(self): + "Create all processors in one go." + KeeperBasket.__init__(self) + self.processors = [ + IntegralTOC(), IntegralBiblioEntry(), + IntegralFloat(), IntegralListOf(), IntegralReference(), + ] + + def finish(self): + "Process everything which cannot be done in one pass and write to disk." + self.process() + self.flush() + + def process(self): + "Process everything with the integral processors." + self.searchintegral() + for processor in self.processors: + processor.process() + + def searchintegral(self): + "Search for all containers for all integral processors." + for container in self.contents: + # container.tree() + if self.integrallocate(container): + self.integralstore(container) + container.locateprocess(self.integrallocate, self.integralstore) + + def integrallocate(self, container): + "Locate all integrals." + for processor in self.processors: + if processor.locate(container): + return True + return False + + def integralstore(self, container): + "Store a container in one or more processors." + for processor in self.processors: + if processor.locate(container): + processor.store(container) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/layout.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/layout.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/layout.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/layout.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,336 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090411 +# LyX layout and derived classes + +from elyxer.util.trace import Trace +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.gen.container import * +from elyxer.gen.styles import * +from elyxer.gen.header import * +from elyxer.proc.postprocess import * +from elyxer.ref.label import * +from elyxer.ref.partkey import * +from elyxer.ref.link import * + + +class Layout(Container): + "A layout (block of text) inside a lyx file" + + type = 'none' + + def __init__(self): + "Initialize the layout." + self.contents = [] + self.parser = BoundedParser() + self.output = TaggedOutput().setbreaklines(True) + + def process(self): + "Get the type and numerate if necessary." + self.type = self.header[1] + if self.type in TagConfig.layouts: + self.output.tag = TagConfig.layouts[self.type] + ' class="' + self.type + '"' + elif self.type.replace('*', '') in TagConfig.layouts: + self.output.tag = TagConfig.layouts[self.type.replace('*', '')] + self.output.tag += ' class="' + self.type.replace('*', '-') + '"' + else: + self.output.tag = 'div class="' + self.type + '"' + self.numerate() + + def numerate(self): + "Numerate if necessary." + partkey = PartKeyGenerator.forlayout(self) + if partkey: + self.partkey = partkey + self.output.tag = self.output.tag.replace('?', unicode(partkey.level)) + + def __unicode__(self): + "Return a printable representation." + if self.partkey: + return 'Layout ' + self.type + ' #' + unicode(self.partkey.partkey) + return 'Layout of type ' + self.type + +class StandardLayout(Layout): + "A standard layout -- can be a true div or nothing at all" + + indentation = False + + def process(self): + self.type = 'standard' + self.output = ContentsOutput() + + def complete(self, contents): + "Set the contents and return it." + self.process() + self.contents = contents + return self + +class Title(Layout): + "The title of the whole document" + + def process(self): + self.type = 'title' + self.output.tag = 'h1 class="title"' + title = self.extracttext() + DocumentTitle.title = title + Trace.message('Title: ' + title) + +class Author(Layout): + "The document author" + + def process(self): + self.type = 'author' + self.output.tag = 'h2 class="author"' + author = self.extracttext() + Trace.debug('Author: ' + author) + DocumentAuthor.appendauthor(author) + +class Abstract(Layout): + "A paper abstract" + + done = False + + def process(self): + self.type = 'abstract' + self.output.tag = 'div class="abstract"' + if Abstract.done: + return + message = Translator.translate('abstract') + tagged = TaggedText().constant(message, 'p class="abstract-message"', True) + self.contents.insert(0, tagged) + Abstract.done = True + +class FirstWorder(Layout): + "A layout where the first word is extracted" + + def extractfirstword(self): + "Extract the first word as a list" + return self.extractfromcontents(self.contents) + + def extractfromcontents(self, contents): + "Extract the first word in contents." + firstcontents = [] + while len(contents) > 0: + if self.isfirstword(contents[0]): + firstcontents.append(contents[0]) + del contents[0] + return firstcontents + if self.spaceincontainer(contents[0]): + extracted = self.extractfromcontainer(contents[0]) + firstcontents.append(extracted) + return firstcontents + firstcontents.append(contents[0]) + del contents[0] + return firstcontents + + def extractfromcontainer(self, container): + "Extract the first word from a container cloning it including its output." + if isinstance(container, StringContainer): + return self.extractfromstring(container) + result = Cloner.clone(container) + result.output = container.output + result.contents = self.extractfromcontents(container.contents) + return result + + def extractfromstring(self, container): + "Extract the first word from elyxer.a string container." + if not ' ' in container.string: + Trace.error('No space in string ' + container.string) + return container + split = container.string.split(' ', 1) + container.string = split[1] + return Constant(split[0]) + + def spaceincontainer(self, container): + "Find out if the container contains a space somewhere." + return ' ' in container.extracttext() + + def isfirstword(self, container): + "Find out if the container is valid as a first word." + if not isinstance(container, FirstWord): + return False + return not container.isempty() + +class FirstWord(Container): + "A container which is in itself a first word, unless it's empty." + "Should be inherited by other containers, e.g. ERT." + + def isempty(self): + "Find out if the first word is empty." + Trace.error('Unimplemented isempty()') + return True + +class Description(FirstWorder): + "A description layout" + + def process(self): + "Set the first word to bold" + self.type = 'Description' + self.output.tag = 'div class="Description"' + firstword = self.extractfirstword() + if not firstword: + return + tag = 'span class="Description-entry"' + self.contents.insert(0, TaggedText().complete(firstword, tag)) + self.contents.insert(1, Constant(u' ')) + +class List(FirstWorder): + "A list layout" + + def process(self): + "Set the first word to bold" + self.type = 'List' + self.output.tag = 'div class="List"' + firstword = self.extractfirstword() + if not firstword: + return + first = TaggedText().complete(firstword, 'span class="List-entry"') + second = TaggedText().complete(self.contents, 'span class="List-contents"') + self.contents = [first, second] + +class PlainLayout(Layout): + "A plain layout" + + def process(self): + "Output just as contents." + self.output = ContentsOutput() + self.type = 'Plain' + + def makevisible(self): + "Make the layout visible, output as tagged text." + self.output = TaggedOutput().settag('div class="PlainVisible"', True) + +class LyXCode(Layout): + "A bit of LyX-Code." + + def process(self): + "Output as pre." + self.output.tag = 'pre class="LyX-Code"' + for newline in self.searchall(Newline): + index = newline.parent.contents.index(newline) + newline.parent.contents[index] = Constant('\n') + +class PostLayout(object): + "Numerate an indexed layout" + + processedclass = Layout + + def postprocess(self, last, layout, next): + "Group layouts and/or number them." + if layout.type in TagConfig.group['layouts']: + return self.group(last, layout) + if layout.partkey: + self.number(layout) + return layout + + def group(self, last, layout): + "Group two layouts if they are the same type." + if not self.isgroupable(layout) or not self.isgroupable(last) or last.type != layout.type: + return layout + layout.contents = last.contents + [Constant('<br/>\n')] + layout.contents + last.contents = [] + last.output = EmptyOutput() + return layout + + def isgroupable(self, container): + "Check that the container can be grouped." + if not isinstance(container, Layout): + return False + for element in container.contents: + if not element.__class__.__name__ in LayoutConfig.groupable['allowed']: + return False + return True + + def number(self, layout): + "Generate a number and place it before the text" + layout.partkey.addtoclabel(layout) + +class PostStandard(object): + "Convert any standard spans in root to divs" + + processedclass = StandardLayout + + def postprocess(self, last, standard, next): + "Switch to div, and clear if empty." + type = 'Standard' + if self.isempty(standard): + standard.output = EmptyOutput() + return standard + if DocumentParameters.indentstandard: + if isinstance(last, StandardLayout): + type = 'Indented' + else: + type = 'Unindented' + standard.output = TaggedOutput().settag('div class="' + type + '"', True) + return standard + + def isempty(self, standard): + "Find out if the standard layout is empty." + for element in standard.contents: + if not element.output.isempty(): + return False + return True + +class PostPlainLayout(PostLayout): + "Numerate a plain layout" + + processedclass = PlainLayout + + def postprocess(self, last, plain, next): + "Group plain layouts." + if not self.istext(last) or not self.istext(plain): + return plain + plain.makevisible() + return self.group(last, plain) + + def istext(self, container): + "Find out if the container is only text." + if not isinstance(container, PlainLayout): + return False + extractor = ContainerExtractor(TOCConfig.extractplain) + text = extractor.extract(container) + return (len(text) > 0) + +class PostLyXCode(object): + "Coalesce contiguous LyX-Code layouts." + + processedclass = LyXCode + + def postprocess(self, last, lyxcode, next): + "Coalesce if last was also LyXCode" + if not isinstance(last, LyXCode): + return lyxcode + if hasattr(last, 'first'): + lyxcode.first = last.first + else: + lyxcode.first = last + toappend = lyxcode.first.contents + toappend.append(Constant('\n')) + toappend += lyxcode.contents + lyxcode.output = EmptyOutput() + return lyxcode + +Postprocessor.stages += [ + PostLayout, PostStandard, PostLyXCode, PostPlainLayout + ] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/list.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/list.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/list.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/list.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,165 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20100427 +# eLyXer lists and list post-processing + +from elyxer.util.trace import Trace +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.gen.container import * +from elyxer.proc.postprocess import * + + +class ListItem(Container): + "An element in a list" + + type = 'none' + + def __init__(self): + "Create a list item." + self.parser = BoundedParser() + self.output = ContentsOutput() + + def process(self): + "Set the correct type and contents." + self.type = self.header[1] + tag = TaggedText().complete(self.contents, 'li', True) + self.contents = [tag] + + def __unicode__(self): + return self.type + ' item @ ' + unicode(self.begin) + +class DeeperList(Container): + "A nested list" + + def __init__(self): + "Create a nested list element." + self.parser = BoundedParser() + self.output = ContentsOutput() + self.contents = [] + + def process(self): + "Create the deeper list" + if len(self.contents) == 0: + Trace.error('Empty deeper list') + return + + def __unicode__(self): + result = 'deeper list @ ' + unicode(self.begin) + ': [' + for element in self.contents: + result += unicode(element) + ', ' + return result[:-2] + ']' + +class PendingList(object): + "A pending list" + + def __init__(self): + self.contents = [] + self.type = None + + def additem(self, item): + "Add a list item" + self.contents += item.contents + if not self.type: + self.type = item.type + + def adddeeper(self, deeper): + "Add a deeper list item" + if self.empty(): + self.insertfake() + self.contents[-1].contents += deeper.contents + + def generate(self): + "Get the resulting list" + if not self.type: + tag = 'ul' + else: + tag = TagConfig.listitems[self.type] + text = TaggedText().complete(self.contents, tag, True) + self.__init__() + return text + + def isduewithitem(self, item): + "Decide whether the pending list must be generated before the given item" + if not self.type: + return False + if self.type != item.type: + return True + return False + + def isduewithnext(self, next): + "Applies only if the list is finished with next item." + if not next: + return True + if not isinstance(next, ListItem) and not isinstance(next, DeeperList): + return True + return False + + def empty(self): + return len(self.contents) == 0 + + def insertfake(self): + "Insert a fake item" + item = TaggedText().constant('', 'li class="nested"', True) + self.contents = [item] + self.type = 'Itemize' + + def __unicode__(self): + result = 'pending ' + unicode(self.type) + ': [' + for element in self.contents: + result += unicode(element) + ', ' + if len(self.contents) > 0: + result = result[:-2] + return result + ']' + +class PostListItem(object): + "Postprocess a list item" + + processedclass = ListItem + + def postprocess(self, last, item, next): + "Add the item to pending and return an empty item" + if not hasattr(self.postprocessor, 'list'): + self.postprocessor.list = PendingList() + self.postprocessor.list.additem(item) + if self.postprocessor.list.isduewithnext(next): + return self.postprocessor.list.generate() + if isinstance(next, ListItem) and self.postprocessor.list.isduewithitem(next): + return self.postprocessor.list.generate() + return BlackBox() + +class PostDeeperList(object): + "Postprocess a deeper list" + + processedclass = DeeperList + + def postprocess(self, last, deeper, next): + "Append to the list in the postprocessor" + if not hasattr(self.postprocessor, 'list'): + self.postprocessor.list = PendingList() + self.postprocessor.list.adddeeper(deeper) + if self.postprocessor.list.isduewithnext(next): + return self.postprocessor.list.generate() + return BlackBox() + +Postprocessor.stages += [PostListItem, PostDeeperList] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/notes.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/notes.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/notes.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/notes.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,152 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20101119 +# LyX notes: notes, footnotes and margin notes. + +from elyxer.util.trace import Trace +from elyxer.util.numbering import * +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.gen.container import * +from elyxer.ref.link import * + + +class SideNote(Container): + "A side note that appears at the right." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput() + + def process(self): + "Enclose everything in a marginal span." + self.output.settag('span class="Marginal"', True) + +class FootnoteMarker(Container): + "A marker for a footnote." + + def __init__(self): + "Set the correct span class." + self.contents = [] + span = 'span class="SupFootMarker"' + if Options.alignfoot: + span = 'span class="AlignFootMarker"' + self.output = TaggedOutput().settag(span, False) + mode = 'A' + if Options.numberfoot: + mode = '1' + if Options.symbolfoot: + mode = '*' + NumberGenerator.generator.getcounter('Footnote').setmode(mode) + + def create(self): + "Create the marker for a footnote." + self.order = NumberGenerator.generator.generate('Footnote') + if Options.endfoot: + self.link = Link().complete(self.getmark(), 'footmarker-' + self.order) + self.createcontents() + return self + + def createanchor(self, marker): + "Create the anchor for a footnote. Adds a link for end footnotes." + self.order = marker.order + if Options.endfoot: + self.link = Link().complete(self.getmark(), 'footnote-' + self.order) + self.link.setmutualdestination(marker.link) + self.createcontents() + return self + + def createlabel(self, marker): + "Create the label for a footnote. Used in hoverfoot and marginfoot." + self.order = marker.order + self.contents = [Constant(self.getmark())] + space = Constant(u' ') + self.contents = [space] + self.contents + [space] + return self + + def createcontents(self): + "Create the contents of the marker." + if Options.endfoot: + self.contents = [self.link] + else: + self.contents = [Constant(self.getmark())] + space = Constant(u' ') + self.contents = [space] + self.contents + [space] + + def getmark(self): + "Get the mark to be displayed in the marker based on the order." + if Options.symbolfoot: + return self.order + else: + return '[' + self.order + ']' + +class Footnote(Container): + "A footnote to the main text." + + def __init__(self): + self.parser = InsetParser() + self.output = TaggedOutput().settag('span class="FootOuter"', False) + + def process(self): + "Add a counter for the footnote." + "Can be numeric or a letter depending on runtime options." + marker = FootnoteMarker().create() + anchor = FootnoteMarker().createanchor(marker) + label = FootnoteMarker().createlabel(marker) + notecontents = list(self.contents) + self.contents = [marker] + if Options.hoverfoot: + self.contents.append(self.createnote([label] + notecontents, 'span class="HoverFoot"')) + if Options.marginfoot: + self.contents.append(self.createnote([label] + notecontents, 'span class="MarginFoot"')) + if Options.endfoot: + EndFootnotes.footnotes.append(self.createnote([anchor] + notecontents, 'div class="EndFoot"')) + + def createnote(self, contents, tag): + "Create a note with the given contents and HTML tag." + return TaggedText().complete(contents, tag, False) + +class EndFootnotes(Container): + "The collection of footnotes at the document end." + + footnotes = [] + + def __init__(self): + "Generate all footnotes and a proper header for them all." + self.output = ContentsOutput() + header = TaggedText().constant(Translator.translate('footnotes'), 'h1 class="index"') + self.contents = [header] + self.footnotes + +class Note(Container): + "A LyX note of several types" + + def __init__(self): + self.parser = InsetParser() + self.output = EmptyOutput() + + def process(self): + "Hide note and comment, dim greyed out" + self.type = self.header[2] + if TagConfig.notes[self.type] == '': + return + self.output = TaggedOutput().settag(TagConfig.notes[self.type], True) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/size.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/size.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/size.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/size.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,155 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20100828 +# Container size parsing and output + +from elyxer.util.trace import Trace +from elyxer.gen.container import * + + +class ContainerSize(object): + "The size of a container." + + width = None + height = None + maxwidth = None + maxheight = None + scale = None + + def set(self, width = None, height = None): + "Set the proper size with width and height." + self.setvalue('width', width) + self.setvalue('height', height) + return self + + def setmax(self, maxwidth = None, maxheight = None): + "Set max width and/or height." + self.setvalue('maxwidth', maxwidth) + self.setvalue('maxheight', maxheight) + return self + + def readparameters(self, container): + "Read some size parameters off a container." + self.setparameter(container, 'width') + self.setparameter(container, 'height') + self.setparameter(container, 'scale') + self.checkvalidheight(container) + return self + + def setparameter(self, container, name): + "Read a size parameter off a container, and set it if present." + value = container.getparameter(name) + self.setvalue(name, value) + + def setvalue(self, name, value): + "Set the value of a parameter name, only if it's valid." + value = self.processparameter(value) + if value: + setattr(self, name, value) + + def checkvalidheight(self, container): + "Check if the height parameter is valid; otherwise erase it." + heightspecial = container.getparameter('height_special') + if self.height and self.extractnumber(self.height) == '1' and heightspecial == 'totalheight': + self.height = None + + def processparameter(self, value): + "Do the full processing on a parameter." + if not value: + return None + if self.extractnumber(value) == '0': + return None + for ignored in StyleConfig.size['ignoredtexts']: + if ignored in value: + value = value.replace(ignored, '') + return value + + def extractnumber(self, text): + "Extract the first number in the given text." + result = '' + decimal = False + for char in text: + if char.isdigit(): + result += char + elif char == '.' and not decimal: + result += char + decimal = True + else: + return result + return result + + def checkimage(self, width, height): + "Check image dimensions, set them if possible." + if width: + self.maxwidth = unicode(width) + 'px' + if self.scale and not self.width: + self.width = self.scalevalue(width) + if height: + self.maxheight = unicode(height) + 'px' + if self.scale and not self.height: + self.height = self.scalevalue(height) + if self.width and not self.height: + self.height = 'auto' + if self.height and not self.width: + self.width = 'auto' + + def scalevalue(self, value): + "Scale the value according to the image scale and return it as unicode." + scaled = value * int(self.scale) / 100 + return unicode(int(scaled)) + 'px' + + def removepercentwidth(self): + "Remove percent width if present, to set it at the figure level." + if not self.width: + return None + if not '%' in self.width: + return None + width = self.width + self.width = None + if self.height == 'auto': + self.height = None + return width + + def addstyle(self, container): + "Add the proper style attribute to the output tag." + if not isinstance(container.output, TaggedOutput): + Trace.error('No tag to add style, in ' + unicode(container)) + if not self.width and not self.height and not self.maxwidth and not self.maxheight: + # nothing to see here; move along + return + tag = ' style="' + tag += self.styleparameter('width') + tag += self.styleparameter('maxwidth') + tag += self.styleparameter('height') + tag += self.styleparameter('maxheight') + if tag[-1] == ' ': + tag = tag[:-1] + tag += '"' + container.output.tag += tag + + def styleparameter(self, name): + "Get the style for a single parameter." + value = getattr(self, name) + if value: + return name.replace('max', 'max-') + ': ' + value + '; ' + return '' + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/splitpart.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/splitpart.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/splitpart.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/splitpart.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,320 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20100418 +# eLyXer split part processing +# http://www.nongnu.org/elyxer/ + + +from elyxer.util.translate import * +from elyxer.gen.basket import * +from elyxer.gen.integral import * + + +class SplitPartLink(IntegralProcessor): + "A link processor for multi-page output." + + processedtype = Link + + def processeach(self, link): + "Process each link and add the current page." + link.page = self.page + +class NavigationLink(Container): + "A link in the navigation header." + + def __init__(self, name): + "Create the link for a given name (prev, next...)." + self.name = name + self.link = Link().complete(u' ', name, type=name) + self.output = TaggedOutput().settag('span class="' + name + '"') + self.contents = [self.link] + + def complete(self, container, after = False): + "Complete the navigation link with destination container." + "The 'after' parameter decides if the link goes after the part title." + if not container.partkey: + Trace.error('No part key for link name ' + unicode(container)) + return + self.link.contents = [Constant(Translator.translate(self.name))] + partname = self.getpartname(container) + separator = Constant(u' ') + if after: + self.contents = partname + [separator, self.link] + else: + self.contents = [self.link, separator] + partname + + def getpartname(self, container): + "Get the part name for a container, title optional." + partname = [Constant(container.partkey.tocentry)] + if not container.partkey.titlecontents: + return partname + if Options.notoclabels: + return container.partkey.titlecontents + return partname + [Constant(': ')] + container.partkey.titlecontents + + def setdestination(self, destination): + "Set the destination for this link." + self.link.destination = destination + + def setmutualdestination(self, destination): + "Set the destination for this link, and vice versa." + self.link.setmutualdestination(destination.link) + +class UpAnchor(Link): + "An anchor to the top of the page for the up links." + + def create(self, container): + "Create the up anchor based on the first container." + if not container.partkey: + Trace.error('No part key for ' + unicode(container)) + return None + self.createliteral(container.partkey.tocentry) + self.partkey.titlecontents = container.partkey.titlecontents + return self + + def createmain(self): + "Create the up anchor for the main page." + return self.createliteral(Translator.translate('main-page')) + + def createliteral(self, literal): + "Create the up anchor based on a literal string." + self.complete('', '') + self.output = EmptyOutput() + self.partkey = PartKey().createanchor(literal) + return self + +class SplitPartNavigation(object): + "Used to create the navigation links for a new split page." + + def __init__(self): + self.upanchors = [] + self.lastcontainer = None + self.nextlink = None + self.lastnavigation = None + + def writefirstheader(self, basket): + "Write the first header to the basket." + anchor = self.createmainanchor() + basket.write(anchor) + basket.write(self.createnavigation(anchor)) + + def writeheader(self, basket, container): + "Write the header to the basket." + basket.write(LyXHeader()) + basket.write(self.currentupanchor(container)) + basket.write(self.createnavigation(container)) + + def writefooter(self, basket): + "Write the footer to the basket." + if self.lastnavigation: + basket.write(self.lastnavigation) + basket.write(LyXFooter()) + + def createnavigation(self, container): + "Create the navigation bar with all links." + prevlink = NavigationLink('prev') + uplink = NavigationLink('up') + if self.nextlink: + prevlink.complete(self.lastcontainer) + self.nextlink.complete(container, after=True) + prevlink.setmutualdestination(self.nextlink) + uplink.complete(self.getupdestination(container)) + uplink.setdestination(self.getupdestination(container)) + self.nextlink = NavigationLink('next') + contents = [prevlink, Constant('\n'), uplink, Constant('\n'), self.nextlink] + header = TaggedText().complete(contents, 'div class="splitheader"', True) + self.lastcontainer = container + self.lastnavigation = header + return header + + def currentupanchor(self, container): + "Update the internal list of up anchors, and return the current one." + level = self.getlevel(container) + while len(self.upanchors) > level: + del self.upanchors[-1] + while len(self.upanchors) < level: + self.upanchors.append(self.upanchors[-1]) + upanchor = UpAnchor().create(container) + self.upanchors.append(upanchor) + return upanchor + + def createmainanchor(self): + "Create the up anchor to the main page." + mainanchor = UpAnchor().createmain() + self.upanchors.append(mainanchor) + return mainanchor + + def getupdestination(self, container): + "Get the name of the up page." + level = self.getlevel(container) + if len(self.upanchors) < level: + uppage = self.upanchors[-1] + else: + uppage = self.upanchors[level - 1] + return uppage + + def getlevel(self, container): + "Get the level of the container." + if not container.partkey: + return 1 + else: + return container.partkey.level + 1 + +class SplitFileBasket(MemoryBasket): + "A memory basket which contains a part split into a file, possibly with a TOC." + + def __init__(self): + MemoryBasket.__init__(self) + self.entrycount = 0 + self.root = None + self.converter = TOCConverter() + + def write(self, container): + "Keep track of numbered layouts." + MemoryBasket.write(self, container) + if not container.partkey: + return + if container.partkey.header: + return + entry = self.converter.convert(container) + if not entry: + return + self.entrycount += 1 + self.root = entry + + def addtoc(self): + "Add the table of contents if necessary." + if self.entrycount != 1: + return + if self.root.branches == []: + return + text = Translator.translate('toc-for') + self.root.partkey.tocentry + toc = TableOfContents().create(text) + self.addbranches(self.root, toc) + toc.add(self.converter.convertindented(LyXFooter())) + self.write(toc) + + def addbranches(self, entry, toc): + "Add an entry and all of its branches to the table of contents." + for branch in entry.branches: + toc.add(self.converter.indent(branch)) + self.addbranches(branch, toc) + +class SplitPartBasket(Basket): + "A basket used to split the output in different files." + + baskets = [] + + def setwriter(self, writer): + if not hasattr(writer, 'filename') or not writer.filename: + Trace.error('Cannot use standard output for split output; ' + + 'please supply an output filename.') + exit() + self.writer = writer + self.filename = writer.filename + self.converter = TOCConverter() + self.basket = MemoryBasket() + self.basket.page = writer.filename + return self + + def write(self, container): + "Write a container, possibly splitting the file." + self.basket.write(container) + + def splitbaskets(self): + "Process the whole basket and create all baskets for split part pages." + self.basket.process() + basket = self.firstbasket() + navigation = SplitPartNavigation() + for container in self.basket.contents: + if self.mustsplit(container): + filename = self.getfilename(container) + Trace.debug('New page ' + filename) + basket.addtoc() + navigation.writefooter(basket) + basket = self.addbasket(filename) + navigation.writeheader(basket, container) + basket.write(container) + if self.afterheader(container): + navigation.writefirstheader(basket) + self.mainanchor = navigation.upanchors[0] + for basket in self.baskets: + basket.process() + + def finish(self): + "Process the whole basket, split into page baskets and flush all of them." + self.splitbaskets() + for basket in self.baskets: + basket.flush() + + def afterheader(self, container): + "Find out if this is the header on the file." + return isinstance(container, LyXHeader) + + def firstbasket(self): + "Create the first basket." + return self.addbasket(self.filename, self.writer) + + def addbasket(self, filename, writer = None): + "Add a new basket." + if not writer: + writer = LineWriter(filename) + basket = SplitFileBasket() + basket.setwriter(writer) + self.baskets.append(basket) + # set the page name everywhere + basket.page = filename + splitpartlink = SplitPartLink() + splitpartlink.page = os.path.basename(basket.page) + basket.processors = [splitpartlink] + return basket + + def mustsplit(self, container): + "Find out if the oputput file has to be split at this entry." + if not container.partkey: + return False + if not container.partkey.filename: + return False + return True + + def getfilename(self, container): + "Get the new file name for a given container." + partname = container.partkey.filename + basename = self.filename + if Options.tocfor: + basename = Options.tocfor + base, extension = os.path.splitext(basename) + return base + '-' + partname + extension + +class SplitTOCBasket(SplitPartBasket): + "A basket which contains the TOC for a split part document." + + def finish(self): + "Process the whole basket, split into page baskets and flush all of them." + self.splitbaskets() + tocbasket = TOCBasket().setwriter(self.writer) + self.mainanchor.partkey = PartKey().createmain() + tocbasket.write(self.mainanchor) + for container in self.basket.contents: + tocbasket.write(container) + tocbasket.finish() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/styles.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/styles.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/styles.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/styles.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,241 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090311 +# LyX styles in containers + +from elyxer.util.trace import Trace +from elyxer.util.numbering import * +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.gen.container import * +from elyxer.gen.size import * + + +class QuoteContainer(Container): + "A container for a pretty quote" + + def __init__(self): + self.parser = BoundedParser() + self.output = FixedOutput() + + def process(self): + "Process contents" + self.type = self.header[2] + if not self.type in StyleConfig.quotes: + Trace.error('Quote type ' + self.type + ' not found') + self.html = ['"'] + return + self.html = [StyleConfig.quotes[self.type]] + +class LyXLine(Container): + "A Lyx line" + + def __init__(self): + self.parser = LoneCommand() + self.output = FixedOutput() + + def process(self): + self.html = ['<hr class="line" />'] + +class EmphaticText(TaggedText): + "Text with emphatic mode" + + def process(self): + self.output.tag = 'i' + +class ShapedText(TaggedText): + "Text shaped (italic, slanted)" + + def process(self): + self.type = self.header[1] + if not self.type in TagConfig.shaped: + Trace.error('Unrecognized shape ' + self.header[1]) + self.output.tag = 'span' + return + self.output.tag = TagConfig.shaped[self.type] + +class VersalitasText(TaggedText): + "Text in versalitas" + + def process(self): + self.output.tag = 'span class="versalitas"' + +class ColorText(TaggedText): + "Colored text" + + def process(self): + self.color = self.header[1] + self.output.tag = 'span class="' + self.color + '"' + +class SizeText(TaggedText): + "Sized text" + + def process(self): + self.size = self.header[1] + self.output.tag = 'span class="' + self.size + '"' + +class BoldText(TaggedText): + "Bold text" + + def process(self): + self.output.tag = 'b' + +class TextFamily(TaggedText): + "A bit of text from elyxer.a different family" + + def process(self): + "Parse the type of family" + self.type = self.header[1] + if not self.type in TagConfig.family: + Trace.error('Unrecognized family ' + type) + self.output.tag = 'span' + return + self.output.tag = TagConfig.family[self.type] + +class Hfill(TaggedText): + "Horizontall fill" + + def process(self): + self.output.tag = 'span class="hfill"' + +class BarredText(TaggedText): + "Text with a bar somewhere" + + def process(self): + "Parse the type of bar" + self.type = self.header[1] + if not self.type in TagConfig.barred: + Trace.error('Unknown bar type ' + self.type) + self.output.tag = 'span' + return + self.output.tag = TagConfig.barred[self.type] + +class LangLine(TaggedText): + "A line with language information" + + def process(self): + "Only generate a span with lang info when the language is recognized." + lang = self.header[1] + if not lang in TranslationConfig.languages: + self.output = ContentsOutput() + return + isolang = TranslationConfig.languages[lang] + self.output = TaggedOutput().settag('span lang="' + isolang + '"', False) + +class InsetLength(BlackBox): + "A length measure inside an inset." + + def process(self): + self.length = self.header[1] + +class Space(Container): + "A space of several types" + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + + def process(self): + self.type = self.header[2] + if self.type not in StyleConfig.hspaces: + Trace.error('Unknown space type ' + self.type) + self.html = [' '] + return + self.html = [StyleConfig.hspaces[self.type]] + length = self.getlength() + if not length: + return + self.output = TaggedOutput().settag('span class="hspace"', False) + ContainerSize().set(length).addstyle(self) + + def getlength(self): + "Get the space length from elyxer.the contents or parameters." + if len(self.contents) == 0 or not isinstance(self.contents[0], InsetLength): + return None + return self.contents[0].length + +class VerticalSpace(Container): + "An inset that contains a vertical space." + + def __init__(self): + self.parser = InsetParser() + self.output = FixedOutput() + + def process(self): + "Set the correct tag" + self.type = self.header[2] + if self.type not in StyleConfig.vspaces: + self.output = TaggedOutput().settag('div class="vspace" style="height: ' + self.type + ';"', True) + return + self.html = [StyleConfig.vspaces[self.type]] + +class Align(Container): + "Bit of aligned text" + + def __init__(self): + self.parser = ExcludingParser() + self.output = TaggedOutput().setbreaklines(True) + + def process(self): + self.output.tag = 'div class="' + self.header[1] + '"' + +class Newline(Container): + "A newline" + + def __init__(self): + self.parser = LoneCommand() + self.output = FixedOutput() + + def process(self): + "Process contents" + self.html = ['<br/>\n'] + +class NewPage(Newline): + "A new page" + + def process(self): + "Process contents" + self.html = ['<p><br/>\n</p>\n'] + +class Separator(Container): + "A separator string which is not extracted by extracttext()." + + def __init__(self, constant): + self.output = FixedOutput() + self.contents = [] + self.html = [constant] + +class StrikeOut(TaggedText): + "Striken out text." + + def process(self): + "Set the output tag to strike." + self.output.tag = 'strike' + +class StartAppendix(BlackBox): + "Mark to start an appendix here." + "From this point on, all chapters become appendices." + + def process(self): + "Activate the special numbering scheme for appendices, using letters." + NumberGenerator.generator.startappendix() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/table.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/table.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/table.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/table.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,191 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090207 +# eLyXer tables + +from elyxer.util.trace import Trace +from elyxer.gen.container import * +from elyxer.gen.layout import * +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.parse.tableparse import * +from elyxer.proc.postprocess import * + + +class Table(Container): + "A lyx table" + + def __init__(self): + self.parser = TableParser() + self.output = TaggedOutput().settag('table', True) + self.columns = [] + + def process(self): + "Set the columns on every row" + index = 0 + while index < len(self.contents): + element = self.contents[index] + if isinstance(element, Column): + self.columns.append(element) + del self.contents[index] + elif isinstance(element, BlackBox): + del self.contents[index] + elif isinstance(element, Row): + element.setcolumns(self.columns) + index += 1 + else: + Trace.error('Unknown element type ' + element.__class__.__name__ + + ' in table: ' + unicode(element.contents[0])) + index += 1 + +class Row(Container): + "A row in a table" + + def __init__(self): + self.parser = TablePartParser() + self.output = TaggedOutput().settag('tr', True) + self.columns = list() + + def setcolumns(self, columns): + "Process alignments for every column" + if len(columns) != len(self.contents): + Trace.error('Columns: ' + unicode(len(columns)) + ', cells: ' + unicode(len(self.contents))) + return + for index, cell in enumerate(self.contents): + columns[index].set(cell) + +class Column(Container): + "A column definition in a table" + + def __init__(self): + self.parser = ColumnParser() + self.output = EmptyOutput() + + def process(self): + "Read size parameters if present." + self.size = ContainerSize().readparameters(self) + + def set(self, cell): + "Set alignments in the corresponding cell" + alignment = self.getparameter('alignment') + if alignment == 'block': + alignment = 'justify' + cell.setattribute('align', alignment) + valignment = self.getparameter('valignment') + cell.setattribute('valign', valignment) + self.size.addstyle(cell) + +class Cell(Container): + "A cell in a table" + + def __init__(self): + self.parser = TablePartParser() + self.output = TaggedOutput().settag('td', True) + + def setmulticolumn(self, span): + "Set the cell as multicolumn" + self.setattribute('colspan', span) + + def setattribute(self, attribute, value): + "Set a cell attribute in the tag" + self.output.tag += ' ' + attribute + '="' + unicode(value) + '"' + +class PostTable(object): + "Postprocess a table" + + processedclass = Table + + def postprocess(self, last, table, next): + "Postprocess a table: long table, multicolumn rows" + self.longtable(table) + for row in table.contents: + index = 0 + while index < len(row.contents): + self.checkforplain(row, index) + self.checkmulticolumn(row, index) + index += 1 + return table + + def longtable(self, table): + "Postprocess a long table, removing unwanted rows" + features = table.getparameter('features') + if not features: + return + if not 'islongtable' in features: + return + if features['islongtable'] != 'true': + return + if self.hasrow(table, 'endfirsthead'): + self.removerows(table, 'endhead') + if self.hasrow(table, 'endlastfoot'): + self.removerows(table, 'endfoot') + + def hasrow(self, table, attrname): + "Find out if the table has a row of first heads" + for row in table.contents: + if row.getparameter(attrname): + return True + return False + + def removerows(self, table, attrname): + "Remove the head rows, since the table has first head rows." + for row in table.contents: + if row.getparameter(attrname): + row.output = EmptyOutput() + + def checkforplain(self, row, index): + "Make plain layouts visible if necessary." + cell = row.contents[index] + plainlayouts = cell.searchall(PlainLayout) + if len(plainlayouts) <= 1: + return + for plain in plainlayouts: + plain.makevisible() + + def checkmulticolumn(self, row, index): + "Process a multicolumn attribute" + cell = row.contents[index] + mc = cell.getparameter('multicolumn') + if not mc: + return + if mc != '1': + Trace.error('Unprocessed multicolumn=' + unicode(multicolumn) + + ' cell ' + unicode(cell)) + return + total = 1 + index += 1 + while self.checkbounds(row, index): + del row.contents[index] + total += 1 + cell.setmulticolumn(total) + + def checkbounds(self, row, index): + "Check if the index is within bounds for the row" + if index >= len(row.contents): + return False + mc = row.contents[index].getparameter('multicolumn') + if mc != '2': + return False + return True + +Postprocessor.stages.append(PostTable) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/toc.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/toc.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/gen/toc.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/gen/toc.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,199 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20091006 +# eLyXer TOC generation +# http://www.nongnu.org/elyxer/ + + +from elyxer.gen.header import * +from elyxer.ref.label import * +from elyxer.util.docparams import * + + +class TOCEntry(Container): + "A container for a TOC entry." + + def __init__(self): + Container.__init__(self) + self.branches = [] + + def create(self, container): + "Create the TOC entry for a container, consisting of a single link." + if container.partkey.header: + return self.header(container) + self.contents = [self.createlink(container)] + self.output = TaggedOutput().settag('div class="toc"', True) + self.partkey = container.partkey + return self + + def header(self, container): + "Create a TOC entry for header and footer (0 depth)." + self.partkey = container.partkey + self.output = EmptyOutput() + return self + + def createlink(self, container): + "Create the link that will make the whole TOC entry." + labels = container.searchall(Label) + link = Link() + if self.isanchor(labels): + link.url = '#' + container.partkey.partkey + if Options.tocfor: + link.url = Options.tocfor + link.url + else: + label = labels[0] + link.destination = label + if container.partkey.tocentry: + link.complete(container.partkey.tocentry) + if container.partkey.titlecontents: + if Options.notoclabels: + separator = u' ' + else: + separator = u': ' + if container.partkey.tocentry: + link.contents.append(Constant(separator)) + link.contents += container.partkey.titlecontents + return link + + def isanchor(self, labels): + "Decide if the link is an anchor based on a set of labels." + if len(labels) == 0: + return True + if not Options.tocfor: + return False + if Options.splitpart: + return False + return True + + def __unicode__(self): + "Return a printable representation." + if not self.partkey.tocentry: + return 'Unnamed TOC entry' + return 'TOC entry: ' + self.partkey.tocentry + +class Indenter(object): + "Manages and writes indentation for the TOC." + + def __init__(self): + self.depth = 0 + + def getindent(self, depth): + indent = '' + if depth > self.depth: + indent = self.openindent(depth - self.depth) + elif depth < self.depth: + indent = self.closeindent(self.depth - depth) + self.depth = depth + return Constant(indent) + + def openindent(self, times): + "Open the indenting div a few times." + indent = '' + for i in range(times): + indent += '<div class="tocindent">\n' + return indent + + def closeindent(self, times): + "Close the indenting div a few times." + indent = '' + for i in range(times): + indent += '</div>\n' + return indent + +class IndentedEntry(Container): + "An entry with an indentation." + + def __init__(self): + self.output = ContentsOutput() + + def create(self, indent, entry): + "Create the indented entry." + self.entry = entry + self.contents = [indent, entry] + return self + + def __unicode__(self): + "Return a printable documentation." + return 'Indented ' + unicode(self.entry) + +class TOCTree(object): + "A tree that contains the full TOC." + + def __init__(self): + self.tree = [] + self.branches = [] + + def store(self, entry): + "Place the entry in a tree of entries." + while len(self.tree) < entry.partkey.level: + self.tree.append(None) + if len(self.tree) > entry.partkey.level: + self.tree = self.tree[:entry.partkey.level] + stem = self.findstem() + if len(self.tree) == 0: + self.branches.append(entry) + self.tree.append(entry) + if stem: + entry.stem = stem + stem.branches.append(entry) + + def findstem(self): + "Find the stem where our next element will be inserted." + for element in reversed(self.tree): + if element: + return element + return None + +class TOCConverter(object): + "A converter from elyxer.containers to TOC entries." + + cache = dict() + tree = TOCTree() + + def __init__(self): + self.indenter = Indenter() + + def convertindented(self, container): + "Convert a container into an indented TOC entry." + entry = self.convert(container) + if not entry: + return None + return self.indent(entry) + + def indent(self, entry): + "Indent a TOC entry." + indent = self.indenter.getindent(entry.partkey.level) + return IndentedEntry().create(indent, entry) + + def convert(self, container): + "Convert a container to a TOC entry." + if not container.partkey: + return None + if container.partkey.partkey in self.cache: + return TOCConverter.cache[container.partkey.partkey] + if container.partkey.level > DocumentParameters.tocdepth: + return None + entry = TOCEntry().create(container) + TOCConverter.cache[container.partkey.partkey] = entry + TOCConverter.tree.store(entry) + return entry + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/io/bulk.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/io/bulk.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/io/bulk.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/io/bulk.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,74 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090416 +# Bulk file processing + +import os +import codecs +from elyxer.io.fileline import * +from elyxer.util.trace import Trace + + +class BulkFile(object): + "A file to treat in bulk" + + encodings = ['utf-8','Cp1252'] + + def __init__(self, filename): + self.filename = filename + self.temp = self.filename + '.temp' + + def readall(self): + "Read the whole file" + for encoding in BulkFile.encodings: + try: + return self.readcodec(encoding) + except UnicodeDecodeError: + pass + Trace.error('No suitable encoding for ' + self.filename) + return [] + + def readcodec(self, encoding): + "Read the whole file with the given encoding" + filein = codecs.open(self.filename, 'rU', encoding) + lines = filein.readlines() + result = [] + for line in lines: + result.append(line.strip('\r\n') + '\n') + filein.close() + return result + + def getfiles(self): + "Get reader and writer for a file name" + reader = LineReader(self.filename) + writer = LineWriter(self.temp) + return reader, writer + + def swaptemp(self): + "Swap the temp file for the original" + os.chmod(self.temp, os.stat(self.filename).st_mode) + os.rename(self.temp, self.filename) + + def __unicode__(self): + "Get the unicode representation" + return 'file ' + self.filename + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/io/fileline.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/io/fileline.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/io/fileline.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/io/fileline.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,132 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090308 +# File line management for eLyXer + +import sys +import codecs +from elyxer.util.trace import Trace + + +class LineReader(object): + "Reads a file line by line" + + def __init__(self, filename): + if isinstance(filename, file): + self.file = filename + else: + self.file = codecs.open(filename, 'rU', 'utf-8') + self.linenumber = 1 + self.lastline = None + self.current = None + self.mustread = True + self.depleted = False + try: + self.readline() + except UnicodeDecodeError: + # try compressed file + import gzip + self.file = gzip.open(filename, 'rb') + self.readline() + + def setstart(self, firstline): + "Set the first line to read." + for i in range(firstline): + self.file.readline() + self.linenumber = firstline + + def setend(self, lastline): + "Set the last line to read." + self.lastline = lastline + + def currentline(self): + "Get the current line" + if self.mustread: + self.readline() + return self.current + + def nextline(self): + "Go to next line" + if self.depleted: + Trace.fatal('Read beyond file end') + self.mustread = True + + def readline(self): + "Read a line from elyxer.file" + self.current = self.file.readline() + if not isinstance(self.file, codecs.StreamReaderWriter): + self.current = self.current.decode('utf-8') + if len(self.current) == 0: + self.depleted = True + self.current = self.current.rstrip('\n\r') + self.linenumber += 1 + self.mustread = False + Trace.prefix = 'Line ' + unicode(self.linenumber) + ': ' + if self.linenumber % 1000 == 0: + Trace.message('Parsing') + + def finished(self): + "Find out if the file is finished" + if self.lastline and self.linenumber == self.lastline: + return True + if self.mustread: + self.readline() + return self.depleted + + def close(self): + self.file.close() + +class LineWriter(object): + "Writes a file as a series of lists" + + file = False + + def __init__(self, filename): + if isinstance(filename, file): + self.file = filename + self.filename = None + else: + self.filename = filename + + def write(self, strings): + "Write a list of strings" + for string in strings: + if not isinstance(string, basestring): + Trace.error('Not a string: ' + unicode(string) + ' in ' + unicode(strings)) + return + self.writestring(string) + + def writestring(self, string): + "Write a string" + if not self.file: + self.file = codecs.open(self.filename, 'w', "utf-8") + if self.file == sys.stdout and sys.version_info < (3,0): + string = string.encode('utf-8') + self.file.write(string) + + def writeline(self, line): + "Write a line to file" + self.writestring(line + '\n') + + def close(self): + self.file.close() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/io/path.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/io/path.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/io/path.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/io/path.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,118 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090905 +# Path manipulations + +import os +import os.path +import codecs +from elyxer.util.options import Options +from elyxer.util.trace import Trace + + +class Path(object): + "Represents a generic path" + + def exists(self): + "Check if the file exists" + return os.path.exists(self.path) + + def open(self): + "Open the file as readonly binary" + return codecs.open(self.path, 'rb') + + def getmtime(self): + "Return last modification time" + return os.path.getmtime(self.path) + + def hasexts(self, exts): + "Check if the file has one of the given extensions." + for ext in exts: + if self.hasext(ext): + return True + return False + + def hasext(self, ext): + "Check if the file has the given extension" + return self.getext() == ext + + def getext(self): + "Get the current extension of the file." + base, ext = os.path.splitext(self.path) + return ext + + def __unicode__(self): + "Return a unicode string representation" + return self.path + + def __eq__(self, path): + "Compare to another path" + if not hasattr(path, 'path'): + return False + return self.path == path.path + +class InputPath(Path): + "Represents an input file" + + def __init__(self, url): + "Create the input path based on url" + self.url = url + self.path = url + if not os.path.isabs(url): + self.path = os.path.join(Options.directory, url) + +class OutputPath(Path): + "Represents an output file" + + def __init__(self, inputpath): + "Create the output path based on an input path" + self.url = inputpath.url + if os.path.isabs(self.url): + self.url = os.path.basename(self.url) + self.path = os.path.join(Options.destdirectory, self.url) + + def changeext(self, ext): + "Change extension to the given one" + base, oldext = os.path.splitext(self.path) + self.path = base + ext + base, oldext = os.path.splitext(self.url) + self.url = base + ext + + def exists(self): + "Check if the file exists" + return os.path.exists(self.path) + + def createdirs(self): + "Create any intermediate directories that don't exist" + dir = os.path.dirname(self.path) + if len(dir) > 0 and not os.path.exists(dir): + os.makedirs(dir) + + def removebackdirs(self): + "Remove any occurrences of ../ (or ..\ on Windows)" + self.path = os.path.normpath(self.path) + backdir = '..' + os.path.sep + while self.path.startswith(backdir): + self.path = self.path[len(backdir):] + while self.url.startswith('../'): + self.url = self.url[len('../'):] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/main/convert.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/main/convert.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/main/convert.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/main/convert.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,197 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090919 +# eLyXer converter +# http://www.nongnu.org/elyxer/ + + +import os.path +from elyxer.io.fileline import * +from elyxer.util.options import * +from elyxer.gen.factory import * +from elyxer.gen.toc import * +from elyxer.gen.inset import * +from elyxer.gen.basket import * +from elyxer.gen.integral import * +from elyxer.gen.splitpart import * +from elyxer.proc.process import * +from elyxer.maths.postformula import * + + +class eLyXerConverter(object): + "Converter for a document in a lyx file. Places all output in a given basket." + + def __init__(self): + self.filtering = False + + def setio(self, ioparser): + "Set the InOutParser" + self.reader = ioparser.getreader() + self.basket = self.getbasket() + self.basket.setwriter(ioparser.getwriter()) + return self + + def getbasket(self): + "Get the appropriate basket for the current options." + if Options.tocfor: + if Options.splitpart: + return SplitTOCBasket() + return TOCBasket() + if Options.splitpart: + return SplitPartBasket() + if Options.memory: + return MemoryBasket() + return WriterBasket() + + def embed(self, reader): + "Embed the results from elyxer.a reader into a memory basket." + "Header and footer are ignored. Useful for embedding one document inside another." + self.filtering = True + self.reader = reader + self.basket = MemoryBasket() + return self + + def convert(self): + "Perform the conversion for the document" + try: + self.processcontents() + except (Exception): + version = '[eLyXer version ' + GeneralConfig.version['number'] + version += ' (' + GeneralConfig.version['date'] + ') in ' + version += Options.location + '] ' + Trace.error(version) + Trace.error('Conversion failed at ' + self.reader.currentline()) + raise + + def processcontents(self): + "Parse the contents and write it by containers" + factory = ContainerFactory() + processor = Processor(self.filtering) + while not self.reader.finished(): + container = factory.createcontainer(self.reader) + result = processor.process(container) + self.writecontainer(result) + result = processor.postprocess(None) + self.writecontainer(result) + if not self.filtering: + self.basket.finish() + + def writecontainer(self, container): + "Write each container to the correct basket." + if not container: + return + includes = container.searchremove(IncludeInset) + self.basket.write(container) + # recursive processing for IncludeInset + for include in includes: + for element in include.contents: + self.basket.write(element) + + def getcontents(self): + "Return the contents of the basket." + return self.basket.contents + + def __unicode__(self): + "Printable representation." + string = 'Converter with filtering ' + unicode(self.filtering) + string += ' and basket ' + unicode(self.basket) + return string + +class InOutParser(object): + "Parse in and out arguments" + + def __init__(self): + self.filein = sys.stdin + self.fileout = sys.stdout + + def parse(self, args): + "Parse command line arguments" + self.filein = sys.stdin + self.fileout = sys.stdout + if len(args) < 2: + Trace.quietmode = True + if len(args) > 0: + self.filein = args[0] + del args[0] + self.readdir(self.filein, 'directory') + else: + Options.directory = '.' + if len(args) > 0: + self.fileout = args[0] + del args[0] + self.readdir(self.fileout, 'destdirectory') + else: + Options.destdirectory = '.' + if len(args) > 0: + raise Exception('Unused arguments: ' + unicode(args)) + return self + + def getreader(self): + "Get the resulting reader." + return LineReader(self.filein) + + def getwriter(self): + "Get the resulting writer." + return LineWriter(self.fileout) + + def readdir(self, filename, diroption): + "Read the current directory if needed" + if getattr(Options, diroption) != None: + return + setattr(Options, diroption, os.path.dirname(filename)) + if getattr(Options, diroption) == '': + setattr(Options, diroption, '.') + +class NullWriter(object): + "A writer that goes nowhere." + + def write(self, list): + "Do nothing." + pass + +class ConverterFactory(object): + "Create a converter fit for converting a filename and embedding the result." + + def create(self, container): + "Create a converter for a given container, with filename" + " and possibly other parameters." + fullname = os.path.join(Options.directory, container.filename) + reader = LineReader(container.filename) + if 'firstline' in container.lstparams: + reader.setstart(int(container.lstparams['firstline'])) + if 'lastline' in container.lstparams: + reader.setend(int(container.lstparams['lastline'])) + return eLyXerConverter().embed(reader) + +IncludeInset.converterfactory = ConverterFactory() + +def convertdoc(args): + "Read a whole document from the command line and write it." + Options().parseoptions(args) + ioparser = InOutParser().parse(args) + converter = eLyXerConverter().setio(ioparser) + converter.convert() + +def main(): + "Main function, called if invoked from the command line" + convertdoc(list(sys.argv)) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/array.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/array.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/array.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/array.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,225 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090427 +# eLyXer arrays in formulae + +from elyxer.gen.container import * +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.conf.config import * +from elyxer.maths.formula import * +from elyxer.maths.command import * +from elyxer.maths.symbol import * + + +class FormulaEquation(CommandBit): + "A simple numbered equation." + + piece = 'equation' + + def parsebit(self, pos): + "Parse the array" + self.output = ContentsOutput() + self.add(self.factory.parsetype(WholeFormula, pos)) + +class FormulaCell(FormulaCommand): + "An array cell inside a row" + + def setalignment(self, alignment): + self.alignment = alignment + self.output = TaggedOutput().settag('span class="arraycell align-' + alignment +'"', True) + return self + + def parsebit(self, pos): + self.factory.clearskipped(pos) + if pos.finished(): + return + self.add(self.factory.parsetype(WholeFormula, pos)) + +class FormulaRow(FormulaCommand): + "An array row inside an array" + + cellseparator = FormulaConfig.array['cellseparator'] + + def setalignments(self, alignments): + self.alignments = alignments + self.output = TaggedOutput().settag('span class="arrayrow"', True) + return self + + def parsebit(self, pos): + "Parse a whole row" + index = 0 + pos.pushending(self.cellseparator, optional=True) + while not pos.finished(): + cell = self.createcell(index) + cell.parsebit(pos) + self.add(cell) + index += 1 + pos.checkskip(self.cellseparator) + if len(self.contents) == 0: + self.output = EmptyOutput() + + def createcell(self, index): + "Create the cell that corresponds to the given index." + alignment = self.alignments[index % len(self.alignments)] + return self.factory.create(FormulaCell).setalignment(alignment) + +class MultiRowFormula(CommandBit): + "A formula with multiple rows." + + def parserows(self, pos): + "Parse all rows, finish when no more row ends" + self.rows = [] + first = True + for row in self.iteraterows(pos): + if first: + first = False + else: + # intersparse empty rows + self.addempty() + row.parsebit(pos) + self.addrow(row) + self.size = len(self.rows) + + def iteraterows(self, pos): + "Iterate over all rows, end when no more row ends" + rowseparator = FormulaConfig.array['rowseparator'] + while True: + pos.pushending(rowseparator, True) + row = self.factory.create(FormulaRow) + yield row.setalignments(self.alignments) + if pos.checkfor(rowseparator): + self.original += pos.popending(rowseparator) + else: + return + + def addempty(self): + "Add an empty row." + row = self.factory.create(FormulaRow).setalignments(self.alignments) + for index, originalcell in enumerate(self.rows[-1].contents): + cell = row.createcell(index) + cell.add(FormulaConstant(u' ')) + row.add(cell) + self.addrow(row) + + def addrow(self, row): + "Add a row to the contents and to the list of rows." + self.rows.append(row) + self.add(row) + +class FormulaArray(MultiRowFormula): + "An array within a formula" + + piece = 'array' + + def parsebit(self, pos): + "Parse the array" + self.output = TaggedOutput().settag('span class="array"', False) + self.parsealignments(pos) + self.parserows(pos) + + def parsealignments(self, pos): + "Parse the different alignments" + # vertical + self.valign = 'c' + literal = self.parsesquareliteral(pos) + if literal: + self.valign = literal + # horizontal + literal = self.parseliteral(pos) + self.alignments = [] + for l in literal: + self.alignments.append(l) + +class FormulaMatrix(MultiRowFormula): + "A matrix (array with center alignment)." + + piece = 'matrix' + + def parsebit(self, pos): + "Parse the matrix, set alignments to 'c'." + self.output = TaggedOutput().settag('span class="array"', False) + self.valign = 'c' + self.alignments = ['c'] + self.parserows(pos) + +class FormulaCases(MultiRowFormula): + "A cases statement" + + piece = 'cases' + + def parsebit(self, pos): + "Parse the cases" + self.output = ContentsOutput() + self.alignments = ['l', 'l'] + self.parserows(pos) + for row in self.contents: + for cell in row.contents: + cell.output.settag('span class="case align-l"', True) + cell.contents.append(FormulaConstant(u' ')) + array = TaggedBit().complete(self.contents, 'span class="bracketcases"', True) + brace = BigBracket(len(self.contents), '{', 'l') + self.contents = brace.getcontents() + [array] + +class EquationEnvironment(MultiRowFormula): + "A \\begin{}...\\end equation environment with rows and cells." + + def parsebit(self, pos): + "Parse the whole environment." + self.output = TaggedOutput().settag('span class="environment"', False) + environment = self.piece.replace('*', '') + if environment in FormulaConfig.environments: + self.alignments = FormulaConfig.environments[environment] + else: + Trace.error('Unknown equation environment ' + self.piece) + self.alignments = ['l'] + self.parserows(pos) + +class BeginCommand(CommandBit): + "A \\begin{}...\end command and what it entails (array, cases, aligned)" + + commandmap = {FormulaConfig.array['begin']:''} + + types = [FormulaEquation, FormulaArray, FormulaCases, FormulaMatrix] + + def parsebit(self, pos): + "Parse the begin command" + command = self.parseliteral(pos) + bit = self.findbit(command) + ending = FormulaConfig.array['end'] + '{' + command + '}' + pos.pushending(ending) + bit.parsebit(pos) + self.add(bit) + self.original += pos.popending(ending) + self.size = bit.size + + def findbit(self, piece): + "Find the command bit corresponding to the \\begin{piece}" + for type in BeginCommand.types: + if piece.replace('*', '') == type.piece: + return self.factory.create(type) + bit = self.factory.create(EquationEnvironment) + bit.piece = piece + return bit + +FormulaCommand.types += [BeginCommand] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/bits.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/bits.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/bits.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/bits.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,280 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090614 +# eLyXer formula bits + +from elyxer.util.trace import Trace +from elyxer.conf.config import * +from elyxer.maths.formula import * + + +class FormulaBit(Container): + "A bit of a formula" + + type = None + size = 1 + original = '' + + def __init__(self): + "The formula bit type can be 'alpha', 'number', 'font'." + self.contents = [] + self.output = ContentsOutput() + + def setfactory(self, factory): + "Set the internal formula factory." + self.factory = factory + return self + + def add(self, bit): + "Add any kind of formula bit already processed" + self.contents.append(bit) + self.original += bit.original + bit.parent = self + + def skiporiginal(self, string, pos): + "Skip a string and add it to the original formula" + self.original += string + if not pos.checkskip(string): + Trace.error('String ' + string + ' not at ' + pos.identifier()) + + def computesize(self): + "Compute the size of the bit as the max of the sizes of all contents." + if len(self.contents) == 0: + return 1 + self.size = max([element.size for element in self.contents]) + return self.size + + def clone(self): + "Return a copy of itself." + return self.factory.parseformula(self.original) + + def __unicode__(self): + "Get a string representation" + return self.__class__.__name__ + ' read in ' + self.original + +class TaggedBit(FormulaBit): + "A tagged string in a formula" + + def constant(self, constant, tag): + "Set the constant and the tag" + self.output = TaggedOutput().settag(tag) + self.add(FormulaConstant(constant)) + return self + + def complete(self, contents, tag, breaklines = False): + "Set the constant and the tag" + self.contents = contents + self.output = TaggedOutput().settag(tag, breaklines) + return self + + def selfcomplete(self, tag): + "Set the self-closing tag, no contents (as in <hr/>)." + self.output = TaggedOutput().settag(tag, empty = True) + return self + +class FormulaConstant(Constant): + "A constant string in a formula" + + def __init__(self, string): + "Set the constant string" + Constant.__init__(self, string) + self.original = string + self.size = 1 + self.type = None + + def computesize(self): + "Compute the size of the constant: always 1." + return self.size + + def clone(self): + "Return a copy of itself." + return FormulaConstant(self.original) + + def __unicode__(self): + "Return a printable representation." + return 'Formula constant: ' + self.string + +class RawText(FormulaBit): + "A bit of text inside a formula" + + def detect(self, pos): + "Detect a bit of raw text" + return pos.current().isalpha() + + def parsebit(self, pos): + "Parse alphabetic text" + alpha = pos.globalpha() + self.add(FormulaConstant(alpha)) + self.type = 'alpha' + +class FormulaSymbol(FormulaBit): + "A symbol inside a formula" + + modified = FormulaConfig.modified + unmodified = FormulaConfig.unmodified['characters'] + + def detect(self, pos): + "Detect a symbol" + if pos.current() in FormulaSymbol.unmodified: + return True + if pos.current() in FormulaSymbol.modified: + return True + return False + + def parsebit(self, pos): + "Parse the symbol" + if pos.current() in FormulaSymbol.unmodified: + self.addsymbol(pos.current(), pos) + return + if pos.current() in FormulaSymbol.modified: + self.addsymbol(FormulaSymbol.modified[pos.current()], pos) + return + Trace.error('Symbol ' + pos.current() + ' not found') + + def addsymbol(self, symbol, pos): + "Add a symbol" + self.skiporiginal(pos.current(), pos) + self.contents.append(FormulaConstant(symbol)) + +class FormulaNumber(FormulaBit): + "A string of digits in a formula" + + def detect(self, pos): + "Detect a digit" + return pos.current().isdigit() + + def parsebit(self, pos): + "Parse a bunch of digits" + digits = pos.glob(lambda: pos.current().isdigit()) + self.add(FormulaConstant(digits)) + self.type = 'number' + +class Comment(FormulaBit): + "A LaTeX comment: % to the end of the line." + + start = FormulaConfig.starts['comment'] + + def detect(self, pos): + "Detect the %." + return pos.current() == self.start + + def parsebit(self, pos): + "Parse to the end of the line." + self.original += pos.globincluding('\n') + +class WhiteSpace(FormulaBit): + "Some white space inside a formula." + + def detect(self, pos): + "Detect the white space." + return pos.current().isspace() + + def parsebit(self, pos): + "Parse all whitespace." + self.original += pos.skipspace() + + def __unicode__(self): + "Return a printable representation." + return 'Whitespace: *' + self.original + '*' + +class Bracket(FormulaBit): + "A {} bracket inside a formula" + + start = FormulaConfig.starts['bracket'] + ending = FormulaConfig.endings['bracket'] + + def __init__(self): + "Create a (possibly literal) new bracket" + FormulaBit.__init__(self) + self.inner = None + + def detect(self, pos): + "Detect the start of a bracket" + return pos.checkfor(self.start) + + def parsebit(self, pos): + "Parse the bracket" + self.parsecomplete(pos, self.innerformula) + return self + + def parsetext(self, pos): + "Parse a text bracket" + self.parsecomplete(pos, self.innertext) + return self + + def parseliteral(self, pos): + "Parse a literal bracket" + self.parsecomplete(pos, self.innerliteral) + return self + + def parsecomplete(self, pos, innerparser): + "Parse the start and end marks" + if not pos.checkfor(self.start): + Trace.error('Bracket should start with ' + self.start + ' at ' + pos.identifier()) + return None + self.skiporiginal(self.start, pos) + pos.pushending(self.ending) + innerparser(pos) + self.original += pos.popending(self.ending) + self.computesize() + + def innerformula(self, pos): + "Parse a whole formula inside the bracket" + while not pos.finished(): + self.add(self.factory.parseany(pos)) + + def innertext(self, pos): + "Parse some text inside the bracket, following textual rules." + specialchars = FormulaConfig.symbolfunctions.keys() + specialchars.append(FormulaConfig.starts['command']) + specialchars.append(FormulaConfig.starts['bracket']) + specialchars.append(Comment.start) + while not pos.finished(): + if pos.current() in specialchars: + self.add(self.factory.parseany(pos)) + if pos.checkskip(' '): + self.original += ' ' + else: + self.add(FormulaConstant(pos.skipcurrent())) + + def innerliteral(self, pos): + "Parse a literal inside the bracket, which does not generate HTML." + self.literal = '' + while not pos.finished() and not pos.current() == self.ending: + if pos.current() == self.start: + self.parseliteral(pos) + else: + self.literal += pos.skipcurrent() + self.original += self.literal + +class SquareBracket(Bracket): + "A [] bracket inside a formula" + + start = FormulaConfig.starts['squarebracket'] + ending = FormulaConfig.endings['squarebracket'] + + def clone(self): + "Return a new square bracket with the same contents." + bracket = SquareBracket() + bracket.contents = self.contents + return bracket + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/command.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/command.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/command.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/command.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,288 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090330 +# eLyXer commands in formula processing + +import unicodedata +from elyxer.gen.container import * +from elyxer.ref.label import * +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.conf.config import * +from elyxer.maths.formula import * +from elyxer.maths.bits import * + + +class FormulaCommand(FormulaBit): + "A LaTeX command inside a formula" + + types = [] + start = FormulaConfig.starts['command'] + commandmap = None + + def detect(self, pos): + "Find the current command." + return pos.checkfor(FormulaCommand.start) + + def parsebit(self, pos): + "Parse the command." + command = self.extractcommand(pos) + bit = self.parsewithcommand(command, pos) + if bit: + return bit + if command.startswith('\\up') or command.startswith('\\Up'): + upgreek = self.parseupgreek(command, pos) + if upgreek: + return upgreek + if not self.factory.defining: + Trace.error('Unknown command ' + command) + self.output = TaggedOutput().settag('span class="unknown"') + self.add(FormulaConstant(command)) + return None + + def parsewithcommand(self, command, pos): + "Parse the command type once we have the command." + for type in FormulaCommand.types: + if command in type.commandmap: + return self.parsecommandtype(command, type, pos) + return None + + def parsecommandtype(self, command, type, pos): + "Parse a given command type." + bit = self.factory.create(type) + bit.setcommand(command) + returned = bit.parsebit(pos) + if returned: + return returned + return bit + + def extractcommand(self, pos): + "Extract the command from elyxer.the current position." + if not pos.checkskip(FormulaCommand.start): + pos.error('Missing command start ' + FormulaCommand.start) + return + if pos.finished(): + return self.emptycommand(pos) + if pos.current().isalpha(): + # alpha command + command = FormulaCommand.start + pos.globalpha() + # skip mark of short command + pos.checkskip('*') + return command + # symbol command + return FormulaCommand.start + pos.skipcurrent() + + def emptycommand(self, pos): + """Check for an empty command: look for command disguised as ending. + Special case against '{ \{ \} }' situation.""" + command = '' + if not pos.isout(): + ending = pos.nextending() + if ending and pos.checkskip(ending): + command = ending + return FormulaCommand.start + command + + def parseupgreek(self, command, pos): + "Parse the Greek \\up command.." + if len(command) < 4: + return None + if command.startswith('\\up'): + upcommand = '\\' + command[3:] + elif pos.checkskip('\\Up'): + upcommand = '\\' + command[3:4].upper() + command[4:] + else: + Trace.error('Impossible upgreek command: ' + command) + return + upgreek = self.parsewithcommand(upcommand, pos) + if upgreek: + upgreek.type = 'font' + return upgreek + +class CommandBit(FormulaCommand): + "A formula bit that includes a command" + + def setcommand(self, command): + "Set the command in the bit" + self.command = command + if self.commandmap: + self.original += command + self.translated = self.commandmap[self.command] + + def parseparameter(self, pos): + "Parse a parameter at the current position" + self.factory.clearskipped(pos) + if pos.finished(): + return None + parameter = self.factory.parseany(pos) + self.add(parameter) + return parameter + + def parsesquare(self, pos): + "Parse a square bracket" + self.factory.clearskipped(pos) + if not self.factory.detecttype(SquareBracket, pos): + return None + bracket = self.factory.parsetype(SquareBracket, pos) + self.add(bracket) + return bracket + + def parseliteral(self, pos): + "Parse a literal bracket." + self.factory.clearskipped(pos) + if not self.factory.detecttype(Bracket, pos): + if not pos.isvalue(): + Trace.error('No literal parameter found at: ' + pos.identifier()) + return None + return pos.globvalue() + bracket = Bracket().setfactory(self.factory) + self.add(bracket.parseliteral(pos)) + return bracket.literal + + def parsesquareliteral(self, pos): + "Parse a square bracket literally." + self.factory.clearskipped(pos) + if not self.factory.detecttype(SquareBracket, pos): + return None + bracket = SquareBracket().setfactory(self.factory) + self.add(bracket.parseliteral(pos)) + return bracket.literal + + def parsetext(self, pos): + "Parse a text parameter." + self.factory.clearskipped(pos) + if not self.factory.detecttype(Bracket, pos): + Trace.error('No text parameter for ' + self.command) + return None + bracket = Bracket().setfactory(self.factory).parsetext(pos) + self.add(bracket) + return bracket + +class EmptyCommand(CommandBit): + "An empty command (without parameters)" + + commandmap = FormulaConfig.commands + + def parsebit(self, pos): + "Parse a command without parameters" + self.contents = [FormulaConstant(self.translated)] + +class SpacedCommand(CommandBit): + "An empty command which should have math spacing in formulas." + + commandmap = FormulaConfig.spacedcommands + + def parsebit(self, pos): + "Place as contents the command translated and spaced." + self.contents = [FormulaConstant(u' ' + self.translated + u' ')] + +class AlphaCommand(EmptyCommand): + "A command without paramters whose result is alphabetical" + + commandmap = FormulaConfig.alphacommands + + def parsebit(self, pos): + "Parse the command and set type to alpha" + EmptyCommand.parsebit(self, pos) + self.type = 'alpha' + +class OneParamFunction(CommandBit): + "A function of one parameter" + + commandmap = FormulaConfig.onefunctions + simplified = False + + def parsebit(self, pos): + "Parse a function with one parameter" + self.output = TaggedOutput().settag(self.translated) + self.parseparameter(pos) + self.simplifyifpossible() + + def simplifyifpossible(self): + "Try to simplify to a single character." + if self.original in self.commandmap: + self.output = FixedOutput() + self.html = [self.commandmap[self.original]] + self.simplified = True + +class SymbolFunction(CommandBit): + "Find a function which is represented by a symbol (like _ or ^)" + + commandmap = FormulaConfig.symbolfunctions + + def detect(self, pos): + "Find the symbol" + return pos.current() in SymbolFunction.commandmap + + def parsebit(self, pos): + "Parse the symbol" + self.setcommand(pos.current()) + pos.skip(self.command) + self.output = TaggedOutput().settag(self.translated) + self.parseparameter(pos) + +class TextFunction(CommandBit): + "A function where parameters are read as text." + + commandmap = FormulaConfig.textfunctions + + def parsebit(self, pos): + "Parse a text parameter" + self.output = TaggedOutput().settag(self.translated) + self.parsetext(pos) + + def process(self): + "Set the type to font" + self.type = 'font' + +class LabelFunction(CommandBit): + "A function that acts as a label" + + commandmap = FormulaConfig.labelfunctions + + def parsebit(self, pos): + "Parse a literal parameter" + self.key = self.parseliteral(pos) + + def process(self): + "Add an anchor with the label contents." + self.type = 'font' + self.label = Label().create(' ', self.key, type = 'eqnumber') + self.contents = [self.label] + # store as a Label so we know it's been seen + Label.names[self.key] = self.label + +class FontFunction(OneParamFunction): + "A function of one parameter that changes the font" + + commandmap = FormulaConfig.fontfunctions + + def process(self): + "Simplify if possible using a single character." + self.type = 'font' + self.simplifyifpossible() + +FormulaFactory.types += [FormulaCommand, SymbolFunction] +FormulaCommand.types = [ + AlphaCommand, EmptyCommand, OneParamFunction, FontFunction, LabelFunction, + TextFunction, SpacedCommand, + ] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/extracommand.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/extracommand.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/extracommand.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/extracommand.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,268 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20101218 +# eLyXer extra commands for unusual things. + +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.conf.config import * +from elyxer.maths.command import * +from elyxer.maths.symbol import * +from elyxer.maths.array import * + +import datetime + + +class CombiningFunction(OneParamFunction): + + commandmap = FormulaConfig.combiningfunctions + + def parsebit(self, pos): + "Parse a combining function." + self.type = 'alpha' + combining = self.translated + parameter = self.parsesingleparameter(pos) + if not parameter: + Trace.error('Empty parameter for combining function ' + self.command) + elif len(parameter.extracttext()) != 1: + Trace.error('Applying combining function ' + self.command + ' to invalid string "' + parameter.extracttext() + '"') + self.contents.append(Constant(combining)) + + def parsesingleparameter(self, pos): + "Parse a parameter, or a single letter." + self.factory.clearskipped(pos) + if pos.finished(): + Trace.error('Error while parsing single parameter at ' + pos.identifier()) + return None + if self.factory.detecttype(Bracket, pos) \ + or self.factory.detecttype(FormulaCommand, pos): + return self.parseparameter(pos) + letter = FormulaConstant(pos.skipcurrent()) + self.add(letter) + return letter + +class DecoratingFunction(OneParamFunction): + "A function that decorates some bit of text" + + commandmap = FormulaConfig.decoratingfunctions + + def parsebit(self, pos): + "Parse a decorating function" + self.type = 'alpha' + symbol = self.translated + self.symbol = TaggedBit().constant(symbol, 'span class="symbolover"') + self.parameter = self.parseparameter(pos) + self.output = TaggedOutput().settag('span class="withsymbol"') + self.contents.insert(0, self.symbol) + self.parameter.output = TaggedOutput().settag('span class="undersymbol"') + self.simplifyifpossible() + +class LimitCommand(EmptyCommand): + "A command which accepts limits above and below, in display mode." + + commandmap = FormulaConfig.limitcommands + + def parsebit(self, pos): + "Parse a limit command." + pieces = BigSymbol(self.translated).getpieces() + self.output = TaggedOutput().settag('span class="limits"') + for piece in pieces: + self.contents.append(TaggedBit().constant(piece, 'span class="limit"')) + +class LimitPreviousCommand(LimitCommand): + "A command to limit the previous command." + + commandmap = None + + def parsebit(self, pos): + "Do nothing." + self.output = TaggedOutput().settag('span class="limits"') + self.factory.clearskipped(pos) + + def __unicode__(self): + "Return a printable representation." + return 'Limit previous command' + +class LimitsProcessor(MathsProcessor): + "A processor for limits inside an element." + + def process(self, contents, index): + "Process the limits for an element." + if Options.simplemath: + return + if self.checklimits(contents, index): + self.modifylimits(contents, index) + if self.checkscript(contents, index) and self.checkscript(contents, index + 1): + self.modifyscripts(contents, index) + + def checklimits(self, contents, index): + "Check if the current position has a limits command." + if not DocumentParameters.displaymode: + return False + if self.checkcommand(contents, index + 1, LimitPreviousCommand): + self.limitsahead(contents, index) + return False + if not isinstance(contents[index], LimitCommand): + return False + return self.checkscript(contents, index + 1) + + def limitsahead(self, contents, index): + "Limit the current element based on the next." + contents[index + 1].add(contents[index].clone()) + contents[index].output = EmptyOutput() + + def modifylimits(self, contents, index): + "Modify a limits commands so that the limits appear above and below." + limited = contents[index] + subscript = self.getlimit(contents, index + 1) + limited.contents.append(subscript) + if self.checkscript(contents, index + 1): + superscript = self.getlimit(contents, index + 1) + else: + superscript = TaggedBit().constant(u' ', 'sup class="limit"') + limited.contents.insert(0, superscript) + + def getlimit(self, contents, index): + "Get the limit for a limits command." + limit = self.getscript(contents, index) + limit.output.tag = limit.output.tag.replace('script', 'limit') + return limit + + def modifyscripts(self, contents, index): + "Modify the super- and subscript to appear vertically aligned." + subscript = self.getscript(contents, index) + # subscript removed so instead of index + 1 we get index again + superscript = self.getscript(contents, index) + scripts = TaggedBit().complete([superscript, subscript], 'span class="scripts"') + contents.insert(index, scripts) + + def checkscript(self, contents, index): + "Check if the current element is a sub- or superscript." + return self.checkcommand(contents, index, SymbolFunction) + + def checkcommand(self, contents, index, type): + "Check for the given type as the current element." + if len(contents) <= index: + return False + return isinstance(contents[index], type) + + def getscript(self, contents, index): + "Get the sub- or superscript." + bit = contents[index] + bit.output.tag += ' class="script"' + del contents[index] + return bit + +class BracketCommand(OneParamFunction): + "A command which defines a bracket." + + commandmap = FormulaConfig.bracketcommands + + def parsebit(self, pos): + "Parse the bracket." + OneParamFunction.parsebit(self, pos) + + def create(self, direction, character): + "Create the bracket for the given character." + self.original = character + self.command = '\\' + direction + self.contents = [FormulaConstant(character)] + return self + +class BracketProcessor(MathsProcessor): + "A processor for bracket commands." + + def process(self, contents, index): + "Convert the bracket using Unicode pieces, if possible." + if Options.simplemath: + return + if self.checkleft(contents, index): + return self.processleft(contents, index) + + def processleft(self, contents, index): + "Process a left bracket." + rightindex = self.findright(contents, index + 1) + if not rightindex: + return + size = self.findmax(contents, index, rightindex) + self.resize(contents[index], size) + self.resize(contents[rightindex], size) + + def checkleft(self, contents, index): + "Check if the command at the given index is left." + return self.checkdirection(contents[index], '\\left') + + def checkright(self, contents, index): + "Check if the command at the given index is right." + return self.checkdirection(contents[index], '\\right') + + def checkdirection(self, bit, command): + "Check if the given bit is the desired bracket command." + if not isinstance(bit, BracketCommand): + return False + return bit.command == command + + def findright(self, contents, index): + "Find the right bracket starting at the given index, or 0." + depth = 1 + while index < len(contents): + if self.checkleft(contents, index): + depth += 1 + if self.checkright(contents, index): + depth -= 1 + if depth == 0: + return index + index += 1 + return None + + def findmax(self, contents, leftindex, rightindex): + "Find the max size of the contents between the two given indices." + sliced = contents[leftindex:rightindex] + return max([element.size for element in sliced]) + + def resize(self, command, size): + "Resize a bracket command to the given size." + character = command.extracttext() + alignment = command.command.replace('\\', '') + bracket = BigBracket(size, character, alignment) + command.output = ContentsOutput() + command.contents = bracket.getcontents() + +class TodayCommand(EmptyCommand): + "Shows today's date." + + commandmap = None + + def parsebit(self, pos): + "Parse a command without parameters" + self.output = FixedOutput() + self.html = [datetime.date.today().strftime('%b %d, %Y')] + + +FormulaCommand.types += [ + DecoratingFunction, CombiningFunction, LimitCommand, BracketCommand, + ] + +FormulaProcessor.processors += [ + LimitsProcessor(), BracketProcessor(), + ] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/formula.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/formula.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/formula.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/formula.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,225 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090207 +# eLyXer formula processing + +import urllib +from elyxer.gen.container import * +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.util.docparams import * +from elyxer.conf.config import * +from elyxer.parse.formulaparse import * +from elyxer.proc.formulaproc import * + + +class Formula(Container): + "A LaTeX formula" + + def __init__(self): + self.parser = FormulaParser() + self.output = TaggedOutput().settag('span class="formula"') + + def process(self): + "Convert the formula to tags" + if self.header[0] == 'inline': + DocumentParameters.displaymode = False + else: + DocumentParameters.displaymode = True + self.output.settag('div class="formula"', True) + if Options.jsmath: + self.jsmath() + elif Options.mathjax: + self.mathjax() + elif Options.googlecharts: + self.googlecharts() + else: + self.classic() + + def jsmath(self): + "Make the contents for jsMath." + if self.header[0] != 'inline': + self.output = TaggedOutput().settag('div class="math"') + else: + self.output = TaggedOutput().settag('span class="math"') + self.contents = [Constant(self.parsed)] + + def mathjax(self): + "Make the contents for MathJax." + self.output.tag = 'span class="MathJax_Preview"' + tag = 'script type="math/tex' + if self.header[0] != 'inline': + tag += ';mode=display' + self.contents = [TaggedText().constant(self.parsed, tag + '"', True)] + + def googlecharts(self): + "Make the contents using Google Charts http://code.google.com/apis/chart/." + url = FormulaConfig.urls['googlecharts'] + urllib.quote_plus(self.parsed) + img = '<img class="chart" src="' + url + '" alt="' + self.parsed + '"/>' + self.contents = [Constant(img)] + + def classic(self): + "Make the contents using classic output generation with XHTML and CSS." + whole = FormulaFactory().parseformula(self.parsed) + FormulaProcessor().process(whole) + whole.parent = self + self.contents = [whole] + + def parse(self, pos): + "Parse using a parse position instead of self.parser." + if pos.checkskip('$$'): + self.parsedollarblock(pos) + elif pos.checkskip('$'): + self.parsedollarinline(pos) + elif pos.checkskip('\\('): + self.parseinlineto(pos, '\\)') + elif pos.checkskip('\\['): + self.parseblockto(pos, '\\]') + else: + pos.error('Unparseable formula') + self.process() + return self + + def parsedollarinline(self, pos): + "Parse a $...$ formula." + self.header = ['inline'] + self.parsedollar(pos) + + def parsedollarblock(self, pos): + "Parse a $$...$$ formula." + self.header = ['block'] + self.parsedollar(pos) + if not pos.checkskip('$'): + pos.error('Formula should be $$...$$, but last $ is missing.') + + def parsedollar(self, pos): + "Parse to the next $." + pos.pushending('$') + self.parsed = pos.globexcluding('$') + pos.popending('$') + + def parseinlineto(self, pos, limit): + "Parse a \\(...\\) formula." + self.header = ['inline'] + self.parseupto(pos, limit) + + def parseblockto(self, pos, limit): + "Parse a \\[...\\] formula." + self.header = ['block'] + self.parseupto(pos, limit) + + def parseupto(self, pos, limit): + "Parse a formula that ends with the given command." + pos.pushending(limit) + self.parsed = pos.glob(lambda: True) + pos.popending(limit) + + def __unicode__(self): + "Return a printable representation." + if self.partkey and self.partkey.number: + return 'Formula (' + self.partkey.number + ')' + return 'Unnumbered formula' + +class WholeFormula(FormulaBit): + "Parse a whole formula" + + def detect(self, pos): + "Not outside the formula is enough." + return not pos.finished() + + def parsebit(self, pos): + "Parse with any formula bit" + while not pos.finished(): + self.add(self.factory.parseany(pos)) + +class FormulaFactory(object): + "Construct bits of formula" + + # bit types will be appended later + types = [FormulaSymbol, RawText, FormulaNumber, Bracket, Comment, WhiteSpace] + skippedtypes = [Comment, WhiteSpace] + defining = False + + def __init__(self): + "Initialize the map of instances." + self.instances = dict() + + def detecttype(self, type, pos): + "Detect a bit of a given type." + if pos.finished(): + return False + return self.instance(type).detect(pos) + + def instance(self, type): + "Get an instance of the given type." + if not type in self.instances or not self.instances[type]: + self.instances[type] = self.create(type) + return self.instances[type] + + def create(self, type): + "Create a new formula bit of the given type." + return Cloner.create(type).setfactory(self) + + def clearskipped(self, pos): + "Clear any skipped types." + while not pos.finished(): + if not self.skipany(pos): + return + return + + def skipany(self, pos): + "Skip any skipped types." + for type in self.skippedtypes: + if self.instance(type).detect(pos): + return self.parsetype(type, pos) + return None + + def parseany(self, pos): + "Parse any formula bit at the current location." + for type in self.types + self.skippedtypes: + if self.detecttype(type, pos): + return self.parsetype(type, pos) + Trace.error('Unrecognized formula at ' + pos.identifier()) + return FormulaConstant(pos.skipcurrent()) + + def parsetype(self, type, pos): + "Parse the given type and return it." + bit = self.instance(type) + self.instances[type] = None + returnedbit = bit.parsebit(pos) + if returnedbit: + return returnedbit.setfactory(self) + return bit + + def parseformula(self, formula): + "Parse a string of text that contains a whole formula." + pos = TextPosition(formula) + whole = self.create(WholeFormula) + if whole.detect(pos): + whole.parsebit(pos) + return whole + # no formula found + if not pos.finished(): + Trace.error('Unknown formula at: ' + pos.identifier()) + whole.add(TaggedBit().constant(formula, 'span class="unknown"')) + return whole + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/hybrid.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/hybrid.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/hybrid.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/hybrid.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,266 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20091214 +# eLyXer functions with a variable number of parameters. + +from elyxer.util.trace import Trace +from elyxer.conf.config import * +from elyxer.maths.command import * +from elyxer.maths.extracommand import * + + +class ParameterDefinition(object): + "The definition of a parameter in a hybrid function." + "[] parameters are optional, {} parameters are mandatory." + "Each parameter has a one-character name, like {$1} or {$p}." + "A parameter that ends in ! like {$p!} is a literal." + "Example: [$1]{$p!} reads an optional parameter $1 and a literal mandatory parameter p." + + parambrackets = [('[', ']'), ('{', '}')] + + def __init__(self): + self.name = None + self.literal = False + self.optional = False + self.value = None + self.literalvalue = None + + def parse(self, pos): + "Parse a parameter definition: [$0], {$x}, {$1!}..." + for (opening, closing) in ParameterDefinition.parambrackets: + if pos.checkskip(opening): + if opening == '[': + self.optional = True + if not pos.checkskip('$'): + Trace.error('Wrong parameter name, did you mean $' + pos.current() + '?') + return None + self.name = pos.skipcurrent() + if pos.checkskip('!'): + self.literal = True + if not pos.checkskip(closing): + Trace.error('Wrong parameter closing ' + pos.skipcurrent()) + return None + return self + Trace.error('Wrong character in parameter template: ' + pos.skipcurrent()) + return None + + def read(self, pos, function): + "Read the parameter itself using the definition." + if self.literal: + if self.optional: + self.literalvalue = function.parsesquareliteral(pos) + else: + self.literalvalue = function.parseliteral(pos) + if self.literalvalue: + self.value = FormulaConstant(self.literalvalue) + elif self.optional: + self.value = function.parsesquare(pos) + else: + self.value = function.parseparameter(pos) + + def __unicode__(self): + "Return a printable representation." + result = 'param ' + self.name + if self.value: + result += ': ' + unicode(self.value) + else: + result += ' (empty)' + return result + +class ParameterFunction(CommandBit): + "A function with a variable number of parameters defined in a template." + "The parameters are defined as a parameter definition." + + def readparams(self, readtemplate, pos): + "Read the params according to the template." + self.params = dict() + for paramdef in self.paramdefs(readtemplate): + paramdef.read(pos, self) + self.params['$' + paramdef.name] = paramdef + + def paramdefs(self, readtemplate): + "Read each param definition in the template" + pos = TextPosition(readtemplate) + while not pos.finished(): + paramdef = ParameterDefinition().parse(pos) + if paramdef: + yield paramdef + + def getparam(self, name): + "Get a parameter as parsed." + if not name in self.params: + return None + return self.params[name] + + def getvalue(self, name): + "Get the value of a parameter." + return self.getparam(name).value + + def getliteralvalue(self, name): + "Get the literal value of a parameter." + param = self.getparam(name) + if not param or not param.literalvalue: + return None + return param.literalvalue + +class HybridFunction(ParameterFunction): + """ + A parameter function where the output is also defined using a template. + The template can use a number of functions; each function has an associated + tag. + Example: [f0{$1},span class="fbox"] defines a function f0 which corresponds + to a span of class fbox, yielding <span class="fbox">$1</span>. + Literal parameters can be used in tags definitions: + [f0{$1},span style="color: $p;"] + yields <span style="color: $p;">$1</span>, where $p is a literal parameter. + Sizes can be specified in hybridsizes, e.g. adding parameter sizes. By + default the resulting size is the max of all arguments. Sizes are used + to generate the right parameters. + A function followed by a single / is output as a self-closing XHTML tag: + [f0/,hr] + will generate <hr/>. + """ + + commandmap = FormulaConfig.hybridfunctions + + def parsebit(self, pos): + "Parse a function with [] and {} parameters" + readtemplate = self.translated[0] + writetemplate = self.translated[1] + self.readparams(readtemplate, pos) + self.contents = self.writeparams(writetemplate) + self.computehybridsize() + + def writeparams(self, writetemplate): + "Write all params according to the template" + return self.writepos(TextPosition(writetemplate)) + + def writepos(self, pos): + "Write all params as read in the parse position." + result = [] + while not pos.finished(): + if pos.checkskip('$'): + param = self.writeparam(pos) + if param: + result.append(param) + elif pos.checkskip('f'): + function = self.writefunction(pos) + if function: + function.type = None + result.append(function) + elif pos.checkskip('('): + result.append(self.writebracket('left', '(')) + elif pos.checkskip(')'): + result.append(self.writebracket('right', ')')) + else: + result.append(FormulaConstant(pos.skipcurrent())) + return result + + def writeparam(self, pos): + "Write a single param of the form $0, $x..." + name = '$' + pos.skipcurrent() + if not name in self.params: + Trace.error('Unknown parameter ' + name) + return None + if not self.params[name]: + return None + if pos.checkskip('.'): + self.params[name].value.type = pos.globalpha() + return self.params[name].value + + def writefunction(self, pos): + "Write a single function f0,...,fn." + tag = self.readtag(pos) + if not tag: + return None + if pos.checkskip('/'): + # self-closing XHTML tag, such as <hr/> + return TaggedBit().selfcomplete(tag) + if not pos.checkskip('{'): + Trace.error('Function should be defined in {}') + return None + pos.pushending('}') + contents = self.writepos(pos) + pos.popending() + if len(contents) == 0: + return None + return TaggedBit().complete(contents, tag) + + def readtag(self, pos): + "Get the tag corresponding to the given index. Does parameter substitution." + if not pos.current().isdigit(): + Trace.error('Function should be f0,...,f9: f' + pos.current()) + return None + index = int(pos.skipcurrent()) + if 2 + index > len(self.translated): + Trace.error('Function f' + unicode(index) + ' is not defined') + return None + tag = self.translated[2 + index] + if not '$' in tag: + return tag + for variable in self.params: + if variable in tag: + param = self.params[variable] + if not param.literal: + Trace.error('Parameters in tag ' + tag + ' should be literal: {' + variable + '!}') + continue + if param.literalvalue: + value = param.literalvalue + else: + value = '' + tag = tag.replace(variable, value) + return tag + + def writebracket(self, direction, character): + "Return a new bracket looking at the given direction." + return self.factory.create(BracketCommand).create(direction, character) + + def computehybridsize(self): + "Compute the size of the hybrid function." + if not self.command in HybridSize.configsizes: + self.computesize() + return + self.size = HybridSize().getsize(self) + # set the size in all elements at first level + for element in self.contents: + element.size = self.size + +class HybridSize(object): + "The size associated with a hybrid function." + + configsizes = FormulaConfig.hybridsizes + + def getsize(self, function): + "Read the size for a function and parse it." + sizestring = self.configsizes[function.command] + for name in function.params: + if name in sizestring: + size = function.params[name].value.computesize() + sizestring = sizestring.replace(name, unicode(size)) + if '$' in sizestring: + Trace.error('Unconverted variable in hybrid size: ' + sizestring) + return 1 + return eval(sizestring) + + +FormulaCommand.types += [HybridFunction] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/macro.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/macro.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/macro.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/macro.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,200 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20100615 +# eLyXer macro processing + +from elyxer.util.trace import Trace +from elyxer.conf.config import * +from elyxer.parse.formulaparse import * +from elyxer.parse.headerparse import * +from elyxer.maths.formula import * +from elyxer.maths.hybrid import * + + +class MacroDefinition(CommandBit): + "A function that defines a new command (a macro)." + + macros = dict() + + def parsebit(self, pos): + "Parse the function that defines the macro." + self.output = EmptyOutput() + self.parameternumber = 0 + self.defaults = [] + self.factory.defining = True + self.parseparameters(pos) + self.factory.defining = False + Trace.debug('New command ' + self.newcommand + ' (' + \ + unicode(self.parameternumber) + ' parameters)') + self.macros[self.newcommand] = self + + def parseparameters(self, pos): + "Parse all optional parameters (number of parameters, default values)" + "and the mandatory definition." + self.newcommand = self.parsenewcommand(pos) + # parse number of parameters + literal = self.parsesquareliteral(pos) + if literal: + self.parameternumber = int(literal) + # parse all default values + bracket = self.parsesquare(pos) + while bracket: + self.defaults.append(bracket) + bracket = self.parsesquare(pos) + # parse mandatory definition + self.definition = self.parseparameter(pos) + + def parsenewcommand(self, pos): + "Parse the name of the new command." + self.factory.clearskipped(pos) + if self.factory.detecttype(Bracket, pos): + return self.parseliteral(pos) + if self.factory.detecttype(FormulaCommand, pos): + return self.factory.create(FormulaCommand).extractcommand(pos) + Trace.error('Unknown formula bit in defining function at ' + pos.identifier()) + return 'unknown' + + def instantiate(self): + "Return an instance of the macro." + return self.definition.clone() + +class MacroParameter(FormulaBit): + "A parameter from elyxer.a macro." + + def detect(self, pos): + "Find a macro parameter: #n." + return pos.checkfor('#') + + def parsebit(self, pos): + "Parse the parameter: #n." + if not pos.checkskip('#'): + Trace.error('Missing parameter start #.') + return + self.number = int(pos.skipcurrent()) + self.original = '#' + unicode(self.number) + self.contents = [TaggedBit().constant('#' + unicode(self.number), 'span class="unknown"')] + +class MacroFunction(CommandBit): + "A function that was defined using a macro." + + commandmap = MacroDefinition.macros + + def parsebit(self, pos): + "Parse a number of input parameters." + self.output = FilteredOutput() + self.values = [] + macro = self.translated + self.parseparameters(pos, macro) + self.completemacro(macro) + + def parseparameters(self, pos, macro): + "Parse as many parameters as are needed." + self.parseoptional(pos, list(macro.defaults)) + self.parsemandatory(pos, macro.parameternumber - len(macro.defaults)) + if len(self.values) < macro.parameternumber: + Trace.error('Missing parameters in macro ' + unicode(self)) + + def parseoptional(self, pos, defaults): + "Parse optional parameters." + optional = [] + while self.factory.detecttype(SquareBracket, pos): + optional.append(self.parsesquare(pos)) + if len(optional) > len(defaults): + break + for value in optional: + default = defaults.pop() + if len(value.contents) > 0: + self.values.append(value) + else: + self.values.append(default) + self.values += defaults + + def parsemandatory(self, pos, number): + "Parse a number of mandatory parameters." + for index in range(number): + parameter = self.parsemacroparameter(pos, number - index) + if not parameter: + return + self.values.append(parameter) + + def parsemacroparameter(self, pos, remaining): + "Parse a macro parameter. Could be a bracket or a single letter." + "If there are just two values remaining and there is a running number," + "parse as two separater numbers." + self.factory.clearskipped(pos) + if pos.finished(): + return None + if self.factory.detecttype(FormulaNumber, pos): + return self.parsenumbers(pos, remaining) + return self.parseparameter(pos) + + def parsenumbers(self, pos, remaining): + "Parse the remaining parameters as a running number." + "For example, 12 would be {1}{2}." + number = self.factory.parsetype(FormulaNumber, pos) + if not len(number.original) == remaining: + return number + for digit in number.original: + value = self.factory.create(FormulaNumber) + value.add(FormulaConstant(digit)) + value.type = number + self.values.append(value) + return None + + def completemacro(self, macro): + "Complete the macro with the parameters read." + self.contents = [macro.instantiate()] + replaced = [False] * len(self.values) + for parameter in self.searchall(MacroParameter): + index = parameter.number - 1 + if index >= len(self.values): + Trace.error('Macro parameter index out of bounds: ' + unicode(index)) + return + replaced[index] = True + parameter.contents = [self.values[index].clone()] + for index in range(len(self.values)): + if not replaced[index]: + self.addfilter(index, self.values[index]) + + def addfilter(self, index, value): + "Add a filter for the given parameter number and parameter value." + original = '#' + unicode(index + 1) + value = ''.join(self.values[0].gethtml()) + self.output.addfilter(original, value) + +class FormulaMacro(Formula): + "A math macro defined in an inset." + + def __init__(self): + self.parser = MacroParser() + self.output = EmptyOutput() + + def __unicode__(self): + "Return a printable representation." + return 'Math macro' + +FormulaFactory.types += [ MacroParameter ] + +FormulaCommand.types += [ + MacroFunction, + ] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/misc.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/misc.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/misc.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/misc.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,67 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20110109 +# eLyXer misc commands, invoked by class name from the configuration file. + +from elyxer.util.numbering import * +from elyxer.maths.command import * +from elyxer.maths.extracommand import * +from elyxer.maths.macro import * + + +class SetCounterFunction(CommandBit): + "A function which is used in the preamble to set a counter." + + def parsebit(self, pos): + "Parse a function with [] and {} parameters." + counter = self.parseliteral(pos) + value = self.parseliteral(pos) + try: + self.setcounter(counter, int(value)) + except: + Trace.error('Counter ' + counter + ' cannot be set to ' + value) + + def setcounter(self, counter, value): + "Set a global counter." + Trace.debug('Setting counter ' + unicode(counter) + ' to ' + unicode(value)) + NumberGenerator.generator.getcounter(counter).init(value) + +class FormulaTag(CommandBit): + "A \\tag command." + + def parsebit(self, pos): + "Parse the tag and apply it." + self.output = EmptyOutput() + self.tag = self.parseliteral(pos) + +class MiscCommand(CommandBit): + "A generic command which maps to a command class." + + commandmap = FormulaConfig.misccommands + + def parsebit(self, pos): + "Find the right command to parse and parse it." + commandtype = globals()[self.translated] + return self.parsecommandtype(self.translated, commandtype, pos) + +FormulaCommand.types += [MiscCommand] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/postformula.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/postformula.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/postformula.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/postformula.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,97 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090422 +# eLyXer postprocessor for formulae + +from elyxer.util.numbering import * +from elyxer.maths.command import * +from elyxer.maths.array import * +from elyxer.maths.misc import * +from elyxer.proc.postprocess import * +from elyxer.ref.link import * +from elyxer.ref.label import * +from elyxer.ref.partkey import * + + +class PostFormula(object): + "Postprocess a formula" + + processedclass = Formula + + def postprocess(self, last, formula, next): + "Postprocess any formulae" + if Options.jsmath or Options.mathjax: + return formula + self.postnumbering(formula) + return formula + + def postnumbering(self, formula): + "Check if it's a numbered equation, insert number." + if formula.header[0] != 'numbered': + return + functions = formula.searchremove(LabelFunction) + if len(functions) == 0: + label = self.createlabel(formula) + elif len(functions) == 1: + label = self.createlabel(formula, functions[0]) + if len(functions) <= 1: + label.parent = formula + formula.contents.insert(0, label) + return + for function in functions: + label = self.createlabel(formula, function) + row = self.searchrow(function) + label.parent = row + row.contents.insert(0, label) + + def createlabel(self, formula, function = None): + "Create a new label for a formula." + "Add a label to a formula." + tag = self.createtag(formula) + partkey = PartKey().createformula(tag) + if not formula.partkey: + formula.partkey = partkey + if not function: + label = Label() + label.create(partkey.tocentry + ' ', 'eq-' + tag, type="eqnumber") + else: + label = function.label + label.complete(partkey.tocentry + ' ') + return label + + def createtag(self, formula): + "Create the label tag." + tags = formula.searchall(FormulaTag) + if len(tags) == 0: + return NumberGenerator.chaptered.generate('formula') + if len(tags) > 1: + Trace.error('More than one tag in formula: ' + unicode(formula)) + return tags[0].tag + + def searchrow(self, function): + "Search for the row that contains the label function." + if isinstance(function.parent, Formula) or isinstance(function.parent, FormulaRow): + return function.parent + return self.searchrow(function.parent) + +Postprocessor.stages.append(PostFormula) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/symbol.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/symbol.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/maths/symbol.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/maths/symbol.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,116 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20101218 +# eLyXer big symbol generation. + +from elyxer.util.trace import Trace +from elyxer.util.docparams import * +from elyxer.conf.config import * +from elyxer.maths.bits import * + + +class BigSymbol(object): + "A big symbol generator." + + symbols = FormulaConfig.bigsymbols + + def __init__(self, symbol): + "Create the big symbol." + self.symbol = symbol + + def getpieces(self): + "Get an array with all pieces." + if not self.symbol in self.symbols: + return [self.symbol] + if self.smalllimit(): + return [self.symbol] + return self.symbols[self.symbol] + + def smalllimit(self): + "Decide if the limit should be a small, one-line symbol." + if not DocumentParameters.displaymode: + return True + if len(self.symbols[self.symbol]) == 1: + return True + return Options.simplemath + +class BigBracket(BigSymbol): + "A big bracket generator." + + def __init__(self, size, bracket, alignment='l'): + "Set the size and symbol for the bracket." + self.size = size + self.original = bracket + self.alignment = alignment + self.pieces = None + if bracket in FormulaConfig.bigbrackets: + self.pieces = FormulaConfig.bigbrackets[bracket] + + def getpiece(self, index): + "Return the nth piece for the bracket." + function = getattr(self, 'getpiece' + unicode(len(self.pieces))) + return function(index) + + def getpiece1(self, index): + "Return the only piece for a single-piece bracket." + return self.pieces[0] + + def getpiece3(self, index): + "Get the nth piece for a 3-piece bracket: parenthesis or square bracket." + if index == 0: + return self.pieces[0] + if index == self.size - 1: + return self.pieces[-1] + return self.pieces[1] + + def getpiece4(self, index): + "Get the nth piece for a 4-piece bracket: curly bracket." + if index == 0: + return self.pieces[0] + if index == self.size - 1: + return self.pieces[3] + if index == (self.size - 1)/2: + return self.pieces[2] + return self.pieces[1] + + def getcell(self, index): + "Get the bracket piece as an array cell." + piece = self.getpiece(index) + span = 'span class="bracket align-' + self.alignment + '"' + return TaggedBit().constant(piece, span) + + def getcontents(self): + "Get the bracket as an array or as a single bracket." + if self.size == 1 or not self.pieces: + return self.getsinglebracket() + rows = [] + for index in range(self.size): + cell = self.getcell(index) + rows.append(TaggedBit().complete([cell], 'span class="arrayrow"')) + return [TaggedBit().complete(rows, 'span class="array"')] + + def getsinglebracket(self): + "Return the bracket as a single sign." + if self.original == '.': + return [TaggedBit().constant('', 'span class="emptydot"')] + return [TaggedBit().constant(self.original, 'span class="symbol"')] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/out/output.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/out/output.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/out/output.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/out/output.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,170 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20090203 +# eLyXer html outputters + +from elyxer.util.trace import Trace + + +class ContainerOutput(object): + "The generic HTML output for a container." + + def gethtml(self, container): + "Show an error." + Trace.error('gethtml() not implemented for ' + unicode(self)) + + def isempty(self): + "Decide if the output is empty: by default, not empty." + return False + +class EmptyOutput(ContainerOutput): + + def gethtml(self, container): + "Return empty HTML code." + return [] + + def isempty(self): + "This output is particularly empty." + return True + +class FixedOutput(ContainerOutput): + "Fixed output" + + def gethtml(self, container): + "Return constant HTML code" + return container.html + +class ContentsOutput(ContainerOutput): + "Outputs the contents converted to HTML" + + def gethtml(self, container): + "Return the HTML code" + html = [] + if container.contents == None: + return html + for element in container.contents: + if not hasattr(element, 'gethtml'): + Trace.error('No html in ' + element.__class__.__name__ + ': ' + unicode(element)) + return html + html += element.gethtml() + return html + +class TaggedOutput(ContentsOutput): + "Outputs an HTML tag surrounding the contents." + + tag = None + breaklines = False + empty = False + + def settag(self, tag, breaklines=False, empty=False): + "Set the value for the tag and other attributes." + self.tag = tag + if breaklines: + self.breaklines = breaklines + if empty: + self.empty = empty + return self + + def setbreaklines(self, breaklines): + "Set the value for breaklines." + self.breaklines = breaklines + return self + + def gethtml(self, container): + "Return the HTML code." + if self.empty: + return [self.selfclosing(container)] + html = [self.open(container)] + html += ContentsOutput.gethtml(self, container) + html.append(self.close(container)) + return html + + def open(self, container): + "Get opening line." + if not self.checktag(): + return '' + open = '<' + self.tag + '>' + if self.breaklines: + return open + '\n' + return open + + def close(self, container): + "Get closing line." + if not self.checktag(): + return '' + close = '</' + self.tag.split()[0] + '>' + if self.breaklines: + return '\n' + close + '\n' + return close + + def selfclosing(self, container): + "Get self-closing line." + if not self.checktag(): + return '' + selfclosing = '<' + self.tag + '/>' + if self.breaklines: + return selfclosing + '\n' + return selfclosing + + def checktag(self): + "Check that the tag is valid." + if not self.tag: + Trace.error('No tag in ' + unicode(container)) + return False + if self.tag == '': + return False + return True + +class FilteredOutput(ContentsOutput): + "Returns the output in the contents, but filtered:" + "some strings are replaced by others." + + def __init__(self): + "Initialize the filters." + self.filters = [] + + def addfilter(self, original, replacement): + "Add a new filter: replace the original by the replacement." + self.filters.append((original, replacement)) + + def gethtml(self, container): + "Return the HTML code" + result = [] + html = ContentsOutput.gethtml(self, container) + for line in html: + result.append(self.filter(line)) + return result + + def filter(self, line): + "Filter a single line with all available filters." + for original, replacement in self.filters: + if original in line: + line = line.replace(original, replacement) + return line + +class StringOutput(ContainerOutput): + "Returns a bare string as output" + + def gethtml(self, container): + "Return a bare string" + return [container.string] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/out/template.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/out/template.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/out/template.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/out/template.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,317 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --end-- +# Alex 20100620 +# eLyXer HTML templates + +import datetime +from elyxer.io.bulk import * +from elyxer.parse.position import * +from elyxer.util.trace import Trace +from elyxer.util.options import * +from elyxer.util.translate import * +from elyxer.util.docparams import * +from elyxer.out.output import * + + +class HTMLTemplate(object): + "A template for HTML generation." + + current = None + + def getheader(self): + "Get the header (before content) of the template." + return [] + + def convertheader(self): + "Convert the header and all variables." + return self.convert(self.getheader()) + + def convertfooter(self): + "Convert the footer and all variables." + return self.convert(self.getfooter()) + + def convert(self, html): + "Convert a bit of HTML replacing all variables." + varmap = VariableMap() + for index, line in enumerate(html): + if '<!--$' in line: + html[index] = varmap.replace(line) + return html + + def getfooter(self): + "Get the footer (after content) of the template." + return [] + + def get(cls): + "Choose the right HTML template." + if not cls.current: + if Options.raw: + cls.current = RawTemplate() + elif Options.template: + cls.current = FileTemplate().read() + else: + cls.current = DefaultTemplate() + return cls.current + + get = classmethod(get) + +class RawTemplate(HTMLTemplate): + "The template for raw output." + + def getheader(self): + "Get the raw header." + return ['<!--starthtml-->\n'] + + def getfooter(self): + "Get the raw footer." + return ['\n\n<!--endhtml-->'] + +class FileTemplate(HTMLTemplate): + "A template read from elyxer.a file." + + divider = '<!--$content-->' + + def read(self): + "Read the file, separate header and footer." + self.header = [] + lines = [] + for line in self.templatelines(): + if FileTemplate.divider == line: + self.header = lines + lines = [] + else: + lines.append(line) + if self.header == []: + Trace.error('No ' + FileTemplate.divider + ' in template') + self.header = lines + lines = [] + self.footer = lines + return self + + def templatelines(self): + "Read all lines in the template, separate content into its own line." + template = BulkFile(Options.template).readall() + for line in template: + if not FileTemplate.divider in line: + yield line + else: + split = line.split(FileTemplate.divider) + for part in split[:-1]: + yield part + yield FileTemplate.divider + yield split[-1] + + def getheader(self): + "Return the header (before content)." + return self.header + + def getfooter(self): + "Return the footer (after the content)." + return self.footer + +class DefaultTemplate(HTMLTemplate): + "The default HTML template when not configured." + + def getheader(self): + "Get the default header (before content)." + html = [] + if not Options.html: + html.append(u'<?xml version="1.0" encoding="<!--$encoding-->"?>\n') + html.append(u'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n') + html.append(u'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n') + else: + html.append(u'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n') + html.append(u'<html lang="en">\n') + html.append(u'<head>\n') + html.append(u'<meta http-equiv="Content-Type" content="text/html; charset=<!--$encoding-->"/>\n') + html.append(u'<meta name="generator" content="http://www.nongnu.org/elyxer/"/>\n') + html.append(u'<meta name="create-date" content="<!--$date-->"/>\n') + html += self.getcss() + html.append(u'<title><!--$title-->\n') + if Options.jsmath: + html.append(u'\n') + html.append(u'\n') + if Options.mathjax: + if Options.mathjax == 'remote': + html.append(u'\n') + else: + html.append(u'\n') + html.append('\n') + html.append('\n') + html.append('
      \n') + if Options.jsmath or Options.mathjax: + if Options.mathjax: + html.append(u'\n') + html.append(u'\n') + return html + + def getcss(self): + "Get the CSS headers, both linked and embedded." + html = [] + for cssdoc in Options.css: + if cssdoc != '': + html.append(u'\n') + for cssfile in Options.embedcss: + html.append(u'\n') + return html + + def getfooter(self): + "Get the default footer (after content)." + html = [] + html.append('\n') + footer = self.createfooter() + if len(footer) > 0: + html.append('\n') + html += footer + html.append('
      \n') + html.append('\n') + html.append('\n') + return html + + def createfooter(self): + "Create the footer proper." + html = [] + if Options.copyright: + html.append('\n') + if Options.nofooter: + return html + html.append('\n') + return html + +class VariableMap(object): + "A map with all replacement variables." + + def __init__(self): + self.variables = dict() + self.variables['title'] = DocumentTitle().getvalue() + self.variables['author'] = DocumentAuthor().getvalue() + self.variables['version'] = GeneralConfig.version['number'] + ' (' \ + + GeneralConfig.version['date'] + ')' + self.variables['year'] = unicode(datetime.date.today().year) + self.variables['date'] = datetime.date.today().isoformat() + self.variables['datetime'] = datetime.datetime.now().isoformat() + self.variables['css'] = Options.css[0] + if Options.iso885915: + self.variables['encoding'] = 'ISO-8859-1' + else: + self.variables['encoding'] = 'UTF-8' + if Options.jsmath: + self.variables['jsmath'] = Options.jsmath + if Options.mathjax: + self.variables['mathjax'] = Options.mathjax + + def replace(self, line): + "Replace all variables in a line." + result = '' + pos = TextPosition(line) + while not pos.finished(): + if pos.checkskip(''): + Trace.error('Weird template format in ' + line) + return value + +class DocumentTitle(object): + "The title of the whole document." + + title = None + + def getvalue(self): + "Return the correct title from elyxer.the option or the PDF title." + if Options.title: + return Options.title + if DocumentTitle.title: + return DocumentTitle.title + if DocumentParameters.pdftitle: + return DocumentParameters.pdftitle + return 'Converted document' + +class DocumentAuthor(object): + "The author of the document." + + author = '' + + def appendauthor(cls, authorline): + "Append a line with author information." + cls.author += authorline + + appendauthor = classmethod(appendauthor) + + def getvalue(self): + "Get the document author." + return DocumentAuthor.author + +class HeaderOutput(ContainerOutput): + "Returns the HTML headers" + + def gethtml(self, container): + "Return a constant header" + return HTMLTemplate.get().convertheader() + +class FooterOutput(ContentsOutput): + "Return the HTML code for the footer" + + def gethtml(self, container): + "Footer HTML" + contents = ContentsOutput.gethtml(self, container) + return contents + HTMLTemplate.get().convertfooter() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/formulaparse.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/formulaparse.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/formulaparse.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/formulaparse.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,148 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090503 +# eLyXer formula parsing + +from elyxer.util.trace import Trace +from elyxer.conf.config import * +from elyxer.parse.parser import * +from elyxer.parse.position import * + + +class FormulaParser(Parser): + "Parses a formula" + + def parseheader(self, reader): + "See if the formula is inlined" + self.begin = reader.linenumber + 1 + type = self.parsetype(reader) + if not type: + reader.nextline() + type = self.parsetype(reader) + if not type: + Trace.error('Unknown formula type in ' + reader.currentline().strip()) + return ['unknown'] + return [type] + + def parsetype(self, reader): + "Get the formula type from the first line." + if reader.currentline().find(FormulaConfig.starts['simple']) >= 0: + return 'inline' + if reader.currentline().find(FormulaConfig.starts['complex']) >= 0: + return 'block' + if reader.currentline().find(FormulaConfig.starts['unnumbered']) >= 0: + return 'block' + if reader.currentline().find(FormulaConfig.starts['beginbefore']) >= 0: + return 'numbered' + return None + + def parse(self, reader): + "Parse the formula until the end" + formula = self.parseformula(reader) + while not reader.currentline().startswith(self.ending): + stripped = reader.currentline().strip() + if len(stripped) > 0: + Trace.error('Unparsed formula line ' + stripped) + reader.nextline() + reader.nextline() + return formula + + def parseformula(self, reader): + "Parse the formula contents" + simple = FormulaConfig.starts['simple'] + if simple in reader.currentline(): + rest = reader.currentline().split(simple, 1)[1] + if simple in rest: + # formula is $...$ + return self.parsesingleliner(reader, simple, simple) + # formula is multiline $...$ + return self.parsemultiliner(reader, simple, simple) + if FormulaConfig.starts['complex'] in reader.currentline(): + # formula of the form \[...\] + return self.parsemultiliner(reader, FormulaConfig.starts['complex'], + FormulaConfig.endings['complex']) + beginbefore = FormulaConfig.starts['beginbefore'] + beginafter = FormulaConfig.starts['beginafter'] + if beginbefore in reader.currentline(): + if reader.currentline().strip().endswith(beginafter): + current = reader.currentline().strip() + endsplit = current.split(beginbefore)[1].split(beginafter) + startpiece = beginbefore + endsplit[0] + beginafter + endbefore = FormulaConfig.endings['endbefore'] + endafter = FormulaConfig.endings['endafter'] + endpiece = endbefore + endsplit[0] + endafter + return startpiece + self.parsemultiliner(reader, startpiece, endpiece) + endpiece + Trace.error('Missing ' + beginafter + ' in ' + reader.currentline()) + return '' + begincommand = FormulaConfig.starts['command'] + beginbracket = FormulaConfig.starts['bracket'] + if begincommand in reader.currentline() and beginbracket in reader.currentline(): + endbracket = FormulaConfig.endings['bracket'] + return self.parsemultiliner(reader, beginbracket, endbracket) + Trace.error('Formula beginning ' + reader.currentline() + ' is unknown') + return '' + + def parsesingleliner(self, reader, start, ending): + "Parse a formula in one line" + line = reader.currentline().strip() + if not start in line: + Trace.error('Line ' + line + ' does not contain formula start ' + start) + return '' + if not line.endswith(ending): + Trace.error('Formula ' + line + ' does not end with ' + ending) + return '' + index = line.index(start) + rest = line[index + len(start):-len(ending)] + reader.nextline() + return rest + + def parsemultiliner(self, reader, start, ending): + "Parse a formula in multiple lines" + formula = '' + line = reader.currentline() + if not start in line: + Trace.error('Line ' + line.strip() + ' does not contain formula start ' + start) + return '' + index = line.index(start) + line = line[index + len(start):].strip() + while not line.endswith(ending): + formula += line + '\n' + reader.nextline() + line = reader.currentline() + formula += line[:-len(ending)] + reader.nextline() + return formula + +class MacroParser(FormulaParser): + "A parser for a formula macro." + + def parseheader(self, reader): + "See if the formula is inlined" + self.begin = reader.linenumber + 1 + return ['inline'] + + def parse(self, reader): + "Parse the formula until the end" + formula = self.parsemultiliner(reader, self.parent.start, self.ending) + reader.nextline() + return formula + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/glob.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/glob.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/glob.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/glob.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,226 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20110111 +# eLyXer globbing of an underlying string. + +from elyxer.util.trace import Trace + + +class Globable(object): + """A bit of text which can be globbed (lumped together in bits). + Methods current(), skipcurrent(), checkfor() and isout() have to be + implemented by subclasses.""" + + leavepending = False + + def __init__(self): + self.endinglist = EndingList() + + def checkbytemark(self): + "Check for a Unicode byte mark and skip it." + if self.finished(): + return + if ord(self.current()) == 0xfeff: + self.skipcurrent() + + def isout(self): + "Find out if we are out of the position yet." + Trace.error('Unimplemented isout()') + return True + + def current(self): + "Return the current character." + Trace.error('Unimplemented current()') + return '' + + def checkfor(self, string): + "Check for the given string in the current position." + Trace.error('Unimplemented checkfor()') + return False + + def finished(self): + "Find out if the current text has finished." + if self.isout(): + if not self.leavepending: + self.endinglist.checkpending() + return True + return self.endinglist.checkin(self) + + def skipcurrent(self): + "Return the current character and skip it." + Trace.error('Unimplemented skipcurrent()') + return '' + + def glob(self, currentcheck): + "Glob a bit of text that satisfies a check on the current char." + glob = '' + while not self.finished() and currentcheck(): + glob += self.skipcurrent() + return glob + + def globalpha(self): + "Glob a bit of alpha text" + return self.glob(lambda: self.current().isalpha()) + + def globnumber(self): + "Glob a row of digits." + return self.glob(lambda: self.current().isdigit()) + + def isidentifier(self): + "Return if the current character is alphanumeric or _." + if self.current().isalnum() or self.current() == '_': + return True + return False + + def globidentifier(self): + "Glob alphanumeric and _ symbols." + return self.glob(self.isidentifier) + + def isvalue(self): + "Return if the current character is a value character:" + "not a bracket or a space." + if self.current().isspace(): + return False + if self.current() in '{}()': + return False + return True + + def globvalue(self): + "Glob a value: any symbols but brackets." + return self.glob(self.isvalue) + + def skipspace(self): + "Skip all whitespace at current position." + return self.glob(lambda: self.current().isspace()) + + def globincluding(self, magicchar): + "Glob a bit of text up to (including) the magic char." + glob = self.glob(lambda: self.current() != magicchar) + magicchar + self.skip(magicchar) + return glob + + def globexcluding(self, excluded): + "Glob a bit of text up until (excluding) any excluded character." + return self.glob(lambda: self.current() not in excluded) + + def pushending(self, ending, optional = False): + "Push a new ending to the bottom" + self.endinglist.add(ending, optional) + + def popending(self, expected = None): + "Pop the ending found at the current position" + if self.isout() and self.leavepending: + return expected + ending = self.endinglist.pop(self) + if expected and expected != ending: + Trace.error('Expected ending ' + expected + ', got ' + ending) + self.skip(ending) + return ending + + def nextending(self): + "Return the next ending in the queue." + nextending = self.endinglist.findending(self) + if not nextending: + return None + return nextending.ending + +class EndingList(object): + "A list of position endings" + + def __init__(self): + self.endings = [] + + def add(self, ending, optional = False): + "Add a new ending to the list" + self.endings.append(PositionEnding(ending, optional)) + + def pickpending(self, pos): + "Pick any pending endings from a parse position." + self.endings += pos.endinglist.endings + + def checkin(self, pos): + "Search for an ending" + if self.findending(pos): + return True + return False + + def pop(self, pos): + "Remove the ending at the current position" + if pos.isout(): + Trace.error('No ending out of bounds') + return '' + ending = self.findending(pos) + if not ending: + Trace.error('No ending at ' + pos.current()) + return '' + for each in reversed(self.endings): + self.endings.remove(each) + if each == ending: + return each.ending + elif not each.optional: + Trace.error('Removed non-optional ending ' + each) + Trace.error('No endings left') + return '' + + def findending(self, pos): + "Find the ending at the current position" + if len(self.endings) == 0: + return None + for index, ending in enumerate(reversed(self.endings)): + if ending.checkin(pos): + return ending + if not ending.optional: + return None + return None + + def checkpending(self): + "Check if there are any pending endings" + if len(self.endings) != 0: + Trace.error('Pending ' + unicode(self) + ' left open') + + def __unicode__(self): + "Printable representation" + string = 'endings [' + for ending in self.endings: + string += unicode(ending) + ',' + if len(self.endings) > 0: + string = string[:-1] + return string + ']' + +class PositionEnding(object): + "An ending for a parsing position" + + def __init__(self, ending, optional): + self.ending = ending + self.optional = optional + + def checkin(self, pos): + "Check for the ending" + return pos.checkfor(self.ending) + + def __unicode__(self): + "Printable representation" + string = 'Ending ' + self.ending + if self.optional: + string += ' (optional)' + return string + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/headerparse.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/headerparse.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/headerparse.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/headerparse.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,132 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100509 +# eLyXer: LyX header parsing. + +from elyxer.util.trace import Trace +from elyxer.util.options import * +from elyxer.conf.config import * +from elyxer.parse.parser import * + + +class HeaderParser(Parser): + "Parses the LyX header" + + def parse(self, reader): + "Parse header parameters into a dictionary, return the preamble." + contents = [] + self.parseending(reader, lambda: self.parseline(reader, contents)) + # skip last line + reader.nextline() + return contents + + def parseline(self, reader, contents): + "Parse a single line as a parameter or as a start" + line = reader.currentline() + if line.startswith(HeaderConfig.parameters['branch']): + self.parsebranch(reader) + return + elif line.startswith(HeaderConfig.parameters['lstset']): + LstParser().parselstset(reader) + return + elif line.startswith(HeaderConfig.parameters['beginpreamble']): + contents.append(self.factory.createcontainer(reader)) + return + # no match + self.parseparameter(reader) + + def parsebranch(self, reader): + "Parse all branch definitions." + branch = reader.currentline().split()[1] + reader.nextline() + subparser = HeaderParser().complete(HeaderConfig.parameters['endbranch']) + subparser.parse(reader) + options = BranchOptions(branch) + for key in subparser.parameters: + options.set(key, subparser.parameters[key]) + Options.branches[branch] = options + + def complete(self, ending): + "Complete the parser with the given ending." + self.ending = ending + return self + +class PreambleParser(Parser): + "A parser for the LyX preamble." + + preamble = [] + + def parse(self, reader): + "Parse the full preamble with all statements." + self.ending = HeaderConfig.parameters['endpreamble'] + self.parseending(reader, lambda: self.parsepreambleline(reader)) + return [] + + def parsepreambleline(self, reader): + "Parse a single preamble line." + PreambleParser.preamble.append(reader.currentline()) + reader.nextline() + +class LstParser(object): + "Parse global and local lstparams." + + globalparams = dict() + + def parselstset(self, reader): + "Parse a declaration of lstparams in lstset." + paramtext = self.extractlstset(reader) + if not '{' in paramtext: + Trace.error('Missing opening bracket in lstset: ' + paramtext) + return + lefttext = paramtext.split('{')[1] + croppedtext = lefttext[:-1] + LstParser.globalparams = self.parselstparams(croppedtext) + + def extractlstset(self, reader): + "Extract the global lstset parameters." + paramtext = '' + while not reader.finished(): + paramtext += reader.currentline() + reader.nextline() + if paramtext.endswith('}'): + return paramtext + Trace.error('Could not find end of \\lstset settings; aborting') + + def parsecontainer(self, container): + "Parse some lstparams from elyxer.a container." + container.lstparams = LstParser.globalparams.copy() + paramlist = container.getparameterlist('lstparams') + container.lstparams.update(self.parselstparams(paramlist)) + + def parselstparams(self, paramlist): + "Process a number of lstparams from elyxer.a list." + paramdict = dict() + for param in paramlist: + if not '=' in param: + if len(param.strip()) > 0: + Trace.error('Invalid listing parameter ' + param) + else: + key, value = param.split('=', 1) + paramdict[key] = value + return paramdict + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/parser.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/parser.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/parser.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/parser.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,201 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090203 +# eLyXer parsers + +from elyxer.util.trace import Trace +from elyxer.util.options import * +from elyxer.conf.config import * + + +class Parser(object): + "A generic parser" + + def __init__(self): + self.begin = 0 + self.parameters = dict() + + def parseheader(self, reader): + "Parse the header" + header = reader.currentline().split() + reader.nextline() + self.begin = reader.linenumber + return header + + def parseparameter(self, reader): + "Parse a parameter" + if reader.currentline().strip().startswith('<'): + key, value = self.parsexml(reader) + self.parameters[key] = value + return + split = reader.currentline().strip().split(' ', 1) + reader.nextline() + if len(split) == 0: + return + key = split[0] + if len(split) == 1: + self.parameters[key] = True + return + if not '"' in split[1]: + self.parameters[key] = split[1].strip() + return + doublesplit = split[1].split('"') + self.parameters[key] = doublesplit[1] + + def parsexml(self, reader): + "Parse a parameter in xml form: " + strip = reader.currentline().strip() + reader.nextline() + if not strip.endswith('>'): + Trace.error('XML parameter ' + strip + ' should be <...>') + split = strip[1:-1].split() + if len(split) == 0: + Trace.error('Empty XML parameter <>') + return None, None + key = split[0] + del split[0] + if len(split) == 0: + return key, dict() + attrs = dict() + for attr in split: + if not '=' in attr: + Trace.error('Erroneous attribute for ' + key + ': ' + attr) + attr += '="0"' + parts = attr.split('=') + attrkey = parts[0] + value = parts[1].split('"')[1] + attrs[attrkey] = value + return key, attrs + + def parseending(self, reader, process): + "Parse until the current ending is found" + if not self.ending: + Trace.error('No ending for ' + unicode(self)) + return + while not reader.currentline().startswith(self.ending): + process() + + def parsecontainer(self, reader, contents): + container = self.factory.createcontainer(reader) + if container: + container.parent = self.parent + contents.append(container) + + def __unicode__(self): + "Return a description" + return self.__class__.__name__ + ' (' + unicode(self.begin) + ')' + +class LoneCommand(Parser): + "A parser for just one command line" + + def parse(self,reader): + "Read nothing" + return [] + +class TextParser(Parser): + "A parser for a command and a bit of text" + + stack = [] + + def __init__(self, container): + Parser.__init__(self) + self.ending = None + if container.__class__.__name__ in ContainerConfig.endings: + self.ending = ContainerConfig.endings[container.__class__.__name__] + self.endings = [] + + def parse(self, reader): + "Parse lines as long as they are text" + TextParser.stack.append(self.ending) + self.endings = TextParser.stack + [ContainerConfig.endings['Layout'], + ContainerConfig.endings['Inset'], self.ending] + contents = [] + while not self.isending(reader): + self.parsecontainer(reader, contents) + return contents + + def isending(self, reader): + "Check if text is ending" + current = reader.currentline().split() + if len(current) == 0: + return False + if current[0] in self.endings: + if current[0] in TextParser.stack: + TextParser.stack.remove(current[0]) + else: + TextParser.stack = [] + return True + return False + +class ExcludingParser(Parser): + "A parser that excludes the final line" + + def parse(self, reader): + "Parse everything up to (and excluding) the final line" + contents = [] + self.parseending(reader, lambda: self.parsecontainer(reader, contents)) + return contents + +class BoundedParser(ExcludingParser): + "A parser bound by a final line" + + def parse(self, reader): + "Parse everything, including the final line" + contents = ExcludingParser.parse(self, reader) + # skip last line + reader.nextline() + return contents + +class BoundedDummy(Parser): + "A bound parser that ignores everything" + + def parse(self, reader): + "Parse the contents of the container" + self.parseending(reader, lambda: reader.nextline()) + # skip last line + reader.nextline() + return [] + +class StringParser(Parser): + "Parses just a string" + + def parseheader(self, reader): + "Do nothing, just take note" + self.begin = reader.linenumber + 1 + return [] + + def parse(self, reader): + "Parse a single line" + contents = reader.currentline() + reader.nextline() + return contents + +class InsetParser(BoundedParser): + "Parses a LyX inset" + + def parse(self, reader): + "Parse inset parameters into a dictionary" + startcommand = ContainerConfig.string['startcommand'] + while reader.currentline() != '' and not reader.currentline().startswith(startcommand): + self.parseparameter(reader) + return BoundedParser.parse(self, reader) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/position.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/position.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/position.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/position.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,181 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090503 +# eLyXer formula parsing + +from elyxer.io.fileline import * +from elyxer.util.trace import Trace +from elyxer.conf.config import * +from elyxer.parse.glob import * + + +class Position(Globable): + """A position in a text to parse. + Including those in Globable, functions to implement by subclasses are: + skip(), identifier(), extract(), isout() and current().""" + + def __init__(self): + Globable.__init__(self) + + def skip(self, string): + "Skip a string" + Trace.error('Unimplemented skip()') + + def identifier(self): + "Return an identifier for the current position." + Trace.error('Unimplemented identifier()') + return 'Error' + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text," + "without advancing the parse position." + Trace.error('Unimplemented extract()') + return None + + def checkfor(self, string): + "Check for a string at the given position." + return string == self.extract(len(string)) + + def checkforlower(self, string): + "Check for a string in lower case." + extracted = self.extract(len(string)) + if not extracted: + return False + return string.lower() == self.extract(len(string)).lower() + + def skipcurrent(self): + "Return the current character and skip it." + current = self.current() + self.skip(current) + return current + + def next(self): + "Advance the position and return the next character." + self.skipcurrent() + return self.current() + + def checkskip(self, string): + "Check for a string at the given position; if there, skip it" + if not self.checkfor(string): + return False + self.skip(string) + return True + + def error(self, message): + "Show an error message and the position identifier." + Trace.error(message + ': ' + self.identifier()) + +class TextPosition(Position): + "A parse position based on a raw text." + + def __init__(self, text): + "Create the position from elyxer.some text." + Position.__init__(self) + self.pos = 0 + self.text = text + self.checkbytemark() + + def skip(self, string): + "Skip a string of characters." + self.pos += len(string) + + def identifier(self): + "Return a sample of the remaining text." + length = 30 + if self.pos + length > len(self.text): + length = len(self.text) - self.pos + return '*' + self.text[self.pos:self.pos + length] + '*' + + def isout(self): + "Find out if we are out of the text yet." + return self.pos >= len(self.text) + + def current(self): + "Return the current character, assuming we are not out." + return self.text[self.pos] + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text." + if self.pos + length > len(self.text): + return None + return self.text[self.pos : self.pos + length] + +class FilePosition(Position): + "A parse position based on an underlying file." + + def __init__(self, filename): + "Create the position from a file." + Position.__init__(self) + self.reader = LineReader(filename) + self.pos = 0 + self.checkbytemark() + + def skip(self, string): + "Skip a string of characters." + length = len(string) + while self.pos + length > len(self.reader.currentline()): + length -= len(self.reader.currentline()) - self.pos + 1 + self.nextline() + self.pos += length + + def currentline(self): + "Get the current line of the underlying file." + return self.reader.currentline() + + def nextline(self): + "Go to the next line." + self.reader.nextline() + self.pos = 0 + + def linenumber(self): + "Return the line number of the file." + return self.reader.linenumber + 1 + + def identifier(self): + "Return the current line and line number in the file." + before = self.reader.currentline()[:self.pos - 1] + after = self.reader.currentline()[self.pos:] + return 'line ' + unicode(self.getlinenumber()) + ': ' + before + '*' + after + + def isout(self): + "Find out if we are out of the text yet." + if self.pos > len(self.reader.currentline()): + if self.pos > len(self.reader.currentline()) + 1: + Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos)) + self.nextline() + return self.reader.finished() + + def current(self): + "Return the current character, assuming we are not out." + if self.pos == len(self.reader.currentline()): + return '\n' + if self.pos > len(self.reader.currentline()): + Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos)) + return '*' + return self.reader.currentline()[self.pos] + + def extract(self, length): + "Extract the next string of the given length, or None if not enough text." + if self.pos + length > len(self.reader.currentline()): + return None + return self.reader.currentline()[self.pos : self.pos + length] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/tableparse.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/tableparse.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/parse/tableparse.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/parse/tableparse.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,69 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090503 +# eLyXer table parsing + +from elyxer.parse.parser import * +from elyxer.conf.config import * + + +class TableParser(BoundedParser): + "Parse the whole table" + + headers = ContainerConfig.table['headers'] + + def __init__(self): + BoundedParser.__init__(self) + self.columns = list() + + def parseheader(self, reader): + "Parse table headers" + reader.nextline() + while self.startswithheader(reader): + self.parseparameter(reader) + return [] + + def startswithheader(self, reader): + "Check if the current line starts with a header line" + for start in TableParser.headers: + if reader.currentline().strip().startswith(start): + return True + return False + +class TablePartParser(BoundedParser): + "Parse a table part (row or cell)" + + def parseheader(self, reader): + "Parse the header" + tablekey, parameters = self.parsexml(reader) + self.parameters = parameters + return list() + +class ColumnParser(LoneCommand): + "Parse column properties" + + def parseheader(self, reader): + "Parse the column definition" + key, parameters = self.parsexml(reader) + self.parameters = parameters + return [] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/proc/formulaproc.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/proc/formulaproc.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/proc/formulaproc.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/proc/formulaproc.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,94 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20101111 +# eLyXer formulae processing. + +from elyxer.util.trace import * +from elyxer.conf.config import * +from elyxer.maths.bits import * + + +class MathsProcessor(object): + "A processor for a maths construction inside the FormulaProcessor." + + def process(self, contents, index): + "Process an element inside a formula." + Trace.error('Unimplemented process() in ' + unicode(self)) + + def __unicode__(self): + "Return a printable description." + return 'Maths processor ' + self.__class__.__name__ + +class FormulaProcessor(object): + "A processor specifically for formulas." + + processors = [] + + def process(self, bit): + "Process the contents of every formula bit, recursively." + self.processcontents(bit) + self.processinsides(bit) + self.traversewhole(bit) + + def processcontents(self, bit): + "Process the contents of a formula bit." + if not isinstance(bit, FormulaBit): + return + bit.process() + for element in bit.contents: + self.processcontents(element) + + def processinsides(self, bit): + "Process the insides (limits, brackets) in a formula bit." + if not isinstance(bit, FormulaBit): + return + for index, element in enumerate(bit.contents): + for processor in self.processors: + processor.process(bit.contents, index) + # continue with recursive processing + self.processinsides(element) + + def traversewhole(self, formula): + "Traverse over the contents to alter variables and space units." + last = None + for bit, contents in self.traverse(formula): + if bit.type == 'alpha': + self.italicize(bit, contents) + elif bit.type == 'font' and last and last.type == 'number': + bit.contents.insert(0, FormulaConstant(u' ')) + last = bit + + def traverse(self, bit): + "Traverse a formula and yield a flattened structure of (bit, list) pairs." + for element in bit.contents: + if hasattr(element, 'type') and element.type: + yield (element, bit.contents) + elif isinstance(element, FormulaBit): + for pair in self.traverse(element): + yield pair + + def italicize(self, bit, contents): + "Italicize the given bit of text." + index = contents.index(bit) + contents[index] = TaggedBit().complete([bit], 'i') + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/proc/postprocess.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/proc/postprocess.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/proc/postprocess.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/proc/postprocess.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,94 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090324 +# eLyXer postprocessor code + + +class Postprocessor(object): + "Postprocess a container keeping some context" + + stages = [] + + def __init__(self): + self.stages = StageDict(Postprocessor.stages, self) + self.current = None + self.last = None + + def postprocess(self, next): + "Postprocess a container and its contents." + self.postrecursive(self.current) + result = self.postcurrent(next) + self.last = self.current + self.current = next + return result + + def postrecursive(self, container): + "Postprocess the container contents recursively" + if not hasattr(container, 'contents'): + return + if len(container.contents) == 0: + return + if hasattr(container, 'postprocess'): + if not container.postprocess: + return + postprocessor = Postprocessor() + contents = [] + for element in container.contents: + post = postprocessor.postprocess(element) + if post: + contents.append(post) + # two rounds to empty the pipeline + for i in range(2): + post = postprocessor.postprocess(None) + if post: + contents.append(post) + container.contents = contents + + def postcurrent(self, next): + "Postprocess the current element taking into account next and last." + stage = self.stages.getstage(self.current) + if not stage: + return self.current + return stage.postprocess(self.last, self.current, next) + +class StageDict(object): + "A dictionary of stages corresponding to classes" + + def __init__(self, classes, postprocessor): + "Instantiate an element from elyxer.each class and store as a dictionary" + instances = self.instantiate(classes, postprocessor) + self.stagedict = dict([(x.processedclass, x) for x in instances]) + + def instantiate(self, classes, postprocessor): + "Instantiate an element from elyxer.each class" + stages = [x.__new__(x) for x in classes] + for element in stages: + element.__init__() + element.postprocessor = postprocessor + return stages + + def getstage(self, element): + "Get the stage for a given element, if the type is in the dict" + if not element.__class__ in self.stagedict: + return None + return self.stagedict[element.__class__] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/proc/process.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/proc/process.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/proc/process.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/proc/process.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,79 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100714 +# eLyXer: internal processing code + + +from elyxer.util.trace import * +from elyxer.gen.header import * +from elyxer.ref.index import * +from elyxer.gen.layout import * +from elyxer.proc.postprocess import * + + +class Processor(object): + "Process a container and its contents." + + prestages = [] + skipfiltered = ['LyXHeader', 'LyXFooter', 'Title', 'Author', 'TableOfContents'] + + def __init__(self, filtering): + "Set filtering mode (to skip postprocessing)." + "With filtering on, the classes in skipfiltered are not processed at all." + self.filtering = filtering + self.postprocessor = Postprocessor() + + def process(self, container): + "Do the whole processing on a container." + if self.filtering and container.__class__.__name__ in self.skipfiltered: + return None + container = self.preprocess(container) + self.processcontainer(container) + if not container: + # do not postprocess empty containers from elyxer.here + return container + return self.postprocess(container) + + def preprocess(self, root): + "Preprocess a root container with all prestages." + if not root: + return None + for stage in self.prestages: + root = stage.preprocess(root) + if not root: + return None + return root + + def processcontainer(self, container): + "Process a container and its contents, recursively." + if not container: + return + for element in container.contents: + self.processcontainer(element) + container.process() + + def postprocess(self, container): + "Postprocess a container, unless filtering is on." + if self.filtering: + return container + return self.postprocessor.postprocess(container) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/ref/index.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/ref/index.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/ref/index.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/ref/index.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,267 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100713 +# eLyXer: indexing entries + +from elyxer.util.trace import Trace +from elyxer.util.translate import * +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.gen.container import * +from elyxer.gen.styles import * +from elyxer.ref.link import * +from elyxer.ref.partkey import * +from elyxer.proc.process import * + + +class ListInset(Container): + "An inset with a list, normally made of links." + + def __init__(self): + self.parser = InsetParser() + self.output = ContentsOutput() + + def sortdictionary(self, dictionary): + "Sort all entries in the dictionary" + keys = dictionary.keys() + # sort by name + keys.sort() + return keys + + sortdictionary = classmethod(sortdictionary) + +class ListOf(ListInset): + "A list of entities (figures, tables, algorithms)" + + def process(self): + "Parse the header and get the type" + self.type = self.header[2] + text = Translator.translate('list-' + self.type) + self.contents = [TaggedText().constant(text, 'div class="tocheader"', True)] + +class TableOfContents(ListInset): + "Table of contents" + + def process(self): + "Parse the header and get the type" + self.create(Translator.translate('toc')) + + def create(self, heading): + "Create a table of contents with the given heading text." + self.output = TaggedOutput().settag('div class="fulltoc"', True) + self.contents = [TaggedText().constant(heading, 'div class="tocheader"', True)] + return self + + def add(self, entry): + "Add a new entry to the TOC." + if entry: + self.contents.append(entry) + +class IndexReference(Link): + "A reference to an entry in the alphabetical index." + + name = 'none' + + def process(self): + "Put entry in index" + name = self.getparameter('name') + if name: + self.name = name.strip() + else: + self.name = self.extracttext() + IndexEntry.get(self.name).addref(self) + + def __unicode__(self): + "Return a printable representation." + return 'Reference to ' + self.name + +class IndexHeader(Link): + "The header line for an index entry. Keeps all arrows." + + keyescapes = {'!':'', '|':'-', ' ':'-', '--':'-', ',':'', '\\':'', '@':'_', u'°':''} + + def create(self, names): + "Create the header for the given index entry." + self.output = TaggedOutput().settag('p class="printindex"', True) + self.name = names[-1] + keys = [self.escape(part, self.keyescapes) for part in names] + self.key = '-'.join(keys) + self.anchor = Link().complete('', 'index-' + self.key, None, 'printindex') + self.contents = [self.anchor, Constant(self.name + ': ')] + self.arrows = [] + return self + + def addref(self, reference): + "Create an arrow pointing to a reference." + reference.index = unicode(len(self.arrows)) + reference.destination = self.anchor + reference.complete(u'↓', 'entry-' + self.key + '-' + reference.index) + arrow = Link().complete(u'↑', type = 'IndexArrow') + arrow.destination = reference + if len(self.arrows) > 0: + self.contents.append(Constant(u', ')) + self.arrows.append(arrow) + self.contents.append(arrow) + + def __unicode__(self): + "Return a printable representation." + return 'Index header for ' + self.name + +class IndexGroup(Container): + "A group of entries in the alphabetical index, for an entry." + + root = None + + def create(self): + "Create an index group." + self.entries = dict() + self.output = EmptyOutput() + return self + + def findentry(self, names): + "Find the entry with the given names." + if self == IndexGroup.root: + self.output = ContentsOutput() + else: + self.output = TaggedOutput().settag('div class="indexgroup"', True) + lastname = names[-1] + if not lastname in self.entries: + self.entries[lastname] = IndexEntry().create(names) + return self.entries[lastname] + + def sort(self): + "Sort all entries in the group." + for key in ListInset.sortdictionary(self.entries): + entry = self.entries[key] + entry.group.sort() + self.contents.append(entry) + + def __unicode__(self): + "Return a printable representation." + return 'Index group' + +IndexGroup.root = IndexGroup().create() + +class IndexEntry(Container): + "An entry in the alphabetical index." + "When an index entry is of the form 'part1 ! part2 ...', " + "a hierarchical structure in the form of an IndexGroup is constructed." + "An index entry contains a mandatory header, and an optional group." + + def create(self, names): + "Create an index entry with the given name." + self.output = ContentsOutput() + self.header = IndexHeader().create(names) + self.group = IndexGroup().create() + self.contents = [self.header, self.group] + return self + + def addref(self, reference): + "Add a reference to the entry." + self.header.addref(reference) + + def get(cls, name): + "Get the index entry for the given name." + group = IndexGroup.root + parts = IndexEntry.splitname(name) + readparts = [] + for part in parts: + readparts.append(part) + entry = group.findentry(readparts) + group = entry.group + return entry + + def splitname(cls, name): + "Split a name in parts divided by !." + return [part.strip() for part in name.split('!')] + + def __unicode__(self): + "Return a printable representation." + return 'Index entry for ' + self.header.name + + get = classmethod(get) + splitname = classmethod(splitname) + +class PrintIndex(ListInset): + "Command to print an index" + + def process(self): + "Create the alphabetic index" + self.name = Translator.translate('index') + self.partkey = PartKeyGenerator.forindex(self) + if not self.partkey: + return + self.contents = [TaggedText().constant(self.name, 'h1 class="index"')] + self.partkey.addtoclabel(self) + IndexGroup.root.sort() + self.contents.append(IndexGroup.root) + +class NomenclatureEntry(Link): + "An entry of LyX nomenclature" + + entries = dict() + + def process(self): + "Put entry in index" + symbol = self.getparameter('symbol') + description = self.getparameter('description') + key = symbol.replace(' ', '-').lower() + if key in NomenclatureEntry.entries: + Trace.error('Duplicated nomenclature entry ' + key) + self.complete(u'↓', 'noment-' + key) + entry = Link().complete(u'↑', 'nom-' + key) + entry.symbol = symbol + entry.description = description + self.setmutualdestination(entry) + NomenclatureEntry.entries[key] = entry + +class PrintNomenclature(ListInset): + "Print all nomenclature entries" + + def process(self): + "Create the nomenclature." + self.name = Translator.translate('nomenclature') + self.partkey = PartKeyGenerator.forindex(self) + if not self.partkey: + return + self.contents = [TaggedText().constant(self.name, 'h1 class="nomenclature"')] + self.partkey.addtoclabel(self) + for key in self.sortdictionary(NomenclatureEntry.entries): + entry = NomenclatureEntry.entries[key] + contents = [entry, Constant(entry.symbol + u' ' + entry.description)] + text = TaggedText().complete(contents, 'div class="Nomenclated"', True) + self.contents.append(text) + +class PreListInset(object): + "Preprocess any container that contains a list inset." + + def preprocess(self, container): + "Preprocess a container, extract any list inset and return it." + listinsets = container.searchall(ListInset) + if len(listinsets) == 0: + return container + if len(container.contents) > 1: + return container + return listinsets[0] + +Processor.prestages += [PreListInset()] + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/ref/label.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/ref/label.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/ref/label.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/ref/label.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,142 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090218 +# eLyXer labels + +from elyxer.util.trace import Trace +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.gen.container import * +from elyxer.gen.styles import * +from elyxer.ref.link import * +from elyxer.proc.postprocess import * + + +class Label(Link): + "A label to be referenced" + + names = dict() + lastlayout = None + + def __init__(self): + Link.__init__(self) + self.lastnumbered = None + + def process(self): + "Process a label container." + key = self.getparameter('name') + self.create(' ', key) + self.lastnumbered = Label.lastlayout + + def create(self, text, key, type = 'Label'): + "Create the label for a given key." + self.key = key + self.complete(text, anchor = key, type = type) + Label.names[key] = self + if key in Reference.references: + for reference in Reference.references[key]: + reference.destination = self + return self + + def findpartkey(self): + "Get the part key for the latest numbered container seen." + numbered = self.numbered(self) + if numbered and numbered.partkey: + return numbered.partkey + return '' + + def numbered(self, container): + "Get the numbered container for the label." + if container.partkey: + return container + if not container.parent: + if self.lastnumbered: + return self.lastnumbered + return None + return self.numbered(container.parent) + + def __unicode__(self): + "Return a printable representation." + if not hasattr(self, 'key'): + return 'Unnamed label' + return 'Label ' + self.key + +class Reference(Link): + "A reference to a label." + + references = dict() + key = 'none' + + def process(self): + "Read the reference and set the arrow." + self.key = self.getparameter('reference') + if self.key in Label.names: + self.direction = u'↑' + label = Label.names[self.key] + else: + self.direction = u'↓' + label = Label().complete(' ', self.key, 'preref') + self.destination = label + self.formatcontents() + if not self.key in Reference.references: + Reference.references[self.key] = [] + Reference.references[self.key].append(self) + + def formatcontents(self): + "Format the reference contents." + formatkey = self.getparameter('LatexCommand') + if not formatkey: + formatkey = 'ref' + self.formatted = u'↕' + if formatkey in StyleConfig.referenceformats: + self.formatted = StyleConfig.referenceformats[formatkey] + else: + Trace.error('Unknown reference format ' + formatkey) + self.replace(u'↕', self.direction) + self.replace('#', '1') + self.replace('on-page', Translator.translate('on-page')) + partkey = self.destination.findpartkey() + # only if partkey and partkey.number are not null, send partkey.number + self.replace('@', partkey and partkey.number) + self.replace(u'¶', partkey and partkey.tocentry) + if not '$' in self.formatted or not partkey or not partkey.titlecontents: + # there is a $ left, but it should go away on preprocessing + self.contents = [Constant(self.formatted)] + return + pieces = self.formatted.split('$') + self.contents = [Constant(pieces[0])] + for piece in pieces[1:]: + self.contents += partkey.titlecontents + self.contents.append(Constant(piece)) + + def replace(self, key, value): + "Replace a key in the format template with a value." + if not key in self.formatted: + return + if not value: + value = '' + self.formatted = self.formatted.replace(key, value) + + def __unicode__(self): + "Return a printable representation." + return 'Reference ' + self.key + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/ref/link.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/ref/link.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/ref/link.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/ref/link.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,132 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090218 +# eLyXer links + +from elyxer.util.trace import Trace +from elyxer.util.translate import * +from elyxer.parse.parser import * +from elyxer.out.output import * +from elyxer.gen.container import * +from elyxer.gen.styles import * + + +class Link(Container): + "A link to another part of the document" + + anchor = None + url = None + type = None + page = None + target = None + destination = None + title = None + + def __init__(self): + "Initialize the link, add target if configured." + self.contents = [] + self.parser = InsetParser() + self.output = LinkOutput() + if Options.target: + self.target = Options.target + + def complete(self, text, anchor = None, url = None, type = None, title = None): + "Complete the link." + self.contents = [Constant(text)] + if anchor: + self.anchor = anchor + if url: + self.url = url + if type: + self.type = type + if title: + self.title = title + return self + + def computedestination(self): + "Use the destination link to fill in the destination URL." + if not self.destination: + return + self.url = '' + if self.destination.anchor: + self.url = '#' + self.destination.anchor + if self.destination.page: + self.url = self.destination.page + self.url + + def setmutualdestination(self, destination): + "Set another link as destination, and set its destination to this one." + self.destination = destination + destination.destination = self + + def __unicode__(self): + "Return a printable representation." + result = 'Link' + if self.anchor: + result += ' #' + self.anchor + if self.url: + result += ' to ' + self.url + return result + +class URL(Link): + "A clickable URL" + + def process(self): + "Read URL from elyxer.parameters" + target = self.escape(self.getparameter('target')) + self.url = target + type = self.getparameter('type') + if type: + self.url = self.escape(type) + target + name = self.getparameter('name') + if not name: + name = target + self.contents = [Constant(name)] + +class FlexURL(URL): + "A flexible URL" + + def process(self): + "Read URL from elyxer.contents" + self.url = self.extracttext() + +class LinkOutput(ContainerOutput): + "A link pointing to some destination" + "Or an anchor (destination)" + + def gethtml(self, link): + "Get the HTML code for the link" + type = link.__class__.__name__ + if link.type: + type = link.type + tag = 'a class="' + type + '"' + if link.anchor: + tag += ' name="' + link.anchor + '"' + if link.destination: + link.computedestination() + if link.url: + tag += ' href="' + link.url + '"' + if link.target: + tag += ' target="' + link.target + '"' + if link.title: + tag += ' title="' + link.title + '"' + return TaggedOutput().settag(tag).gethtml(link) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/ref/partkey.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/ref/partkey.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/ref/partkey.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/ref/partkey.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,223 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100705 +# eLyXer: key that identifies a given document part (chapter, section...). + +from elyxer.util.trace import Trace +from elyxer.util.options import * +from elyxer.util.translate import * +from elyxer.util.numbering import * +from elyxer.util.docparams import * +from elyxer.ref.label import * +from elyxer.gen.inset import * +from elyxer.out.template import * + + +class PartKey(object): + "A key to identify a given document part (chapter, section...)." + + partkey = None + tocentry = None + anchortext = None + number = None + filename = None + titlecontents = None + header = False + + def __init__(self): + self.level = 0 + + def createindex(self, partkey): + "Create a part key for an index page." + self.partkey = partkey + self.tocentry = partkey + self.filename = partkey + return self + + def createfloat(self, float): + "Create a part key for a float." + self.number = NumberGenerator.chaptered.generate(float.type) + self.partkey = Translator.translate('float-' + float.type) + self.number + if Options.notoclabels: + self.tocentry = self.number + else: + self.tocentry = self.partkey + self.readtitle(float) + return self + + def createsubfloat(self, number): + "Create the part key for a subfloat." + self.partkey = '(' + number + ')' + self.number = number + return self + + def createformula(self, number): + "Create the part key for a formula." + self.number = number + self.partkey = 'formula-' + number + self.tocentry = '(' + number + ')' + return self + + def createheader(self, headorfooter): + "Create the part key for a header or footer." + self.partkey = headorfooter + self.tocentry = None + self.header = True + return self + + def createanchor(self, partkey): + "Create an anchor for the page." + self.partkey = partkey + self.tocentry = partkey + self.header = True + return self + + def createmain(self): + "Create the part key for the main page." + self.partkey = '' + self.tocentry = DocumentTitle().getvalue() + return self + + def addtoclabel(self, container): + "Create the label for the TOC, and add it to the container." + labeltext = '' + if self.anchortext: + labeltext = self.anchortext + container.contents.insert(0, Separator(u' ')) + label = Label().create(labeltext, self.partkey, type='toc') + container.contents.insert(0, label) + + def readtitle(self, container): + "Read the title of the TOC entry." + shorttitles = container.searchall(ShortTitle) + if len(shorttitles) > 0: + self.titlecontents = [] + for shorttitle in shorttitles: + self.titlecontents += shorttitle.contents + return + extractor = ContainerExtractor(TOCConfig.extracttitle) + captions = container.searchall(Caption) + if len(captions) == 1: + self.titlecontents = extractor.extract(captions[0]) + return + self.titlecontents = extractor.extract(container) + + def __unicode__(self): + "Return a printable representation." + return 'Part key for ' + self.partkey + +class LayoutPartKey(PartKey): + "The part key for a layout." + + generator = NumberGenerator() + + def create(self, layout): + "Set the layout for which we are creating the part key." + self.processtype(layout.type) + self.readtitle(layout) + return self + + def processtype(self, type): + "Process the layout type." + self.level = self.generator.getlevel(type) + self.number = self.generator.generate(type) + anchortype = self.getanchortype(type) + self.partkey = 'toc-' + anchortype + '-' + self.number + self.tocentry = self.gettocentry(type) + self.filename = self.getfilename(type) + if self.generator.isnumbered(type): + if not self.tocentry: + self.tocentry = '' + else: + self.tocentry += ' ' + self.tocentry += self.number + self.anchortext = self.getanchortext(type) + + def getanchortype(self, type): + "Get the type for the anchor." + parttype = self.generator.getparttype(type) + if self.generator.isunordered(type): + parttype += '-' + return parttype + + def gettocentry(self, type): + "Get the entry for the TOC: Chapter, Section..." + if Options.notoclabels: + return '' + return Translator.translate(self.generator.getparttype(type)) + + def addtotocentry(self, text): + "Add some text to the tocentry; create if None." + if not self.tocentry: + self.tocentry = '' + self.tocentry += text + + def getanchortext(self, type): + "Get the text for the anchor given to a layout type." + if self.generator.isunique(type): + return self.tocentry + '.' + return self.number + + def getfilename(self, type): + "Get the filename to be used if splitpart is active." + if self.level == Options.splitpart and self.generator.isnumbered(type): + return self.number + if self.level <= Options.splitpart: + return self.partkey.replace('toc-', '') + return None + + def needspartkey(self, layout): + "Find out if a layout needs a part key." + if self.generator.isunique(layout.type): + return True + return self.generator.isinordered(layout.type) + + def __unicode__(self): + "Get a printable representation." + return 'Part key for layout ' + self.tocentry + +class PartKeyGenerator(object): + "Number a layout with the relevant attributes." + + partkeyed = [] + layoutpartkey = LayoutPartKey() + + def forlayout(cls, layout): + "Get the part key for a layout." + if layout.hasemptyoutput(): + return None + if not cls.layoutpartkey.needspartkey(layout): + return None + Label.lastlayout = layout + cls.partkeyed.append(layout) + return LayoutPartKey().create(layout) + + def forindex(cls, index): + "Get the part key for an index or nomenclature." + if index.hasemptyoutput(): + return None + cls.partkeyed.append(index) + return PartKey().createindex(index.name) + + forlayout = classmethod(forlayout) + forindex = classmethod(forindex) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/tex/texcode.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/tex/texcode.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/tex/texcode.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/tex/texcode.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,201 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20110105 +# eLyXer TeX (LyX ERT) parser. + +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.conf.config import * +from elyxer.parse.position import * +from elyxer.gen.layout import * +from elyxer.maths.formula import * +from elyxer.maths.command import * + + +class ERT(FirstWord): + "Evil Red Text: embedded TeX code." + "Considered as a first word for descriptions." + + def __init__(self): + self.parser = InsetParser() + self.output = ContentsOutput() + + def process(self): + "Process all TeX code, formulas, commands." + text = '' + separator = '' + for container in self.contents: + text += separator + container.extracttext() + separator = '\n' + pos = TextPosition(text) + pos.leavepending = True + code = TeXCode() + code.parse(pos) + self.contents = [code] + + def isempty(self): + "Find out if the ERT is empty or not." + if len(self.contents) == 0: + return True + if len(self.contents) > 1: + Trace.error('Unknown ERT length 2') + return False + texcode = self.contents[0] + return len(texcode.contents) == 0 + +class TeXCode(Container): + "A parser and processor for TeX code." + + texseparators = ['{', '\\', '}', '$', '%'] + replaced = BibTeXConfig.replaced + factory = FormulaFactory() + endinglist = EndingList() + + def __init__(self): + self.contents = [] + self.output = ContentsOutput() + + def parse(self, pos): + "Parse some TeX code." + self.parserecursive(pos) + if pos.leavepending: + self.endinglist.pickpending(pos) + + def findlaststring(self): + "Find the last string in the contents." + if len(self.contents) == 0: + return None + string = self.contents[-1] + if not isinstance(string, StringContainer): + return None + return string + + def add(self, piece): + "Add a new piece to the tag." + if isinstance(piece, basestring): + self.addtext(piece) + else: + self.contents.append(piece) + + def addtext(self, piece): + "Add a text string to the tag." + last = self.findlaststring() + if last: + last.string += piece + return + self.contents.append(Constant(piece)) + + def parserecursive(self, pos): + "Parse brackets or quotes recursively." + while not pos.finished(): + self.parsetext(pos) + if pos.finished(): + return + elif pos.checkfor('{'): + self.parseopenbracket(pos) + elif pos.checkfor('}'): + self.parseclosebracket(pos) + elif pos.checkfor('\\'): + self.parseescaped(pos) + elif pos.checkfor('$'): + self.parseformula(pos) + elif pos.checkfor('%'): + self.parsecomment(pos) + else: + pos.error('Unexpected character ' + pos.current()) + pos.skipcurrent() + + def parsetext(self, pos): + "Parse a bit of text, excluding separators and compressing spaces." + text = self.parsecompressingspace(pos) + if text == '': + return + for key in self.replaced: + if key in text: + text = text.replace(key, self.replaced[key]) + self.add(text) + + def parsecompressingspace(self, pos): + "Parse some text excluding value separators and compressing spaces." + parsed = '' + while not pos.finished(): + parsed += pos.glob(lambda: self.excludespaces(pos)) + if not pos.finished() and pos.current().isspace(): + parsed += ' ' + pos.skipspace() + else: + return parsed + return parsed + + def excludespaces(self, pos): + "Exclude value separators and spaces." + current = pos.current() + if current in self.texseparators: + return False + if current.isspace(): + return False + return True + + def parseescaped(self, pos): + "Parse an escaped string \\*." + if pos.checkfor('\\(') or pos.checkfor('\\['): + # start of formula commands + self.parseformula(pos) + return + if not self.factory.detecttype(FormulaCommand, pos): + pos.error('Not an escape sequence') + return + self.add(self.factory.parsetype(FormulaCommand, pos)) + + def parseopenbracket(self, pos): + "Parse a { bracket." + if not pos.checkskip('{'): + pos.error('Missing opening { bracket') + return + pos.pushending('}') + self.parserecursive(pos) + pos.popending('}') + + def parseclosebracket(self, pos): + "Parse a } bracket." + ending = self.endinglist.findending(pos) + if not ending: + Trace.error('Unexpected closing } bracket') + else: + self.endinglist.pop(pos) + if not pos.checkskip('}'): + pos.error('Missing closing } bracket') + return + + def parseformula(self, pos): + "Parse a whole formula." + formula = Formula().parse(pos) + self.add(formula) + + def parsecomment(self, pos): + "Parse a TeX comment: % to the end of the line." + pos.globexcluding('\n') + + def __unicode__(self): + "Return a printable representation." + return 'TeX code: ' + self.extracttext() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/clone.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/clone.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/clone.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/clone.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,84 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20091101 +# eLyXer object cloning + +from elyxer.util.trace import Trace + + +class Cloner(object): + "An object used to clone other objects." + + def clone(cls, original): + "Return an exact copy of an object." + "The original object must have an empty constructor." + return cls.create(original.__class__) + + def create(cls, type): + "Create an object of a given class." + clone = type.__new__(type) + clone.__init__() + return clone + + clone = classmethod(clone) + create = classmethod(create) + +class ContainerExtractor(object): + "A class to extract certain containers." + + def __init__(self, config): + "The config parameter is a map containing three lists: allowed, copied and extracted." + "Each of the three is a list of class names for containers." + "Allowed containers are included as is into the result." + "Cloned containers are cloned and placed into the result." + "Extracted containers are looked into." + "All other containers are silently ignored." + self.allowed = config['allowed'] + self.cloned = config['cloned'] + self.extracted = config['extracted'] + + def extract(self, container): + "Extract a group of selected containers from elyxer.a container." + list = [] + locate = lambda c: c.__class__.__name__ in self.allowed + self.cloned + recursive = lambda c: c.__class__.__name__ in self.extracted + process = lambda c: self.process(c, list) + container.recursivesearch(locate, recursive, process) + return list + + def process(self, container, list): + "Add allowed containers, clone cloned containers and add the clone." + name = container.__class__.__name__ + if name in self.allowed: + list.append(container) + elif name in self.cloned: + list.append(self.safeclone(container)) + else: + Trace.error('Unknown container class ' + name) + + def safeclone(self, container): + "Return a new container with contents only in a safe list, recursively." + clone = Cloner.clone(container) + clone.output = container.output + clone.contents = self.extract(container) + return clone + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/clparse.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/clparse.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/clparse.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/clparse.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,94 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090416 +# Command line option parser + +from elyxer.util.trace import * + + +class CommandLineParser(object): + "A parser for runtime options" + + def __init__(self, options): + self.options = options + + def parseoptions(self, args): + "Parse command line options" + if len(args) == 0: + return None + while len(args) > 0 and args[0].startswith('--'): + key, value = self.readoption(args) + if not key: + return 'Option ' + value + ' not recognized' + if not value: + return 'Option ' + key + ' needs a value' + setattr(self.options, key, value) + return None + + def readoption(self, args): + "Read the key and value for an option" + arg = args[0][2:] + del args[0] + if '=' in arg: + key = self.readequalskey(arg, args) + else: + key = arg.replace('-', '') + if not hasattr(self.options, key): + return None, key + current = getattr(self.options, key) + if isinstance(current, bool): + return key, True + # read value + if len(args) == 0: + return key, None + if args[0].startswith('"'): + initial = args[0] + del args[0] + return key, self.readquoted(args, initial) + value = args[0].decode('utf-8') + del args[0] + if isinstance(current, list): + current.append(value) + return key, current + return key, value + + def readquoted(self, args, initial): + "Read a value between quotes" + Trace.error('Oops') + value = initial[1:] + while len(args) > 0 and not args[0].endswith('"') and not args[0].startswith('--'): + Trace.error('Appending ' + args[0]) + value += ' ' + args[0] + del args[0] + if len(args) == 0 or args[0].startswith('--'): + return None + value += ' ' + args[0:-1] + return value + + def readequalskey(self, arg, args): + "Read a key using equals" + split = arg.split('=', 1) + key = split[0] + value = split[1] + args.insert(0, value) + return key + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/docparams.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/docparams.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/docparams.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/docparams.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,40 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100713 +# eLyXer: LyX document parameters + +from elyxer.util.trace import Trace + + +class DocumentParameters(object): + "Global parameters for the document." + + pdftitle = None + indentstandard = False + tocdepth = 10 + startinglevel = 0 + maxdepth = 10 + language = None + bibliography = None + outputchanges = False + displaymode = False + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/numbering.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/numbering.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/numbering.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/numbering.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,266 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090418 +# eLyXer number generator + +from elyxer.util.trace import Trace +from elyxer.util.translate import * +from elyxer.util.docparams import * +from elyxer.conf.config import * + + +class NumberCounter(object): + "A counter for numbers (by default)." + "The type can be changed to return letters, roman numbers..." + + name = None + value = None + mode = None + master = None + + letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + symbols = NumberingConfig.sequence['symbols'] + romannumerals = [ + ('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), + ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), + ('IV', 4), ('I', 1) + ] + + def __init__(self, name): + "Give a name to the counter." + self.name = name + + def setmode(self, mode): + "Set the counter mode. Can be changed at runtime." + self.mode = mode + return self + + def init(self, value): + "Set an initial value." + self.value = value + + def gettext(self): + "Get the next value as a text string." + return unicode(self.value) + + def getletter(self): + "Get the next value as a letter." + return self.getsequence(self.letters) + + def getsymbol(self): + "Get the next value as a symbol." + return self.getsequence(self.symbols) + + def getsequence(self, sequence): + "Get the next value from elyxer.a sequence." + return sequence[(self.value - 1) % len(sequence)] + + def getroman(self): + "Get the next value as a roman number." + result = '' + number = self.value + for numeral, value in self.romannumerals: + if number >= value: + result += numeral * (number / value) + number = number % value + return result + + def getvalue(self): + "Get the current value as configured in the current mode." + if not self.mode or self.mode in ['text', '1']: + return self.gettext() + if self.mode == 'A': + return self.getletter() + if self.mode == 'a': + return self.getletter().lower() + if self.mode == 'I': + return self.getroman() + if self.mode == '*': + return self.getsymbol() + Trace.error('Unknown counter mode ' + self.mode) + return self.gettext() + + def getnext(self): + "Increase the current value and get the next value as configured." + if not self.value: + self.value = 0 + self.value += 1 + return self.getvalue() + + def reset(self): + "Reset the counter." + self.value = 0 + + def __unicode__(self): + "Return a printable representation." + result = 'Counter ' + self.name + if self.mode: + result += ' in mode ' + self.mode + return result + +class DependentCounter(NumberCounter): + "A counter which depends on another one (the master)." + + def setmaster(self, master): + "Set the master counter." + self.master = master + self.last = self.master.getvalue() + return self + + def getnext(self): + "Increase or, if the master counter has changed, restart." + if self.last != self.master.getvalue(): + self.reset() + value = NumberCounter.getnext(self) + self.last = self.master.getvalue() + return value + + def getvalue(self): + "Get the value of the combined counter: master.dependent." + return self.master.getvalue() + '.' + NumberCounter.getvalue(self) + +class NumberGenerator(object): + "A number generator for unique sequences and hierarchical structures. Used in:" + " * ordered part numbers: Chapter 3, Section 5.3." + " * unique part numbers: Footnote 15, Bibliography cite [15]." + " * chaptered part numbers: Figure 3.15, Equation (8.3)." + " * unique roman part numbers: Part I, Book IV." + + chaptered = None + generator = None + + romanlayouts = [x.lower() for x in NumberingConfig.layouts['roman']] + orderedlayouts = [x.lower() for x in NumberingConfig.layouts['ordered']] + + counters = dict() + appendix = None + + def deasterisk(self, type): + "Remove the possible asterisk in a layout type." + return type.replace('*', '') + + def isunique(self, type): + "Find out if the layout type corresponds to a unique part." + return self.isroman(type) + + def isroman(self, type): + "Find out if the layout type should have roman numeration." + return self.deasterisk(type).lower() in self.romanlayouts + + def isinordered(self, type): + "Find out if the layout type corresponds to an (un)ordered part." + return self.deasterisk(type).lower() in self.orderedlayouts + + def isnumbered(self, type): + "Find out if the type for a layout corresponds to a numbered layout." + if '*' in type: + return False + if self.isroman(type): + return True + if not self.isinordered(type): + return False + if self.getlevel(type) > DocumentParameters.maxdepth: + return False + return True + + def isunordered(self, type): + "Find out if the type contains an asterisk, basically." + return '*' in type + + def getlevel(self, type): + "Get the level that corresponds to a layout type." + if self.isunique(type): + return 0 + if not self.isinordered(type): + Trace.error('Unknown layout type ' + type) + return 0 + type = self.deasterisk(type).lower() + level = self.orderedlayouts.index(type) + 1 + return level - DocumentParameters.startinglevel + + def getparttype(self, type): + "Obtain the type for the part: without the asterisk, " + "and switched to Appendix if necessary." + if NumberGenerator.appendix and self.getlevel(type) == 1: + return 'Appendix' + return self.deasterisk(type) + + def generate(self, type): + "Generate a number for a layout type." + "Unique part types such as Part or Book generate roman numbers: Part I." + "Ordered part types return dot-separated tuples: Chapter 5, Subsection 2.3.5." + "Everything else generates unique numbers: Bibliography [1]." + "Each invocation results in a new number." + return self.getcounter(type).getnext() + + def getcounter(self, type): + "Get the counter for the given type." + type = type.lower() + if not type in self.counters: + self.counters[type] = self.create(type) + return self.counters[type] + + def create(self, type): + "Create a counter for the given type." + if self.isnumbered(type) and self.getlevel(type) > 1: + index = self.orderedlayouts.index(type) + above = self.orderedlayouts[index - 1] + master = self.getcounter(above) + return self.createdependent(type, master) + counter = NumberCounter(type) + if self.isroman(type): + counter.setmode('I') + return counter + + def getdependentcounter(self, type, master): + "Get (or create) a counter of the given type that depends on another." + if not type in self.counters or not self.counters[type].master: + self.counters[type] = self.createdependent(type, master) + return self.counters[type] + + def createdependent(self, type, master): + "Create a dependent counter given the master." + return DependentCounter(type).setmaster(master) + + def startappendix(self): + "Start appendices here." + firsttype = self.orderedlayouts[DocumentParameters.startinglevel] + counter = self.getcounter(firsttype) + counter.setmode('A').reset() + NumberGenerator.appendix = True + +class ChapteredGenerator(NumberGenerator): + "Generate chaptered numbers, as in Chapter.Number." + "Used in equations, figures: Equation (5.3), figure 8.15." + + def generate(self, type): + "Generate a number which goes with first-level numbers (chapters). " + "For the article classes a unique number is generated." + if DocumentParameters.startinglevel > 0: + return NumberGenerator.generator.generate(type) + chapter = self.getcounter('Chapter') + return self.getdependentcounter(type, chapter).getnext() + + +NumberGenerator.chaptered = ChapteredGenerator() +NumberGenerator.generator = NumberGenerator() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/options.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/options.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/options.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/options.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,272 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090313 +# eLyXer runtime options + +import os.path +import sys +from elyxer.conf.config import * +from elyxer.util.trace import * +from elyxer.util.clparse import * + + +class Options(object): + "A set of runtime options" + + instance = None + + location = None + nocopy = False + copyright = False + debug = False + quiet = False + version = False + hardversion = False + versiondate = False + html = False + help = False + showlines = True + unicode = False + iso885915 = False + css = [] + title = None + directory = None + destdirectory = None + toc = False + toctarget = '' + tocfor = None + forceformat = None + lyxformat = False + target = None + splitpart = None + memory = True + lowmem = False + nobib = False + converter = 'imagemagick' + raw = False + jsmath = None + mathjax = None + nofooter = False + simplemath = False + template = None + noconvert = False + notoclabels = False + letterfoot = True + numberfoot = False + symbolfoot = False + hoverfoot = True + marginfoot = False + endfoot = False + supfoot = True + alignfoot = False + footnotes = None + imageformat = None + copyimages = False + googlecharts = False + embedcss = [] + + branches = dict() + + def parseoptions(self, args): + "Parse command line options" + Options.location = args[0] + del args[0] + parser = CommandLineParser(Options) + result = parser.parseoptions(args) + if result: + Trace.error(result) + self.usage() + self.processoptions() + + def processoptions(self): + "Process all options parsed." + if Options.help: + self.usage() + if Options.version: + self.showversion() + if Options.hardversion: + self.showhardversion() + if Options.versiondate: + self.showversiondate() + if Options.lyxformat: + self.showlyxformat() + if Options.splitpart: + try: + Options.splitpart = int(Options.splitpart) + if Options.splitpart <= 0: + Trace.error('--splitpart requires a number bigger than zero') + self.usage() + except: + Trace.error('--splitpart needs a numeric argument, not ' + Options.splitpart) + self.usage() + if Options.lowmem or Options.toc or Options.tocfor: + Options.memory = False + self.parsefootnotes() + if Options.forceformat and not Options.imageformat: + Options.imageformat = Options.forceformat + if Options.imageformat == 'copy': + Options.copyimages = True + if Options.css == []: + Options.css = ['http://elyxer.nongnu.org/lyx.css'] + if Options.html: + Options.simplemath = True + if Options.toc and not Options.tocfor: + Trace.error('Option --toc is deprecated; use --tocfor "page" instead') + Options.tocfor = Options.toctarget + if Options.nocopy: + Trace.error('Option --nocopy is deprecated; it is no longer needed') + if Options.jsmath: + Trace.error('Option --jsmath is deprecated; use --mathjax instead') + # set in Trace if necessary + for param in dir(Trace): + if param.endswith('mode'): + setattr(Trace, param, getattr(self, param[:-4])) + + def usage(self): + "Show correct usage" + Trace.error('Usage: ' + os.path.basename(Options.location) + ' [options] [filein] [fileout]') + Trace.error('Convert LyX input file "filein" to HTML file "fileout".') + Trace.error('If filein (or fileout) is not given use standard input (or output).') + Trace.error('Main program of the eLyXer package (http://elyxer.nongnu.org/).') + self.showoptions() + + def parsefootnotes(self): + "Parse footnotes options." + if not Options.footnotes: + return + Options.marginfoot = False + Options.letterfoot = False + Options.hoverfoot = False + options = Options.footnotes.split(',') + for option in options: + footoption = option + 'foot' + if hasattr(Options, footoption): + setattr(Options, footoption, True) + else: + Trace.error('Unknown footnotes option: ' + option) + if not Options.endfoot and not Options.marginfoot and not Options.hoverfoot: + Options.hoverfoot = True + if not Options.numberfoot and not Options.symbolfoot: + Options.letterfoot = True + + def showoptions(self): + "Show all possible options" + Trace.error(' Common options:') + Trace.error(' --help: show this online help') + Trace.error(' --quiet: disables all runtime messages') + Trace.error('') + Trace.error(' Advanced options:') + Trace.error(' --debug: enable debugging messages (for developers)') + Trace.error(' --version: show version number and release date') + Trace.error(' --lyxformat: return the highest LyX version supported') + Trace.error(' Options for HTML output:') + Trace.error(' --title "title": set the generated page title') + Trace.error(' --css "file.css": use a custom CSS file') + Trace.error(' --embedcss "file.css": embed styles from a CSS file into the output') + Trace.error(' --html: output HTML 4.0 instead of the default XHTML') + Trace.error(' --unicode: full Unicode output') + Trace.error(' --iso885915: output a document with ISO-8859-15 encoding') + Trace.error(' --nofooter: remove the footer "generated by eLyXer"') + Trace.error(' --simplemath: do not generate fancy math constructions') + Trace.error(' Options for image output:') + Trace.error(' --directory "img_dir": look for images in the specified directory') + Trace.error(' --destdirectory "dest": put converted images into this directory') + Trace.error(' --imageformat ".ext": image output format, or "copy" to copy images') + Trace.error(' --noconvert: do not convert images, use in original locations') + Trace.error(' --converter "inkscape": use an alternative program to convert images') + Trace.error(' Options for footnote display:') + Trace.error(' --numberfoot: mark footnotes with numbers instead of letters') + Trace.error(' --symbolfoot: mark footnotes with symbols (*, **...)') + Trace.error(' --hoverfoot: show footnotes as hovering text (default)') + Trace.error(' --marginfoot: show footnotes on the page margin') + Trace.error(' --endfoot: show footnotes at the end of the page') + Trace.error(' --supfoot: use superscript for footnote markers (default)') + Trace.error(' --alignfoot: use aligned text for footnote markers') + Trace.error(' --footnotes "options": specify several comma-separated footnotes options') + Trace.error(' Available options are: "number", "symbol", "hover", "margin", "end",') + Trace.error(' "sup", "align"') + Trace.error(' Advanced output options:') + Trace.error(' --splitpart "depth": split the resulting webpage at the given depth') + Trace.error(' --tocfor "page": generate a TOC that points to the given page') + Trace.error(' --target "frame": make all links point to the given frame') + Trace.error(' --notoclabels: omit the part labels in the TOC, such as Chapter') + Trace.error(' --lowmem: do the conversion on the fly (conserve memory)') + Trace.error(' --raw: generate HTML without header or footer.') + Trace.error(' --mathjax remote: use MathJax remotely to display equations') + Trace.error(' --mathjax "URL": use MathJax from the given URL to display equations') + Trace.error(' --googlecharts: use Google Charts to generate formula images') + Trace.error(' --template "file": use a template, put everything in ') + Trace.error(' --copyright: add a copyright notice at the bottom') + Trace.error(' Deprecated options:') + Trace.error(' --toc: (deprecated) create a table of contents') + Trace.error(' --toctarget "page": (deprecated) generate a TOC for the given page') + Trace.error(' --nocopy: (deprecated) maintained for backwards compatibility') + Trace.error(' --jsmath "URL": use jsMath from the given URL to display equations') + sys.exit() + + def showversion(self): + "Return the current eLyXer version string" + string = 'eLyXer version ' + GeneralConfig.version['number'] + string += ' (' + GeneralConfig.version['date'] + ')' + Trace.error(string) + sys.exit() + + def showhardversion(self): + "Return just the version string" + Trace.message(GeneralConfig.version['number']) + sys.exit() + + def showversiondate(self): + "Return just the version dte" + Trace.message(GeneralConfig.version['date']) + sys.exit() + + def showlyxformat(self): + "Return just the lyxformat parameter" + Trace.message(GeneralConfig.version['lyxformat']) + sys.exit() + +class BranchOptions(object): + "A set of options for a branch" + + def __init__(self, name): + self.name = name + self.options = {'color':'#ffffff'} + + def set(self, key, value): + "Set a branch option" + if not key.startswith(ContainerConfig.string['startcommand']): + Trace.error('Invalid branch option ' + key) + return + key = key.replace(ContainerConfig.string['startcommand'], '') + self.options[key] = value + + def isselected(self): + "Return if the branch is selected" + if not 'selected' in self.options: + return False + return self.options['selected'] == '1' + + def __unicode__(self): + "String representation" + return 'options for ' + self.name + ': ' + unicode(self.options) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/trace.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/trace.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/trace.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/trace.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,73 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090131 +# eLyXer trace library + +import sys + +class Trace(object): + "A tracing class" + + debugmode = False + quietmode = False + showlinesmode = False + + prefix = None + + def debug(cls, message): + "Show a debug message" + if not Trace.debugmode or Trace.quietmode: + return + Trace.show(message, sys.stdout) + + def message(cls, message): + "Show a trace message" + if Trace.quietmode: + return + if Trace.prefix and Trace.showlinesmode: + message = Trace.prefix + message + Trace.show(message, sys.stdout) + + def error(cls, message): + "Show an error message" + message = '* ' + message + if Trace.prefix and Trace.showlinesmode: + message = Trace.prefix + message + Trace.show(message, sys.stderr) + + def fatal(cls, message): + "Show an error message and terminate" + Trace.error('FATAL: ' + message) + exit(-1) + + def show(cls, message, channel): + "Show a message out of a channel" + if sys.version_info < (3,0): + message = message.encode('utf-8') + channel.write(message + '\n') + + debug = classmethod(debug) + message = classmethod(message) + error = classmethod(error) + fatal = classmethod(fatal) + show = classmethod(show) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/translate.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/translate.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/util/translate.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/util/translate.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,86 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100112 +# eLyXer translations and translation generation + +import gettext +from elyxer.util.trace import Trace +from elyxer.util.docparams import * +from elyxer.conf.config import * + + +class Translator(object): + "Reads the configuration file and tries to find a translation." + "Otherwise falls back to the messages in the config file." + + instance = None + + def translate(cls, key): + "Get the translated message for a key." + return cls.instance.getmessage(key) + + translate = classmethod(translate) + + def __init__(self): + self.translation = None + self.first = True + + def findtranslation(self): + "Find the translation for the document language." + self.langcodes = None + if not DocumentParameters.language: + Trace.error('No language in document') + return + if not DocumentParameters.language in TranslationConfig.languages: + Trace.error('Unknown language ' + DocumentParameters.language) + return + if TranslationConfig.languages[DocumentParameters.language] == 'en': + return + langcodes = [TranslationConfig.languages[DocumentParameters.language]] + try: + self.translation = gettext.translation('elyxer', None, langcodes) + except IOError: + Trace.error('No translation for ' + unicode(langcodes)) + + def getmessage(self, key): + "Get the translated message for the given key." + if self.first: + self.findtranslation() + self.first = False + message = self.getuntranslated(key) + if not self.translation: + return message + try: + message = self.translation.ugettext(message) + except IOError: + pass + return message + + def getuntranslated(self, key): + "Get the untranslated message." + if not key in TranslationConfig.constants: + Trace.error('Cannot translate ' + key) + return key + return TranslationConfig.constants[key] + +Translator.instance = Translator() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/elyxer/xtra/newfangle.py elyxer-1.2.5/forks/jras-elyxer/src/elyxer/xtra/newfangle.py --- elyxer-1.2.3/forks/jras-elyxer/src/elyxer/xtra/newfangle.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/elyxer/xtra/newfangle.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,218 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100201 +# LyX literate programming with the newfangle module. + +from elyxer.util.trace import Trace +from elyxer.util.numbering import * +from elyxer.gen.container import * +from elyxer.gen.layout import * +from elyxer.gen.inset import * +from elyxer.gen.float import * +from elyxer.ref.label import * + + +class NewfangledChunk(Layout): + "A chunk of literate programming." + + names = dict() + firsttime = True + + def process(self): + "Process the literate chunk." + self.output.tag = 'div class="chunk"' + self.type = 'chunk' + text = self.extracttext() + parts = text.split(',') + if len(parts) < 1: + Trace.error('Not enough parameters in ' + text) + return + self.name = parts[0] + self.number = self.order() + self.createlinks() + self.contents = [self.left, self.declaration(), self.right] + ChunkProcessor.lastchunk = self + + def order(self): + "Create the order number for the chunk." + return NumberGenerator.generator.generate('chunk') + + def createlinks(self): + "Create back and forward links." + self.leftlink = Link().complete(self.number, 'chunk:' + self.number, type='chunk') + self.left = TaggedText().complete([self.leftlink], 'span class="chunkleft"', False) + self.right = TaggedText().constant('', 'span class="chunkright"', False) + if not self.name in NewfangledChunk.names: + NewfangledChunk.names[self.name] = [] + else: + last = NewfangledChunk.names[self.name][-1] + forwardlink = Link().complete(self.number + u'→', 'chunkback:' + last.number, type='chunk') + backlink = Link().complete(u'←' + last.number + u' ', 'chunkforward:' + self.number, type='chunk') + forwardlink.setmutualdestination(backlink) + last.right.contents.append(forwardlink) + self.right.contents.append(backlink) + NewfangledChunk.names[self.name].append(self) + self.origin = self.createorigin() + if self.name in NewfangledChunkRef.references: + for ref in NewfangledChunkRef.references[self.name]: + self.linkorigin(ref.origin) + + def createorigin(self): + "Create a link that points to the chunks' origin." + link = Link() + self.linkorigin(link) + return link + + def linkorigin(self, link): + "Create a link to the origin." + start = NewfangledChunk.names[self.name][0] + link.complete(start.number, type='chunk') + link.destination = start.leftlink + link.computedestination() + + def declaration(self): + "Get the chunk declaration." + contents = [] + text = u'⟨' + self.name + '[' + unicode(len(NewfangledChunk.names[self.name])) + '] ' + contents.append(Constant(text)) + contents.append(self.origin) + text = '' + if NewfangledChunk.firsttime: + Listing.processor = ChunkProcessor() + NewfangledChunk.firsttime = False + text += u'⟩' + if len(NewfangledChunk.names[self.name]) > 1: + text += '+' + text += u'≡' + contents.append(Constant(text)) + return TaggedText().complete(contents, 'span class="chunkdecl"', True) + +class ChunkProcessor(object): + "A processor for listings that belong to chunks." + + lastchunk = None + counters = dict() + endcommand = '}' + chunkref = 'chunkref' + + def preprocess(self, listing): + "Preprocess a listing: set the starting counter." + if not ChunkProcessor.lastchunk: + return + name = ChunkProcessor.lastchunk.name + if not name in ChunkProcessor.counters: + ChunkProcessor.counters[name] = 0 + listing.counter = ChunkProcessor.counters[name] + for command, container, index in self.commandsinlisting(listing): + chunkref = self.getchunkref(command) + if chunkref: + self.insertchunkref(chunkref, container, index) + + def commandsinlisting(self, listing): + "Find all newfangle commands in a listing." + for container in listing.contents: + for index in range(len(container.contents) - 2): + if self.findinelement(container, index): + third = container.contents[index + 2].string + end = third.index(NewfangleConfig.constants['endmark']) + command = third[:end] + lenstart = len(NewfangleConfig.constants['startmark']) + container.contents[index].string = container.contents[index].string[:-lenstart] + del container.contents[index + 1] + container.contents[index + 1].string = third[end + len(NewfangleConfig.constants['endmark']):] + yield command, container, index + + def findinelement(self, container, index): + "Find a newfangle command in an element." + for i in range(2): + if not isinstance(container.contents[index + i], StringContainer): + return False + first = container.contents[index].string + second = container.contents[index + 1].string + third = container.contents[index + 2].string + if not first.endswith(NewfangleConfig.constants['startmark']): + return False + if second != NewfangleConfig.constants['startcommand']: + return False + if not NewfangleConfig.constants['endmark'] in third: + return False + return True + + def getchunkref(self, command): + "Get the contents of a chunkref command, if present." + if not command.startswith(NewfangleConfig.constants['chunkref']): + return None + if not NewfangleConfig.constants['endcommand'] in command: + return None + start = len(NewfangleConfig.constants['chunkref']) + end = command.index(NewfangleConfig.constants['endcommand']) + return command[start:end] + + def insertchunkref(self, ref, container, index): + "Insert a chunkref after the given index at the given container." + chunkref = NewfangledChunkRef().complete(ref) + container.contents.insert(index + 1, chunkref) + + def postprocess(self, listing): + "Postprocess a listing: store the ending counter for next chunk." + if not ChunkProcessor.lastchunk: + return + ChunkProcessor.counters[ChunkProcessor.lastchunk.name] = listing.counter + +class NewfangledChunkRef(Inset): + "A reference to a chunk." + + references = dict() + + def process(self): + "Show the reference." + self.output.tag = 'span class="chunkref"' + self.ref = self.extracttext() + self.addbits() + + def complete(self, ref): + "Complete the reference to the given string." + self.output = ContentsOutput() + self.ref = ref + self.contents = [Constant(self.ref)] + self.addbits() + return self + + def addbits(self): + "Add the bits to the reference." + if not self.ref in NewfangledChunkRef.references: + NewfangledChunkRef.references[self.ref] = [] + NewfangledChunkRef.references[self.ref].append(self) + if self.ref in NewfangledChunk.names: + start = NewfangledChunk.names[self.ref][0] + self.origin = start.createorigin() + else: + self.origin = Link() + self.contents.insert(0, Constant(u'⟨')) + self.contents.append(Constant(' ')) + self.contents.append(self.origin) + self.contents.append(Constant(u'⟩')) + + def __unicode__(self): + "Return a printable representation." + return 'Reference to chunk ' + self.ref + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/exportconfig.py elyxer-1.2.5/forks/jras-elyxer/src/exportconfig.py --- elyxer-1.2.3/forks/jras-elyxer/src/exportconfig.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/exportconfig.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,171 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090504 +# eLyXer configuration manipulation + +import sys +import datetime +from elyxer.util.trace import Trace +from elyxer.util.clparse import * +from elyxer.conf.fileconfig import * +from elyxer.conf.importconfig import * + + +class Config(object): + "A configuration file" + + cfg = 'conf/base.cfg' + py = 'elyxer/conf/config.py' + po = 'conf/elyxer.pot' + addcfg = None + importcfg = None + importcsv = None + importunimath = None + help = False + + def run(self, args): + "Parse command line options and run export to cfg or to py" + parser = CommandLineParser(Config) + error = parser.parseoptions(args) + if error: + Trace.error(error) + self.usage() + elif Config.help: + self.usage() + option = self.parseoption(args) + if not option: + Trace.error('Choose cfg, py or po') + self.usage() + if option == 'cfg': + self.exportcfg() + return + elif option == 'py': + self.exportpy() + return + elif option == 'po': + self.exportpo() + else: + Trace.error('Unknown option ' + option) + self.usage() + + def usage(self): + "Show tool usage" + Trace.error('Usage: exportconfig.py [options] [cfg|py|po]') + Trace.error(' cfg: export to text configuration file') + Trace.error(' py: export to python file') + Trace.error(' po: export elyxer.pot internationalization file') + Trace.error(' options:') + Trace.error(' --cfg base.cfg: choose base config file') + Trace.error(' --addcfg add.cfg: load additional config file') + Trace.error(' --py config.py: choose Python config file') + Trace.error(' --importcfg unicodesymbols: import LyX unicode symbols file') + Trace.error(' --importcsv unicodecsv: import a file of "\command,unicode" pairs') + Trace.error(' --importunimath unimath.txt: import a file in unimath format') + Trace.error(' (See http://milde.users.sourceforge.net/LUCR/Math/)') + exit() + + def read(self): + "Read from configuration file" + reader = ConfigReader(Config.cfg).parse() + if Config.addcfg: + addreader = ConfigReader(Config.addcfg).parse() + self.mix(reader, addreader) + if Config.importcfg: + addreader = ImportCommands(Config.importcfg).parse() + self.mix(reader, addreader) + if Config.importcsv: + addreader = ImportCsv(Config.importcsv).parse() + self.mix(reader, addreader) + if Config.importunimath: + addreader = ImportUnimath(Config.importunimath).parse() + self.mix(reader, addreader) + reader.objects['GeneralConfig.version']['date'] = datetime.date.today().isoformat() + return reader + + def exportcfg(self): + "Export configuration to a cfg file" + linewriter = LineWriter(Config.cfg) + writer = ConfigWriter(linewriter) + configs = [globals()[x] for x in dir(elyxer.conf.config) if x.endswith('Config')] + writer.writeall(configs) + + def exportpy(self): + "Export configuration as a Python file" + reader = self.read() + linewriter = LineWriter(Config.py) + translator = ConfigToPython(linewriter) + translator.write(reader.objects) + + def exportpo(self): + "Export configuration as a gettext .po file." + reader = self.read() + writer = LineWriter(Config.po) + export = TranslationExport(writer) + export.export(reader.objects['TranslationConfig.constants']) + + def parseoption(self, args): + "Parse the next option" + if len(args) == 0: + return None + option = args[0] + del args[0] + return option + + def mix(self, reader, addreader): + "Mix two configuration files" + Trace.message('--- new content follows ---') + for name, object in addreader.objects.iteritems(): + Trace.message('') + Trace.message('[' + name + ']') + equiv = reader.objects[name] + for key, value in object.iteritems(): + if not key in equiv: + equiv[key] = value + Trace.message(key + ':' + unicode(value)) + +class TranslationExport(object): + "Export the translation to a file." + + def __init__(self, writer): + self.writer = writer + + def export(self, constants): + "Export the translation constants as a .po file." + self.writer.writeline('# eLyXer internationalization file.') + self.writer.writeline('# Created on ' + datetime.date.today().isoformat()) + self.writer.writeline(u'# Contact: Alex Fernandez ') + self.writer.writeline(u'# http://elyxer.nongnu.org/') + self.writer.writeline('# This file is distributed under the same license as the eLyXer package.') + self.writer.writeline('# (C) 2010 Alex Fernandez .') + self.writer.writeline('#') + self.writer.writeline('') + for key, message in constants.iteritems(): + self.writer.writeline('') + self.writer.writeline('#: ' + key) + self.writer.writeline('msgid "' + message + '"') + self.writer.writeline('msgstr "' + message + '"') + self.writer.close() + +config = Config() +del sys.argv[0] +config.run(sys.argv) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/freebsd-license elyxer-1.2.5/forks/jras-elyxer/src/freebsd-license --- elyxer-1.2.3/forks/jras-elyxer/src/freebsd-license 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/freebsd-license 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,18 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# math2html: convert LaTeX equations to HTML output. +# +# Copyright (C) 2009-2011 Alex Fernández +# +# Released under the terms of the `2-Clause BSD license'_, in short: +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +# This file is offered as-is, without any warranty. +# +# .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause + +# Based on eLyXer: convert LyX source files to HTML output. +# http://elyxer.nongnu.org/ + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/gpl-license elyxer-1.2.5/forks/jras-elyxer/src/gpl-license --- elyxer-1.2.3/forks/jras-elyxer/src/gpl-license 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/gpl-license 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,20 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009-2010 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/javatopy.py elyxer-1.2.5/forks/jras-elyxer/src/javatopy.py --- elyxer-1.2.3/forks/jras-elyxer/src/javatopy.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/javatopy.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,61 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20091226 +# Port a Java program to a Python equivalent. Used to port MathToWeb. + +import sys +import os.path +from elyxer.io.fileline import * +from elyxer.parse.position import * +from elyxer.util.trace import Trace +from jtp.porter import * + + +def readargs(args): + "Read arguments from the command line" + del args[0] + if len(args) == 0: + usage() + return + inputfile = args[0] + del args[0] + outputfile = os.path.splitext(inputfile)[0].lower() + '.py' + if len(args) > 0: + outputfile = args[0] + del args[0] + if len(args) > 0: + usage() + return + return inputfile, outputfile + +def usage(): + Trace.error('Usage: javatopy.py filein.java [fileout.py]') + return + +inputfile, outputfile = readargs(sys.argv) +Trace.debugmode = True +Trace.showlinesmode = True +if inputfile: + JavaPorter().topy(FilePosition(inputfile), LineWriter(outputfile)) + Trace.message('Conversion done, running ' + outputfile) + os.system('python ' + outputfile) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/jtp/exportconfig.sh elyxer-1.2.5/forks/jras-elyxer/src/jtp/exportconfig.sh --- elyxer-1.2.3/forks/jras-elyxer/src/jtp/exportconfig.sh 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/jtp/exportconfig.sh 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,5 @@ +#!/bin/bash +# Alex 2010-03-14: export configuration for JavaToPy + +./exportconfig.py --cfg conf/jtp.cfg --py conf/javatopyconf.py py + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/jtp/grammar.py elyxer-1.2.5/forks/jras-elyxer/src/jtp/grammar.py --- elyxer-1.2.3/forks/jras-elyxer/src/jtp/grammar.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/jtp/grammar.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,378 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20100311 +# Read a generic grammar. + +from elyxer.util.trace import Trace +from elyxer.util.clone import * +from elyxer.conf.javatopyconf import * +from elyxer.parse.position import * + + +class Piece(object): + "Represents a piece (word, bracket... of any type) in a grammar." + + def __init__(self): + "Initialize common variables." + self.closed = False + self.valid = True + + def match(self, tok): + "Match the piece against the current token and return the match." + Trace.error('Unmatchable piece ' + unicode(self) + ' in ' + unicode(tok)) + return None + + def fitnext(self, token): + "Try to fit the next token and return the corresponding declaration." + Trace.error('Unimplemented method: fit()') + +class ConstantWord(Piece): + "Represents a constant word in a grammar." + + def __init__(self, constant): + "Initialize the word with the constant." + self.constant = constant + + def match(self, tok): + "Just match the current token against the constant." + if tok.current() == self.constant: + tok.next() + return self + return None + + def fitnext(self, token): + "Try to fit the next token." + self.closed = True + if token != self.constant: + self.valid = False + return None + return self + + def __unicode__(self): + "Printable representation." + return '\'' + self.constant + '\'' + +class IdentifierWord(Piece): + "A word made of alphanumeric and _ characters." + + def __init__(self): + "Just create an empty word." + self.word = None + + def set(self, word): + self.word = word + return self + + def match(self, tok): + "Match the current token and store in the template." + if tok.iscurrentidentifier(): + identifier = IdentifierWord().set(tok.current()) + tok.next() + return identifier + return None + + def fitnext(self, token): + "Try to fit the next token." + self.closed = True + if token.iscurrentidentifier(): + return IdentifierWord().set(tok.current()) + return None + +class Bracket(Piece): + "A bracket consisting of other words (repeated, conditional)." + + quantified = dict() + + def __init__(self): + "Create an empty bracket." + self.declaration = None + self.quantifier = None + + def create(self, declaration, quantifier): + "Create the bracket for a given declaration." + self.declaration = declaration + self.quantifier = quantifier + return self + + def parse(self, pos): + "Parse the bracket." + pos.pushending(']') + declaration = Declaration('bracket').parse(pos) + pos.popending(']') + quantifier = pos.skipcurrent() + if not quantifier in self.quantified: + Trace.error('Unknown quantifier ' + quantifier) + return self + bracket = Cloner.clone(self.quantified[quantifier]).create(declaration, quantifier) + Trace.debug('Bracket: ' + unicode(bracket)) + return bracket + + def __unicode__(self): + "Printable representation." + return '[' + unicode(self.declaration) + ']' + self.quantifier + +class MultipleBracket(Bracket): + "A bracket present zero or more times (quantifier *)." + + def match(self, tok): + "Match the bracket zero or more times." + decl = Declaration('*') + result = self.declaration.match(tok) + while result != None: + decl.pieces.append(result) + result = self.declaration.match(tok) + return decl + +class RepeatedBracket(Bracket): + "A bracket present one or more times (quantifier +)." + + def match(self, tok): + "Match the bracket at least one time." + decl = Declaration('*') + result = self.declaration.match(tok) + if not result: + return None + while result != None: + decl.pieces.append(result) + result = self.declaration.match(tok) + return decl + +class ConditionalBracket(Bracket): + "A bracket which may or may not be present (quantifier ?)." + + def match(self, tok): + "Match the bracket, or not." + decl = Declaration('?') + result = self.declaration.match(tok) + if result: + decl.pieces.append(result) + return decl + + def fitnext(self, token): + "Try to fit the next token." + result = self.declaration.fitnext(token) + decl = None + if not self.declaration.valid: + self.closed = True + elif self.declaration.closed: + self.closed = True + if result: + return result + if token != self.constant: + self.valid = False + return None + return self + +Bracket.quantified = { + '*': MultipleBracket(), '+': RepeatedBracket(), '?': ConditionalBracket() +} + +class Alternatives(Piece): + "A group of alternatives to parse." + + def __init__(self): + "Create an empty set of alternatives." + self.alternatives = [] + + def add(self, pieces): + "Add a new set of alternative pieces." + alternative = Declaration('#' + unicode(len(self.alternatives))) + alternative.pieces = pieces + self.alternatives.append(alternative) + Trace.debug('Alternatives: ' + unicode(self)) + return self + + def match(self, tok): + "Match any of the alternatives." + for alternative in self.alternatives: + result = alternative.match(tok) + if result: + return result + return None + + def __unicode__(self): + "Printable representation." + if len(self.alternatives) == 0: + return 'Empty alternatives' + result = '' + for alternative in self.alternatives: + result += ' | ' + unicode(alternative) + return result[3:] + +class Declaration(Piece): + "A grammar declaration consisting of several pieces." + + notsymbol = '[]_ |$' + pieces = [] + + def __init__(self, key): + self.key = key + self.pieces = [] + + def parse(self, pos): + "Parse the given position." + while not pos.finished(): + if pos.checkskip('$'): + self.parsevariable(pos) + elif pos.checkskip('['): + self.parsebracket(pos) + elif pos.checkidentifier(): + self.parseidentifier(pos) + elif pos.checkskip(' '): + # ignore blank characters + pass + elif pos.checkskip('|'): + self.parsealternative(pos) + else: + self.parsesymbol(pos) + self.checkalternatives() + return self + + def parsevariable(self, pos): + "Parse a variable." + if pos.checkskip('$'): + self.pieces.append(IdentifierWord()) + return + name = '$' + pos.globidentifier() + if not name in Grammar.instance.declarations: + Trace.error('Unknown variable ' + name) + return + Trace.debug('New variable ' + name) + self.pieces.append(Grammar.instance.declarations[name]) + + def parsebracket(self, pos): + "Parse a bracket and the quantifier (*+?)." + self.pieces.append(Bracket().parse(pos)) + + def parseidentifier(self, pos): + "Parse a constant identifier value." + self.addconstant(pos.globidentifier()) + + def parsealternative(self, pos): + "Parse an alternative in a group." + if len(self.pieces) == 0: + Trace.error('Empty beginning alternative at ' + pos.identifier()) + return + if self.checkalternatives(): + return + alt = Alternatives().add(self.pieces) + self.pieces = [alt] + + def checkalternatives(self): + "Check if there is a set of alternatives active, and add everything there." + if len(self.pieces) == 0 or not isinstance(self.pieces[0], Alternatives): + return False + if len(self.pieces) == 1: + Trace.error('Empty alternative') + return + self.pieces[0].add(self.pieces[1:]) + self.pieces = [self.pieces[0]] + return True + + def parsesymbol(self, pos): + "Parse a symbol." + symbol = '' + while self.issymbol(pos): + symbol += pos.skipcurrent() + if symbol == '': + symbol += pos.skipcurrent() + Trace.error('Empty symbol; acquiring ' + symbol) + self.addconstant(symbol) + + def issymbol(self, pos): + "Find out if the current character belongs to a larger symbol." + if pos.finished(): + return False + if pos.current() in self.notsymbol: + return False + if pos.checkidentifier(): + return False + return True + + def addconstant(self, constant): + "Add a constant value." + if constant in Grammar.instance.constants: + Trace.error('Repeated constant ' + constant) + return + Trace.debug('New constant: ' + constant) + self.pieces.append(ConstantWord(constant)) + + def match(self, tok): + "Match the declaration against a tokenizer." + decl = Declaration(self.key) + state = tok.mark() + for piece in self.pieces: + Trace.debug('Matching ' + tok.current() + ' against ' + unicode(piece)) + result = piece.match(tok) + if not result: + Trace.error('Mismatch of ' + tok.current() + ' against ' + unicode(piece)) + tok.revert(state) + return None + decl.pieces.append(result) + return decl + + def __unicode__(self): + "Printable representation." + if len(self.pieces) == 0: + return u'❲empty❳' + result = '' + for piece in self.pieces: + if isinstance(piece, Declaration): + pieceresult = piece.key + else: + pieceresult = unicode(piece) + result += ', ' + pieceresult + return u'❲' + result[2:] + u'❳' + +class Grammar(object): + "Read a complete grammar into memory." + + instance = None + + def __init__(self): + "Read all declarations into variables." + self.variables = dict() + self.declarations = dict() + self.constants = dict() + + def process(self): + "Process the grammar and create all necessary structures." + for key in JavaToPyConfig.declarations: + self.variables[key] = JavaToPyConfig.declarations[key] + for key in self.variables: + self.declarations[key] = Declaration(key) + for key in self.variables: + Trace.debug('Interpreting ' + self.variables[key]) + pos = TextPosition(self.variables[key]) + self.declarations[key].parse(pos) + + def parse(self, tok): + "Parse a whole file using a tokenizer." + tok.next() + filedecl = self.declarations['$file'] + result = filedecl.match(tok) + if not result: + Trace.error('Actual file does not match $file.') + return + +Grammar.instance = Grammar() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/jtp/parser.py elyxer-1.2.5/forks/jras-elyxer/src/jtp/parser.py --- elyxer-1.2.3/forks/jras-elyxer/src/jtp/parser.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/jtp/parser.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,360 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20091226 +# Port a Java program to a Python equivalent. Used to port MathToWeb. + +from elyxer.util.trace import Trace + + +class StatementParser(object): + "A parser for a statement." + + def __init__(self, chooser): + self.chooser = chooser + + def checkvariable(self, token): + "Check if the token is a valid variable name." + for char in token: + if not Tokenizer.isalphanumeric(char): + return False + return True + + def autoincrease(self, tok): + "Process a Java autoincrease (++)." + variable = tok.autoincreases.pop() + return variable + ' += 1' + + def autodecrease(self, tok): + "Process a Java autodecrease (--)." + variable = tok.autodecreases.pop() + return variable + ' -= 1' + + def translateclass(self, tok): + "Translate a class definition." + tok.checknext('class') + name = tok.next() + tok.inclass = name + inheritance = '' + while tok.peek() != '{': + inheritance += ' ' + tok.next() + Trace.error('Unused inheritance ' + inheritance) + return 'class ' + name + '(object):' + + def translateinternal(self, tok): + "Translate an internal element (attribute or method)." + token = self.membertoken(tok) + name = self.membertoken(tok) + if token == tok.inclass and name == '(': + # constructor + return self.translatemethod(token, tok) + after = tok.next() + while after == '[': + tok.checknext(']') + after = tok.next() + if after == ';': + return self.translateemptyattribute(name) + if after == '(': + return self.translatemethod(name, tok) + if after != '=': + Trace.error('Weird token after member: ' + token + ' ' + name + ' ' + after) + return self.translateattribute(name, tok) + + def membertoken(self, tok): + "Get the next member token, excluding static, []..." + token = tok.next() + if token in ['static', 'synchronized', 'final']: + return self.membertoken(tok) + if token == '[': + tok.checknext(']') + return self.membertoken(tok) + return token + + def translatemethod(self, name, tok): + "Translate a class method." + tok.inmethod = name + pars = self.listparameters(tok) + self.expectblock(tok) + parlist = ', ' + for par in pars: + if not ' ' in par: + Trace.error('Invalid parameter declaration: ' + par) + else: + newpar = par.strip().split(' ', 1)[1] + parlist += newpar + ', ' + parlist = parlist[:-2] + return '\ndef ' + name + '(self' + parlist + '):' + + def translateemptyattribute(self, name): + "Translate an empty attribute definition." + return name + ' = None' + + def translateattribute(self, name, tok): + "Translate a class attribute." + return name + ' = ' + self.parseupto(';', tok) + + def listparameters(self, tok): + "Parse the parameters of a method definition, return them as a list." + params = self.parseinparens(tok)[1:-1] + pars = params.split(',') + if pars[0] == '': + return [] + return pars + + def processtoken(self, tok): + "Process a single token." + token = tok.current() + if token in self.chooser.javatokens: + function = getattr(self.chooser, self.chooser.javatokens[token]) + return function(tok) + if token in tok.javasymbols: + return self.processsymbol(tok) + return token + + def processsymbol(self, tok): + "Process a single java symbol." + if tok.current() == '"' or tok.current() == '\'': + return self.parsequoted(tok.current(), tok) + if tok.current() == '{': + return '{' + self.parseupto('}', tok) + '}' + if tok.current() == '}': + Trace.error('Erroneously closing }') + return '' + if tok.current() == '(': + result = self.parseinparens(tok) + return result + if tok.current() == '[': + result = self.parseinsquare(tok) + return result + if tok.current() == ')': + Trace.error('Erroneously closing )') + return ')' + if tok.current() in tok.modified: + return tok.modified[tok.current()] + return tok.current() + + def parsequoted(self, quote, tok): + "Parse a quoted sentence, with variable quotes." + result = tok.current() + tok.pos.globincluding(quote) + while result.endswith('\\' + quote) and not result.endswith('\\\\' + quote): + result += tok.pos.globincluding(quote) + return result + + def parseparameters(self, tok): + "Parse the parameters to a method invocation." + result = '(' + while tok.current() != ')': + param = self.parsevalue(tok, [',',')']) + result += param + ', ' + if len(result) == 1: + return '()' + return result[:-2] + ')' + + def parseparens(self, tok): + "Parse a couple of () and the contents inside." + tok.checknext('(') + return self.parseinparens(tok) + + def parseinparens(self, tok): + "Parse the contents inside ()." + contents = self.parseupto(')', tok) + if '{' in contents: + # anonymous function; ignore + return '()' + if Tokenizer.isalphanumeric(contents): + if Tokenizer.isalphanumeric(tok.peek()): + # type cast; ignore + return '' + result = '(' + contents + ')' + return result + result = self.parseinbrackets('(', ')', tok) + + def parseinsquare(self, tok): + "Parse the contents inside []." + return self.parseinbrackets('[', ']', tok) + + def parseinbrackets(self, opening, closing, tok): + "Parse the contents in any kind of brackets." + result = self.parseupto(closing, tok) + return opening + result + closing + + def parsecondition(self, tok, ending): + "Parse a condition given the ending token." + return self.parseupto(ending, tok) + + def parsevalue(self, tok, endings = [';']): + "Parse a value (to be assigned or returned)." + return self.parsetoendings(tok, endings) + + def parseinvocation(self, tok, previous = None): + "Parse a class or method invocation." + result = previous or '' + name = tok.current() + tok.checknext('(') + params = self.parseparameters(tok) + result += name + params + if tok.peek() != '.': + return result + tok.checknext('.') + return self.parseinvocation(tok, result + '.') + + def parseupto(self, ending, tok): + "Parse the tokenizer up to the supplied ending." + return self.parsetoendings(tok, [ending]) + + def parsetoendings(self, tok, endings): + "Parse the tokenizer up to a number of endings." + result = '' + tok.next() + while not tok.current() in endings: + processed = self.processtoken(tok) + if processed == '++': + processed = '+ 1' + Trace.debug('Increasing ' + result + ' for endings: ' + unicode(endings)) + tok.autoincreases.append(result) + if processed == '--': + Trace.debug('Decreasing ' + result) + processed = '- 1' + tok.autodecreases.append(result) + if processed != '.' and not result.endswith('.'): + processed = ' ' + processed + result += processed + if not tok.current in endings: + tok.next() + if len(result) > 0: + result = result[1:] + Trace.debug('Left after ' + tok.current() + ', endings ' + unicode(endings) + ', result: ' + result) + return result + + def expectblock(self, tok): + "Mark that a block is to be expected." + tok.depth += 1 + tok.waitingforblock = True + +class Tokenizer(object): + "Tokenizes a parse position." + + unmodified = [ + '&', '|', '=', '(', ')', '{', '}', '.', '+', '-', '"', ',', '/', + '*', '<', '>', '\'', '[', ']', '%', ';', + '!=','<=','>=', '==', '++', '--' + ] + modified = { + '&&':'and', '||':'or', '!':'not' + } + comments = ['//', '/*'] + javasymbols = comments + unmodified + modified.keys() + + def __init__(self, pos): + self.pos = pos + self.currenttoken = None + self.peeked = None + self.autoincreases = [] + self.autodecreases = [] + self.depth = 0 + self.waitingforblock = False + self.inclass = None + self.inmethod = None + self.variables = ['this'] + self.infor = 0 + + def next(self): + "Get the next single token, and store it for current()." + if self.peeked: + self.currenttoken = self.peeked + self.peeked = None + else: + self.currenttoken = self.extractwithoutcomments() + return self.currenttoken + + def checknext(self, token): + "Check that the next token is the parameter." + self.next() + if self.currenttoken != token: + Trace.error('Expected token ' + token + ', found ' + self.currenttoken) + return False + return True + + def extractwithoutcomments(self): + "Get the next single token without comments." + token = self.extracttoken() + while token in self.comments: + self.skipcomment(token) + token = self.extracttoken() + self.pos.skipspace() + return token + + def extracttoken(self): + "Extract the next token." + if self.finished(): + return None + if self.pos.checkidentifier(): + return self.pos.globidentifier() + if self.pos.current() in self.javasymbols: + result = self.pos.skipcurrent() + while result + self.pos.current() in self.javasymbols: + result += self.pos.skipcurrent() + return result + current = self.pos.skipcurrent() + raise Exception('Unrecognized character: ' + current) + + def current(self): + "Get the current token." + return self.currenttoken + + def finished(self): + "Find out if the tokenizer has finished tokenizing." + self.pos.skipspace() + return self.pos.finished() + + def iscurrentidentifier(self): + "Return if the current token is an identifier (alphanumeric or _ characters)." + if self.currenttoken.replace('_', '').isalnum(): + return True + return False + + def skipcomment(self, token): + "Skip over a comment." + if token == '//': + comment = self.pos.globexcluding('\n') + return + if token == '/*': + while not self.pos.checkskip('/'): + comment = self.pos.globincluding('*') + return + Trace.error('Unknown comment type ' + token) + + def peek(self): + "Look ahead at the next token, without advancing the parse position." + token = self.extractwithoutcomments() + self.peeked = token + return token + + def mark(self): + "Mark the current state and return a handle." + Trace.error('Unimplemented mark()') + return None + + def revert(self, state): + "Revert to a previous state as returned by mark()." + Trace.error('Unimplemented revert()') + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/jtp/porter.py elyxer-1.2.5/forks/jras-elyxer/src/jtp/porter.py --- elyxer-1.2.3/forks/jras-elyxer/src/jtp/porter.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/jtp/porter.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,293 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20091226 +# Port a Java program to a Python equivalent. Used to port MathToWeb. + +from elyxer.jtp.parser import * +from elyxer.jtp.grammar import * +from elyxer.util.trace import Trace + + +class JavaPorter(object): + "Ports a Java file." + + def __init__(self): + Grammar.instance.process() + self.chooser = StatementChooser() + + def topy(self, filepos, writer): + "Port the Java input file to Python." + tok = Tokenizer(filepos) + Grammar.instance.parse(tok) + return + while not tok.finished(): + statement = self.nextstatement(tok) + writer.writeline(statement) + writer.close() + + def nextstatement(self, tok): + "Return the next statement." + statement = None + while not statement and not tok.finished(): + indent = self.chooser.getindent(tok) + statement = self.parsestatement(tok) + if not statement: + return '' + Trace.debug('Statement: ' + statement.strip()) + if statement.startswith('\n'): + # displace newline + return '\n' + indent + statement[1:] + return indent + statement + + def parsestatement(self, tok): + "Parse a single statement." + pending = self.chooser.pendingstatement(tok) + if pending: + return pending + return self.chooser.choose(tok) + +class StatementChooser(object): + "Chooses the next statement to parse, according to the first token." + + starttokens = { + 'if':'conditionblock', 'catch':'parametersblock', 'import':'ignorestatement', + 'public':'classormember', 'protected':'classormember', 'private':'classormember', + 'class':'parseclass', 'else':'elseblock', 'try':'tryblock', + 'return':'returnstatement', '{':'openblock', '}':'closeblock', + 'for':'forparens0', 'throw':'throwstatement', 'throws':'throwsdeclaration', + ';':'ignorestatement', 'while':'conditionblock' + } + javatokens = { + 'new':'createstatement', 'this':'thisstatement' + } + + def __init__(self): + self.parser = StatementParser(self) + + def getindent(self, tok): + "Get the indent for the next statement." + return ' ' * tok.depth + + def choose(self, tok): + "Parse a single statement." + token = tok.next() + if not token: + return None + if token in self.starttokens: + function = getattr(self, self.starttokens[token]) + elif token in self.javatokens: + function = getattr(self, self.javatokens[token]) + else: + function = self.assigninvoke + return function(tok) + + def pendingstatement(self, tok): + "Return any pending statement from elyxer.before." + if tok.infor != 0: + tok.next() + function = getattr(self, 'forparens' + unicode(tok.infor)) + return function(tok) + if len(tok.autoincreases) != 0: + return self.autoincrease(tok) + if len(tok.autodecreases) != 0: + return self.autodecrease(tok) + return None + + def autoincrease(self, tok): + "Process a Java autoincrease (++)." + variable = tok.autoincreases.pop() + return variable + ' += 1' + + def autodecrease(self, tok): + "Process a Java autodecrease (--)." + variable = tok.autodecreases.pop() + return variable + ' -= 1' + + def classormember(self, tok): + "Parse a class or member (attribute or method)." + if tok.inclass: + return self.parser.translateinternal(tok) + else: + return self.parser.translateclass(tok) + + def conditionblock(self, tok): + "Parse a condition in () and then a block {} (if or while statements)." + token = tok.current() + tok.checknext('(') + parens = self.parser.parsecondition(tok, ')') + self.parser.expectblock(tok) + return token + ' ' + parens + ':' + + def parametersblock(self, tok): + "Parse a parameters () and then a block {} (catch statement)." + tok.checknext('(') + parens = self.parser.listparameters(tok) + self.parser.expectblock(tok) + return 'except:' + + def forparens0(self, tok): + "Parse the first statement of a for loop." + "The remaining parts of the for(;;){} are parsed later." + tok.checknext('(') + first = self.assigninvoke(tok, tok.next()) + tok.infor = 1 + return first + + def forparens1(self, tok): + "Read the condition in a for loop." + condition = tok.current() + ' ' + self.parser.parseupto(';', tok) + tok.depth += 1 + tok.infor = 2 + return 'while ' + condition + ':' + + def forparens2(self, tok): + "Read the repeating statement in a for loop." + statement = tok.current() + ' ' + self.parser.parseupto(')', tok) + tok.depth -= 1 + tok.infor = 0 + self.parser.expectblock(tok) + return statement + + def tryblock(self, tok): + "Parse a block after a try." + self.parser.expectblock(tok) + return tok.current() + ':' + + def elseblock(self, tok): + "Parse a block after an else." + self.parser.expectblock(tok) + if tok.peek() == 'if': + tok.next() + self.closeblock(tok) + return 'el' + self.conditionblock(tok) + return 'else:' + + def openblock(self, tok): + "Open a block of code." + if tok.waitingforblock: + tok.waitingforblock = False + else: + tok.depth += 1 + if tok.peek() == '}': + return 'pass' + return None + + def closeblock(self, tok): + "Close a block of code." + tok.depth -= 1 + return None + + def returnstatement(self, tok): + "A statement that contains a value (a return statement)." + self.onelineblock(tok) + return 'return ' + self.parser.parsevalue(tok) + + def throwstatement(self, tok): + "A statement to throw (raise) an exception." + exception = tok.next() + if exception == 'new': + return 'raise ' + self.createstatement(tok) + token = tok.next() + if token == ';': + return 'raise ' + exception + Trace.error('Invalid throw statement: "throw ' + exception + ' ' + token + '"') + return 'raise ' + exception + + def throwsdeclaration(self, tok): + "A throws clause, should be ignored." + name = tok.next() + return '' + + def assigninvoke(self, tok, token = None): + "An assignment or a method invocation." + self.onelineblock(tok) + if not token: + token = tok.current() + token2 = tok.next() + if token2 == '=': + # assignment + return token + ' = ' + self.parser.parsevalue(tok) + if token2 == '.': + member = tok.next() + return self.assigninvoke(tok, token + '.' + member) + if token2 == '(': + parameters = self.parser.parseparameters(tok) + Trace.debug('Parameters: ' + parameters) + return self.assigninvoke(tok, token + parameters) + if token2 == '[': + square = self.parser.parseinsquare(tok) + return self.assigninvoke(tok, token + square) + if token2 == '{': + # ignore anonymous class + self.parser.parseupto('}', tok) + return token + if token2 == '++': + Trace.debug('Increasing invoked ' + token) + tok.autoincreases.append(token) + return self.assigninvoke(tok, token + ' + 1') + if token2 == '--': + Trace.debug('Decreasing invoked ' + token) + tok.autodecreases.append(token) + return self.assigninvoke(tok, token + ' - 1') + if token2 in [';', ',', ')']: + # finished invocation + return token + if token2 in tok.javasymbols: + Trace.error('Unknown symbol ' + token2 + ' for ' + token) + return '*error ' + token + ' ' + token2 + ' error*' + token3 = tok.next() + if token3 == ';': + # a declaration; ignore + return '' + if token3 == '=': + # declaration + assignment + tok.variables.append(token2) + return token2 + ' = ' + self.parser.parsevalue(tok) + if token3 == '[': + # array declaration + self.parser.parseupto(']', tok) + return self.assigninvoke(tok, token2) + Trace.error('Unknown combination ' + token + '+' + token2 + '+' + token3) + return '*error ' + token + ' ' + token2 + ' ' + token + ' error*' + + def onelineblock(self, tok): + "Check if a block was expected." + if tok.waitingforblock: + tok.waitingforblock = False + tok.depth -= 1 + + def ignorestatement(self, tok): + "Ignore a whole statement." + while tok.current() != ';': + tok.next() + return None + + def createstatement(self, tok): + "A statement to create an object and use it: new Class().do()." + tok.next() + return self.parser.parseinvocation(tok) + + def thisstatement(self, tok): + "A statement starting with this, which translates to self." + return self.assigninvoke(tok, 'self') + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/licensify.py elyxer-1.2.5/forks/jras-elyxer/src/licensify.py --- elyxer-1.2.3/forks/jras-elyxer/src/licensify.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/licensify.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,62 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090314 +# Modifies the license of a Python source file + +import sys +from elyxer.io.fileline import * +from elyxer.io.bulk import * +from elyxer.util.trace import Trace + + +mark = '--end--' + +def process(reader, writer, license): + "Conflate all Python files used in filein to fileout" + for line in license: + writer.writestring(line) + while not mark in reader.currentline(): + reader.nextline() + while not reader.finished(): + line = reader.currentline() + writer.writeline(line) + reader.nextline() + reader.close() + +def processall(args): + "Process all arguments" + del args[0] + if len(args) == 0: + Trace.error('Usage: licensify.py licensefile [file...]') + return + licensefile = BulkFile(args[0]) + license = licensefile.readall() + del args[0] + while len(args) > 0: + pythonfile = BulkFile(args[0]) + reader, writer = pythonfile.getfiles() + del args[0] + process(reader, writer, license) + pythonfile.swaptemp() + +processall(sys.argv) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/load-elyxer.py elyxer-1.2.5/forks/jras-elyxer/src/load-elyxer.py --- elyxer-1.2.3/forks/jras-elyxer/src/load-elyxer.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/load-elyxer.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,33 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090308 +# eLyXer main script +# http://www.nongnu.org/elyxer/ + + +import sys +from elyxer.main.convert import * + + +if __name__ == '__main__': + main() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/loremipsumize.py elyxer-1.2.5/forks/jras-elyxer/src/loremipsumize.py --- elyxer-1.2.3/forks/jras-elyxer/src/loremipsumize.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/loremipsumize.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,113 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20091210 +# Lorem-ipsumize a document: replace all alphanumeric texts longer than two words with "Lorem ipsum" and leave the symbols. + +import sys +from elyxer.io.fileline import * +from elyxer.parse.position import * +from elyxer.util.trace import Trace + + +files = list() + +def getreader(filename): + "Get a reader for lines" + if filename in files: + # already parsed; skip + return None + files.append(filename) + return LineReader(filename) + +def readargs(args): + "Read arguments from the command line" + del args[0] + if len(args) == 0: + usage() + return None, None + if args[0] == '-h' or args[0] == '--help': + usage() + return None, None + reader = getreader(args[0]) + del args[0] + fileout = sys.stdout + if len(args) > 0: + fileout = args[0] + del args[0] + if len(args) > 0: + usage() + return + writer = LineWriter(fileout) + return reader, writer + +def usage(): + "Show command line help." + Trace.error('Usage: loremipsumize.py filein [fileout]') + Trace.error('Mask your document using nonsensical words (Lorem Ipsum).') + Trace.error('Part of the eLyXer package (http://elyxer.nongnu.org/).') + Trace.error(' Options:') + Trace.error(' --help: show this message and quit.') + return + +class LoremIpsumizer(object): + + starts = '@\\' + + def loremipsumize(self, reader, writer): + "Convert all texts longer than two words to 'lorem ipsum'." + if not reader: + return + while not reader.finished(): + line = self.processline(reader.currentline()) + writer.writeline(line) + reader.nextline() + reader.close() + + def processline(self, line): + "Process a single line and return the result." + if len(line) == 0: + return '' + if line[0] in LoremIpsumizer.starts: + return line + pos = TextPosition(line) + result = '' + while not pos.finished(): + result += self.parsepos(pos) + return result + + def parsepos(self, pos): + "Parse the current position, return the result." + if pos.current().isalpha() or pos.current().isdigit(): + alpha = pos.glob(lambda current: current.isalpha() or current.isspace() or current.isdigit()) + if len(alpha.split()) > 2: + return "lorem ipsum" + return alpha + if pos.current().isspace(): + return pos.skipspace() + return pos.skipcurrent() + +reader, writer = readargs(sys.argv) +if reader: + LoremIpsumizer().loremipsumize(reader, writer) + writer.close() + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/math2html.py elyxer-1.2.5/forks/jras-elyxer/src/math2html.py --- elyxer-1.2.3/forks/jras-elyxer/src/math2html.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/math2html.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,56 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20101110 +# eLyXer standalone formula conversion to HTML. + +from elyxer.util.trace import Trace +from elyxer.util.options import * +from elyxer.maths.formula import * +from elyxer.maths.bits import * +from elyxer.maths.command import * +from elyxer.maths.hybrid import * +from elyxer.maths.array import * +from elyxer.maths.macro import * +from elyxer.proc.formulaproc import * + + +def math2html(formula): + "Convert some TeX math to HTML." + factory = FormulaFactory() + whole = factory.parseformula(formula) + FormulaProcessor().process(whole) + whole.process() + return ''.join(whole.gethtml()) + +def main(): + "Main function, called if invoked from elyxer.the command line" + args = sys.argv + Options().parseoptions(args) + if len(args) != 1: + Trace.error('Usage: math2html.py escaped_string') + exit() + result = math2html(args[0]) + Trace.message(result) + +if __name__ == '__main__': + main() + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/setup.py elyxer-1.2.5/forks/jras-elyxer/src/setup.py --- elyxer-1.2.3/forks/jras-elyxer/src/setup.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/setup.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,54 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090908 +# eLyXer distutils management + +from distutils.core import setup + + +packages = [ + 'elyxer', 'elyxer.bib', 'elyxer.conf', 'elyxer.gen', 'elyxer.io', + 'elyxer.main', 'elyxer.maths', 'elyxer.out', 'elyxer.parse', + 'elyxer.proc', 'elyxer.ref', 'elyxer.util', 'elyxer.xtra' + ] +packages = [] + +setup(name = 'eLyXer', + version = 'unknown', + description = 'LyX to HTML converter', + long_description = 'eLyXer is a LyX to HTML converter, with a focus on flexibility and elegant output.', + author = 'Alex Fernandez', + author_email = 'elyxer@gmail.com', + url = 'http://elyxer.nongnu.org/', + packages = packages, + scripts = ['elyxer.py', 'math2html.py', 'loremipsumize.py'], + classifiers = [ + 'License :: OSI Approved :: GNU General Public License (GPL)', + 'Development Status :: 5 - Production/Stable', 'Environment :: Console', + 'Operating System :: OS Independent', 'Programming Language :: Python :: 2.4', + 'Topic :: Printing', 'Topic :: Text Processing :: Markup :: HTML', + 'Topic :: Utilities', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content' + ], + license = 'GPL version 3 or later', + platforms = ['Windows NT/2000/XP', 'Mac OS X', 'GNU/Linux'], + ) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/src/textchange.py elyxer-1.2.5/forks/jras-elyxer/src/textchange.py --- elyxer-1.2.3/forks/jras-elyxer/src/textchange.py 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/src/textchange.py 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,87 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# --end-- +# Alex 20090416 +# Change text in some files at once + +import sys +from elyxer.io.fileline import * +from elyxer.io.bulk import * +from elyxer.util.trace import Trace +from elyxer.util.clparse import * + + +class TextChange(object): + "A change in some text" + + def __init__(self, key, value): + self.key = key + self.value = value + + def affects(self, line): + "Decide if the change affects the line" + if self.key in line: + return True + return False + + def do(self, line): + "Change the text in the line" + return line.replace(self.key, self.value) + +def process(reader, writer, change): + "Change all lines in the file" + counter = 0 + while not reader.finished(): + line = reader.currentline() + if change.affects(line): + line = change.do(line) + counter += 1 + writer.writeline(line) + reader.nextline() + reader.close() + return counter + +def processall(args): + "Process all arguments" + del args[0] + if len(args) < 3: + Trace.error('Usage: textchange.py original changed [file...]') + return + original = args[0] + del args[0] + changed = args[0] + del args[0] + Trace.message('Replacing ' + original + '->' + changed) + change = TextChange(original, changed) + total = 0 + while len(args) > 0: + pythonfile = BulkFile(args[0]) + reader, writer = pythonfile.getfiles() + del args[0] + counter = process(reader, writer, change) + total += counter + Trace.message(' ' + unicode(counter) + ' occurrences in ' + + unicode(pythonfile)) + pythonfile.swaptemp() + Trace.message('Total replacements: ' + unicode(total)) + +processall(sys.argv) + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/Test.java elyxer-1.2.5/forks/jras-elyxer/test/Test.java --- elyxer-1.2.3/forks/jras-elyxer/test/Test.java 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/Test.java 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,111 @@ +// Comment. +// A Test class based on Paul Hunter's Selection.java in MathToWeb. +/* + * Another comment. + */ +// A third comment. +public class Test implements AnInterface +{ + // Constructor + public Test(int par1, int par2) + { + if (par1 > par2) + { + this.attr1 = par2; + this.attr2 = par1; + } + else + { + attr1 = par1; + attr2 = par2; + } + } + + public Test(Test original) + { + attr1 = original.attr2; + attr2 = original.attr2; + } + + // Empty constructor. + public Test() + { + attr1 = -1; + attr2 = -1; + } + + public Object clone() // Embedded comment. + { + try + { + return super.clone(); // Another embedded comment + } + catch (CloneNotSupportedException e) + { + return null; + } + } + + public void indecrease() + { + this.attr1++; + this.attr2--; + } + + public void plusize() + { + return new Test(this.attr1++, this.attr2++); + } + + public String toString() + { return ("attr1 = " + attr1 + ", " + "attr2 = " + attr2); + } + public void message(String message, Test original) + { + for (int i = 0; i < message.length(); i++) + { + if(message.charAt(i) == '\'') + { + System.out.println("Quote in message"); + } + else if (message.charAt(i) == 'P') + { + System.out.println("P in message"); + } + try + { + System.out.println("Hullo"); + } + catch (Exception e) + { + // nothing to do here + } + } + String mossage = (String)message; + int value = (5 * 8) / 40; + while (value != -1) + { + value--; + } + } + public void runThread() + { + Test test = null; + this.message("hello", (Test)test); + new Thread(new Runnable() + { + public void run() + { + total = 0; + int i = 0; + while (i < 100) + { + total += i; + } + } + }).start(); + } + + public int attr1; + public int attr2; +} diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/abstract-good.html elyxer-1.2.5/forks/jras-elyxer/test/abstract-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/abstract-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/abstract-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,35 @@ + + + + + + + + +Abstract Test + + +
      +

      +Abstract Test +

      +
      +

      +Abstract +

      +This document is a test of the abstract capabilities of LyX. +
      +
      +When exported in LyX, this abstract should be shown contiguous. +
      +
      +Apart from the abstract, not much more yet. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/abstract.lyx elyxer-1.2.5/forks/jras-elyxer/test/abstract.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/abstract.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/abstract.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,67 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\use_default_options true +\begin_modules +theorems-ams +eqs-within-sections +figs-within-sections +\end_modules +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Abstract Test +\end_layout + +\begin_layout Abstract +This document is a test of the abstract capabilities of LyX. +\end_layout + +\begin_layout Abstract +When exported in LyX, this abstract should be shown contiguous. +\end_layout + +\begin_layout Standard +Apart from the abstract, not much more yet. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/accept-all elyxer-1.2.5/forks/jras-elyxer/test/accept-all --- elyxer-1.2.3/forks/jras-elyxer/test/accept-all 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/accept-all 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,43 @@ +#!/bin/bash + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Alex 20091129: accept all test files as good + +echo "Accepting all eLyXer test files as good" +echo "You should only do this if you have made a large change in all test files" +echo " and you are sure that all files come out right!" + +# first from the test directory +for oldfile in *-test.html; do + newfile=${oldfile/"test"/"good"} + mv -f "$oldfile" "$newfile" +done + +# now the test file in subdir +cd subdir +for oldfile in *-test.html; do + newfile=${oldfile/"test"/"good"} + mv -f "$oldfile" "$newfile" +done +cd .. + +# and now for splitpart test files +cd parts +./accept-all + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/appendix-1-6-frameset.html elyxer-1.2.5/forks/jras-elyxer/test/appendix-1-6-frameset.html --- elyxer-1.2.3/forks/jras-elyxer/test/appendix-1-6-frameset.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/appendix-1-6-frameset.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,9 @@ + + + + + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/appendix-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/appendix-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/appendix-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/appendix-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,540 @@ + + + + + + + + +Appendix Test + + +
      +

      +Appendix Test +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + + + +

      +Part I. Of How Our Hero Came and Went +

      +

      +1 The Coming +

      +
      +Our hero came in. He was tired. He thought the world belonged to him. +
      +

      +1.1 The Meeting +

      +
      +Our hero met with Laurinda. She was smiling. But our hero was not amused. His whiskers were dripping wet, he was astonishingly thirsty, and the contradiction was killing him. “Give me some beer, woman!”, he ordered. +
      +

      +1.2 The Melting +

      +
      +Laurinda smiled again. “But Wenceslau, you don’t belong here.” What a stupid thing to say at that precise moment, our hero thought to himself. Only that it came out loud. At that precise moment he knew that the desired beer would not be forthcoming. +
      +
      +He turned to the bartender and tried to obtain a beer by the very old method of purchasing it. But being ignored was not one of Laurinda’s specialities. +
      +

      +2 The Going +

      +
      +It could not last. Laurinda’s hips were flapping, and she was hopping mad. +
      +

      +2.1 Our Hero’s Imagination +

      +
      +Our hero imagined her as a rabbit with long ears and a fine set of tusks. In a short time the image drifted to a walrus, and our hero could not help letting his sinister smile giving him away. Figure 2.1↓ shows a gross approximation of the rabbit-walrus. +
      +
      +
      +
      +
      +figure rabbit-walrus.png + +
      +
      +Figure 2.1 The rabbit-walrus. +
      + +
      + +
      + +
      +

      +2.2 Laurinda’s Anger +

      +
      +“Wasn’t it great”, said Laurinda. Actually she said it in the present tense, but our poor storytelling skills have changed that to a cheesy past. Don’t do this at home, kids. You want to be regarded for your authenticity, and misquoting isn’t going to help much. +
      +
      +Anyway, back to the story. Laurinda wanted to hit him in the head with a big ham that she kept just for occassions like this, and being a solid Hitchcock fan she was ready to cook the ham afterwards and serve the resulting stew to any policemen that might come by. She was also a huge Almodóvar fan, but she was unaware that in an early film the divine Pedro had copied the scene. Actually both directors had copied the idea from a short story by Roald Dahl, very much worth reading. Although it must be said that in this story it was a lamb leg, which hardly offers the consistency and stiffness necessary to kill a sturdy husband. +
      +
      +But who cares. Laurinda meanwhile had a funny appearance; if you want to see why please direct your eyes to figure 2.2↓. +
      +
      +
      +
      +
      +figure laurindas-anger.png + +
      +
      +Figure 2.2 Laurinda’s anger pictured in a mildly humorous tone. +
      + +
      + +
      + +
      +
      +And yet, how furious was really Laurinda, whom we may optionally refer to as Melinda from now on? Table 2.1↓ vainly attempts to quantify it. +
      +
      +
      +
      +
      + + + + + + + + + + + + +
      +Anger + +Time +
      +1 + +2 +
      + +
      +
      +Table 2.1 Laurinda’s anger as a function of time. +
      + +
      + +
      + +
      +
      +For the sake of Laurinda’s furiousness, here is figure 2.3↓ again. +
      +
      +
      +
      +
      +figure laurindas-anger.png + +
      +
      +Figure 2.3 Laurinda’s anger, again. +
      + +
      + +
      + +
      +
      +But how did Laurinda compute her anger? We cannot but speculate; here is a stupid suggestion in listing 2.1↓. +
      +
      +
      +
      +anger = time - 1
      +Algorithm 2.1 Laurinda computes her anger. +
      + +
      + +
      + +
      +
      +The result is in table 2.2↓, proving we were right all along. Also subtables a↓ and b↓ show anger and time, respectively. +
      +
      +
      +
      +
      + +
      +
      + + + + + + + + + + +
      +Anger +
      +1 +
      + +
      +
      +(a) Only Anger. +
      + +
      + +
      + +
      +
      + + + + + + + + + + +
      +Time +
      +2 +
      +
      +(b) Only Time. +
      + +
      + +
      + +
      + +
      +
      +Table 2.2 Laurinda’s anger quantified, divided in two. +
      + +
      + +
      + +
      +
      +Interested in that last table? Let us repeat it but without a label and with a table and a subtable a↓. +
      +
      +
      +
      +
      + +
      +Censored
      +(a) The rabbit-walrus does an encore. +
      + +
      + +
      + + + + + + + + + + + + +
      +Anger + +Time +
      +1 + +2 +
      + +
      +
      +Table 2.3 One more time. +
      + +
      + +
      + +
      +

      +2.3 The Passing Away +

      +
      +Our hero was passing by the village. He had only stopped to say “Hi!” Again here our lousy skills have made us spoil the quote, but this time for the opposite reasons: everyone knows how to say “Hi!”, so we don’t need an actual quote. It is enough to report that the had stopped to say hi, even maybe qualifying it a bit to make do for the missing exclamation sign: he could have stopped to say a friendly hi. Getting all literary he could have stopped to say a longing hi, although this road leads to bizarreness. It could be cool though. +
      +
      +But anyway. Laurinda was so mad, so hopping mad that she called her friend, the Assassin. He was not in town at that precise moment, but that didn’t help our hero as he was just outside town killing people in a small barn. Just for practice. +
      +
      +Our hero left the village, but Laurinda cunningly annotated the MAC address of his laptop’s wifi card. The lack of networking knowledge on the part of our hero (who really couldn’t tell a SYN packet from an ACK) was to play an important part in the story — if he had known how to change the MAC address, which identified him with the precision of a surgeon’s scalpel, he would have been safe. +
      +
      +Let’s not even get into that last scalpel metaphor, shall we not? It leaks worse than the Titanic. +
      +

      +Part II. Of How Our Hero Went No More +

      +

      +3 The Killing +

      +
      +Our hero led a happy existence for a long time afterwards, randomly avoiding all points within connecting distance of a wifi network. It could not last. +
      +
      +Our hero went to the next village, found a friendly Moonrams cafe and connected to the net. Quickly the assassin (who knew the very people that run the internet, and who by this display of nerdiness no longer merits the starting capital letter) traced a bunch of IP packets coming from our hero’s MAC address. He deployed a team of murderous African bees, which as surely as a well-cared-for AK-47 reached our hero and killed him with three fast stings. Of course they died afterwards, being bees and all, so it was an astounding feat this training of wild African bees just for this one murder. Maybe the Assassin merits that capital letter after all. +
      +

      +3.1 The Passing Away +

      +
      +Our hero was undone. He was no more. He was, actually, an ex-hero. We shall narrate his wake soon. +
      +
        +
      • +But first a message from our kind sponsors. They want to present you the next section in this deeper inset.

        +3.2 The Mourning +

        +
        +Everyone cried in the ceremony. It was so sad that we need an image of this moment. You can find it in figure 3.1↓. +Mental note: never pay the artist beforehand. + + +
        + +
      • + +
      +
      +
      +
      +
      +figure mourning.png + +
      +
      +Figure 3.1 A crude approximation to our hero’s mourning. +
      + +
      + +
      + +
      +
      +And thusly everything happened. +
      +

      +4 The Mourning +

      +
      +We have already talked at length about the mourning, and under sponsorship no less, so no further details will be given here. Suffice to say that our hero was mourned. A lot. +
      +

      +A The Rebirth +

      +
      +Surprising everyone, our hero was about to make a comeback. +
      +

      +A.1 Coming Again +

      +
      +As it happened, our hero had never died; he had just faked his own death to find out his assassin. It was not difficult, what with the capital letter and all. +
      +

      +A.2 Two is Better than One +

      +
      +How to make another comeback? This is left as an exercise to the reader. +
      +

      +B Our Recommendation to Kids +

      +
      +Never trust killer bees. Or Assassins. +
      +

      +B.1 Killer Bees and Their Perils +

      +
      +A killer bee cannot be trained consistently, since it will die at the first sting. Better use killing wasps — or, even better, solve your differencies talking. +
      +
      +For the sake of your education, check figure B.1↓. It shows a bunch of killer bees, or something. +
      +
      +
      +
      +
      +figure mourning.png + +
      +
      +Figure B.1 A gathering of killer bees. Supposedly. +
      + +
      + +
      + +
      +

      +B.2 Assassins: Inherently Unreliable +

      +
      +Someone who kills people (even for business) is not someone you want to deal with. Watch “Fargo” by the Coen Brothers if you don’t believe me. And remember: a hero under the belt is a feather on the hat. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/appendix-1-6-toc-good.html elyxer-1.2.5/forks/jras-elyxer/test/appendix-1-6-toc-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/appendix-1-6-toc-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/appendix-1-6-toc-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,88 @@ + + + + + + + + +Converted document + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/appendix-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/appendix-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/appendix-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/appendix-1-6.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1164 @@ +#LyX 1.6.5 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass scrbook +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . + +% DO NOT ALTER THIS PREAMBLE!!! +% +% This preamble is designed to ensure that the User's Guide prints +% out as advertised. If you mess with this preamble, +% parts of the User's Guide may not print out as expected. If you +% have problems LaTeXing this file, please contact +% the documentation team +% email: lyx-docs@lists.lyx.org + +\usepackage{ifpdf} % part of the hyperref bundle +\ifpdf % if pdflatex is used + + % set fonts for nicer pdf view + \IfFileExists{lmodern.sty}{\usepackage{lmodern}}{} + +\fi % end if pdflatex is used + +% for correct jump positions whe clicking on a link to a float +\usepackage[figure]{hypcap} + +% the pages of the TOC is numbered roman +% and a pdf-bookmark for the TOC is added +\let\myTOC\tableofcontents +\renewcommand{\tableofcontents}{% + \frontmatter + \pdfbookmark[1]{\contentsname}{} + \myTOC + \mainmatter } + +% redefine the \LyX macro for PDF bookmarks +\def\LyX{\texorpdfstring{% + L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} + {LyX}} + +% define a short command for \textvisiblespace +\newcommand{\spce}{\textvisiblespace} + +% macro for italic page numbers in the index +\newcommand{\IndexDef}[1]{\textit{#1}} + +% redefine the greyed out note +\end_preamble +\options intoc,bibtotoc,idxtotoc,BCOR7mm,tablecaptionabove +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize 12 +\spacing single +\use_hyperref true +\pdf_title "Appendix Test" +\pdf_author "Alex Fernández" +\pdf_subject "Containing Numeration and Other Appendixy things" +\pdf_keywords "LyX eLyXer" +\pdf_bookmarks true +\pdf_bookmarksnumbered true +\pdf_bookmarksopen false +\pdf_bookmarksopenlevel 1 +\pdf_breaklinks false +\pdf_pdfborder false +\pdf_colorlinks true +\pdf_backref false +\pdf_pdfusetitle false +\pdf_quoted_options "linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue,pdfpagelayout=OneColumn, pdfnewwindow=true,pdfstartview=XYZ, plainpages=false, pdfpagelabels,pdftex" +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 0 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 2 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Appendix Test +\end_layout + +\begin_layout Author +Alex Fernández (elyxer@gmail.com) +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset FloatList figure + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset FloatList table + +\end_inset + + +\end_layout + +\begin_layout Part +Of How Our Hero Came and Went +\end_layout + +\begin_layout Chapter +The Coming +\end_layout + +\begin_layout Standard +Our hero came in. + He was tired. + He thought the world belonged to him. +\end_layout + +\begin_layout Section +The Meeting +\end_layout + +\begin_layout Standard +Our hero met with Laurinda. + She was smiling. + But our hero was not amused. + His whiskers were dripping wet, he was astonishingly thirsty, and the contradic +tion was killing him. + +\begin_inset Quotes eld +\end_inset + +Give me some beer, woman! +\begin_inset Quotes erd +\end_inset + +, he ordered. +\end_layout + +\begin_layout Section +The Melting +\end_layout + +\begin_layout Standard +Laurinda smiled again. + +\begin_inset Quotes eld +\end_inset + +But Wenceslau, you don't belong here. +\begin_inset Quotes erd +\end_inset + + What a stupid thing to say at that precise moment, our hero thought to + himself. + Only that it came out loud. + At that precise moment he knew that the desired beer would not be forthcoming. +\end_layout + +\begin_layout Standard +He turned to the bartender and tried to obtain a beer by the very old method + of purchasing it. + But being ignored was not one of Laurinda's specialities. +\end_layout + +\begin_layout Chapter +The Going +\end_layout + +\begin_layout Standard +It could not last. + Laurinda's hips were flapping, and she was hopping mad. +\end_layout + +\begin_layout Section +Our Hero's Imagination +\end_layout + +\begin_layout Standard +Our hero imagined her as a rabbit with long ears and a fine set of tusks. + In a short time the image drifted to a walrus, and our hero could not help + letting his sinister smile giving him away. + Figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:rabbit-walrus" + +\end_inset + + shows a gross approximation of the rabbit-walrus. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename rabbit-walrus.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:rabbit-walrus" + +\end_inset + +The rabbit-walrus. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +Laurinda's Anger +\end_layout + +\begin_layout Standard +\begin_inset Quotes eld +\end_inset + +Wasn't it great +\begin_inset Quotes erd +\end_inset + +, said Laurinda. + Actually she said it in the present tense, but our poor storytelling skills + have changed that to a cheesy past. + Don't do this at home, kids. + You want to be regarded for your authenticity, and misquoting isn't going + to help much. +\end_layout + +\begin_layout Standard +Anyway, back to the story. + Laurinda wanted to hit him in the head with a big ham that she kept just + for occassions like this, and being a solid Hitchcock fan she was ready + to cook the ham afterwards and serve the resulting stew to any policemen + that might come by. + She was also a huge Almodóvar fan, but she was unaware that in an early + film the divine Pedro had copied the scene. + Actually both directors had copied the idea from a short story by Roald + Dahl, very much worth reading. + Although it must be said that in this story it was a lamb leg, which hardly + offers the consistency and stiffness necessary to kill a sturdy husband. +\end_layout + +\begin_layout Standard +But who cares. + Laurinda meanwhile had a funny appearance; if you want to see why please + direct your eyes to figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:anger" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename laurindas-anger.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:anger" + +\end_inset + +Laurinda's anger pictured in a mildly humorous tone. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +And yet, how furious was really Laurinda, whom we may optionally refer to + as Melinda from now on? Table +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:anger-time" + +\end_inset + + vainly attempts to quantify it. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Anger +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Time +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2 +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:anger-time" + +\end_inset + +Laurinda's anger as a function of time. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +For the sake of Laurinda's furiousness, here is figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:anger-again" + +\end_inset + + again. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename laurindas-anger.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:anger-again" + +\end_inset + +Laurinda's anger, again. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +But how did Laurinda compute her anger? We cannot but speculate; here is + a stupid suggestion in listing +\begin_inset CommandInset ref +LatexCommand ref +reference "alg:computation" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Plain Layout +anger = time - 1 +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "alg:computation" + +\end_inset + +Laurinda computes her anger. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +The result is in table +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:anger-time-again" + +\end_inset + +, proving we were right all along. + Also subtables +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Only-Anger" + +\end_inset + + and +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Only-Time" + +\end_inset + + show anger and time, respectively. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Anger +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:Only-Anger" + +\end_inset + +Only Anger. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Time +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +2 +\end_layout + +\end_inset + + + + +\end_inset + + +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:Only-Time" + +\end_inset + +Only Time. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:anger-time-again" + +\end_inset + +Laurinda's anger quantified, divided in two. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Interested in that last table? Let us repeat it but without a label and + with a table and a subtable +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:rabbit-walrus-encore" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +Censored +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:rabbit-walrus-encore" + +\end_inset + +The rabbit-walrus does an encore. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Tabular + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Anger +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Time +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2 +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +One more time. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +The Passing Away +\end_layout + +\begin_layout Standard +Our hero was passing by the village. + He had only stopped to say +\begin_inset Quotes eld +\end_inset + +Hi! +\begin_inset Quotes erd +\end_inset + + Again here our lousy skills have made us spoil the quote, but this time + for the opposite reasons: everyone knows how to say +\begin_inset Quotes eld +\end_inset + +Hi! +\begin_inset Quotes erd +\end_inset + +, so we don't need an actual quote. + It is enough to report that the had stopped to say hi, even maybe qualifying + it a bit to make do for the missing exclamation sign: he could have stopped + to say a friendly hi. + Getting all literary he could have stopped to say a longing hi, although + this road leads to bizarreness. + It could be cool though. +\end_layout + +\begin_layout Standard +But anyway. + Laurinda was so mad, so hopping mad that she called her friend, the Assassin. + He was not in town at that precise moment, but that didn't help our hero + as he was just outside town killing people in a small barn. + Just for practice. +\end_layout + +\begin_layout Standard +Our hero left the village, but Laurinda cunningly annotated the MAC address + of his laptop's wifi card. + The lack of networking knowledge on the part of our hero (who really couldn't + tell a SYN packet from an ACK) was to play an important part in the story + -- if he had known how to change the MAC address, which identified him + with the precision of a surgeon's scalpel, he would have been safe. +\end_layout + +\begin_layout Standard +Let's not even get into that last scalpel metaphor, shall we not? It leaks + worse than the Titanic. +\end_layout + +\begin_layout Part +Of How Our Hero Went No More +\end_layout + +\begin_layout Chapter +The Killing +\end_layout + +\begin_layout Standard +Our hero led a happy existence for a long time afterwards, randomly avoiding + all points within connecting distance of a wifi network. + It could not last. +\end_layout + +\begin_layout Standard +Our hero went to the next village, found a friendly Moonrams cafe and connected + to the net. + Quickly the assassin (who knew the very people that run the internet, and + who by this display of nerdiness no longer merits the starting capital + letter) traced a bunch of IP packets coming from our hero's MAC address. + He deployed a team of murderous African bees, which as surely as a well-cared-f +or AK-47 reached our hero and killed him with three fast stings. + Of course they died afterwards, being bees and all, so it was an astounding + feat this training of wild African bees just for this one murder. + Maybe the Assassin merits that capital letter after all. +\end_layout + +\begin_layout Section +The Passing Away +\end_layout + +\begin_layout Standard +Our hero was undone. + He was no more. + He was, actually, an ex-hero. + We shall narrate his wake soon. +\end_layout + +\begin_layout Itemize +But first a message from our kind sponsors. + They want to present you the next section in this deeper inset. +\end_layout + +\begin_deeper +\begin_layout Section +The Mourning +\end_layout + +\begin_layout Standard +Everyone cried in the ceremony. + It was so sad that we need an image of this moment. + You can find it in figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:mourning" + +\end_inset + +. + +\begin_inset Note Greyedout +status open + +\begin_layout Plain Layout +Mental note: never pay the artist beforehand. +\end_layout + +\end_inset + + +\end_layout + +\end_deeper +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename mourning.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:mourning" + +\end_inset + +A crude approximation to our hero's mourning. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +And thusly everything happened. +\end_layout + +\begin_layout Chapter +The Mourning +\end_layout + +\begin_layout Standard +We have already talked at length about the mourning, and under sponsorship + no less, so no further details will be given here. + Suffice to say that our hero was mourned. + A lot. +\end_layout + +\begin_layout Chapter +\start_of_appendix +The Rebirth +\end_layout + +\begin_layout Standard +Surprising everyone, our hero was about to make a comeback. +\end_layout + +\begin_layout Section +Coming Again +\end_layout + +\begin_layout Standard +As it happened, our hero had never died; he had just faked his own death + to find out his assassin. + It was not difficult, what with the capital letter and all. +\end_layout + +\begin_layout Section +Two is Better than One +\end_layout + +\begin_layout Standard +How to make another comeback? This is left as an exercise to the reader. +\end_layout + +\begin_layout Chapter +Our Recommendation to Kids +\end_layout + +\begin_layout Standard +Never trust killer bees. + Or Assassins. +\end_layout + +\begin_layout Section +Killer Bees and Their Perils +\end_layout + +\begin_layout Standard +A killer bee cannot be trained consistently, since it will die at the first + sting. + Better use killing wasps -- or, even better, solve your differencies talking. +\end_layout + +\begin_layout Standard +For the sake of your education, check figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:killer-bees" + +\end_inset + +. + It shows a bunch of killer bees, or something. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename mourning.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:killer-bees" + +\end_inset + +A gathering of killer bees. + Supposedly. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +Assassins: Inherently Unreliable +\end_layout + +\begin_layout Standard +Someone who kills people (even for business) is not someone you want to + deal with. + Watch +\begin_inset Quotes eld +\end_inset + +Fargo +\begin_inset Quotes erd +\end_inset + + by the Coen Brothers if you don't believe me. + And remember: a hero under the belt is a feather on the hat. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/bibtex-alpha.bib elyxer-1.2.5/forks/jras-elyxer/test/bibtex-alpha.bib --- elyxer-1.2.3/forks/jras-elyxer/test/bibtex-alpha.bib 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/bibtex-alpha.bib 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,27 @@ +%% eLyXer: test BibTeX bibliography for alpha style. +%% Created on 20100601 by Alex Fernandez. + + +@article{alphavolume, + Author = {E. Praline and B. Brooky}, + Title = {The population explosion}, + Number = {1}, + Pages = {2--4}, + Journal = {Just The Words}, + Publisher = {Brooky \& Sons}, + Volume = {1}, + Year = {1969}, + url = {http://www.ibras.dk/montypython/episode18.htm} +} + +@article{alphabasic, + Author = {B. Bishop and W. Belpit}, + Journal = {Just The Words}, + Publisher = {Grillomat Snack Bar, Paignton}, + Title = {Your legs are so swollen}, + Year = {1969}, + file = :bibtex-good.html:HTML, + url = http://www.ibras.dk/montypython/episode18.htm, + note = {Found on \url{http://www.ibras.dk/montypython/episode18.htm}.} +} + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/bibtex-good.html elyxer-1.2.5/forks/jras-elyxer/test/bibtex-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/bibtex-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/bibtex-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,136 @@ + + + + + + + + +BibTeX Test + + +
      +

      +BibTeX Test +

      + +

      +1 Ethel the Frog +

      +
      +Some random text. With a random reference [2]. +
      +

      +2 The Other Other Operation +

      +
      +And a book to prove that we have read one (untrue): [1]. +
      +

      +3 Spiny Norman +

      +
      +We are going to need a reference here [3]. +
      +

      +4 In the Grillomat +

      +
      +There are two kinds of vancouver references: with volume information[4] and without[5]. +
      +

      +5 Alpha, Mr Belpit +

      +
      +Two references in one: [BB69, PB69]. Also, a repeated reference[BB69]. +
      +
      +

      +References +

      +

      +[1] J.M. Cleese, M.E. Palin. And Now for Something Different from Voigtländer. Python Monty Editions, 1971. +

      +

      +[2] S.W. Colonel. Summary for Year 1969. Journal of the Society for Putting Things onto Other Things, 457(1):1348—1350, 1969. +

      +

      +[3] Z.X. Pudey. My Silly Walks. Private Walkings, 1970. +

      + +
      +
      +

      +References +

      +

      +[4] J. Linkman. A Little Hors d'Oeuvres. Just The Words, 1969;300(3):1—300. URL: http://www.ibras.dk/montypython/episode18.htm. +

      +

      +[5] J. Linkman. Our Main Course: Prawn Salad. Just The Words, 1969. URL: http://www.ibras.dk/montypython/episode18.htm. +

      + +
      +
      +

      +References +

      +

      +[BB69] B. Bishop, W. Belpit. Your legs are so swollen. Just The Words, 1969. http://www.ibras.dk/montypython/episode18.htm. bibtex-good.html. Found on http://www.ibras.dk/montypython/episode18.htm. +

      +

      +[PB69] E. Praline, B. Brooky. The population explosion. Just The Words, 1(1): 2—4, 1969. http://www.ibras.dk/montypython/episode18.htm. +

      + +
      +
      +

      +References +

      +

      +[Nam10] Latin1 Accents !`©ª®º?` ÀÁÂÃÄÅÅÆÇÈÉÊËÌÍÎÏÐÑ ÒÓÔÕÖØÙÚÛÜÝÞ ßàáâãäåæçèéêë ìı̀ı̀ı́ı̂ı̈ðñ òóôõöøùúûüýþÿ in Name. Latin1 Accents !`©ª®º?` ÀÁÂÃÄÅÅÆÇÈÉÊËÌÍÎÏÐÑ ÒÓÔÕÖØÙÚÛÜÝÞ ßàáâãäåæçèéêë ìı̀ı̀ı́ı̂ı̈ðñ òóôõöøùúûüýþÿ in title. Test, 2010. +

      +

      +[Cen34] Somebody in the Century. Finding ϵn decimals of the number π. About ζ in π things, 1934. According to The Society for

      +ϵn +
      + decimals of the number
      +π +
      +, only 1 in 2n dentists read this magazine. +

      + +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/bibtex-latin1.bib elyxer-1.2.5/forks/jras-elyxer/test/bibtex-latin1.bib --- elyxer-1.2.3/forks/jras-elyxer/test/bibtex-latin1.bib 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/bibtex-latin1.bib 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,26 @@ +@preamble { Please ignore. } + +@string { mykey = "myvalue" } + +@Article{AcentsTest, + Author = {{Latin1 Accents + !`\copyright{}\textordfeminine{}\textregistered{}\textordmasculine{}?` \`A\'A\^A\~A\"A\AA{}\r A\AE{}\c{C}\`E\'E\^E\"E\`I\'I\^I\"I\DH{}\~N \`O\'O\^O\~O\"O\O{}\`U\'U\^U\"U\'Y\TH{} + \ss{}\`a\'a\^a\~a\"a\aa{}\ae{}\c{c}\`e\'e\^e\"e \`i\`\i\`{\i}\'{\i}\^{\i}\"{\i}\dh{}\~n \`o\'o\^o\~o\"o\o{}\`u\'u\^u\"u\'y\th{}\"y + in Name}}, + Title = {Latin1 Accents + !`\copyright{}\textordfeminine{}\textregistered{}\textordmasculine{}?` \`{A}\'{A}\^{A}\~{A}\"{A}\AA{}\r {A}\AE{}\c{{C}}\`{E}\'{E}\^{E}\"{E}\`{I}\'{I}\^{I}\"{I}\DH{}\~{N} \`{O}\'{O}\^{O}\~{O}\"{O}\O{}\`{U}\'{U}\^{U}\"{U}\'{Y}\TH{} + \ss{}\`a\'a\^a\~a\"a\aa{}\ae{}\c{c}\`e\'e\^e\"e \`i\`\i\`{\i}\'{\i}\^{\i}\"{\i}\dh{}\~n \`o\'o\^o\~o\"o\o{}\`u\'u\^u\"u\'y\th{}\"y + in title}, + Journal = {Test}, + year = 2010 +} + +@article{alphaeqs, + Author = {Somebody in the $20^{th}$ Century}, + Title = {Finding $\epsilon^{n}$ decimals of the number $\pi$}, + Journal = {About \(\zeta\) in \(\pi\) things}, + Year = {1934}, + note = {According to The Society for $$\sum\epsilon^{n}$$ decimals of the number \[\sum\pi\], + only 1 in $2n$ dentists read this magazine.} +} + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/bibtex-plain.bib elyxer-1.2.5/forks/jras-elyxer/test/bibtex-plain.bib --- elyxer-1.2.3/forks/jras-elyxer/test/bibtex-plain.bib 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/bibtex-plain.bib 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,60 @@ +%% eLyXer: test BibTeX bibliography. +%% Created on 20090905 by Alex Fernandez. + +@preamble { This text should be ignored. } + +@STRING{ tei = "The Spanish Inquisition" } + +@sTrIng { cleese = "Cleese, J.M." } + +@string{ inlowercase = "string in lowercase" } + +@article { randomref, + Author = {Colonel, S.W.}, + Journal = {Journal of the Society for Putting Things onto Other Things}, + Number = {1}, + Pages = {1348--1350}, + Publisher = {Monty Python Ltd}, + Title = {{Summary for Year 1969}}, + Volume = {457}, + Year = {1969}} + +Comment outside an entry + +@article{unused, + Author = {Teabag, J.M.}, + Journal = {Journal of the Silly Walking Committee}, + Number = {384}, + Silly-Putty = putty-silly, + Pages = {589--1530}, + Publisher = {Monty Python Ltd}, + Title = {{Some + Techniques + from + our + French + Cousins}}, + Volume = {3}, + Year = {1970}} + +@article{reduced, + Author = {Pudey, Z.X.}, + Journal = {Private Walkings}, + Title = {My Silly Walks}, + Year = {1970}} + +@COMMENT { Do not look at the pretty lights } + +@comment { "A comment including double quotes because we like it." } + +@book {pythonesque:1971, + Author = cleese # + " and Palin, M.E.", + Date-Added = {2009-09-05 16:32:00 +0100}, + Date-Modified = {2009-09-05 16:33:00 +0100}, + Publisher = "Python Monty " # "Editions", + Title = {{And Now for Something Different + from Voigtl{\"a}nder}}, + Year = {1971}, + Conceptual-Disaster = {{\"O}berg} + } diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/bibtex-vancouver.bib elyxer-1.2.5/forks/jras-elyxer/test/bibtex-vancouver.bib --- elyxer-1.2.3/forks/jras-elyxer/test/bibtex-vancouver.bib 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/bibtex-vancouver.bib 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,25 @@ +%% eLyXer: test BibTeX bibliography for vancouver style. +%% Created on 20100529 by Alex Fernandez. + + +@article{withvolume, + Author = {J. Linkman}, + Journal = {Just The Words}, + Number = {3}, + Pages = {1--300}, + Publisher = {Grillomat Snack Bar, Paignton}, + Title = {A Little Hors d'Oeuvres}, + Volume = {300}, + Year = {1969}, + url = {http://www.ibras.dk/montypython/episode18.htm} +} + +@article{withoutvolume, + Author = {J. Linkman}, + Journal = {Just The Words}, + Publisher = {Grillomat Snack Bar, Paignton}, + Title = {Our Main Course: Prawn Salad}, + Year = {1969}, + url = http://www.ibras.dk/montypython/episode18.htm +} + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/bibtex.lyx elyxer-1.2.5/forks/jras-elyxer/test/bibtex.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/bibtex.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/bibtex.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,234 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +BibTeX Test +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Section +Ethel the Frog +\end_layout + +\begin_layout Standard +Some random text. + With a random reference +\begin_inset CommandInset citation +LatexCommand cite +key "randomref" + +\end_inset + +. +\end_layout + +\begin_layout Section +The Other Other Operation +\end_layout + +\begin_layout Standard +And a book to prove that we have read one (untrue): +\begin_inset CommandInset citation +LatexCommand cite +key "pythonesque:1971" + +\end_inset + +. +\end_layout + +\begin_layout Section +Spiny Norman +\end_layout + +\begin_layout Standard +We are going to need a reference here +\begin_inset CommandInset citation +LatexCommand cite +key "reduced" + +\end_inset + +. +\end_layout + +\begin_layout Section +In the Grillomat +\end_layout + +\begin_layout Standard +There are two kinds of vancouver references: with volume information +\begin_inset CommandInset citation +LatexCommand cite +key "withvolume" + +\end_inset + + and without +\begin_inset CommandInset citation +LatexCommand cite +key "withoutvolume" + +\end_inset + +. +\end_layout + +\begin_layout Section +Alpha, Mr Belpit +\end_layout + +\begin_layout Standard +Two references in one: +\begin_inset CommandInset citation +LatexCommand cite +key "alphabasic,alphavolume" + +\end_inset + +. + Also, a repeated reference +\begin_inset CommandInset citation +LatexCommand cite +key "alphabasic" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset CommandInset bibtex +LatexCommand bibtex +bibfiles "bibtex-plain" +options "bibtotoc,plain" + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset CommandInset bibtex +LatexCommand bibtex +bibfiles "bibtex-vancouver" +options "vancouver" + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset CommandInset bibtex +LatexCommand bibtex +bibfiles "bibtex-alpha" +options "alpha" + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset CommandInset bibtex +LatexCommand bibtex +btprint "btPrintAll" +bibfiles "bibtex-latin1" +options "alpha" + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset Note Comment +status open + +\begin_layout Plain Layout +\begin_inset CommandInset bibtex +LatexCommand bibtex +btprint "btPrintAll" +bibfiles "bibtex-latin1" +options "bibtotoc,alpha" + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/branches-1-5-good.html elyxer-1.2.5/forks/jras-elyxer/test/branches-1-5-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/branches-1-5-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/branches-1-5-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,41 @@ + + + + + + + + +Document with branches + + +
      +

      +Document with branches +

      +
      +First some stupid text. +
      +
      +Now some intermediately stupid text. +
      +
      + +
      +In this second branch, reddish, we have to be more careful: it is active. +
      + +
      + +
      +
      +Finally some terminally stupid text. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/branches-1-5.lyx elyxer-1.2.5/forks/jras-elyxer/test/branches-1-5.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/branches-1-5.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/branches-1-5.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,112 @@ +#LyX 1.5.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 276 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 +\graphics default +\paperfontsize default +\spacing single +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\branch First +\selected 0 +\color #faf0e6 +\end_branch +\branch Second +\selected 1 +\color #fa6a6a +\end_branch +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Document with branches +\end_layout + +\begin_layout Standard +First some stupid text. +\end_layout + +\begin_layout Standard +\begin_inset Branch First +status collapsed + +\begin_layout Standard +In this first branch, without color, we carn write whatever we want: it + is inactive. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Now some intermediately stupid text. +\end_layout + +\begin_layout Standard +\begin_inset Branch Second +status open + +\begin_layout Standard +In this second branch, reddish, we have to be more careful: it is active. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Finally some terminally stupid text. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/change-good.html elyxer-1.2.5/forks/jras-elyxer/test/change-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/change-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/change-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,29 @@ + + + + + + + + +Change Test + + +
      +

      +Change Test +

      +
      +Prisoner:Well... I’d just like to say, m’lud, I’ve got a family... a wife and six kids... and I hoope very much you don’t have to take away my freedom... because... well, because m’lud freedom is a state much prized within the realm of civilized society. It is a bond wherewith the savage man may charm the outward hatchments of his soul, and soothe the troubled breast into a magnitude of quiet. It is most precious as a blessed balm, the saviour of princes, the harbinger of happiness, yea, the very stuff and pith of all we hold most dear. What frees the prisoner in his lonely cell, chained within the bondage of rude walls, far from the owl of Thebbes? What fires and stirs the woodcock in his springe or wakes the drowsy apricot betides? What goddess doth the storm toss’d mariner offer her most tempestuous prayers to? Freedom! Freedom! Freedom! +
      +
      +Judge:It’s only a bloody parking offence. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/change.lyx elyxer-1.2.5/forks/jras-elyxer/test/change.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/change.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/change.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,97 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\use_default_options true +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes true +\output_changes true +\author "chenno,,," +\end_header + +\begin_body + +\begin_layout Title +Change Test +\end_layout + +\begin_layout List +\labelwidthstring 00.00.0000 + +\change_inserted 0 1283108483 +Prisoner: +\change_unchanged +Well... + I'd just like to say, m'lud, I've got a family... + a wife and six kids... + and I ho +\change_deleted 0 1283108130 +o +\change_unchanged +pe very much you don't have to take away my freedom... + because... + well, because m'lud freedom is a state much prized within the rea +\change_inserted 0 1283108101 +l +\change_unchanged +m of civilized society. + It is a bond wherewith the savage man may charm the outward hatchments + of his soul, and soothe the troubled brea +\change_inserted 0 1283108102 +s +\change_unchanged +t into a magnitude of quiet. + It is most precious as a blessed balm, the saviour of princes, the harbinger + of happiness, yea, the very stuff and pith of all we hold most dear. + What frees the prisoner in his lonely cell, chained within the bondage + of rude walls, far from the owl of Theb +\change_deleted 0 1283108105 +b +\change_unchanged +es? What fires and stirs the woodcock in his springe or wakes the drowsy + apricot betides? What goddess doth the storm toss'd mariner offer her most + tempestuous prayers to? Freedom! Freedom! Freedom! +\change_inserted 0 1283108446 + +\end_layout + +\begin_layout List +\labelwidthstring 00.00.0000 + +\change_inserted 0 1283108472 +Judge: It's only a bloody parking offence. +\change_unchanged + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/compressed-good.html elyxer-1.2.5/forks/jras-elyxer/test/compressed-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/compressed-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/compressed-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,32 @@ + + + + + + + + +Compressed Test + + +
      +

      +Compressed Test +

      +
      +A simple test of a compressed document. +
      +

      +Part I. The Main Part +

      +
      +Nothing else here. +
      +

      Index

      + + +
      + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/compressed.lyx and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/compressed.lyx differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/copyimages/docs/elyxer.svg elyxer-1.2.5/forks/jras-elyxer/test/copyimages/docs/elyxer.svg --- elyxer-1.2.3/forks/jras-elyxer/test/copyimages/docs/elyxer.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/copyimages/docs/elyxer.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/copyimages/elyxer-svg.svg elyxer-1.2.5/forks/jras-elyxer/test/copyimages/elyxer-svg.svg --- elyxer-1.2.3/forks/jras-elyxer/test/copyimages/elyxer-svg.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/copyimages/elyxer-svg.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/copyimages/mini-elyxer.jpg and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/copyimages/mini-elyxer.jpg differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/copyimages/square.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/copyimages/square.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/copyimages/with images-1-5-good.html elyxer-1.2.5/forks/jras-elyxer/test/copyimages/with images-1-5-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/copyimages/with images-1-5-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/copyimages/with images-1-5-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,49 @@ + + + + + + + + +Images Tests + + +
      +

      +Images Tests +

      +
      + +figure elyxer-svg.svg + +First image: regular path. +
      +
      + +figure elyxer-svg.svg + +Second image: convoluted path. +
      +
      + +figure docs/elyxer.svg + +Third image: from another directory. +
      +
      +figure mini-elyxer.jpg +Fourth image: from a JPEG file. +
      +
      +figure square.png +Fifth image: from a PNG file. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/copyimages/with images-1-5-test.html elyxer-1.2.5/forks/jras-elyxer/test/copyimages/with images-1-5-test.html --- elyxer-1.2.3/forks/jras-elyxer/test/copyimages/with images-1-5-test.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/copyimages/with images-1-5-test.html 2013-03-10 10:39:45.000000000 +0000 @@ -0,0 +1,49 @@ + + + + + + + + +Images Tests + + +
      +

      +Images Tests +

      +
      + +figure elyxer-svg.svg + +First image: regular path. +
      +
      + +figure elyxer-svg.svg + +Second image: convoluted path. +
      +
      + +figure docs/elyxer.svg + +Third image: from another directory. +
      +
      +figure mini-elyxer.jpg +Fourth image: from a JPEG file. +
      +
      +figure square.png +Fifth image: from a PNG file. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/decorations-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/decorations-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/decorations-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/decorations-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,224 @@ + + + + + + + + +Decorations Test + + +
      +

      +Decorations Test +

      +

      +1 Decorations +

      +
      +A few examples taken from the Spanish Lyx User’s Guide. +
      +
      +An accent that looks like a hat: , done using \hat a within an equation. The following table shows commands to make decorations. +
      +
      +
      +
      +
      +Table 1.1 Decorations and commands. +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +Name + +Command + +Sample +
      +circumflex + +\hat + + +
      +grave + +\grave + + +
      +acute + +\acute + + +
      +diaeresis + +\ddot + + +
      +tilde + +\tilde + + +
      +dot + +\dot + + +
      +triple dot + +\dddot + +o⃛ +
      +breve + +\breve + + +
      +caron + +\check + + +
      +bar + +\bar + +l +
      +vector + +\vec + +m⃗ +
      +long vector + +\overrightarrow + +ABC +
      +wide hat + +\widehat + +^house +
      + +
      + +
      + +
      + +
      +
      +Decorations should also appear correctly in unit names: 100 años and in superscripts: 40100 años. +
      +
      +That’s all folks! +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/decorations-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/decorations-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/decorations-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/decorations-1-6.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,716 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass scrbook +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . + +% DO NOT ALTER THIS PREAMBLE!!! +% +% This preamble is designed to ensure that the User's Guide prints +% out as advertised. If you mess with this preamble, +% parts of the User's Guide may not print out as expected. If you +% have problems LaTeXing this file, please contact +% the documentation team +% email: lyx-docs@lists.lyx.org + +\usepackage{ifpdf} % part of the hyperref bundle +\ifpdf % if pdflatex is used + + % set fonts for nicer pdf view + \IfFileExists{lmodern.sty}{\usepackage{lmodern}}{} + +\fi % end if pdflatex is used + +% for correct jump positions whe clicking on a link to a float +\usepackage[figure]{hypcap} + +% the pages of the TOC is numbered roman +% and a pdf-bookmark for the TOC is added +\let\myTOC\tableofcontents +\renewcommand{\tableofcontents}{% + \frontmatter + \pdfbookmark[1]{\contentsname}{} + \myTOC + \mainmatter } + +% redefine the \LyX macro for PDF bookmarks +\def\LyX{\texorpdfstring{% + L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} + {LyX}} + +% define a short command for \textvisiblespace +\newcommand{\spce}{\textvisiblespace} + +% macro for italic page numbers in the index +\newcommand{\IndexDef}[1]{\textit{#1}} + +% redefine the greyed out note +\end_preamble +\options intoc,bibtotoc,idxtotoc,BCOR7mm,tablecaptionabove +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize 12 +\spacing single +\use_hyperref true +\pdf_title "Decorations Test" +\pdf_author "Alex Fernández" +\pdf_subject "Taken from Guía de Usuario de Lyx, Ignacio García" +\pdf_keywords "LyX" +\pdf_bookmarks true +\pdf_bookmarksnumbered true +\pdf_bookmarksopen false +\pdf_bookmarksopenlevel 1 +\pdf_breaklinks false +\pdf_pdfborder false +\pdf_colorlinks true +\pdf_backref false +\pdf_pdfusetitle false +\pdf_quoted_options "linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue,pdfpagelayout=OneColumn, pdfnewwindow=true,pdfstartview=XYZ, plainpages=false, pdfpagelabels,pdftex" +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 0 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 2 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Decorations Test +\end_layout + +\begin_layout Chapter +Decorations +\end_layout + +\begin_layout Standard +A few examples taken from the Spanish Lyx User's Guide. +\end_layout + +\begin_layout Standard +An accent that looks like a hat: +\begin_inset Formula $\hat{a}$ +\end_inset + +, done using +\series bold + +\backslash +hat +\begin_inset ERT +status open + +\begin_layout Plain Layout + + +\backslash +spce +\end_layout + +\end_inset + +a +\series default + within an equation. + The following table shows commands to make decorations. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Decorations and commands. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\align center +\begin_inset VSpace defskip +\end_inset + + +\begin_inset Tabular + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Name +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Command +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Sample +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +circumflex +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +hat +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\hat{a}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +grave +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +grave +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\grave{m}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +acute +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +acute +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\acute{A}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +diaeresis +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +ddot +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\ddot{B}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +tilde +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +tilde +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\tilde{N}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +dot +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +dot +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\dot{L}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +triple dot +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +dddot +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\dddot{o}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +breve +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +breve +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\breve{g}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +caron +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +check +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\check{s}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +bar +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +bar +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\bar{l}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +vector +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +vec +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\vec{m}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +long vector +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +overrightarrow +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\overrightarrow{ABC}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +wide hat +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold + +\backslash +widehat +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Formula $\widehat{house}$ +\end_inset + + +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Decorations should also appear correctly in unit names: +\begin_inset Formula $100\mathrm{a\tilde{n}os}$ +\end_inset + + and in superscripts: +\begin_inset Formula $40^{100\mathrm{a\tilde{n}os}}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +That's all folks! +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/descriptions-1-5-good.html elyxer-1.2.5/forks/jras-elyxer/test/descriptions-1-5-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/descriptions-1-5-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/descriptions-1-5-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,62 @@ + + + + + + + + +Descriptions Tests + + +
      +

      +Descriptions Tests +

      +
      +First description. +
      +
      +Second description.  +
      +
      +Third description which should hold all words but these. +
      +
      +Fourth description. +
      +
      +Fifth description with odd spaces. +
      +
      +Mixed font description. +
      +
      +Aneven more difficult description with change of font in the middle. +
      +
      +Animpossible description with intermixed changes of font and color. +
      +
      +A description which leads to fixed text in dif(fere)nt colors. And now some more. +
      +
      +ERT precedes this description, it should be kept. +
      +
      +ERT is the description  and not only the first word. +
      +
      +Word that leads a description and which appears in the Index. +
      +

      Index

      +Word: +

      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/descriptions-1-5.lyx elyxer-1.2.5/forks/jras-elyxer/test/descriptions-1-5.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/descriptions-1-5.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/descriptions-1-5.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,199 @@ +#LyX 1.5.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 276 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 +\graphics default +\paperfontsize default +\spacing single +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Descriptions Tests +\end_layout + +\begin_layout Description +First description. +\end_layout + +\begin_layout Description +Second\InsetSpace ~ +description. +\end_layout + +\begin_layout Description +Third\InsetSpace ~ +description\InsetSpace ~ +which\InsetSpace ~ +should\InsetSpace ~ +hold\InsetSpace ~ +all\InsetSpace ~ +words but these. +\end_layout + +\begin_layout Description +Fourth description. +\end_layout + +\begin_layout Description +Fifth\InsetSpace \space{} +description\InsetSpace \thinspace{} +with odd spaces. +\end_layout + +\begin_layout Description + +\family typewriter +Mixed +\family default + font description. +\end_layout + +\begin_layout Description + +\family typewriter +An even +\family default + more difficult description with change of font in the middle. +\end_layout + +\begin_layout Description + +\family typewriter +A +\color red +n +\family default +i +\color inherit +mpossible description with intermixed changes of font and color. +\end_layout + +\begin_layout Description +A description which leads to +\family typewriter +fixed +\color blue +text +\color red +in +\color inherit + +\color green +dif +\family default +(fere) +\family typewriter +nt +\color inherit + +\color magenta +colors +\family default +\color inherit +. + And now +\family typewriter +\series bold +some +\series default + more +\family default +. +\end_layout + +\begin_layout Description +\begin_inset ERT +status open + +\begin_layout Standard + +\end_layout + +\end_inset + +ERT precedes this description, it should be kept. +\end_layout + +\begin_layout Description +\begin_inset ERT +status open + +\begin_layout Standard + +ERT is the description +\end_layout + +\end_inset + + and not only the first word. +\end_layout + +\begin_layout Description +\begin_inset LatexCommand index +name "Word" + +\end_inset + +Word that leads a description and which appears in the Index. +\end_layout + +\begin_layout Description +\begin_inset LatexCommand printindex + +\end_inset + + +\end_layout + +\end_body +\end_document Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/docs/elyxer.jpg and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/docs/elyxer.jpg differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/docs/elyxer.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/docs/elyxer.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/elyxer-eps.eps elyxer-1.2.5/forks/jras-elyxer/test/elyxer-eps.eps --- elyxer-1.2.3/forks/jras-elyxer/test/elyxer-eps.eps 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/elyxer-eps.eps 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1725 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: inkscape 0.46 +%%Pages: 1 +%%Orientation: Portrait +%%BoundingBox: 2 10 125 119 +%%HiResBoundingBox: 2.2857151 10.705055 124.8714 118.85715 +%%EndComments +%%Page: 1 1 +0 128 translate +0.8 -0.8 scale +0 0 0 setrgbcolor +[] 0 setdash +1 setlinewidth +0 setlinejoin +0 setlinecap +gsave [1 0 0 1 0 0] concat +gsave [1 0 0 1 -549.09823 -447.62427] concat +gsave [1.6412659 -0.049648468 0.045147815 1.8048788 539.20253 448.91643] concat +gsave +0.12941177 0.12941177 0.12941177 setrgbcolor +newpath +24.859391 31.907937 moveto +23.419824 24.350211 24.964801 11.778293 30.054438 8.9789918 curveto +35.144076 6.1796912 40.379124 5.3034583 41.760605 9.7424375 curveto +43.243834 14.508354 39.448349 16.768623 34.704351 20.597833 curveto +29.745701 24.600304 28.340109 28.103497 24.859391 31.907937 curveto +closepath +eofill +grestore +grestore +gsave +0.40000001 0.5411765 0.68235296 setrgbcolor +newpath +580.10453 531.54842 moveto +580.10453 531.54842 579.6867 492.49241 611.02396 486.97862 curveto +642.36123 481.46483 653.85156 533.84584 651.5535 542.11652 curveto +649.25543 550.3872 619.7687 571.03208 600.54851 564.13984 curveto +581.32832 557.24761 583.02934 548.08979 580.10453 531.54842 curveto +closepath +eofill +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [61.980095 88.524223 51.749805 51.554661] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +584.83412 532.92616 moveto +584.83412 532.92616 584.45739 497.71217 612.71194 492.74079 curveto +640.96649 487.7694 652.64504 537.06898 649.25449 542.45465 curveto +645.86394 547.84032 623.2603 556.95452 605.93085 550.74029 curveto +588.60139 544.52606 587.47121 547.84032 584.83412 532.92616 curveto +closepath +eoclip +gsave [1.7854196 0 0 1.6604081 538.73934 444.56248] concat +shfill +grestore +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [46.503231 26.114084 46.767101 52.293003] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +581.25097 532.88232 moveto +581.25097 532.88232 580.83314 493.82631 612.1704 488.31252 curveto +643.50767 482.79873 656.4604 537.47714 652.69993 543.45042 curveto +648.93946 549.42369 623.86965 559.5323 604.64946 552.64007 curveto +585.42927 545.74783 584.17578 549.42369 581.25097 532.88232 curveto +closepath +eoclip +gsave [1.7854196 0 0 1.6604081 538.73934 444.56248] concat +shfill +grestore +grestore +gsave +0.6156863 0.21960784 0.074509807 setrgbcolor +newpath +605.59217 576.5777 moveto +605.59217 568.99624 620.95005 543.07752 627.46707 542.68271 curveto +634.13135 542.27897 630.66198 547.17083 635.67595 546.71134 curveto +640.68991 546.25186 649.04651 546.71134 650.71783 552.68462 curveto +652.38916 558.65789 652.80699 575.65874 647.37519 577.03719 curveto +641.9434 578.41563 637.34727 579.79408 634.42246 584.38891 curveto +631.49764 588.98373 622.72321 597.25442 614.36661 593.11907 curveto +606.18558 589.07062 605.59217 584.15916 605.59217 576.5777 curveto +closepath +eofill +grestore +gsave +0.87843138 0.80784315 0.11372549 setrgbcolor +newpath +617.29142 580.71305 moveto +617.70925 577.95615 621.46972 558.1984 626.06585 554.98203 curveto +630.66198 551.76565 627.73717 558.1984 629.40849 561.41478 curveto +631.07981 564.63116 639.43642 551.76565 639.43642 557.27944 curveto +639.43642 562.79323 631.91547 566.46909 636.92944 565.55012 curveto +641.9434 564.63116 655.7318 560.03634 648.62868 566.00961 curveto +641.52557 571.98288 637.7651 580.71305 632.75114 577.95615 curveto +627.73717 575.19926 626.06585 583.92942 621.88755 583.92942 curveto +617.70925 583.92942 616.87359 583.92942 617.29142 580.71305 curveto +closepath +eofill +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [50.659912 88.177994 53.563347 65.57518] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [0 0 0] +/C1 [0 0 0] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +606.02896 575.57264 moveto +606.02896 567.99118 621.38684 542.07246 627.90386 541.67764 curveto +634.56814 541.2739 631.09877 546.16576 636.11273 545.70628 curveto +641.12669 545.2468 649.4833 545.70628 651.15463 551.67955 curveto +652.82595 557.65282 653.24378 574.65367 647.81197 576.03212 curveto +642.38019 577.41057 637.78406 578.78902 634.85925 583.38384 curveto +631.93443 587.97867 623.15999 596.24935 614.8034 592.11401 curveto +606.62237 588.06555 606.02896 583.1541 606.02896 575.57264 curveto +closepath +eoclip +gsave [1.6300939 0 0 1.8186149 538.73934 444.56248] concat +shfill +grestore +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [32.921471 69.997231 49.624016 77.805328] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [0 0 0] +/C1 [0 0 0] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +622.72321 525.57515 moveto +667.84887 539.81911 lineto +703.36444 511.33119 lineto +622.72321 525.57515 lineto +closepath +eoclip +gsave [2.896845 0 0 1.0233611 538.73934 444.56248] concat +shfill +grestore +grestore +gsave [1.9828475 0 0 2.1805117 515.32574 433.14447] concat +gsave +0.95686275 0.95686275 0.95686275 setrgbcolor +newpath +70.49148 30.108479 moveto +70.49148 35.025069 66.501204 39.015345 61.584614 39.015345 curveto +56.668024 39.015345 52.677748 35.025069 52.677748 30.108479 curveto +52.677748 25.191888 56.668024 21.201612 61.584614 21.201612 curveto +66.501204 21.201612 70.49148 25.191888 70.49148 30.108479 curveto +closepath +eofill +grestore +grestore +gsave +0.6156863 0.21960784 0.074509807 setrgbcolor +newpath +584.70066 544.87341 moveto +584.70066 544.87341 583.865 549.92772 587.62547 554.52255 curveto +591.38594 559.11737 606.84566 574.73977 601.41387 583.92942 curveto +595.98208 593.11907 581.77585 594.03804 576.76189 587.60528 curveto +571.74792 581.17253 553.3634 572.90184 553.78123 569.68547 curveto +554.19906 566.46909 547.09594 550.3872 558.37736 549.46824 curveto +569.65877 548.54927 577.17972 540.27859 580.52236 539.81911 curveto +583.865 539.35962 585.11849 541.65704 584.70066 544.87341 curveto +closepath +eofill +grestore +gsave +0.87843138 0.80784315 0.11372549 setrgbcolor +newpath +581.77585 555.44151 moveto +581.77585 555.44151 585.95415 566.46909 590.13245 572.44236 curveto +594.31076 578.41563 588.87896 586.68632 583.44717 581.17253 curveto +578.01538 575.65874 560.88434 571.5234 561.30217 566.00961 curveto +561.72 560.49582 568.82311 570.60443 570.0766 566.00961 curveto +571.33009 561.41478 561.72 550.84669 566.73396 552.22513 curveto +571.74792 553.60358 575.5084 567.38806 576.76189 559.57685 curveto +578.01538 551.76565 576.34406 544.87341 581.77585 555.44151 curveto +closepath +eofill +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [13.065491 85.119431 26.982304 67.89669] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [0 0 0] +/C1 [0 0 0] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +585.18255 544.61321 moveto +585.18255 544.61321 584.34689 549.66752 588.10736 554.26234 curveto +591.86783 558.85717 607.32755 574.47957 601.89575 583.66922 curveto +596.46396 592.85887 582.25773 593.77784 577.24377 587.34508 curveto +572.22981 580.91233 553.84528 572.64164 554.26311 569.42527 curveto +554.68094 566.20889 547.57783 550.127 558.85924 549.20804 curveto +570.14066 548.28907 577.6616 540.01839 581.00424 539.55891 curveto +584.34689 539.09942 585.60038 541.39684 585.18255 544.61321 curveto +closepath +eoclip +gsave [1.6986295 0 0 1.7452532 538.73934 444.56248] concat +shfill +grestore +grestore +gsave [1.5953948 0 0 1.754435 539.61141 446.55548] concat +gsave +0.87450981 0.82352942 0.44705883 setrgbcolor +newpath +70.49148 30.108479 moveto +70.49148 35.025069 66.501204 39.015345 61.584614 39.015345 curveto +56.668024 39.015345 52.677748 35.025069 52.677748 30.108479 curveto +52.677748 25.191888 56.668024 21.201612 61.584614 21.201612 curveto +66.501204 21.201612 70.49148 25.191888 70.49148 30.108479 curveto +closepath +eofill +grestore +grestore +gsave [1.6418859 0 0 1.8055607 538.59447 444.01461] concat +gsave +0 0 0 setrgbcolor +newpath +67.437697 31.126406 moveto +67.437697 34.357308 64.815516 36.979489 61.584614 36.979489 curveto +58.353712 36.979489 55.731531 34.357308 55.731531 31.126406 curveto +55.731531 27.895504 58.353712 25.273323 61.584614 25.273323 curveto +64.815516 25.273323 67.437697 27.895504 67.437697 31.126406 curveto +closepath +eofill +grestore +grestore +gsave +0.27058825 0.48627451 0.05882353 setrgbcolor +newpath +581.35802 532.0079 moveto +581.35802 532.0079 590.96811 531.08894 587.62547 536.60273 curveto +584.28283 542.11652 573.00141 543.95445 580.10453 546.25186 curveto +587.20764 548.54927 624.81236 549.46824 628.99066 551.76565 curveto +633.16896 554.06306 621.05189 568.30702 613.11311 565.55012 curveto +605.17434 562.79323 593.89293 551.30617 582.19368 553.1441 curveto +570.49443 554.98203 559.21302 562.33375 558.79519 554.52255 curveto +558.37736 546.71134 567.56962 534.30532 581.35802 532.0079 curveto +closepath +eofill +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [9.9581957 96.715332 22.288982 86.950264] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +584.91531 528.92355 moveto +584.91531 528.92355 594.12586 528.0428 590.92219 533.32734 curveto +587.71852 538.61189 576.90615 540.3734 583.71394 542.5753 curveto +590.52173 544.77719 626.56298 545.65795 630.56756 547.85984 curveto +634.57215 550.06174 622.95886 563.71348 615.35015 561.07121 curveto +607.74144 558.42894 596.92906 547.41947 585.71623 549.18098 curveto +574.5034 550.9425 563.69102 557.98856 563.29056 550.50212 curveto +562.89011 543.01568 571.70019 531.12545 584.91531 528.92355 curveto +closepath +eoclip +gsave [2.4909379 0 0 1.1901263 538.73934 444.56248] concat +shfill +grestore +grestore +gsave +0.32156864 0.57647061 0.074509807 setrgbcolor +newpath +651.5535 540.27859 moveto +651.5535 540.27859 666.17755 545.3329 657.40312 547.17083 curveto +648.62868 549.00876 626.90151 546.71134 620.63406 551.30617 curveto +614.36661 555.90099 607.26349 570.60443 612.27746 573.36133 curveto +617.29142 576.11822 630.66198 560.49582 642.36123 558.1984 curveto +654.06048 555.90099 679.13029 557.27944 680.38378 552.68462 curveto +681.63727 548.08979 657.68987 534.19383 653.09374 534.19383 curveto +648.49761 534.19383 651.5535 540.27859 651.5535 540.27859 curveto +closepath +eofill +grestore +gsave [1.5138028 0 0 1.6647094 573.78363 440.3665] concat +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [39.077763 45.47282 38.935726 34.73687] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [0 0 0] +/C1 [0 0 0] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +51.150857 35.452599 moveto +51.150857 40.509662 47.046573 44.613946 41.98951 44.613946 curveto +36.932446 44.613946 32.828162 40.509662 32.828162 35.452599 curveto +32.828162 30.395535 36.932446 26.291251 41.98951 26.291251 curveto +47.046573 26.291251 51.150857 30.395535 51.150857 35.452599 curveto +closepath +eoclip +shfill +grestore +grestore +gsave [1.9194088 0 0 2.110749 526.87749 437.18904] concat +gsave +0.95686275 0.95686275 0.95686275 setrgbcolor +newpath +51.150857 35.452599 moveto +51.150857 40.509662 47.046573 44.613946 41.98951 44.613946 curveto +36.932446 44.613946 32.828162 40.509662 32.828162 35.452599 curveto +32.828162 30.395535 36.932446 26.291251 41.98951 26.291251 curveto +47.046573 26.291251 51.150857 30.395535 51.150857 35.452599 curveto +closepath +eofill +grestore +grestore +gsave [1.5138028 0 0 1.6647094 544.11762 452.31315] concat +gsave +0.87450981 0.82352942 0.44705883 setrgbcolor +newpath +51.150857 35.452599 moveto +51.150857 40.509662 47.046573 44.613946 41.98951 44.613946 curveto +36.932446 44.613946 32.828162 40.509662 32.828162 35.452599 curveto +32.828162 30.395535 36.932446 26.291251 41.98951 26.291251 curveto +47.046573 26.291251 51.150857 30.395535 51.150857 35.452599 curveto +closepath +eofill +grestore +grestore +gsave [1.5138028 0 0 1.6647094 544.11762 451.85354] concat +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [39.077763 45.47282 38.935726 34.73687] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [0 0 0] +/C1 [0 0 0] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +51.150857 35.452599 moveto +51.150857 40.509662 47.046573 44.613946 41.98951 44.613946 curveto +36.932446 44.613946 32.828162 40.509662 32.828162 35.452599 curveto +32.828162 30.395535 36.932446 26.291251 41.98951 26.291251 curveto +47.046573 26.291251 51.150857 30.395535 51.150857 35.452599 curveto +closepath +eoclip +shfill +grestore +grestore +gsave [1.6418859 0 0 1.8055607 539.38094 444.75289] concat +gsave +0 0 0 setrgbcolor +newpath +48.351557 36.216045 moveto +48.351557 39.587421 45.615368 42.32361 42.243992 42.32361 curveto +38.872616 42.32361 36.136427 39.587421 36.136427 36.216045 curveto +36.136427 32.84467 38.872616 30.10848 42.243992 30.10848 curveto +45.615368 30.10848 48.351557 32.84467 48.351557 36.216045 curveto +closepath +eofill +grestore +grestore +gsave [1.2624477 0 0 1.3882974 552.1086 456.0066] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [42.243992 36.216045 0 42.243992 36.216045 6.1075649] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +48.351557 36.216045 moveto +48.351557 39.587421 45.615368 42.32361 42.243992 42.32361 curveto +38.872616 42.32361 36.136427 39.587421 36.136427 36.216045 curveto +36.136427 32.84467 38.872616 30.10848 42.243992 30.10848 curveto +45.615368 30.10848 48.351557 32.84467 48.351557 36.216045 curveto +closepath +eoclip +shfill +grestore +grestore +gsave [1.2624477 0 0 1.3882974 582.90721 446.3383] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [42.243992 36.216045 0 42.243992 36.216045 6.1075649] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +48.351557 36.216045 moveto +48.351557 39.587421 45.615368 42.32361 42.243992 42.32361 curveto +38.872616 42.32361 36.136427 39.587421 36.136427 36.216045 curveto +36.136427 32.84467 38.872616 30.10848 42.243992 30.10848 curveto +45.615368 30.10848 48.351557 32.84467 48.351557 36.216045 curveto +closepath +eoclip +shfill +grestore +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [51.998035 87.448608 44.157574 78.630959] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +649.96666 539.48867 moveto +649.96666 539.48867 664.59071 544.54298 655.81627 546.38091 curveto +647.04185 548.21884 625.31467 545.92142 619.04722 550.51625 curveto +612.77977 555.11107 605.67665 569.81451 610.69062 572.57141 curveto +615.70458 575.3283 629.07514 559.7059 640.77439 557.40848 curveto +652.47364 555.11107 677.54345 556.48952 678.79694 551.8947 curveto +680.05042 547.29987 656.10303 533.40391 651.5069 533.40391 curveto +646.91076 533.40391 649.96666 539.48867 649.96666 539.48867 curveto +closepath +eoclip +gsave [2.2898233 0 0 1.2946538 538.73934 444.56248] concat +shfill +grestore +grestore +gsave [1.400681 -0.042370668 0.03852975 1.5403108 548.74078 452.34447] concat +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [50.072014 13.720966 26.487234 13.768328] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +24.859391 31.907937 moveto +23.419824 24.350211 24.964801 11.778293 30.054438 8.9789918 curveto +35.144076 6.1796912 40.379124 5.3034583 41.760605 9.7424375 curveto +43.243834 14.508354 39.448349 16.768623 34.704351 20.597833 curveto +29.745701 24.600304 28.340109 28.103497 24.859391 31.907937 curveto +closepath +eoclip +gsave [0.838005 0 0 1.19331 0 0] concat +shfill +grestore +grestore +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [84.674622 134.8858 79.578964 116.69227] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +616.907 580.83088 moveto +617.32484 578.07397 621.08532 558.31616 625.68146 555.09978 curveto +630.27761 551.88339 627.35279 558.31616 629.02412 561.53256 curveto +630.69544 564.74894 639.05207 551.88339 639.05207 557.3972 curveto +639.05207 562.91101 631.5311 566.58688 636.54508 565.6679 curveto +641.55906 564.74894 655.3475 560.1541 648.24436 566.12739 curveto +641.14122 572.10068 637.38074 580.83088 632.36677 578.07397 curveto +627.35279 575.31707 625.68146 584.04726 621.50315 584.04726 curveto +617.32484 584.04726 616.48917 584.04726 616.907 580.83088 curveto +closepath +eoclip +gsave [1.2747221 0 0 1.1373574 531.37626 430.58177] concat +shfill +grestore +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [36.185604 131.57237 34.983452 109.63145] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +581.39134 555.55926 moveto +581.39134 555.55926 585.56965 566.58688 589.74796 572.56017 curveto +593.92628 578.53345 588.49447 586.80416 583.06266 581.29036 curveto +577.63086 575.77656 560.49977 571.6412 560.9176 566.12739 curveto +561.33543 560.61358 568.43856 570.72224 569.69206 566.12739 curveto +570.94555 561.53256 561.33543 550.96442 566.34941 552.34288 curveto +571.36338 553.72133 575.12387 567.50584 576.37736 559.69462 curveto +577.63086 551.88339 575.95953 544.99114 581.39134 555.55926 curveto +closepath +eoclip +gsave [1.1551703 0 0 1.2550639 531.37626 430.58177] concat +shfill +grestore +grestore +gsave [0.3512975 0 0 0.3512975 625.25272 503.74669] concat +gsave [0 -0.525214 0.525214 0 11.42181 267.4213] concat +gsave +0.34117648 0.63529414 0.05882353 setrgbcolor +newpath +428.62836 222.16092 moveto +428.62836 323.67816 346.23755 406.06897 244.72031 406.06897 curveto +143.20306 406.06897 60.812256 323.67816 60.812256 222.16092 curveto +60.812256 120.64368 143.20306 38.252869 244.72031 38.252869 curveto +346.23755 38.252869 428.62836 120.64368 428.62836 222.16092 curveto +closepath +fill +grestore +0.34117648 0.63529414 0.05882353 setrgbcolor +[] 0 setdash +10.839739 setlinewidth +1 setlinejoin +0 setlinecap +newpath +428.62836 222.16092 moveto +428.62836 323.67816 346.23755 406.06897 244.72031 406.06897 curveto +143.20306 406.06897 60.812256 323.67816 60.812256 222.16092 curveto +60.812256 120.64368 143.20306 38.252869 244.72031 38.252869 curveto +346.23755 38.252869 428.62836 120.64368 428.62836 222.16092 curveto +closepath +stroke +grestore +gsave [0 -0.525214 0.525214 0 11.42181 267.4213] concat +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [60.812256 222.16092 428.62836 222.16092] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [0.34509805 0.28627452 0.90980393] +/C1 [0.12941177 0.074509807 0.6156863] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +428.62836 222.16092 moveto +428.62836 323.67816 346.23755 406.06897 244.72031 406.06897 curveto +143.20306 406.06897 60.812256 323.67816 60.812256 222.16092 curveto +60.812256 120.64368 143.20306 38.252869 244.72031 38.252869 curveto +346.23755 38.252869 428.62836 120.64368 428.62836 222.16092 curveto +closepath +clip +shfill +grestore +grestore +gsave [0 -0.525214 0.525214 0 11.42181 267.4213] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [244.72031 222.16092 0 244.72031 222.16092 183.90805] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [0.11764706 0.074509807 0.6156863] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [0.11764706 0.074509807 0.6156863] +/C1 [0.34509805 0.28627452 0.90980393] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.80000001 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +428.62836 222.16092 moveto +428.62836 323.67816 346.23755 406.06897 244.72031 406.06897 curveto +143.20306 406.06897 60.812256 323.67816 60.812256 222.16092 curveto +60.812256 120.64368 143.20306 38.252869 244.72031 38.252869 curveto +346.23755 38.252869 428.62836 120.64368 428.62836 222.16092 curveto +closepath +clip +shfill +grestore +grestore +gsave [0 0.382405 0.382405 0 43.14837 21.00481] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [49.709621 222.16092 0 49.709621 222.16092 183.90805] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +428.62836 222.16092 moveto +428.62836 323.67816 346.23755 406.06897 244.72031 406.06897 curveto +143.20306 406.06897 60.812256 323.67816 60.812256 222.16092 curveto +60.812256 120.64368 143.20306 38.252869 244.72031 38.252869 curveto +346.23755 38.252869 428.62836 120.64368 428.62836 222.16092 curveto +closepath +clip +gsave [1.353938 0 0 1.353938 -33.88875 -78.63119] concat +shfill +grestore +grestore +grestore +gsave [0 -0.306725 0.412392 0 36.48655 251.3615] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [69.944862 222.16092 0 69.944862 222.16092 183.90805] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +428.62836 222.16092 moveto +428.62836 323.67816 346.23755 406.06897 244.72031 406.06897 curveto +143.20306 406.06897 60.812256 323.67816 60.812256 222.16092 curveto +60.812256 120.64368 143.20306 38.252869 244.72031 38.252869 curveto +346.23755 38.252869 428.62836 120.64368 428.62836 222.16092 curveto +closepath +clip +gsave [1.353938 0 0 1.353938 -33.88875 -78.63119] concat +shfill +grestore +grestore +grestore +gsave [0.525214 0 0 0.525214 -0.426697 22.2088] concat +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [98 240.92043 420 240.92043] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +201.58219 398.66524 moveto +201.58219 398.66524 25.59643 220.69905 234.16166 39.888097 curveto +-1.634599 220.03851 202.12567 397.72391 201.58219 398.66524 curveto +closepath +eoclip +gsave [0.543478 -0.941332 0.941332 0.543478 -156.6701 314.8289] concat +shfill +grestore +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [98 240.92043 420 240.92043] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +418.06183 185.18557 moveto +418.06183 185.18557 240.09557 9.1998797 59.284695 217.76518 curveto +239.43502 -18.031148 417.12049 185.72905 418.06183 185.18557 curveto +closepath +eoclip +gsave [-0.941332 0.543478 0.543478 0.941332 334.2253 -173.0667] concat +shfill +grestore +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [98 240.92043 420 240.92043] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +66.93794 267.02123 moveto +66.93794 267.02123 244.9042 443.00692 425.71507 234.44162 curveto +245.56475 470.23795 67.879272 266.47776 66.93794 267.02123 curveto +closepath +eoclip +gsave [0.941332 -0.543478 -0.543478 -0.941332 150.7744 625.2735] concat +shfill +grestore +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [98 240.92043 420 240.92043] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +283.41758 47.541558 moveto +283.41758 47.541558 459.40333 225.50774 250.83811 406.3187 curveto +486.63436 226.16829 282.8741 48.482895 283.41758 47.541558 curveto +closepath +eoclip +gsave [-0.543478 0.941332 -0.941332 -0.543478 641.6699 131.3779] concat +shfill +grestore +grestore +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [246.35255 226.88303 0 246.35255 226.88303 154.3577] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +92 316 moveto +92 316 262.42047 243.53212 400.71024 137.76606 curveto +239 206 91 316 92 316 curveto +closepath +eoclip +gsave [1 -0.57734 0.12401 0.214795 -28.13556 320.3787] concat +shfill +grestore +grestore +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [246.35255 226.88303 0 246.35255 226.88303 154.3577] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +335.46957 381.23563 moveto +335.46957 381.23563 263.00169 210.81516 157.23563 72.525391 curveto +225.46957 234.23563 335.46957 382.23563 335.46957 381.23563 curveto +closepath +eoclip +gsave [-0.57734 -1 0.214795 -0.12401 339.8483 501.3712] concat +shfill +grestore +grestore +grestore +gsave [0.983093 0 0 0.983093 -24.81549 -4.294319] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.417478 0 0 0.417478 112.5483 29.80421] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.255874 0 0 0.255874 157.2722 63.78154] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.525214 0 0 0.525214 15.85494 9.603656] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.525214 0 0 0.525214 100.9397 30.61223] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.525214 0 0 0.525214 76.2546 115.6969] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.525214 0 0 0.525214 -10.93098 96.264] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.417478 0 0 0.417478 109.9222 127.494] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.255874 0 0 0.255874 123.1333 167.7739] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.417478 0 0 0.417478 13.28276 129.5949] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.417478 0 0 0.417478 13.28276 31.90504] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.255874 0 0 0.255874 19.66611 143.614] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +gsave [0.255874 0 0 0.255874 50.65376 36.99558] concat +gsave +<< +/ShadingType 3 +/ColorSpace /DeviceRGB +/Coords [156.5 148.5 0 156.5 148.5 19.5] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ 0.34999999 ] +/Encode [ 0 1 0 1 ] +>> +>> +newpath +176 148.5 moveto +176 159.264 167.264 168 156.5 168 curveto +145.736 168 137 159.264 137 148.5 curveto +137 137.736 145.736 129 156.5 129 curveto +167.264 129 176 137.736 176 148.5 curveto +closepath +clip +shfill +grestore +grestore +grestore +gsave +0.72156864 0.20392157 0.015686275 setrgbcolor +newpath +621.46972 524.65618 moveto +703.36444 498.92517 lineto +664.0884 533.38635 lineto +621.46972 524.65618 lineto +closepath +eofill +grestore +gsave +<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [58.108067 60.616997 42.782681 60.616997] +/Extend [true true] +/Domain [0 1] +/Function << +/FunctionType 3 +/Functions +[ +<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 1 1] +/C1 [1 1 1] +/N 1 +>> +] +/Domain [0 1] +/Bounds [ ] +/Encode [ 0 1 ] +>> +>> +newpath +630.28777 523.32068 moveto +697.733 502.12964 lineto +665.38682 530.5105 lineto +630.28777 523.32068 lineto +closepath +eoclip +gsave [2.6542399 0 0 1.1169018 538.73934 444.56248] concat +shfill +grestore +grestore +grestore +grestore +showpage +%%EOF Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/elyxer-eps.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/elyxer-eps.png differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/elyxer-svg.jpg and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/elyxer-svg.jpg differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/elyxer-svg.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/elyxer-svg.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/elyxer-svg.svg elyxer-1.2.5/forks/jras-elyxer/test/elyxer-svg.svg --- elyxer-1.2.3/forks/jras-elyxer/test/elyxer-svg.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/elyxer-svg.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/elyxer.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/elyxer.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/ert-good.html elyxer-1.2.5/forks/jras-elyxer/test/ert-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/ert-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/ert-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,53 @@ + + + + + + + + +ERT Test + + +
      +

      +ERT Test +

      +
      +This is a test for Evil Red Test (TeX code). +
      +
      +Pure TeX can contain formulas: Equation a = b. This activates the dorky math mode. +
      +
      +It can also contain arbitrary commands: $ http://elyxer.nongnu.org/ ○. +
      +
      +ERTs can be left open and be closed afterwards with text. This allows us to apply commands to arbitrary text: this text should be red, http://should.be.an.url/. +
      +
      +ERTs can also be inserted in formulas: +
      +
      +
      +(unnumbered) a = b. +
      + +
      +
      +Curly brackets can be inserted escaping them: { like this }. Also in a formula: {h}. Escaped curly brackets should not be confused with regular TeX brackets: {}. +
      +
      +A rule in an ERT:
      . +
      +
      +Other commands can be ignored: . TeX comments should also be ignored: but not text between comments. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/ert.lyx elyxer-1.2.5/forks/jras-elyxer/test/ert.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/ert.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/ert.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,298 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +\usepackage{url} +\usepackage{color} +\end_preamble +\use_default_options true +\begin_modules +theorems-ams +eqs-within-sections +figs-within-sections +\end_modules +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +ERT Test +\end_layout + +\begin_layout Standard +This is a test for Evil Red Test ( +\begin_inset ERT +status open + +\begin_layout Plain Layout + +TeX +\end_layout + +\end_inset + + code). +\end_layout + +\begin_layout Standard +Pure TeX can contain formulas: +\begin_inset ERT +status open + +\begin_layout Plain Layout + +Equation $a=b$ +\end_layout + +\end_inset + +. + This activates the dorky math mode. +\end_layout + +\begin_layout Standard +It can also contain arbitrary commands: +\begin_inset ERT +status open + +\begin_layout Plain Layout + + +\backslash +$ +\backslash +url{http://elyxer.nongnu.org/} +\backslash +Circle +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +ERTs can be left open +\begin_inset ERT +status open + +\begin_layout Plain Layout + +{ +\end_layout + +\end_inset + + and be closed afterwards +\begin_inset ERT +status open + +\begin_layout Plain Layout + +} with text +\end_layout + +\end_inset + +. + This allows us to apply commands to arbitrary text: +\begin_inset ERT +status open + +\begin_layout Plain Layout + +{ +\backslash +color{red} +\end_layout + +\end_inset + +this text should be red +\begin_inset ERT +status open + +\begin_layout Plain Layout + +} +\end_layout + +\end_inset + +, +\begin_inset ERT +status open + +\begin_layout Plain Layout + + +\backslash +url{ +\end_layout + +\end_inset + +http://should.be.an.url/ +\begin_inset ERT +status open + +\begin_layout Plain Layout + +} +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +ERTs can also be inserted in formulas: +\end_layout + +\begin_layout Standard +\begin_inset Formula \begin{equation} +a=b\tag{{unnumbered}}.\end{equation} + +\end_inset + + +\end_layout + +\begin_layout Standard +Curly brackets can be inserted escaping them: +\begin_inset ERT +status open + +\begin_layout Plain Layout + + +\backslash +{ like this +\backslash +} +\end_layout + +\end_inset + +. + Also in a formula: +\begin_inset Formula $\{h\}$ +\end_inset + +. + Escaped curly brackets should not be confused with regular TeX brackets: + +\begin_inset ERT +status open + +\begin_layout Plain Layout + +{ +\backslash +{ +\backslash +}} +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +A rule in an ERT: +\begin_inset ERT +status open + +\begin_layout Plain Layout + + +\backslash +rule{3cm}{2pt} +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +Other commands can be ignored: +\begin_inset ERT +status open + +\begin_layout Plain Layout + + +\backslash +fboxrule 3mm +\backslash +fboxsep 0.4mm +\end_layout + +\end_inset + +. + TeX comments should also be ignored: +\begin_inset ERT +status open + +\begin_layout Plain Layout + +%comment +\end_layout + +\begin_layout Plain Layout + +but not text between comments. +\end_layout + +\begin_layout Plain Layout + +% another comment +\end_layout + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/figures-good.html elyxer-1.2.5/forks/jras-elyxer/test/figures-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/figures-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/figures-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,452 @@ + + + + + + + + +Figures Test + + +
      +

      +Figures Test +

      + + +

      +1 Floats +

      +
      +First, figure 1↓. +
      +
      +
      +
      +
      +figure random.png + +
      +
      +Figure 1 A random image +
      + +
      + +
      + +
      +
      +Next, figure 2↓. +
      +
      +
      +
      + +
      +
      +figure lyx credits.png + +
      +
      +(a) Random image A +
      + +
      + +
      + +
      +
      +figure lyx credits.png + +
      +
      +(b) Random image B +
      + +
      + +
      +
      +Figure 2 Two random images +
      + +
      + +
      + +
      +
      +And last, 3↓. +
      +
      +
      +
      + +
      +
      +figure random.png + +
      +
      +(a) Random image A +
      + +
      + +
      + +
      +
      +figure random.png + +
      +
      +(b) Random image B +
      + +
      + +
      + +
      +
      +figure random.png + +
      +
      +(c) Random image C +
      + +
      + +
      +
      +Figure 3 Three random images +
      + +
      + +
      + +
      +
      +That’s all, folks. +
      +

      +2 Wraps +

      +
      +Now with wraps. +
      +
      +
      +
      +
      +figure random.png + +
      +
      +Figure 4 A wrapped image. +
      + +
      + +
      + +
      +
      +This image should wrap around the text. The text should be fairly complete and cover several paragraphs, but we might not get so much text. After all typing just because tends to bore the readers, who bear the grunt of the gruntwork of reading the resulting text. +
      +
      +
      +
      +
      +figure random.png + +
      +
      +Figure 5 Exterior wrapped image. +
      + +
      + +
      + +
      +
      +The next wrapping image should be smaller, and has default (outer) placement. Again, a lot of text would be required so the image fits around the text; the wrapped image will probably fall on some other page in the PDF, anyway. +
      +

      +3 Algorithms and Listings +

      +
      +We can also add a listing. +
      +
      +
      +
      This listing appears here courtesy of the fine Ministry of Silly Walks.
      +And appear here it does alright.
      +
      +
      + +
      +
      +And also a listing inside a float. +
      +
      +
      +
      +
      +
      This listing appears here courtesy of the fine Ministry of Silly Walks.
      +And appear here it does alright.
      +
      +
      +
      +Algorithm 1 An algorithm. +
      + +
      + +
      + +
      +
      +Another algorithm for the sake of it. +
      +
      +
      +
      +
      +\my_first_tex_command
      +it does not work at all!
      +\end_command +
      +
      +Algorithm 2 Another algorithm, embedded. +
      + +
      + +
      + +
      +
      +Now the same text outside the algorithm. +
      +
      +\my_first_tex_command
      +it does not work at all!
      +\end_command +
      +
      +And an algorithm without caption. +
      +
      +
      +
      +
      +\my_first_tex_command
      +it should work this time!
      +\end_command +
      + +
      + +
      + +
      +
      +Now a numbered listing. +
      +
      +
      +
      1This listing has been numbered.
      +2Each line has its own number.
      +
      +
      + +
      +
      +A numbered listing with a caption. +
      +
      +
      +
      1This listing has a caption.
      +
      +First caption which should not be numbered. +
      +
      2It should not be numbered.
      +3These lines, on the other hand, should.
      +
      +This second caption should not be numbered either. +
      + +
      + +
      +
      +As soon as we can get to it: a LyX-Code. +
      +
      +This is LyX-Code.
      +Code-LyX it’s not.
      +My heart will explode,
      +My tongue’s in a knot.
      +
      +
      +Another algorithm, this time without styling. +
      +
      +
      +
      +
      +Who shall declare this good, that ill
      +When good and ill so intertwine
      +But to fulfil the vast design of an omniscient will.
      +When seeming again but turns to loss
      +When earthly treasure proves but dross
      +And what seems lost but turns again
      +To high eternal gain. +
      +
      +Algorithm 4 A poem by Dame Irene Stoat. +
      + +
      + +
      + +
      +
      +And many other things. +
      +

      +4 Boxes (Minipages) +

      +
      +We can insert a box here: +
      +
      +
      +Well I, I think that, er, nobody who has gone abroad should be allowed back in the country. I mean, er, blimey, blimey if they’re not keen enough to stay here when they’re ’ere, why should we allow them back, er, at the tax-payers’ expense? I mean, be fair, I mean, I don’t eat squirrels do I? I mean well perhaps I do one or two but there’s no law against that, is there? It’s a free country. I mean if I want to eat a squirrel now and again, that’s me own business, innit? I mean, I’m no racialist. I, oh, oh... +
      + +
      +
      +A decorated centered box: +
      +
      +
      +
      +CONFUSE-A-CAT LIMITED +
      +
      +
      +INCORPORATING +
      + +
      +
      +
      +AMAZE-A-VOLE LTD +
      + +
      +
      +
      +STUN-A-STOAT LTD +
      + +
      +
      +
      +PUZZLE-A-PUMA LTD +
      + +
      +
      +
      +STARTLE-A-THOMPSON’S GAZELLE LTD +
      + +
      +
      +
      +BEWILDEREBEEST INC +
      + +
      +
      +
      +DISTRACT-A-BEE +
      + +
      + +
      + +
      +
      +And a double-decorated box with a certain width: +
      +
      +
      +
      +Goodnight. Ding-ding-ding-ding-ding, five, four, three, two, one… Goodnight. Ding-ding-ding-ding-ding, five, four, three, two, one…
      +Five, four, three, two, one, zero! +
      + +
      + +
      +
      +It was fine doing that. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/figures.lyx elyxer-1.2.5/forks/jras-elyxer/test/figures.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/figures.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/figures.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,985 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass scrartcl +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Figures Test +\end_layout + +\begin_layout Standard +\begin_inset FloatList figure + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset FloatList algorithm + +\end_inset + + +\end_layout + +\begin_layout Section +Floats +\end_layout + +\begin_layout Standard +First, figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:A-random-image" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename random.png + width 50col% + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:A-random-image" + +\end_inset + +A random image +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Next, figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:Two-random-images." + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename lyx credits.png + width 50col% + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Random image A +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename lyx credits.png + width 50col% + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Random image B +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:Two-random-images." + +\end_inset + +Two random images +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +And last, +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:Three-random-images" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename random.png + width 30col% + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Random image A +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename random.png + width 30col% + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Random image B +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename random.png + width 30col% + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Random image C +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:Three-random-images" + +\end_inset + +Three random images +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +That's all, folks. +\end_layout + +\begin_layout Section +Wraps +\end_layout + +\begin_layout Standard +Now with wraps. +\end_layout + +\begin_layout Standard +\begin_inset Wrap figure +lines 0 +placement l +overhang 0in +width "50col%" +status open + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename random.png + width 50col% + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +A wrapped image. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +This image should wrap around the text. + The text should be fairly complete and cover several paragraphs, but we + might not get so much text. + After all typing just because tends to bore the readers, who bear the grunt + of the gruntwork of reading the resulting text. +\end_layout + +\begin_layout Standard +\begin_inset Wrap figure +lines 0 +placement o +overhang 0in +width "4cm" +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename random.png + width 4cm + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Exterior wrapped image. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +The next wrapping image should be smaller, and has default (outer) placement. + Again, a lot of text would be required so the image fits around the text; + the wrapped image will probably fall on some other page in the PDF, anyway. +\end_layout + +\begin_layout Section +Algorithms and Listings +\end_layout + +\begin_layout Standard +We can also add a listing. +\end_layout + +\begin_layout Standard +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +This listing appears here courtesy of the fine Ministry of Silly Walks. +\end_layout + +\begin_layout Plain Layout + +And appear here it does alright. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +And also a listing inside a float. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Plain Layout +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +This listing appears here courtesy of the fine Ministry of Silly Walks. +\end_layout + +\begin_layout Plain Layout + +And appear here it does alright. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +An algorithm. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Another algorithm for the sake of it. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Quotation + +\family typewriter + +\backslash +my_first_tex_command +\end_layout + +\begin_layout Quotation + +\family typewriter +it does not work at all! +\end_layout + +\begin_layout Quotation + +\family typewriter + +\backslash +end_command +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Another algorithm, embedded. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Now the same text outside the algorithm. +\end_layout + +\begin_layout Quotation + +\family typewriter + +\backslash +my_first_tex_command +\end_layout + +\begin_layout Quotation + +\family typewriter +it does not work at all! +\end_layout + +\begin_layout Quotation + +\family typewriter + +\backslash +end_command +\end_layout + +\begin_layout Standard +And an algorithm without caption. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Quotation + +\family typewriter + +\backslash +my_first_tex_command +\end_layout + +\begin_layout Quotation + +\family typewriter +it should work this time! +\end_layout + +\begin_layout Quotation + +\family typewriter + +\backslash +end_command +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Now a numbered listing. +\end_layout + +\begin_layout Standard +\begin_inset listings +lstparams "numbers=left,stepnumber=1" +inline false +status open + +\begin_layout Plain Layout + +This listing has been numbered. +\end_layout + +\begin_layout Plain Layout + +Each line has its own number. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +A numbered listing with a caption. +\end_layout + +\begin_layout Standard +\begin_inset listings +lstparams "numbers=left,stepnumber=1" +inline false +status open + +\begin_layout Plain Layout + +This listing has a caption. +\end_layout + +\begin_layout Plain Layout + +\begin_inset Caption + +\begin_layout Plain Layout + +First caption which should not be numbered. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +It should not be numbered. +\end_layout + +\begin_layout Plain Layout + +These lines, on the other hand, should. +\end_layout + +\begin_layout Plain Layout + +\begin_inset Caption + +\begin_layout Plain Layout + +This second caption should not be numbered either. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +As soon as we can get to it: a LyX-Code. +\end_layout + +\begin_layout LyX-Code +This is LyX-Code. +\end_layout + +\begin_layout LyX-Code +Code-LyX it's not. +\end_layout + +\begin_layout LyX-Code +My heart will explode, +\end_layout + +\begin_layout LyX-Code +My tongue's in a knot. +\end_layout + +\begin_layout Standard +Another algorithm, this time without styling. +\end_layout + +\begin_layout Quote +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Plain Layout +Who shall declare this good, that ill +\end_layout + +\begin_layout Plain Layout +When good and ill so intertwine +\end_layout + +\begin_layout Plain Layout +But to fulfil the vast design of an omniscient will. +\end_layout + +\begin_layout Plain Layout +When seeming again but turns to loss +\end_layout + +\begin_layout Plain Layout +When earthly treasure proves but dross +\end_layout + +\begin_layout Plain Layout +And what seems lost but turns again +\end_layout + +\begin_layout Plain Layout +To high eternal gain. +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +A poem by Dame Irene Stoat. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +And many other things. +\end_layout + +\begin_layout Section +Boxes (Minipages) +\end_layout + +\begin_layout Standard +We can insert a box here: +\end_layout + +\begin_layout Standard +\begin_inset Box Frameless +position "t" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +width "100col%" +special "none" +height "1in" +height_special "totalheight" +status open + +\begin_layout Plain Layout +\noindent +Well I, I think that, er, nobody who has gone abroad should be allowed back + in the country. + I mean, er, blimey, blimey if they're not keen enough to stay here when + they're 'ere, why should we allow them back, er, at the tax-payers' expense? + I mean, be fair, I mean, I don't eat squirrels do I? I mean well perhaps + I do one or two but there's no law against that, is there? It's a free + country. + I mean if I want to eat a squirrel now and again, that's me own business, + innit? I mean, I'm no racialist. + I, oh, oh... + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +A decorated centered box: +\end_layout + +\begin_layout Standard +\begin_inset Box Boxed +position "t" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +width "100col%" +special "none" +height "1in" +height_special "totalheight" +status open + +\begin_layout Plain Layout +\noindent +\align center +CONFUSE-A-CAT LIMITED +\end_layout + +\begin_layout Plain Layout +\noindent +\align center +INCORPORATING +\end_layout + +\begin_layout Plain Layout +\noindent +\align center +AMAZE-A-VOLE LTD +\end_layout + +\begin_layout Plain Layout +\noindent +\align center +STUN-A-STOAT LTD +\end_layout + +\begin_layout Plain Layout +\noindent +\align center +PUZZLE-A-PUMA LTD +\end_layout + +\begin_layout Plain Layout +\noindent +\align center +STARTLE-A-THOMPSON'S GAZELLE LTD +\end_layout + +\begin_layout Plain Layout +\noindent +\align center +BEWILDEREBEEST INC +\end_layout + +\begin_layout Plain Layout +\noindent +\align center +DISTRACT-A-BEE +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +And a double-decorated box with a certain width: +\end_layout + +\begin_layout Standard +\begin_inset Box Doublebox +position "t" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +width "60col%" +special "none" +height "1in" +height_special "totalheight" +status open + +\begin_layout Plain Layout +Goodnight. + Ding-ding-ding-ding-ding, five, four, three, two, one\SpecialChar \ldots{} + Goodnight. + Ding-ding-ding-ding-ding, five, four, three, two, one\SpecialChar \ldots{} + +\end_layout + +\begin_layout Plain Layout +Five, four, three, two, one, zero! +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +It was fine doing that. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/file-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/file-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/file-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/file-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,70 @@ + + + + + + + + +File Test + + +
      +

      +File Test +

      +

      +Created by Alex Fernández +

      +
      +This document was created with LyX 1.6.2rc2, a great text editor. +
      +

      +Part I. The only part +

      +

      +1 The First Section +

      +
      +With some text. +And a greyed out note. + + +
      +

      +Another Section (Not Numbered) +

      +
      +With some more text. +
      +
      +Now we include a different document. +
      +
      + +
      +
      +Hello world +
      +
      +And now a verbatim include. +
      +
      + +
      +
      +Plain text document.
      +  To be included verbatim in a LyX document.
      +
      +Do not modify unless you want to test something.
      +
      +
      +
      +

      Index

      + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/file-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/file-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/file-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/file-1-6.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,184 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options true +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +File Test +\end_layout + +\begin_layout Author +Created by Alex Fernández +\end_layout + +\begin_layout Standard +This document was created with LyX 1.6.2rc2, a great text editor. +\end_layout + +\begin_layout Part +The only part +\end_layout + +\begin_layout Section +The First Section +\end_layout + +\begin_layout Standard +With some text. +\begin_inset Note Greyedout +status open + +\begin_layout Plain Layout +And a greyed out note. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section* +Another Section (Not Numbered) +\end_layout + +\begin_layout Standard +With some more text. +\begin_inset Note Note +status open + +\begin_layout Plain Layout +And a note which should not appear at all. +\end_layout + +\end_inset + + +\begin_inset Note Comment +status open + +\begin_layout Plain Layout +Actually, two notes which should not appear. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Now we include a different document. +\end_layout + +\begin_layout Standard +\begin_inset CommandInset include +LatexCommand include +filename "helloworld.lyx" + +\end_inset + + +\end_layout + +\begin_layout Standard +And now a verbatim include. +\end_layout + +\begin_layout Standard +\begin_inset CommandInset include +LatexCommand verbatiminput +filename "plain-text.txt" + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset Note Comment +status open + +\begin_layout Plain Layout +An include which should not appear since it's inside a comment. + +\begin_inset CommandInset include +LatexCommand include +filename "helloworld.lyx" + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset CommandInset index_print +LatexCommand printindex + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/footnotes-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/footnotes-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/footnotes-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/footnotes-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,82 @@ + + + + + + + + +Footnotes Tests + + +
      +

      +Footnotes Tests +

      + +

      +1 This is just some random section text used to insert some footnotes. [A]  [A] And this is one of those footnotes. +And this is a margin note, also tested here. + + +

      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing [B]  [B] adipisicing elit [C]  [C] elit, sed do eiusmod +eiusmod + + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa  [D]  [D] culpa qui officia  [E]  [E] officia deserunt mollit anim id est laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum [F]  [F] laborum, laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do tempor incididunt ut  [G]  [G] ut labore [H]  [H] labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod +eiusmod + + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis +Duis + + aute irure dolor in reprehenderit in voluptate velit [I]  [I] velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id +id + + est laborum. +
      +

      Nomenclature

      +eiusmod eiusmod indeed +
      +
      +

      +References +

      + +
      +

      Index

      +ullamco: +

      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/footnotes-1-6-hover-end-good.html elyxer-1.2.5/forks/jras-elyxer/test/footnotes-1-6-hover-end-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/footnotes-1-6-hover-end-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/footnotes-1-6-hover-end-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,82 @@ + + + + + + + + +Footnotes Tests + + +
      +

      +Footnotes Tests +

      + +

      +1 This is just some random section text used to insert some footnotes.[1] [1] And this is one of those footnotes. +And this is a margin note, also tested here. + + +

      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing[2] [2] adipisicing elit[3] [3] elit, sed do eiusmod +eiusmod + + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa [4] [4] culpa qui officia [5] [5] officia deserunt mollit anim id est laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum[6] [6] laborum, laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do tempor incididunt ut [7] [7] ut labore[8] [8] labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod +eiusmod + + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis +Duis + + aute irure dolor in reprehenderit in voluptate velit[9] [9] velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id +id + + est laborum. +
      +

      Nomenclature

      +eiusmod eiusmod indeed +
      +
      +

      +References +

      + +
      +

      Index

      +ullamco: +

      +

      Footnotes

      [1]And this is one of those footnotes.
      [2]adipisicing
      [3]elit
      [4]culpa
      [5]officia
      [6]laborum, laborum
      [7]ut
      [8]labore
      [9]velit
      + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/footnotes-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/footnotes-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/footnotes-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/footnotes-1-6.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,306 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Footnotes Tests +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Section +This is just some random section text used to insert some footnotes. +\begin_inset Foot +status open + +\begin_layout Plain Layout +And this is one of those footnotes. +\end_layout + +\end_inset + + +\begin_inset Marginal +status open + +\begin_layout Plain Layout +And this is a margin note, also tested here. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Lorem ipsum dolor sit amet, consectetur adipisicing +\begin_inset Foot +status open + +\begin_layout Plain Layout +adipisicing +\end_layout + +\end_inset + + elit +\begin_inset Foot +status open + +\begin_layout Plain Layout +elit +\end_layout + +\end_inset + +, sed do eiusmod +\begin_inset Marginal +status open + +\begin_layout Plain Layout +eiusmod +\end_layout + +\end_inset + + tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi + ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore + eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa +\begin_inset Foot +status open + +\begin_layout Plain Layout +culpa +\end_layout + +\end_inset + + qui officia +\begin_inset Foot +status open + +\begin_layout Plain Layout +officia +\end_layout + +\end_inset + + deserunt mollit anim id est laborum. +\end_layout + +\begin_layout Standard +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi + ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore + eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum +\begin_inset Foot +status open + +\begin_layout Plain Layout +laborum, laborum +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do +\begin_inset CommandInset nomenclature +LatexCommand nomenclature +symbol "eiusmod" +description "eiusmod indeed" + +\end_inset + + tempor incididunt ut +\begin_inset Foot +status open + +\begin_layout Plain Layout +ut +\end_layout + +\end_inset + + labore +\begin_inset Foot +status open + +\begin_layout Plain Layout +labore +\end_layout + +\end_inset + + et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco +\begin_inset Index +status open + +\begin_layout Plain Layout +ullamco +\end_layout + +\end_inset + + laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore + eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. +\end_layout + +\begin_layout Standard +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod +\begin_inset Marginal +status open + +\begin_layout Plain Layout +eiusmod +\end_layout + +\end_inset + + tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi + ut aliquip ex ea commodo consequat. + Duis +\begin_inset Marginal +status open + +\begin_layout Plain Layout +Duis +\end_layout + +\end_inset + + aute irure dolor in reprehenderit in voluptate velit +\begin_inset Foot +status open + +\begin_layout Plain Layout +velit +\end_layout + +\end_inset + + esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id +\begin_inset Marginal +status open + +\begin_layout Plain Layout +id +\end_layout + +\end_inset + + est laborum. +\end_layout + +\begin_layout Standard +\begin_inset CommandInset nomencl_print +LatexCommand printnomenclature + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset CommandInset bibtex +LatexCommand bibtex +bibfiles "bibtex-alpha" +options "plain" + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset CommandInset index_print +LatexCommand printindex + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/formula-good.html elyxer-1.2.5/forks/jras-elyxer/test/formula-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/formula-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/formula-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,35 @@ + + + + + + + + +Formula Test + + +
      +

      +Formula Test +

      +
      +Inline formula: a = b. Display formula:
      +b = a. +
      + Numbered formula:
      +(1) c = c +
      + +
      +
      +No more, no less. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/formula.lyx elyxer-1.2.5/forks/jras-elyxer/test/formula.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/formula.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/formula.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,96 @@ +#LyX 2.0 created this file. For more info see http://www.lyx.org/ +\lyxformat 413 +\begin_document +\begin_header +\textclass article +\use_default_options true +\maintain_unincluded_children false +\language english +\language_package default +\inputencoding auto +\fontencoding global +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\use_non_tex_fonts false +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\default_output_format default +\output_sync 0 +\bibtex_command default +\index_command default +\paperfontsize default +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\use_mhchem 1 +\use_mathdots 1 +\cite_engine basic +\use_bibtopic false +\use_indices false +\paperorientation portrait +\suppress_date false +\use_refstyle 1 +\index Index +\shortcut idx +\color #008000 +\end_index +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\paragraph_indentation default +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\html_math_output 0 +\html_css_as_file 0 +\html_be_strict false +\end_header + +\begin_body + +\begin_layout Title +Formula Test +\end_layout + +\begin_layout Standard +Inline formula: +\begin_inset Formula $a=b$ +\end_inset + +. + Display formula: +\begin_inset Formula +\[ +b=a. +\] + +\end_inset + + Numbered formula: +\begin_inset Formula +\begin{equation} +c=c +\end{equation} + +\end_inset + + +\end_layout + +\begin_layout Standard +No more, no less. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/helloworld-embedcss-good.html elyxer-1.2.5/forks/jras-elyxer/test/helloworld-embedcss-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/helloworld-embedcss-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/helloworld-embedcss-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,32 @@ + + + + + + + + + + +Converted document + + +
      +
      +Hello world +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/helloworld-good.html elyxer-1.2.5/forks/jras-elyxer/test/helloworld-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/helloworld-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/helloworld-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,23 @@ + + + + + + + + +Converted document + + +
      +
      +Hello world +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/helloworld-raw-good.html elyxer-1.2.5/forks/jras-elyxer/test/helloworld-raw-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/helloworld-raw-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/helloworld-raw-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,7 @@ + +
      +Hello world +
      + + + \ No newline at end of file diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/helloworld-template-good.html elyxer-1.2.5/forks/jras-elyxer/test/helloworld-template-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/helloworld-template-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/helloworld-template-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,20 @@ + + + + + + Converted document + + + + +
      +
      +Hello world +
      + + +

      (C) 2013

      +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/helloworld.lyx elyxer-1.2.5/forks/jras-elyxer/test/helloworld.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/helloworld.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/helloworld.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,68 @@ +#LyX 1.6.5 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language spanish +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Standard +Hello world +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/image-scaling-good.html elyxer-1.2.5/forks/jras-elyxer/test/image-scaling-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/image-scaling-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/image-scaling-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,80 @@ + + + + + + + + +Image Scaling Tests + + +
      +

      +Image Scaling Tests +

      +

      +1 Scale +

      +
      +figure elyxer.png +PNG unscaled. +
      +
      +figure elyxer.png +PNG scaled 50%. +
      +
      +figure elyxer-eps.png +Unscaled EPS. +
      +
      +figure elyxer-eps.png +EPS scaled 50%. +
      +

      +2 Exploring Width +

      +
      +figure elyxer.png +50% column width. +
      +
      +figure elyxer.png +5cm wide. +
      +
      +figure elyxer.png +50% line width. +
      +
      +figure elyxer.png +5mm wide. +
      +

      +3 Exploring Height +

      +
      +figure elyxer.png +50% column height. +
      +
      +figure elyxer.png +5cm high. +
      +
      +figure elyxer.png +50% page height. +
      +
      +figure elyxer.png +5 mm high. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/image-scaling.lyx elyxer-1.2.5/forks/jras-elyxer/test/image-scaling.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/image-scaling.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/image-scaling.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,207 @@ +#LyX 1.6.5 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Image Scaling Tests +\end_layout + +\begin_layout Section +Scale +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + +\end_inset + +PNG unscaled. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + scale 50 + +\end_inset + +PNG scaled 50%. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer-eps.eps + +\end_inset + +Unscaled EPS. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer-eps.eps + scale 50 + +\end_inset + +EPS scaled 50%. +\end_layout + +\begin_layout Section +Exploring Width +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + width 50col% + +\end_inset + +50% column width. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + width 5cm + +\end_inset + +5cm wide. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + width 50line% + +\end_inset + +50% line width. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + width 5mm + +\end_inset + +5mm wide. +\end_layout + +\begin_layout Section +Exploring Height +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + height 50col% + +\end_inset + +50% column height. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + height 5cm + +\end_inset + +5cm high. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + height 50page% + +\end_inset + +50% page height. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer.png + lyxscale 50 + height 5mm + +\end_inset + +5 mm high. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/index-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/index-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/index-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/index-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,484 @@ + + + + + + + + +Index Test + + +
      +

      +Index Test +

      + +

      +Part I. The Making +

      +

      +1 Explanations +

      +
      +This chapter contains a lot of explanations for terms, which you might want to look up later. Because better sooner than later, although later has been repeated twice. Actually, thrice now. +
      +
      +Do you not want to look any of them up right now? No problem. You will be able to do it later, in the index. +
      +
      +Now we will add two cites in one, just because [2, 3]. +
      +
      +As we will see in 3↓, not everything is clear. +
      +
      +You could also look down on someone, but that is not nice. +
      +

      +1.1Magical type face changes in the world +

      +
      +Little more can be added, at least at this point. +
      +

      +1.2Color and colour +

      +
      +At this other point, however, more could be added, but won’t. +
      +

      +Unnumbered Section +

      +
      +They have a right to live too. +
      +
        +
      • +A list would be nice here. +
      • +
      • +Because it corrupts the next chapter’s beginning. +
      • + +
      +

      +2 Nomenclature +

      +
      +We should explain what an index is. We can do that with the nomenclature. Normally we will want to mix index and nomenclature terms. But what happens if we actually do? We will know later, when we generate the file. +
      +

      +2.1 Reminder +

      +
      +We have to remind the reader that things will be remembered. +
      +

      +2.2 Remainder +

      +
      +Whatever remains should be explained here. +
      +

      +Part II. The Additions +

      +

      +3 Bulk +

      +
      +We actually need a lot more text in order for our index to have more terms; so we can find out if the links are working. Since they are anchors inside the page, they might otherwise just take us to the top of the page, and we would not like that. +
      +
      +Yes, it would be bad for us. But on the other hand too much text can hide errors. So not much more text is needed. +
      +
      +Thanks for reading us. +
      +

      +Unnumbered Part +

      +

      +Unnumbered Chapter +

      +
      +This extra chapter contains nothing of interest except for a couple of unnumbered parts (one actual part and one chapter). +
      +
      + +
      + +
      +
      +List of Figures +
      + + +
      +

      +Part III. Our Definition +

      +

      +4 The definition +

      +
      +A TOC is a Table Of Contents. +
      +

      +4.1 But I Already Knew That +

      +
      +You were lucky. +
      +

      +4.1.1 I Want My Money Back +

      +
      +There you have your 0€ back. +
      +

      +4.1.1.1 Completely Unfair Dude +

      +
      +Hey, I didn’t call you here. +
      +
      +A Paragraph For You +
      +
      +Totally uncalled for. +
      +
      +
      +
      +
      +figure elyxer-svg.png + +
      +
      +Figure 4.1 eLyXer logo +
      + +
      + +
      + +
      +

      +Unordered Section +

      +
      +Just to show that it works. +
      +
      +And now a list. +
      +
        +
      1. +First item. +
      2. +
      3. +We will embed an ordered subsection here just to fake it.

        +4.1.2 There We Go +

        + +
      4. +
      5. +See if it’s in your TOC. +
      6. + +
      +
      +But There Is More +
      +
      +And nothing else. +
      +

      +A Appendix +

      +
      +An appendix here, an appendix there. +
      +

      Index

      +able: +

      +

      +anchor: +

      +

      +error: +

      +

      +explained: +

      +

      +hand: +

      +

      +index: , , , +

      +

      +later: , , +

      +

      +link: +

      +

      +look: +

      +
      +

      +down: +

      +

      +up: , +

      + +
      +

      +page: +

      +

      +remembered: +

      +

      +sooner: +

      +

      +term: +

      +

      +terms: +

      +

      +text: , , +

      +

      +thrice: +

      +

      +top of the page: +

      +

      +twice: +

      +

      Nomenclature

      +generate An activity that requires a source and a destination, something like eLyXer does with files. +
      +
      +index A list of terms with a reference to where they occur. +
      +
      +nomenclature A list of common words with an explanation. +
      +

      +Bibliography +

      +

      +[1] WordReference.com: “definition of elixir”, accessed March 2009. http://www.wordreference.com/definition/elixir +

      +

      +[2] W3C: “HTML 4.01 Specification”, 24 December 1999. http://www.w3.org/TR/REC-html40/ +

      +

      +[3] W3C: “HTML 4.01 Specification”, 24 December 1999. http://www.w3.org/TR/REC-html40/ +

      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/index-1-6-lowmem-good.html elyxer-1.2.5/forks/jras-elyxer/test/index-1-6-lowmem-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/index-1-6-lowmem-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/index-1-6-lowmem-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,300 @@ + + + + + + + + +Index Test + + +
      +

      +Index Test +

      +
      +
      +Table of Contents +
      + +
      +

      +Part I. The Making +

      +

      +1 Explanations +

      +
      +This chapter contains a lot of explanations for terms, which you might want to look up later. Because better sooner than later, although later has been repeated twice. Actually, thrice now. +
      +
      +Do you not want to look any of them up right now? No problem. You will be able to do it later, in the index. +
      +
      +Now we will add two cites in one, just because [1, 2]. +
      +
      +As we will see in , not everything is clear. +
      +
      +You could also look down on someone, but that is not nice. +
      +

      +1.1Magical type face changes in the world +

      +
      +Little more can be added, at least at this point. +
      +

      +1.2Color and colour +

      +
      +At this other point, however, more could be added, but won’t. +
      +

      +Unnumbered Section +

      +
      +They have a right to live too. +
      +
        +
      • +A list would be nice here. +
      • +
      • +Because it corrupts the next chapter’s beginning. +
      • + +
      +

      +2 Nomenclature +

      +
      +We should explain what an index is. We can do that with the nomenclature. Normally we will want to mix index and nomenclature terms. But what happens if we actually do? We will know later, when we generate the file. +
      +

      +2.1 Reminder +

      +
      +We have to remind the reader that things will be remembered. +
      +

      +2.2 Remainder +

      +
      +Whatever remains should be explained here. +
      +

      +Part II. The Additions +

      +

      +3 Bulk +

      +
      +We actually need a lot more text in order for our index to have more terms; so we can find out if the links are working. Since they are anchors inside the page, they might otherwise just take us to the top of the page, and we would not like that. +
      +
      +Yes, it would be bad for us. But on the other hand too much text can hide errors. So not much more text is needed. +
      +
      +Thanks for reading us. +
      +

      +Unnumbered Part +

      +

      +Unnumbered Chapter +

      +
      +This extra chapter contains nothing of interest except for a couple of unnumbered parts (one actual part and one chapter). +
      +
      + +
      +
      +
      +Table of Contents +
      + +
      +
      +List of Figures +
      +

      +Part III. Our Definition +

      +

      +4 The definition +

      +
      +A TOC is a Table Of Contents. +
      +

      +4.1 But I Already Knew That +

      +
      +You were lucky. +
      +

      +4.1.1 I Want My Money Back +

      +
      +There you have your 0€ back. +
      +

      +4.1.1.1 Completely Unfair Dude +

      +
      +Hey, I didn’t call you here. +
      +
      +A Paragraph For You +
      +
      +Totally uncalled for. +
      +
      +
      +
      +
      +figure elyxer-svg.png + +
      +
      +Figure 4.1 eLyXer logo +
      + +
      + +
      + +
      +

      +Unordered Section +

      +
      +Just to show that it works. +
      +
      +And now a list. +
      +
        +
      1. +First item. +
      2. +
      3. +We will embed an ordered subsection here just to fake it.

        +4.1.2 There We Go +

        + +
      4. +
      5. +See if it’s in your TOC. +
      6. + +
      +
      +But There Is More +
      +
      +And nothing else. +
      +

      +A Appendix +

      +
      +An appendix here, an appendix there. +
      +

      Index

      +able: +

      +

      +anchor: +

      +

      +error: +

      +

      +explained: +

      +

      +hand: +

      +

      +index: , , , +

      +

      +later: , , +

      +

      +link: +

      +

      +look: +

      +
      +

      +down: +

      +

      +up: , +

      + +
      +

      +page: +

      +

      +remembered: +

      +

      +sooner: +

      +

      +term: +

      +

      +terms: +

      +

      +text: , , +

      +

      +thrice: +

      +

      +top of the page: +

      +

      +twice: +

      +

      Nomenclature

      +generate An activity that requires a source and a destination, something like eLyXer does with files. +
      +
      +index A list of terms with a reference to where they occur. +
      +
      +nomenclature A list of common words with an explanation. +
      +

      +Bibliography +

      +

      +[-] WordReference.com: “definition of elixir”, accessed March 2009. http://www.wordreference.com/definition/elixir +

      +

      +[1] W3C: “HTML 4.01 Specification”, 24 December 1999. http://www.w3.org/TR/REC-html40/ +

      +

      +[2] W3C: “HTML 4.01 Specification”, 24 December 1999. http://www.w3.org/TR/REC-html40/ +

      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/index-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/index-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/index-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/index-1-6.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,739 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass book +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . + +% DO NOT ALTER THIS PREAMBLE!!! +% +% This preamble is designed to ensure that the User's Guide prints +% out as advertised. If you mess with this preamble, +% parts of the User's Guide may not print out as expected. If you +% have problems LaTeXing this file, please contact +% the documentation team +% email: lyx-docs@lists.lyx.org + +\usepackage{ifpdf} % part of the hyperref bundle +\ifpdf % if pdflatex is used + + % set fonts for nicer pdf view + \IfFileExists{lmodern.sty}{\usepackage{lmodern}}{} + +\fi % end if pdflatex is used + +% for correct jump positions whe clicking on a link to a float +\usepackage[figure]{hypcap} + +% the pages of the TOC is numbered roman +% and a pdf-bookmark for the TOC is added +\let\myTOC\tableofcontents +\renewcommand{\tableofcontents}{% + \frontmatter + \pdfbookmark[1]{\contentsname}{} + \myTOC + \mainmatter } + +% redefine the \LyX macro for PDF bookmarks +\def\LyX{\texorpdfstring{% + L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} + {LyX}} + +% define a short command for \textvisiblespace +\newcommand{\spce}{\textvisiblespace} + +% macro for italic page numbers in the index +\newcommand{\IndexDef}[1]{\textit{#1}} + +% redefine the greyed out note +\end_preamble +\options intoc,bibtotoc,idxtotoc,BCOR7mm,tablecaptionabove +\use_default_options false +\begin_modules +theorems-ams +eqs-within-sections +figs-within-sections +\end_modules +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize 12 +\spacing single +\use_hyperref true +\pdf_title "Index Test" +\pdf_author "Alex Fernández" +\pdf_subject "Reconstituted from various sources" +\pdf_keywords "LyX" +\pdf_bookmarks true +\pdf_bookmarksnumbered true +\pdf_bookmarksopen false +\pdf_bookmarksopenlevel 1 +\pdf_breaklinks false +\pdf_pdfborder false +\pdf_colorlinks true +\pdf_backref false +\pdf_pdfusetitle false +\pdf_quoted_options "linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue,pdfpagelayout=OneColumn, pdfnewwindow=true,pdfstartview=XYZ, plainpages=false, pdfpagelabels,pdftex" +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 0 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 2 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Index Test +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Part +The Making +\end_layout + +\begin_layout Chapter +Explanations +\end_layout + +\begin_layout Standard +This chapter contains a lot of explanations for terms +\begin_inset Index +status open + +\begin_layout Plain Layout +terms +\end_layout + +\end_inset + +, which you might want to +\begin_inset Index +status open + +\begin_layout Plain Layout +look ! up +\end_layout + +\end_inset + +look up later +\begin_inset Index +status open + +\begin_layout Plain Layout +later +\end_layout + +\end_inset + +. + Because better sooner +\begin_inset Index +status open + +\begin_layout Plain Layout +sooner +\end_layout + +\end_inset + + than later, although later +\begin_inset Index +status open + +\begin_layout Plain Layout +later +\end_layout + +\end_inset + + has been repeated twice +\begin_inset Index +status open + +\begin_layout Plain Layout +twice +\end_layout + +\end_inset + +. + Actually, thrice +\begin_inset Index +status open + +\begin_layout Plain Layout +thrice +\end_layout + +\end_inset + + now. +\end_layout + +\begin_layout Standard +Do you not want to look any of them up +\begin_inset Index +status open + +\begin_layout Plain Layout +look ! up +\end_layout + +\end_inset + + right now? No problem. + You will be able +\begin_inset Index +status open + +\begin_layout Plain Layout +able +\end_layout + +\end_inset + + to do it later, in the index +\begin_inset Index +status open + +\begin_layout Plain Layout +index +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +Now we will add two cites in one, just because +\begin_inset CommandInset citation +LatexCommand cite +key "key-1,key-2" + +\end_inset + +. +\end_layout + +\begin_layout Standard +As we will see in +\begin_inset CommandInset ref +LatexCommand ref +reference "cha:Bulk" + +\end_inset + +, not everything is clear. +\end_layout + +\begin_layout Standard +You could also look down +\begin_inset Index +status open + +\begin_layout Plain Layout +look ! down +\end_layout + +\end_inset + + on someone, but that is not nice. +\end_layout + +\begin_layout Section + +\family typewriter +Magical +\family roman +type +\family default + +\emph on +face +\emph default + +\series medium +changes +\series default +\noun on +in +\noun default + +\size normal +the +\size default + world +\end_layout + +\begin_layout Standard +Little more can be added, at least at this point. +\end_layout + +\begin_layout Section + +\color red +Color +\color inherit + +\begin_inset space ~ +\end_inset + +and +\lang british +colour +\end_layout + +\begin_layout Standard +At this other point, however, more could be added, but won't. +\end_layout + +\begin_layout Section* +Unnumbered Section +\end_layout + +\begin_layout Standard +They have a right to live too. +\end_layout + +\begin_layout Itemize +A list would be nice here. +\end_layout + +\begin_layout Itemize +Because it corrupts the next chapter's beginning. +\end_layout + +\begin_layout Chapter +Nomenclature +\end_layout + +\begin_layout Standard +We should explain what an index +\begin_inset Index +status open + +\begin_layout Plain Layout +index +\end_layout + +\end_inset + + is. + We can do that with the nomenclature +\begin_inset CommandInset nomenclature +LatexCommand nomenclature +symbol "nomenclature" +description "A list of common words with an explanation." + +\end_inset + +. + Normally we will want to mix index +\begin_inset CommandInset nomenclature +LatexCommand nomenclature +symbol "index" +description "A list of terms with a reference to where they occur." + +\end_inset + + +\begin_inset Index +status open + +\begin_layout Plain Layout +index +\end_layout + +\end_inset + + and nomenclature terms. + But what happens if we actually do? We will know later +\begin_inset Index +status open + +\begin_layout Plain Layout +later +\end_layout + +\end_inset + +, when we generate +\begin_inset CommandInset nomenclature +LatexCommand nomenclature +symbol "generate" +description "An activity that requires a source and a destination, something like eLyXer does with files." + +\end_inset + + the file. +\end_layout + +\begin_layout Section +Reminder +\end_layout + +\begin_layout Standard +We have to remind the reader that things will be remembered +\begin_inset Index +status open + +\begin_layout Plain Layout +remembered +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Section +Remainder +\end_layout + +\begin_layout Standard +Whatever remains should be explained +\begin_inset Index +status open + +\begin_layout Plain Layout +explained +\end_layout + +\end_inset + + here. +\end_layout + +\begin_layout Part +The Additions +\end_layout + +\begin_layout Chapter +Bulk +\begin_inset OptArg +status open + +\begin_layout Plain Layout +Bulk, or what used to be bulk text +\end_layout + +\end_inset + + +\begin_inset CommandInset label +LatexCommand label +name "cha:Bulk" + +\end_inset + + +\end_layout + +\begin_layout Standard +We actually need a lot more text +\begin_inset Index +status open + +\begin_layout Plain Layout +text +\end_layout + +\end_inset + + in order for our index +\begin_inset Index +status open + +\begin_layout Plain Layout +index +\end_layout + +\end_inset + + to have more terms +\begin_inset Index +status open + +\begin_layout Plain Layout +term +\end_layout + +\end_inset + +; so we can find out if the links +\begin_inset Index +status open + +\begin_layout Plain Layout +link +\end_layout + +\end_inset + + are working. + Since they are anchors +\begin_inset Index +status open + +\begin_layout Plain Layout +anchor +\end_layout + +\end_inset + + inside the page +\begin_inset Index +status open + +\begin_layout Plain Layout +page +\end_layout + +\end_inset + +, they might otherwise just take us to the +\begin_inset Index +status open + +\begin_layout Plain Layout +top of the page +\end_layout + +\end_inset + +top of the page, and we would not like that. +\end_layout + +\begin_layout Standard +Yes, it would be bad for us. + But on the other hand +\begin_inset Index +status open + +\begin_layout Plain Layout +hand +\end_layout + +\end_inset + + too much text +\begin_inset Index +status open + +\begin_layout Plain Layout +text +\end_layout + +\end_inset + + can hide +\begin_inset Index +status open + +\begin_layout Plain Layout +error +\end_layout + +\end_inset + +errors. + So not much more text +\begin_inset Index +status open + +\begin_layout Plain Layout +text +\end_layout + +\end_inset + + is needed. +\end_layout + +\begin_layout Standard +Thanks for reading us. +\end_layout + +\begin_layout Part* +Unnumbered Part +\end_layout + +\begin_layout Chapter* +Unnumbered Chapter +\end_layout + +\begin_layout Standard +This extra chapter contains nothing of interest except for a couple of unnumbere +d parts (one actual part and one chapter). +\end_layout + +\begin_layout Standard +\begin_inset CommandInset include +LatexCommand include +filename "toc-book.lyx" + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset CommandInset index_print +LatexCommand printindex + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset CommandInset nomencl_print +LatexCommand printnomenclature + +\end_inset + + +\end_layout + +\begin_layout Bibliography +\begin_inset CommandInset bibitem +LatexCommand bibitem +key "wordreference-elixir" + +\end_inset + +WordReference.com: +\begin_inset Quotes eld +\end_inset + +definition of elixir +\begin_inset Quotes erd +\end_inset + +, accessed March 2009. + +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +http://www.wordreference.com/definition/elixir +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Bibliography +\begin_inset CommandInset bibitem +LatexCommand bibitem +key "key-1" + +\end_inset + +W3C: +\begin_inset Quotes eld +\end_inset + +HTML 4.01 Specification +\begin_inset Quotes erd +\end_inset + +, 24 December 1999. + +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +http://www.w3.org/TR/REC-html40/ +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Bibliography +\begin_inset CommandInset bibitem +LatexCommand bibitem +key "key-2" + +\end_inset + +W3C: +\begin_inset Quotes eld +\end_inset + +HTML 4.01 Specification +\begin_inset Quotes erd +\end_inset + +, 24 December 1999. + +\begin_inset Flex URL +status collapsed + +\begin_layout Plain Layout + +http://www.w3.org/TR/REC-html40/ +\end_layout + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/languages-good.html elyxer-1.2.5/forks/jras-elyxer/test/languages-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/languages-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/languages-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,26 @@ + + + + + + + + +Converted document + + +
      +
      +This is some English text. +
      +
      +Esto es texto en español. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/languages.lyx elyxer-1.2.5/forks/jras-elyxer/test/languages.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/languages.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/languages.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,76 @@ +#LyX 2.0 created this file. For more info see http://www.lyx.org/ +\lyxformat 413 +\begin_document +\begin_header +\textclass article +\use_default_options true +\maintain_unincluded_children false +\language russian +\language_package default +\inputencoding auto +\fontencoding global +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\use_non_tex_fonts false +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\default_output_format default +\output_sync 0 +\bibtex_command default +\index_command default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\use_mhchem 1 +\use_mathdots 1 +\cite_engine basic +\use_bibtopic false +\use_indices false +\paperorientation portrait +\suppress_date false +\use_refstyle 1 +\index Index +\shortcut idx +\color #008000 +\end_index +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\paragraph_indentation default +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\html_math_output 0 +\html_css_as_file 0 +\html_be_strict false +\end_header + +\begin_body + +\begin_layout Standard + +\lang english +This is some English text. +\end_layout + +\begin_layout Standard + +\lang spanish +Esto es texto en español. +\end_layout + +\end_body +\end_document Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/laurindas-anger.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/laurindas-anger.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/laurindas-anger.svg elyxer-1.2.5/forks/jras-elyxer/test/laurindas-anger.svg --- elyxer-1.2.3/forks/jras-elyxer/test/laurindas-anger.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/laurindas-anger.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,106 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/lists-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/lists-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/lists-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/lists-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,191 @@ + + + + + + + + +List Test + + +
      +

      +List Test +

      +
      +This document was created with LyX 1.6.2rc2, a great text editor. It is used to test lists, descriptions and item lists. +
      +

      +1 List and Description +

      +
      +Utenim ad minim veniam, quis nostrud exercitation +
      +
      +ullamcolaboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est +
      +
      +laborum. +
      +
      +Duis aute irure dolor in reprehenderit in +
      +
      +voluptate velit esse cillum dolore eu fugiat nulla pariatur. +
      +

      +2 Itemize and Enumerate +

      +
        +
      1. +First enumerated, +
      2. +
      3. +second enumerated. +
      4. + +
      +
        +
      • +First itemized, +
      • +
      • +second itemized. +
      • + +
      +

      +3 Lists with Levels +

      +
      +First a simple nested list. +
      +
        +
      • +Level one:
          +
        • +level two first item, +
        • +
        • +level two second item. +
        • + +
        + +
      • + +
      +
      +Now a more complex example. +
      +
        +
      • +First in first level:
          +
        • +first in second level, +
        • +
        • +second in second level, +
        • + +
        + +
      • +
      • +second in first level:
          +
        • +now third on second level:
            +
          • +third level 1, +
          • +
          • +third level 2. +
          • + +
          + +
        • + +
        + +
      • +
      • +back to third in first level. +
      • + +
      +
        +
      1. +Now 1st in 1st level:
          +
        1. +1st on 2nd level:
            +
          1. +1st on 3rd level! +
          2. +
          3. +2nd on 3rd level. +
          4. + +
          +
            +
          • +And now mixing 3rd level itemized, +
          • +
          • +and another. +
          • + +
          + +
        2. +
        3. +back to 2nd on 2nd street, sorry, level, +
        4. + +
        + +
      2. +
      3. +and back to 1st level:
        +Now with some non-list text. +
        +
          +
        1. +And an ordered list.
          +Just the nested text. +
          +
          +Repeated twice. +
          + +
        2. +
        3. +Second element in the ordered list. +
        4. + +
        +
          +
        • +For a still more difficult number: unordered now. +
        • + +
        +

        +3.1 And now a new subsection. +

        + +
      4. +
      5. +3rd on 1st level. +
      6. + +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/lists-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/lists-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/lists-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/lists-1-6.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,260 @@ +#LyX 1.6.5 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options true +\language spanish +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +List Test +\end_layout + +\begin_layout Standard +This document was created with LyX 1.6.2rc2, a great text editor. + It is used to test lists, descriptions and item lists. +\end_layout + +\begin_layout Section +List and Description +\end_layout + +\begin_layout List +\labelwidthstring 00.00.0000 +Ut enim ad minim veniam, quis nostrud exercitation +\end_layout + +\begin_layout List +\labelwidthstring 00.00.0000 +ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore + eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est +\end_layout + +\begin_layout List +\labelwidthstring 00.00.0000 +laborum. +\end_layout + +\begin_layout Description +Duis aute irure dolor in reprehenderit in +\end_layout + +\begin_layout Description +voluptate velit esse cillum dolore eu fugiat nulla pariatur. +\end_layout + +\begin_layout Section +Itemize and Enumerate +\end_layout + +\begin_layout Enumerate +First enumerated, +\end_layout + +\begin_layout Enumerate +second enumerated. +\end_layout + +\begin_layout Itemize +First itemized, +\end_layout + +\begin_layout Itemize +second itemized. +\end_layout + +\begin_layout Section +Lists with Levels +\end_layout + +\begin_layout Standard +First a simple nested list. +\end_layout + +\begin_layout Itemize +Level one: +\end_layout + +\begin_deeper +\begin_layout Itemize +level two first item, +\end_layout + +\begin_layout Itemize +level two second item. +\end_layout + +\end_deeper +\begin_layout Standard +Now a more complex example. +\end_layout + +\begin_layout Itemize +First in first level: +\end_layout + +\begin_deeper +\begin_layout Itemize +first in second level, +\end_layout + +\begin_layout Itemize +second in second level, +\end_layout + +\end_deeper +\begin_layout Itemize +second in first level: +\end_layout + +\begin_deeper +\begin_layout Itemize +now third on second level: +\end_layout + +\begin_deeper +\begin_layout Itemize +third level 1, +\end_layout + +\begin_layout Itemize +third level 2. +\end_layout + +\end_deeper +\end_deeper +\begin_layout Itemize +back to third in first level. +\end_layout + +\begin_layout Enumerate +Now 1st in 1st level: +\end_layout + +\begin_deeper +\begin_layout Enumerate +1st on 2nd level: +\end_layout + +\begin_deeper +\begin_layout Enumerate +1st on 3rd level! +\end_layout + +\begin_layout Enumerate +2nd on 3rd level. +\end_layout + +\begin_layout Itemize +And now mixing 3rd level itemized, +\end_layout + +\begin_layout Itemize +and another. +\end_layout + +\end_deeper +\begin_layout Enumerate +back to 2nd on 2nd street, sorry, level, +\end_layout + +\end_deeper +\begin_layout Enumerate +and back to 1st level: +\end_layout + +\begin_deeper +\begin_layout Standard +Now with some non-list text. +\end_layout + +\begin_layout Enumerate +And an ordered list. +\end_layout + +\begin_deeper +\begin_layout Standard +Just the nested text. +\end_layout + +\begin_layout Standard +Repeated twice. +\end_layout + +\end_deeper +\begin_layout Enumerate +Second element in the ordered list. +\end_layout + +\begin_layout Itemize +For a still more difficult number: unordered now. +\end_layout + +\begin_layout Subsection +And now a new subsection. +\end_layout + +\end_deeper +\begin_layout Enumerate +3rd on 1st level. +\end_layout + +\end_body +\end_document Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/lyx credits.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/lyx credits.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/math-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/math-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/math-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/math-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,852 @@ + + + + + + + + +Math Test + + +
      +

      +Math Test +

      +

      +1 Limits +

      +
      +A limit:
      +limx → ∞f(x),  +
      +which should appear as x → ∞ in italics, and «lim» in plain style. Inlined: limx → ∞f(x). +
      +
      +And why not, a sum:
      +i = 1ai,  +
      +where the sum’s limits should appear below (i = 1) and above () the but to the right. Inlined: i = 1ai. Integral: x = ax dx. Display mode:
      +x = ax dx. +
      + +
      +
      +We can also integrate without limits: A dx. +
      +
      +A sum inside another element (red color): +
      +
      +
      +i = 1ai. +
      + +
      +
      +The placing of limits can be cofigured with the \limits and \nolimits macros:
      +limx → ∞f(x),  i = 1x,  0f(x) dx +
      + +
      +

      +1.1 Super- and Subscript +

      +
      +When any element has both super- and subscript, they should appear like inlined limits, one above the other: a34. Also before an element: 32 He. In display mode: +
      +
      +
      +i, jaij + i, jaji = iaii,  +
      +
      +21 H + 21 H → 32 He + 10 n. +
      + +
      +

      +2 Numeration +

      +
      +Equations can be numbered, like 1↓. +
      +
      +
      +(1) y = x +
      + +
      +
      +And also like 2↓. +
      +
      +
      +(2) x = 3 +
      + +
      +
      +Notice that eq. 2↑ comes after eq. 1↑. +
      +
      +Some equations can also be numbered, even if they don’t have a label. +
      +
      +
      +(3) x = 2y +
      + +
      +
      +Other equations that contain * should not numbered, but perhaps aligned: +
      +
      +
      + + +left + + + + + +right + + + + +
      + +
      +
      +Some environments allow for multiple labels:
      + +(4) +a + + + =  + + +b × c + + + + + +  + + +  + + +  + + + + +(5) +c × d × e + + + =  + + +i. + + + + +
      + +
      +
      +Now a random environment: + +x + + + +y. +
      +

      +3 Brackets +

      +
      +An array:
      + + +12 + + +2 + + + + + +  + + +  + + + + + +3 + + +4 × yx + + + + +
      +And an inline array + +a + + +b + + + + + +  + + +  + + + + + +c + + +dio + + + +. +
      +
      +Arrays are separated by variable-size brackets: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + ||| + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||which might also differ on right and left + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or use the empty opening + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or closing: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||. There are also fixed-size big brackets: (a) [b] {c} d |e| f. +
      +
      +Aligned brackets can be present: (toText). One of them may be omitted: toText). +
      +
      +Aligned brackets can be applied to complex items:
      +s × 1 +  + +a11 + + +a21 + + + + + +  + + +  + + + + + +a12 + + +a22 + + + + ×  + +1 + + + − 1 + + + + + +  + + +  + + + + + + − 1 + + + − 1 + + + + +  + +1 + + + − 1 + + +0 + + + + + +  + + +  + + +  + + + + + + − 1 + + +1 + + +0 + + + + + +  + + +  + + +  + + + + + +0 + + +0 + + +r + + + +. +
      + +
      +
      +Math brackets should not be mistaken for TeX brackets: ({s(x)})/(2). +
      +

      +4 Fraction +

      +
      +A big recursive fraction:
      +(1)/(1 + (1)/(1 + (1)/(1 + 2x))) +
      + +
      +
      +A nice fraction: 56. +
      +
      +A non-diminishing fraction containing alignments:
      +(1)/(1 + (1)/(1 + x) × (1)/(1 + x)). +
      + +
      +
      +A similar concept is a binomial coefficient: (A + 1B). It can be prettily presented:
      +AB + 1. +
      + +
      +
      +A symbol can be stacked over another using \stackrel: xR → y. Anything can be stacked: headheels. +
      +

      +5 Roots +

      +
      +A square root: (3). A root in a fraction: (((78x + 45y) × (Height))/(sin(x + 1)) + 5). +
      +
      +A more complex square root in a fraction:
      +(1)/(1 + (2)(1)/(1 + (2)) + ((1)/(2))). +
      + +
      +
      +Higher order roots: 3(x + y), x + 1(Weight). In a fraction:
      +(78((8)/(4)x))/(s + 5(((78x + 45y) × (Height))/(sin(x + 1)) + 5)). +
      + +
      +

      +6 Decorations +

      +

      +6.1 Cases +

      +
      +Used to switch several values. +
      +
      +
      +y =  + + +x  + + +i = 0,   + + + + + +   + + +   + + + + + +x + 1  + + +i < 3  + + + + + + +
      + +
      +
      +Cases may have more than two rows: +
      +
      +
      +f(x) =  + + +0  + + +x < 0,   + + + + + +   + + +   + + + + + +∞  + + +x = 0,   + + + + + +   + + +   + + + + + +0  + + +x > 0  + + + + + + +
      + +
      +

      +6.2 Braces +

      +
      +Values can be underbraced or overbraced.
      +a − b = c + d + e + f. +
      + +
      +
      +Underbraces and overbraces can contain text.
      +a − bover = c + d + eover + funder + g. +
      +They can also be inlined: a + bover. +
      +

      +7 Spacing +

      +
      +The command \raisebox is useful to, surprisingly, raise a little box,
      +raisedoverlowered and back. +
      +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + BV. +
      +
      +There are other spacing commands: \hspace a b, protected space a b, and at “block level” \vspace: a b. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +8 Fonts +

      +
      +This section tests font support. +
      +

      +8.1 Variables and Functions +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic: αx + αy = α(x + y), with the exception of upright capital Greek letters, G ≠ Γ. Letters run together represent different variables: abcd = a × b × c × d. +
      +
      +There has been some trouble over some commands like Greek letters; some of them should be italicized, as in: μ or Å. Others should not, as in Ω. Upright Greek letters are also available: μ ≠ μ. An example from the LyX math guide:
       +  → μ +  + νμ. +
      + +
      +
      +Functions names should be upright: sin(2π), log(x), tanδ. +
      +

      +8.2 Mathematical Fonts +

      +
      +Mathematical fonts used in equations include Roman (\mathrm), Sans Serif (\mathsf), Typewriter (\mathtt), Bold (\mathbf), SCRIPT (\mathscr), CALLIGRAPHIC (\mathcal), BLACKBOARD BOLD (\mathbb), and Fraktur (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: , 𝔽, 𝔉. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: 5  to 10, via boxes like \mbox (prevents line breaks): 6  is more than 5, or the AMSmath \text macro (scales like math symbols) basesupersub. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: sfbfit, tipa. +
      +

      +8.3 Units +

      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, km, with magnitude, 57 km, with fractional unit, 200 kmh, or with a fraction before the units, 32 km, (7)/(16) s. +
      +

      +8.4 Sizes +

      +
      +Sizes can be specified in formulas: display, text, script, scriptscript. +
      +

      +9 Colors and Boxes +

      +
      +A colored box: aaa. +
      +
      +A framed box: box. It can be aligned left: box or right: box. +
      +

      +10 Macros +

      +
      +Definitions can be added as macros. Then they can be used in formulae: (12) + 1(2). +
      +
      +Macro definitions can accept default parameters. Again, useful in formulae: 4(5). Default parameters can then be overriden: 5(y) + x(4). +
      +
      +Other definitions from the preamble can be used: 3(4). +
      +
      +Definitions on the fly are also possible: 7(8), and used with different values: a(b). +
      +
      +Macros may contain a literal parameter. It should parse correctly: t. +
      +
      +A macro with four parameters from the LyX detailed math guide. Now in use: 1 + x1,  2 =  − ((1 − x))/(2)±(((1 − x)2)/(4) − 5) − B. +
      +

      +11 Pathological Cases +

      +
      +Empty equations have been known to fail: . +
      +
      +An equation with an mbox containing a comment: text more, and a comment inside textrm: text more. Finally, a comment at the end of a text function: only text. +
      +

      +12 Bye-bye +

      +
      +That’s all folks! +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/math-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/math-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/math-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/math-1-6.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1213 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass scrartcl +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . + +% DO NOT ALTER THIS PREAMBLE!!! +% +% This preamble is designed to ensure that the User's Guide prints +% out as advertised. If you mess with this preamble, +% parts of the User's Guide may not print out as expected. If you +% have problems LaTeXing this file, please contact +% the documentation team +% email: lyx-docs@lists.lyx.org + +\usepackage{ifpdf} % part of the hyperref bundle +\ifpdf % if pdflatex is used + + % set fonts for nicer pdf view + \IfFileExists{lmodern.sty}{\usepackage{lmodern}}{} + +\fi % end if pdflatex is used + +% for correct jump positions whe clicking on a link to a float +\usepackage[figure]{hypcap} + +% the pages of the TOC is numbered roman +% and a pdf-bookmark for the TOC is added +\let\myTOC\tableofcontents +\renewcommand{\tableofcontents}{% + \frontmatter + \pdfbookmark[1]{\contentsname}{} + \myTOC + \mainmatter } + +% redefine the \LyX macro for PDF bookmarks +\def\LyX{\texorpdfstring{% + L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} + {LyX}} + +% define a short command for \textvisiblespace +\newcommand{\spce}{\textvisiblespace} + +% macro for italic page numbers in the index +% test macro with a lot of spaces (bug #31243) +\newcommand % Renewing a command with spaces and comments +{ \IndexDef } [1] { \textit {#1} } + +% test macro with two arguments +\newcommand{\preambleroot}[2]{\sqrt[#1]{#2}} + +% redefine the greyed out note + +\usepackage{mathrsfs} +\usepackage{upgreek} +\end_preamble +\options intoc,bibtotoc,idxtotoc,BCOR7mm,tablecaptionabove +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize 12 +\spacing single +\use_hyperref true +\pdf_title "Math Test" +\pdf_author "Alex Fernández" +\pdf_subject "Taken from Guía de Usuario de Lyx, Ignacio García" +\pdf_keywords "LyX" +\pdf_bookmarks true +\pdf_bookmarksnumbered true +\pdf_bookmarksopen false +\pdf_bookmarksopenlevel 1 +\pdf_breaklinks false +\pdf_pdfborder false +\pdf_colorlinks true +\pdf_backref false +\pdf_pdfusetitle false +\pdf_quoted_options "linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue,pdfpagelayout=OneColumn, pdfnewwindow=true,pdfstartview=XYZ, plainpages=false, pdfpagelabels,pdftex" +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 0 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 2 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Math Test +\end_layout + +\begin_layout Section +Limits +\end_layout + +\begin_layout Standard +A limit: +\begin_inset Formula \[ +\lim_{x\rightarrow\infty}\lyxlock f(x),\] + +\end_inset + +which should appear as +\begin_inset Formula $x\rightarrow\infty$ +\end_inset + + in italics, and +\begin_inset Quotes fld +\end_inset + +lim +\begin_inset Quotes frd +\end_inset + + in plain style. + Inlined: +\begin_inset Formula $\lim_{x\rightarrow\infty}\lyxlock f(x)$ +\end_inset + +. +\end_layout + +\begin_layout Standard +And why not, a sum: +\begin_inset Formula \[ +\sum_{i=1}^{\infty}a_{i},\] + +\end_inset + +where the sum's limits should appear below ( +\begin_inset Formula $i=1$ +\end_inset + +) and above ( +\begin_inset Formula $\infty$ +\end_inset + +) the +\begin_inset Formula $\sum$ +\end_inset + + but to the right. + Inlined: +\begin_inset Formula $\sum_{i=1}^{\infty}a_{i}.$ +\end_inset + + Integral: +\begin_inset Formula $\intop_{x=a}^{\infty}x\,\text{d}x.$ +\end_inset + + Display mode: +\begin_inset Formula \[ +\intop_{x=a}^{\infty}x\,\text{d}x.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +We can also integrate without limits: +\begin_inset Formula $\int A\,\text{d}x$ +\end_inset + +. +\end_layout + +\begin_layout Standard +A sum inside another element (red color): +\end_layout + +\begin_layout Standard +\begin_inset Formula \[ +\textcolor{red}{\sum_{i=1}^{\infty}a_{i}}.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +The placing of limits can be cofigured with the +\family typewriter + +\backslash +limits +\family default + and +\family typewriter + +\backslash +nolimits +\family default + macros: +\begin_inset Formula \[ +\lim\nolimits _{x\rightarrow\infty}\lyxlock f(x),\;\sum\nolimits _{i=1}^{\infty}x,\;\int\limits _{0}^{\infty}f(x)\,\mathrm{d}x\] + +\end_inset + + +\end_layout + +\begin_layout Subsection +Super- and Subscript +\end_layout + +\begin_layout Standard +When any element has both super- and subscript, they should appear like + inlined limits, one above the other: +\begin_inset Formula $a_{4}^{3}$ +\end_inset + +. + Also before an element: +\begin_inset Formula $_{2}^{3}\text{He}$ +\end_inset + +. + In display mode: +\end_layout + +\begin_layout Standard +\begin_inset Formula \[ +\sum_{i,j}a_{j}^{i}+\sum_{i,j}a_{i}^{j}=\sum_{i}a_{i}^{i},\] + +\end_inset + + +\begin_inset Formula \[ +_{1}^{2}\text{H}+{}_{1}^{2}\text{H}\rightarrow{}_{2}^{3}\text{He}+{}_{0}^{1}\text{n}.\] + +\end_inset + + +\end_layout + +\begin_layout Section +Numeration +\end_layout + +\begin_layout Standard +Equations can be numbered, like +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:first" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Formula \begin{equation} +y=x\label{eq:first}\end{equation} + +\end_inset + + +\end_layout + +\begin_layout Standard +And also like +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:second" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Formula \begin{equation} +x=3\label{eq:second}\end{equation} + +\end_inset + + +\end_layout + +\begin_layout Standard +Notice that eq. + +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:second" + +\end_inset + + comes after eq. + +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:first" + +\end_inset + +. +\end_layout + +\begin_layout Standard +Some equations can also be numbered, even if they don't have a label. +\end_layout + +\begin_layout Standard +\begin_inset Formula \begin{equation} +x=2y\end{equation} + +\end_inset + + +\end_layout + +\begin_layout Standard +Other equations that contain * should not numbered, but perhaps aligned: +\end_layout + +\begin_layout Standard +\begin_inset Formula \begin{align*} +left & & right\end{align*} + +\end_inset + + +\end_layout + +\begin_layout Standard +Some environments allow for multiple labels: +\begin_inset Formula \begin{eqnarray} +a & = & b\times c\label{eq:third}\\ +c\times d\times e & = & i.\label{eq:fourth}\end{eqnarray} + +\end_inset + + +\end_layout + +\begin_layout Standard +Now a random environment: +\begin_inset Formula $\begin{gathered}x\end{gathered} +y$ +\end_inset + +. +\end_layout + +\begin_layout Section +Brackets +\end_layout + +\begin_layout Standard +An array: +\begin_inset Formula \[ +\left[\begin{array}{lc} +12 & 2\\ +3 & 4\times y^{x}\end{array}\right]\] + +\end_inset + +And an inline array +\begin_inset Formula $\left[\begin{array}[t]{cc} +a & b\\ +c & dio\end{array}\right]$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Arrays are separated by variable-size brackets: +\begin_inset Formula $\left(\begin{array}{cc} +a & b\\ +c & d\end{array}\right)$ +\end_inset + + +\begin_inset Formula $\left[\begin{array}{cc} +a & b\\ +c & d\end{array}\right]$ +\end_inset + + +\begin_inset Formula $\left\{ \begin{array}{cc} +a & b\\ +c & d\end{array}\right\} $ +\end_inset + + +\begin_inset Formula $\left\langle \begin{array}{cc} +a & b\\ +c & d\end{array}\right\rangle $ +\end_inset + + +\begin_inset Formula $\left|\begin{array}{cc} +a & b\\ +c & d\end{array}\right|$ +\end_inset + +which might also differ on right and left +\begin_inset Formula $\left(\begin{array}{cc} +a & b\\ +c & d\end{array}\right)$ +\end_inset + + or use the empty opening +\begin_inset Formula $\left\{ \begin{array}{cc} +a & b\\ +c & d\end{array}\right.$ +\end_inset + + or closing: +\begin_inset Formula $\left.\begin{array}{cc} +a & b\\ +c & d\end{array}\right|$ +\end_inset + +. + There are also fixed-size big brackets: +\begin_inset Formula $\left(a\right)$ +\end_inset + + +\begin_inset Formula $\left[b\right]$ +\end_inset + + +\begin_inset Formula $\left\{ c\right\} $ +\end_inset + + +\begin_inset Formula $\left\langle d\right\rangle $ +\end_inset + + +\begin_inset Formula $\left|e\right|$ +\end_inset + + +\begin_inset Formula $\bigl\langle f\bigr\rangle$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Aligned brackets can be present: +\begin_inset Formula $\left(toText\right)$ +\end_inset + +. + One of them may be omitted: +\begin_inset Formula $\left.toText\right)$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Aligned brackets can be applied to complex items: +\begin_inset Formula \[ +s\times\left(1+\left(\begin{array}{cc} +a_{11} & a_{21}\\ +a_{12} & a_{22}\end{array}\right)\times\left(\begin{array}{cc} +1 & -1\\ +-1 & -1\end{array}\right)+\left\Vert \begin{array}{ccc} +1 & -1 & 0\\ +-1 & 1 & 0\\ +0 & 0 & r\end{array}\right\Vert \right).\] + +\end_inset + + +\end_layout + +\begin_layout Standard +Math brackets should not be mistaken for TeX brackets: +\begin_inset Formula $\frac{\mathcal{F}\left\{ s(x)\right\} }{2}$ +\end_inset + +. +\end_layout + +\begin_layout Section +Fraction +\end_layout + +\begin_layout Standard +A big recursive fraction: +\begin_inset Formula \[ +\frac{1}{\left(1+\left(\frac{1}{1+\left(\frac{1}{1+2x}\lyxlock\right)}\lyxlock\right)\right)}\lyxlock\] + +\end_inset + + +\end_layout + +\begin_layout Standard +A nice fraction: +\begin_inset Formula $\nicefrac{5}{6}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +A non-diminishing fraction containing alignments: +\begin_inset Formula \[ +\cfrac{1}{1+\left(\cfrac[l]{1}{1+x}\times\cfrac[r]{1}{1+x}\right)}.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +A similar concept is a binomial coefficient: +\begin_inset Formula $\binom{A+1}{B}.$ +\end_inset + + It can be prettily presented: +\begin_inset Formula \[ +\dbinom{A}{B+1}.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +A symbol can be stacked over another using +\family typewriter + +\backslash +stackrel +\family default +: +\begin_inset Formula $x\stackrel{R}{\rightarrow}y$ +\end_inset + +. + Anything can be stacked: +\begin_inset Formula $\stackrel{head}{heels}$ +\end_inset + +. +\end_layout + +\begin_layout Section +Roots +\end_layout + +\begin_layout Standard +A square root: +\begin_inset Formula $\sqrt{3}.$ +\end_inset + + A root in a fraction: +\begin_inset Formula $\sqrt{\frac{(78x+45y)\times\sqrt{Height}}{\sin(x+1)}+5}.$ +\end_inset + + +\end_layout + +\begin_layout Standard +A more complex square root in a fraction: +\begin_inset Formula \[ +\frac{1}{\left(1+\sqrt{2}\left(\frac{1}{1+\sqrt{2}}\lyxlock\right)+\sqrt{\frac{1}{2}}\right)}\lyxlock.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +Higher order roots: +\begin_inset Formula $\sqrt[3]{x+y}$ +\end_inset + +, +\begin_inset Formula $\sqrt[x+1]{Weight}$ +\end_inset + +. + In a fraction: +\begin_inset Formula \[ +\frac{\sqrt[\nicefrac{7}{8}]{\frac{8}{4}x}}{\sqrt[s+5]{\frac{(78x+45y)\times\sqrt{Height}}{\sin(x+1)}+5}}\lyxlock.\] + +\end_inset + + +\end_layout + +\begin_layout Section +Decorations +\end_layout + +\begin_layout Subsection +Cases +\end_layout + +\begin_layout Standard +Used to switch several values. +\end_layout + +\begin_layout Standard +\begin_inset Formula \[ +y=\begin{cases} +x & i=0,\\ +x+1 & i<3\end{cases}\] + +\end_inset + + +\end_layout + +\begin_layout Standard +Cases may have more than two rows: +\end_layout + +\begin_layout Standard +\begin_inset Formula \[ +f(x)=\begin{cases} +0 & x<0,\\ +\infty & x=0,\\ +0 & x>0\end{cases}\] + +\end_inset + + +\end_layout + +\begin_layout Subsection +Braces +\end_layout + +\begin_layout Standard +Values can be underbraced or overbraced. +\begin_inset Formula \[ +\underbrace{a-b}=\overbrace{c+d+e}+f.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +Underbraces and overbraces can contain text. +\begin_inset Formula \[ +\overbrace{a-b}^{over}=\underbrace{c+\overbrace{d+e}^{over}+f}_{under}+g.\] + +\end_inset + +They can also be inlined: +\begin_inset Formula $\overbrace{a+b}^{over}$ +\end_inset + +. +\end_layout + +\begin_layout Section +Spacing +\end_layout + +\begin_layout Standard +The command +\family typewriter + +\backslash +raisebox +\family default + is useful to, surprisingly, raise a little box, +\begin_inset Formula \[ +\raisebox{2mm}{raised}over\raisebox{-2mm}{lowered}\textrm{ and back}.\] + +\end_inset + +Like +\family typewriter + +\backslash +mbox +\family default +, it puts its content in a text box. + It can also be used just for spacing: +\begin_inset Newline newline +\end_inset + + +\begin_inset Formula $\raisebox{5mm}{}B^{V}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +There are other spacing commands: +\family typewriter + +\backslash +hspace +\family default + +\begin_inset Formula $a\hspace{4mm}b$ +\end_inset + +, protected space +\begin_inset Formula $a\ b$ +\end_inset + +, and at +\begin_inset Quotes eld +\end_inset + +block level +\begin_inset Quotes erd +\end_inset + + +\family typewriter + +\backslash +vspace +\family default +: +\begin_inset Formula $a\vspace{1cm}b$ +\end_inset + +. +\end_layout + +\begin_layout Standard +There should be 1 +\begin_inset space ~ +\end_inset + +cm of vertical space above this paragraph. +\end_layout + +\begin_layout Section +Fonts +\end_layout + +\begin_layout Standard +This section tests font support. +\end_layout + +\begin_layout Subsection +Variables and Functions +\end_layout + +\begin_layout Standard +By default, letters denote variables and are taken from the +\family typewriter + +\backslash +mathnormal +\family default + font, which is italic: +\begin_inset Formula $\alpha x+\alpha y=\alpha(x+y)$ +\end_inset + +, with the exception of upright capital Greek letters, +\begin_inset Formula $G\ne\Gamma$ +\end_inset + +. + Letters run together represent different variables: +\begin_inset Formula $abcd=a\times b\times c\times d$ +\end_inset + +. + +\end_layout + +\begin_layout Standard +There has been some trouble over some commands like Greek letters; some + of them should be italicized, as in: +\begin_inset Formula $\mu$ +\end_inset + + or +\begin_inset Formula $\AA$ +\end_inset + +. + Others should not, as in +\begin_inset Formula $\Omega$ +\end_inset + +. + Upright Greek letters are also available: +\begin_inset Formula $\upmu\neq\mu$ +\end_inset + +. + An example from the LyX math guide: +\begin_inset Formula \[ +\uppi^{+}\to\upmu^{+}+\upnu_{\upmu}.\] + +\end_inset + + +\end_layout + +\begin_layout Standard +Functions names should be upright: +\begin_inset Formula $\sin(2\pi),\log(x),\tan\delta$ +\end_inset + +. +\end_layout + +\begin_layout Subsection +Mathematical Fonts +\end_layout + +\begin_layout Standard +Mathematical fonts used in equations include +\begin_inset Formula $\mathrm{Roman}$ +\end_inset + + ( +\family typewriter + +\backslash +mathrm +\family default +), +\begin_inset Formula $\mathsf{Sans\: Serif}$ +\end_inset + + ( +\family typewriter + +\backslash +mathsf +\family default +), +\begin_inset Formula $\mathtt{Typewriter}$ +\end_inset + + ( +\family typewriter + +\backslash +mathtt +\family default +), +\begin_inset Formula $\mathbf{Bold}$ +\end_inset + + ( +\family typewriter + +\backslash +mathbf +\family default +), +\begin_inset Formula $\mathscr{SCRIPT}$ +\end_inset + + ( +\family typewriter + +\backslash +mathscr +\family default +), +\begin_inset Formula $\mathcal{CALLIGRAPHIC}$ +\end_inset + + ( +\family typewriter + +\backslash +mathcal +\family default +), +\begin_inset Formula $\mathbb{BLACKBOARD\: BOLD}$ +\end_inset + + ( +\family typewriter +\noun on + +\backslash + +\noun default +mathbb +\family default +), and +\begin_inset Formula $\mathfrak{Fraktur}$ +\end_inset + + ( +\family typewriter + +\backslash +mathfrak +\family default +). + For the latter, some single characters are translated to their Unicode + equivalents: +\begin_inset Formula $\mathscr{F}$ +\end_inset + +, +\begin_inset Formula $\mathbb{F}$ +\end_inset + +, +\begin_inset Formula $\mathfrak{F}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Regular text in a formula can be achieved via text font commands like +\family typewriter + +\backslash +textrm +\family default +: +\begin_inset Formula $5\:\textrm{to}\:10$ +\end_inset + +, via boxes like +\backslash +mbox (prevents line breaks): +\begin_inset Formula $6\mbox{ is more than }5$ +\end_inset + +, or the AMSmath +\family typewriter + +\backslash +text +\family default + macro (scales like math symbols) +\begin_inset Formula $\text{base}_{\text{sub}}^{\text{super}}$ +\end_inset + +. + The content of an mbox is processed in LaTeX text mode. + This allows text font commands, e.g. + a switch to +\family sans +\series bold +\shape italic +sans-serif-bold-italic +\family default +\series default +\shape default +, or the phonetic alphabet: +\begin_inset Formula $\mbox{\textbf{\textsf{\textbf{\textit{sfbfit}}}}, \textipa{tipa}}$ +\end_inset + +. +\end_layout + +\begin_layout Subsection +Units +\end_layout + +\begin_layout Standard +Units should be written upright, either with +\family typewriter + +\backslash +mathrm +\family default + or with macros from the +\family typewriter +units +\family default + package, e.g. + as simple unit, +\begin_inset Formula $\unit{km}$ +\end_inset + +, with magnitude, +\begin_inset Formula $\unit[57]{km}$ +\end_inset + +, with fractional unit, +\begin_inset Formula $\unitfrac[200]{km}{h}$ +\end_inset + +, or with a fraction before the units, +\begin_inset Formula $\unit[\nicefrac{3}{2}]{km}$ +\end_inset + +, +\begin_inset Formula $\unit[\frac{7}{16}]{s}$ +\end_inset + +. +\end_layout + +\begin_layout Subsection +Sizes +\end_layout + +\begin_layout Standard +Sizes can be specified in formulas: +\begin_inset Formula ${\displaystyle \text{display}},{\textstyle \text{text}},{\scriptstyle \text{script}},{\scriptscriptstyle \text{scriptscript}}$ +\end_inset + +. +\end_layout + +\begin_layout Section +Colors and Boxes +\end_layout + +\begin_layout Standard +A colored box: +\begin_inset Formula $\colorbox{red}{aaa}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +A framed box: +\begin_inset Formula $\framebox[2cm][c]{box}$ +\end_inset + +. + It can be aligned left: +\begin_inset Formula $\framebox[2cm][l]{box}$ +\end_inset + + or right: +\begin_inset Formula $\framebox[2cm][r]{box}$ +\end_inset + +. +\end_layout + +\begin_layout Section +Macros +\end_layout + +\begin_layout Standard +Definitions can be added as macros +\begin_inset FormulaMacro +\renewcommand{\stupidroot}[2]{\sqrt[#1]{#2}} +{\sqrt[#1]{#2}} +\end_inset + +. + Then they can be used in formulae: +\begin_inset Formula $\stupidroot{}{12}+\stupidroot 12$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Macro definitions can accept default parameters +\begin_inset FormulaMacro +\renewcommand{\defaultroot}[2][4][5]{\sqrt[#1]{#2}} +{#1\sqrt{#2}} +\end_inset + +. + Again, useful in formulae: +\begin_inset Formula $\defaultroot$ +\end_inset + +. + Default parameters can then be overriden: +\begin_inset Formula $\defaultroot[][y]+\defaultroot[x]$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Other definitions from the preamble can be used: +\begin_inset Formula $\preambleroot{3}{4}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Definitions on the fly are also possible: +\begin_inset Formula $\newcommand{\ontheflyroot}[2]{\sqrt[#1]{#2}}\ontheflyroot{7}{8}$ +\end_inset + +, and used with different values: +\begin_inset Formula $\ontheflyroot{a}{b}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Macros may contain a literal parameter +\begin_inset FormulaMacro +\renewcommand{\colort}[1]{\colorbox{#1}{t}} +{\colorbox{#1}{t}} +\end_inset + +. + It should parse correctly: +\begin_inset Formula $\colort{red}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +A macro with four parameters from the LyX detailed math guide +\begin_inset FormulaMacro +\renewcommand{\qG}[4][1,\,2]{#2_{#1}=-\frac{#3}{2}\pm\sqrt{\frac{#3^{2}}{4}-#4}} +\end_inset + +. + Now in use: +\begin_inset Formula $1+\qG x{(1-x)}5-B$ +\end_inset + +. +\end_layout + +\begin_layout Section +Pathological Cases +\end_layout + +\begin_layout Standard +Empty equations have been known to fail: +\begin_inset Formula $ $ +\end_inset + +. +\end_layout + +\begin_layout Standard +An equation with an mbox containing a comment: +\begin_inset Formula $\mbox{text %comment +more}$ +\end_inset + +, and a comment inside textrm: +\begin_inset Formula $\textrm{text %comment +more}$ +\end_inset + +. + Finally, a comment at the end of a text function: +\begin_inset Formula $\mbox{only text%comment +}$ +\end_inset + +. +\end_layout + +\begin_layout Section +Bye-bye +\end_layout + +\begin_layout Standard +That's all folks! +\end_layout + +\end_body +\end_document Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/mini-elyxer.jpg and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/mini-elyxer.jpg differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/mourning.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/mourning.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/mourning.svg elyxer-1.2.5/forks/jras-elyxer/test/mourning.svg --- elyxer-1.2.3/forks/jras-elyxer/test/mourning.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/mourning.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,90 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/accept-all elyxer-1.2.5/forks/jras-elyxer/test/parts/accept-all --- elyxer-1.2.3/forks/jras-elyxer/test/parts/accept-all 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/accept-all 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,33 @@ +#!/bin/bash + +# eLyXer -- convert LyX source files to HTML output. +# +# Copyright (C) 2009 Alex Fernández +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Alex 20100419: accept all splitpart test files as good + +echo "Accepting all eLyXer splitpart test files as good" +echo "You should only do this if you have made a large change in all test files" +echo " and you are sure that all files come out right!" + + +# do it only for splitpart test files +for oldfile in *test*.html; do + newfile=${oldfile/"test"/"good"} + mv -f "$oldfile" "$newfile" +done + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/parts/elyxer-svg.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/parts/elyxer-svg.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-frameset.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-frameset.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-frameset.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-frameset.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,9 @@ + + + + + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-1.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-1.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-1.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-1.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,75 @@ + + + + + + + + +Index Test + + +
      +
      + Part I: The Making +Up Part I: The Making +Chapter 2: Nomenclature  +
      +

      +1 Explanations +

      +
      +This chapter contains a lot of explanations for terms, which you might want to look up later. Because better sooner than later, although later has been repeated twice. Actually, thrice now. +
      +
      +Do you not want to look any of them up right now? No problem. You will be able to do it later, in the index. +
      +
      +Now we will add two cites in one, just because [2, 3]. +
      +
      +As we will see in 3↓, not everything is clear. +
      +
      +You could also look down on someone, but that is not nice. +
      +

      +1.1Magical type face changes in the world +

      +
      +Little more can be added, at least at this point. +
      +

      +1.2Color and colour +

      +
      +At this other point, however, more could be added, but won’t. +
      +

      +Unnumbered Section +

      +
      +They have a right to live too. +
      +
        +
      • +A list would be nice here. +
      • +
      • +Because it corrupts the next chapter’s beginning. +
      • + +
      +
      + Part I: The Making +Up Part I: The Making +Chapter 2: Nomenclature  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-2.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-2.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-2.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-2.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,48 @@ + + + + + + + + +Index Test + + +
      +
      + Chapter 1: Explanations +Up Part I: The Making +Part II: The Additions  +
      +

      +2 Nomenclature +

      +
      +We should explain what an index is. We can do that with the nomenclature. Normally we will want to mix index and nomenclature terms. But what happens if we actually do? We will know later, when we generate the file. +
      +

      +2.1 Reminder +

      +
      +We have to remind the reader that things will be remembered. +
      +

      +2.2 Remainder +

      +
      +Whatever remains should be explained here. +
      +
      + Chapter 1: Explanations +Up Part I: The Making +Part II: The Additions  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-3.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-3.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-3.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-3.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,42 @@ + + + + + + + + +Index Test + + +
      +
      + Part II: The Additions +Up Part II: The Additions +Part: Unnumbered Part  +
      +

      +3 Bulk +

      +
      +We actually need a lot more text in order for our index to have more terms; so we can find out if the links are working. Since they are anchors inside the page, they might otherwise just take us to the top of the page, and we would not like that. +
      +
      +Yes, it would be bad for us. But on the other hand too much text can hide errors. So not much more text is needed. +
      +
      +Thanks for reading us. +
      +
      + Part II: The Additions +Up Part II: The Additions +Part: Unnumbered Part  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-4.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-4.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-4.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-4.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,106 @@ + + + + + + + + +Index Test + + +
      +
      + Part III: Our Definition +Up Part III: Our Definition +Appendix A: Appendix  +
      +

      +4 The definition +

      +
      +A TOC is a Table Of Contents. +
      +

      +4.1 But I Already Knew That +

      +
      +You were lucky. +
      +

      +4.1.1 I Want My Money Back +

      +
      +There you have your 0€ back. +
      +

      +4.1.1.1 Completely Unfair Dude +

      +
      +Hey, I didn’t call you here. +
      +
      +A Paragraph For You +
      +
      +Totally uncalled for. +
      +
      +
      +
      +
      +figure elyxer-svg.png + +
      +
      +Figure 4.1 eLyXer logo +
      + +
      + +
      + +
      +

      +Unordered Section +

      +
      +Just to show that it works. +
      +
      +And now a list. +
      +
        +
      1. +First item. +
      2. +
      3. +We will embed an ordered subsection here just to fake it.

        +4.1.2 There We Go +

        + +
      4. +
      5. +See if it’s in your TOC. +
      6. + +
      +
      +But There Is More +
      +
      +And nothing else. +
      +
      + Part III: Our Definition +Up Part III: Our Definition +Appendix A: Appendix  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-5.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-5.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-5.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-5.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,54 @@ + + + + + + + + +Article TOC Test + + +
      + +

      +5 But I Already Knew That +

      +
      +You were lucky. +
      +

      +I Want My Money Back +

      +
      +There you have your 0€ back. +
      +

      +Completely Unfair Dude +

      +
      +Hey, I didn’t call you here. +
      +
      +A Paragraph For You +
      +
      +Totally uncalled for. +
      + + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-A.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-A.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-A.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-A.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,36 @@ + + + + + + + + +Index Test + + +
      +
      + Chapter 4: The definition +Up Part III: Our Definition +Index  +
      +

      +A Appendix +

      +
      +An appendix here, an appendix there. +
      +
      + Chapter 4: The definition +Up Part III: Our Definition +Index  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Bibliography.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Bibliography.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Bibliography.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Bibliography.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,37 @@ + + + + + + + + +Index Test + + +
      +
      + Nomenclature +Up Main page + +
      +

      +Bibliography +

      +

      +[1] WordReference.com: “definition of elixir”, accessed March 2009. http://www.wordreference.com/definition/elixir +

      +

      +[2] W3C: “HTML 4.01 Specification”, 24 December 1999. http://www.w3.org/TR/REC-html40/ +

      +

      +[3] W3C: “HTML 4.01 Specification”, 24 December 1999. http://www.w3.org/TR/REC-html40/ +

      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Chapter--1.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Chapter--1.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Chapter--1.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Chapter--1.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,143 @@ + + + + + + + + +Index Test + + +
      +
      + Part: Unnumbered Part +Up Part: Unnumbered Part +Part III: Our Definition  +
      +

      +Unnumbered Chapter +

      +
      +This extra chapter contains nothing of interest except for a couple of unnumbered parts (one actual part and one chapter). +
      +
      + +
      + +
      +
      +List of Figures +
      + + +
      +
      + Part: Unnumbered Part +Up Part: Unnumbered Part +Part III: Our Definition  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Index.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Index.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Index.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Index.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,93 @@ + + + + + + + + +Index Test + + +
      +
      + Appendix A: Appendix +Up Main page +Nomenclature  +
      +

      Index

      +able: +

      +

      +anchor: +

      +

      +error: +

      +

      +explained: +

      +

      +hand: +

      +

      +index: , , , +

      +

      +later: , , +

      +

      +link: +

      +

      +look: +

      +
      +

      +down: +

      +

      +up: , +

      + +
      +

      +page: +

      +

      +remembered: +

      +

      +sooner: +

      +

      +term: +

      +

      +terms: +

      +

      +text: , , +

      +

      +thrice: +

      +

      +top of the page: +

      +

      +twice: +

      +
      + Appendix A: Appendix +Up Main page +Nomenclature  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Nomenclature.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Nomenclature.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Nomenclature.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Nomenclature.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,39 @@ + + + + + + + + +Index Test + + +
      +
      + Index +Up Main page +Bibliography  +
      +

      Nomenclature

      +generate An activity that requires a source and a destination, something like eLyXer does with files. +
      +
      +index A list of terms with a reference to where they occur. +
      +
      +nomenclature A list of common words with an explanation. +
      +
      + Index +Up Main page +Bibliography  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Part--I.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Part--I.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Part--I.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Part--I.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,44 @@ + + + + + + + + +Index Test + + +
      +
      + Chapter 3: Bulk, or what used to be bulk text +Up Main page +Chapter: Unnumbered Chapter  +
      +

      +Unnumbered Part +

      +
      +
      +Contents for Part +
      + + +
      +
      + Chapter 3: Bulk, or what used to be bulk text +Up Main page +Chapter: Unnumbered Chapter  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-I.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-I.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-I.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-I.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,66 @@ + + + + + + + + +Index Test + + +
      +
      + Main page +Up Main page +Chapter 1: Explanations  +
      +

      +Part I. The Making +

      + +
      + Main page +Up Main page +Chapter 1: Explanations  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-II.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-II.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-II.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-II.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,44 @@ + + + + + + + + +Index Test + + +
      +
      + Chapter 2: Nomenclature +Up Main page +Chapter 3: Bulk, or what used to be bulk text  +
      +

      +Part II. The Additions +

      +
      +
      +Contents for Part II +
      + + +
      +
      + Chapter 2: Nomenclature +Up Main page +Chapter 3: Bulk, or what used to be bulk text  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-III.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-III.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-III.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Part-III.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,70 @@ + + + + + + + + +Index Test + + +
      +
      + Chapter: Unnumbered Chapter +Up Main page +Chapter 4: The definition  +
      +

      +Part III. Our Definition +

      + +
      + Chapter: Unnumbered Chapter +Up Main page +Chapter 4: The definition  +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Section--2.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Section--2.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good-Section--2.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good-Section--2.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,73 @@ + + + + + + + + +Article TOC Test + + +
      + +

      +Unordered Section +

      +
      +Just to show that it works. +
      +
      +And now a list. +
      +
        +
      1. +First item. +
      2. +
      3. +We will embed an ordered subsection here just to fake it.

        +There We Go +

        + +
      4. +
      5. +See if it’s in your TOC. +
      6. + +
      +
      +But There Is More +
      +
      +And nothing else. +
      +
      +
      +Contents for Section +
      + + +
      + + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-part-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-part-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,128 @@ + + + + + + + + +Index Test + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-toc-good.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-toc-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-toc-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-toc-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,107 @@ + + + + + + + + +Index Test + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-toc-test.html elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-toc-test.html --- elyxer-1.2.3/forks/jras-elyxer/test/parts/index-1-6-toc-test.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/parts/index-1-6-toc-test.html 2013-03-10 10:39:47.000000000 +0000 @@ -0,0 +1,107 @@ + + + + + + + + +Index Test + + + + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/plain-text-good.html elyxer-1.2.5/forks/jras-elyxer/test/plain-text-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/plain-text-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/plain-text-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,56 @@ + + + + + + + + +Plain Text Test + + +
      +

      +Plain Text Test +

      +
      +This document will test whatever happens with plain text. +
      +

      +1 Paragraph Justification +

      +
      +
      +Well, to discuss the implications of that sketch and to consider the moral problems raised by the law-enforcement methods involved we have a duck, a cat and a lizard. +
      + +
      +
      +
      +Now first of all I’d like to put this question to you please, lizard. How effective do you consider the legal weapons employed by legal customs officers, nowadays? +
      + +
      +
      +
      +Well while you’re thinking about that, I’d like to bring the duck in here, and ask her, if possible, to clarify the whole question of currency restrictions, and customs regulations in the world today. +
      + +
      +
      +
      +Perhaps the cat would rather answer that? +
      + +
      +
      +That is all for now. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/plain-text.lyx elyxer-1.2.5/forks/jras-elyxer/test/plain-text.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/plain-text.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/plain-text.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,86 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\use_default_options true +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\end_header + +\begin_body + +\begin_layout Title +Plain Text Test +\end_layout + +\begin_layout Standard +This document will test whatever happens with plain text. +\end_layout + +\begin_layout Section +Paragraph Justification +\end_layout + +\begin_layout Standard +\align block +Well, to discuss the implications of that sketch and to consider the moral + problems raised by the law-enforcement methods involved we have a duck, + a cat and a lizard. +\end_layout + +\begin_layout Standard +\align left +Now first of all I'd like to put this question to you please, lizard. + How effective do you consider the legal weapons employed by legal customs + officers, nowadays? +\end_layout + +\begin_layout Standard +\align center +Well while you're thinking about that, I'd like to bring the duck in here, + and ask her, if possible, to clarify the whole question of currency restriction +s, and customs regulations in the world today. +\end_layout + +\begin_layout Standard +\align right +Perhaps the cat would rather answer that? +\end_layout + +\begin_layout Standard +That is all for now. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/plain-text.txt elyxer-1.2.5/forks/jras-elyxer/test/plain-text.txt --- elyxer-1.2.3/forks/jras-elyxer/test/plain-text.txt 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/plain-text.txt 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,5 @@ +Plain text document. + To be included verbatim in a LyX document. + +Do not modify unless you want to test something. + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/rabbit-walrus.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/rabbit-walrus.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/rabbit-walrus.svg elyxer-1.2.5/forks/jras-elyxer/test/rabbit-walrus.svg --- elyxer-1.2.3/forks/jras-elyxer/test/rabbit-walrus.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/rabbit-walrus.svg 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,106 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/random.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/random.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/references-good.html elyxer-1.2.5/forks/jras-elyxer/test/references-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/references-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/references-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,53 @@ + + + + + + + + +References Test + + +
      +

      +References Test +

      +

      +Alex Fernández (elyxer@gmail.com) +

      +

      +1 First Chapter +

      +
      +This first chapter contains the reference: 2↓, contained in chapter: 2↓. +
      +

      +1.1 Sectioned +

      +
      +This section contains a reference in brackets: (2↓). It should be on page: 1↓, and so be: 2 on page 1↓. +
      +
      +Adding a pretty reference: Chapter 2↓. Now a named reference: Second Chapter↓. +
      +

      +2 Second Chapter +

      +
      +This second chapter contains the label . +
      +

      +2.1 URIs +

      + + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/references.lyx elyxer-1.2.5/forks/jras-elyxer/test/references.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/references.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/references.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,214 @@ +#LyX 2.0.0svn created this file. For more info see http://www.lyx.org/ +\lyxformat 410 +\begin_document +\begin_header +\textclass book +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options true +\maintain_unincluded_children false +\language english +\inputencoding auto +\fontencoding global +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\use_non_tex_fonts false +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\default_output_format default +\output_sync 0 +\bibtex_command default +\index_command default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\use_mhchem 1 +\use_mathdots 1 +\cite_engine basic +\use_bibtopic false +\use_indices false +\paperorientation portrait +\suppress_date false +\use_refstyle 0 +\index Index +\shortcut idx +\color #008000 +\end_index +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\paragraph_indentation default +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\html_math_output 0 +\html_be_strict false +\end_header + +\begin_body + +\begin_layout Title +References Test +\begin_inset Note Note +status open + +\begin_layout Plain Layout +This note should not appear in the resulting page title +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Author +Alex Fernández (elyxer@gmail.com) +\end_layout + +\begin_layout Chapter +First Chapter +\end_layout + +\begin_layout Standard +This first chapter contains the reference: +\begin_inset CommandInset ref +LatexCommand ref +reference "cha:inchapter2" + +\end_inset + +, contained in chapter: +\begin_inset CommandInset ref +LatexCommand ref +reference "cha:Second-Chapter" + +\end_inset + +. +\end_layout + +\begin_layout Section +Sectioned +\end_layout + +\begin_layout Standard +This section contains a reference in brackets: +\begin_inset CommandInset ref +LatexCommand eqref +reference "cha:inchapter2" + +\end_inset + +. + It should be on page: +\begin_inset CommandInset ref +LatexCommand pageref +reference "cha:inchapter2" + +\end_inset + +, and so be: +\begin_inset CommandInset ref +LatexCommand vref +reference "cha:inchapter2" + +\end_inset + +. +\end_layout + +\begin_layout Standard +Adding a pretty reference: +\begin_inset CommandInset ref +LatexCommand formatted +reference "cha:inchapter2" + +\end_inset + +. + Now a named reference: +\begin_inset CommandInset ref +LatexCommand nameref +reference "cha:inchapter2" + +\end_inset + +. +\end_layout + +\begin_layout Chapter +Second Chapter +\begin_inset CommandInset label +LatexCommand label +name "cha:Second-Chapter" + +\end_inset + + +\end_layout + +\begin_layout Standard +This second chapter contains the label +\begin_inset CommandInset label +LatexCommand label +name "cha:inchapter2" + +\end_inset + +. +\end_layout + +\begin_layout Section +URIs +\end_layout + +\begin_layout Standard +Now a couple of test URIs: +\begin_inset CommandInset href +LatexCommand href +name "Savannah interface" +target "https://savannah.nongnu.org/bugs/?func=additem&group=elyxer" + +\end_inset + +, +\begin_inset CommandInset href +LatexCommand href +target "https://savannah.nongnu.org/bugs/?func=additem&group=elyxer" + +\end_inset + +. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/setcounter-good.html elyxer-1.2.5/forks/jras-elyxer/test/setcounter-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/setcounter-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/setcounter-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,111 @@ + + + + + + + + +Setcounter Test + + +
      +

      +Setcounter Test +

      + +
      +
      +List of Figures +
      + + +
      +

      +Part III. Third Part +

      +

      +4 Chapter Four +

      +
      +This is the fourth chapter, even if it comes out first. +
      +
      +
      +
      +
      +figure random.png + +
      +
      +Figure 4.1 Figure 4.1 it is. +
      + +
      + +
      + +
      +

      +4.1 Section Four Point One +

      +
      +This is the section 4.1, even if sections were bumped to 2. +
      +

      +4.1.1 Subsection 4.1.1 +

      +
      +Ignoring the subsection \setcounter statement in the preamble. +
      +

      +4.2 Section Four Point Two +

      +
      +Section 4.2 comes next. +
      +

      +5 Chapter Five +

      +
      +The last one. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/setcounter.lyx elyxer-1.2.5/forks/jras-elyxer/test/setcounter.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/setcounter.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/setcounter.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,184 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass book +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . + +\setcounter{part}{2} + +\setcounter{chapter}{3} + +\setcounter{figure}{4} + +\setcounter{section}{1} + +\setcounter{subsection}{5} +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 2 +\tocdepth 2 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Setcounter Test +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset FloatList figure + +\end_inset + + +\end_layout + +\begin_layout Part +Third Part +\end_layout + +\begin_layout Chapter +Chapter Four +\end_layout + +\begin_layout Standard +This is the fourth chapter, even if it comes out first. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\noindent +\align center +\begin_inset Graphics + filename random.png + scale 50 + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +Figure 4.1 it is. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +Section Four Point One +\end_layout + +\begin_layout Standard +This is the section 4.1, even if sections were bumped to 2. +\end_layout + +\begin_layout Subsection +Subsection 4.1.1 +\end_layout + +\begin_layout Standard +Ignoring the subsection +\family typewriter + +\backslash +setcounter +\family default + statement in the preamble. +\end_layout + +\begin_layout Section +Section Four Point Two +\end_layout + +\begin_layout Standard +Section 4.2 comes next. +\end_layout + +\begin_layout Chapter +Chapter Five +\end_layout + +\begin_layout Standard +The last one. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/spacing-good.html elyxer-1.2.5/forks/jras-elyxer/test/spacing-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/spacing-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/spacing-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,155 @@ + + + + + + + + +Spacing Test + + +
      +

      +Spacing Test +

      +

      +1 Paragraph +

      +
      +As our world turns more complex, paragraph spacing tends to be more and more important. +
      +
      +Some people would say that paragraph spacing is the first and foremost issue in our modern culture. Perhaps they can be said to be exaggerating, but not by much. +
      +

      +2 Issues in Horizontal Spacing +

      +
      +Some new issues arise every day. Today we would like to explore horizontal fill. +
      +
      + + + + + + + + + + + + + + + + + +
      +Cheese + +available +
      +Red Leicester + +no +
      +Tilsit + +no +
      + + + + + + + + + + + + + + + + + +
      +Cheese + +available +
      +Camembert + +runny +
      +Cheddar + +no +
      + +
      +
      +These tables should be separated by equal horizontal spacing. Can it be done? It should. +
      +

      +2.1 Horizontal Space +

      +
      +The horizontal space is inserted using Insert ▷ Format ▷ Horizontal space. The result is as follows: a b c d e  f. +
      +
      +Custom spaces can also be used: 01cm1in. +
      +

      +2.2 Half Spaces +

      +
      +As reported by Uwe Stöhr: 22 m, 3.53 €. It is correctly converted to a thin space. +
      +

      +3 Issues in Vertical Spacing +

      +
      +Vertical spacing can also be added. Let us now separate a few sentences with it. +
      +
      +
      +
      +
      +J. Losey
      +
      +
      +L. Anderson
      +
      +
      +S. Kubrick
      +
      +
      +P.P. Pasolini +
      +
      +
      + +
      + +
      +
      +O. Welles
      + +
      + +
      +
      +The Late B. Forbes +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/spacing.lyx elyxer-1.2.5/forks/jras-elyxer/test/spacing.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/spacing.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/spacing.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,383 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Spacing Test +\end_layout + +\begin_layout Section +Paragraph +\end_layout + +\begin_layout Standard +As our world turns more complex, paragraph spacing tends to be more and + more important. +\end_layout + +\begin_layout Standard +Some people would say that paragraph spacing is the first and foremost issue + in our modern culture. + Perhaps they can be said to be exaggerating, but not by much. +\end_layout + +\begin_layout Section +Issues in Horizontal Spacing +\end_layout + +\begin_layout Standard +Some new issues arise every day. + Today we would like to explore horizontal fill. +\end_layout + +\begin_layout Standard +\begin_inset space \hfill{} +\end_inset + + +\begin_inset Tabular + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Cheese +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +available +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Red Leicester +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +no +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Tilsit +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +no +\end_layout + +\end_inset + + + + +\end_inset + + +\begin_inset space \hfill{} +\end_inset + + +\begin_inset Tabular + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Cheese +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +available +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Camembert +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +runny +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Cheddar +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +no +\end_layout + +\end_inset + + + + +\end_inset + + +\begin_inset space \hfill{} +\end_inset + + +\end_layout + +\begin_layout Standard +These tables should be separated by equal horizontal spacing. + Can it be done? It should. +\end_layout + +\begin_layout Subsection +Horizontal Space +\end_layout + +\begin_layout Standard +The horizontal space is inserted using Insert\SpecialChar \menuseparator +Format\SpecialChar \menuseparator +Horizontal space. + The result is as follows: a +\begin_inset space \space{} +\end_inset + +b +\begin_inset space ~ +\end_inset + +c +\begin_inset space \enskip{} +\end_inset + +d +\begin_inset space \quad{} +\end_inset + +e +\begin_inset space \qquad{} +\end_inset + +f. +\end_layout + +\begin_layout Standard +Custom spaces can also be used: 0 +\begin_inset space \hspace{} +\length 1cm +\end_inset + +1cm +\begin_inset space \hspace{} +\length 1in +\end_inset + +1in. +\end_layout + +\begin_layout Subsection +Half Spaces +\end_layout + +\begin_layout Standard +As reported by Uwe Stöhr: 22 +\begin_inset space \thinspace{} +\end_inset + +m, 3.53 +\begin_inset space \thinspace{} +\end_inset + +€. + It is correctly converted to a thin space. +\end_layout + +\begin_layout Section +Issues in Vertical Spacing +\end_layout + +\begin_layout Standard +Vertical spacing can also be added. + Let us now separate a few sentences with it. +\end_layout + +\begin_layout Standard +\begin_inset VSpace defskip +\end_inset + + +\end_layout + +\begin_layout Standard +J. + Losey +\begin_inset VSpace smallskip +\end_inset + + +\end_layout + +\begin_layout Standard +L. + Anderson +\begin_inset VSpace medskip +\end_inset + + +\end_layout + +\begin_layout Standard +S. + Kubrick +\begin_inset VSpace bigskip +\end_inset + + +\end_layout + +\begin_layout Standard +P.P. + Pasolini +\end_layout + +\begin_layout Standard +\begin_inset VSpace 1.5ex +\end_inset + + +\end_layout + +\begin_layout Standard +O. + Welles +\begin_inset VSpace 1in +\end_inset + + +\end_layout + +\begin_layout Standard +The Late B. + Forbes +\end_layout + +\end_body +\end_document Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/square.jpg and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/square.jpg differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/square.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/square.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/subdir/appendix-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/subdir/appendix-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/subdir/appendix-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/subdir/appendix-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,543 @@ + + + + + + + + +Appendix Test + + +
      +

      +Appendix Test +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + + + +

      +Part I. Of How Our Hero Came and Went +

      +

      +1 The Coming +

      +
      +Our hero came in. He was tired. He thought the world belonged to him. +
      +

      +1.1 The Meeting +

      +
      +Our hero met with Laurinda. She was smiling. But our hero was not amused. His whiskers were dripping wet, he was astonishingly thirsty, and the contradiction was killing him. “Give me some beer, woman!”, he ordered. +
      +

      +1.2 The Melting +

      +
      +Laurinda smiled again. “But Wenceslau, you don’t belong here.” What a stupid thing to say at that precise moment, our hero thought to himself. Only that it came out loud. At that precise moment he knew that the desired beer would not be forthcoming. +
      +
      +He turned to the bartender and tried to obtain a beer by the very old method of purchasing it. But being ignored was not one of Laurinda’s specialities. +
      +

      +2 The Going +

      +
      +It could not last. Laurinda’s hips were flapping, and she was hopping mad. +
      +

      +2.1 Our Hero’s Imagination +

      +
      +Our hero imagined her as a rabbit with long ears and a fine set of tusks. In a short time the image drifted to a walrus, and our hero could not help letting his sinister smile giving him away. Figure 2.1↓ shows a gross approximation of the rabbit-walrus. +
      +
      +
      +
      +
      +figure rabbit-walrus.png + +
      +
      +Figure 2.1 The rabbit-walrus. +
      + +
      + +
      + +
      +

      +2.2 Laurinda’s Anger +

      +
      +“Wasn’t it great”, said Laurinda. Actually she said it in the present tense, but our poor storytelling skills have changed that to a cheesy past. Don’t do this at home, kids. You want to be regarded for your authenticity, and misquoting isn’t going to help much. +
      +
      +Anyway, back to the story. Laurinda wanted to hit him in the head with a big ham that she kept just for occassions like this, and being a solid Hitchcock fan she was ready to cook the ham afterwards and serve the resulting stew to any policemen that might come by. She was also a huge Almodóvar fan, but she was unaware that in an early film the divine Pedro had copied the scene. Actually both directors had copied the idea from a short story by Roald Dahl, very much worth reading. Although it must be said that in this story it was a lamb leg, which hardly offers the consistency and stiffness necessary to kill a sturdy husband. +
      +
      +But who cares. Laurinda meanwhile had a funny appearance; if you want to see why please direct your eyes to figure 2.2↓. +
      +
      +
      +
      +
      +figure laurindas-anger.png + +
      +
      +Figure 2.2 Laurinda’s anger pictured in a mildly humorous tone. +
      + +
      + +
      + +
      +
      +And yet, how furious was really Laurinda, whom we may optionally refer to as Melinda from now on? Table 2.1↓ vainly attempts to quantify it. +
      +
      +
      +
      +
      + + + + + + + + + + + + +
      +Anger + +Time +
      +1 + +2 +
      + +
      +
      +Table 2.1 Laurinda’s anger as a function of time. +
      + +
      + +
      + +
      +
      +For the sake of Laurinda’s furiousness, here is figure 2.3↓ again. +
      +
      +
      +
      +
      +figure laurindas-anger.png + +
      +
      +Figure 2.3 Laurinda’s anger, again. +
      + +
      + +
      + +
      +
      +But how did Laurinda compute her anger? We cannot but speculate; here is a stupid suggestion in listing 2.1↓. +
      +
      +
      +
      +anger = time - 1
      +Algorithm 2.1 Laurinda computes her anger. +
      + +
      + +
      + +
      +
      +The result is in table 2.2↓, proving we were right all along. Also subtables a↓ and b↓ show anger and time, respectively. +
      +
      +
      +
      +
      + +
      +
      + + + + + + + + + + +
      +Anger +
      +1 +
      + +
      +
      +(a) Only Anger. +
      + +
      + +
      + +
      +
      + + + + + + + + + + +
      +Time +
      +2 +
      +
      +(b) Only Time. +
      + +
      + +
      + +
      + +
      +
      +Table 2.2 Laurinda’s anger quantified, divided in two. +
      + +
      + +
      + +
      +
      +Interested in that last table? Let us repeat it but without a label and with a table and a subtable a↓. +
      +
      +
      +
      +
      + +
      +Censored
      +(a) The rabbit-walrus does an encore. +
      + +
      + +
      + + + + + + + + + + + + +
      +Anger + +Time +
      +1 + +2 +
      + +
      +
      +Table 2.3 One more time. +
      + +
      + +
      + +
      +

      +2.3 The Passing Away +

      +
      +Our hero was passing by the village. He had only stopped to say “Hi!” Again here our lousy skills have made us spoil the quote, but this time for the opposite reasons: everyone knows how to say “Hi!”, so we don’t need an actual quote. It is enough to report that the had stopped to say hi, even maybe qualifying it a bit to make do for the missing exclamation sign: he could have stopped to say a friendly hi. Getting all literary he could have stopped to say a longing hi, although this road leads to bizarreness. It could be cool though. +
      +
      +But anyway. Laurinda was so mad, so hopping mad that she called her friend, the Assassin. He was not in town at that precise moment, but that didn’t help our hero as he was just outside town killing people in a small barn. Just for practice. +
      +
      +Our hero left the village, but Laurinda cunningly annotated the MAC address of his laptop’s wifi card. The lack of networking knowledge on the part of our hero (who really couldn’t tell a SYN packet from an ACK) was to play an important part in the story — if he had known how to change the MAC address, which identified him with the precision of a surgeon’s scalpel, he would have been safe. +
      +
      +Let’s not even get into that last scalpel metaphor, shall we not? It leaks worse than the Titanic. +
      +

      +Part II. Of How Our Hero Went No More +

      +

      +3 The Killing +

      +
      +Our hero led a happy existence for a long time afterwards, randomly avoiding all points within connecting distance of a wifi network. It could not last. +
      +
      +Our hero went to the next village, found a friendly Moonrams cafe and connected to the net. Quickly the assassin (who knew the very people that run the internet, and who by this display of nerdiness no longer merits the starting capital letter) traced a bunch of IP packets coming from our hero’s MAC address. He deployed a team of murderous African bees, which as surely as a well-cared-for AK-47 reached our hero and killed him with three fast stings. Of course they died afterwards, being bees and all, so it was an astounding feat this training of wild African bees just for this one murder. Maybe the Assassin merits that capital letter after all. +
      +

      +3.1 The Passing Away +

      +
      +Our hero was undone. He was no more. He was, actually, an ex-hero. We shall narrate his wake soon. +
      +
        +
      • +But first a message from our kind sponsors. They want to present you the next section in this deeper inset.

        +3.2 The Mourning +

        +
        +Everyone cried in the ceremony. It was so sad that we need an image of this moment. You can find it in figure 3.1↓. +Mental note: never pay the artist beforehand. + + +
        + +
      • + +
      +
      +
      +
      +
      +figure mourning.png + +
      +
      +Figure 3.1 A crude approximation to our hero’s mourning. +
      + +
      + +
      + +
      +
      +And thusly everything happened. +
      +

      +4 The Mourning +

      +
      +We have already talked at length about the mourning, and under sponsorship no less, so no further details will be given here. Suffice to say that our hero was mourned. A lot. +
      +

      +A The Rebirth +

      +
      +Surprising everyone, our hero was about to make a comeback. +
      +

      +A.1 Coming Again +

      +
      +As it happened, our hero had never died; he had just faked his own death to find out his assassin. It was not difficult, what with the capital letter and all. +
      +

      +A.2 Two is Better than One +

      +
      +How to make another comeback? This is left as an exercise to the reader. +
      +

      +B Our Recommendation to Kids +

      +
      +Never trust killer bees. Or Assassins. +
      +

      +B.1 Killer Bees and Their Perils +

      +
      +A killer bee cannot be trained consistently, since it will die at the first sting. Better use killing wasps — or, even better, solve your differencies talking. +
      +
      +For the sake of your education, check figure B.1↓. It shows a bunch of killer bees, or something. +
      +
      +
      +
      +
      +figure mourning.png + +
      +
      +Figure B.1 A gathering of killer bees. Supposedly. +
      + +
      + +
      + +
      +

      +B.2 Assassins: Inherently Unreliable +

      +
      +Someone who kills people (even for business) is not someone you want to deal with. Watch “Fargo” by the Coen Brothers if you don’t believe me. And remember: a hero under the belt is a feather on the hat. +
      + + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/subdir/appendix-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/subdir/appendix-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/subdir/appendix-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/subdir/appendix-1-6.lyx 2013-03-10 10:39:45.000000000 +0000 @@ -0,0 +1,1164 @@ +#LyX 1.6.5 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass scrbook +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . + +% DO NOT ALTER THIS PREAMBLE!!! +% +% This preamble is designed to ensure that the User's Guide prints +% out as advertised. If you mess with this preamble, +% parts of the User's Guide may not print out as expected. If you +% have problems LaTeXing this file, please contact +% the documentation team +% email: lyx-docs@lists.lyx.org + +\usepackage{ifpdf} % part of the hyperref bundle +\ifpdf % if pdflatex is used + + % set fonts for nicer pdf view + \IfFileExists{lmodern.sty}{\usepackage{lmodern}}{} + +\fi % end if pdflatex is used + +% for correct jump positions whe clicking on a link to a float +\usepackage[figure]{hypcap} + +% the pages of the TOC is numbered roman +% and a pdf-bookmark for the TOC is added +\let\myTOC\tableofcontents +\renewcommand{\tableofcontents}{% + \frontmatter + \pdfbookmark[1]{\contentsname}{} + \myTOC + \mainmatter } + +% redefine the \LyX macro for PDF bookmarks +\def\LyX{\texorpdfstring{% + L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} + {LyX}} + +% define a short command for \textvisiblespace +\newcommand{\spce}{\textvisiblespace} + +% macro for italic page numbers in the index +\newcommand{\IndexDef}[1]{\textit{#1}} + +% redefine the greyed out note +\end_preamble +\options intoc,bibtotoc,idxtotoc,BCOR7mm,tablecaptionabove +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize 12 +\spacing single +\use_hyperref true +\pdf_title "Appendix Test" +\pdf_author "Alex Fernández" +\pdf_subject "Containing Numeration and Other Appendixy things" +\pdf_keywords "LyX eLyXer" +\pdf_bookmarks true +\pdf_bookmarksnumbered true +\pdf_bookmarksopen false +\pdf_bookmarksopenlevel 1 +\pdf_breaklinks false +\pdf_pdfborder false +\pdf_colorlinks true +\pdf_backref false +\pdf_pdfusetitle false +\pdf_quoted_options "linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue,pdfpagelayout=OneColumn, pdfnewwindow=true,pdfstartview=XYZ, plainpages=false, pdfpagelabels,pdftex" +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 0 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 2 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Appendix Test +\end_layout + +\begin_layout Author +Alex Fernández (elyxer@gmail.com) +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset FloatList figure + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset FloatList table + +\end_inset + + +\end_layout + +\begin_layout Part +Of How Our Hero Came and Went +\end_layout + +\begin_layout Chapter +The Coming +\end_layout + +\begin_layout Standard +Our hero came in. + He was tired. + He thought the world belonged to him. +\end_layout + +\begin_layout Section +The Meeting +\end_layout + +\begin_layout Standard +Our hero met with Laurinda. + She was smiling. + But our hero was not amused. + His whiskers were dripping wet, he was astonishingly thirsty, and the contradic +tion was killing him. + +\begin_inset Quotes eld +\end_inset + +Give me some beer, woman! +\begin_inset Quotes erd +\end_inset + +, he ordered. +\end_layout + +\begin_layout Section +The Melting +\end_layout + +\begin_layout Standard +Laurinda smiled again. + +\begin_inset Quotes eld +\end_inset + +But Wenceslau, you don't belong here. +\begin_inset Quotes erd +\end_inset + + What a stupid thing to say at that precise moment, our hero thought to + himself. + Only that it came out loud. + At that precise moment he knew that the desired beer would not be forthcoming. +\end_layout + +\begin_layout Standard +He turned to the bartender and tried to obtain a beer by the very old method + of purchasing it. + But being ignored was not one of Laurinda's specialities. +\end_layout + +\begin_layout Chapter +The Going +\end_layout + +\begin_layout Standard +It could not last. + Laurinda's hips were flapping, and she was hopping mad. +\end_layout + +\begin_layout Section +Our Hero's Imagination +\end_layout + +\begin_layout Standard +Our hero imagined her as a rabbit with long ears and a fine set of tusks. + In a short time the image drifted to a walrus, and our hero could not help + letting his sinister smile giving him away. + Figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:rabbit-walrus" + +\end_inset + + shows a gross approximation of the rabbit-walrus. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename rabbit-walrus.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:rabbit-walrus" + +\end_inset + +The rabbit-walrus. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +Laurinda's Anger +\end_layout + +\begin_layout Standard +\begin_inset Quotes eld +\end_inset + +Wasn't it great +\begin_inset Quotes erd +\end_inset + +, said Laurinda. + Actually she said it in the present tense, but our poor storytelling skills + have changed that to a cheesy past. + Don't do this at home, kids. + You want to be regarded for your authenticity, and misquoting isn't going + to help much. +\end_layout + +\begin_layout Standard +Anyway, back to the story. + Laurinda wanted to hit him in the head with a big ham that she kept just + for occassions like this, and being a solid Hitchcock fan she was ready + to cook the ham afterwards and serve the resulting stew to any policemen + that might come by. + She was also a huge Almodóvar fan, but she was unaware that in an early + film the divine Pedro had copied the scene. + Actually both directors had copied the idea from a short story by Roald + Dahl, very much worth reading. + Although it must be said that in this story it was a lamb leg, which hardly + offers the consistency and stiffness necessary to kill a sturdy husband. +\end_layout + +\begin_layout Standard +But who cares. + Laurinda meanwhile had a funny appearance; if you want to see why please + direct your eyes to figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:anger" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename laurindas-anger.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:anger" + +\end_inset + +Laurinda's anger pictured in a mildly humorous tone. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +And yet, how furious was really Laurinda, whom we may optionally refer to + as Melinda from now on? Table +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:anger-time" + +\end_inset + + vainly attempts to quantify it. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Anger +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Time +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2 +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:anger-time" + +\end_inset + +Laurinda's anger as a function of time. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +For the sake of Laurinda's furiousness, here is figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:anger-again" + +\end_inset + + again. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename laurindas-anger.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:anger-again" + +\end_inset + +Laurinda's anger, again. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +But how did Laurinda compute her anger? We cannot but speculate; here is + a stupid suggestion in listing +\begin_inset CommandInset ref +LatexCommand ref +reference "alg:computation" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float algorithm +wide false +sideways false +status open + +\begin_layout Plain Layout +anger = time - 1 +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "alg:computation" + +\end_inset + +Laurinda computes her anger. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +The result is in table +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:anger-time-again" + +\end_inset + +, proving we were right all along. + Also subtables +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Only-Anger" + +\end_inset + + and +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Only-Time" + +\end_inset + + show anger and time, respectively. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Anger +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:Only-Anger" + +\end_inset + +Only Anger. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Time +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +2 +\end_layout + +\end_inset + + + + +\end_inset + + +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:Only-Time" + +\end_inset + +Only Time. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:anger-time-again" + +\end_inset + +Laurinda's anger quantified, divided in two. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Interested in that last table? Let us repeat it but without a label and + with a table and a subtable +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:rabbit-walrus-encore" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +Censored +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "tab:rabbit-walrus-encore" + +\end_inset + +The rabbit-walrus does an encore. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Tabular + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +Anger +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Time +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2 +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +One more time. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +The Passing Away +\end_layout + +\begin_layout Standard +Our hero was passing by the village. + He had only stopped to say +\begin_inset Quotes eld +\end_inset + +Hi! +\begin_inset Quotes erd +\end_inset + + Again here our lousy skills have made us spoil the quote, but this time + for the opposite reasons: everyone knows how to say +\begin_inset Quotes eld +\end_inset + +Hi! +\begin_inset Quotes erd +\end_inset + +, so we don't need an actual quote. + It is enough to report that the had stopped to say hi, even maybe qualifying + it a bit to make do for the missing exclamation sign: he could have stopped + to say a friendly hi. + Getting all literary he could have stopped to say a longing hi, although + this road leads to bizarreness. + It could be cool though. +\end_layout + +\begin_layout Standard +But anyway. + Laurinda was so mad, so hopping mad that she called her friend, the Assassin. + He was not in town at that precise moment, but that didn't help our hero + as he was just outside town killing people in a small barn. + Just for practice. +\end_layout + +\begin_layout Standard +Our hero left the village, but Laurinda cunningly annotated the MAC address + of his laptop's wifi card. + The lack of networking knowledge on the part of our hero (who really couldn't + tell a SYN packet from an ACK) was to play an important part in the story + -- if he had known how to change the MAC address, which identified him + with the precision of a surgeon's scalpel, he would have been safe. +\end_layout + +\begin_layout Standard +Let's not even get into that last scalpel metaphor, shall we not? It leaks + worse than the Titanic. +\end_layout + +\begin_layout Part +Of How Our Hero Went No More +\end_layout + +\begin_layout Chapter +The Killing +\end_layout + +\begin_layout Standard +Our hero led a happy existence for a long time afterwards, randomly avoiding + all points within connecting distance of a wifi network. + It could not last. +\end_layout + +\begin_layout Standard +Our hero went to the next village, found a friendly Moonrams cafe and connected + to the net. + Quickly the assassin (who knew the very people that run the internet, and + who by this display of nerdiness no longer merits the starting capital + letter) traced a bunch of IP packets coming from our hero's MAC address. + He deployed a team of murderous African bees, which as surely as a well-cared-f +or AK-47 reached our hero and killed him with three fast stings. + Of course they died afterwards, being bees and all, so it was an astounding + feat this training of wild African bees just for this one murder. + Maybe the Assassin merits that capital letter after all. +\end_layout + +\begin_layout Section +The Passing Away +\end_layout + +\begin_layout Standard +Our hero was undone. + He was no more. + He was, actually, an ex-hero. + We shall narrate his wake soon. +\end_layout + +\begin_layout Itemize +But first a message from our kind sponsors. + They want to present you the next section in this deeper inset. +\end_layout + +\begin_deeper +\begin_layout Section +The Mourning +\end_layout + +\begin_layout Standard +Everyone cried in the ceremony. + It was so sad that we need an image of this moment. + You can find it in figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:mourning" + +\end_inset + +. + +\begin_inset Note Greyedout +status open + +\begin_layout Plain Layout +Mental note: never pay the artist beforehand. +\end_layout + +\end_inset + + +\end_layout + +\end_deeper +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename mourning.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:mourning" + +\end_inset + +A crude approximation to our hero's mourning. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +And thusly everything happened. +\end_layout + +\begin_layout Chapter +The Mourning +\end_layout + +\begin_layout Standard +We have already talked at length about the mourning, and under sponsorship + no less, so no further details will be given here. + Suffice to say that our hero was mourned. + A lot. +\end_layout + +\begin_layout Chapter +\start_of_appendix +The Rebirth +\end_layout + +\begin_layout Standard +Surprising everyone, our hero was about to make a comeback. +\end_layout + +\begin_layout Section +Coming Again +\end_layout + +\begin_layout Standard +As it happened, our hero had never died; he had just faked his own death + to find out his assassin. + It was not difficult, what with the capital letter and all. +\end_layout + +\begin_layout Section +Two is Better than One +\end_layout + +\begin_layout Standard +How to make another comeback? This is left as an exercise to the reader. +\end_layout + +\begin_layout Chapter +Our Recommendation to Kids +\end_layout + +\begin_layout Standard +Never trust killer bees. + Or Assassins. +\end_layout + +\begin_layout Section +Killer Bees and Their Perils +\end_layout + +\begin_layout Standard +A killer bee cannot be trained consistently, since it will die at the first + sting. + Better use killing wasps -- or, even better, solve your differencies talking. +\end_layout + +\begin_layout Standard +For the sake of your education, check figure +\begin_inset CommandInset ref +LatexCommand ref +reference "fig:killer-bees" + +\end_inset + +. + It shows a bunch of killer bees, or something. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename mourning.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +\begin_inset CommandInset label +LatexCommand label +name "fig:killer-bees" + +\end_inset + +A gathering of killer bees. + Supposedly. +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +Assassins: Inherently Unreliable +\end_layout + +\begin_layout Standard +Someone who kills people (even for business) is not someone you want to + deal with. + Watch +\begin_inset Quotes eld +\end_inset + +Fargo +\begin_inset Quotes erd +\end_inset + + by the Coen Brothers if you don't believe me. + And remember: a hero under the belt is a feather on the hat. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/subdir/image-directory-good.html elyxer-1.2.5/forks/jras-elyxer/test/subdir/image-directory-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/subdir/image-directory-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/subdir/image-directory-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,48 @@ + + + + + + + + +Image Directory Test + + +
      +

      +Image Directory Test +

      +

      +1 Directory +

      +
      +Just images that have to be taken from another directory. +
      +
      +
      +
      +
      +figure mourning.png + +
      +
      +Figure 1.1 An image from another directory +
      + +
      + +
      + +
      +
      +Nothing else. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/subdir/image-directory.lyx elyxer-1.2.5/forks/jras-elyxer/test/subdir/image-directory.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/subdir/image-directory.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/subdir/image-directory.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,153 @@ +#LyX 1.6.4 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass scrbook +\begin_preamble +% DO NOT ALTER THIS PREAMBLE!!! +% +% This preamble is designed to ensure that the User's Guide prints +% out as advertised. If you mess with this preamble, +% parts of the User's Guide may not print out as expected. If you +% have problems LaTeXing this file, please contact +% the documentation team +% email: lyx-docs@lists.lyx.org + +\usepackage{ifpdf} % part of the hyperref bundle +\ifpdf % if pdflatex is used + + % set fonts for nicer pdf view + \IfFileExists{lmodern.sty}{\usepackage{lmodern}}{} + +\fi % end if pdflatex is used + +% for correct jump positions whe clicking on a link to a float +\usepackage[figure]{hypcap} + +% the pages of the TOC is numbered roman +% and a pdf-bookmark for the TOC is added +\let\myTOC\tableofcontents +\renewcommand{\tableofcontents}{% + \frontmatter + \pdfbookmark[1]{\contentsname}{} + \myTOC + \mainmatter } + +% redefine the \LyX macro for PDF bookmarks +\def\LyX{\texorpdfstring{% + L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} + {LyX}} + +% define a short command for \textvisiblespace +\newcommand{\spce}{\textvisiblespace} + +% macro for italic page numbers in the index +\newcommand{\IndexDef}[1]{\textit{#1}} + +% redefine the greyed out note +\end_preamble +\options intoc,bibtotoc,idxtotoc,BCOR7mm,tablecaptionabove +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize 12 +\spacing single +\use_hyperref true +\pdf_title "Appendix Test" +\pdf_author "Alex Fernández" +\pdf_subject "Containing Numeration and Other Appendixy things" +\pdf_keywords "LyX eLyXer" +\pdf_bookmarks true +\pdf_bookmarksnumbered true +\pdf_bookmarksopen false +\pdf_bookmarksopenlevel 1 +\pdf_breaklinks false +\pdf_pdfborder false +\pdf_colorlinks true +\pdf_backref false +\pdf_pdfusetitle false +\pdf_quoted_options "linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue,pdfpagelayout=OneColumn, pdfnewwindow=true,pdfstartview=XYZ, plainpages=false, pdfpagelabels,pdftex" +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 0 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 2 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Image Directory Test +\end_layout + +\begin_layout Chapter +Directory +\end_layout + +\begin_layout Standard +Just images that have to be taken from another directory. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Graphics + filename mourning.png + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +An image from another directory +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Nothing else. +\end_layout + +\end_body +\end_document Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/subdir/laurindas-anger.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/subdir/laurindas-anger.png differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/subdir/mini-elyxer.jpg and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/subdir/mini-elyxer.jpg differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/subdir/mourning.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/subdir/mourning.png differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/jras-elyxer/test/subdir/rabbit-walrus.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/jras-elyxer/test/subdir/rabbit-walrus.png differ diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/table-1-6-good.html elyxer-1.2.5/forks/jras-elyxer/test/table-1-6-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/table-1-6-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/table-1-6-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,560 @@ + + + + + + + + +Table Test + + +
      +

      +Table Test +

      +

      +Alex Fernández (elyxer@gmail.com) +

      +
      +This test may contain several tables. +
      +

      +1 Longtable +

      +
      +The first one comes straight from the LyX User Guide, shortened. +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +Example Phone List (ignore the names) +
      +NAME + +TEL. +
      +Annovi + +Silvia + +555 +
      +Bertoli + +Stefano + +555 +
      +Bozzi + +Walter + +555 +
      +Cachia + +Maurizio + +555 +
      +Cinquemani + +Giusi + +555 +
      +Colin + +Bernard + +555 +
      +Dal Bosco + +Carolina + +555 +
      +Dalpiaz + +Annamaria + +555 +
      +Feliciello + +Domenico + +555 +
      +Focarelli + +Paola + +555 +
      +Galletti + +Oreste + +555 +
      +Rizzardi + +Paola + +555 +
      +Malfatti + +Luciano + +555 +
      +Meneguzzo + +Roberto + +555 +
      +Pirpamer + +Erich + +555 +
      +Radina + +Claudio + +555 +
      +Unterkalmsteiner + +Frieda + +555 +
      +Vigna + +Jürgen + +999 +
      +Winkler + +Franz + +555 +
      +End +
      + +
      + +
      +

      +2 Multicolumn +

      +
      +The second table contains some multicolumn cells. +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +12 + +3 + +4 +
      +1 + +23 + +4 +
      +1 + +2 + +3 + +4 +
      +1234 +
      +1 + +234 +
      +12 + +34 +
      +123 + +4 +
      + +
      + +
      +

      +3 Alignment +

      +
      +Now for some non-standard alignments. +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +left + +center + +right +
      +left-top + +figure elyxer.png + + +right-top +
      +left-middle + +center-middle + +figure elyxer.png + +
      +figure elyxer.png + + +center-bottom + +right-bottom +
      + +
      +
      +Bit of a mess, wasn’t it. +
      +

      +4 Multi-row +

      +
      +A table with several rows per cell. +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + +First Part + +Second Part +
      + + +First subpart + +
      + +
      +
      +Second subpart
      +Now with a supplementary row +
      + +
      +Third subpart + +Fourth subpart +
      +row + +
      + +
      +
      + +
      +
      +The first row
      +The second row
      +The third row +
      + +
      +Empty + +
      + +
      +
      +The first row
      +The second row +
      + +
      +Empty too +
      +row + + + +
      + +
      +
      + +
      +
      +Only three rows: first
      +Only three rows: second
      +Only three rows: fourth +
      + +
      +Mostly empty + +Not empty +
      + +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/table-1-6.lyx elyxer-1.2.5/forks/jras-elyxer/test/table-1-6.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/table-1-6.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/table-1-6.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,1607 @@ +#LyX 1.6.5 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options true +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Table Test +\end_layout + +\begin_layout Author +Alex Fernández (elyxer@gmail.com) +\end_layout + +\begin_layout Standard +This test may contain several tables. +\end_layout + +\begin_layout Section +Longtable +\end_layout + +\begin_layout Standard +The first one comes straight from the LyX User Guide, shortened. +\end_layout + +\begin_layout Standard +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Example Phone List (ignore the names) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +NAME +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +TEL. +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Example Phone List +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +NAME +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +TEL. +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +continue ... +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Annovi +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Silvia +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Bertoli +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Stefano +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Bozzi +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Walter +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Cachia +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Maurizio +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Cinquemani +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Giusi +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Colin +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Bernard +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Dal Bosco +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Carolina +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Dalpiaz +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Annamaria +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Feliciello +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Domenico +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Focarelli +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Paola +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Galletti +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Oreste +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Rizzardi +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Paola +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Malfatti +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Luciano +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Meneguzzo +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Roberto +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Pirpamer +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Erich +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Radina +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Claudio +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Unterkalmsteiner +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Frieda +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Vigna +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Jürgen +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +999 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +Winkler +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Franz +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +555 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +End +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Section +Multicolumn +\end_layout + +\begin_layout Standard +The second table contains some multicolumn cells. +\end_layout + +\begin_layout Standard +\align center +\begin_inset Tabular + + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +12 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +3 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +4 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +23 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +4 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +2 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +3 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +4 +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1234 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +234 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +12 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +34 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +123 +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +4 +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Section +Alignment +\end_layout + +\begin_layout Standard +Now for some non-standard alignments. +\end_layout + +\begin_layout Standard +\begin_inset Tabular + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +left +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +center +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +right +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +left-top +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Graphics + filename elyxer.png + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +right-top +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +left-middle +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +center-middle +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Graphics + filename elyxer.png + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +\begin_inset Graphics + filename elyxer.png + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +center-bottom +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +right-bottom +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Standard +Bit of a mess, wasn't it. +\end_layout + +\begin_layout Section +Multi-row +\end_layout + +\begin_layout Standard +A table with several rows per cell. +\end_layout + +\begin_layout Standard +\begin_inset Tabular + + + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +First Part +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Second Part +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +First subpart +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Second subpart +\end_layout + +\begin_layout Plain Layout + +\size footnotesize +Now with a supplementary row +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Third subpart +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Fourth subpart +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +row +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +The first row +\end_layout + +\begin_layout Plain Layout + +\size footnotesize +The second row +\end_layout + +\begin_layout Plain Layout + +\size scriptsize +The third row +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Empty +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +The first row +\end_layout + +\begin_layout Plain Layout + +\size footnotesize +The second row +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Empty too +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +row +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Only three rows: first +\end_layout + +\begin_layout Plain Layout + +\size footnotesize +Only three rows: second +\end_layout + +\begin_layout Plain Layout + +\size footnotesize +Only three rows: fourth +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size scriptsize +Mostly empty +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Not empty +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/template.html elyxer-1.2.5/forks/jras-elyxer/test/template.html --- elyxer-1.2.3/forks/jras-elyxer/test/template.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/template.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,17 @@ + + + + + + <!--$title--> + + + + +
      + + +

      (C)

      +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/test.css elyxer-1.2.5/forks/jras-elyxer/test/test.css --- elyxer-1.2.3/forks/jras-elyxer/test/test.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/test.css 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,6 @@ +/* + * Test CSS +*/ +div.Standard { + background: #909090; +} diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/toc-article-good.html elyxer-1.2.5/forks/jras-elyxer/test/toc-article-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/toc-article-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/toc-article-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,125 @@ + + + + + + + + +Article TOC Test + + +
      +

      +Article TOC Test +

      + +

      +Part I. Our Definition +

      +

      +1 The definition +

      +
      +A TOC is a Table Of Contents. +
      +

      +2 But I Already Knew That +

      +
      +You were lucky. +
      +

      +I Want My Money Back +

      +
      +There you have your 0€ back. +
      +

      +Completely Unfair Dude +

      +
      +Hey, I didn’t call you here. +
      +
      +A Paragraph For You +
      +
      +Totally uncalled for. +
      +

      +Unordered Section +

      +
      +Just to show that it works. +
      +
      +And now a list. +
      +
        +
      1. +First item. +
      2. +
      3. +We will embed an ordered subsection here just to fake it.

        +There We Go +

        + +
      4. +
      5. +See if it’s in your TOC. +
      6. + +
      +
      +But There Is More +
      +
      +And nothing else. +
      +

      +A Appendix +

      +
      +An appendix here, an appendix there. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/toc-article.lyx elyxer-1.2.5/forks/jras-elyxer/test/toc-article.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/toc-article.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/toc-article.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,223 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 1 +\tocdepth 2 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Article TOC Test +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Part +Our Definition +\end_layout + +\begin_layout Section +The definition +\end_layout + +\begin_layout Standard +A TOC is a Table Of Contents. +\end_layout + +\begin_layout Standard +\begin_inset Note Comment +status open + +\begin_layout Section +Hidden Section +\end_layout + +\begin_layout Plain Layout +This section should be hidden from mortals, and from the TOC. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +But I Already Knew That +\end_layout + +\begin_layout Standard +You were lucky. +\end_layout + +\begin_layout Subsection +I Want My Money Back +\end_layout + +\begin_layout Standard +There you have your 0€ back. +\end_layout + +\begin_layout Subsubsection +Completely Unfair Dude +\end_layout + +\begin_layout Standard +Hey, I didn't call you here. +\end_layout + +\begin_layout Paragraph +A Paragraph For You +\end_layout + +\begin_layout Standard +Totally uncalled for. +\end_layout + +\begin_layout Section* +Unordered Section +\end_layout + +\begin_layout Standard +Just to show that it works. +\end_layout + +\begin_layout Standard +And now a list. +\end_layout + +\begin_layout Enumerate +First item. +\end_layout + +\begin_layout Enumerate +We will embed an ordered subsection here just to fake it. +\end_layout + +\begin_deeper +\begin_layout Subsection +There We Go +\end_layout + +\end_deeper +\begin_layout Enumerate +See if it's in your TOC. +\end_layout + +\begin_layout Paragraph +But There Is More +\end_layout + +\begin_layout Standard +And nothing else. +\end_layout + +\begin_layout Standard +\begin_inset Note Comment +status open + +\begin_layout Plain Layout +\begin_inset CommandInset index_print +LatexCommand printindex + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +\start_of_appendix +Appendix +\end_layout + +\begin_layout Standard +An appendix here, an appendix there. +\end_layout + +\begin_layout Standard +\begin_inset Note Comment +status open + +\begin_layout Plain Layout +\begin_inset CommandInset bibtex +LatexCommand bibtex +bibfiles "bibtex-plain" +options "bibtotoc,plain" + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/toc-book-good.html elyxer-1.2.5/forks/jras-elyxer/test/toc-book-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/toc-book-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/toc-book-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,152 @@ + + + + + + + + +Book TOC Test + + +
      +

      +Book TOC Test +

      + +
      +
      +List of Figures +
      + + +
      +

      +Part I. Our Definition +

      +

      +1 The definition +

      +
      +A TOC is a Table Of Contents. +
      +

      +1.1 But I Already Knew That +

      +
      +You were lucky. +
      +

      +I Want My Money Back +

      +
      +There you have your 0€ back. +
      +

      +Completely Unfair Dude +

      +
      +Hey, I didn’t call you here. +
      +
      +A Paragraph For You +
      +
      +Totally uncalled for. +
      +
      +
      +
      +
      +figure elyxer-svg.png + +
      +
      +Figure 1.1 eLyXer logo +
      + +
      + +
      + +
      +

      +Unordered Section +

      +
      +Just to show that it works. +
      +
      +And now a list. +
      +
        +
      1. +First item. +
      2. +
      3. +We will embed an ordered subsection here just to fake it.

        +There We Go +

        + +
      4. +
      5. +See if it’s in your TOC. +
      6. + +
      +
      +But There Is More +
      +
      +And nothing else. +
      +

      +A Appendix +

      +
      +An appendix here, an appendix there. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/toc-book-notoclabels-good.html elyxer-1.2.5/forks/jras-elyxer/test/toc-book-notoclabels-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/toc-book-notoclabels-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/toc-book-notoclabels-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,152 @@ + + + + + + + + +Book TOC Test + + +
      +

      +Book TOC Test +

      +
      +
      +Table of Contents +
      + + + +
      +
      +
      +List of Figures +
      + + +
      +

      +I. Our Definition +

      +

      +1 The definition +

      +
      +A TOC is a Table Of Contents. +
      +

      +1.1 But I Already Knew That +

      +
      +You were lucky. +
      +

      +I Want My Money Back +

      +
      +There you have your 0€ back. +
      +

      +Completely Unfair Dude +

      +
      +Hey, I didn’t call you here. +
      +
      +A Paragraph For You +
      +
      +Totally uncalled for. +
      +
      +
      +
      +
      +figure elyxer-svg.png + +
      +
      +Figure 1.1 eLyXer logo +
      + +
      + +
      + +
      +

      +Unordered Section +

      +
      +Just to show that it works. +
      +
      +And now a list. +
      +
        +
      1. +First item. +
      2. +
      3. +We will embed an ordered subsection here just to fake it.

        +There We Go +

        + +
      4. +
      5. +See if it’s in your TOC. +
      6. + +
      +
      +But There Is More +
      +
      +And nothing else. +
      +

      +A Appendix +

      +
      +An appendix here, an appendix there. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/toc-book.lyx elyxer-1.2.5/forks/jras-elyxer/test/toc-book.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/toc-book.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/toc-book.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,269 @@ +#LyX 1.6.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 345 +\begin_document +\begin_header +\textclass book +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\use_default_options false +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 1 +\tocdepth 2 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Book TOC Test +\end_layout + +\begin_layout Standard +\begin_inset CommandInset toc +LatexCommand tableofcontents + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset FloatList figure + +\end_inset + + +\end_layout + +\begin_layout Part +Our Definition +\end_layout + +\begin_layout Chapter +The definition +\end_layout + +\begin_layout Standard +A TOC is a Table Of Contents. +\end_layout + +\begin_layout Standard +\begin_inset Note Comment +status open + +\begin_layout Section +Hidden Section +\end_layout + +\begin_layout Plain Layout +This section should be hidden from mortals, and from the TOC. +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section +But I Already Knew That +\end_layout + +\begin_layout Standard +You were lucky. +\end_layout + +\begin_layout Subsection +I Want My Money Back +\end_layout + +\begin_layout Standard +There you have your 0€ back. +\end_layout + +\begin_layout Subsubsection +Completely Unfair Dude +\end_layout + +\begin_layout Standard +Hey, I didn't call you here. +\end_layout + +\begin_layout Paragraph +A Paragraph For You +\end_layout + +\begin_layout Standard +Totally uncalled for. +\end_layout + +\begin_layout Standard +\begin_inset Float figure +wide false +sideways false +status open + +\begin_layout Plain Layout +\noindent +\align center +\begin_inset Graphics + filename elyxer-svg.svg + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption + +\begin_layout Plain Layout +eLyXer logo +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Section* +Unordered Section +\end_layout + +\begin_layout Standard +Just to show that it works. +\end_layout + +\begin_layout Standard +And now a list. +\end_layout + +\begin_layout Enumerate +First item. +\end_layout + +\begin_layout Enumerate +We will embed an ordered subsection here just to fake it. +\end_layout + +\begin_deeper +\begin_layout Subsection +There We Go +\end_layout + +\end_deeper +\begin_layout Enumerate +See if it's in your TOC. +\end_layout + +\begin_layout Paragraph +But There Is More +\end_layout + +\begin_layout Standard +And nothing else. +\end_layout + +\begin_layout Standard +\begin_inset Note Comment +status open + +\begin_layout Plain Layout +\begin_inset CommandInset index_print +LatexCommand printindex + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Chapter +\start_of_appendix +Appendix +\end_layout + +\begin_layout Standard +An appendix here, an appendix there. +\end_layout + +\begin_layout Standard +\begin_inset Note Comment +status open + +\begin_layout Plain Layout +\begin_inset CommandInset bibtex +LatexCommand bibtex +bibfiles "bibtex-plain" +options "bibtotoc,plain" + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/version2.0-good.html elyxer-1.2.5/forks/jras-elyxer/test/version2.0-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/version2.0-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/version2.0-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,29 @@ + + + + + + + + +Version 2.0 Test + + +
      +

      +Version 2.0 Test +

      +
      +Some random document for preliminary 2.0 tests. +
      +
      +Savannah bug 33961: Apparently super and subscript fails. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/version2.0.lyx elyxer-1.2.5/forks/jras-elyxer/test/version2.0.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/version2.0.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/version2.0.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,101 @@ +#LyX 2.0 created this file. For more info see http://www.lyx.org/ +\lyxformat 413 +\begin_document +\begin_header +\textclass scrbook +\use_default_options true +\maintain_unincluded_children false +\language english +\language_package default +\inputencoding auto +\fontencoding global +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\use_non_tex_fonts false +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\default_output_format default +\output_sync 0 +\bibtex_command default +\index_command default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\use_mhchem 1 +\use_mathdots 1 +\cite_engine basic +\use_bibtopic false +\use_indices false +\paperorientation portrait +\suppress_date false +\use_refstyle 0 +\index Index +\shortcut idx +\color #008000 +\end_index +\secnumdepth 2 +\tocdepth 2 +\paragraph_separation indent +\paragraph_indentation default +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\html_math_output 0 +\html_css_as_file 0 +\html_be_strict false +\end_header + +\begin_body + +\begin_layout Title +Version 2.0 Test +\end_layout + +\begin_layout Standard +Some random document for preliminary 2.0 tests. +\end_layout + +\begin_layout Standard +\begin_inset CommandInset href +LatexCommand href +name "Savannah bug 33961" +target "https://savannah.nongnu.org/bugs/index.php?33961" + +\end_inset + +: Apparently +\begin_inset script superscript + +\begin_layout Plain Layout +super +\end_layout + +\end_inset + + and +\begin_inset script subscript + +\begin_layout Plain Layout +subscript +\end_layout + +\end_inset + + fails. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-good.html elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,43 @@ + + + + + + + + +Images Tests + + +
      +

      +Images Tests +

      +
      +figure elyxer-svg.png +First image: regular path. +
      +
      +figure elyxer-svg.png +Second image: convoluted path. +
      +
      +figure docs/elyxer.png +Third image: from another directory. +
      +
      +figure mini-elyxer.jpg +Fourth image: from a JPEG file. +
      +
      +figure square.png +Fifth image: from a PNG file. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-html-good.html elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-html-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-html-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-html-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,42 @@ + + + + + + + +Images Tests + + +
      +

      +Images Tests +

      +
      +figure elyxer-svg.png +First image: regular path. +
      +
      +figure elyxer-svg.png +Second image: convoluted path. +
      +
      +figure docs/elyxer.png +Third image: from another directory. +
      +
      +figure mini-elyxer.jpg +Fourth image: from a JPEG file. +
      +
      +figure square.png +Fifth image: from a PNG file. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-inkscape-good.html elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-inkscape-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-inkscape-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-inkscape-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,40 @@ + + + + + + + + +Images Tests + + +
      + +

      +Images Tests +

      +
      +figure elyxer-svg.png +First image: regular path. +
      +
      +figure elyxer-svg.png +Second image: convoluted path. +
      +
      +figure docs/elyxer.png +Third image: from another directory. +
      +
      +figure mini-elyxer.jpg +Fourth image: from a JPEG file. +
      +
      +figure square.png +Fifth image: from a PNG file. +
      + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-jpg-good.html elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-jpg-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-jpg-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-jpg-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,43 @@ + + + + + + + + +Images Tests + + +
      +

      +Images Tests +

      +
      +figure elyxer-svg.jpg +First image: regular path. +
      +
      +figure elyxer-svg.jpg +Second image: convoluted path. +
      +
      +figure docs/elyxer.jpg +Third image: from another directory. +
      +
      +figure mini-elyxer.jpg +Fourth image: from a JPEG file. +
      +
      +figure square.jpg +Fifth image: from a PNG file. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-noconvert-good.html elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-noconvert-good.html --- elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5-noconvert-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5-noconvert-good.html 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,49 @@ + + + + + + + + +Images Tests + + +
      +

      +Images Tests +

      +
      + +figure elyxer-svg.svg + +First image: regular path. +
      +
      + +figure elyxer-svg.svg + +Second image: convoluted path. +
      +
      + +figure ../docs/elyxer.svg + +Third image: from another directory. +
      +
      +figure mini-elyxer.jpg +Fourth image: from a JPEG file. +
      +
      +figure square.png +Fifth image: from a PNG file. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5.lyx elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5.lyx --- elyxer-1.2.3/forks/jras-elyxer/test/with images-1-5.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/jras-elyxer/test/with images-1-5.lyx 2013-03-10 10:39:30.000000000 +0000 @@ -0,0 +1,118 @@ +#LyX 1.5.7 created this file. For more info see http://www.lyx.org/ +\lyxformat 276 +\begin_document +\begin_header +\textclass article +\begin_preamble +% eLyXer -- convert LyX source files to HTML output. +% +% Copyright (C) 2009-2010 Alex Fernández +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +\end_preamble +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 +\graphics default +\paperfontsize default +\spacing single +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Title +Images Tests +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer-svg.svg + lyxscale 50 + scale 50 + +\end_inset + +First image: regular path. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename elyxer-svg.svg + lyxscale 50 + scale 50 + +\end_inset + +Second image: convoluted path. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename ../docs/elyxer.svg + lyxscale 50 + scale 50 + +\end_inset + +Third image: from another directory. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename mini-elyxer.jpg + +\end_inset + +Fourth image: from a JPEG file. +\end_layout + +\begin_layout Standard +\begin_inset Graphics + filename square.png + lyxscale 1000 + scale 1000 + +\end_inset + +Fifth image: from a PNG file. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/forks/pages-elyxer/changelog.html elyxer-1.2.5/forks/pages-elyxer/changelog.html --- elyxer-1.2.3/forks/pages-elyxer/changelog.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/changelog.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,1803 @@ + + + + + + + + +eLyXer changelog + + +
      +

      +figure elyxer.png +eLyXer Changelog +

      +
      +This document lists all public versions, the date they were released on and the changes they contain. For more information about eLyXer visit the main page. +
      +
        +
      • +1.2.4 (2013-01-11):
          +
        • +Implemented generic converters, and lyx -C as an image converter (thanks, Tommaso!). +
        • +
        • +Implemented command \today: Mar 10, 2013. +
        • +
        • +Added a Russian translation (thanks, Vladimir!). +
        • +
        • +Solved a bug when parsing a BibTeX entry with a trailing comma (thanks, Bob!). +
        • +
        • +BibTeX: correctly use booktitle instead of journal in an @inproceedings entry (thanks, Pascal!). +
        • +
        • +Expose language information as additional markup (using the lang attribute in HTML). +
        • +
        • +Fix by Guenter Milde for math2html under Python 3.0. +
        • +
        • +Convert em-dash only when surrounded by spaces (thanks, Robert). +
        • +
        • +Fix by José Ramón Álvarez Sánchez of problem in simultaneous use of hover and end options for footnotes (thanks, Tim!). +
        • + +
        + +
      • +
      • +1.2.3 (2011-08-31):
          +
        • +Changed the license for math2html from Apache v2 to FreeBSD 2-clause license, to better suit integration with DocUtils. +
        • +
        • +Removed a false positive error which appeared during the tests: “* No title in”. +
        • +
        • +Added most commands in Günter Milde’s excellent list of Unicode to LaTeX commands, except categories mathaccent, mathfence, mathradical, mathover and mathunder. Examples: \hash as  ⋕ , \smalltriangleleft as . +
        • +
        • +Deprecated option --jsmath, users are encouraged to use --mathjax instead. +
        • +
        • +Added argument --mathjax remote to access the MathJax CDN instead of hit a local copy. Changed the Math showcase to work remotely by default. +
        • +
        • +Solved Debian bug 639712: eLyXer didn’t accept Unicode characters in --title option, added test. +
        • +
        • +Solved Savannah bug 33961: eLyXer didn’t support sub- or superscript insets as used in LyX 2.0, added test. +
        • +
        • +Solved installation problem when $PATH contains a directory which does not exist; the eLyXer binary was created with the same name as said directory. Now install.py should just ignore the directory. (Thanks, Jack!) +
        • + +
        + +
      • +
      • +1.2.2 (2011-06-12):
          +
        • +Bug in description: when a (non-empty) ERT is the first element of a description, use it as first word and make it bold. +
        • +
        • +Proper support for \scriptstyle and \scriptscriptstyle: script, scriptscript. +
        • +
        • +Bug #33156: CSS specification as in --css=lyx.css was not working, solved now. +
        • +
        • +Support for \noindent and \centering in ERTs. +
        • +
        • +Ignore BibTeX entries which are not publication entries. Show a debug message for non-referenced entries. +
        • +
        • +Understand command \& in BibTeX files. +
        • +
        • +Bumped Lyx format supported (--lyxformat) to 413 (LyX 2.0.0). +
        • +
        • +Solved error when parsing display formulas generated with LyX 2.0: "Formula beginning \begin_inset Formula is unknown" (thanks, Pascal!). Added test case. +
        • +
        • +Added a bunch of new symbols, including \textsection §, \textemdash — or \v{z} ž (thanks again, Pascal!). +
        • +
        • +Changed output characters for English quotes, from Unicode “ and ‘ to HTML entities &ldquo; and &lsquo; (thanks, Marco!). +
        • +
        • +Make Flex styles in titles work (thanks, Tiago!). +
        • +
        • +Make custom Flex CharStyles work: generate HTML spans of the same class as the Flex type (thanks again, Marco!). +
        • + +
        + +
      • +
      • +1.2.1 (2011-03-07):
          +
        • +Wish list: support for formatted references (showing the part name and number) and named references (showing the part title, equivalent to \nameref). +
        • +
        • +Wish list: include part titles in --splitpart navigation header. +
        • +
        • +Changed literal for previous page in --splitpart: now it’s “Prev” instead of “Previous”. +
        • +
        • +Bug in --notoclabels: removed the “.” after the part number but before the title shown in the TOC. “5. How to Make Friends” is now “5 How to Make Friends” (thanks, José Ramón!). +
        • +
        • +Allow math2html to be invoked using parameters (like --debug). +
        • +
        • +Bugs in ERT parsing: brackets {} are not parsed correctly across different ERTs. The TeX parser was being thrown off by escaped brackets as in {\{\}}, added test. Comments are ignored now. +
        • +
        • +Solved conflict in CSS between .script (used to properly layout super- and subscripts) and span.script (used for the script-type \mathscr and \mathcal fonts). Changed the latter to span.scriptfont, forcing an incompatible but unavoidable change in the CSS. +
        • +
        • +Forced span.scriptfont to be shown as italic so it’s properly displayed on Firefox. +
        • +
        • +Wish list: new option --googlecharts adds support for formula images generated using Google Charts. +
        • +
        • +Wish list: merged options --toc and --toctarget into --tocfor. +
        • +
        • +Wish list: options --splitpart and --tocfor (previously --toc) now work together. Also: the separate TOC has a link to the main page. +
        • +
        • +Bug in --splitpart combined with --notoclabels: unnumbered parts displayed an ugly colon as in “Next : Section”, now removed (thanks, José Ramón!). +
        • +
        • +Modified the spacing in formulas so that words in the mathnormal font now appear separated, as a product of variables. +
        • +
        • +Do not show limit symbols such as or in a larger font than the rest for inline formulas. +
        • +
        • +Added support for \textcircled: w⃝. +
        • + +
        + +
      • +
      • +1.2.0 (2011-01-30):
          +
        • +Bumped LyX version support to 410. +
        • +
        • +Correctly create big brackets for environments with odd alignments such as matrix (thanks, Günther!). +
        • +
        • +Create and use big brackets for fractions and other structures, if needed. +
        • +
        • +Added option --simplemath to avoid fancy math structures: do not generate multi-line Unicode brackets or stacked limits. +
        • +
        • +eLyXer is now a proper Python package, instead of just a coalesced script elyxer.py containing everything. However only the script is installed right now. +
        • +
        • +Interpret TeXCode (previously known as Evil Red Text) as TeX commands and formulas. +
        • +
        • +Support for TeX commands \textvisiblespace, \AmS, \parbox, \tag, \rule, and more: , AmS. +
        • +
        • +Support for \Game: . +
        • +
        • +Changed the navigation header for --splitpart so that the left and right spans overflow (thanks, Axel!). +
        • +
        • +Bug in --notoclabels: labels such as “Figure” should be omitted in the TOC, but not in captions (thanks again, Axel!). +
        • +
        • +Bug in --splitpart: empty navigation links caused the header to look unbalanced, fixed now with a non-breaking space. Also, up link in the main page used to point to itself; now it’s an empty link (more thanks, Axel!). +
        • +
        • +Support for \limits and \nolimits: control if the last symbol should show limits above or below the symbol or not. +
        • +
        • +Bug in \vspace: add the vertical space after the command, not before; or at least try to. +
        • +
        • +Bug in \raisebox: parse and display the contents as text mode. +
        • +
        • +Wish list: do not number captions in code listings. +
        • +
        • +Do not install as a module (to run as python -m elyxer) but only as a script (to run as elyxer.py). +
        • + +
        + +
      • +
      • +1.1.2 (2010-12-23):
          +
        • +Wish list: display large Unicode symbols for sums and integrals in display mode. +
        • +
        • +Also in display mode, place limits for commands that take them above or below the symbol, instead of to the right. +
        • +
        • +Support for new Flex insets: Code, MenuItem, Noun, Strong; new Argument, Phantom and line (ruler) insets; new style \strikeout; new LaTeX commands \href, \newline. +
        • +
        • +BibTeX: apply a combining function only to the following character, not to the next word. +
        • +
        • +Added reference format for vpageref (“on page #”). +
        • +
        • +Improved math macro parsing: optional parameters, literal parameters, single-letter parameters, parameter defaults with operations. +
        • +
        • +Display math cases, full-sized binomials (\dbinom) and array brackets using Unicode bracket pieces. +
        • +
        • +Change all table-type elements in formulas to spans and do the formatting in the CSS, to generate valid XHTML. +
        • +
        • +Support graceful degradation of fractions and roots when the CSS is not present. +
        • +
        • +Adjusted roots to insert the root power inside the radical symbol. +
        • +
        • +Adjusted nice fractions (34) to improve their appearance. +
        • +
        • +Support for all upright Greek letters: μ, τ. +
        • + +
        + +
      • +
      • +1.1.1 (2010-12-13):
          +
        • +Wish list: understand \url{} in BibTeX files. +
        • +
        • +Wish list: parse math formulas in BibTeX files. +
        • +
        • +Improved support for dotless i and j as \imath and \jmath: ı, ȷ. +
        • +
        • +Solved bug when parsing a quoted string inside a BibTeX file containing a comma. +
        • +
        • +Added math environments equation* and matrix. +
        • +
        • +Do not break inline formulas at whitespace (thanks, José Ramón!). +
        • +
        • +Break up the CSS into pieces, and generate an independent math.css for use within math2html.py. +
        • +
        • +Ignore hyphens in option names, so e.g. --split-part is equivalent to --splitpart. +
        • +
        • +Changed --forceformat to --imageformat (kept the old option for backwards compatibility). +
        • +
        • +Wish list: added --imageformat "copy" to just copy images instead of converting them. +
        • +
        • +Wish list: added option --embedcss "file.css" to embed the CSS styles in file.css into the resulting HTML. +
        • +
        • +Wish list: more than one --css options can be added to use several CSS files. +
        • +
        • +Wish list: display sub- and superscript aligned vertically (as in integrals). +
        • + +
        + +
      • +
      • +1.1.0 (2010-11-23):
          +
        • +Wish list: understand \setcounter in the preamble to set the number of the first Chapter or Section. +
        • +
        • +Generate a new math2html.py file with an API to convert raw LaTeX code to HTML, and a command line utility. +
        • +
        • +Wish list: new option --notoclabels to omit part labels in the TOC. +
        • +
        • +Wish list: make “show changes in the output” work for change tracking. +
        • +
        • +Solve an existing issue with Description and List layouts: correct splitting of first words when intermixing styles. +
        • +
        • +Show decorations using Unicode combining characters, whenever possible. +
        • +
        • +Support for \dddot: o⃛ (with combining character) and \widehat: ^abc (with character on top). +
        • +
        • +Wish list: add several options for footnote generation (align markers instead of using superscript, place markers at the bottom of the page, use symbols for markers…). Also added a generic --footnotes option to aggregate them all. +
        • +
        • +Wish list: use ps:use-cropbox=true in ImageMagick for PostScript and EPS images. +
        • +
        • +Support for dotless i and j: ı, ȷ. +
        • + +
        + +
      • +
      • +1.0.4 (2010-10-29):
          +
        • +Solved bug #31342: detect appendices as they appear instead of looking at the containing layout. +
        • +
        • +Also reported in bug #31342: set part name to “Appendix A-Z” in the TOC for appendices, instead of showing them as regular chapters or sections. +
        • +
        • +Also reported in bug #31342: number parts and books using roman numerals, as in “Part I” or “Book IV”. +
        • +
        • +Fixed bug due to wrapped float placement not being mandatory anymore, despite what EmbeddedObjects.lyx says (thanks, Hans!). +
        • +
        • +Solved bug #31351: do not number (or add to the TOC) any document parts inside comments. +
        • +
        • +Also in bug #31351: the bibliography should be added to the TOC if so configured (and not inside a comment), and split into its own page with --splitpart. +
        • +
        • +Also in bug #31351: show the bibliography in regular size, not smaller than the main text as before. +
        • +
        • +Changed header from “Bibliography” to “References” for document classes other than book and report. +
        • +
        • +Solved bug #31414: bootstrap creation of conf/config.py. +
        • +
        • +Also in bug #31414: remodeled unit tests to try out Python 2.4 only if present, and to remove test files from previous runs. +
        • +
        • +Show the “Abstract” header only for the first Abstract layout (thanks, Yaron!). +
        • +
        • +Do not separate consecutive Abstract paragraphs, and display the abstract in slightly smaller font size. +
        • +
        • +Solved bug #31345: ignore preamble and comments in BibTeX files. Use string definitions (@string) in other entries. +
        • +
        • +Also in bug #31345: avoid endless loops for undesired characters in BibTeX entries. +
        • +
        • +Support for \fbox, \boxed, \framebox and \fcolorbox: fbox, boxed, framebox. +
        • + +
        + +
      • +
      • +1.0.3 (2010-10-15):
          +
        • +Do not hide errors when parsing child documents. +
        • +
        • +Correctly convert documents even when images are not found. +
        • +
        • +Do not center the content in figure or table floats by default. +
        • +
        • +Correctly convert child documents even when inserted in layouts. +
        • +
        • +Generate navigation bars for first page created with --splitpart. +
        • +
        • +Added wishlist to the user guide to keep track of requested features. +
        • +
        • +Solved bug #31243: spaces and comments in formulas (command definitions, empty formulas…). +
        • +
        • +Also reported in bug #31243: do not add numbering twice to child documents, and ignore child documents in comments. +
        • +
        • +Added support for \stackrel: xR → y (thanks, José Ramón!). +
        • +
        • +Added a lot of escaped characters to BibTeX parsing: \~n, \’{\i}… Also added a field note to all BibTeX styles. +
        • +
        • +Show all references (even those not cited) in the bibliography if configured to do so. +
        • +
        • +Understand relative sizes (e.g. 10col%) in spaces (thanks, Uwe!). +
        • + +
        + +
      • +
      • +1.0.2 (2010-09-20):
          +
        • +Updated MathJax to version 1.0.1 — no changes to eLyXer documents are necessary. +
        • +
        • +Added option --noconvert to use images in their original formats, and avoid converting images altogether. +
        • +
        • +Output <object> tags for SVG images. Size information is not used as it causes problems on Firefox. +
        • +
        • +BibTeX: include booktitle tag for the @incollection format. +
        • +
        • +BibTex: added a tag <span class="bibcites"> around all bibliographical cites, so they can be e.g. superscripted. +
        • +
        • +Show footnotes as hovering text instead of as marginal notes. Make the default footnote marker a bluish superscript letter in brackets:  [A]  [A] like this. +
        • +
        • +Updated --lyxformat to 398 (2.0alpha5); added warning if document version is bigger than that. +
        • +
        • +Support for \textless and \textgreater: <, >. +
        • +
        • +Added adjustments for better printing to default CSS. +
        • +
        • +Added languages “british” and “american” (which translate to plain English). +
        • +
        • +Avoid extracting indexes out of the containing layout if there is anything else in there (thanks, Amy!). This bug caused some content to be lost (e.g. child documents) if they were inside the same layout as e.g. an alphabetical index. +
        • + +
        + +
      • +
      • +1.0.1 (2010-09-01):
          +
        • +BibTeX: more robust parsing, specifically: correctly parse entries separated by commas. Support all TeX commands already available in math formulae. +
        • +
        • +Support for \textasciitilde: ~, \textasciicircum: ^ and a few other \text… symbols. Also, \textrm, \textsf and \textnormal should be working now in equations: a + roman + sans-serif + normal + b. +
        • +
        • +Improved support for custom horizontal and vertical spaces; absolute measures can now be used. +
        • +
        • +Support for sizes in table columns, figures and boxes. +
        • +
        • +Solved bug in --nofooter which required a dummy argument (thanks, Yan!). +
        • +
        • +Corrected box styling: <div class="Frameless"> is now indeed frameless, while <div class="Framed"> no longer has a double border. +
        • +
        • +Solved bug in text handling which separated consecutive centered lines with a space. +
        • +
        • +Basic support for LyX change tracking. +
        • + +
        + +
      • +
      • +1.0.0 (2010-07-21):
          +
        • +Replicate the navigation bar for --splitpart at the bottom of pages. Use translated strings for “Previous”, “Up” and “Next” links. Also added an explanatory text to the “up” link in the navigation bar, as in: “Up: Chapter 1”. +
        • +
        • +Added partial table of contents to pages generated with --splitpart. +
        • +
        • +Dependency cleanup between code modules. +
        • +
        • +Child documents of type “verbatim input” are now correctly converted on versions of Python built without universal newline support. +
        • +
        • +Include Index and Nomenclature in the Table of Contents. +
        • +
        • +When an Index, TOC, List of Figures… and the like is embedded in another layout, do not follow the style of the layout (thanks, Yaron!). +
        • +
        • +Solved a couple of XHTML validation errors: removed asterisks (*) in anchor names, avoid empty rows in arrays or case statements. +
        • +
        • +Make index entries work in Descriptions. Also, mixed styles should work again within Descriptions. +
        • +
        • +Group certain layouts together, such as Quote and Quotation. +
        • +
        • +Improved output for algorithms: do not run lines together, and do not separate other lines with double space. +
        • +
        • +List of algorithms does now correctly extract the text from the caption. +
        • +
        • +Increased line height for h2 in the main CSS (thanks, Wolfgang!). +
        • +
        • +Better color support in formulas: \color, \textcolor, \colorbox. blue, blue. +
        • +
        • +Formulas and formula labels are not colored by default. +
        • +
        • +Improved Index output: there is only one anchor for each entry, and entries are not shown in italics. +
        • +
        • +Allow hierarchical index entries, of the form “Main ! Secondary ! Final”. +
        • + +
        + +
      • +
      • +0.99 (2010-06-24):
          +
        • +Added --splitpart to online help (thanks, Sven!). +
        • +
        • +Restored compatibility with Python 2.4 (lost in 0.98 by mistake), added test to ensure it does not happen again. +
        • +
        • +BibTeX: improved template definitions for Vancouver style. +
        • +
        • +BibTeX: better parsing of braces (in templates) and quotes (in .bib files). Nested braces in templates are supported. +
        • +
        • +BibTeX: variable citing styles. Enclose cites in brackets instead of using superscripts. +
        • +
        • +BibTeX: export all BibTeX variables in bib-… spans. +
        • +
        • +BibTeX: limited author parsing, support for surname abbreviations as in style alpha. +
        • +
        • +BibTeX: use the file tag to show a link to the local file. +
        • +
        • +Added \oint and friends as a bigsymbol: x·dx. +
        • +
        • +Support for \officialeuro: . +
        • +
        • +Fix captions in lists of figures which use standard layouts (thanks, Hans!). +
        • +
        • +Added option --template to use an HTML template and substitute <!--$content-->, <!--$title-->… +
        • +
        • +Added option --copyright to add a copyright notice at the bottom (no longer generated by default). Deprecated old option --nocopy. +
        • +
        • +Added support for including files as a code listing. +
        • + +
        + +
      • +
      • +0.98 (2010-05-13):
          +
        • +MathJax: workaround bug in MSIE, that causes it to fail to render anything. +
        • +
        • +Add a margin to LyX-Code. Also improve line break separation inside LyX-Code. +
        • +
        • +Coalesce Python code: use relative paths when importing (thanks, Jack!). +
        • +
        • +Experimental installation script. +
        • +
        • +Avoid postprocessing child documents twice (thanks, Rainer!). +
        • +
        • +Solved bug when loading images from child documents in subdirectories (thanks, Rainer!). +
        • +
        • +Solved bug in image scaling when only one dimension is set (thanks, Wolfgang!). +
        • +
        • +Corrected issue with one-liner \lstset (thanks again, Rainer!). +
        • +
        • +Improved lists of figures, tables and algorithms: use short title, better labeling of floats. +
        • +
        • +Solved weird bug in float numbering when a chapter has only one layout. +
        • +
        • +Added \diagup and \diagdown: , . +
        • +
        • +First public release of option --splitpart [level]: split resulting web page at the given level. +
        • +
        • +Support for macros, both in LyX macro inset and as \newcommand. +
        • +
        • +Added URLs to most BibTeX formats. +
        • +
        • +Added BibTeX style “vancouver” for articles (thanks, John!). +
        • +
        • +Added a footer detailing eLyXer version and conversion date; it can be turned off with --nofooter. +
        • + +
        + +
      • +
      • +0.43 (2010-04-10):
          +
        • +Many BibTeX improvements: new style abbrvnat, conditional formatting, look up types in lowercase, understand “--” as dash. +
        • +
        • +Added options for mathematical equations: --jsmath to use jsMath and --mathjax to use MathJax. +
        • +
        • +Added command help to loremipsumize.py so it can be used outside of eLyXer. +
        • +
        • +Include internationalization files in .zip file. +
        • +
        • +Solved bug in table parsing: separate different plain layouts (thanks, Sara!). +
        • +
        • +eLyXer compressed files now contain a single directory called elyxer-$VERSION, instead of just elyxer. +
        • +
        • +Added italicized uppercase Greek letters: ΓΩ. De-italicized regular uppercase Greek letters: ΓΩ. +
        • + +
        + +
      • +
      • +0.42 (2010-03-17):
          +
        • +Changed author everywhere to the real name, to avoid any copyleft uncertainties. +
        • +
        • +Remove hook in the main text ([D→]) from margin notes. +
        • +
        • +Do not crash when BibTeX files are not found, just show an error. +
        • +
        • +Added support for some IPA characters, including ħ. Better parsing of \textipa text. +
        • +
        • +Added option --numberfoot to label footnotes with numbers instead of letters. +
        • +
        • +Solved bug in assignment of default formatting to references (thanks, Hans!). +
        • +
        • +Added option --raw to output raw HTML without header or footer. +
        • +
        • +Added French and Dutch translations. +
        • +
        • +Solved indenting problem for lists: only the first line was being indented. +
        • + +
        + +
      • +
      • +0.41 (2010-02-11):
          +
        • +Select the translation based on document language. +
        • +
        • +Added em-dash — such as in this sentence, , \textup. +
        • +
        • +Added option --converter inkscape to use Inkscape as SVG converter. +
        • +
        • +Solved bug when numbering unordered unique parts such as Part* (thanks, Geremy!). +
        • +
        • +Show error instead of crashing when included document does not exist. +
        • +
        • +Support for all box styles. In CSS: switched to outline-style instead of border for boxes. +
        • +
        • +Support for vertical space insets. +
        • +
        • +Support for references inside paragraphs and formatted references. +
        • +
        • +Listings are now converted using <pre> tags, instead of <code>. They are also justified left. +
        • +
        • +Solved bug that prevented numbered listings to appear numbered (thanks, Sam!). +
        • +
        • +Support for generic Flex insets, incuding Flex CharStyle:MenuItem. +
        • +
        • +All &nbsp; entities are now generated as the Unicode U+00A0 character. +
        • +
        • +New option --iso885915 to generate a document with ISO-8859-15 encoding. +
        • +
        • +Support for Sam Liddicott’s Newfangle module for literate programming. +
        • +
        • +Updated the developer guide for potential contributors; added link from the main page. +
        • +
        • +Support for \underbrace and \overbrace (as bars and without sub/superscripts). +
        • + +
        + +
      • +
      • +0.40 (2010-01-19):
          +
        • +Faster (about 25%) BibTeX file parsing. +
        • +
        • +Show version number after a crash. +
        • +
        • +Imported Jens Nöckel’s contributed list of LaTeX to Unicode mappings: , and many more. +
        • +
        • +Added support for compressed documents (Document ▷ Compressed). +
        • +
        • +Added configurable alignment support for equation environments (thanks, Jens!). Multiple labels per formula are correctly processed. +
        • +
        • +Added a couple of note insets for Tufte document classes, appearing as side notes without a reference (thanks, Joachim!). +
        • +
        • +Support for escaped characters in BibTeX files, added German umlauts for starters. +
        • +
        • +Support for internationalization using GNU gettext files. Added Spanish and German translations in the po/ folder. +
        • +
        • +Support for verbatim includes. +
        • + +
        + +
      • +
      • +0.39 (2009-12-20):
          +
        • +Avoid oversized images on IE6. +
        • +
        • +Solved several crashes with the LyX documentation (thanks, Uwe!). +
        • +
        • +Created script to lorem-ipsumize texts, found in src/loremipsumize.py. +
        • +
        • +Solved some issues with BibTeX parsing; now it should work with most real-world files (thanks, Ken!). Also improved error reporting and implemented a new way of line-by-line parsing from file, activated with --lowmem. +
        • +
        • +Support for binomial coefficients: (AB). Ignore commands \leftroot, \uproot. Generic support for variable commands in math mode. +
        • +
        • +Support for omitted aligned brackets: right) (thanks, Jens!). +
        • +
        • +Solved bug with image conversion from directories (thanks, Olivier!). +
        • + +
        + +
      • +
      • +0.38 (2009-12-03):
          +
        • +Resized all logos in the documentation. +
        • +
        • +Solved bug in paragraph indentation that indented all formula spans and elements. +
        • +
        • +Solved a couple of bugs in image scaling: wraps with images, images in figures. +
        • +
        • +Solved bug in TOC generation: article-class documents had their TOC depth off-by-one. +
        • +
        • +Solved bug with listings inserted in documents using LyX 1.6, and improved their looks. +
        • +
        • +Slight font size reduction on Firefox, and huge reduction on some other proprietary browsers. Now global font size specification is done using percents. +
        • +
        • +New commands: \gtrless: , \complement: , \measuredangle: , \sphericalangle: , \nmid: , \circeq: , \lessgtr: , \nparallel: . +
        • + +
        + +
      • +
      • +0.37 (2009-11-30):
          +
        • +Further improvements in float manipulation: figures enclosing other figures have their own tweaked CSS class (thanks, Olivier). +
        • +
        • +PNG and JPEG images are not rescaled anymore, and never shown above their maximum size. Width and height are set using CSS properties. +
        • +
        • +TOC generation for unordered entries (like Section*) and entries inserted in other layouts. Max TOC depth and max numbering depth are honored. Also solved bug in tagging of unordered parts. +
        • +
        • +Implemented indented paragraphs when specified in the document. +
        • +
        • +Horizontal fill is now shown as a fixed-width space. +
        • +
        • +Simplified postprocessing code. Inclusion of child documents is now done inside a Standard layout. +
        • +
        • +Support for commands \varkappa: ϰ, \varnothing: , \mathring: , \backprime: , \notin: , \hfill: , \circledR: ®, \hslash: . +
        • +
        • +New option --splitpart to split the output in multiple pages, one page per part; needs more tweaking. +
        • + +
        + +
      • +
      • +0.36 (2009-11-19):
          +
        • +New in-memory processing of a document before file output, activated by default. It includes: TOC generation (TOC entries admit typefaces, colors, weights, spaces, short titles but restrict most other content), sequential numbering to bibliography entries, lists of floats (figures, tables, algorithms), correct labeling of references and use of the embedded title as HTML title. +
        • +
        • +New option --lowmem to do one-pass filtering only, to preserve memory (keeping the old behavior). +
        • +
        • +Updated the developer guide. +
        • +
        • +Change the postprocessing of equation labels so that only one anchor is used for the whole equation. +
        • +
        • +Added \mathscr and a few script fonts: hello. Added several characters for math script (\mathscr), fraktur (\mathfrak) and blackboard (\mathbb) fonts, and implemented the translation to Unicode chars: , 𝔉, 𝔽. +
        • +
        • +New math commands: \dfrac, implemented as \cfrac; \c for cedilla, already implemented as characters and now as decoration: ; thick space \; and quotes ": " "; \hspace for horizontal space and \vspace for vertical space; and a few size commands: \big, \Big, \bigg, \Bigg, \middle. +
        • +
        • +Added a parent attribute to every Container, for easier processing. +
        • +
        • +Image conversion and display: process width and height in an image if both are present; use % width of image within a float to scale the float; set max scaling of images to 100% with max-width CSS attribute. (Thanks, Olivier and Uwe.) +
        • +
        • +Subfloats are numbered (a), (b) (instead of x.ya, x.yb). +
        • +
        • +Convert all pathnames for image conversion using sys.getfilesystemencoding(). +
        • + +
        + +
      • +
      • +0.35 (2009-11-05):
          +
        • +Added new characters: \checkmark , \blacklozenge , \nexists , \mathcircumflex ^. +
        • +
        • +Updated all documentation to LyX 1.6. +
        • +
        • +Solved CSS validation error in table.align (thanks, Olivier). +
        • +
        • +Solved XHTML validation error in greyed out note, removing useless divs. +
        • +
        • +Add a space after a fraction and before the units: 32 km, (7)/(16) s. +
        • +
        • +Corrected display of float within a float (thanks again, Olivier!). +
        • +
        • +Modified the meaning of --toc to be an on/off switch; the old behavior is now under --toctarget. +
        • +
        • +Changed the 2009-11-05 option --cutpart to --splitpart: new option to split the output file in parts. Not yet working correctly (for instance, links are not redirected). +
        • +
        • +eLyXer now understands and processes new Graphics options: width 50col%, height 50theight% and friends (thanks, Uwe). +
        • +
        • +PDF images are cropped before conversion to PNG (thanks, Uwe). +
        • +
        • +Included child documents can be inserted using firstline and lastline (as seen in EmbeddedObjects.lyx). +
        • + +
        + +
      • +
      • +0.34 (2009-10-28):
          +
        • +Support for child document inclusion (Insert ▷ File ▷ Child Document…). +
        • +
        • +Avoid generating images on different directories (relative paths starting with ../). +
        • +
        • +Added \maltese and financial symbols $, €, ¥. +
        • +
        • +Removed annoying message “Unexpected end of bracket” when parsing empty brackets. +
        • +
        • +Support for \raisebox. +
        • +
        • +Created new structure of Writers, preparing for document segmentation and TOC generation. +
        • + +
        + +
      • +
      • +0.33 (2009-10-19):
          +
        • +New TOC generation process based on an already-generated HTML document, not ready for prime time yet. +
        • +
        • +Adapted --help option so that it shows the executable file as invoked (elyxer.py, elyxer or whatever). Expanded online help from this command. +
        • +
        • +Support for new text commands \textsf, \texttt, \textit, \textbf, \textsl, \textsc. +
        • +
        • +Properly parse all text commands \text…, including \textipa. +
        • +
        • +Support for \cfrac. Now regular \frac shows embedded formulas smaller. +
        • +
        • +Do not number equations containing *, like in \begin{align*}. (Once more, thanks Uwe.) +
        • +
        • +Properly align equations for AMS align environment. Other environments are parsed but not necessarily honored. +
        • +
        • +Correctly distinguish \epsilon ϵ from \varepsilon ε. +
        • +
        • +Added TeX-to-Unicode mappings from Markus Kuhn. +
        • +
        • +Support for \unitfrac. +
        • +
        • +Added \dots: . +
        • + +
        + +
      • +
      • +0.32 (2009-10-05):
          +
        • +Fixed unit processing. Now units appear separated by a space after the number. +
        • +
        • +Repaired use of AlphaCommands. Decorations so defined in the configuration file appear again as a single symbol: . +
        • +
        • +Added option --lyxformat to return the highest LyX format that eLyXer understands. Should help when integrating with lyx2lyx. +
        • +
        • +Improved TOC (table of contents) generation. Modified option --toc to accept an URL, and documented it. +
        • +
        • +Added option --target to add a target frame to every link. +
        • +
        • +Corrected equation numbering error: now all \begin{equation}…\end{equation} formulae are numbered. (Thanks once more, Uwe.) +
        • + +
        + +
      • +
      • +0.31 (2009-09-27):
          +
        • +Modified image parsing code to remove dependency on Python 2.5, expurging os.SEEK_CUR. +
        • +
        • +Removed the ill-fated elyxerconv.py library file (but kept io/convert.py), see lyx-devel thread. Now the file elyxer.py itself can be installed as a library, and run as a module with python -m.; see also lyx-devel thread. +
        • +
        • +eLyXer was added to the Python Package Index (PyPI) starting with 0.30. Now it should be automatically registered for each release. +
        • +
        • +Updated documentation (user guide, README file) with details of distutils installation. +
        • +
        • +Modified single string Containers (StringContainer, Constant) so that they appear as empty Containers — should speed up postprocessing. +
        • +
        • +Solved bug when parsing BibTeX files with incorrect lines. +
        • +
        • +Modified postprocessing to correctly process lists within tables. +
        • +
        • +In the process refactored postprocessing completely: now instead of unconditional postprocessor stages, each stage can add a postprocessing hook. Should be faster — but is indeed a bit slower. +
        • + +
        + +
      • +
      • +0.30 (2009-09-13):
          +
        • +Removed most comments from the final distributed file elyxer.py. +
        • +
        • +Added distutils support for cross-platform distribution. The library elyxerconv is added to local Python libraries. +
        • +
        • +Added command line option --forceformat: force eLyXer to convert all images to the given output format. +
        • +
        • +Switched all options in command line help to quotes: --title <title> is now --title "title". +
        • +
        • +Solved bug reported by Uwe Stöhr when reading Windows BibTeX file generated by JabRef. Now eLyXer tries several encodings for each file, initially UTF-8 and Cp1252. +
        • +
        • +Another bug, also reported by Uwe Stöhr, in branch selection. Added test branches.lyx. +
        • + +
        + +
      • +
      • +0.29 (2009-09-08):
          +
        • +Preliminary support for BibTeX. Configurable output styles (albeit cumbersome and quite primitive). +
        • +
        • +Added new cite commands citep, citet, citealt; and reference command prettyref. +
        • +
        • +A couple of new math commands: \ldots, \qquad. +
        • + +
        + +
      • +
      • +0.28 (2009-09-05):
          +
        • +Various fixes related to Windows integration. +
        • +
        • +Documented integration with LyX in the user guide. +
        • + +
        + +
      • +
      • +0.27 (2009-06-17):
          +
        • +Units without the magnitude (the number) are working. +
        • +
        • +Complex roots now working, added to the math showcase. +
        • +
        • +Leave JPEG images untransformed instead of converting them to PNG (or at least transform them to JPEG). Read JPEG image sizes. +
        • +
        • +More flexible configuration options for lists of values. +
        • +
        • +Added --destdirectory option to convert images into. +
        • +
        • +Image conversion from a different directory (or even with absolute paths) should work now. +
        • +
        • +Changed the whole infrastructure for formulae parsing. More structured parsing should now be possible, e.g. square brackets are first-class citizens. +
        • +
        • +Implemented nice fractions: 78. +
        • +
        • +Redid basic typography: default font is now sans-serif, which looks better on your average browser. Formulae have a bit more space around. +
        • +
        • +Imported the complete symbol list from the unicodesymbols file in LyX. +
        • + +
        + +
      • +
      • +0.26 (2009-06-10):
          +
        • +Added a lot of new LaTeX commands, both for Unicode symbols and for math functions. +
        • +
        • +New mechanism to include new lists of “command:Unicode” equivalents. +
        • +
        • +New decoration command \overrightarrow, to show a long arrow above some text. +
        • +
        • +Solved bug: --directory option was not working. A new test for this option added. +
        • + +
        + +
      • +
      • +0.25 (2009-06-08):
          +
        • +Added new characters: German dash separator, a few arrows, horizontal ellipsis. +
        • +
        • +Automatic insertion of release date in the changelog upon version release. +
        • +
        • +New formula commands: phantom text (for spacing), mbox (literal text). +
        • +
        • +Solved two bugs in URLs: make FlexURLs point to the link in their contents, and do not show “mailto:” in email links. +
        • +
        • +Properly display Date layouts as <h2>. +
        • +
        • +Display a FATAL error (and terminate) when trying to read beyond the end of the document. +
        • +
        • +Cross-platform support for newlines. Besides the Unix \n, now supports Windows (\r\n) and Mac OS X (\r) newlines. +
        • +
        • +Support for \unit command, showing units for a magnitude. +
        • +
        • +New format for formulae (instead of $…$ or \[…\]): \command{…}. +
        • + +
        + +
      • +
      • +0.24 (2009-06-02):
          +
        • +Show sum and integral limits correctly in Konqueror, Safari and Chrome. +
        • +
        • +Also show roots and arrays correctly in those browsers. Larger radical symbol looks better. +
        • +
        • +Added Math Showcase to test on browsershots.org. +
        • +
        • +Substituted medium mathematical spaces with midspaces for better browser compatibility. +
        • +
        • +Added --unicode option to switch on full Unicode output; right now only re-adds medium mathematical spaces. +
        • +
        • +Included all Greek letters, upper and lower case; and common math symbols. +
        • +
        • +Make title from command line option prevail over PDF title. +
        • +
        • +Specified minimum browser versions in the user guide and in the requirements. +
        • +
        • +Documented option --directory (it existed already but was not in the docs). +
        • +
        • +Option --toc can generate a Table Of Contents. Not documented because it is only a start for bigger things. +
        • +
        • +Repaired configuration export to base.cfg: now all objects in config.py are automatically exported. +
        • + +
        + +
      • +
      • +0.23 (2009-05-24):
          +
        • +Corrected numbering and appearance of subfloats. +
        • +
        • +Plain layouts are not reflected in HTML output. +
        • +
        • +Unified table parsing, moved table starts to configuration file. +
        • +
        • +Use unicode output in debug and error messages. +
        • +
        • +Automated testing now shows unified diff, to show the file that doesn’t pass the tests. +
        • +
        • +Finally got UTF-8 output right (hopefully). +
        • +
        • +Display floats with tables properly aligned, and on a white background. Listings are working too. +
        • +
        • +Show warning when document is created with LyX 1.4.x. +
        • +
        • +Transform \newpage to an empty paragraph. +
        • +
        • +Standard layouts can be <div> or nothing at all, generating valid XHTML. +
        • +
        • +Added nomenclature commands for 1.5.x. +
        • +
        • +Got Index and nomenclature working again, added test file so they don’t break anymore. +
        • + +
        + +
      • +
      • +0.22 (2009-05-15):
          +
        • +Modified user guide to explain --html option. +
        • +
        • +Solved a few bugs manifested when exporting to HTML 4.0 with --html. +
        • +
        • +More configurable containers: quote types, barred text, boxes, info insets… +
        • +
        • +Added note on the main page about slow mirrors and latest versions. +
        • +
        • +Standard layouts can now be translated to <div> or to <span>, depending on the context. +
        • +
        • +Command endings can be deduced from starts in configuration file. +
        • +
        • +A bunch of new math symbols: nu, angle brackets. +
        • +
        • +Generalized big brackets of several types. Consolidated parameter parsing in formulas. +
        • +
        • +Equation numbering is working. +
        • +
        • +Unknown commands are shown in red: \unknown. +
        • + +
        + +
      • +
      • +0.21 (2009-05-11):
          +
        • +Command line option --html to export to HTML 4.0. +
        • +
        • +Container endings are now configurable from the main config file. +
        • +
        • +Styles can be mixed and matched at will (like typewriter bold in blue). +
        • +
        • +All constant strings (such as “Table of contents”) should now be configurable. +
        • +
        • +Added a few more colors: green, magenta, cyan, yellow, white (those two were yellow and white). +
        • + +
        + +
      • +
      • +0.20 (2009-05-09):
          +
        • +Command line option --version to show the current version number and date. +
        • +
        • +Release date is now automatically added to the configuration. +
        • +
        • +Preliminary support for inset boxes. +
        • +
        • +Support for numbered listings. +
        • +
        • +Added <meta> tag for Content-Type, to ease importing into word processors. +
        • +
        • +Automated version generation, taking version number and date from config, and updating current version in the main page. +
        • + +
        + +
      • +
      • +0.19 (2009-05-07):
          +
        • +More powerful configuration file manipulation: export to generic config and Python files. +
        • +
        • +Start lines for every parsed structure can now be configured in the global base.cfg file. +
        • +
        • +New Info types package and textclass. +
        • +
        • +New formula symbols: up and down arrows, long double arrows, Gamma and Upsilon, mu, backslash. +
        • +
        • +Show line number and current line for generic errors. +
        • +
        • +Listings and document abstracts are displayed properly. +
        • + +
        + +
      • +
      • +0.18 (2009-05-04):
          +
        • +Wrap floats are separated by a bit of space (two exes, actually) from the text. +
        • +
        • +Solved bug when running without any arguments. +
        • +
        • +Main executable file is now changed from elyxer to elyxer.py, to prevent problems on platforms that require the extension; main source file has changed from elyxer.py to principal.py, to avoid confusion. +
        • +
        • +Moved all parsing code to the new package parse, and configuration files to package conf. +
        • +
        • +All configuration is now read from (and written to) plain text files. +
        • + +
        + +
      • +
      • +0.17 (2009-04-27):
          +
        • +Alignment of table cells is now respected, both horizontally and vertically. +
        • +
        • +Wrap floats are actually floated left or right. +
        • +
        • +Correctly interpret symbols in formulae: !, ;,  ≤ ,  ≥ ,  ≠ ,   ∈ , , and a few spaces. +
        • +
        • +In formulae, \displaystyle and friends are ignored. +
        • +
        • +Square roots are again displayed correctly, and even better than before! +
        • +
        • +Cases are working (not perfect: with a bar instead of a bracket, but working). +
        • + +
        + +
      • +
      • +0.16 (2009-04-22):
          +
        • +Document date is shown centered. +
        • +
        • +Special rows in a longtable are properly ignored. +
        • +
        • +Multicolumn cells are properly interpreted. +
        • +
        • +Sums and integral limits are properly displayed with respect to the symbol: i = 1. +
        • + +
        + +
      • +
      • +0.15 (2009-04-19):
          +
        • +Info insets (containing shortcuts) are now interpreted and shown. +
        • +
        • +LyX-Code is interpreted as a <pre> tag. +
        • +
        • +Reorganized code into a few packages. +
        • +
        • +Line numbers are not shown for utility classes. +
        • +
        • +Floats (figures, tables and algorithms) are now numbered. +
        • +
        • +Float links point to the start of the table or figure, not to the caption. +
        • + +
        + +
      • +
      • +0.14 (2009-04-13):
          +
        • +Deeper layouts (of any kind, not just in lists) are now supported. +
        • +
        • +Appendices are numbered correctly (as A, B, C…). +
        • +
        • +Sections in deeper layouts are numbered correctly too. +
        • +
        • +Double dash does not catch Unix-style options: --css is not converted -- while the version with spaces is. +
        • +
        • +Corrected serious bug in formula parsing affecting inline arrays. +
        • +
        • +Arrays with vertical alignment are correctly parsed. +
        • + +
        + +
      • +
      • +0.13 (2009-04-12):
          +
        • +Lists are correctly displayed, instead of one list per item. +
        • +
        • +Lists can contain nested layouts. +
        • +
        • +List layouts (not to mistake with Enumerate or Itemize lists) are processed correctly. +
        • +
        • +Changelog moved to separate document. +
        • +
        • +Read image sizes correctly on big-endian architectures (e.g. Mac OS X on PowerPC). +
        • +
        • +Numeration of chapters, sections… is working. +
        • +
        • +Error messages now show the line where they happen. +
        • + +
        + +
      • +
      • +0.12 (2009-04-05):
          +
        • +Arrays are parsed correctly and displayed acceptably. +
        • +
        • +Numbers and units are correctly separated. +
        • +
        • +Text decorations (such as ) are shown in line. +
        • +
        • +Variables are italicized. +
        • +
        • +Notes and comments are not output at all, greyed-out notes are shown in grey. +
        • +
        • +LyX guides parse completely. +
        • + +
        + +
      • +
      • +0.11 (2009-03-27):
          +
        • +Arrays are at least well parsed (but still show wrong). +
        • +
        • +Integrals and sums appear as large characters. +
        • +
        • +Appendices are separated from the main document. +
        • +
        • +The bibliography appears separated with a title. +
        • +
        • +Floats appear centered on-screen. +
        • + +
        + +
      • +
      • +0.10 (2009-03-23):
          +
        • +Better handling of footnotes and margin notes: not overlapping and with a reference in the text. +
        • +
        • +Better parsing of first word in a Description. +
        • +
        • +Short titles are ignored. +
        • +
        • +Added a few font families for equations. Not that they display too well… +
        • + +
        + +
      • +
      • +0.9 (2009-03-21):
          +
        • +Better formula parsing (including line breaks). Supports a few math fonts. +
        • +
        • +Supports menu separator, text with bar, nomenclature and many more quote types. +
        • +
        • +Single configuration file general.py. +
        • +
        • +Layout of type Space is not shown. +
        • +
        • +Supports branches. Inactive branches are not shown. +
        • +
        • +New symbols: greek letters, shapes: bullet, right triangle. +
        • +
        • +Added support for new style (1.6.x) index entries. +
        • +
        • +From LyX documentation: UserGuide.lyx is now working (except for some math functions). +
        • + +
        + +
      • +
      • +0.8 (2009-03-20):
          +
        • +Can be run from other directories than the one with the document. +
        • +
        • +Tables have light grey separations. Table spacing is now better adjusted. +
        • +
        • +Descriptions appear with the first word in bold), but only within the first text style. Changing style in the middle of a word may distract the algorithm. +
        • +
        • +Added support for Lyx notes (not rendered in the HTML), margin notes, pretty quotes ‘’, weird spaces. +
        • +
        • +Added support for new style (1.6.x) hyperlinks, labels and references, TOC, index. +
        • +
        • +Uses PDF title if present. +
        • +
        • +From LyX documentation: Intro.lyx is now working. +
        • + +
        + +
      • +
      • +0.7 (2009-03-16):
          +
        • +Images referenced by absolute path are converted to relative PNGs. +
        • +
        • +Range of supported quotes is greater. Unknown quotes are now marked as errors but do not make the tool fail. +
        • +
        • +Default CSS is always on nongnu.org, it can be changed via command line option --css. +
        • +
        • +Reinstated layout classes for unknown types. +
        • +
        • +Updated documentation to include how to run on Windows. +
        • +
        • +Added meta generator tag to all pages. +
        • +
        • +Added option --title to change the default page title. +
        • +
        • +Phonetic symbols appear in dark cyan: [sample]. +
        • +
        • +Lots of small fixes and improvements to correctly parse the official LyX guides (UserGuide.lyx, EmbeddedObjects.lyx and Math.lyx). +
        • + +
        + +
      • +
      • +0.6 (2009-03-15):
          +
        • +Added Flex URLs, Flex code. +
        • +
        • +Works with Python 2.3.5, but not yet Mac OS X terminal. +
        • +
        • +Alignment now works right (and center and left). +
        • +
        • +Modified license files to comply with Savannah policies. +
        • +
        • +Added index page and logo. +
        • + +
        + +
      • +
      • +0.5 (2009-03-14):
          +
        • +Inset parameters are all parsed correctly (including spaces in image paths). +
        • +
        • +Formulae and tables should work again (including complex formatting). +
        • +
        • +Modified to (mostly) run under Python 2.3.5 (Mac OS X Tiger). +
        • +
        • +Processes layouts ending in ‘*’ (like ‘Section*’). +
        • +
        • +Runtime options for help and to disable the copyright notice, debug, quietness. +
        • +
        • +Accepts scaling for images. +
        • +
        • +Nested lists working. +
        • + +
        + +
      • +
      • +0.4 (2009-03-12):
          +
        • +When images do not exist warns but does not fail. +
        • +
        • +Author and title containing tags are properly processed. +
        • +
        • +Slanted text translated to italics. +
        • +
        • +Title no longer necessary to have a working document. +
        • +
        • +ERT is ignored. Status line (open/collapsed) is ignored. +
        • +
        • +Supports footnotes, newlines, bibitem entries and citations. +
        • +
        • +Dev guide includes a Container tutorial. +
        • + +
        + +
      • +
      • +0.3 (2009-03-11): Now works with generic Insets. +
      • +
      • +0.2 (2009-03-11): ImageMagick is not required anymore. +
      • +
      • +0.1 (2009-03-10): first public version. +
      • + +
      + + + +
      + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/pages-elyxer/container.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/pages-elyxer/container.png differ diff -Nru elyxer-1.2.3/forks/pages-elyxer/container.svg elyxer-1.2.5/forks/pages-elyxer/container.svg --- elyxer-1.2.3/forks/pages-elyxer/container.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/container.svg 2013-03-10 11:34:20.000000000 +0000 @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Container + + + + parser + + + + output + + + + contents + + + + + + + LyX + + + + HTML + + + + + + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/pages-elyxer/converters.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/pages-elyxer/converters.png differ diff -Nru elyxer-1.2.3/forks/pages-elyxer/devguide.html elyxer-1.2.5/forks/pages-elyxer/devguide.html --- elyxer-1.2.3/forks/pages-elyxer/devguide.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/devguide.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,874 @@ + + + + + + + + +eLyxer Developer Guide + + +
      +

      +figure elyxer.png +eLyXer Developer Guide +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 The Basics +

      +
      +This document should help you get started if you want to understand how eLyXer works, and maybe extending its functionality. The package (including this guide and all accompanying materials) is licensed under the GPL version 3 or, at your option, any later version. See the LICENSE file for details. Also visit the main page to find out about the latest developments. +
      +
      +In this first section we will outline how eLyXer performs the basic tasks. Next section will be devoted to more arcane matters. The third section explains how to contribute to eLyXer, while the fourth one deals with future planned extensions. The fifth section includes things that will probably not be implemented. Finally there is a FAQ that contains answers to questions asked privately and on the lyx-devel list [7]. +
      +

      +1.1 Getting eLyXer +

      +
      +If you are interested in eLyXer from a developer perspective the first thing to do is fetch the code. It is included in the standard distribution, so just navigate to the src/ folder and take a look at the .py Python code files. +
      +
      +For more serious use, or if your distribution did not carry the source code, or perhaps to get the latest copy of the code: you need to install the tool git, created by Linus Torvalds (of Linux fame) [8]. You will also need to have Python installed; versions at or above 2.4 should be fine [9]. The code is hosted in Savannah [1], a GNU project for hosting non-GNU projects. So first you have to fetch the code: +
      +
      +$ git clone git://git.sv.gnu.org/elyxer.git
      +
      +
      +You should see some output similar to this: +
      +
      +Initialized empty Git repository in /home/user/install/elyxer/.git/
      +remote: Counting objects: 528, done.
      +remote: Compressing objects: 100% (157/157), done.
      +remote: Total 528 (delta 371), reused 528 (delta 371)
      +Receiving objects: 100% (528/528), 150.00 KiB | 140 KiB/s, done.
      +Resolving deltas: 100% (371/371), done. 
      +
      +
      +Now enter the directory that git has created. +
      +
      +$ cd elyxer
      +
      +
      +Your first task is to create the main executable file: +
      +
      +$ ./make
      +
      +
      +The build system for eLyXer will compile it for you, and even run some basic tests. (We will see later on section 3.1↓ how this “compilation” is done.) Now you can try it out: +
      +
      +$ cd docs/
      +$ ../elyxer.py devguide.lyx devguide2.html
      +
      +
      +You have just created your first eLyXer page! The result is in devguide2.html; to view it in Firefox: +
      +
      +$ firefox-bin devguide2.html
      +
      +
      +If you want to debug eLyXer then it is better to run it from the source code folder, instead of the compiled version. For this you need to make just a small change, instead of elyxer.py run src/principal.py: +
      +
      +$ ../src/principal.py --debug devguide.lyx devguide2.html
      +
      +
      +and you will see the internal debug messages. +
      +
      +Note for Windows developers: on Windows eLyXer needs to be invoked using the Python executable, and of course changing the slashes to backward-slashes: +
      +
      +> Python ..\elyxer.py devguide.lyx devguide2.html
      +
      +
      +or for the source code version: +
      +
      +> Python ..\src\elyxer.py devguide.lyx devguide2.html
      +
      +
      +If you want to install the created version you just have to run the provided install script as root: +
      +
      +# ./install
      +
      +
      +Once eLyXer has been installed it can be invoked as any other Unix command: +
      +
      +$ elyxer.py devguide.lyx devguide3.html
      +
      +
      +In the rest of this section we will delve a little bit into how eLyXer works. +
      +

      +1.2Containers +

      +
      +The basic code artifact (or ‘class’ in Python talk) is the Container, located in the gen package (file src/gen/Container.py). Its responsibility is to take a bit of LyX code and generate working HTML code. This includes (with the aid of some helper classes): reading from file a few lines, converting it to HTML, and writing the lines back to a second file. +
      +
      +The following figure 1↓ shows how a Container works. Each type of Container should have a parser and an output, and a list of contents. The parser object receives LyX input and produces a list of contents that is stored in the Container. The output object then converts those contents to a portion of valid HTML code. +
      +
      +
      +
      +
      +figure container.png + +
      +
      +Figure 1 Container structure. +
      + +
      + +
      + +
      +
      +Two important class attributes of a Container are: +
      +
        +
      • +start: a string of text containing the LyX command that we are about to process; +
      • +
      • +and ending, which is used on some Containers to determine when to stop parsing. +
      • + +
      +
      +A class called ContainerFactory has the responsibility of creating the appropriate containers, as the strings in their start attributes are found. +
      +
      +The basic method of a Container is: +
      +
        +
      • +process(): called after parsing the LyX text and before outputting the HTML result. Here the Container can alter its contents as needed, once everything has been read and before it is output. +
      • + +
      +
      +Now we will see each subordinate class in detail. +
      +

      +1.3Parsers +

      +
      +The package parse contains almost all parsing code; it has been isolated on purpose so that LyX format changes can be tackled just by changing the code in that directory. +
      +
      +A Parser has two main methods: parseheader() and parse(). +
      +
      +parseheader(): parses the first line and returns the contents as a list of words. This method is common for all Parsers. For example, for the command ’\\emph on’ the Parser will return a list [’\\emph’,’on’]. This list will end up in the Container as an attribute header. +
      +
      +parse(): parses all the remaining lines of the command. They will end up in the Container as an attribute contents. This method depends on the particular Parser employed. +
      +
      +Basic Parsers reside in the file parser.py. Among them are the following usual classes: +
      +
      +LoneCommand: parses a single line containing a LyX command. +
      +
      +BoundedParser: reads until it finds the ending. For each line found within, the BoundedParser will call the ContainerFactory to recursively parse its contents. The parser then returns everything found inside as a list. +
      +

      +1.4 Outputs +

      +
      +Common outputs reside in output.py. They have just one method: +
      +
      +gethtml(): processes the contents of a Container and returns a list with file lines. Carriage returns \n must be added manually at the desired points; eLyXer will just merge all lines and write them to file. +
      +
      +Outputs do not however inherit from a common class; all you need is an object with a method gethtml(self,container) that processes the Container’s contents (as a list attribute). An output can also use all attributes of a Container to do their job. +
      +

      +1.5 Tutorial: Adding Your Own Container +

      +
      +If you want to add your own Container to the processing you do not need to modify all these files. You just need to create your own source file that includes the Container, the Parser and the output (or reuse existing ones). Once it is added to the types in the ContainerFactory eLyXer will happily start matching it against LyX commands as they are parsed. +
      +
      +There are good examples of parsing commands in just one file in image.py and formula.py. But let us build our own container BibitemInset here. We want to parse the LyX command in listing 1↓. In the resulting HTML we will generate an anchor: a single tag <a name="mykey"> with fixed text "[ref]". +
      +
      +
      +
      +
      +\begin_inset CommandInset bibitem
      +LatexCommand bibitem
      +key "mykey"
      +\end_inset +
      +
      +Algorithm 1 The LyX command to parse. +
      + +
      + +
      + +
      +
      +We will call the Container BibitemInset, and it will process precisely the inset that we have here. We will place the class in bibitem.py. So this file starts as shown in listing 2↓. +
      +
      +
      +
      +
      +class BibitemInset(Container):
      +  "An inset containing a bibitem command"
      +  
      +  start = ’\\begin_inset CommandInset bibitem’
      +  ending = ’\\end_inset’ +
      +
      +Algorithm 2 Class definition for BibitemInset. +
      + +
      + +
      + +
      +
      +We can use the parser for a bounded command with start and ending, BoundedParser. For the output we will generate a single HTML tag <a>, so the TagOutput() is appropriate. Finally we will set the breaklines attribute to False, so that the output shows the tag in the same line as the contents: <a …>[ref]</a>. Listing 3↓ shows the constructor. +
      +
      +
      +
      +
      +  def __init__(self):
      +    self.parser = BoundedParser()
      +    self.output = TagOutput()
      +    self.tag = ’a’
      +    self.breaklines = False +
      +
      +Algorithm 3 Constructor for BibitemInset. +
      + +
      + +
      + +
      +
      +The BoundedParser will automatically parse the header and the contents. In the process() method we will discard the first line with the LatexCommand, and place the key from the second line as link destination. The class StringContainer holds string constants; in our case we will have to isolate the key by splitting the string around the double quote ", and then access the anchor with the same name. The contents will be set to the fixed string [ref]. The result is shown in listing 4↓. +
      +
      +
      +
      +
      +  def process(self):
      +    #skip first line
      +    del self.contents[0]
      +    # parse second line: fixed string
      +    string = self.contents[0]
      +    # split around the "
      +    key = string.contents[0].split(’"’)[1]
      +    # make tag and contents
      +    self.tag = ’a name="’ + key + ’"’
      +    string.contents[0] = ’[ref] ’ +
      +
      +Algorithm 4 Processing for BibitemInset. +
      + +
      + +
      + +
      +
      +And then we have to add the new class to the types parsed by the ContainerFactory; this has to be done outside the class definition. The complete file is shown in listing 5↓. +
      +
      +
      +
      +
      +from parser import *
      +from output import *
      +from container import *
      +  
      +class BibitemInset(Container):
      +  "An inset containing a bibitem command"
      +  
      +  start = ’\\begin_inset CommandInset bibitem’
      +  ending = ’\\end_inset’
      +  
      +  def __init__(self):
      +    self.parser = BoundedParser()
      +    self.output = TagOutput()
      +    self.breaklines = False
      +  
      +  def process(self):
      +    #skip first line
      +    del self.contents[0]
      +    # parse second line: fixed string
      +    string = self.contents[0]
      +    # split around the "
      +    key = string.contents[0].split(’"’)[1]
      +    # make tag and contents
      +    self.tag = ’a name="’ + key + ’"’
      +    string.contents[0] = ’[ref] ’
      +  
      +ContainerFactory.types.append(BibitemInset) +
      +
      +Algorithm 5 Full listing for BibitemInset. +
      + +
      + +
      + +
      +
      +The end result of processing the command in listing 1↑ is a valid anchor: +
      +
      +<a name="mykey">[ref] </a> +
      +
      +The final touch is to make sure that the class is run, importing it in the file gen/factory.py, as shown in listing 6↓. This ensures that the ContainerFactory will know what to do when it finds an element that corresponds to the BibitemInset. +
      +
      +
      +
      +
      +
      +from structure import *
      +from bibitem import *
      +from container import *
      + +
      +
      +Algorithm 6 Importing the BibitemInset from the factory file. +
      + +
      + +
      + +
      +
      +Now this Container is not too refined: the link text is fixed, and we need to do additional processing on the bibitem entry to show consecutive numbers. The approach is not very flexible either: e.g. anchor text is fixed. But in less than 20 lines we have parsed a new LyX command and have outputted valid, working XHTML code. The actual code is a bit different but follows the same principles; it can be found in src/bib/biblio.py: in the classes BiblioCite and BiblioEntry, and it processes bibliography entries and citations (with all our missing bits) in about 50 lines. +
      +

      +2 Advanced Features +

      +
      +This section tackles other, more complex features; all of them are included in current versions. +
      +

      +2.1 Parse Tree +

      +
      +On initialization of the ContainerFactory, a ParseTree is created to quickly pass each incoming LyX command to the appropriate containers, which are created on demand. For example, when the ContainerFactory finds a command: +
      +
      +\\emph on +
      +
      +it will create and initialize an EmphaticText object. The ParseTree works with words: it creates a tree where each keyword has its own node. At that node there may be a leaf, which is a Container class, and/or additional branches that point to other nodes. If the tree finds a Container leaf at the last node then it has found the right point; otherwise it must backtrack to the last node with a Container leaf. +
      +
      +Figure 2↓ shows a piece of the actual parse tree. You can see how if the string to parse is \begin_inset LatexCommand, at the node for the second keyword LatexCommand there is no leaf, just two more branches label and ref. In this case the ParseTree would backtrack to begin_inset, and choose the generic Inset. +
      +
      +
      +
      +
      +figure parse tree.png + +
      +
      +Figure 2 Portion of the parse tree. +
      + +
      + +
      + +
      +
      +Parsing is much faster this way, but there are disadvantages; for one, parsing can only be done using whole words and not prefixes. SGML tags (such as <lyxtabular>) pose particular problems: sometimes they may appear with attributes (as in <lyxtabular version="3">), and in this case the starting word is <lyxtabular without the trailing ’>’ character. So the parse tree removes any trailing ’>’, and the start string would be just <lyxtabular; this way both starting words <lyxtabular> and <lyxtabular are recognized. +
      +

      +2.2 Postprocessors +

      +
      +Some post-processing of the resulting HTML page can make the results look much better. The main stage in the postprocessing pipeline inserts a title “Bibliography” before the first bibliographical entry. But more can be added to alter the result. As eLyXer parses a LyX document it automatically numbers all chapters and sections. This is also done in the postprocessor. +
      +
      +The package post contains most postprocessing code, although some postprocessors are located in the classes of their containers for easy access. +
      +

      +2.3 Mathematical Formulae +

      +
      +Formulae in LyX are rendered beautifully into TeX and PDF documents. For HTML the conversion is not so simple. There are basically three options: +
      +
        +
      • +render the formula as an image (GIF or PNG), then import the image; +
      • +
      • +export a specific language called MathML +
      • +
      • +or render using a variety of Unicode characters, HTML and CSS wizardry [2]. +
      • + +
      +
      +eLyXer employs the third technique, with varied results. Basic fractions and square roots should be rendered fine, albeit at the moment there may be some issues pending. Complex fractions with several levels do not come out right. (But see subsection 2.4↓.) +
      +

      +2.4 MathML +

      +
      +There are two options in place to generate MathML, as suggested by Günther Milne and Abdelrazak Younes [4, 5]. Both rely on some JavaScript page manipulations, and they need to be hosted on the same server as the documents. MathJax is less mature but it has grown faster so it has become the preferred option. +
      +
      +To use this last option in your own pages you just have to add the --mathjax option: +
      +
      +$ elyxer.py --mathjax ./MathJax math.lyx math.html
      +
      +
      +You will notice that the --mathjax option requires an argument: the directory where MathJax resides. MathJax needs to live on your server; after downloading the package, deploy it to your server and give the installation directory as an argument to --mathjax. +
      +
      +In principle you might think of using some external installation of MathJax to avoid downloading it and serving it from your server, e.g. from Savannah: +
      +
      +$ elyxer.py --mathjax http://elyxer.nongnu.org/MathJax/ math.lyx math.html
      +
      +
      +This approach may not work on certain browsers for two reasons: JavaScript loaded from a different site may not work, and WebFonts are also subject to this same-origin policy. If you have made it work it would be great to hear about it. +
      +

      +2.5 Baskets +

      +
      +eLyXer supports a few distinct modes of operation. In each incarnation the tasks to do are quite different: +
      +
        +
      • +A pure filter: read from disk and write to disk each Container, keeping no context in memory. +
      • +
      • +In-memory processing: read a complete file, process it and write it all to disk. +
      • +
      • +TOC generation: output just a table of contents for a LyX document. +
      • +
      • +Split document generation: separates each chapter, section or subsection in a different file. +
      • + +
      +
      +How can it do so many different tasks without changing a lot of code? The answer is in the file gen/basket.py. A Basket is an object that keeps Containers. Once a batch is ready, the Basket outputs them to disk or to some other Basket, but it may decide to just wait a little longer. +
      +
      +The basic Basket is the WriterBasket: it writes everything that it gets to disk immediately and then forgets about it. Some bits of state are kept around, like for example which biliography entries have been found so far, but the bulk of the memory is released. +
      +
      +Another more complex object is the TOCBasket: it checks if the Container is worthy to appear in a TOC, and otherwise just discards it. For chapters, sections and so on it converts them to TOC entries and outputs them to disk. +
      +
      +The MemoryBasket does most of its work in memory: it stores all Containers until they have all been read, then does some further processing on them and outputs an improved version of the document, at the cost of using quite more memory. This allows us for example to generate a list of figures or to set consecutive labels for bibliography entries (instead of just numbering them as they appear in the text). +
      +
      +The most complex kind of Basket is the SplittingBasket: it writes each document part to a separate file, choosing what parts to split depending on the configuration passed in the --splitpart option. By default it creates a TOC at the top of each page. +
      +

      +2.6 Hybrid Functions +

      +
      +Math processing is very configurable; most of it is based on configuration options found in src/conf/base.cfg. Parsing can be done using a few simple functions: commands (contained in [FormulaConfig.commands]) output some content and don’t have any parameters, while one-parameter functions (in [FormulaConfig.onefunctions]) take exactly one parameter and output an HTML tag. Thus, the definition for \bar is: +
      +
      +
      +
      \bar:span class="bar"
      +
      +
      + +
      +
      +Whenever eLyXer finds the command it parses a parameter, then outputs the tag <span class="bar"> surrounding the parameter. For instance: e.g. \bar{38} becomes <span class="bar">38</span> in the output. Decorating functions (in [FormulaConfig.decoratingfunctions]) place a symbol from in the definition above the parameter, and so on. +
      +
      +Such simple processing is not always enough; there is a generic mechanism for producing complex output from a number of parameters. They are called hybrid functions. +
      +
      +Each definition for a hybrid function contains: parser definition, output definition and a number of function tags. The parser definition tells eLyXer what to parse. Hybrid functions can have any number of optional parameters, denoted as [$p]; mandatory parameters are shown as {$p}. Each parameter consists of the symbol $ followed by a letter or number: $0, $p. +
      +
      +The output definition contains regular text, plus parameters and functions. Each function consists of the letter f plus a number, such as f0; and each is associated with a tagged HTML element. These function tags are the last part of the definition. Presently there can be as many as 10 function tags (from f0 to f9). +
      +
      +Let us see a simple example, equivalent to the above formula — a one-parameter, one-tag hybrid function: +
      +
      +
      +
      \fun:[{$p},f0{$p},span class="fun"]
      +
      +
      + +
      +
      +The only function tag f0 generates the HTML tag <span class="fun">. Whenever eLyXer finds \fun in a math formula, it will parse one parameter and put it into $p. Then it will generate f0{$p}, i.e. apply the tag <span class="fun">. Putting it all together: \fun{38} becomes <span class="fun">38</span>. +
      +
      +Parameters can be parsed as a literal, in which case eLyXer will take everything between the brackets without parsing it. Literal parameters can be used within a tag definition. A real life hybrid function with literal parameters: +
      +
      +
      +
      \raisebox:[{$p!}{$1},f0{$1},span class="raisebox" style="vertical-align: $p;"]
      +
      +
      + +
      +
      +In this case there are two mandatory parameters, the first one literal and the second one a regular TeX expression. The output is just one function tag, in this case using the first mandatory parameter. For instance, \raisebox{3cm}{5} would generate: +
      +
      +
      +
      <span class="raisebox" style="vertical-align: 3cm;">5</span>
      +
      +
      + +
      +
      +The parameter $p is parsed as 3cm, which is not parsed further. +
      +
      +Hybrid functions are easy to configure once you get the hang of it. Adding new TeX commands, even complex ones, becomes simply a matter of configuration. +
      +

      +3 Developing and Contributing +

      +
      +This chapter will show you how to further develop eLyXer and how to contribute your own code. +
      +

      +3.1 Distribution +

      +
      +You will notice that in the src/ folder there are several Python files, while in the main directory there is just a big one called elyxer.py. The reason is that before distributing the source code is coalesced and placed on the main directory, so that users can run it without worrying about libraries, directories and the such. (They need of course to have Python 2.5 installed.) And the weapon is a little Python script called coalesce.py that does the dirty job of parsing dependencies and inserting them into the main file. There is also a make Bash script that takes care of permissions and generates the documentation. Just type +
      +
      +$ ./make +
      +
      +at the prompt. This coalesces all code and configuration into elyxer.py. It is a primitive way perhaps to generate the “binary” (ok, not really a binary but a distributable Python file), but it works great. +
      +
      +The make script also runs all of the included tests to check that no functionality has been lost from one release to the next. These tests can also be run independently using the run-tests script: +
      +
      +$ ./run-tests +
      +
      +They are used to verify that no functionality is lost from one version to the next — although issues can certainly slip undetected if there is no test for them. +
      +
      +At the moment there is no way to do this packaging on non-Unix operating systems with a single script, e.g. a Windows .bat script. However the steps themselves are trivial. +
      +

      +3.2 Debugging +

      +
      +Code problems are quite difficult to debug using the full elyxer.py file. It is much better to use the uncoalesced version instead, since it is quite modular and neatly divided. To do so you just need to locate the file src/principal.py and run that instead of elyxer.py. For example, if you are in the docs/ directory and you want to convert math.lyx you can run eLyXer as: +
      +
      +$ ../src/principal.py math.lyx math.html +
      +
      +For extra debugging information you can activate the --debug option: +
      +
      +$ ../src/principal.py --debug math.lyx math.html +
      +
      +This will make any traces more meaningful and will let you follow the code much more easily. +
      +

      +3.3 Configuration +

      +
      +The make script does not just construct a single .py file from all sources; it is also used to extract the configuration in human-readable form and create a Python file which is then coalesced with all the rest. The original configuration file (the one you should modify) is called base.cfg, while the resulting Python file is called config.py. +
      +
      +The original configuration file uses this format: +
      +
      +
      +
      [ContainerConfig.startendings]
      +\begin_deeper:\end_deeper
      +\begin_inset:\end_inset
      +\begin_layout:\end_layout
      +
      +
      + +
      +
      +where each section header is enclosed in square brackets; it contains an object name and a section name. In the example above the object is called ContainerConfig, while the section is called startendings. Inside each section there are a number of key:value pairs separated by a colon; the key is used to reference the value in other Python code. +
      +
      +To create config.py go to the src/ folder and type: +
      +
      +$ ./exportconfig py +
      +
      +This will create all configuration objects to be used inside your Python code, where each section will become an object attribute containing a map. For instance, to access the first value above \end_deeper you would write in your Python code: +
      +
      +ContainerConfig.startendings[’\begin_deeper’] +
      +
      +Each section can contain as many values as needed. +
      +

      +3.4 License +

      +
      +eLyXer is published under the GPL, version 3 or later [3]. This basically means that you can modify the code and distribute the result as desired, as long as you publish your modifications under the same license. But consult a lawyer if you want an authoritative opinion. +
      +

      +3.5 Contributions +

      +
      +All contributions will be published under this same license, so if you send them this way you implicitly give your consent. An explicit license grant would be even better and may be required for larger contributions. +
      +
      +Please send any suggestions, patches, ideas and whatever else related to development to the mailing list. (Alternatively you may contact elyxer@gmail.com privately.) If you are willing to create a patch and submit it, you should patch against the proper sources in src/ and send it to the list. This will make everyone’s lives better than if you patch against elyxer.py. +
      +
      +The first external patches have started arriving during late 2009 and early 2010 (provided by Olivier Ripoll, Geremy Condra and Simon South). You can join in the fun! +
      +

      +4 Roadmap +

      +
      +You can see what user features are planned for the near feature in the wish list. +
      +
      +After the release of eLyXer 1.0, the goal is full LyX document support; any deviation from the output of LyX on e.g. PDF will be considered as bugs. (Keep in mind that some deviations arise in an inherent limitation in the design of eLyXer, and these will logically not be considered as bugs.) +
      +
      +For eLyXer 1.3.0 there are plans to convert it into a proper Python package so it can be installed using full source code (and not a coalesced script elyxer.py that contains everything). Also, once ERTs are parsed, eLyXer might be extended for 1.3.0 to translate generic LaTeX documents. +
      +
      +All this within the usual constraints: day job, family, etc. +
      +

      +5 Discarded Bits +

      +
      +Some features suggested for eLyXer have been discarded; they do not fit with the design of eLyXer or are too much effort for the proposed gains. +
      +

      +5.1 Spellchecking +

      +
      +LyX can use a spellchecker to verify the words used. However it is not interactive so you may forget to run it before generating a version. It is possible to integrate eLyXer with a spellchecker and verify the spelling before generating the HTML, but it is not clear that it can be done cleanly. +
      +

      +5.2 URL Checking +

      +
      +Another fun possibility is to make eLyXer check all the external URLs embedded in the document. However the Python facilities for URL checking are not very mature, at least with Python 2.5: some of them do not return errors, others throw complex exceptions that have to be parsed… It is far easier to just create the HTML page and use wget (or a similar tool) to recursively check all links in the page. +
      +

      +5.3 Use of lyx2lyx Framework +

      +
      +Abdelrazak Younes suggests using the lyx2lyx framework, which after all already knows about LyX formats [5]. It is an interesting suggestion, but one that for now does not fit well with the design of eLyXer: a standalone tool to convert between two formats, or as Kernighan and Plauger put it, a standalone filter [6]. Long-term maintenance might result a bit heavier with this approach though, especially if LyX changes to a different file format in the future. +
      +

      +6 FAQ +

      +
      +Q: I don’t like how your tool outputs my document, what can I do? +
      +
      +A: First make sure that you are using the proper CSS file, i.e. copy the existing docs/lyx.css file to your web page directory. Next try to customize the CSS file to your liking; it is a flexible approach that requires no code changes. Then try changing the code (and submitting the patch back). +
      +
      +Q: How is the code maintained? +
      +
      +A: It is kept in a git repository on Savannah. Patches in git format are welcome (but keep in mind that my knowledge of git is even shallower than my Python skills). +
      +
      +Q: I found a bug, what should I do? +
      +
      +A: Just report it to the Savannah interface, to the mailing list or directly to the main author. +
      +

      Nomenclature

      +class A self-contained piece of code that hosts attributes (values) and methods (functions). +
      +
      +filter A type of program that reads from a file and writes to another file, keeping in memory only what is needed short term. +
      +
      +TOC Table of contents +
      +

      +References +

      +

      +[1] Free Software Foundation, Inc.: eLyXer summary. https://savannah.nongnu.org/projects/elyxer/ +

      +

      +[2] S White: “Math in HTML with CSS”, accessed March 2009. http://www.zipcon.net/~swhite/docs/math/math.html +

      +

      +[3] R S Stallman et al: “GNU GENERAL PUBLIC LICENSE” version 3, 20070629. http://www.gnu.org/copyleft/gpl.html +

      +

      +[4] G Milde: “Re: eLyXer: LyX to HTML converter”, message to list lyx-devel, 20090309. http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg148627.html +

      +

      +[5] A Younes: “Re: eLyXer: LyX to HTML converter”, message to list lyx-devel, 20090309. http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg148634.html +

      +

      +[6] B W Kernighan, P J Plauger: “Software Tools”, ed. Addison-Wesley Professional 1976, p. 35. +

      +

      +[7] Various authors: “lyx-devel mailing list”, accessed November 2009. http://www.mail-archive.com/lyx-devel@lists.lyx.org/ +

      +

      +[8] S Chacon: “Git — Download”, accessed November 2009. http://git-scm.com/download +

      +

      +[9] Python community: “Download Python”, accessed November 2009. http://www.python.org/download/ +

      + + + +
      + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/pages-elyxer/elyxer.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/pages-elyxer/elyxer.png differ diff -Nru elyxer-1.2.3/forks/pages-elyxer/elyxer.svg elyxer-1.2.5/forks/pages-elyxer/elyxer.svg --- elyxer-1.2.3/forks/pages-elyxer/elyxer.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/elyxer.svg 2013-03-10 11:34:20.000000000 +0000 @@ -0,0 +1,1355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/index.html elyxer-1.2.5/forks/pages-elyxer/index.html --- elyxer-1.2.3/forks/pages-elyxer/index.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/index.html 2013-03-10 11:52:27.000000000 +0000 @@ -0,0 +1,120 @@ + + + + + + + + +eLyXer + + +
      +

      +figure elyxer.png +eLyXer +

      +
      +elixir, n: a substance believed to cure all ills. +
      +
      +eLyXer (pronounced elixir) is a LyX to HTML converter. While there are a ton of such projects all over the web, eLyXer has a clear focus on flexibility and elegant output. +
      +
      +LyX is a wonderful text editor which produces beautiful PDF files. Internally it exports documents to LaTeX, and from there to PDF. Sadly there is not an equivalent “export to HTML” option… Until now! With eLyXer you can convert your master’s thesis, learned article, fascinating novel or love letter to a web page that you can then share, publish on the web or import into other text editors. +
      +
      +The user guide can be accessed online. The developer guide is recommended reading for people that want to contribute to the development, especially section 3. For the mathematically inclined: be sure to visit the Math Showcase. +
      +

      +Requirements +

      +
      +eLyXer is a standalone tool: it does not require that LyX is installed to run. It can convert documents generated with versions of LyX from 1.5.5 through 2.0 (and probably earlier versions). It requires Python 2.3.4, and should work with versions up to 2.6.1. It has been tested to run on Linux, Mac OS X and Windows. +
      +
      +Resource usage is minimum. Converting UserGuide.lyx (154 pages, about 40000 words) takes less than 15 seconds on my Asus EeePC 1000H, which sports an Intel Atom processor at 1.60 GHz. Memory usage is also quite frugal, remaining at about 35 MB even with in-memory processing. +
      +
      +The output requires XHTML, CSS2 and Unicode; any CSS2-compatible browser should do. Minimum browser versions for some popular programs are: Microsoft Internet Explorer 7, Mozilla Firefox 3, Safari 3 and Chrome 1. +
      +

      +Usage +

      +
      +eLyXer is a command line tool written in Python. Installation is done using the included installer; just type at the prompt as root: +
      +
      +# python install.py
      +
      +
      +or, on Windows: +
      +
      +> Python.exe install.py
      +
      +
      +Basic usage is as simple as writing at the command line prompt: +
      +
      +$ elyxer.py document.lyx page.html
      +
      +
      +or, on Windows: +
      +
      +> elyxer.py document.lyx page.html
      +
      +
      +where document.lyx is your LyX document, and page.html is the resulting HTML page. Write +
      +
      +$ elyxer.py --help
      +
      +
      +or see the user guide for details. +
      +

      +Downloads +

      +
      + You can download the latest version 1.2.4, created on 2013-01-11, as a zip file or as a tar.gz file. For older versions please refer to the project’s download area. See the change log for information about past versions. +
      +
      +eLyXer (including this page and all accompanying materials) is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See the LICENSE file for details. +
      +
      +math2html (and math.css) is released without warranties or conditions of any kind under the terms of the Apache License, version 2.0. +
      +

      +Contact +

      +
      +You can contact the main developer at elyxer@gmail.com; he really likes getting challenging documents and making eLyXer work with them. Any document sample you send will be treated with the utmost confidentiality. +
      +
      +The author lingers around official LyX mailing lists and monitors for mentions of eLyXer. You can also join the low-volume mailing list, where announcements of new versions are always posted. Bugs can be reported at the Savannah page; features can be requested too. Feature requests that fit in will be added to the wish list. +
      +

      +Acknowledgments +

      +
      +This little project is my little contribution back to the wonderful LyX community, for all these years of fruitful use. +
      +
      +Thanks to Stevan White for encouraging me to publish the tool. Thanks also to John D. Cook, rikal, Bradley M. Bell, Markus Kuhn, Jens Nöckel, Günter Milde and LyX developers Georg Baum, Uwe Stöhr and Jürgen Spitzmüller for their wonderful lists of TeX commands and Unicode equivalents; to FileFormat.info for their complete tables of Unicode characters. More thanks go to Christian Ridderström for helping me out right at the start; to Ignacio García for relentless encouragement; to Abdelrazak Younes, Pavel Sanda, Günter Milde, Olivier Ripoll, José Matos, Iain Mac Donald, Uwe Stöhr for their interesting suggestions. Thanks to Uwe Stöhr, Hans Bezemer, Sara Teinturier, Vladimir Ermakov for their translations. Packagers Sven Hoexter (for Debian) and Uwe Stöhr (on Windows) have helped with their work to make it easy to try it out. Olivier Ripoll, Geremy Condra, Simon South, Jack Desert, John Boik, Yan Wong, Jose Ramón Álvarez Sánchez, Günter Milde, Pascal Francq, Marco R. Gazzetta have provided quite interesting patches. Davide P. Cervone has been extremely helpful and responsive about jsMath and MathJax integration, while Paul Hunter has also gone beyond the call of duty with his help integrating MathToWeb (which unfortunately has not been fruitful yet, due to my lack of skill and certainly not to his lack of interest). +
      +
      +Thanks to Nikos Alexandris, Joachim Kreimer-de Fries (Osnabryg), Richard Talley, Wolfgang Keller, Murray Eisenberg, Robert Orr, a Linux guy in Singapore, Anders Ekberg, Pavel Sanda, Steve Hastings, Sven Hoexter, Xie Chao, Uwe Stöhr, Jürgen Spitzmüller, Olivier Ripoll, Konrad Hofbauer, Eduardo Grosclaude, Ken, Jens Nöckel, Dr Eberhard W Lisse, William Crocker, Sara Teinturier, Hans Bezemer, Jack Desert, Hartmut Haase, Rainer Dorsch, Wolfgang Engelmann, Rodrigo Benenson, Stefano Franchi, Steve Litt, Paul Johnson, Yan Wong, Yaron Goland, Francis Girard, Rene de Zwart, Jose Ramón Álvarez Sánchez, Günter Milde, Axel Jacobs, Tiago Pedro Alves-Ferreira, Hoy Loper, Bob Alvarez, Tommaso Cucinotta for their testing and bug reporting. +
      +
      +A silent “thank you” goes to all those who downloaded the tool and silently tested it to their satisfaction (or were not bugged enough to write about it). Thanks to those who have criticized the tool for making eLyXer improve every day, if only to prove you wrong. And finally thanks to all those who have helped and yet I am now forgetting about them, for not hating me for it. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/lyx.css elyxer-1.2.5/forks/pages-elyxer/lyx.css --- elyxer-1.2.3/forks/pages-elyxer/lyx.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/lyx.css 2013-03-10 11:34:08.000000000 +0000 @@ -0,0 +1,1060 @@ +/* +* eLyXer -- convert LyX source files to HTML output. +* +* Copyright (C) 2009-2010 Alex Fernández +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see http://www.gnu.org/licenses/. +*/ +/* --end-- +* Global CSS file for LyX documents. +*/ + +body { + font: 90% sans-serif; + background: #f9f9f9; + color: black; + margin: 0; + padding: 0; +} + +#globalWrapper { + margin: 10px 5%; + padding: 20px; + background: #ffffff; + line-height: 1.5em; +} + +/* Basic styles */ +a { + text-decoration: none; + background: none; +} +a:link { + color: #0030c0; +} +a:visited { + color: #603090; +} +a:active { + color: #ffa000; +} +a:hover { + text-decoration: underline; +} +h1 { + margin-top: 1em; + line-height: 1.5em; +} +h1.Part { + text-align: center; +} +h1.Part- { + text-align: center; +} +sup { + font-size: 0.75em; + line-height: 0.5em; + vertical-align: text-top; +} +sub { + font-size: 0.75em; + line-height: 0.5em; + vertical-align: text-bottom; +} +div.Standard { + margin: 1em 0; +} +div.Unindented { + margin: 0; +} +div.Indented { + text-indent: 30pt; + margin: 0; +} +div.Indented * { + text-indent: 0pt; +} +p.dir { + float: right; +} +p.printindex { + font-size: 0.90em; +} +a.printindex { + color: black; +} +table { + display: inline-table; + text-align: center; + border-collapse: collapse; + margin-top: 1em; + margin-bottom: 1em; +} +tr.header { + border-bottom: thin solid #c0c0c0; + background: #ffffff; + font-weight: bold; +} +td { + padding: 1ex; + border: thin solid #f0f0f0; +} +td div.Standard { + margin: 0ex; + padding: 0ex; +} +div.caption div.Standard, div.table div.Standard { + margin: 0ex; + padding: 0ex; +} +td.numeric { + text-align: right; +} +td.empty { + text-align: center; +} +div.right { + text-align: right; +} +div.center { + text-align: center; + margin-left: auto; + margin-right: auto; +} +p.biblio { +} +div.Paragraph, div.Paragraph- { + font-weight: bold; + font-size: 103%; +} +span.versalitas, span.noun { + font-variant: small-caps; +} +span.sans { + font-family: sans-serif; +} +span.code { + font-family: monospace; +} +div.Plain { + display: inline; + width: auto; +} +h2 { + line-height: 1.4em; +} +span.Description-entry { + font-weight: bold; +} +span.List-entry { + display: inline-block; + width: 25%; + vertical-align: text-top; +} +span.List-contents { + display: inline-block; + width: 75%; + vertical-align: text-top; +} +div.Space { + display: none; +} +span.appendix { + display: none; +} +h1.biblio { +} +span.greyedout { + color: #808080; +} +div.Description, div.List, li { + margin: 1em 0; +} +li.nested { + list-style-type: none; +} +span.Info { + background: #f0f0f0; + border: thin solid #c0c0c0; +} +pre { + padding: 0em; + margin: 0em; + width: auto; + font-family: monospace; + line-height: 1.5em; +} +pre.LyX-Code { + margin: 0.5em 3em; +} +a.Label { + text-decoration: none; + color: #000000; +} +span.phantom { + color: #ffffff; +} +a.biblioentry { + color: black; +} +span.menuitem { + font-size: 105%; +} +span.normal { + font-style: normal; +} +div.PlainVisible { + width: auto; +} +div.indexgroup { + margin-left: 2em; +} +span.strong { + font-weight: bold; +} + +/* Figures and Tables */ +img.embedded { + width: 100%; + _width: auto; +} +div.float { + margin-top: 1ex; + margin-bottom: 1ex; + text-align: center; +} +span.float { + margin-top: 1ex; + margin-bottom: 1ex; + text-align: center; +} +div.figure { + display: inline-block; + text-align: left; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.table { + display: inline-block; + text-align: left; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.algorithm { + display: inline-block; + text-align: left; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.caption { + text-align: center; + font-family: sans-serif; + margin-left: auto; + margin-right: auto; + padding: 0.5ex; +} +img.figure { + width: 100%; + _width: auto; +} +div.multifigure { + padding: 1ex; + width: 100%; +} +div.multitable { + display: inline-block; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.multialgorithm { + display: inline-block; + padding: 1ex; + margin-left: auto; + margin-right: auto; + border: thin solid #c0c0c0; +} +div.wrap-l, div.wrap-o, div.wrap-i { + margin: 2ex; + float: left; +} +div.wrap-r { + margin: 2ex; + float: right; +} +div.listing { + display: inline-block; + text-align: left; + margin-left: auto; + margin-right: auto; + padding: 0.5ex; + border: thin solid #c0c0c0; +} +span.number-left { + float: left; + background: #f0f0f0; + width: 3em; + text-align: right; + margin-right: 1em; +} +span.number-right { + float: right; + background: #f0f0f0; + width: 3em; + text-align: right; + margin-left: 1em; +} + +/* Header */ +h1.title { + text-align: center; +} +h2.author { + text-align: center; +} +h2.Date { + text-align: center; +} +div.abstract { + margin: 1em 3em; + text-align: left; + font-size: 0.95em; +} +p.abstract-message { + text-align: center; + font-weight: bold; +} +div.tocheader { + margin: 1em 0; + font-size: large; +} +a.toc { + color: black; +} +div.tocindent { + padding: 0 0 0 2em; +} +div.toc { + margin: 0.5em 0; + font-size: 0.95em; +} +div.fulltoc { + padding: 1em; +} +div.warning { + font-size: 120%; + color:#cc0000; +} +div.Institute { + text-align: center; +} +/* +* Extras: colors, footnotes, boxes, spaces... +*/ + +/* Raw colors */ +span.red { + color: #c00000; +} +span.blue { + color: #0000c0; +} +span.green { + color: #00c000; +} +span.magenta { + color: #c000c0; +} +span.cyan { + color: #00c0c0; +} +span.yellow { + color: #c0c000; +} +span.white { + color: #ffffff; +} + +/* Footnotes */ +span.SupFootMarker { + color: #0030c0; + font-size: 0.75em; + line-height: 0.5em; + vertical-align: text-top; +} +span.AlignFootMarker { + color: #0030c0; +} +div.EndFoot { + margin: 0.2ex; + background: #ffffff; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.MarginFoot { + float: right; + clear: right; + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + width: 30%; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.HoverFoot { + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.FootOuter .HoverFoot { + display: none; + position: absolute; +} +span.FootOuter:hover .HoverFoot { + display: inline; + float: none; +} +span.Marginal { + float: right; + clear: right; + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + width: 30%; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.Note { + display: none; +} + +/* Boxes */ +div.framed { + outline-style: solid; +} +div.frameless { +} +div.Frameless { +} +div.Boxed { + outline-width: thin; + outline-style: solid; +} +div.Framed { + outline-width: thin; + outline-style: solid; + line-height: 200%; +} +div.Doublebox { + outline-style: double; +} +div.Shadowbox { + outline-style: outset; +} +div.Shaded { + outline-style: inset; +} +div.ovalbox { + outline-style: groove; +} +div.Ovalbox { + outline-style: ridge; +} +hr.line { + display: inline-block; +} + +/* Spaces */ +span.hspace { + display: inline-block; +} +span.vspace { + display: inline-block; + vertical-align: text-top; +} +span.hfill { + display: inline-block; + margin-left: auto; + margin-right: auto; + min-width: 20mm; + background: #fff0f0; +} +div.defskip { + display: block; + height: 1em; +} +div.smallskip { + display: block; + height: 0.5em; +} +div.medskip { + display: block; + height: 1em; +} +div.bigskip { + display: block; + height: 2em; +} +div.vfill { + display: block; + height: 30em; +} + +/* Sizes */ +span.scriptstyle { + font-size: 0.75em; +} +span.scriptscriptstyle { + font-size: 0.60em; +} + +/* Chunks */ +div.chunk { + width: auto; +} +span.chunkleft span.chunkright { + font-style: normal; +} +span.chunkdecl { + font-style: italic; + padding: 0em 2em; +} +span.chunkref { + font-style: italic; +} + +/* Split Part Navigation */ +div.splitheader { + margin: 0em; + padding: 0.1em; + text-align: center; + background: #f9f9f9; + overflow: auto; +} +span.next { + float: right; + width: 30%; + text-align: right; +} +span.up { + display: inline-block; + width: 30%; + text-align: center; +} +span.prev { + float: left; + width: 30%; + text-align: left; +} +hr.footer { + margin-top: 2em; +} +div.footer { + font-size: 0.90em; + margin: 1em 0; +} + +/* Change Tracking */ +span.inserted { + color: #0000ff; +} +span.deleted { + color: #ff0000; + text-decoration: line-through; +} + +/* Google Charts */ +img.chart { + vertical-align: middle; +} +/* --end-- +* CSS file for LaTeX formulas. +*/ + +/* Formulas */ +.formula { + text-align: center; + font-family: "DejaVu Serif", serif; + margin: 1.2em 0; +} +span.formula { + white-space: nowrap; +} +div.formula { + padding: 0.5ex; + margin-left: auto; + margin-right: auto; +} + +/* Basic features */ +a.eqnumber { + display: inline-block; + float: right; + clear: right; + font-weight: bold; +} +span.unknown { + color: #800000; +} +span.ignored, span.arraydef { + display: none; +} +.formula i { + letter-spacing: 0.1ex; +} + +/* Alignment */ +.align-left, .align-l { + text-align: left; +} +.align-right, .align-r { + text-align: right; +} +.align-center, .align-c { + text-align: center; +} + +/* Structures */ +span.overline, span.bar { + text-decoration: overline; +} +.fraction, .fullfraction { + display: inline-block; + vertical-align: middle; + text-align: center; +} +.fraction .fraction { + font-size: 80%; + line-height: 100%; +} +span.numerator { + display: block; +} +span.denominator { + display: block; + padding: 0ex; + border-top: thin solid; +} +sup.numerator, sup.unit { + font-size: 70%; + vertical-align: 80%; +} +sub.denominator, sub.unit { + font-size: 70%; + vertical-align: -20%; +} +span.sqrt { + display: inline-block; + vertical-align: middle; + padding: 0.1ex; +} +sup.root { + font-size: 70%; + position: relative; + left: 1.4ex; +} +span.radical { + display: inline-block; + padding: 0ex; + font-size: 150%; + vertical-align: top; +} +span.root { + display: inline-block; + border-top: thin solid; + padding: 0ex; + vertical-align: middle; +} +span.symbol { + font-size: 125%; +} +span.bigsymbol { + font-size: 150%; +} +span.largesymbol { + font-size: 175%; +} +span.hugesymbol { + font-size: 200%; +} +span.scripts { + display: inline-table; + vertical-align: middle; +} +.script { + display: table-row; + text-align: left; + line-height: 150%; +} +span.limits { + display: inline-table; + vertical-align: middle; +} +.limit { + display: table-row; + line-height: 95%; +} +sup.limit, sub.limit { + line-height: 150%; +} +span.symbolover { + display: inline-block; + text-align: center; + position: relative; + float: right; + right: 100%; + bottom: 0.5em; + width: 0px; +} +span.withsymbol { + display: inline-block; +} +span.symbolunder { + display: inline-block; + text-align: center; + position: relative; + float: right; + right: 80%; + top: 0.3em; + width: 0px; +} + +/* Environments */ +span.array, span.bracketcases, span.binomial, span.environment { + display: inline-table; + text-align: center; + border-collapse: collapse; + margin: 0em; + vertical-align: middle; +} +span.arrayrow, span.binomrow { + display: table-row; + padding: 0ex; + border: 0ex; +} +span.arraycell, span.bracket, span.case, span.binomcell, span.environmentcell { + display: table-cell; + padding: 0ex 0.2ex; + line-height: 99%; + border: 0ex; +} +/* +* CSS file for LaTeX formulas, extra stuff: +* binomials, vertical braces, stackrel, fonts and colors. +*/ + +/* Inline binomials */ +span.binom { + display: inline-block; + vertical-align: middle; + text-align: center; + font-size: 80%; +} +span.binomstack { + display: block; + padding: 0em; +} + +/* Over- and underbraces */ +span.overbrace { + border-top: 2pt solid; +} +span.underbrace { + border-bottom: 2pt solid; +} + +/* Stackrel */ +span.stackrel { + display: inline-block; + text-align: center; +} +span.upstackrel { + display: block; + padding: 0em; + font-size: 80%; + line-height: 64%; + position: relative; + top: 0.15em; + +} +span.downstackrel { + display: block; + vertical-align: bottom; + padding: 0em; +} + +/* Fonts */ +span.mathsf, span.textsf { + font-style: normal; + font-family: sans-serif; +} +span.mathrm, span.textrm { + font-style: normal; + font-family: serif; +} +span.text, span.textnormal { + font-style: normal; +} +span.textipa { + color: #008080; +} +span.fraktur { + font-family: "Lucida Blackletter", eufm10, blackletter; +} +span.blackboard { + font-family: Blackboard, msbm10, serif; +} +span.scriptfont { + font-family: "Monotype Corsiva", "Apple Chancery", "URW Chancery L", cursive; + font-style: italic; +} + +/* Colors */ +span.colorbox { + display: inline-block; + padding: 5px; +} +span.fbox { + display: inline-block; + border: thin solid black; + padding: 2px; +} +span.boxed, span.framebox { + display: inline-block; + border: thin solid black; + padding: 5px; +} + +/* +* Obsolete definitions, kept for backwards compatibility. +*/ + +/* Footnotes */ +span.FootMarker { + color: #0030c0; + font-size: 0.75em; + line-height: 0.5em; + vertical-align: text-top; +} +span.Foot { + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.FootOuter .Foot { + display: none; + position: absolute; +} +span.FootOuter:hover .Foot { + display: inline; + float: none; +} + +/* Dotted box */ +span.dotted { + border-top: thin dotted; +} + +/* Obsolete aligned structures */ +span.numerator-l { + display: block; + text-align: left; +} +span.numerator-r { + display: block; + text-align: right; +} +span.numeratorl { + display: block; + text-align: left; +} +span.numeratorr { + display: block; + text-align: right; +} +span.framebox- { + display: inline-block; + border: thin solid black; + text-align: center; + padding: 5px; +} +span.framebox-l { + display: inline-block; + border: thin solid black; + text-align: left; + padding: 5px; +} +span.framebox-r { + display: inline-block; + border: thin solid black; + text-align: right; + padding: 5px; +} +td.formula-l { + text-align: left; + padding: 0.2ex; + border: 0ex; +} +td.formula-c { + text-align: center; + padding: 0.2ex; + border: 0ex; +} +td.formula-r { + text-align: right; + padding: 0.2ex; + border: 0ex; +} + +/* Obsolete limits */ +sub.bigsymbol { + display: table-row; + text-align: left; + line-height: 150%; +} +sup.bigsymbol { + display: table-row; + text-align: left; + line-height: 150%; +} + +/* Obsolete cases */ +table.cases { + display: inline-block; + text-align: center; + border-collapse: collapse; + margin: 0.2em; + border-left: thin solid; + vertical-align: middle; +} +table.cases tr td { + padding-left: 1ex; + padding-right: 1em; +} + +/* Obsolete binomials */ +span.fullbinom { + display: inline-block; + vertical-align: middle; + text-align: center; +} +span.upbinom { + display: block; + padding: 0em; +} +span.downbinom { + display: block; + padding: 0em; +} + +/* Obsolete environments */ +table.formula { + display: inline-block; + text-align: center; + border-collapse: collapse; + margin: 0em; + vertical-align: middle; +} +td.formula { + padding: 0.2ex; + border: 0ex; +} +table.environment { + display: inline-block; + text-align: right; + margin: 0; + vertical-align: middle; +} +table.environment tr td { + padding: 0 1em; +} +/* +* CSS section for print. +*/ +@media print { +body { + font: 90% serif; + background: #ffffff; + color: black; + margin: 0; + padding: 0; +} +#globalWrapper { + width: 100%; + margin: 0px; + padding: 0px; + background: #ffffff; + line-height: 1.5em; +} +span.FootOuter .Foot { + display: block; + position: relative; + float: right; + clear: right; + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + width: 30%; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +span.FootOuter .HoverFoot { + display: block; + position: relative; + float: right; + clear: right; + margin: 0.2ex; + border: thin solid #c0c0c0; + background: #ffffff; + width: 30%; + padding: 0.5ex; + font-size: small; + font-weight: normal; + line-height: 1.5em; + text-align: left; +} +a:visited { + color: #0030c0; +} +/* end of print CSS */ +} diff -Nru elyxer-1.2.3/forks/pages-elyxer/math-googlecharts.html elyxer-1.2.5/forks/pages-elyxer/math-googlecharts.html --- elyxer-1.2.3/forks/pages-elyxer/math-googlecharts.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/math-googlecharts.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,407 @@ + + + + + + + + +eLyxer Math Showcase (Google Charts edition) + + +
      +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: \phi, \pi, \Xi. eLyXer offers a complete set in both upper case: \Gamma\ldots\Omega and lower case: \alpha\ldots\omega. Also the AMS italicized upper case: \varGamma\ldots\varOmega. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: \exists\partial\nabla\geq. It can also render a few more: \propto\times. You also get all symbols from Markus Kuhn's list: \bigodot\amalg. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows: \leftarrow\rightarrow, or geometrical shapes: \circ, \square. eLyXer offers limited support for them. You might also want to use financial symbols in formulae: \yen\euro\$. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: x=3. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: \frac{4}{18}\mathrm{em} for medium mathematical spaces versus \frac{1}{2}\mathrm{en}, where 1\mathrm{em}=2\mathrm{en}. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box,
      +
+\raisebox{2mm}{raised}over\raisebox{-2mm}{lowered}\textrm{and back}. +
      +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + \raisebox{5mm}{}B^{V}. +
      +
      +There are other spacing commands: \hspace: a\hspace{4mm}b, protected space: a\ b, and (at “block level”) \vspace: a\vspace{1cm}b. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, \alpha x+\alpha y=\alpha(x+y), with the exception of upright capital Greek letters, G\ne\Gamma. +
      +
      +Function names should be upright: \sin(2\pi),\log(x),\tan\delta. +
      +
      +Mathematical fonts used in equations include \mathrm{Roman} (\mathrm), \mathsf{Sans\: Serif} (\mathsf), \mathtt{Typewriter} (\mathtt), \mathbf{Bold} (\mathbf), \mathscr{SCRIPT} (\mathscr), \mathcal{CALLIGRAPHIC} (\mathcal), \mathbb{BLACKBOARD\: BOLD} (\mathbb), and \mathfrak{Fraktur} (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: \mathscr{F}, \mathbb{F}, \mathfrak{F}. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: 5\:\textrm{to}\:10, via boxes like \mbox (prevents line breaks): 6\mbox{ is more than }5, or the AMSmath \text macro (scales like math symbols) \text{base}_{\text{sub}}^{\text{super}}. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: \mbox{\textbf{\textsf{\textbf{\textit{sfbfit}}}}, \textipa{tipa}}. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, \unit{km}, with magnitude, \unit[57]{km}, with fractional unit, \unitfrac[200]{km}{h}, or with a fraction before the units, \unit[\nicefrac{3}{2}]{km}, \unit[\frac{7}{16}]{s}. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like ()
      +(1) \begin{equation}
+y=x\label{eq:first}\end{equation} +
      + And also like (↓).
      +(2) \begin{equation}
+x=3\label{eq:second}\end{equation} +
      + Some equations can be numbered even if they don’t have a label. +
      +
      +
      +(3) \begin{equation}
+x=2y\end{equation} +
      + Notice that equation () comes after (). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction:
      +
+\frac{1}{2}. +
      +Inlined: \frac{2}{3}. +
      +
      +A big recursive fraction:
      +
+\frac{1}{\left(1+\left(\frac{1}{1+\left(\frac{1}{1+2x}\lyxlock\right)}\lyxlock\right)\right)}\lyxlock +
      + +
      +
      +A nice fraction: \nicefrac{5}{6}. A non-diminishing fraction containing alignments:
      +
+\cfrac{1}{1+\left(\cfrac[l]{1}{1+x}\times\cfrac[r]{1}{1+x}\right)}. +
      + +
      +
      +A similar concept is a binomial coefficient: \binom{A+1}{B}. It can be prettily presented:
      +
+\dbinom{A}{B+1}. +
      + +
      +
      +A symbol can be stacked over another using \stackrel: x\stackrel{R}{\rightarrow}y. Anything can be stacked:
      +
+d\stackrel{x>3}{\lim}x,\quad\stackrel{\mathrm{head}}{\mathrm{heels}}. +
      + +
      +

      +4.2 Limits +

      +
      +\lim_{x\rightarrow\infty}f(x) should appear as x\rightarrow\infty in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol:
      +
+\lim_{x\rightarrow\infty}\lyxlock f(x). +
      + +
      +
      +Limits are also used in sums and integrals:
      +
+\sum_{i=1}^{\infty}x,\;\int_{0}^{\infty}f(x)\,\mathrm{d}x +
      +where the sum’s limits should appear below (i=1) and above (\infty) the \sum. The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the \int. Limits are shown to the right in inline formulae: \sum_{i=1}^{\infty}x and \intop_{i=1}^{\infty}x. +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros:
      +
+\lim\nolimits _{x\rightarrow\infty}\lyxlock f(x),\;\sum\nolimits _{i=1}^{\infty}x,\;\int\limits _{0}^{\infty}f(x)\,\mathrm{d}x +
      + +
      +

      +4.3 Roots +

      +
      +A square root: \sqrt{3}. A more complex root in a fraction:
      +
+\frac{1}{\left(1+\sqrt{2}\left(\frac{1}{1+\sqrt{2}}\lyxlock\right)+\sqrt{\frac{1}{2}}\right)}\lyxlock. +
      + +
      +
      +eLyXer can also do higher-order roots: \sqrt[3]{x+y}. A devilish case mixing everything we have seen so far:
      +
+\frac{\sqrt[\nicefrac{7}{8}]{\frac{8}{4}x}+\sum_{i=1}^{\infty}x}{\sqrt[s+5]{\frac{(78x+45y)\times\sqrt{\Omega}}{\sin(x+1)}+\unit[38]{km}}}\lyxlock. +
      + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array \left[\begin{array}{cc}
+a & b\\
+c & d\end{array}\right] is always shown in the same line. In display mode, the array is shown on its own line:
      +
+\left[\begin{array}{lc}
+12 & 2\\
+3 & 4\times y^{x}\end{array}\right] +
      +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: \left(\begin{array}{cc}
+a & b\\
+c & d\end{array}\right) \left[\begin{array}{cc}
+a & b\\
+c & d\end{array}\right] \left\{ \begin{array}{cc}
+a & b\\
+c & d\end{array}\right\} \left\langle \begin{array}{cc}
+a & b\\
+c & d\end{array}\right\rangle \left|\begin{array}{cc}
+a & b\\
+c & d\end{array}\right|which might also differ on right and left \left(\begin{array}{cc}
+a & b\\
+c & d\end{array}\right) or use the empty opening \left\{ \begin{array}{cc}
+a & b\\
+c & d\end{array}\right. or closing: \left.\begin{array}{cc}
+a & b\\
+c & d\end{array}\right|. There are also fixed-size big brackets, e.g. \bigl\langle f\bigr\rangle. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      +
      +
+y=\begin{cases}
+x & i=0,\\
+x+1 & i<3\end{cases} +
      + +
      +
      +Cases may have more than two rows: +
      +
      +
      +
+f(x)=\begin{cases}
+0 & x<0,\\
+\infty & x=0\\
+0 & x>0\end{cases} +
      + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      +\underbrace{a-b}=\overbrace{b+c+d+e}. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: \stupidroot 12. They can accept default parameters. Again, useful in formulae: \defaultroot. +
      +
      +Other definitions from the preamble can be used: \preambleroot{3}{4}. +
      +
      +Definitions on the fly are also possible: \newcommand{\ontheflyroot}[2]{\sqrt[#1]{#2}}\ontheflyroot{7}{8}, and used with different values: \ontheflyroot{a}{b}. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/math-html.html elyxer-1.2.5/forks/pages-elyxer/math-html.html --- elyxer-1.2.3/forks/pages-elyxer/math-html.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/math-html.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,712 @@ + + + + + + + +eLyxer Math Showcase (HTML edition) + + +
      +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: φ, π, Ξ. eLyXer offers a complete set in both upper case: Γ…Ω and lower case: αω. Also the AMS italicized upper case: ΓΩ. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: ∃∂∇ ≥ . It can also render a few more:  ∝  × . You also get all symbols from Markus Kuhn's list: ⊙∐. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows:  ←  → , or geometrical shapes: , . eLyXer offers limited support for them. You might also want to use financial symbols in formulae: ¥€$. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: x = 3. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: (4)/(18) em for medium mathematical spaces versus (1)/(2) en, where 1 em = 2 en. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box,
      +raisedoverloweredand back. +
      +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + BV. +
      +
      +There are other spacing commands: \hspace: a b, protected space: a b, and (at “block level”) \vspace: a b. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, αx + αy = α(x + y), with the exception of upright capital Greek letters, G ≠ Γ. +
      +
      +Function names should be upright: sin(2π), log(x), tanδ. +
      +
      +Mathematical fonts used in equations include Roman (\mathrm), Sans Serif (\mathsf), Typewriter (\mathtt), Bold (\mathbf), SCRIPT (\mathscr), CALLIGRAPHIC (\mathcal), BLACKBOARD BOLD (\mathbb), and Fraktur (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: , 𝔽, 𝔉. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: 5  to 10, via boxes like \mbox (prevents line breaks): 6  is more than 5, or the AMSmath \text macro (scales like math symbols) basesubsuper. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: sfbfit, tipa. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, km, with magnitude, 57 km, with fractional unit, 200 kmh, or with a fraction before the units, 32 km, (7)/(16) s. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like (1↓)
      +(1) y = x +
      + And also like (2↓).
      +(2) x = 3 +
      + Some equations can be numbered even if they don’t have a label. +
      +
      +
      +(3) x = 2y +
      + Notice that equation (2↑) comes after (1↑). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction:
      +(1)/(2). +
      +Inlined: (2)/(3). +
      +
      +A big recursive fraction:
      +(1)/((1 + ((1)/(1 + ((1)/(1 + 2x)))))) +
      + +
      +
      +A nice fraction: 56. A non-diminishing fraction containing alignments:
      +(1)/(1 + ((1)/(1 + x) × (1)/(1 + x))). +
      + +
      +
      +A similar concept is a binomial coefficient: (A + 1B). It can be prettily presented:
      +(AB + 1). +
      + +
      +
      +A symbol can be stacked over another using \stackrel: xR → y. Anything can be stacked:
      +dx > 3limx,  headheels. +
      + +
      +

      +4.2 Limits +

      +
      +limx → ∞f(x) should appear as x → ∞ in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol:
      +limx → ∞f(x). +
      + +
      +
      +Limits are also used in sums and integrals:
      +i = 1x,  0f(x) dx +
      +where the sum’s limits should appear below (i = 1) and above () the . The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the . Limits are shown to the right in inline formulae: i = 1x and i = 1x. +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros:
      +limx → ∞f(x),  i = 1x,  0f(x) dx +
      + +
      +

      +4.3 Roots +

      +
      +A square root: (3). A more complex root in a fraction:
      +(1)/((1 + (2)((1)/(1 + (2))) + ((1)/(2)))). +
      + +
      +
      +eLyXer can also do higher-order roots: 3(x + y). A devilish case mixing everything we have seen so far:
      +(78((8)/(4)x) + i = 1x)/(s + 5(((78x + 45y) × (Ω))/(sin(x + 1)) + 38 km)). +
      + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array [ + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +] is always shown in the same line. In display mode, the array is shown on its own line:
      +[ + +12 + + +2 + + + + + +  + + +  + + + + + +3 + + +4 × yx + + + +] +
      +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: ( + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +) [ + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +] { + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +} + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + | + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|which might also differ on right and left ( + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +) or use the empty opening { + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or closing: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|. There are also fixed-size big brackets, e.g. f. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      +
      +y =  + + +x  + + +i = 0,   + + + + + +   + + +   + + + + + +x + 1  + + +i < 3  + + + + + + +
      + +
      +
      +Cases may have more than two rows: +
      +
      +
      +f(x) =  + + +0  + + +x < 0,   + + + + + +   + + +   + + + + + +∞  + + +x = 0  + + + + + +   + + +   + + + + + +0  + + +x > 0  + + + + + + +
      + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      +a − b = b + c + d + e. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: 1(2). They can accept default parameters. Again, useful in formulae: 4(5). +
      +
      +Other definitions from the preamble can be used: 3(4). +
      +
      +Definitions on the fly are also possible: 7(8), and used with different values: a(b). +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/math-iso885915.html elyxer-1.2.5/forks/pages-elyxer/math-iso885915.html --- elyxer-1.2.3/forks/pages-elyxer/math-iso885915.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/math-iso885915.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,713 @@ + + + + + + + + +eLyxer Math Showcase (ISO-8859-15 edition) + + +
      +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: φ, π, Ξ. eLyXer offers a complete set in both upper case: Γ…Ω and lower case: αω. Also the AMS italicized upper case: ΓΩ. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: ∃∂∇ ≥ . It can also render a few more:  ∝  × . You also get all symbols from Markus Kuhn's list: ⊙∐. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows:  ←  → , or geometrical shapes: , . eLyXer offers limited support for them. You might also want to use financial symbols in formulae: ¥€$. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: x = 3. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: (4)/(18) em for medium mathematical spaces versus (1)/(2) en, where 1 em = 2 en. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box,
      +raisedoverloweredand back. +
      +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + BV. +
      +
      +There are other spacing commands: \hspace: a b, protected space: a b, and (at “block level”) \vspace: a b. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, αx + αy = α(x + y), with the exception of upright capital Greek letters, G ≠ Γ. +
      +
      +Function names should be upright: sin(2π), log(x), tanδ. +
      +
      +Mathematical fonts used in equations include Roman (\mathrm), Sans Serif (\mathsf), Typewriter (\mathtt), Bold (\mathbf), SCRIPT (\mathscr), CALLIGRAPHIC (\mathcal), BLACKBOARD BOLD (\mathbb), and Fraktur (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: , 𝔽, 𝔉. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: 5  to 10, via boxes like \mbox (prevents line breaks): 6  is more than 5, or the AMSmath \text macro (scales like math symbols) basesupersub. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: sfbfit, tipa. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, km, with magnitude, 57 km, with fractional unit, 200 kmh, or with a fraction before the units, 32 km, (7)/(16) s. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like (1↓)
      +(1) y = x +
      + And also like (2↓).
      +(2) x = 3 +
      + Some equations can be numbered even if they don’t have a label. +
      +
      +
      +(3) x = 2y +
      + Notice that equation (2↑) comes after (1↑). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction:
      +(1)/(2). +
      +Inlined: (2)/(3). +
      +
      +A big recursive fraction:
      +(1)/(1 + (1)/(1 + (1)/(1 + 2x))) +
      + +
      +
      +A nice fraction: 56. A non-diminishing fraction containing alignments:
      +(1)/(1 + (1)/(1 + x) × (1)/(1 + x)). +
      + +
      +
      +A similar concept is a binomial coefficient: (A + 1B). It can be prettily presented:
      +AB + 1. +
      + +
      +
      +A symbol can be stacked over another using \stackrel: xR → y. Anything can be stacked:
      +dx > 3limx,  headheels. +
      + +
      +

      +4.2 Limits +

      +
      +limx → ∞f(x) should appear as x → ∞ in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol:
      +limx → ∞f(x). +
      + +
      +
      +Limits are also used in sums and integrals:
      +i = 1x,  0f(x) dx +
      +where the sum’s limits should appear below (i = 1) and above () the . The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the . Limits are shown to the right in inline formulae: i = 1x and i = 1x. +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros:
      +limx → ∞f(x),  i = 1x,  0f(x) dx +
      + +
      +

      +4.3 Roots +

      +
      +A square root: (3). A more complex root in a fraction:
      +(1)/(1 + (2)(1)/(1 + (2)) + ((1)/(2))). +
      + +
      +
      +eLyXer can also do higher-order roots: 3(x + y). A devilish case mixing everything we have seen so far:
      +(78((8)/(4)x) + i = 1x)/(s + 5(((78x + 45y) × (Ω))/(sin(x + 1)) + 38 km)). +
      + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + is always shown in the same line. In display mode, the array is shown on its own line:
      + + +12 + + +2 + + + + + +  + + +  + + + + + +3 + + +4 × yx + + + + +
      +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + ||| + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||which might also differ on right and left + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or use the empty opening + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or closing: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||. There are also fixed-size big brackets, e.g. f. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      +
      +y =  + + +x  + + +i = 0,   + + + + + +   + + +   + + + + + +x + 1  + + +i < 3  + + + + + + +
      + +
      +
      +Cases may have more than two rows: +
      +
      +
      +f(x) =  + + +0  + + +x < 0,   + + + + + +   + + +   + + + + + +∞  + + +x = 0  + + + + + +   + + +   + + + + + +0  + + +x > 0  + + + + + + +
      + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      +a − b = b + c + d + e. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: 1(2). They can accept default parameters. Again, useful in formulae: 4(5). +
      +
      +Other definitions from the preamble can be used: 3(4). +
      +
      +Definitions on the fly are also possible: 7(8), and used with different values: a(b). +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/math-mathjax-local.html elyxer-1.2.5/forks/pages-elyxer/math-mathjax-local.html --- elyxer-1.2.3/forks/pages-elyxer/math-mathjax-local.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/math-mathjax-local.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,696 @@ + + + + + + + + +eLyxer Math Showcase (MathJax local edition) + + + +
      + + +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: +, +, +. eLyXer offers a complete set in both upper case: + and lower case: +. Also the AMS italicized upper case: +. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: +. It can also render a few more: +. You also get all symbols from Markus Kuhn's list: +. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows: +, or geometrical shapes: +, +. eLyXer offers limited support for them. You might also want to use financial symbols in formulae: +. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: +. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: + for medium mathematical spaces versus +, where +. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box, + + + +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + +. +
      +
      +There are other spacing commands: \hspace: +, protected space: +, and (at “block level”) \vspace: +. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, +, with the exception of upright capital Greek letters, +. +
      +
      +Function names should be upright: +. +
      +
      +Mathematical fonts used in equations include + (\mathrm), + (\mathsf), + (\mathtt), + (\mathbf), + (\mathscr), + (\mathcal), + (\mathbb), and + (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: +, +, +. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: +, via boxes like \mbox (prevents line breaks): +, or the AMSmath \text macro (scales like math symbols) +. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: +. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, +, with magnitude, +, with fractional unit, +, or with a fraction before the units, +, +. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like () + + + + And also like (↓). + + + + Some equations can be numbered even if they don’t have a label. +
      +
      + + + + + Notice that equation () comes after (). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction: + + + +Inlined: + +
      +
      +A big recursive fraction: + + + + +
      +
      +A nice fraction: +. A non-diminishing fraction containing alignments: + + + + +
      +
      +A similar concept is a binomial coefficient: + It can be prettily presented: + + + + +
      +
      +A symbol can be stacked over another using \stackrel: +. Anything can be stacked: + + + + +
      +

      +4.2 Limits +

      +
      + + should appear as + in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol: + + + + +
      +
      +Limits are also used in sums and integrals: + + + +where the sum’s limits should appear below ( +) and above ( +) the +. The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the +. Limits are shown to the right in inline formulae: + and + +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros: + + + + +
      +

      +4.3 Roots +

      +
      +A square root: + A more complex root in a fraction: + + + + +
      +
      +eLyXer can also do higher-order roots: +. A devilish case mixing everything we have seen so far: + + + + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + is always shown in the same line. In display mode, the array is shown on its own line: + + + +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + + + + +which might also differ on right and left + or use the empty opening + or closing: +. There are also fixed-size big brackets, e.g. +. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      + + + + + +
      +
      +Cases may have more than two rows: +
      +
      + + + + + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      + +. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: +. They can accept default parameters. Again, useful in formulae: +. +
      +
      +Other definitions from the preamble can be used: +. +
      +
      +Definitions on the fly are also possible: +, and used with different values: +. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/math-mathjax.html elyxer-1.2.5/forks/pages-elyxer/math-mathjax.html --- elyxer-1.2.3/forks/pages-elyxer/math-mathjax.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/math-mathjax.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,691 @@ + + + + + + + + +eLyxer Math Showcase (MathJax remote edition) + + + +
      + + +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: +, +, +. eLyXer offers a complete set in both upper case: + and lower case: +. Also the AMS italicized upper case: +. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: +. It can also render a few more: +. You also get all symbols from Markus Kuhn's list: +. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows: +, or geometrical shapes: +, +. eLyXer offers limited support for them. You might also want to use financial symbols in formulae: +. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: +. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: + for medium mathematical spaces versus +, where +. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box, + + + +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + +. +
      +
      +There are other spacing commands: \hspace: +, protected space: +, and (at “block level”) \vspace: +. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, +, with the exception of upright capital Greek letters, +. +
      +
      +Function names should be upright: +. +
      +
      +Mathematical fonts used in equations include + (\mathrm), + (\mathsf), + (\mathtt), + (\mathbf), + (\mathscr), + (\mathcal), + (\mathbb), and + (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: +, +, +. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: +, via boxes like \mbox (prevents line breaks): +, or the AMSmath \text macro (scales like math symbols) +. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: +. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, +, with magnitude, +, with fractional unit, +, or with a fraction before the units, +, +. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like () + + + + And also like (↓). + + + + Some equations can be numbered even if they don’t have a label. +
      +
      + + + + + Notice that equation () comes after (). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction: + + + +Inlined: + +
      +
      +A big recursive fraction: + + + + +
      +
      +A nice fraction: +. A non-diminishing fraction containing alignments: + + + + +
      +
      +A similar concept is a binomial coefficient: + It can be prettily presented: + + + + +
      +
      +A symbol can be stacked over another using \stackrel: +. Anything can be stacked: + + + + +
      +

      +4.2 Limits +

      +
      + + should appear as + in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol: + + + + +
      +
      +Limits are also used in sums and integrals: + + + +where the sum’s limits should appear below ( +) and above ( +) the +. The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the +. Limits are shown to the right in inline formulae: + and + +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros: + + + + +
      +

      +4.3 Roots +

      +
      +A square root: + A more complex root in a fraction: + + + + +
      +
      +eLyXer can also do higher-order roots: +. A devilish case mixing everything we have seen so far: + + + + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + is always shown in the same line. In display mode, the array is shown on its own line: + + + +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + + + + +which might also differ on right and left + or use the empty opening + or closing: +. There are also fixed-size big brackets, e.g. +. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      + + + + + +
      +
      +Cases may have more than two rows: +
      +
      + + + + + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      + +. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: +. They can accept default parameters. Again, useful in formulae: +. +
      +
      +Other definitions from the preamble can be used: +. +
      +
      +Definitions on the fly are also possible: +, and used with different values: +. +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/math-unicode.html elyxer-1.2.5/forks/pages-elyxer/math-unicode.html --- elyxer-1.2.3/forks/pages-elyxer/math-unicode.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/math-unicode.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,713 @@ + + + + + + + + +eLyxer Math Showcase (Unicode edition) + + +
      +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: φ, π, Ξ. eLyXer offers a complete set in both upper case: Γ…Ω and lower case: αω. Also the AMS italicized upper case: ΓΩ. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: ∃∂∇ ≥ . It can also render a few more:  ∝  × . You also get all symbols from Markus Kuhn's list: ⊙∐. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows:  ←  → , or geometrical shapes: , . eLyXer offers limited support for them. You might also want to use financial symbols in formulae: ¥€$. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: x = 3. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: (4)/(18) em for medium mathematical spaces versus (1)/(2) en, where 1 em = 2 en. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box,
      +raisedoverloweredand back. +
      +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + BV. +
      +
      +There are other spacing commands: \hspace: a b, protected space: a b, and (at “block level”) \vspace: a b. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, αx + αy = α(x + y), with the exception of upright capital Greek letters, G ≠ Γ. +
      +
      +Function names should be upright: sin(2π), log(x), tanδ. +
      +
      +Mathematical fonts used in equations include Roman (\mathrm), Sans Serif (\mathsf), Typewriter (\mathtt), Bold (\mathbf), SCRIPT (\mathscr), CALLIGRAPHIC (\mathcal), BLACKBOARD BOLD (\mathbb), and Fraktur (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: , 𝔽, 𝔉. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: 5  to 10, via boxes like \mbox (prevents line breaks): 6  is more than 5, or the AMSmath \text macro (scales like math symbols) basesupersub. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: sfbfit, tipa. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, km, with magnitude, 57 km, with fractional unit, 200 kmh, or with a fraction before the units, 32 km, (7)/(16) s. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like (1↓)
      +(1) y = x +
      + And also like (2↓).
      +(2) x = 3 +
      + Some equations can be numbered even if they don’t have a label. +
      +
      +
      +(3) x = 2y +
      + Notice that equation (2↑) comes after (1↑). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction:
      +(1)/(2). +
      +Inlined: (2)/(3). +
      +
      +A big recursive fraction:
      +(1)/(1 + (1)/(1 + (1)/(1 + 2x))) +
      + +
      +
      +A nice fraction: 56. A non-diminishing fraction containing alignments:
      +(1)/(1 + (1)/(1 + x) × (1)/(1 + x)). +
      + +
      +
      +A similar concept is a binomial coefficient: (A + 1B). It can be prettily presented:
      +AB + 1. +
      + +
      +
      +A symbol can be stacked over another using \stackrel: xR → y. Anything can be stacked:
      +dx > 3limx,  headheels. +
      + +
      +

      +4.2 Limits +

      +
      +limx → ∞f(x) should appear as x → ∞ in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol:
      +limx → ∞f(x). +
      + +
      +
      +Limits are also used in sums and integrals:
      +i = 1x,  0f(x) dx +
      +where the sum’s limits should appear below (i = 1) and above () the . The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the . Limits are shown to the right in inline formulae: i = 1x and i = 1x. +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros:
      +limx → ∞f(x),  i = 1x,  0f(x) dx +
      + +
      +

      +4.3 Roots +

      +
      +A square root: (3). A more complex root in a fraction:
      +(1)/(1 + (2)(1)/(1 + (2)) + ((1)/(2))). +
      + +
      +
      +eLyXer can also do higher-order roots: 3(x + y). A devilish case mixing everything we have seen so far:
      +(78((8)/(4)x) + i = 1x)/(s + 5(((78x + 45y) × (Ω))/(sin(x + 1)) + 38 km)). +
      + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + is always shown in the same line. In display mode, the array is shown on its own line:
      + + +12 + + +2 + + + + + +  + + +  + + + + + +3 + + +4 × yx + + + + +
      +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + ||| + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||which might also differ on right and left + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or use the empty opening + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or closing: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||. There are also fixed-size big brackets, e.g. f. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      +
      +y =  + + +x  + + +i = 0,   + + + + + +   + + +   + + + + + +x + 1  + + +i < 3  + + + + + + +
      + +
      +
      +Cases may have more than two rows: +
      +
      +
      +f(x) =  + + +0  + + +x < 0,   + + + + + +   + + +   + + + + + +∞  + + +x = 0  + + + + + +   + + +   + + + + + +0  + + +x > 0  + + + + + + +
      + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      +a − b = b + c + d + e. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: 1(2). They can accept default parameters. Again, useful in formulae: 4(5). +
      +
      +Other definitions from the preamble can be used: 3(4). +
      +
      +Definitions on the fly are also possible: 7(8), and used with different values: a(b). +
      + + + +
      + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/math.css elyxer-1.2.5/forks/pages-elyxer/math.css --- elyxer-1.2.3/forks/pages-elyxer/math.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/math.css 2013-03-10 11:34:08.000000000 +0000 @@ -0,0 +1,274 @@ +/* +* math2html: convert LaTeX equations to HTML output. +* +* Copyright (C) 2009,2010 Alex Fernández +* +* Released under the terms of the `2-Clause BSD license'_, in short: +* Copying and distribution of this file, with or without modification, +* are permitted in any medium without royalty provided the copyright +* notice and this notice are preserved. +* This file is offered as-is, without any warranty. +* +* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause +* +* Based on eLyXer: convert LyX source files to HTML output. +* http://elyxer.nongnu.org/ +*/ +/* --end-- +* CSS file for LaTeX formulas. +*/ + +/* Formulas */ +.formula { + text-align: center; + font-family: "DejaVu Serif", serif; + margin: 1.2em 0; +} +span.formula { + white-space: nowrap; +} +div.formula { + padding: 0.5ex; + margin-left: auto; + margin-right: auto; +} + +/* Basic features */ +a.eqnumber { + display: inline-block; + float: right; + clear: right; + font-weight: bold; +} +span.unknown { + color: #800000; +} +span.ignored, span.arraydef { + display: none; +} +.formula i { + letter-spacing: 0.1ex; +} + +/* Alignment */ +.align-left, .align-l { + text-align: left; +} +.align-right, .align-r { + text-align: right; +} +.align-center, .align-c { + text-align: center; +} + +/* Structures */ +span.overline, span.bar { + text-decoration: overline; +} +.fraction, .fullfraction { + display: inline-block; + vertical-align: middle; + text-align: center; +} +.fraction .fraction { + font-size: 80%; + line-height: 100%; +} +span.numerator { + display: block; +} +span.denominator { + display: block; + padding: 0ex; + border-top: thin solid; +} +sup.numerator, sup.unit { + font-size: 70%; + vertical-align: 80%; +} +sub.denominator, sub.unit { + font-size: 70%; + vertical-align: -20%; +} +span.sqrt { + display: inline-block; + vertical-align: middle; + padding: 0.1ex; +} +sup.root { + font-size: 70%; + position: relative; + left: 1.4ex; +} +span.radical { + display: inline-block; + padding: 0ex; + font-size: 150%; + vertical-align: top; +} +span.root { + display: inline-block; + border-top: thin solid; + padding: 0ex; + vertical-align: middle; +} +span.symbol { + font-size: 125%; +} +span.bigsymbol { + font-size: 150%; +} +span.largesymbol { + font-size: 175%; +} +span.hugesymbol { + font-size: 200%; +} +span.scripts { + display: inline-table; + vertical-align: middle; +} +.script { + display: table-row; + text-align: left; + line-height: 150%; +} +span.limits { + display: inline-table; + vertical-align: middle; +} +.limit { + display: table-row; + line-height: 95%; +} +sup.limit, sub.limit { + line-height: 150%; +} +span.symbolover { + display: inline-block; + text-align: center; + position: relative; + float: right; + right: 100%; + bottom: 0.5em; + width: 0px; +} +span.withsymbol { + display: inline-block; +} +span.symbolunder { + display: inline-block; + text-align: center; + position: relative; + float: right; + right: 80%; + top: 0.3em; + width: 0px; +} + +/* Environments */ +span.array, span.bracketcases, span.binomial, span.environment { + display: inline-table; + text-align: center; + border-collapse: collapse; + margin: 0em; + vertical-align: middle; +} +span.arrayrow, span.binomrow { + display: table-row; + padding: 0ex; + border: 0ex; +} +span.arraycell, span.bracket, span.case, span.binomcell, span.environmentcell { + display: table-cell; + padding: 0ex 0.2ex; + line-height: 99%; + border: 0ex; +} +/* +* CSS file for LaTeX formulas, extra stuff: +* binomials, vertical braces, stackrel, fonts and colors. +*/ + +/* Inline binomials */ +span.binom { + display: inline-block; + vertical-align: middle; + text-align: center; + font-size: 80%; +} +span.binomstack { + display: block; + padding: 0em; +} + +/* Over- and underbraces */ +span.overbrace { + border-top: 2pt solid; +} +span.underbrace { + border-bottom: 2pt solid; +} + +/* Stackrel */ +span.stackrel { + display: inline-block; + text-align: center; +} +span.upstackrel { + display: block; + padding: 0em; + font-size: 80%; + line-height: 64%; + position: relative; + top: 0.15em; + +} +span.downstackrel { + display: block; + vertical-align: bottom; + padding: 0em; +} + +/* Fonts */ +span.mathsf, span.textsf { + font-style: normal; + font-family: sans-serif; +} +span.mathrm, span.textrm { + font-style: normal; + font-family: serif; +} +span.text, span.textnormal { + font-style: normal; +} +span.textipa { + color: #008080; +} +span.fraktur { + font-family: "Lucida Blackletter", eufm10, blackletter; +} +span.blackboard { + font-family: Blackboard, msbm10, serif; +} +span.scriptfont { + font-family: "Monotype Corsiva", "Apple Chancery", "URW Chancery L", cursive; + font-style: italic; +} + +/* Colors */ +span.colorbox { + display: inline-block; + padding: 5px; +} +span.fbox { + display: inline-block; + border: thin solid black; + padding: 2px; +} +span.boxed, span.framebox { + display: inline-block; + border: thin solid black; + padding: 5px; +} + diff -Nru elyxer-1.2.3/forks/pages-elyxer/math.html elyxer-1.2.5/forks/pages-elyxer/math.html --- elyxer-1.2.3/forks/pages-elyxer/math.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/math.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,713 @@ + + + + + + + + +eLyxer Math Showcase (non-Unicode edition) + + +
      +

      +figure elyxer.png +eLyXer Math Showcase +

      +

      +Alex Fernández (elyxer@gmail.com) +

      + +

      +1 Introduction +

      +
      +This document is intended as a showcase of the mathematical abilities of eLyXer; for more information be sure to visit the main page. +
      +

      +1.1 Versions +

      +
      +There are several versions of this page: +
      + +
      +All of them are generated from the same .lyx source file; they should help you decide which rendering options suit you best. +
      +
      +Also available online is the eLyXer translation of the latest LyX’s detailed Math manual, which contains a lot more examples of LyX maths. +
      +

      +2 Typography +

      +
      +Math formulae use a lot of different symbols and fonts. +
      +

      +2.1 Greek Symbols +

      +
      +Greek symbols are very important in equations: φ, π, Ξ. eLyXer offers a complete set in both upper case: Γ…Ω and lower case: αω. Also the AMS italicized upper case: ΓΩ. +
      +

      +2.2 Math Symbols +

      +
      +eLyXer supports the whole set of math symbols in John D. Cook's list: ∃∂∇ ≥ . It can also render a few more:  ∝  × . You also get all symbols from Markus Kuhn's list: ⊙∐. +
      +

      +2.3 Other Symbols +

      +
      +There are other symbols like arrows:  ←  → , or geometrical shapes: , . eLyXer offers limited support for them. You might also want to use financial symbols in formulae: ¥€$. +
      +

      +2.4 Spacing +

      +
      +Equations look good when items are properly separated. The main separation is the Medium Mathematical Space: x = 3. +Note: if you are viewing the non-Unicode version math.html of this page then you are in fact seeing midspaces, which are very similar but not exactly the same: (4)/(18) em for medium mathematical spaces versus (1)/(2) en, where 1 em = 2 en. Try out the Unicode version math-unicode.html — and viceversa. You can check out what version this page is in the page title. + + +
      +
      +The command \raisebox is useful to, surprisingly, raise a little box,
      +raisedoverloweredand back. +
      +Like \mbox, it puts its content in a text box. It can also be used just for spacing:
      + BV. +
      +
      +There are other spacing commands: \hspace: a b, protected space: a b, and (at “block level”) \vspace: a b. +
      +
      +There should be 1 cm of vertical space above this paragraph. +
      +

      +2.5 Fonts +

      +
      +By default, letters denote variables and are taken from the \mathnormal font, which is italic, αx + αy = α(x + y), with the exception of upright capital Greek letters, G ≠ Γ. +
      +
      +Function names should be upright: sin(2π), log(x), tanδ. +
      +
      +Mathematical fonts used in equations include Roman (\mathrm), Sans Serif (\mathsf), Typewriter (\mathtt), Bold (\mathbf), SCRIPT (\mathscr), CALLIGRAPHIC (\mathcal), BLACKBOARD BOLD (\mathbb), and Fraktur (\mathfrak). For the latter, some single characters are translated to their Unicode equivalents: , 𝔽, 𝔉. +
      +
      +Regular text in a formula can be achieved via text font commands like \textrm: 5  to 10, via boxes like \mbox (prevents line breaks): 6  is more than 5, or the AMSmath \text macro (scales like math symbols) basesupersub. The content of an mbox is processed in LaTeX text mode. This allows text font commands, e.g. a switch to sans-serif-bold-italic, or the phonetic alphabet: sfbfit, tipa. +
      +
      +Units should be written upright, either with \mathrm or with macros from the units package, e.g. as simple unit, km, with magnitude, 57 km, with fractional unit, 200 kmh, or with a fraction before the units, 32 km, (7)/(16) s. +
      +

      +3 Numeration +

      +
      +Equations can be numbered, like (1↓)
      +(1) y = x +
      + And also like (2↓).
      +(2) x = 3 +
      + Some equations can be numbered even if they don’t have a label. +
      +
      +
      +(3) x = 2y +
      + Notice that equation (2↑) comes after (1↑). +
      +

      +4 Simple Structures +

      +
      +Let’s now see a few of the simpler structures that eLyXer can output. +
      +

      +4.1 Fractions +

      +
      +A simple fraction:
      +(1)/(2). +
      +Inlined: (2)/(3). +
      +
      +A big recursive fraction:
      +(1)/(1 + (1)/(1 + (1)/(1 + 2x))) +
      + +
      +
      +A nice fraction: 56. A non-diminishing fraction containing alignments:
      +(1)/(1 + (1)/(1 + x) × (1)/(1 + x)). +
      + +
      +
      +A similar concept is a binomial coefficient: (A + 1B). It can be prettily presented:
      +AB + 1. +
      + +
      +
      +A symbol can be stacked over another using \stackrel: xR → y. Anything can be stacked:
      +dx > 3limx,  headheels. +
      + +
      +

      +4.2 Limits +

      +
      +limx → ∞f(x) should appear as x → ∞ in italics, and «lim» in plain style. In display mode, a limit must appear below the main symbol:
      +limx → ∞f(x). +
      + +
      +
      +Limits are also used in sums and integrals:
      +i = 1x,  0f(x) dx +
      +where the sum’s limits should appear below (i = 1) and above () the . The placement of the integral limits depends on the document class: LaTeX standard classes place them right to the . Limits are shown to the right in inline formulae: i = 1x and i = 1x. +
      +
      +The placing of limits can be configured with the \limits and \nolimits macros:
      +limx → ∞f(x),  i = 1x,  0f(x) dx +
      + +
      +

      +4.3 Roots +

      +
      +A square root: (3). A more complex root in a fraction:
      +(1)/(1 + (2)(1)/(1 + (2)) + ((1)/(2))). +
      + +
      +
      +eLyXer can also do higher-order roots: 3(x + y). A devilish case mixing everything we have seen so far:
      +(78((8)/(4)x) + i = 1x)/(s + 5(((78x + 45y) × (Ω))/(sin(x + 1)) + 38 km)). +
      + +
      +

      +5 Complex Structures +

      +
      +In this section we will explore arrays and related constructs. +
      +

      +5.1 Arrays +

      +
      +An inline array + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + is always shown in the same line. In display mode, the array is shown on its own line:
      + + +12 + + +2 + + + + + +  + + +  + + + + + +3 + + +4 × yx + + + + +
      +Apart from that the appearance should be the same. +
      +

      +5.2 Brackets +

      +
      +Arrays are separated by variable-size brackets: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + ||| + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||which might also differ on right and left + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or use the empty opening + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + + or closing: + +a + + +b + + + + + +  + + +  + + + + + +c + + +d + + + +|||. There are also fixed-size big brackets, e.g. f. +
      +

      +5.3 Cases +

      +
      +Used to switch between several values. +
      +
      +
      +y =  + + +x  + + +i = 0,   + + + + + +   + + +   + + + + + +x + 1  + + +i < 3  + + + + + + +
      + +
      +
      +Cases may have more than two rows: +
      +
      +
      +f(x) =  + + +0  + + +x < 0,   + + + + + +   + + +   + + + + + +∞  + + +x = 0  + + + + + +   + + +   + + + + + +0  + + +x > 0  + + + + + + +
      + +
      +

      +5.4 Braces +

      +
      +Values can be underbraced or overbraced. +
      +
      +a − b = b + c + d + e. +
      +

      +6 Macros +

      +
      +Now it’s time for user-defined commands (sometimes called “macros”). +
      +
      +Definitions can be added as macros. Then they can be used in formulae: 1(2). They can accept default parameters. Again, useful in formulae: 4(5). +
      +
      +Other definitions from the preamble can be used: 3(4). +
      +
      +Definitions on the fly are also possible: 7(8), and used with different values: a(b). +
      + + + +
      + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/pages-elyxer/parse tree.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/pages-elyxer/parse tree.png differ diff -Nru elyxer-1.2.3/forks/pages-elyxer/parse tree.svg elyxer-1.2.5/forks/pages-elyxer/parse tree.svg --- elyxer-1.2.3/forks/pages-elyxer/parse tree.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/parse tree.svg 2013-03-10 11:34:20.000000000 +0000 @@ -0,0 +1,437 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + \begin_inset + + + + Graphics + + + + Text + + + + LatexCommand + + + + Inset + + + + label + + + + ref + + + + + + + + Image + + + + Reference + + + + Label + + + + + + + + + InsetText + + + + Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/forks/pages-elyxer/pipeline.png and /tmp/d8f5cQswGk/elyxer-1.2.5/forks/pages-elyxer/pipeline.png differ diff -Nru elyxer-1.2.3/forks/pages-elyxer/pipeline.svg elyxer-1.2.5/forks/pages-elyxer/pipeline.svg --- elyxer-1.2.3/forks/pages-elyxer/pipeline.svg 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/pipeline.svg 2013-03-10 11:34:20.000000000 +0000 @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + elyxer + + + + LyX file + + + + singleHTML file + + + + + + multipleHTML files + + + + + elyxer --splitpart + + + + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/toc.css elyxer-1.2.5/forks/pages-elyxer/toc.css --- elyxer-1.2.3/forks/pages-elyxer/toc.css 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/toc.css 2013-03-10 11:34:08.000000000 +0000 @@ -0,0 +1,40 @@ +/* +* Styles for lyx TOC. +*/ +body { + font: small sans-serif; + background: #f9f9f9; + color: black; + margin: 0; + padding: 0; +} + +#globalWrapper { + font-size: 115%; + margin: 5px 20px 5px 20px; + padding: 0px; + background: #ffffff; + line-height: 1.5em; + overflow: hidden; +} +a { + text-decoration: none; + color: #0030c0; + background: none; +} +a:visited { + color: #603090; +} +a:active { + color: #ffa000; +} +a:hover { + text-decoration: underline; +} +div.tocindent { + padding: 0 0 0 2em; +} +div.toc { + margin: 0.5em 0; + font-size: 0.95em; +} diff -Nru elyxer-1.2.3/forks/pages-elyxer/userguide-frameset.html elyxer-1.2.5/forks/pages-elyxer/userguide-frameset.html --- elyxer-1.2.3/forks/pages-elyxer/userguide-frameset.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/userguide-frameset.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,13 @@ + + + + eLyXer User Guide + + + + + + + + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/userguide-toc.html elyxer-1.2.5/forks/pages-elyxer/userguide-toc.html --- elyxer-1.2.3/forks/pages-elyxer/userguide-toc.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/userguide-toc.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,180 @@ + + + + + + + + +Converted document + + +
      +
      + + + + + + + +
      + + + + +
      + + diff -Nru elyxer-1.2.3/forks/pages-elyxer/userguide.html elyxer-1.2.5/forks/pages-elyxer/userguide.html --- elyxer-1.2.3/forks/pages-elyxer/userguide.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/forks/pages-elyxer/userguide.html 2013-03-10 11:33:59.000000000 +0000 @@ -0,0 +1,1776 @@ + + + + + + + + +eLyXer User Guide + + +
      +

      +figure elyxer.png +eLyXer User Guide +

      +

      +Alex Fernández (elyxer@gmail.com) +

      +
      +
      +Table of Contents +
      +
      + + + + + + + +
      + + +
      +

      +1 The Basics +

      +
      +elixir, n: a substance believed to cure all ills[1]. +
      +
      +eLyXer (pronounced elixir) is a LyX to HTML converter. While there are a ton of such projects all over the web, eLyXer has a clear focus on flexibility and elegant output. +
      +
      +eLyXer (including this guide and all accompanying materials) is licensed under the GPL version 3 or, at your option, any later version. See the LICENSE file for details. +
      +
      +Please visit the main page to find out about the latest developments. +
      +

      +1.1 System Requirements +

      +
      +eLyXer requires Python 2.4.x, and should work with versions up to 2.6.y; it will convert documents generated by LyX 1.5.x to 2.0. It has been tested on the most common operating systems: on Mac OS X, Linux and Windows, with and without CygWin. +
      +
      +Resource usage should be quite frugal; eLyXer runs quite happily on my 1st-gen Asus Eee, with its puny Celeron@570MHz and 512 MB of RAM. It should also be fast — the Eee can convert ~200 pages of LyX text in just over 50 seconds. Performance is fairly linear: 200 pages take 10 ×  as long as 20, so there are no scalability problems. Memory usage stays low even when processing large documents, and conversion can be done on the fly (with --lowmem) for even lower memory requirements. +
      +

      +1.2 Installation +

      +
      +This section looks at how to install eLyXer on your system, assuming that Python 2.4 to 2.6 is already there. +
      +

      +Download eLyXer +

      +
      +First you will need to fetch the official distribution file from the download area. Now, there is more than one way to install eLyXe, but all of them start by uncompressing the distributed file to a suitable directory. Just write at the command prompt: +
      +
      +$ tar -xzf elyxer-[version].tar.gz
      +
      +
      +Or for the .zip version: +
      +
      +$ unzip elyxer-[version].zip
      +
      +
      +A directory called elyxer should appear, where the main executable file elyxer.py resides. +
      +

      +Using the Installer +

      +
      +An installer is provided in the root directory, called install.py; it is the recommended way to install eLyXer. To run it just type in a console as root: +
      +
      +# python install.py
      +
      +
      +On Windows you can type (as a regular user): +
      +
      +> python.exe install.py
      +
      +
      +In any case, the script will install eLyXer as a Python script. Now you can check if it was installed successfully: +
      +
      +$ elyxer.py --help
      +
      +
      +A brief help text and the list of command line options should appear. +
      +
      +The installer will also copy existing translation files to your hard drive so that they can be used from within eLyXer for internationalization. +
      +

      +Prepackaged Versions +

      +
      +The easiest way to install eLyXer is if someone has prepackaged it for your system. Some Linux distributions include eLyXer: Debian squeeze and Ubuntu Lucid. Installation is done using apt-get or aptitude, for Debian as root: +
      +
      +# apt-get install elyxer
      +
      +
      +or, for Ubuntu: +
      +
      +$ sudo aptitude install elyxer
      +
      +
      +For both Debian and Ubuntu eLyXer needs to be run as "elyxer": +
      +
      +$ elyxer --help
      +
      +
      +On Windows, the alternate LyX installer includes eLyXer in the default installation. See 1.6↓ for LyX integration. +
      +

      +Manual Installation +

      +
      +If the installer did not work for you, you can manually install it as a module. On Linux go to the elyxer directory and type, as root: +
      +
      +# python setup.py install
      +
      +
      +On Windows just type: +
      +
      +> python.exe setup.py install
      +
      +
      +On Mac OS X you can use sudo to get the necessary permissions: +
      +
      +% sudo python setup.py install
      +
      +
      +Now you can run eLyXer as a Python script: +
      +
      +$ elyxer.py --help
      +
      +
      +The list of command line options should appear. You can also manually copy the file elyxer.py to a directory found in the execution path (for instance, /usr/bin on Linux or c:\windows\system32 on Windows). +
      +

      +1.3 Test Drive +

      +
      +Now you may want to try to convert the user guide: +
      +
      +$ elyxer.py --css lyx.css --title "eLyXer User Guide" docs/userguide.lyx docs/userguide2.html
      +
      +
      +It should generate a working web page identical to the one distributed: +
      +
      +$ diff docs/userguide.html docs/userguide2.html
      +
      +
      +The typical output will contain just the changed lines, which in this case should be only the header with the file creation date. An example is shown on listing 1↓. +
      +
      +
      +
      +
      +7c7
      +< <meta name="create-date" content="2009-09-11"/>
      +---
      +> <meta name="create-date" content="2009-09-12"/> +
      +
      +Algorithm 1 Example of diff output for functionally identical HTML files. +
      + +
      + +
      + +
      +
      +If nothing else appears (i.e. both files are functionally equal) then everything is working fine. If you have bash installed, to test that everything really works fine you can just run the included tests: +
      +
      +$ ./run-tests
      +
      +
      +It will run a number of test and check the results, so you can see if everything is well. You also need to have installed the command-line tool diff to show differences between two files. +
      +

      +1.4 Usage +

      +
      +eLyXer is a standalone command line tool. It can be invoked from the command line as: +
      +
      +$ elyxer.py [options] [source file] [destination file]
      +
      +
      +If the source file is omitted then STDIN is used; likewise, if no destination file is specified eLyXer will output to STDOUT. This allows its use in pipes and other flexible configurations. Some examples: +
      +
      +$ elyxer.py file.lyx file.html
      +
      +
      +converts file.lyx to file.html. Debug messages are shown. +
      +
      +$ cat file.lyx | elyxer.py > file.html
      +
      +
      +converts file.lyx to file.html, as before. This time debug messages are not shown. +
      +
      +$ elyxer.py file.lyx | grep "<blockquote>" | wc
      +
      +
      +counts all blockquote paragraphs. +
      +
      +$ elyxer.py file.lyx | wget --no-check-certificate --spider -nv -F -i -
      +
      +
      +checks all external links in a document recursively. (Local links will appear as unresolved, but they can be ignored.) +
      +

      +1.5 Image Processing +

      +
      +eLyXer does not convert images directly; it uses the ImageMagick package, in particular the convert tool, to create PNG versions of the images embedded in the original LyX documents, and then it inserts links to those PNG images in the resulting HTML pages. If ImageMagick is not installed eLyXer will show an error message and will not try to convert further images. +
      +
      +HTML pages, unlike PDF documents, do not contain images in the document file; rather they contain pointers to image locations on disk. (Fortunately, LyX documents do not contain images either.) eLyXer will generate pages that point to the same locations as the original images, when they are PNG images, or to the converted versions otherwise. Image types like Encapsulated PostScript cannot be used directly from within pages. +
      +
      +Image location is fragile. All images should be placed in the same location (and with the same structure) as the original document; and they should all be referenced relatively to the current document. During conversion from within LyX image locations can be lost, since LyX does not do in-place conversion; instead, LyX copies the original file to a temporary directory, converts the file and then copies everything back to a directory ending in .LyXconv. +
      +

      +1.6 LyX Integration +

      +
      +If you used the eLyXer installer LyX will automatically detect it after reconfiguration. Just make sure that you are running LyX 1.6.5 or later, and click on Tools ▷ Reconfigure. +
      +
      +LyX should be able to detect if eLyXer was installed as a script, or even if it has been installed from a Linux distribution. In any case you can verify that it has been recognized by LyX by opening Tools ▷ Preferences…, going to External formats ▷ Converters, and finding the converter for “LyX -> HTML”. If eLyXer is there, it worked! Now you can convert your documents using View ▷ HTML. Otherwise try to reinstall eLyXer from scratch and then reconfigure LyX. +
      +

      +Installing as a Package or as a Module +

      +
      +Versions of the eLyXer installer prior to 1.2.0 tried to install eLyXer as a module, so it could be run using "python -m elyxer". This option is deprecated since a module called elyxer would collide with a Python package of the same name, and there are plans to install eLyXer as a proper Python package in the future (probably in the 1.3.0 time frame). In the interim eLyXer is installed only as a script called elyxer.py. +
      +
      +LyX (starting with versions 2.0.0 and 1.6.9) has been patched to recognize only the script and disregard the module. +
      +

      +2 Advanced Use +

      +
      +There are some advanced uses for eLyXer if you want to extract the most of it. +
      +

      +2.1 Command Line Options +

      +
      +eLyXer supports a few command line options: +
      +
      +--help: Show command line help. +
      +
      +--quiet: Be quiet and do not output messages (except errors). This way you can avoid the comforting “Parsing line 1000” messages. When STDIN or STDOUT are used (e.g. in a pipeline) --quiet is always enabled. +
      +

      +Advanced Options +

      +
      +--debug: Show debug messages. They may help a developer understand your problem. +
      +
      +--version: Show version number and date. Use to check which version you are actually running. +
      +
      +--lyxformat: Return the highest LyX version that eLyXer understands. This parameter is provided to help with lyx2lyx integration, so that this tool knows if it must convert the file to a lower LyX format. +
      +

      +Options to Control HTML output +

      +
      +--title "title": Change the title of the generated web page. +
      +
      +--css "new.css": Change default CSS. See section 2.2↓: CSS. +
      +
      +--embedcss "file.css": Embed the styles in file.css into the resulting HTML document. See section 2.2↓: CSS. +
      +
      +--html: Generate HTML 4.0 (instead of XHTML). The resulting pages should be easier to import from certain word processors. See section 2.6↓: HTML code. +
      +
      +--unicode: Restore full Unicode output. Right now switches midspaces to medium mathematical spaces. See also section 2.6↓: HTML code. +
      +
      +--iso885915: Generate a document using ISO-8859-1 encoding. Again, see section 2.6↓: HTML code. +
      +
      +--nofooter: Omit the footer message “Document generated by eLyXer” (shown at the bottom). +
      +

      +Options to Control image output +

      +
      +--directory "images_dir": Look for images in the directory specified. +
      +
      +--destdirectory "dest_dir": Converted images will end up into this directory. +
      +
      +--imageformat ".extension": Force the format implied by the extension (e.g. ".jpg" for JPEG) for output images. Use --imageformat "copy" to make images be copied over instead of converted. +
      +
      +--converter "program":Use the given program to convert images. Right now the supported converters are: imagemagick (default), inkscape and lyx itself. With --converter inkscape eLyXer picks Inkscape as the image converter (Inkscape uses some non-standard extensions so it might be needed to convert SVG images to PNG); with --converter lyx the new LyX option lyx -C is used. You can also supply your own converter command line, using $input and $output as variables (note the single quotes): +
      +
      +$ elyxer.py --converter ’lyx -C $input $output’ [source file] [destination file]
      +
      +
      +--noconvert: Use all images in their original location and do not convert anything. Useful when using images which do not convert well, such as SVG files. +
      +

      +Options to Control footnote output +

      +
      +--numberfoot: Number all footnotes using numbers: “[1]”, instead of the default “[A]”. +
      +
      +--symbolfoot: mark footnotes with symbols (*, **, †, ‡…). +
      +
      +--hoverfoot: show footnotes as hovering text. This is the default position. +
      +
      +--marginfoot: show footnotes with numbers instead of letters. +
      +
      +--endfoot: show footnotes at the end of the page. +
      +
      +--supfoot: use superscript for footnote markers. This is the default style. +
      +
      +--alignfoot: use aligned text for footnote markers, instead of superscript. +
      +
      +--footnotes "options": specify several footnotes options at the same time, separated with commas. Available options are: "number", "hover", "margin", "end". See section 2.9↓: Footnotes. +
      +

      +Advanced Options to Control HTML output +

      +
      +--splitpart "depth": Split the resulting webpage at the given depth. See section 2.5↓: Segmenting Pages. +
      +
      +--tocfor "original.html": Generate just a table of contents with links to the original HTML file. See section 2.4↓: TOC. +
      +
      +--target "frame": Add a target attribute to every link in the generated HTML, making all links point to the provided frame. Again, see section 2.4↓: TOC. +
      +
      +--notoclabels: Omit “Chapter”, “Part” and similar labels from the TOC; just output part numbers (and separate using a period). For instance, a chapter that without this option is labeled “Chapter 2: Advanced Use” in the TOC would now become “2. Advanced Use”, as on the PDF. Option adapted from the wish list: 3.2↓. +
      +
      +--lowmem: Activate a low memory mode which does not keep the whole document in memory: conversion is done on the fly. Keep in mind that some features as the TOC will be missing from the generated document. +
      +
      +--numberfoot:Label footnotes using numbers, instead of letters. Useful when bibliographical references are not numbered and therefore cannot be confused with footnotes. +
      +
      +--raw: Generate an HTML page without header or footer. +
      +
      +--mathjax remote: Use the excellent JavaScript library MathJax remotely to pretty-print mathematical equations. See section 2.8↓. +
      +
      +--mathjax "URL": Use the excellent JavaScript library MathJax at the given URL (usually a local URL is used). See also section 2.8↓. +
      +
      +--googlecharts: Use Google Charts to generate images for every formula. Again, see 2.8↓. +
      +
      +--simplemath: Do not generate fancy math structures such as multi-line Unicode brackets or stacked limits. This option is automatically activated when --html is selected; once more see section 2.8↓. +
      +
      +--template "file": Use an HTML template. The raw converted document will be placed where <!--$content--> appears in the template. Available variables: <!--$content-->, <!--$title-->, <!--$author-->, <!--$encoding-->, <!--$css-->, <!--$navigation-->, <!--$year-->, <!--$date-->, <!--$datetime-->, <!--$version-->, <!--$script-->, <!--$mathjax-->. +
      +
      +--copyright: Include a copyright notice at the bottom. +
      +

      +Deprecated Options +

      +
      +--toc: Generate just a table of contents. Use --tocfor instead. +
      +
      +--toctarget "original.html": Generate a table of contents with links to the original HTML file. Use --tocfor instead. +
      +
      +--nocopy: No effect since the copyright notice is now optional, maintained for backwards compatibility. +
      +
      +When an option accepts an argument it can be added after a space as --target "frame", or with an equals sign as in --target="frame". The quotes are optional and can be useful if your arguments include e.g. spaces. +
      +

      +Adding Options In LyX +

      +
      +To add one of these options so that it is used from within LyX, you have to modify the converter line. To this effect open Tools ▷ Preferences…, go to External formats ▷ Converters, find the converter for “LyX -> HTML” and edit the converter line. It should read something like this: +
      +
      +elyxer.py --directory $$r $$i $$o
      +
      +
      +If you want to generate pure HTML instead of XHTML, change the line to: +
      +
      +elyxer.py --html --directory $$r $$i $$o
      +
      +
      +And so on. Figure 1 shows what to do to add the --html option: after editing the line and adding the new option, click on “Modify” and then “Save” or “Apply” the changes. +You should never remove the $$i $$o at the end, since it is what tells eLyXer where to find the input and output files. + + +
      +
      +
      +
      +
      +figure converters.png + +
      +
      +Figure 1 eLyXer converter in LyX 1.6.5. +
      + +
      + +
      + +
      +
      +LyX 1.6.5 supports a new “extra flag” line; however, at this moment it does not work with eLyXer. +
      +

      +2.2 CSS +

      +
      +HTML output, as generated, can fall short in certain situations. Some CSS wizardry can go a long way to customize eLyXer. +
      +
      +eLyXer tags most elements with the type so you can later modify them using a CSS. The default HTML header is similar to listing 2↓, so the default remote CSS file is used. +
      +
      +
      +
      +
      +<head>
      +[...]
      +<link rel="stylesheet" href="http://elyxer.nongnu.org/lyx.css" type="text/css" media="all"/>
      +<title>Your title here</title>
      +</head> +
      +
      +Algorithm 2 CSS link automatically added to HTML +
      + +
      + +
      + +
      +
      +This sample CSS file is published on nongnu.org and distributed along with the scripts, docs/lyx.css. (You may have found that your document shows minor changes in its appearance with time — this is the reason. The main author regularly publishes a new, updated version of lyx.css on nongnu.org, and all documents using it automatically appear with the changes. Backwards compatibility is maintained as much as possible.) +
      +
      +To give your document a customized appearance (or for pages to be accessible offline) you probably will want to use your own CSS file; to use it first copy it to the directory where your document resides (e.g. renaming it to custom.css), and customize as needed. Then run elyxer.py with the following option: +
      +
      +$ elyxer.py --css=custom.css document.lyx page.html
      +
      +
      +This will make the generated page.html use your custom.css file. The ‘=’ sign between the constant ‘--css’ and the name of the CSS file is optional. More than one --css option can be added if you want several CSS files to be used in the header. +
      +
      +Sometimes the styles in a CSS are needed in the HTML document (for offline viewing, or to distribute as stand-alone pages). For these uses there is the option --embedcss: the styles contained in the CSS file passed as an argument will be embedded in the resulting HTML document. For instance: +
      +
      +$ elyxer.py --embedcss custom.css document.lyx page.html
      +
      +
      +This command generates a document page.html where the styles in custom.css are embedded. The CSS to embed must be a file, not a remote URL. Listing 3↓ shows the resulting HTML header for a test CSS with just one style, div.Standard. Note that the remote CSS is still added by default; to avoid it just add an option with an empty CSS file, --css="". +
      +
      +
      +
      +
      +<head>
      +[...]
      +<head>
      +<link rel="stylesheet" href="http://elyxer.nongnu.org/lyx.css" type="text/css" media="all"/>
      +<style type="text/css">
      +<!--
      +/* Embedded CSS */
      +div.Standard {
      +  background: #909090;
      +}
      +-->
      +</style>
      +<title>Your title here</title>
      +</head> +
      +
      +Algorithm 3 CSS embedded into the HTML +
      + +
      + +
      + +
      +
      +As with the --css option, several --embedcss options can be added to embed more than one file. +
      +
      +The CSS file for eLyXer uses some CSS2 features for math structures (fractions, arrays). This makes the output incompatible with older browsers; it requires Microsoft Internet Explorer 7, Firefox 3, Safari 3 or Chrome 1. Check the Math Showcase to see if your browser can render eLyXer output correctly. +
      +

      +2.3 Title +

      +
      +By default the generated web pages have the title “Converted Document”. If a PDF title is found then it is used instead. The proper LyX title (a paragraph of type “Title” embedded in the text) will also be used if found. But when --lowmem is in use eLyXer does not try to get the proper title, since it may be found in the middle of the document or not be present at all; scanning for it would mean doing two passes, one to look for the title in all the document and another to output the web page, and --lowmem implies on-the-fly conversion to save memory. +
      +
      +You can change the title of the generated web page with the --title option: +
      +
      +$ elyxer.py --title "My Beautiful Document" document.lyx page.html
      +
      +

      +2.4 Table Of Contents +

      +
      +A table of contents (or TOC) can be generated for every converted LyX document. You can optionally also add a target frame to every link. The trick is to combine both options to generate a TOC that links to the original document on a different frame. For example, if the original page is called page.html and you generated it with this command: +
      +
      +$ elyxer.py document.lyx page.html
      +
      +
      +you can generate the TOC linking to this page, and at the same time point it to frame contents: +
      +
      +$ elyxer.py --tocfor page.html --target contents document.lyx page-toc.html
      +
      +
      +Then you can put it all together with a simple frameset generated manually. Just remember to place the original document in the frame called contents. +
      +
      +
      +
      +
      +<html>
      +  <frameset cols="30%,70%">
      +    <frame name="toc" src="page-toc.html" />
      +    <frame name="contents" src="page.html" />
      +  </frameset>
      +</html> +
      +
      +Algorithm 4 An example frameset for TOC navegation +
      + +
      + +
      + +
      +
      +TOC generation accepts the same options as normal document conversion. For example, if you follow these instructions literally you will notice that the TOC has very wide margins and looks a bit weird; that is because it is using the default CSS. A special CSS file for TOC files is provided in docs/toc.css, so better results should be obtained with the --css option: +
      +
      +$ elyxer.py --tocfor page.html --css docs/toc.css --target contents document.lyx page-toc.html
      +
      +
      +With a little bit of practice you will be able to generate useful (and nice looking) TOC files. You can see an example for the user guide (if you are not already looking at it). +
      +

      +2.5 Segmenting Pages +

      +
      +Quite often you don’t want a huge monolithic page, but a set of linked pages. To do so you can use the --splitpart option, specifying the level at which eLyXer should split pages. For instance: +
      +
      +$ elyxer.py --splitpart 1 document.lyx output.html
      +
      +
      +will split document.lyx into pages at level 1, using output.html as the root page. Each page will get a number that starts with output and ends with .html, with a suffix that depends on the page — output-2.html will correspond to the second split part. +
      +
      +The level corresponding to 1 depends on the document class: books will be split at chapters, but articles will get a section per page. And so on with lower levels. +
      +

      +2.6 HTML Code +

      +
      +The HTML code generated is technically XHTML Transitional, version 1.0 [2], using UTF-8 encoding. Some programs have (in this day and age) trouble importing XHTML, notably some popular word processors. To work around this problem and provide more flexible output in general you can output HTML 4.0: +
      +
      +$ elyxer.py --html document.lyx page-to-import.html
      +
      +
      +Again, technically the code generated is HTML 4.01 Transitional [3] using UTF-8 encoding. Both versions should pass the W3C tests [4]. If your particular web page doesn’t pass the tests, then it is a bug and it will be treated as such. +
      +
      +The --html option also activates the --simplemath option; see section 2.8↓: Math for details. +
      +

      +Character Encodings +

      +
      +For better browser compatibility, medium mathematical spaces are substituted in the output with midspaces — improving the output for some popular browsers. If you want your mathematical spaces back, just use the --unicode option: +
      +
      +$ elyxer.py --unicode document.lyx page-to-import.html
      +
      +
      +Check out the Math Showcase with Unicode to see the results. In the future other non-Unicode substitutions might be used. +
      +
      +In case you want to use the ISO-8859-15 encoding in your generated document, you can add the --iso885915 option: +
      +
      +$ elyxer.py --iso885915 document.lyx page.html
      +
      +
      +This will make eLyXer output a document with all non-ASCII characters encoded as &nbsp;, &#x2005; and so on. This encoding is similar to ISO-8859-1, also called Latin-1, but including the Euro sign. The Math Showcase (ISO-8859-15 edition) has been generated using this option. +
      +
      +Both encoding options can be combined with --html at will. +
      +

      +2.7 Internationalization +

      +
      +eLyXer is distributed along with a few translation files. They are automatically regenerated every time make is run, and reside in the folder po/. Internationalization is done using GNU gettext, so every locale is identified by a two-letter code (such as “en” for English and “es” for Spanish). There are two kinds of files: the text .po file (which can be found in po/my.po for locale “my”), and the binary .mo file (found in po/my/elyxer.po). +
      +
      +For internationalization to work properly, Linux distributors should take all binary .mo files and place them in the directory corresponding to locale files, which we will call $localedir. As the Python gettext page explains, this is distribution-dependent: for example on Debian $localedir is /usr/share/locale, so for locale “es” the correct route would be +
      +
      +/usr/share/locale/es/LC_MESSAGES/elyxer.mo
      +
      +
      +Windows distributors on the other hand should place files in %PYTHONHOME%\share\locale, for example for locale “es” on a machine where Python is in C:\python: +
      +
      +C:\python\share\locale\es\LC_MESSAGES\elyxer.mo
      +
      +
      +To generate a new translation file (we will use “my” as an example locale here, corresponding to Burmese): you need to have the GNU gettext package installed. Then go to the directory where elyxer.pot resides: +
      +
      +$ cd src/conf
      +
      +
      +and generate a .po file for your locale: +
      +
      +$ msginit --output-file=my.po --locale=my
      +
      +
      +Then move the file to the po/ directory: +
      +
      +$ mv my.po ../../po/
      +
      +
      +and start translating it to Burmese! Once you are done run make from the root directory: +
      +
      +$ ./make
      +
      +
      +and it will generate the file po/my/elyxer.mo. Finally, place this file in +
      +
      +$localedir/my/LC_MESSAGES/elyxer.mo
      +
      +
      +and you are done. +
      +

      +2.8 Math +

      +
      +Math equations are an important part of what takes LyX apart from other editors, since it supports the full LaTeX feature set — that is, about everything under the sun. Unfortunately, math support is hard to get right. Many developers are focusing on MathML, but at the time of this writing (Q2 2010) support on some common browsers is still missing. +
      +
      +eLyXer follows its usual minimalistic approach and doesn’t try to be everything to everybody — instead, it supports out of the box a set of usual constructs (fraction, square root) and tries to simulate others (binomial, overbrace). See the Math showcase for yourself and learn what eLyXer supports and what not. +
      +
      +For more sophisticated math equations there are a couple of advanced features. +
      +

      +MathJax +

      +
      +The first option is to use MathJax, which is as simple as using the option --mathjax: +
      +
      +$ elyxer.py --mathjax remote math.lyx math-mathjax-remote.html
      +
      +
      +The remote argument tells MathJax to access the MathJax library remotely on the MathJax CDN. (You should always comply with their terms of service.) See the Math showcase (MathJax remote edition) to check the results. +
      +
      +In case you need to go outside the terms of service, or you want the content to be accessible offline, you can always use a local copy of MathJax. Just use the URL of the repository as an argument to the --mathjax option: +
      +
      +$ elyxer.py --mathjax MathJax/ math.lyx math-mathjax-local.html
      +
      +
      +This way eLyXer uses the given URL (in the example MathJax/) to load MathJax from and set it up. Although some code needs to be hosted on the same site as the pages, MathJax uses a feature called web-fonts which can be downloaded from a public server; this is quite easier to host. See the Math showcase (MathJax edition) to see how MathJax fares with eLyXer. +
      +
      +Something to note is that MathJax is a JavaScript library; all rendering is done client-side by the user’s browser. This has quite a few advantages: +
      +
        +
      • +Math processing on the server is quite light; equations are basically surrounded by a special tag and left in TeX form. +
      • +
      • +For developers: integration of these libraries is very easy. It took just a few days to integrate both libraries with eLyXer. +
      • +
      • +MathJax is improving all the time thanks to the efforts of Davide P. Cervone and the rest of the developer team; eLyXer and its users reap the benefits readily. +
      • +
      • +The client browser already knows its abilities, and can choose the rendering method it considers to be the best. MathJax can even choose between MathML and HTML+CSS at page rendering time, showing MathML on fancier browsers and simpler HTML where it is not available. +
      • + +
      +
      +It also brings some disadvantages: +
      +
        +
      • +With the remote argument, JavaScript code resides at a remote server and your users will need online access to view the maths. +
      • +
      • +If MathJax is accessed locally you need to also host the code for MathJax. (Web fonts used in MathJax can at least be hosted elsewhere, so publishers do not need to also host the fonts package, but this hasn’t still been used in eLyXer.) +
      • +
      • +And of course it takes some time to render everything on the client, which can degrade the user experience on older machines. +
      • + +
      +
      +Publishers should carefully consider pros and cons before deciding what to use. +
      +

      +Google Charts +

      +
      +Google Charts is an online service which generates images that contain charts and other stuff; it can also generate TeX formulas. eLyXer can use it using the option --googlecharts: +
      +
      +$ elyxer.py --googlecharts math.lyx math-googlecharts.html
      +
      +
      +There are some limitations to Google Charts: no macros, formulas cannot exceed 200 characters, and the supported command set is limited (commands in text mode, for instance, are out of bounds). Also, generated images can be hard to align vertically — by default they are middle-aligned, but some small characters or superscripted formulas can look weird. But this option can be a quick&dirty way of showing math for older or unsupported browsers. +
      +

      +Brackets and Limits +

      +
      +Fancy math structures are generated by default: arrays and binomials are surrounded by multi-line Unicode brackets, limits in display mode are stacked above / below the symbol, and so on. When the option --simplemath is used eLyXer avoids such structures and just outputs enlarged regular symbols. It is also included in the --html option. +
      +
      +Check out the Math showcase (HTML edition) to see the results. +
      +

      +2.9 Footnotes +

      +
      +Footnote generation is surprisingly hard to get right in an HTML document. eLyXer has a fairly complete set of command line options to customize how footnotes are generated. Here we will use the aggregated option --footnotes "options" which can be used to specify any combination, but they can be turned on independently using --…foot. For instance: --footnotes number,margin is equivalent to --numberfoot --marginfoot. +
      +

      +Markers +

      +
      +The footnote is attached to a point of the text (the referring text) which is usually marked by a bit of text. The default behavior for the marker is to use a superscript letter surrounded by square brackets, in blue: [A]. The text can be changed to aligned text with --footnotes align: [A], so markers are not mistaken with other superscript constructs such as exponents (like ea). +
      +
      +Markers can also be converted to numbers using --footnotes number: [1]. Or, they can be switched over to symbols using --footnotes symbol: *. Available symbols are rotated from this sequence: * ** † ‡ § §§ ¶ ¶¶ # ##. All options can be combined. For instance, symbol markers look best when shown aligned; --footnotes align,symbol will show aligned symbolic markers such as * or . +
      +

      +Position +

      +
      +Footnotes are supposed to appear at the foot of the page, but that is not always possible or practical in web pages. Huge pages make scrolling up and down quite uncomfortable, and remove the immediacy of having the note in the same page as the referring text. +
      +
      +There are a few alternatives: use the margin, show hovering text, or link to the note at the bottom of the page. eLyXer can use all three. --footnotes margin will place the notes at the margin, just as margin notes but with the addition of the footnote marker. While --footnotes hover will show hovering text when the mouse is placed on the marker; this is the default behavior. Note that hovering notes are converted into margin notes when printing. +
      +
      +When footnotes are shown at the end of the page with --footnotes end, footnote markers turn into links. The actual footnote at the end then contains a link back to the marker. +
      +
      +The most interesting part is that these three options can be combined at will: --footnotes margin,hover,end will show footnotes at the three possible locations. The most practical combination is probably --footnotes hover,end, which will show notes as hovering text and also at the end of the page. Note however that in this case notes will be printed twice (at the margin instead of hovering and at the end). +
      +

      +3 Work in Progress +

      +
      +As you can see eLyXer is a mature and tried package, but it has some rough edges. +
      +

      +3.1 Known Issues +

      +
      +The following issues (including bugs and missing features) are acknowledged. Some of them should be solved soon; others may take longer. +
      +
        +
      1. +On Mac OS X the output of a message with Unicode characters may cause an error. Workaround: run elyxer.py with the --quiet option. +
      2. +
      3. +Some phonetic alphabet symbols are not well supported — if generated with LyX they only appear in a different color: [sample]. +
      4. +
      5. +Multi-column layouts are lost. This one is almost impossible to get right in CSS, so there are no plans to even try. +
      6. +
      7. +Many BibTeX styles are missing. (They are quite trivial to add though.) +
      8. +
      9. +ERT (bare TeX code) is ignored. +
      10. +
      11. +Many AMS environments (like alignat, gather…) are not working or look strange — some non-AMS environments too. +
      12. +
      13. +Images are never scaled above their nominal resolution. This is seldom needed if at all, so there are no plans to change it; if people really need the feature just let the author know so it can be added as an option. +
      14. + +
      +

      +3.2 Wish List +

      +
      +The following features have been requested by users; specific people are referenced by a couple of initials so they can recognize themselves while keeping some anonymity. (If you prefer that your initials do not to appear here at all just let me know.) +
      +
      +Queued features will be added at the next big release — the priority for each feature will be set by the number of users requesting it and date requested. Pending features need some assessment. Those marked as too complex have been evaluated as requiring too much work, but the decision might be reversed if there are enough people interested or a simple way to implement them is found. Once done, features are marked with the first release where they appear. +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +Feature + +Date + +Users + +Status +
      +Understand \setcounter{section}{1} + +2010-05-15 + +JB + +1.1.0 +
      +Option to turn off title prefixes in TOC + +2010-07-10 + +YG + +1.1.0 +
      +Use BibLaTeX with eLyXer + +2010-09-14 + +PJ, WE + +Pending +
      +Render change tracking: "Show changes in output" + +2010-09-18 + +YG + +1.1.0 +
      +Option for footnotes at the margin + +2010-09-21 + +A + +1.1.0 +
      +Output SVG as <img> tags (20↓) + +2010-09-22 + +YG + +Pending +
      +EPUB output format (19↓) + +2010-09-23 + +MJ, MG + +Too complex +
      +Option for footnotes at the end of each section + +2010-09-23 + +MJ + +1.1.0 +
      +Add more controls for image conversion (21↓) + +2010-10-02 + +WE + +1.1.0 +
      +Support for format 401 (Insert Horizontal Line) + +2010-10-06 + +US + +1.1.2 +
      +Parse contents of ERTs + +2010-10-06 + +US, JW + +1.2.0 +
      +Correct scaling of tables with relative sizes (e.g. %col) + +2010-10-09 + +US + +Pending +
      +BibTeX: parse math formulas inside BibTeX files + +2010-10-16 + +JA + +1.1.1 +
      +BibTeX: display \url{} as an URL + +2010-10-16 + +JA + +1.1.1 +
      +Do not label bibliography items in comments + +2010-10-21 + +JA + +Pending +
      +Unit tests should warn if ImageMagick not installed + +2010-10-24 + +JA + +Pending +
      +Unit tests should run fine without PNG conversion tools + +2010-10-30 + +JA + +Pending +
      +Option --imageformat copy to avoid converting images + +2010-11-12 + +JD + +1.1.1 +
      +Option to embed the CSS in the HTML file22↓ + +2010-11-23 + +GM, JA + +1.1.1 +
      +Display sub- and superscript aligned vertically (as in integrals) + +2010-11-23 + +GM + +1.1.1 +
      +Use Unicode large characters for sums, integrals, matrices… + +2010-12-07 + +GM + +1.1.2 +
      +Do not number captions in code listings + +2010-12-08 + +DC + +1.2.0 +
      +Support brushes for SyntaxHighlighter + +2010-12-10 + +DC + +Pending +
      +Generate formula images using Google Charts + +2011-01-07 + +ET + +1.2.1 +
      +Output reference arrows as CSS pseudo-elements + +2011-01-12 + +GM + +Pending +
      +Include part names in --splitpart navigation header + +2011-01-15 + +AJ + +1.2.1 +
      +Merge options --toc and --toctarget into --tocfor + +2010-01-17 + +JA + +1.2.1 +
      +Make --splitpart and --tocfor work together + +2010-01-17 + +JA, TP + +1.2.1 +
      +Generate named references (equivalent to \nameref) + +2011-01-19 + +TP + +1.2.1 +
      +Do not generate entries when index or nomenclature are missing + +2011-01-19 + +TP + +Queued +
      +Do not output unknown commands in red except in --debug + +2011-02-22 + +JA + +Queued +
      +Output equations as images + +2011-05-31 + +GK + +Pending +
      +Parse modules for custom Flex CharStyles + +2011-06-08 + +MG + +Pending +
      +Convert several files with a single command + +2011-06-01 + +PF + +Pending +
      +Export slides as HTML5 presentation + +2011-06-28 + +RK + +Pending +
      +Add an option to remove navigation bars + +2011-06-29 + +AH + +Pending +
      +Support for External Material: PDF, Date + +2011-10-22 + +MI + +Pending +
      + +
      +
      +Some features require further explanations. +
      +

      +EPUB output format +

      +
      +The EPUB management package calibre does not output valid EPUB documents when converted from eLyXer HTML files, at least according to the Threepress validator. +
      +
      +This is a complex feature request; calibre does minimal formatting in its EPUB conversion, so making it generate valid EPUB documents requires changing deeply how eLyXer outputs XHTML. Lots of help would be needed to get this working. +
      +
      +That said, EPUB readers are often much less strict than the official format and they readily accept eLyXer output. Just convert your LyX document to HTML using eLyXer, and then import the resulting HTML document into your EPUB reader. Let us know how it goes for you. +
      +

      +Output SVG as <img> tags +

      +
      +This feature would be most welcome from the part of the author. Unfortunately, Firefox alone from the major browsers refuses to render <img> tags correctly for SVG. According to bug #276431, this was fixed on 2010-09-08, so the next version should do the right thing; at that point this feature will be queued for inclusion. +
      +
      +You can check out how your browser does with SVG images with this SVG test page. +
      +

      +More controls for image conversion +

      +
      +eLyXer uses ImageMagick to convert images. Some images (in EPS format, for example) do have blank borders, or they come in varied sizes. It would be nice to remove blank borders and have some kind of unified resolution in the conversion, which would be passed to ImageMagick. +
      +
      +As of 1.1.0, the improvements include using ps:use-cropbox=true in ImageMagick for PostScript and EPS images. Unified resolution has not been added as it might collide with picture density, but suggestions are welcome. +
      +

      +CSS controls +

      +
      +Proposed by JRAS on the elyxer-users mailing list, the following is a direct quote of his message. +
      +
      +“[…]A mixed solution for CSS styles: +
      +
        +
      1. +The essential minimum css for math formatting (a compacted version of a math.css subset) included directly inside HTML head. +
      2. +
      3. +Then a call to download the on-line full CSS, that can repeat the minimum already included math.css (from item 1) plus some other styles. The default can be changed by --css command line option. +
      4. +
      5. +A new option (--addcss) to add another CSS defined by the user. For example, to only redefine some styles from the default, etc. +
      6. + +
      +
      +The styles should be included in that order (using the "cascading" property). Item 1 is fixed in every HTML file. Item 2 is always added and by default pointing to the eLyXer on-line css, but it can be changed by option --css to another url or file. Item 3 is optional and its url would be added after the other two items, only if the --addcss option was used in conversion.” +
      +
      +As of 1.1.1, an option --embedcss has been added which allows embedding one or more custom CSS files into the resulting HTML document. Also, --css can be repeated as many times as desired to use several CSS files. +
      +

      +3.3 Contact Information +

      +
      +If your problem does not appear in the above list, please let the author know; you can find him at elyxer@gmail.com. In the words of Rich Talley: “the tool’s author really likes getting challenging documents and making eLyXer work with them”. You can send your sample documents and we will try to make eLyXer convert them acceptably. Any documents sent will be treated with the utmost confidentiality. +
      +
      +You can also join the mailing list to discuss any information related to eLyXer. The author monitors the official LyX lists for mentions of eLyXer. Bugs can also be reported at the Savannah page. +
      +

      +3.4 Extending eLyXer +

      +
      +eLyXer should now support most LyX features; but sometimes it will ignore a command, sometimes it will signal it, and it might even refuse to work with certain documents. What can you do if eLyXer does not work with your LyX file? Worry not! Its flexible approach to processing allows anyone to write support for the missing commands. +
      +
      +eLyXer is written in Python so that it does not need to be compiled; its code is interpreted on the fly. See the accompanying developer guide to learn how to extend eLyXer for your own purposes. If you know how to program in Python it should not be difficult to support other LyX features. If you don’t your best bet is to ask the author. +
      +

      +4 FAQ +

      +
      +Q: What versions of LyX are supported? +
      +
      +A: The tool should work with all LyX versions from 1.5.5 to the latest and greatest. It has been tested on Linux, Mac OS X and Windows. +
      +
      +Q: There are indeed a ton of similar projects over the web. Why add another one? +
      +
      +A: The four tools supported by LyX (tex4ht, hevea, tth and latex2html) gave inferior results in 2009, and were quite inflexible. The author found the need for a good converter, while at the same time acknowledging the difficulty of the problem. +
      +
      +Q: Speaking of that: why build a LyX to HTML converter, instead of a more generic LaTeX to HTML converter? +
      +
      +A: The problem space is quite simplified, and therefore progress is much faster. To make it even easier eLyXer has historically centered on the subset of LyX functionality that is useful to most LyX users, leaving the rest for a later stage. Nowadays eLyXer aims to support the full LyX feature set. +
      +
      +Q: What can we expect from the tool in the future? +
      +
      +A: eLyXer should fulfill the needs of 99% of LyX users in the short term. It has also learned a couple of tricks of its own such as page segmenting. Eventually it could be distributed along with LyX as part of the standard installer. +
      +
      +Q: Why did you leave out my favorite feature <insert random LyX command here>? +
      +
      +A: In short, because nobody asked for it. Every feature which has been requested (either to me personally or to the list) has been tended to, unless it was too far out or I forgot about it. At this point of development every missing LyX feature will be considered a high priority item for the next version, if at all possible to implement. +
      +
      +Q: My document changed its appearance without my intervention. Was it black magic, elves or what? +
      +
      +A: It probably uses the online CSS file, which is regularly updated. See section 2.2↑ for details. +
      +
      +Q: Why use an online CSS, instead of placing the CSS file in the same directory as the converted file? +
      +
      +A: There were pros and cons. An online CSS resource allowed me to update it for everyone at the same time, but might make it more difficult for people without an internet connection; local CSS files are more flexible but can also be confusing to novice users. In the end the online solution was preferred, with the --css option as a fallback. +
      +
      +Q: My MathJax pages are not rendering correctly; equations are silently ignored. +
      +
      +A: Check that MathJax is installed on the same server as your pages; for security reasons the browser’s “same-origin” policy mandates that JavaScript can only be loaded from the same site as the original page. Also make sure that JavaScript is enabled on the browser. +
      +
      +Q: How can I disable hovering notes? Isn’t there a --nohover option? +
      +
      +A: It can be done using --footnotes margin. This will disable hovering text but keep footnotes in the margin. +
      +
      +Q: I found a bug, what should I do? +
      +
      +A: Just send it to the author at elyxer@gmail.com. You can also report it to the Savannah interface. +
      +

      +References +

      +

      +[1] WordReference.com: “definition of elixir”, accessed March 2009. http://www.wordreference.com/definition/elixir +

      +

      +[2] W3C: “XHTML™ 1.0 The Extensible HyperText Markup Language (Second Edition)”, revised 1 August 2002. http://www.w3.org/TR/xhtml1/ +

      +

      +[3] W3C: “HTML 4.01 Specification”, 24 December 1999. http://www.w3.org/TR/REC-html40/ +

      +

      +[4] W3C: “Markup Validation Service”, accessed March 2009. http://validator.w3.org/ +

      + + + +
      + + diff -Nru elyxer-1.2.3/loremipsumize.py elyxer-1.2.5/loremipsumize.py --- elyxer-1.2.3/loremipsumize.py 2011-08-31 00:08:48.000000000 +0000 +++ elyxer-1.2.5/loremipsumize.py 2013-03-10 21:23:56.000000000 +0000 @@ -70,7 +70,8 @@ def show(cls, message, channel): "Show a message out of a channel" - message = message.encode('utf-8') + if sys.version_info < (3,0): + message = message.encode('utf-8') channel.write(message + '\n') debug = classmethod(debug) @@ -173,7 +174,7 @@ "Write a string" if not self.file: self.file = codecs.open(self.filename, 'w', "utf-8") - if self.file == sys.stdout: + if self.file == sys.stdout and sys.version_info < (3,0): string = string.encode('utf-8') self.file.write(string) @@ -222,7 +223,7 @@ u'@conference':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', u'@inbook':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', u'@incollection':u'$authors: $title{ in $booktitle{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL $url.}{ $note.}', - u'@inproceedings':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@inproceedings':u'$authors: “$title”, $booktitle,{ pp. $pages,} $year.{ URL $url.}{ $note.}', u'@manual':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', u'@mastersthesis':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', u'@misc':u'$authors: $title.{{ $publisher,}{ $howpublished,} $year.}{ URL $url.}{ $note.}', @@ -402,7 +403,7 @@ "Configuration class from elyxer.config file" chars = { - u'\n':u'', u' -- ':u' — ', u'\'':u'’', u'---':u'—', u'`':u'‘', + u'\n':u'', u' -- ':u' — ', u' --- ':u' — ', u'\'':u'’', u'`':u'‘', } commands = { @@ -723,7 +724,9 @@ } hybridfunctions = { - + u'\\addcontentsline':[u'{$p!}{$q!}{$r!}',u'f0{}',u'ignored',], + u'\\addtocontents':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\backmatter':[u'',u'f0{}',u'ignored',], u'\\binom':[u'{$1}{$2}',u'f2{(}f0{f1{$1}f1{$2}}f2{)}',u'span class="binom"',u'span class="binomstack"',u'span class="bigsymbol"',], u'\\boxed':[u'{$1}',u'f0{$1}',u'span class="boxed"',], u'\\cfrac':[u'[$p!]{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator align-$p"',u'span class="denominator"',u'span class="ignored"',], @@ -732,15 +735,21 @@ u'\\dbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], u'\\dfrac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], u'\\displaystyle':[u'{$1}',u'f0{$1}',u'span class="displaystyle"',], + u'\\fancyfoot':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fancyhead':[u'[$p!]{$q!}',u'f0{}',u'ignored',], u'\\fbox':[u'{$1}',u'f0{$1}',u'span class="fbox"',], u'\\fboxrule':[u'{$p!}',u'f0{}',u'ignored',], u'\\fboxsep':[u'{$p!}',u'f0{}',u'ignored',], u'\\fcolorbox':[u'{$p!}{$q!}{$1}',u'f0{$1}',u'span class="boxed" style="border-color: $p; background: $q;"',], u'\\frac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], u'\\framebox':[u'[$p!][$q!]{$1}',u'f0{$1}',u'span class="framebox align-$q" style="width: $p;"',], + u'\\frontmatter':[u'',u'f0{}',u'ignored',], u'\\href':[u'[$o]{$u!}{$t!}',u'f0{$t}',u'a href="$u"',], u'\\hspace':[u'{$p!}',u'f0{ }',u'span class="hspace" style="width: $p;"',], u'\\leftroot':[u'{$p!}',u'f0{ }',u'span class="leftroot" style="width: $p;px"',], + u'\\mainmatter':[u'',u'f0{}',u'ignored',], + u'\\markboth':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\markright':[u'{$p!}',u'f0{}',u'ignored',], u'\\nicefrac':[u'{$1}{$2}',u'f0{f1{$1}⁄f2{$2}}',u'span class="fraction"',u'sup class="numerator"',u'sub class="denominator"',u'span class="ignored"',], u'\\parbox':[u'[$p!]{$w!}{$1}',u'f0{1}',u'div class="Boxed" style="width: $w;"',], u'\\raisebox':[u'{$p!}{$1}',u'f0{$1.font}',u'span class="raisebox" style="vertical-align: $p;"',], @@ -753,6 +762,7 @@ u'\\tbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], u'\\textcolor':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], u'\\textstyle':[u'{$1}',u'f0{$1}',u'span class="textstyle"',], + u'\\thispagestyle':[u'{$p!}',u'f0{}',u'ignored',], u'\\unit':[u'[$0]{$1}',u'$0f0{$1.font}',u'span class="unit"',], u'\\unitfrac':[u'[$0]{$1}{$2}',u'$0f0{f1{$1.font}⁄f2{$2.font}}',u'span class="fraction"',u'sup class="unit"',u'sub class="unit"',], u'\\uproot':[u'{$p!}',u'f0{ }',u'span class="uproot" style="width: $p;px"',], @@ -781,7 +791,7 @@ u'\\limits':u'LimitPreviousCommand', u'\\newcommand':u'MacroDefinition', u'\\renewcommand':u'MacroDefinition', u'\\setcounter':u'SetCounterFunction', u'\\tag':u'FormulaTag', - u'\\tag*':u'FormulaTag', + u'\\tag*':u'FormulaTag', u'\\today':u'TodayCommand', } modified = { @@ -894,7 +904,7 @@ "Configuration class from elyxer.config file" version = { - u'date':u'2011-08-31', u'lyxformat':u'413', u'number':u'1.2.3', + u'date':u'2013-03-10', u'lyxformat':u'413', u'number':u'1.2.5', } class HeaderConfig(object): @@ -923,6 +933,7 @@ u'imagemagick':u'convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output"', u'inkscape':u'inkscape "$input" --export-png="$output"', + u'lyx':u'lyx -C "$input" "$output"', } cropboxformats = { @@ -1081,7 +1092,8 @@ languages = { u'american':u'en', u'british':u'en', u'deutsch':u'de', u'dutch':u'nl', - u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'spanish':u'es', + u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'russian':u'ru', + u'spanish':u'es', } diff -Nru elyxer-1.2.3/math2html.py elyxer-1.2.5/math2html.py --- elyxer-1.2.3/math2html.py 2011-08-31 00:08:50.000000000 +0000 +++ elyxer-1.2.5/math2html.py 2013-03-10 21:23:56.000000000 +0000 @@ -62,7 +62,8 @@ def show(cls, message, channel): "Show a message out of a channel" - message = message.encode('utf-8') + if sys.version_info < (3,0): + message = message.encode('utf-8') channel.write(message + '\n') debug = classmethod(debug) @@ -111,7 +112,7 @@ u'@conference':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', u'@inbook':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', u'@incollection':u'$authors: $title{ in $booktitle{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL $url.}{ $note.}', - u'@inproceedings':u'$authors: “$title”, $journal,{ pp. $pages,} $year.{ URL $url.}{ $note.}', + u'@inproceedings':u'$authors: “$title”, $booktitle,{ pp. $pages,} $year.{ URL $url.}{ $note.}', u'@manual':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', u'@mastersthesis':u'$authors: $title.{{ $publisher,} $year.}{ URL $url.}{ $note.}', u'@misc':u'$authors: $title.{{ $publisher,}{ $howpublished,} $year.}{ URL $url.}{ $note.}', @@ -291,7 +292,7 @@ "Configuration class from elyxer.config file" chars = { - u'\n':u'', u' -- ':u' — ', u'\'':u'’', u'---':u'—', u'`':u'‘', + u'\n':u'', u' -- ':u' — ', u' --- ':u' — ', u'\'':u'’', u'`':u'‘', } commands = { @@ -612,7 +613,9 @@ } hybridfunctions = { - + u'\\addcontentsline':[u'{$p!}{$q!}{$r!}',u'f0{}',u'ignored',], + u'\\addtocontents':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\backmatter':[u'',u'f0{}',u'ignored',], u'\\binom':[u'{$1}{$2}',u'f2{(}f0{f1{$1}f1{$2}}f2{)}',u'span class="binom"',u'span class="binomstack"',u'span class="bigsymbol"',], u'\\boxed':[u'{$1}',u'f0{$1}',u'span class="boxed"',], u'\\cfrac':[u'[$p!]{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator align-$p"',u'span class="denominator"',u'span class="ignored"',], @@ -621,15 +624,21 @@ u'\\dbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], u'\\dfrac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], u'\\displaystyle':[u'{$1}',u'f0{$1}',u'span class="displaystyle"',], + u'\\fancyfoot':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fancyhead':[u'[$p!]{$q!}',u'f0{}',u'ignored',], u'\\fbox':[u'{$1}',u'f0{$1}',u'span class="fbox"',], u'\\fboxrule':[u'{$p!}',u'f0{}',u'ignored',], u'\\fboxsep':[u'{$p!}',u'f0{}',u'ignored',], u'\\fcolorbox':[u'{$p!}{$q!}{$1}',u'f0{$1}',u'span class="boxed" style="border-color: $p; background: $q;"',], u'\\frac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], u'\\framebox':[u'[$p!][$q!]{$1}',u'f0{$1}',u'span class="framebox align-$q" style="width: $p;"',], + u'\\frontmatter':[u'',u'f0{}',u'ignored',], u'\\href':[u'[$o]{$u!}{$t!}',u'f0{$t}',u'a href="$u"',], u'\\hspace':[u'{$p!}',u'f0{ }',u'span class="hspace" style="width: $p;"',], u'\\leftroot':[u'{$p!}',u'f0{ }',u'span class="leftroot" style="width: $p;px"',], + u'\\mainmatter':[u'',u'f0{}',u'ignored',], + u'\\markboth':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\markright':[u'{$p!}',u'f0{}',u'ignored',], u'\\nicefrac':[u'{$1}{$2}',u'f0{f1{$1}⁄f2{$2}}',u'span class="fraction"',u'sup class="numerator"',u'sub class="denominator"',u'span class="ignored"',], u'\\parbox':[u'[$p!]{$w!}{$1}',u'f0{1}',u'div class="Boxed" style="width: $w;"',], u'\\raisebox':[u'{$p!}{$1}',u'f0{$1.font}',u'span class="raisebox" style="vertical-align: $p;"',], @@ -642,6 +651,7 @@ u'\\tbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], u'\\textcolor':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], u'\\textstyle':[u'{$1}',u'f0{$1}',u'span class="textstyle"',], + u'\\thispagestyle':[u'{$p!}',u'f0{}',u'ignored',], u'\\unit':[u'[$0]{$1}',u'$0f0{$1.font}',u'span class="unit"',], u'\\unitfrac':[u'[$0]{$1}{$2}',u'$0f0{f1{$1.font}⁄f2{$2.font}}',u'span class="fraction"',u'sup class="unit"',u'sub class="unit"',], u'\\uproot':[u'{$p!}',u'f0{ }',u'span class="uproot" style="width: $p;px"',], @@ -670,7 +680,7 @@ u'\\limits':u'LimitPreviousCommand', u'\\newcommand':u'MacroDefinition', u'\\renewcommand':u'MacroDefinition', u'\\setcounter':u'SetCounterFunction', u'\\tag':u'FormulaTag', - u'\\tag*':u'FormulaTag', + u'\\tag*':u'FormulaTag', u'\\today':u'TodayCommand', } modified = { @@ -783,7 +793,7 @@ "Configuration class from elyxer.config file" version = { - u'date':u'2011-08-31', u'lyxformat':u'413', u'number':u'1.2.3', + u'date':u'2013-03-10', u'lyxformat':u'413', u'number':u'1.2.5', } class HeaderConfig(object): @@ -812,6 +822,7 @@ u'imagemagick':u'convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output"', u'inkscape':u'inkscape "$input" --export-png="$output"', + u'lyx':u'lyx -C "$input" "$output"', } cropboxformats = { @@ -970,7 +981,8 @@ languages = { u'american':u'en', u'british':u'en', u'deutsch':u'de', u'dutch':u'nl', - u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'spanish':u'es', + u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'russian':u'ru', + u'spanish':u'es', } @@ -1173,6 +1185,7 @@ return Options.marginfoot = False Options.letterfoot = False + Options.hoverfoot = False options = Options.footnotes.split(',') for option in options: footoption = option + 'foot' @@ -1783,7 +1796,7 @@ "Write a string" if not self.file: self.file = codecs.open(self.filename, 'w', "utf-8") - if self.file == sys.stdout: + if self.file == sys.stdout and sys.version_info < (3,0): string = string.encode('utf-8') self.file.write(string) @@ -3622,11 +3635,17 @@ return self.output.tag = TagConfig.barred[self.type] -class LangLine(BlackBox): +class LangLine(TaggedText): "A line with language information" def process(self): - self.lang = self.header[1] + "Only generate a span with lang info when the language is recognized." + lang = self.header[1] + if not lang in TranslationConfig.languages: + self.output = ContentsOutput() + return + isolang = TranslationConfig.languages[lang] + self.output = TaggedOutput().settag('span lang="' + isolang + '"', False) class InsetLength(BlackBox): "A length measure inside an inset." @@ -4566,6 +4585,8 @@ FormulaCommand.types += [BeginCommand] +import datetime + class CombiningFunction(OneParamFunction): @@ -4782,6 +4803,16 @@ command.output = ContentsOutput() command.contents = bracket.getcontents() +class TodayCommand(EmptyCommand): + "Shows today's date." + + commandmap = None + + def parsebit(self, pos): + "Parse a command without parameters" + self.output = FixedOutput() + self.html = [datetime.date.today().strftime('%b %d, %Y')] + FormulaCommand.types += [ DecoratingFunction, CombiningFunction, LimitCommand, BracketCommand, Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/po/locale/ru/LC_MESSAGES/elyxer.mo and /tmp/d8f5cQswGk/elyxer-1.2.5/po/locale/ru/LC_MESSAGES/elyxer.mo differ diff -Nru elyxer-1.2.3/po/ru.po elyxer-1.2.5/po/ru.po --- elyxer-1.2.3/po/ru.po 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/po/ru.po 2013-01-11 22:11:36.000000000 +0000 @@ -0,0 +1,164 @@ +msgid "" +msgstr "" +"Project-Id-Version: elyxer 1.2.3\n" +"PO-Revision-Date: 2011-11-11 16:24+0300\n" +"Last-Translator: Vladimir Ermakov \n" +"Language-Team: Russian\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"POT-Creation-Date: \n" + +# eLyXer internationalization file. +# Created on 2011-08-31 +# Contact: Alex Fernandez +# http://elyxer.nongnu.org/ +# This file is distributed under the same license as the eLyXer package. +# (C) 2010 Alex Fernandez . +# +#: Subsubsection +msgid "Subsubsection" +msgstr "Подподраздел" + +#: figure +msgid "figure" +msgstr "рисунок" + +#: abstract +msgid "Abstract" +msgstr "Аннотация" + +#: jsmath-warning +msgid "Warning: " +msgstr "" + +#: up +msgid "Up" +msgstr "Вверх" + +#: Book +msgid "Book" +msgstr "" + +#: references +msgid "References" +msgstr "Список литературы" + +#: Subsection +msgid "Subsection" +msgstr "Подраздел" + +#: list-algorithm +msgid "List of Algorithms" +msgstr "Список алгоритмов" + +#: Appendix +msgid "Appendix" +msgstr "Приложение" + +#: index +msgid "Index" +msgstr "Предметный указатель" + +#: bibliography +msgid "Bibliography" +msgstr "Библиография" + +#: list-table +msgid "List of Tables" +msgstr "Список таблиц" + +#: next +msgid "Next" +msgstr "След." + +#: float-algorithm +msgid "Algorithm " +msgstr "Алгоритм" + +#: Part +msgid "Part" +msgstr "Часть" + +#: generated-by +msgid "Document generated by " +msgstr "" + +#: toc +msgid "Table of Contents" +msgstr "Содержание" + +#: prev +msgid "Prev" +msgstr "Пред." + +#: Section +msgid "Section" +msgstr "Раздел" + +#: Chapter +msgid "Chapter" +msgstr "Глава" + +#: list-tableau +msgid "List of Tableaux" +msgstr "" + +#: generated-on +msgid " on " +msgstr "" + +#: float-tableau +msgid "Tableau " +msgstr "" + +#: Paragraph +msgid "Paragraph" +msgstr "Абзац" + +#: list-figure +msgid "List of Figures" +msgstr "Список рисунков" + +#: main-page +msgid "Main page" +msgstr "Главная" + +#: float-listing +msgid "Listing " +msgstr "Листинг " + +#: on-page +msgid " on page " +msgstr " на странице " + +#: nomenclature +msgid "Nomenclature" +msgstr "Список обозначений" + +#: float-table +msgid "Table " +msgstr "Таблица " + +#: float-figure +msgid "Figure " +msgstr "Рисунок " + +#: toc-for +msgid "Contents for " +msgstr "Содержание " + +#: jsmath-enable +msgid "Please enable JavaScript on your browser." +msgstr "Пожалуйста включите JavaScript." + +#: footnotes +msgid "Footnotes" +msgstr "Список сносок" + +#: jsmath-requires +msgid " requires JavaScript to correctly process the mathematics on this page. " +msgstr "Для формул необходим JavaScript." + diff -Nru elyxer-1.2.3/run-tests elyxer-1.2.5/run-tests --- elyxer-1.2.3/run-tests 2011-08-30 23:39:33.000000000 +0000 +++ elyxer-1.2.5/run-tests 2013-03-10 10:53:26.000000000 +0000 @@ -136,3 +136,8 @@ ../elyxer.py --quiet --css ../docs/lyx.css --title "By Fernández" "$name.lyx" "$name-test.html" diff -u --ignore-matching-lines="create-date" --ignore-matching-lines="" "$name-good.html" "$name-test.html" +# test simultaneous hover and end in footnotes +name="footnotes-1-6" +../elyxer.py --quiet --footnotes hover,end,number --css ../docs/lyx.css "$name.lyx" "$name-hover-end-test.html" +diff -u --ignore-matching-lines="create-date" "$name-hover-end-good.html" "$name-hover-end-test.html" + diff -Nru elyxer-1.2.3/setup.py elyxer-1.2.5/setup.py --- elyxer-1.2.3/setup.py 2011-08-31 00:35:33.000000000 +0000 +++ elyxer-1.2.5/setup.py 2013-03-10 21:25:54.000000000 +0000 @@ -33,7 +33,7 @@ packages = [] setup(name = 'eLyXer', - version = '1.2.3', + version = '1.2.5', description = 'LyX to HTML converter', long_description = 'eLyXer is a LyX to HTML converter, with a focus on flexibility and elegant output.', author = 'Alex Fernandez', diff -Nru elyxer-1.2.3/src/conf/base.cfg elyxer-1.2.5/src/conf/base.cfg --- elyxer-1.2.3/src/conf/base.cfg 2011-08-31 00:00:49.000000000 +0000 +++ elyxer-1.2.5/src/conf/base.cfg 2013-03-10 21:23:48.000000000 +0000 @@ -39,7 +39,7 @@ @conference:$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.} @inbook:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} @incollection:$authors: <i>$title</i>{ in <i>$booktitle</i>{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} -@inproceedings:$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.} +@inproceedings:$authors: “$title”, <i>$booktitle</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.} @manual:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} @mastersthesis:$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} @misc:$authors: <i>$title</i>.{{ $publisher,}{ $howpublished,} $year.}{ URL <a href="$url">$url</a>.}{ $note.} @@ -253,7 +253,7 @@ [EscapeConfig.chars] : ----:— + --- : — -- : — ':’ `:‘ @@ -1292,6 +1292,16 @@ \scriptstyle:[{$1},f0{$1},span class="scriptstyle"] \displaystyle:[{$1},f0{$1},span class="displaystyle"] \textstyle:[{$1},f0{$1},span class="textstyle"] +\thispagestyle:[{$p!},f0{},ignored] +\frontmatter:[,f0{},ignored] +\mainmatter:[,f0{},ignored] +\backmatter:[,f0{},ignored] +\markboth:[{$p!}{$q!},f0{},ignored] +\markright:[{$p!},f0{},ignored] +\fancyfoot:[[$p!]{$q!},f0{},ignored] +\fancyhead:[[$p!]{$q!},f0{},ignored] +\addcontentsline:[{$p!}{$q!}{$r!},f0{},ignored] +\addtocontents:[{$p!}{$q!},f0{},ignored] [FormulaConfig.hybridsizes] \frac:$1+$2 @@ -1308,6 +1318,7 @@ \tag:FormulaTag \tag*:FormulaTag \limits:LimitPreviousCommand +\today:TodayCommand [FormulaConfig.limitcommands] \sum:∑ @@ -1416,8 +1427,8 @@ googlecharts:http://chart.googleapis.com/chart?cht=tx&chl= [GeneralConfig.version] -date:2009-06-17 -number:1.2.3 +date:2011-11-22 +number:1.2.5 lyxformat:413 [HeaderConfig.parameters] @@ -1441,6 +1452,7 @@ [ImageConfig.converters] imagemagick:convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output" inkscape:inkscape "$input" --export-png="$output" +lyx:lyx -C "$input" "$output" [ImageConfig.cropboxformats] .pdf:pdf @@ -1632,4 +1644,5 @@ french:fr british:en american:en +russian:ru diff -Nru elyxer-1.2.3/src/conf/elyxer.pot elyxer-1.2.5/src/conf/elyxer.pot --- elyxer-1.2.3/src/conf/elyxer.pot 2011-08-31 00:08:51.000000000 +0000 +++ elyxer-1.2.5/src/conf/elyxer.pot 2013-03-10 21:23:56.000000000 +0000 @@ -1,5 +1,5 @@ # eLyXer internationalization file. -# Created on 2011-08-31 +# Created on 2013-03-10 # Contact: Alex Fernandez <elyxer@gmail.com> # http://elyxer.nongnu.org/ # This file is distributed under the same license as the eLyXer package. diff -Nru elyxer-1.2.3/src/elyxer/bib/tag.py elyxer-1.2.5/src/elyxer/bib/tag.py --- elyxer-1.2.3/src/elyxer/bib/tag.py 2011-01-23 22:03:02.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/bib/tag.py 2013-01-11 22:11:36.000000000 +0000 @@ -68,6 +68,8 @@ def parsetag(self, pos): "Parse a single tag." (key, value) = self.getkeyvalue(pos) + if not key: + return if not value: self.key = key return diff -Nru elyxer-1.2.3/src/elyxer/conf/config.py elyxer-1.2.5/src/elyxer/conf/config.py --- elyxer-1.2.3/src/elyxer/conf/config.py 2011-08-31 00:08:45.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/conf/config.py 2013-03-10 21:23:55.000000000 +0000 @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # eLyXer configuration -# autogenerated from elyxer.config file on 2011-08-31 +# autogenerated from elyxer.config file on 2013-03-10 class BibStylesConfig(object): "Configuration class from elyxer.config file" @@ -37,7 +37,7 @@ u'@conference':u'$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}', u'@inbook':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', u'@incollection':u'$authors: <i>$title</i>{ in <i>$booktitle</i>{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', - u'@inproceedings':u'$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}', + u'@inproceedings':u'$authors: “$title”, <i>$booktitle</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}', u'@manual':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', u'@mastersthesis':u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', u'@misc':u'$authors: <i>$title</i>.{{ $publisher,}{ $howpublished,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}', @@ -217,7 +217,7 @@ "Configuration class from elyxer.config file" chars = { - u'\n':u'', u' -- ':u' — ', u'\'':u'’', u'---':u'—', u'`':u'‘', + u'\n':u'', u' -- ':u' — ', u' --- ':u' — ', u'\'':u'’', u'`':u'‘', } commands = { @@ -538,7 +538,9 @@ } hybridfunctions = { - + u'\\addcontentsline':[u'{$p!}{$q!}{$r!}',u'f0{}',u'ignored',], + u'\\addtocontents':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\backmatter':[u'',u'f0{}',u'ignored',], u'\\binom':[u'{$1}{$2}',u'f2{(}f0{f1{$1}f1{$2}}f2{)}',u'span class="binom"',u'span class="binomstack"',u'span class="bigsymbol"',], u'\\boxed':[u'{$1}',u'f0{$1}',u'span class="boxed"',], u'\\cfrac':[u'[$p!]{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator align-$p"',u'span class="denominator"',u'span class="ignored"',], @@ -547,15 +549,21 @@ u'\\dbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], u'\\dfrac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fullfraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], u'\\displaystyle':[u'{$1}',u'f0{$1}',u'span class="displaystyle"',], + u'\\fancyfoot':[u'[$p!]{$q!}',u'f0{}',u'ignored',], + u'\\fancyhead':[u'[$p!]{$q!}',u'f0{}',u'ignored',], u'\\fbox':[u'{$1}',u'f0{$1}',u'span class="fbox"',], u'\\fboxrule':[u'{$p!}',u'f0{}',u'ignored',], u'\\fboxsep':[u'{$p!}',u'f0{}',u'ignored',], u'\\fcolorbox':[u'{$p!}{$q!}{$1}',u'f0{$1}',u'span class="boxed" style="border-color: $p; background: $q;"',], u'\\frac':[u'{$1}{$2}',u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}',u'span class="fraction"',u'span class="numerator"',u'span class="denominator"',u'span class="ignored"',], u'\\framebox':[u'[$p!][$q!]{$1}',u'f0{$1}',u'span class="framebox align-$q" style="width: $p;"',], + u'\\frontmatter':[u'',u'f0{}',u'ignored',], u'\\href':[u'[$o]{$u!}{$t!}',u'f0{$t}',u'a href="$u"',], u'\\hspace':[u'{$p!}',u'f0{ }',u'span class="hspace" style="width: $p;"',], u'\\leftroot':[u'{$p!}',u'f0{ }',u'span class="leftroot" style="width: $p;px"',], + u'\\mainmatter':[u'',u'f0{}',u'ignored',], + u'\\markboth':[u'{$p!}{$q!}',u'f0{}',u'ignored',], + u'\\markright':[u'{$p!}',u'f0{}',u'ignored',], u'\\nicefrac':[u'{$1}{$2}',u'f0{f1{$1}⁄f2{$2}}',u'span class="fraction"',u'sup class="numerator"',u'sub class="denominator"',u'span class="ignored"',], u'\\parbox':[u'[$p!]{$w!}{$1}',u'f0{1}',u'div class="Boxed" style="width: $w;"',], u'\\raisebox':[u'{$p!}{$1}',u'f0{$1.font}',u'span class="raisebox" style="vertical-align: $p;"',], @@ -568,6 +576,7 @@ u'\\tbinom':[u'{$1}{$2}',u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})',u'span class="binomial"',u'span class="binomrow"',u'span class="binomcell"',], u'\\textcolor':[u'{$p!}{$1}',u'f0{$1}',u'span style="color: $p;"',], u'\\textstyle':[u'{$1}',u'f0{$1}',u'span class="textstyle"',], + u'\\thispagestyle':[u'{$p!}',u'f0{}',u'ignored',], u'\\unit':[u'[$0]{$1}',u'$0f0{$1.font}',u'span class="unit"',], u'\\unitfrac':[u'[$0]{$1}{$2}',u'$0f0{f1{$1.font}⁄f2{$2.font}}',u'span class="fraction"',u'sup class="unit"',u'sub class="unit"',], u'\\uproot':[u'{$p!}',u'f0{ }',u'span class="uproot" style="width: $p;px"',], @@ -596,7 +605,7 @@ u'\\limits':u'LimitPreviousCommand', u'\\newcommand':u'MacroDefinition', u'\\renewcommand':u'MacroDefinition', u'\\setcounter':u'SetCounterFunction', u'\\tag':u'FormulaTag', - u'\\tag*':u'FormulaTag', + u'\\tag*':u'FormulaTag', u'\\today':u'TodayCommand', } modified = { @@ -709,7 +718,7 @@ "Configuration class from elyxer.config file" version = { - u'date':u'2011-08-31', u'lyxformat':u'413', u'number':u'1.2.3', + u'date':u'2013-03-10', u'lyxformat':u'413', u'number':u'1.2.5', } class HeaderConfig(object): @@ -738,6 +747,7 @@ u'imagemagick':u'convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output"', u'inkscape':u'inkscape "$input" --export-png="$output"', + u'lyx':u'lyx -C "$input" "$output"', } cropboxformats = { @@ -896,6 +906,7 @@ languages = { u'american':u'en', u'british':u'en', u'deutsch':u'de', u'dutch':u'nl', - u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'spanish':u'es', + u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'russian':u'ru', + u'spanish':u'es', } diff -Nru elyxer-1.2.3/src/elyxer/conf/importconfig.py elyxer-1.2.5/src/elyxer/conf/importconfig.py --- elyxer-1.2.3/src/elyxer/conf/importconfig.py 2011-06-28 21:22:51.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/conf/importconfig.py 2013-03-10 10:53:26.000000000 +0000 @@ -25,7 +25,6 @@ from elyxer.util.trace import Trace from elyxer.io.fileline import * from elyxer.conf.fileconfig import * -from elyxer.conf.config import * class ImportFile(object): diff -Nru elyxer-1.2.3/src/elyxer/gen/image.py elyxer-1.2.5/src/elyxer/gen/image.py --- elyxer-1.2.3/src/elyxer/gen/image.py 2011-01-15 22:05:23.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/gen/image.py 2013-01-11 22:11:36.000000000 +0000 @@ -146,11 +146,10 @@ def buildcommand(self, image): "Build the command to convert the image." - if not Options.converter in ImageConfig.converters: - Trace.error('Converter ' + Options.converter + ' not configured.') - ImageConverter.active = False - return '' - command = ImageConfig.converters[Options.converter] + if Options.converter in ImageConfig.converters: + command = ImageConfig.converters[Options.converter] + else: + command = Options.converter; params = self.getparams(image) for param in params: command = command.replace('$' + param, unicode(params[param])) @@ -266,7 +265,7 @@ def readformat(self, file, format, bytes): "Read any format from elyxer.file" read = file.read(bytes) - if read == '': + if read == '' or len(read) < bytes: Trace.error('EOF reached') return 0 tuple = struct.unpack(format, read) diff -Nru elyxer-1.2.3/src/elyxer/gen/notes.py elyxer-1.2.5/src/elyxer/gen/notes.py --- elyxer-1.2.3/src/elyxer/gen/notes.py 2011-01-01 20:56:42.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/gen/notes.py 2013-03-10 10:53:26.000000000 +0000 @@ -75,6 +75,14 @@ self.createcontents() return self + def createlabel(self, marker): + "Create the label for a footnote. Used in hoverfoot and marginfoot." + self.order = marker.order + self.contents = [Constant(self.getmark())] + space = Constant(u' ') + self.contents = [space] + self.contents + [space] + return self + def createcontents(self): "Create the contents of the marker." if Options.endfoot: @@ -103,14 +111,15 @@ "Can be numeric or a letter depending on runtime options." marker = FootnoteMarker().create() anchor = FootnoteMarker().createanchor(marker) - notecontents = [anchor] + list(self.contents) + label = FootnoteMarker().createlabel(marker) + notecontents = list(self.contents) self.contents = [marker] if Options.hoverfoot: - self.contents.append(self.createnote(notecontents, 'span class="HoverFoot"')) + self.contents.append(self.createnote([label] + notecontents, 'span class="HoverFoot"')) if Options.marginfoot: - self.contents.append(self.createnote(notecontents, 'span class="MarginFoot"')) + self.contents.append(self.createnote([label] + notecontents, 'span class="MarginFoot"')) if Options.endfoot: - EndFootnotes.footnotes.append(self.createnote(notecontents, 'div class="EndFoot"')) + EndFootnotes.footnotes.append(self.createnote([anchor] + notecontents, 'div class="EndFoot"')) def createnote(self, contents, tag): "Create a note with the given contents and HTML tag." diff -Nru elyxer-1.2.3/src/elyxer/gen/styles.py elyxer-1.2.5/src/elyxer/gen/styles.py --- elyxer-1.2.3/src/elyxer/gen/styles.py 2011-08-30 23:59:22.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/gen/styles.py 2013-01-11 22:11:36.000000000 +0000 @@ -129,11 +129,17 @@ return self.output.tag = TagConfig.barred[self.type] -class LangLine(BlackBox): +class LangLine(TaggedText): "A line with language information" def process(self): - self.lang = self.header[1] + "Only generate a span with lang info when the language is recognized." + lang = self.header[1] + if not lang in TranslationConfig.languages: + self.output = ContentsOutput() + return + isolang = TranslationConfig.languages[lang] + self.output = TaggedOutput().settag('span lang="' + isolang + '"', False) class InsetLength(BlackBox): "A length measure inside an inset." diff -Nru elyxer-1.2.3/src/elyxer/io/fileline.py elyxer-1.2.5/src/elyxer/io/fileline.py --- elyxer-1.2.3/src/elyxer/io/fileline.py 2011-02-17 22:46:53.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/io/fileline.py 2013-01-11 22:11:36.000000000 +0000 @@ -119,7 +119,7 @@ "Write a string" if not self.file: self.file = codecs.open(self.filename, 'w', "utf-8") - if self.file == sys.stdout: + if self.file == sys.stdout and sys.version_info < (3,0): string = string.encode('utf-8') self.file.write(string) diff -Nru elyxer-1.2.3/src/elyxer/maths/extracommand.py elyxer-1.2.5/src/elyxer/maths/extracommand.py --- elyxer-1.2.3/src/elyxer/maths/extracommand.py 2011-01-30 10:09:36.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/maths/extracommand.py 2013-01-11 22:11:36.000000000 +0000 @@ -29,6 +29,8 @@ from elyxer.maths.symbol import * from elyxer.maths.array import * +import datetime + class CombiningFunction(OneParamFunction): @@ -245,6 +247,16 @@ command.output = ContentsOutput() command.contents = bracket.getcontents() +class TodayCommand(EmptyCommand): + "Shows today's date." + + commandmap = None + + def parsebit(self, pos): + "Parse a command without parameters" + self.output = FixedOutput() + self.html = [datetime.date.today().strftime('%b %d, %Y')] + FormulaCommand.types += [ DecoratingFunction, CombiningFunction, LimitCommand, BracketCommand, diff -Nru elyxer-1.2.3/src/elyxer/util/options.py elyxer-1.2.5/src/elyxer/util/options.py --- elyxer-1.2.3/src/elyxer/util/options.py 2011-07-08 23:54:48.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/util/options.py 2013-01-11 22:19:39.000000000 +0000 @@ -155,6 +155,7 @@ return Options.marginfoot = False Options.letterfoot = False + Options.hoverfoot = False options = Options.footnotes.split(',') for option in options: footoption = option + 'foot' diff -Nru elyxer-1.2.3/src/elyxer/util/trace.py elyxer-1.2.5/src/elyxer/util/trace.py --- elyxer-1.2.3/src/elyxer/util/trace.py 2011-01-01 20:56:44.000000000 +0000 +++ elyxer-1.2.5/src/elyxer/util/trace.py 2013-01-11 22:11:36.000000000 +0000 @@ -61,7 +61,8 @@ def show(cls, message, channel): "Show a message out of a channel" - message = message.encode('utf-8') + if sys.version_info < (3,0): + message = message.encode('utf-8') channel.write(message + '\n') debug = classmethod(debug) diff -Nru elyxer-1.2.3/src/exportconfig.py elyxer-1.2.5/src/exportconfig.py --- elyxer-1.2.3/src/exportconfig.py 2011-06-28 21:23:34.000000000 +0000 +++ elyxer-1.2.5/src/exportconfig.py 2013-03-10 10:53:26.000000000 +0000 @@ -28,7 +28,6 @@ from elyxer.util.clparse import * from elyxer.conf.fileconfig import * from elyxer.conf.importconfig import * -import elyxer.conf.config class Config(object): diff -Nru elyxer-1.2.3/test/copyimages/with images-1-5-test.html elyxer-1.2.5/test/copyimages/with images-1-5-test.html --- elyxer-1.2.3/test/copyimages/with images-1-5-test.html 2011-08-31 00:10:00.000000000 +0000 +++ elyxer-1.2.5/test/copyimages/with images-1-5-test.html 2013-03-10 21:24:06.000000000 +0000 @@ -4,7 +4,7 @@ <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta name="generator" content="http://www.nongnu.org/elyxer/"/> -<meta name="create-date" content="2011-08-31"/> +<meta name="create-date" content="2013-03-10"/> <link rel="stylesheet" href="../../docs/lyx.css" type="text/css" media="all"/> <title>Images Tests @@ -42,7 +42,7 @@ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/test/elyxer-eps.png and /tmp/d8f5cQswGk/elyxer-1.2.5/test/elyxer-eps.png differ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/test/elyxer-svg.png and /tmp/d8f5cQswGk/elyxer-1.2.5/test/elyxer-svg.png differ diff -Nru elyxer-1.2.3/test/footnotes-1-6-hover-end-good.html elyxer-1.2.5/test/footnotes-1-6-hover-end-good.html --- elyxer-1.2.3/test/footnotes-1-6-hover-end-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/test/footnotes-1-6-hover-end-good.html 2013-03-10 10:53:26.000000000 +0000 @@ -0,0 +1,82 @@ + + + + + + + + +Footnotes Tests + + +
      +

      +Footnotes Tests +

      + +

      +1 This is just some random section text used to insert some footnotes.[1] [1] And this is one of those footnotes. +And this is a margin note, also tested here. + + +

      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing[2] [2] adipisicing elit[3] [3] elit, sed do eiusmod +eiusmod + + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa [4] [4] culpa qui officia [5] [5] officia deserunt mollit anim id est laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum[6] [6] laborum, laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do tempor incididunt ut [7] [7] ut labore[8] [8] labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +
      +
      +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod +eiusmod + + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis +Duis + + aute irure dolor in reprehenderit in voluptate velit[9] [9] velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id +id + + est laborum. +
      +

      Nomenclature

      +eiusmod eiusmod indeed +
      +
      +

      +References +

      + +
      +

      Index

      +ullamco: +

      +

      Footnotes

      [1]And this is one of those footnotes.
      [2]adipisicing
      [3]elit
      [4]culpa
      [5]officia
      [6]laborum, laborum
      [7]ut
      [8]labore
      [9]velit
      + + +
      + + diff -Nru elyxer-1.2.3/test/helloworld-template-good.html elyxer-1.2.5/test/helloworld-template-good.html --- elyxer-1.2.3/test/helloworld-template-good.html 2011-01-02 18:54:53.000000000 +0000 +++ elyxer-1.2.5/test/helloworld-template-good.html 2013-03-10 10:53:26.000000000 +0000 @@ -14,7 +14,7 @@ -

      (C) 2011

      +

      (C) 2013

      diff -Nru elyxer-1.2.3/test/image-scaling-good.html elyxer-1.2.5/test/image-scaling-good.html --- elyxer-1.2.3/test/image-scaling-good.html 2010-09-15 21:51:31.000000000 +0000 +++ elyxer-1.2.5/test/image-scaling-good.html 2013-01-11 22:11:36.000000000 +0000 @@ -4,7 +4,7 @@ - + Image Scaling Tests @@ -25,11 +25,11 @@ PNG scaled 50%.
      -figure elyxer-eps.png +figure elyxer-eps.png Unscaled EPS.
      -figure elyxer-eps.png +figure elyxer-eps.png EPS scaled 50%.

      @@ -73,7 +73,7 @@ diff -Nru elyxer-1.2.3/test/index-1-6-good.html elyxer-1.2.5/test/index-1-6-good.html --- elyxer-1.2.3/test/index-1-6-good.html 2011-05-31 22:08:08.000000000 +0000 +++ elyxer-1.2.5/test/index-1-6-good.html 2013-01-11 22:11:36.000000000 +0000 @@ -4,7 +4,7 @@ - + Index Test @@ -29,7 +29,7 @@ Section 1.1: Magical type face changes in the world
      Section: Unnumbered Section @@ -136,7 +136,7 @@ Little more can be added, at least at this point.

      -1.2Color and colour +1.2Color and colour

      At this other point, however, more could be added, but won’t. @@ -217,7 +217,7 @@ Section 1.1: Magical type face changes in the world
      Section: Unnumbered Section @@ -477,7 +477,7 @@
      diff -Nru elyxer-1.2.3/test/index-1-6-lowmem-good.html elyxer-1.2.5/test/index-1-6-lowmem-good.html --- elyxer-1.2.3/test/index-1-6-lowmem-good.html 2011-05-31 21:43:29.000000000 +0000 +++ elyxer-1.2.5/test/index-1-6-lowmem-good.html 2013-01-11 22:11:36.000000000 +0000 @@ -4,7 +4,7 @@ - + Index Test @@ -47,7 +47,7 @@ Little more can be added, at least at this point.

      -1.2Color and colour +1.2Color and colour

      At this other point, however, more could be added, but won’t. @@ -293,7 +293,7 @@
      diff -Nru elyxer-1.2.3/test/languages-good.html elyxer-1.2.5/test/languages-good.html --- elyxer-1.2.3/test/languages-good.html 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/test/languages-good.html 2013-01-11 22:11:36.000000000 +0000 @@ -0,0 +1,26 @@ + + + + + + + + +Converted document + + +
      +
      +This is some English text. +
      +
      +Esto es texto en español. +
      + + + +
      + + diff -Nru elyxer-1.2.3/test/languages.lyx elyxer-1.2.5/test/languages.lyx --- elyxer-1.2.3/test/languages.lyx 1970-01-01 00:00:00.000000000 +0000 +++ elyxer-1.2.5/test/languages.lyx 2013-01-11 22:11:36.000000000 +0000 @@ -0,0 +1,76 @@ +#LyX 2.0 created this file. For more info see http://www.lyx.org/ +\lyxformat 413 +\begin_document +\begin_header +\textclass article +\use_default_options true +\maintain_unincluded_children false +\language russian +\language_package default +\inputencoding auto +\fontencoding global +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\use_non_tex_fonts false +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 + +\graphics default +\default_output_format default +\output_sync 0 +\bibtex_command default +\index_command default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_amsmath 1 +\use_esint 1 +\use_mhchem 1 +\use_mathdots 1 +\cite_engine basic +\use_bibtopic false +\use_indices false +\paperorientation portrait +\suppress_date false +\use_refstyle 1 +\index Index +\shortcut idx +\color #008000 +\end_index +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\paragraph_indentation default +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\html_math_output 0 +\html_css_as_file 0 +\html_be_strict false +\end_header + +\begin_body + +\begin_layout Standard + +\lang english +This is some English text. +\end_layout + +\begin_layout Standard + +\lang spanish +Esto es texto en español. +\end_layout + +\end_body +\end_document diff -Nru elyxer-1.2.3/test/parts/index-1-6-part-good-1.html elyxer-1.2.5/test/parts/index-1-6-part-good-1.html --- elyxer-1.2.3/test/parts/index-1-6-part-good-1.html 2011-02-03 22:09:45.000000000 +0000 +++ elyxer-1.2.5/test/parts/index-1-6-part-good-1.html 2013-01-11 22:11:36.000000000 +0000 @@ -4,7 +4,7 @@ - + Index Test @@ -40,7 +40,7 @@ Little more can be added, at least at this point.

      -1.2Color and colour +1.2Color and colour

      At this other point, however, more could be added, but won’t. @@ -68,7 +68,7 @@
      diff -Nru elyxer-1.2.3/test/parts/index-1-6-part-good-Chapter--1.html elyxer-1.2.5/test/parts/index-1-6-part-good-Chapter--1.html --- elyxer-1.2.3/test/parts/index-1-6-part-good-Chapter--1.html 2011-02-03 22:09:45.000000000 +0000 +++ elyxer-1.2.5/test/parts/index-1-6-part-good-Chapter--1.html 2013-01-11 22:11:36.000000000 +0000 @@ -4,7 +4,7 @@ - + Index Test @@ -40,7 +40,7 @@ Section 1.1: Magical type face changes in the world
      Section: Unnumbered Section @@ -136,7 +136,7 @@
      diff -Nru elyxer-1.2.3/test/parts/index-1-6-part-good-Part-I.html elyxer-1.2.5/test/parts/index-1-6-part-good-Part-I.html --- elyxer-1.2.3/test/parts/index-1-6-part-good-Part-I.html 2011-02-03 22:09:45.000000000 +0000 +++ elyxer-1.2.5/test/parts/index-1-6-part-good-Part-I.html 2013-01-11 22:11:36.000000000 +0000 @@ -4,7 +4,7 @@ - + Index Test @@ -31,7 +31,7 @@ Section 1.1: Magical type face changes in the world
      Section: Unnumbered Section @@ -59,7 +59,7 @@
      diff -Nru elyxer-1.2.3/test/parts/index-1-6-part-good.html elyxer-1.2.5/test/parts/index-1-6-part-good.html --- elyxer-1.2.3/test/parts/index-1-6-part-good.html 2011-02-03 22:09:45.000000000 +0000 +++ elyxer-1.2.5/test/parts/index-1-6-part-good.html 2013-01-11 22:11:36.000000000 +0000 @@ -4,7 +4,7 @@ - + Index Test @@ -34,7 +34,7 @@ Section 1.1: Magical type face changes in the world
      Section: Unnumbered Section @@ -121,7 +121,7 @@
      diff -Nru elyxer-1.2.3/test/parts/index-1-6-toc-good.html elyxer-1.2.5/test/parts/index-1-6-toc-good.html --- elyxer-1.2.3/test/parts/index-1-6-toc-good.html 2011-02-24 23:18:11.000000000 +0000 +++ elyxer-1.2.5/test/parts/index-1-6-toc-good.html 2013-01-11 22:11:36.000000000 +0000 @@ -4,7 +4,7 @@ - + Index Test @@ -25,7 +25,7 @@ Section 1.1: Magical type face changes in the world
      Section: Unnumbered Section @@ -100,7 +100,7 @@
      diff -Nru elyxer-1.2.3/test/parts/index-1-6-toc-test.html elyxer-1.2.5/test/parts/index-1-6-toc-test.html --- elyxer-1.2.3/test/parts/index-1-6-toc-test.html 2011-08-31 00:10:12.000000000 +0000 +++ elyxer-1.2.5/test/parts/index-1-6-toc-test.html 2013-03-10 21:24:07.000000000 +0000 @@ -4,7 +4,7 @@ - + Index Test @@ -25,7 +25,7 @@ Section 1.1: Magical type face changes in the world
      Section: Unnumbered Section @@ -100,7 +100,7 @@
      diff -Nru elyxer-1.2.3/test/subdir/appendix-1-6-good.html elyxer-1.2.5/test/subdir/appendix-1-6-good.html --- elyxer-1.2.3/test/subdir/appendix-1-6-good.html 2011-05-31 22:06:37.000000000 +0000 +++ elyxer-1.2.5/test/subdir/appendix-1-6-good.html 2013-03-10 10:53:26.000000000 +0000 @@ -533,10 +533,10 @@ Binary files /tmp/esRFHoaOgb/elyxer-1.2.3/test/subdir/mourning.png and /tmp/d8f5cQswGk/elyxer-1.2.5/test/subdir/mourning.png differ