pax_global_header00006660000000000000000000000064131710614410014510gustar00rootroot0000000000000052 comment=e368b6d0f5f773970ade0879ba995b0826ce989a GladTeX-2.3.1/000077500000000000000000000000001317106144100130035ustar00rootroot00000000000000GladTeX-2.3.1/.gitignore000066400000000000000000000001241317106144100147700ustar00rootroot00000000000000*build* dist doc/gleetex.*html doc/index.html gladtex.1 *.pyc *pycache* *.swp *.zip GladTeX-2.3.1/COPYING000066400000000000000000000167431317106144100140510ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser 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 Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. GladTeX-2.3.1/ChangeLog000066400000000000000000000167351317106144100145710ustar00rootroot000000000000002.3.1 Avoid useless spaces - When formula replacement with `-R` is requested, it could happen that additional spaces were inserted, even if not necessary. "für" would for instance become "f\"{u} r". Fixed. 2.3 Fix formula sizing - It seems as if 16px / 12pt were the default font size these days for browsers. Therefore, the default resolution has been set to 115 DPI. Furthermore, the DPI switch now accepts pt values for fontsizes and will calculate the corresponding DPI itself. - When the environment variable `DEBUG=1` is set, the full backtrace will be printed. - Extend unicode table creation script to allow blacklisting of certain commands. 2.2.1 - fix handling of non-ascii alphabetical characters - replace characters with diacritics in the LaTeX source, but keep the unmodified character in image alt attribute (for better readibility) 2.2 - make alternative text of formulas more readable - replace formatting commands in alt attribute; this shortens the formula and makes it mor readable - replace unicode signs also in alt attribute (good for screen reader users and text-mode browsers) - recognize upper-case `ENV` attribute of `EQ` tag (so that e.g. displaymath is recognized correctly) 2.1.1 Bug Fix Release - treat eq element content as verbatim - decode HTML entities within formula tags 2.1 add support for unicode math with translation table - handle subprocess stdin and stdout encoding properly - set UTF-8 as encoding for all LaTeX documents - add -R option (replace non ascii characters) - formulas in .htex documents may now contain umlauts or unicode math characters; conversion will work without adjustments, only -R has to be specified - handle encoding better and more strictly for LaTeX 2E 2.0.1 Bug Fix Release - show user a meaningful error message if LaTeX or dvipng is missing - setup.py: build manual page, if pandoc present - freeze multiprocessing on Windows, to make executables distributable 2.0 - make GladTeX truely platform independent - add formula number in error output; makes tracking of formulas easier in error case - write man page - set css class correctly for display math formulas - HTML label/id generation: - do not create overlong id's - do only generate id's starting with an alphabetical character - squeeze multiple identical characters - reparse outsourced formulas correctly (was a mixture of formatted vs. unformatted formulas) - do not use absolute links when operating on file which is not in current working directory - be more careful with backslashes vs. slashes - allow formulas consisting only of numbers (i.e. example calculations) by prefixing "form_" in front of the HTML id (id must start with a letter but may be followed by digits) - allow removal of unreadable caches with the `-n` switch (extend library with this functionality) - introduce `-m` switch to print the output in a less concise, but more machine-parseable format 1.6 - complete rewrite - rewrite GladTeX fully in Python - allows easy compilation into a binary for a specific platform - comes with a new library to use GladTeX functionality within other applications - fully unit-tested - enable piping support; GladTeX can read from stdin and write to stdout - drop -t switch; image is either transparent by default or has a background color which can be set with -b - drop -s switch - introduce -o (output) option - introduce new cache format containing version numbers; json, so interface to other programming languages 1.5 - Introduce options to make embedding of GladTeX easier - Try to parse LaTeX's error output and display it to help users to find the issue quicker and to make GladTeX better embeddable. - Add option to remove error log file, produced by LaTeX, automatically. - Rewrite some help messages. - Add signal handling to get meaningful error messages if GladTeX hangs. 1.4.2 - bug fix release - Add some eval's to cope with some failures. - Since there were some incompatibilities between Perl 5.10 and 5.18 in how the cache of the generated images is stored, GladTeX now removes this file along with all images starting with "eqn" and generates them again. 1.4.1 - bug fix release - Remove desc.html if created and empty 1.4 - put LaTeX equations into alt tag for text-mode browsers and blind people (and disabled images) - If requested (-a), exclude equations longer than 80 characters in an extra file and make the equation image a link to the longer, excluded image alternative - eqn2img: patch to allow building on windows - Change build system from make to cmake - Refactored gladtex code a lot to allow the usage of "use strict/use warnings" - Fix bug where multiple equations couldn't be on a single (html) line - Rework manpage 1.3 - Un-escape common entities before processing equations - Update man page with CSS class options - Add support for setting the CSS class of images when the environment is "math" or "displaymath" - eqn2img: changed redirection syntax (from dvips to /dev/null) for portability - GladTeX: exit with status 1 when a closing EQ tag is missing - GladTeX: print error messages to stderr instead of stdout - Fix environment-passing to eqn2img - Add support for a "dpi" attribute on EQ tags to customize the DPI used for each equation 1.2 - Fixed a serious memory allocation error, pointed out by Eric J. Francois. Also fixed several leaks. - Added full alpha channel to PNG files (also suggested by Eric) - The -e option was ignored, fixed (pointed out by Andr\'e Schleife) - Added man page, contributed by Volker Schatz 1.1 - Portability fixes: Do not assume a specific location for perl (use "env" in the shebang line) and do not rely on the bash style "&>" redirection. 1.0 - Image alignment workaround (most browsers interpret "ALIGN=MIDDLE" somewhat strangely, so it has been changed to "STYLE=vertical-align: -xx") - Added cache file, so that gladtex doesn't have to regenerate images for equations that haven't changed. - Added ENV option (as in ) to support environments other than "displaymath". - Bug fixes. 0.3 - Added BoundingBox workaround (dvips sometimes outputs wrong BoundingBox, for instance when using \mathbb{}) - Moved the whole "LaTeX eqn to image" conversion into the C code, turning the C program (renamed from pngmodify to eqn2img) into a standalone utility (e.g. echo '\sqrt{2}' | eqn2img -o eqn.png). - Added colour options (-c -b and -t). - Fixed bug causing segfault when adding space _above_ an image. - Fixed image reusing bug (in 0.2 image reuse didn't work across separate files when processing files outside startup cwd). - And some other minor bugs and cosmetic changes. - Makefile added to distribution 0.2 - First official release, completely rewritten code. 0.1 - Used only internally at the Dept. of Mathematics at the Univ. of Oslo July-August 1999 (for the project "Matteknekker'n") under the name htmleqn. # vim: set expandtab sts=4 ts=4 sw=4 expandtab: GladTeX-2.3.1/README.md000066400000000000000000000063311317106144100142650ustar00rootroot00000000000000GladTeX ======= GladTeX is a preprocessor that enables the use of LaTeX formulas within HTML files. The formulas, embedded in ... tags, as if within $$..$$ in LaTeX, is fed through latex and replaced by images. Additionally all images get an alt-tag for alternative texts that contains the LaTeX-equivalent of the image. This is handy for text-mode browsers or blind people. This is a complete rewrite of the old GladTeX which was implemented in Perl and in C. The old version was not easily portable across platforms. The new version is purely implemented in Python, gets rid of the Ghostscript dependency and additionally offers the GladTeX functionality in a Python module called gleetex. to be embedded in other applications. License ------- _Copyright:_ About the old perl version: - (C) 1999-2010 Martin G. Gulbrandsen - (C) 2011-2013 Jonathan Daugherty (especially release 1.3) - (C) 2013-2015 Sebastian Humenda Credits go to - 2013 Patrick Spendrin (patches for cmake and eqn2img to build it on Windows) About the rewritten (current) version: - (c) 2015-2017 Sebastian Humenda - credits go to Martin G. Gulbrandsen who had the idea in the first place This program is distributed under the LGPL-3, or at your option, any later version of the license; for details see the accompanying file COPYING. The official project homepage is at Installation ============ ### Debian/Ubuntu On all derivatives of Debian (as Ubuntu/Mint, etc.), installing GladTeX is as easy as # apt-get install gladtex ### Windows If you want to use the program without the Python library, you should download a pre-compiled binary from . Just unzip the archive and move the files to a directory within `%PATH%`. ### From Source The following is required for installing GladTeX: - Python >= 3.4 - LaTeX (2e), dvipng - the LaTeX package preview.sty On Debian/Ubuntu systems the following commands will satisfy the dependencies: # apt-get install python3-all texlive-fonts-recommended texlive-latex-recommended preview-latex-style dvipng The package can then be installed using # python3 setup.py install Note: If your system ships `python` as the command for Python3 you have to use `python in` the above command instead. ### Compilation On Windows To compile GladTeX on Windows, yu need a Python3 installation. Assumed is python3.4, newer versions should work fine as well. Only the paths need to be adjusted Install py2exe: c:\python34\scripts\pip.exe install py2exe Given that GladTeX is located in c:\users\user\gladtex: cd c:\users\user\gladtex c:\python34\python.exe setup.py install That will install GladTeX as a library to `c:\python34\lib` and the script to `c:\python34\scripts`. It also allows py2exe to find the gleetex module. Now the executable can be build: c:\python34\scripts\build_exe.exe -b 0 -c gladtex.py That'll create a `dist/` folder containing the executable. If you have other python applications in your project it is useful to read about the `-b` switch to share some python components included in the just-built executable. Documentation ------------- Please use `man gladtex` for further instructions. GladTeX-2.3.1/ToDo.FAQ000066400000000000000000000005431317106144100142030ustar00rootroot00000000000000A few items which could go into a FAQ: What do the error messages mean? Why is my formula positioned awkardly within the text? (most probably displaymath instead of inline math) Why are limits over sums and similar not correctly set? (use displaymath, sometimes `\\limits`) Why don't my special characters like (unicode) math symbols or umlauts not work GladTeX-2.3.1/ToDo.md000066400000000000000000000013731317106144100141760ustar00rootroot00000000000000To Do ===== This list contains things to be implemented in GladTeX. If you have additions or even feel like you want to do it, feel free to drop me an email: `shumenda |aT| gmx //dot-- de`. Uncategorized ------------- - introduce command line option which will check whether all all formulas in a cache are used and if not, remove the formula (only useful for caches corresponding to a single document) Gettext ------- Gettext should be integrated to localize messages (especially errors). Compressed Cache ---------------- The cache stores the path, the formula and the positioning of an image. For large documents, this might be quite big, hence it makes sense to compress them. To make things easier, the cache should have a .gz extension. GladTeX-2.3.1/create_windows_distributions.py000066400000000000000000000132701317106144100213570ustar00rootroot00000000000000""" This file builds windows distributions, zip files with GladTeX and all other files.""" import os import shutil import stat import sys import zipfile import gleetex def exec_setup_py(arg_string): """Execute `python setup.py` as a subprocess. Use Wine, if necessary.""" ret = None if sys.platform.startswith('win'): ret = os.system('python setup.py ' + arg_string) else: if not shutil.which('wine'): print("Error: Wine is not installed, aborting…") sys.exit(5) ret = os.system('wine python setup.py ' + arg_string) if ret: if sys.platform.startswith('win'): print("Aborting at command `python setup.py %s`." % arg_string) else: print("Aborting at command `wine python setup.py %s`." % arg_string) sys.exit(7) def get_python_version(): """Return the python version as a string.""" import re, subprocess args = ['python', '--version'] if not sys.platform.startswith('win'): args = ['wine'] + args proc = subprocess.Popen(args, stdout=subprocess.PIPE) stdout = proc.communicate()[0].decode(sys.getdefaultencoding()) if proc.wait(): raise TypeError("Abnormal subprocess termination while querying python version.") return re.search(r'.*?(\d+\.\d+\.\d+)', stdout).groups()[0] def get_executable_name(label): """Construct the name of an executable""" return 'gladtex-win64-%s-py_%s-%s.zip' % (gleetex.VERSION, get_python_version(), label) def bundle_files(src, output_name): """Bundle the compiled binary files with README, ChangeLog and COPYING.""" if os.path.exists(output_name): shutil.rmtree(output_name) os.rename(src, output_name) # add README.first with open(os.path.join(output_name, 'README.first.txt'), 'w') as f: f.write('GladTeX for Windows\r\n===================\r\n\r\n') f.write('This program has been compiled with python 3.4.4. If you want to embedd it in binary form with your binary python application, the version numbers HAVE TO match.\r\n') f.write('\r\nFor more information, see the file README.md or http://humenda.github.io/GladTeX\r\n') # copy README and other files for file in ['README.md', 'COPYING', 'ChangeLog']: dest = os.path.join(output_name, file) # check whether file ending exists if not '.' in dest[-5:]: dest += '.txt' shutil.copy(file, dest) files = [os.path.join(root, file) for root, _, files in os.walk(output_name) for file in files] with zipfile.ZipFile(output_name + '.zip', 'w', zipfile.ZIP_DEFLATED) as z: for file in files: z.write(file) shutil.rmtree(output_name) class TemporaryBuildDirectory(): """Context handler to guard the build process. Upon entering the context, the source is copied to a temporary directory and the program changes to this directory. After all build actions have been done, the output file is copied back to the original directory, the program resets the current working directory and deletes the temporary directory.""" def __init__(self, output_file_name): self.orig_cwd = os.getcwd() self.tmpdir = None self.output_file_name = output_file_name def __enter__(self): self.tmpdir = self.get_temp_directory() shutil.copytree(os.getcwd(), self.tmpdir) os.chdir(self.tmpdir) return self def __exit__(self, _a, _b, _c): os.chdir(self.orig_cwd) shutil.copy(os.path.join(self.tmpdir, self.output_file_name), self.output_file_name) shutil.rmtree(self.tmpdir, onerror=self.__onerror) def get_temp_directory(self): """Find a temporary directory to work in. The checks are done to find a directory which does not reside within the user's path, because py2exe includes absolute paths for python scripts (in their tracebacks). It is not desirable to show the whole world the directory layout of the computer where the source code was built on.""" tmp_base = None if os.path.exists('/tmp'): tmp_base = '/tmp' elif os.path.exists('\\temp'): tmp_base = '\\temp' elif os.path.exists('\\windows\\temp'): tmp_base = '\\windows\\temp' else: import tempfile tmp_base = tempfile.gettempdir() tmpdir = os.path.join(tmp_base, 'gladtex.build') if os.path.exists(tmpdir): shutil.rmtree(tmpdir, onerror=self.__onerror) return tmpdir def __onerror(self, func, path, exc_info): """ Error handler for ``shutil.rmtree``. If the error is due to an access error (read only file) it attempts to add write permission and then retries. If the error is for another reason it re-raises the error. Usage : ``shutil.rmtree(path, onerror=onerror)``.""" if not os.access(path, os.W_OK): # Is the error an access error ? os.chmod(path, stat.S_IWUSR) func(path) else: raise exc_info if __name__ == '__main__': with TemporaryBuildDirectory(get_executable_name('embeddable')) as tb: # build embeddable release, where all files are separate DLL's; if somebody # distributes a python app, these DLL files can be shared exec_setup_py('py2exe -c -O 2 -i gleetex --bundle-files 3') bundle_files('dist', os.path.splitext(tb.output_file_name)[0]) # create a stand-alone version of GladTeX with TemporaryBuildDirectory(get_executable_name('standalone')) as tb: exec_setup_py('py2exe -i gleetex -c -O 2 --bundle-files 1') bundle_files('dist', os.path.splitext(tb.output_file_name)[0]) GladTeX-2.3.1/gladtex.py000066400000000000000000000352651317106144100150200ustar00rootroot00000000000000#!/usr/bin/env python3 import argparse import multiprocessing import os import posixpath import re import sys import gleetex class HelpfulCmdParser(argparse.ArgumentParser): """This variant of arg parser always prints the full help whenever an error occurs.""" def error(self, message): sys.stderr.write('error: %s\n' % message) self.print_help() sys.exit(2) def format_ordinal(number): endings = ['th', 'st', 'nd', 'rd'] + ['th'] * 6 return '%d%s' % (number, endings[number%10]) class Main: """This class parses command line arguments and deals with the conversion. Only the run method needs to be called.""" def __init__(self): self.__encoding = "utf-8" def _parse_args(self, args): """Parse command line arguments and return option instance.""" epilog = "GladTeX %s, http://humenda.github.io/GladTeX" % gleetex.VERSION description = ("GladTeX is a preprocessor that enables the use of LaTeX" " maths within HTML files. The maths, embedded in ... " "tags, as if within \\(..\\) in LaTeX (or $...$ in TeX), is fed " "through latex and replaced by images.\n\nIf the environment " "variable `DEBUG=1`is set, a full Python traceback, instead of a " "short, user-friendly message, will be shown.") parser = HelpfulCmdParser(epilog=epilog, description=description) parser.add_argument("-a", action="store_true", dest="exclusionfile", help="save text alternatives " + "for images which are too long for the alt attribute into a " + "single separate file and link images to it") parser.add_argument('-b', dest='background_color', help="Set background color for resulting images (default transparent)") parser.add_argument('-c', dest='foreground_color', help="Set foreground color for resulting images (default 0,0,0)") parser.add_argument('-d', dest='directory', help="Directory in which to" + " store generated images in (relative path)") parser.add_argument('-e', dest='latex_maths_env', help="Set custom maths environment to surround the formula" + \ " (e.g. flalign)") parser.add_argument('-E', dest='encoding', default=None, help="Overwrite encoding to use (default UTF-8)") parser.add_argument('-i', metavar='CLASS', dest='inlinemath', help="CSS class to assign to inline math (default: 'inlinemath')") parser.add_argument('-l', metavar='CLASS', dest='displaymath', help="CSS class to assign to block-level math (default: 'displaymath')") parser.add_argument('-K', dest='keep_latex_source', action="store_true", default=False, help="keep LaTeX file(s) when converting formulas (useful for debugging)") parser.add_argument('-m', dest='machinereadable', action="store_true", default=False, help="Print output in machine-readable format (less concise, better parseable)") parser.add_argument("-n", action="store_true", dest="notkeepoldcache", help=("Purge unreadable caches along with all eqn*.png files. " "Caches can be unreadable if the used GladTeX version is " "incompatible. If this option is unset, GladTeX will " "simply fail when the cache is unreadable.")) parser.add_argument('-o', metavar='FILENAME', dest='output', help=("Set output file name; '-' will print text to stdout (by" "default input file name is used and .htex extension changed " "to .html)")) parser.add_argument('-p', metavar='LATEX_STATEMENT', dest="preamble", help="Add given LaTeX code to preamble of document; that'll " +\ "affect the conversion of every image") parser.add_argument('-r', metavar='DPI', dest='dpi', default='115', help=("Set resolution (size of images) to 'dpi' (115 for a " "fontsize of 12pt); if the suffix 'pt' is added, the " "resolution wil be calculated from the given font size.")) parser.add_argument('-R', action="store_true", dest='replace_nonascii', default=False, help="Replace non-ascii characters in formulas " "through their LaTeX commands") parser.add_argument("-u", metavar="URL", dest='url', help="URL to image files (relative links are default)") parser.add_argument('input', help="Input .htex file with LaTeX " + "formulas (if omitted or -, stdin will be read)") return parser.parse_args(args) def exit(self, text, status): """Exit function. Could be used to register any clean up action.""" sys.stderr.write(text) if not text.endswith('\n'): sys.stderr.write('\n') sys.exit(status) def validate_options(self, opts): """Validate certain arguments suppliedon the command line. The user will get a (hopefully) helpful error message if he/she gave an invalid parameter.""" color_regex = re.compile(r"^\d(?:\.\d+)?,\d(?:\.\d+)?,\d(?:\.\d+)?") if opts.background_color and not color_regex.match(opts.background_color): print("Option -b requires a string in the format " + "num,num,num where num is a broken decimal between 0 " + "and 1.") sys.exit(12) if opts.foreground_color and not color_regex.match(opts.foreground_color): print("Option -c requires a string in the format " + "num,num,num where num is a broken decimal between 0 " + "and 1.") sys.exit(13) def get_input_output(self, options): """Determine whether GladTeX is reading from stdin/file, writing to stdout/file and determine base_directory if files are in another directory. If no output file name is given and there is a input file to read from, output is written to a file ending on .html instead of .htex. The returned document is either string or byte, the latter if encoding is unknown.""" data = None base_path = options.directory output = '-' if options.input == '-': data = sys.stdin.read() else: try: if options.encoding: with open(options.input) as f: data = f.read() else: # read as binary and guess from HTML meta charset with open(options.input, 'rb') as file: data = file.read() except UnicodeDecodeError as e: self.exit(('Error while reading from %s: %s\nProbably this file' ' has a different encoding, try specifying -E.') % \ (options.input, str(e)), 88) except IsADirectoryError: self.exit("Error: cannot open %s for reading: is a directory." \ % options.input, 19) except FileNotFoundError: self.exit("Error: file %s not found." % options.input, 20) # check which output file name to use if options.output: output = options.output elif options.input != '-': output = os.path.splitext(options.input)[0] + '.html' # else case: output = '-' (see above) if not base_path: if options.output and os.path.dirname(options.output): base_path = os.path.dirname(output) elif options.input and os.path.dirname(options.input): base_path = os.path.dirname(input) if base_path: # if finally a basepath found:, strip \\ if on Windows base_path = posixpath.join(*(options.directory.split('\\'))) # strip base_path from output, if there's one output = os.path.basename(output) return (data, base_path, output) def run(self, args): options = self._parse_args(args[1:]) self.validate_options(options) self.__encoding = options.encoding doc, base_path, output = self.get_input_output(options) docparser = gleetex.htmlhandling.EqnParser() try: docparser.feed(doc) self.__encoding = docparser.get_encoding() self.__encoding = (self.__encoding if self.__encoding else 'utf-8') except gleetex.htmlhandling.ParseException as e: input_fn = ('stdin' if options.input == '-' else options.input) self.exit('Error while parsing {}: {}'.format(input_fn, str(e)), 5) doc = docparser.get_data() processed = self.convert_images(doc, base_path, options) with gleetex.htmlhandling.HtmlImageFormatter(base_path=base_path, link_path=options.url) as img_fmt: img_fmt.set_exclude_long_formulas(True) if options.replace_nonascii: img_fmt.set_replace_nonascii(True) if options.url: img_fmt.set_url(options.url) if options.inlinemath: img_fmt.set_inline_math_css_class(options.inlinemath) if options.displaymath: img_fmt.set_display_math_css_class(options.displaymath) if output == '-': self.write_html(sys.stdout, processed, img_fmt) else: with open(output, 'w', encoding=self.__encoding) as file: self.write_html(file, processed, img_fmt) def write_html(self, file, processed, formatter): """Write back altered HTML file with given formatter.""" # write data back for chunk in processed: if isinstance(chunk, dict): is_displaymath = chunk['displaymath'] file.write(formatter.format(chunk['pos'], chunk['formula'], chunk['path'], is_displaymath)) else: file.write(chunk) def convert_images(self, parsed_htex_document, base_path, options): """Convert all formulas to images and store file path and equation in a list to be processed later on.""" base_path = ('' if not base_path or base_path == '.' else base_path) result = [] try: conv = gleetex.convenience.CachedConverter(base_path, not options.notkeepoldcache, encoding=self.__encoding) except gleetex.caching.JsonParserException as e: self.exit(e.args[0], 78) self.set_options(conv, options) formulas = [c for c in parsed_htex_document if isinstance(c, (tuple, list))] try: conv.convert_all(base_path, formulas) except gleetex.convenience.ConversionException as e: self.emit_latex_error(e, options.machinereadable, options.replace_nonascii) # iterate over chunks of eqnparser for chunk in parsed_htex_document: # chunk == an entity parsed by EqnParser; type 'str' will be taken # literally, 'list' will be treated as formula if isinstance(chunk, (tuple, list)): _p, displaymath, formula = chunk try: data = conv.get_data_for(formula, displaymath) except KeyError as e: raise KeyError(("formula '%s' not found; that means it was " "not converted which should usually not happen.") % e.args[0]) data['formula'] = formula data['displaymath'] = displaymath result.append(data) else: result.append(chunk) return result def set_options(self, conv, options): """Apply options from command line parser to the converter.""" # set options options_to_query = ['preamble', 'latex_maths_env', 'keep_latex_source'] for option_str in options_to_query: option = getattr(options, option_str) if option: if option in ('True', 'False', 'false', 'true'): option = option == 'True' conv.set_option(option_str, option) dpi = None if options.dpi.endswith('pt'): dpi = gleetex.image.fontsize2dpi(float(options.dpi[:-2])) else: dpi = float(options.dpi) conv.set_option("dpi", dpi) # colors need special handling for option_str in ['foreground_color', 'background_color']: option = getattr(options, option_str) if option: conv.set_option(option_str, tuple(map(float, option.split(',')))) if options.replace_nonascii: conv.set_replace_nonascii(True) def emit_latex_error(self, err, machine_readable, escape): """Format a LaTeX error in a meaningful way. The argument escape speicifies, whether the -R switch had been passed.""" if 'DEBUG' in os.environ and os.environ['DEBUG'] == '1': raise err escaped = err.formula if escape: escaped = gleetex.document.escape_unicode_in_formulas(err.formula) msg = None additional = '' if 'Package inputenc' in err.args[0]: additional += ('Add the switch `-R` to automatically replace unicode ' 'characters with LaTeX command sequences.') if machine_readable: msg = 'Line: {}, {}\nNumber: {}\nFormula: {}{}\nMessage: {}'.format( err.src_line_number, err.src_pos_on_line, err.formula_count, err.formula, ('' if escaped == err.formula else '\nLaTeXified formula: %s' % escaped), err.cause) if additional: msg += '; ' + additional else: formula = ' ' + err.formula.replace('\n', '\n ') escaped = (' ' + escaped.replace('\n', '\n ') if escaped != err.formula else '') msg = "Error while converting formula %d at line %d, %d:\n" %\ (err.formula_count, err.src_line_number, err.src_pos_on_line,) msg += '%s%s\n%s' % (formula, ('' if escaped == err.formula else '\nFormula without unicode symbols:\n%s' % escaped), err.cause) if additional: import textwrap msg += ' undefined.\n' + '\n'.join(textwrap.wrap(additional, 80)) self.exit(msg, 91) if __name__ == '__main__': # enable multiprocessing on Windows, see python docs multiprocessing.freeze_support() m = Main() m.run(sys.argv) GladTeX-2.3.1/gleetex/000077500000000000000000000000001317106144100144405ustar00rootroot00000000000000GladTeX-2.3.1/gleetex/__init__.py000066400000000000000000000003621317106144100165520ustar00rootroot00000000000000from . import caching from . import convenience from . import document from . import htmlhandling from . import image VERSION = '2.3.1' __all__ = ['caching', 'convenience', 'document', 'htmlhandling', 'image', 'unicode', 'VERSION'] GladTeX-2.3.1/gleetex/caching.py000066400000000000000000000227541317106144100164200ustar00rootroot00000000000000"""This module contains the ImageCache, which caches formulas which have already been converted. Only with this mechanism, a formula which occurs multiple times can be reused, even across several runs of GladTeX. Cache format: { # dict of formulas 'some formula': # formula as key into dictionary { # list of display math / inline maths variants True: # displaymath = True { # dictionary of values describing formula 'path': 'some/path' 'pos': { # positioning within the HTML document 'height': ..., 'width':..., 'depth:.... } } } } } Formulas are `normalized`, so spacing is unified to detect possibly equal formulas more easyly. """ import json import os CACHE_VERSION = '2.0' def normalize_formula(formula): """This function normalizes a formula. This e.g. means that multiple white spaces are squeezed into one and a tab will be replaced by a space. With this it is more realistic that a recurring formula in a document is detected as such, even though if it might have been written with different spacing. Empty braces ({}) are removed as well.""" return formula.replace('{}', ' ').replace('\t', ' ').replace(' ', ' '). \ rstrip().lstrip() def recover_bools(object): """After JSon is read from disk, keys as False or True have been serialized to 'false' and 'true', but they're not recovered by the json parser. This function alters converts these keys back to booleans; note: it only works with references, so this function doesn't return anything.""" if isinstance(object, dict): for key in ['false', 'true']: if key in object: val = object[key] # store value object[key == 'true'] = val # safe it with boolean representation del object[key] # remove string key # iterate recursively through dict for value in object.values(): recover_bools(value) if isinstance(object, list): for item in object: recover_bools(item) class JsonParserException(Exception): """Specialized exception class for handling errors while parsing the JSON cache.""" pass class ImageCache: """ This cache stores formulas which have been converted already and don't need to be converted again. This is both a disk usage and performance improvement. The cache can be written and read from disk. If the argument keep_old_cache is True, the cache will raise a JsonParserException if that file could not be read (i.e. incompatible GladTeX version). If set to False, it'll discard the cache along with all eqn* files and start with a clean cache. cache = ImageCache() c.add_formula('\\tau', # the formulas {'height': 1, 'depth': 2, 'width='3'}, # the positioning information for the output document 'eqn042.png', displaymath=True): assert len(cache) == 1 # one entry c.write() assert os.path.exists('gladtex.cache') """ VERSION_STR = 'GladTeX__cache__version' def __init__(self, path='gladtex.cache', keep_old_cache=True): self.__cache = {} self.__set_version(CACHE_VERSION) self.__path = path if os.path.exists(path): try: self._read() except JsonParserException: if keep_old_cache: raise else: self._remove_old_cache_and_files() def __len__(self): """Return number of formulas in the cache.""" # ignore version return len(self.__cache) - 1 def __set_version(self, version): """Set version of cache (data structure format).""" self.__cache[ImageCache.VERSION_STR] = version def write(self): """Write cache to disk. The file name will be the one configured during initialisation of the cache.""" if len(self.__cache) == 0: return with open(self.__path, 'w', encoding='UTF-8') as file: file.write(json.dumps(self.__cache)) def _read(self): """Read Json from disk into cache, if file exists. :raises JsonParserException if json could not be parsed""" def raise_error(msg): raise JsonParserException(msg + "\nPlease delete the cache (and" + \ " the images) and rerun the program.") if os.path.exists(self.__path): #pylint: disable=broad-except try: with open(self.__path, 'r', encoding='utf-8') as file: self.__cache = json.load(file) except Exception as e: msg = "error while reading cache from %s: " % os.path.abspath(self.__path) if isinstance(e, (ValueError, OSError)): msg += str(e.args[0]) elif isinstance(e, UnicodeDecodeError): msg += 'expected UTF-8 encoding, erroneous byte ' + \ '{0} at {1}:{2} ({3})'.format(*(e.args[1:])) else: msg += str(e.args[0]) raise_error(msg) if not isinstance(self.__cache, dict): raise_error("Decoded Json is not a dictionary.") if not self.__cache.get(ImageCache.VERSION_STR): self.__set_version(CACHE_VERSION) cur_version = self.__cache.get(ImageCache.VERSION_STR) if cur_version != CACHE_VERSION: raise_error("Cache in %s has version %s, expected %s." % \ (self.__path, cur_version, CACHE_VERSION)) recover_bools(self.__cache) def _remove_old_cache_and_files(self): os.remove(self.__path) directory = os.path.split(self.__path)[0] if not directory: directory = '.' # remove all files starting with eqn* for file in os.listdir(directory): if not file.startswith('eqn'): continue file = os.path.join(directory, file) if os.path.isfile(file): os.remove(file) def add_formula(self, formula, pos, file_path, displaymath=False): """Add formula to cache. The pos argument contains the positioning info for the output document and is a dict with 'height', 'width' and 'depth'. Keep in mind that formulas set with displaymath are not the same as those set iwth inlinemath. This method raises OSError if specified image doesn't exist or if it got an absolute file_path.""" if not pos or not formula or not file_path: raise ValueError("the supplied arguments may not be empty/none") if not isinstance(displaymath, bool): raise ValueError("displaymath must be a boolean") if os.path.isabs(file_path): raise OSError("The file path to the image may NOT be an absolute path") if '\\' in file_path: file_path = file_path.replace('\\', '/') if not os.path.exists(file_path): # could be that the current working directory is different test_path = os.path.join(os.path.split(self.__path)[0], os.path.split(file_path)[1]) if not os.path.exists(test_path): raise OSError("cannot add %s to the cache: doesn't exist" % file_path) formula = normalize_formula(formula) if not formula in self.__cache: self.__cache[formula] = {} val = self.__cache[formula] if not displaymath in val: val[displaymath] = {'pos' : pos, 'path' : file_path} def remove_formula(self, formula, displaymath): """This method removes the given formula from the cache. A KeyError is raised, if the formula did not exist. Internally, formulas are normalized to detect similarities.""" formula = normalize_formula(formula) if not formula in self.__cache: raise KeyError("key %s not in cache" % formula) else: value = self.__cache[formula] if displaymath in value: del self.__cache[formula] else: raise KeyError("key %s (%s) not in cache" % (formula, displaymath)) def contains(self, formula, displaymath): """Check whether a formula was already cached and return True if found.""" try: return bool(self.get_data_for(formula, displaymath)) except KeyError: return False def get_data_for(self, formula, displaymath): """ Retrieve meta data about a formula from the cache. The meta information is used to embed the formula in the HTML document. It is a dictionary with the keys 'pos' and 'path'. The positioning info is described in the documentation of this class. This method raises a KeyError if the formula wasn't found.""" formula = normalize_formula(formula) if not formula in self.__cache: raise KeyError(formula, displaymath) else: # check whether file still exists value = self.__cache[formula] if displaymath in value.keys(): if not os.path.exists(value[displaymath]['path']): del self.__cache[formula] raise KeyError((formula, displaymath)) else: return value[displaymath] else: raise KeyError((formula, displaymath)) GladTeX-2.3.1/gleetex/convenience.py000066400000000000000000000234571317106144100173210ustar00rootroot00000000000000"""In order to convert images only if they are not already cached, the cached converter sacrifices customizability for convenience and provides a class converting a formula directly to a png file.""" import concurrent.futures import multiprocessing import os import subprocess from . import caching, document, image from .caching import normalize_formula class ConversionException(Exception): """This exception is raised whenever a problem occurs during conversion. Example: c = ConversionException("cause", "\\tau", 10, 38, 5) assert c.cause == cause assert c.formula == '\\tau' assert c.src_line_number == 10 # line number in source document (counting from 1) assert c.src_pos_on_line == 38 # position of formula in source line, counting from 1 assert c.formula_count == 5 # fifth formula in document (starting from 1) """ # mind your own business: #pylint: disable=too-many-arguments def __init__(self, cause, formula, src_line_number, src_pos_on_line, formula_count): # provide a default error message super().__init__("LaTeX failed at formula line {}, {}, no. {}: {}".format( src_line_number, src_pos_on_line, formula_count, cause)) # provide attributes for upper level error handling self.cause = cause self.formula = formula self.src_line_number = src_line_number self.src_pos_on_line = src_pos_on_line self.formula_count = formula_count class CachedConverter: """Convert formulas to images. c = CachedConverter(base_path) for formula in [... formulas ...]: pos, file_path = c.convert(formula) ... The formula is either converted or retrieved from a cache in the same directory like the images. :param base_path directory to place files in (relative to the file converted. So if the file being converted is foo/bar.htex and the base_path is set to img, the image will be placed in foo/img/. :param keep_old_cache If an existing cache cannot be read (incompatible GladTeX version, ...) Aand the flag is set, the program will simply crash and tell the user to remove the cache (default). If set to False, the program will instead remove the cache and all eqn* files and recreate the cache. :param encoding The encoding for the LaTeX document, default None """ GLADTEX_CACHE_FILE_NAME = 'gladtex.cache' _converter = image.Tex2img # can be statically altered for testing purposes def __init__(self, base_path, keep_old_cache=True, encoding=None): if base_path and not os.path.exists(base_path): os.makedirs(base_path) cache_path = os.path.join(base_path, CachedConverter.GLADTEX_CACHE_FILE_NAME) self.__cache = caching.ImageCache(cache_path, keep_old_cache=keep_old_cache) self.__options = {'dpi' : None, 'transparency' : None, 'background_color' : None, 'foreground_color' : None, 'preamble' : None, 'latex_maths_env' : None, 'keep_latex_source': False} self.__encoding = encoding self.__replace_nonascii = False def set_option(self, option, value): """Set one of the options accepted for gleetex.image.Tex2img. `option` must be one of dpi, transparency, background_color, foreground_color, preamble, latex_maths_env, keep_latex_source.""" if not option in self.__options.keys(): raise ValueError("Option must be one of " + \ ', '.join(self.__options.keys())) self.__options[option] = value def set_replace_nonascii(self, flag): """If set, GladTeX will convert all non-ascii character to LaTeX commands. This setting is passed through to document.LaTeXDocument.""" self.__replace_nonascii = flag def convert_all(self, base_path, formulas): """convert_all(formulas) Convert all formulas using self.convert concurrently. Each element of `formulas` must be a tuple containing (formula, displaymath, Formulas already contained in the cache are not converted. """ formulas_to_convert = self._get_formulas_to_convert(base_path, formulas) self._convert_concurrently(formulas_to_convert) def _get_formulas_to_convert(self, base_path, formulas): """Return a list of formulas to convert, along with their count in the global list of formulas of the document being converted and the file name. Function was decomposed for better testability.""" formulas_to_convert = [] # find as many file names as equations eqn_path = lambda x: os.path.join(base_path, 'eqn%03d.png' % x) # is (formula, display_math) already in the list of formulas to convert; # displaymath is important since formulas look different in inline maths formula_was_converted = lambda f, dsp: (normalize_formula(f), dsp) in \ ((normalize_formula(u[0]), u[3]) for u in formulas_to_convert) # find enough free file names file_name_count = 0 used_file_names = [] # track which file names have been assigned for formula_count, (pos, dsp, formula) in enumerate(formulas): if not self.__cache.contains(formula, dsp) and \ not formula_was_converted(formula, dsp): while os.path.exists(eqn_path(file_name_count)) or \ eqn_path(file_name_count) in used_file_names: file_name_count += 1 used_file_names.append(eqn_path(file_name_count)) formulas_to_convert.append((formula, pos, eqn_path(file_name_count), dsp, formula_count + 1)) return formulas_to_convert def _convert_concurrently(self, formulas_to_convert): """The actual concurrent conversion process. Method is intended to be called from convert_all().""" # use roughly 2,5 * number of processors as amount of threads (I/O # bound); but don't overdo it with fivetimes like the thread pool does # it (gladtex might be in turn run in parallel on a machine) thread_count = int(multiprocessing.cpu_count() * 2.5) # convert missing formulas with concurrent.futures.ThreadPoolExecutor(max_workers=thread_count) as executor: # start conversion and mark each thread with its formula, position # in the source file and formula_count (index into a global list of # formulas) jobs = {executor.submit(self.convert, eqn, path, dsp): (eqn, pos, count) for (eqn, pos, path, dsp, count) in formulas_to_convert} error_occurred = None for future in concurrent.futures.as_completed(jobs): if error_occurred and not future.done(): future.cancel() continue formula, pos_in_src, formula_count = jobs[future] try: data = future.result() except subprocess.SubprocessError as e: if 'inputenc Error' in e.args[0]: print("piep") # retrieve the position (line, pos on line) in the source # document from original formula list pos_in_src = list(p+1 for p in pos_in_src) # user expects lines/pos_in_src' to count from 1 self.__cache.write() # write back cache with valid entries error_occurred = ConversionException(str(e.args[0]), formula, pos_in_src[0], pos_in_src[1], formula_count) else: self.__cache.add_formula(formula, data['pos'], data['path'], data['displaymath']) self.__cache.write() #pylint: disable=raising-bad-type if error_occurred: raise error_occurred def convert(self, formula, output_path, displaymath=False): """convert(formula, output_path, displaymath=False) Convert given formula with displaymath/inlinemath. This method wraps the formula in a tex document, executes all the steps to produce a PNG file and return the positioning information as given by dvipng. :param formula formula to convert :param output_path image output path :param displaymath whether or not to use displaymath during the conversion :return dictionary with position (pos), image path (path) and formula style (displaymath, boolean) as a dictionary with the keys in parenthesis """ latex = document.LaTeXDocument(formula) latex.set_displaymath(displaymath) if self.__options['preamble']: # add preamble to LaTeX document latex.set_preamble_string(self.__options['preamble']) if self.__options['latex_maths_env']: latex.set_latex_environment(self.__options['latex_maths_env']) if self.__encoding: latex.set_encoding(self.__encoding) if self.__replace_nonascii: latex.set_replace_nonascii(True) try: latex_str = str(latex) except ValueError as e: # propagate error raise ConversionException(e.args[0], formula, 0, 0, 0) conv = self._converter(latex_str, output_path) # apply configured image output options for option, value in self.__options.items(): if value and hasattr(conv, 'set_' + option): getattr(conv, 'set_' + option)(value) conv.convert() pos = conv.get_positioning_info() return {'pos' : pos, 'path' : output_path, 'displaymath' : displaymath} def get_data_for(self, formula, display_math): """Simple wrapper around ImageCache.""" return self.__cache.get_data_for(formula, display_math) GladTeX-2.3.1/gleetex/document.py000066400000000000000000000250041317106144100166310ustar00rootroot00000000000000""" This module wraps a formula in a LaTeX document. With this module, a formula can be turned into a convertable document. It also offers methods to escape non-ascii characters, so that formulas with unicode math or umlauts, etc. can be converted. """ from . import unicode class DocumentSerializationException(Exception): """This error is raised whenever a non-ascii character contained in a formula could not be replaced by a LaTeX command. It provides the following attributes: formula - the formula index - position in formula upoint - unicode point.""" def __init__(self, formula, index, upoint): self.formula = formula self.index = index self.upoint = upoint super().__init__(formula, index, upoint) def __str__(self): return ("could not find LaTeX replacement command for unicode " "character %d, index %d in formula %s") % (self.upoint, self.index, self.formula) def escape_unicode_in_formulas(formula, replace_alphabeticals=True): """This function uses the unicode table to replace any non-ascii character (identified with its unicode code point) with a LaTeX command. It also parses the formula for commands as e.g. \\\text or \\mbox and applies text-mode commands within them.""" if not any(ord(ch) > 160 for ch in formula): return formula # no umlauts, no replacement # characters in math mode need a different replacement than in text mode. # Therefore, the string has to be split into parts of math and text mode. chunks = [] if not ('\\text' in formula or '\\mbox' in formula): # no text mode, so tread a chunks = [formula] else: start = 0 while '\\text' in formula[start:] or '\\mbox' in formula[start:]: index = formula[start:].find('\\text') if index < 0: index = formula[start:].find('\\mbox') opening_brace = formula[start + index:].find('{') + start + index # add text before text-alike command and the command itself to chunks chunks.append(formula[start:opening_brace]) closing_brace = get_matching_brace(formula, opening_brace) # add text-mode stuff chunks.append(formula[opening_brace:closing_brace + 1]) start = closing_brace + 1 # add last chunk chunks.append(formula[start:]) is_math = True for index, chunk in enumerate(chunks): try: chunks[index] = replace_unicode_characters(chunk, is_math, replace_alphabeticals=replace_alphabeticals) except ValueError as e: # unicode point missing index = int(e.args[0]) raise DocumentSerializationException(formula, index, ord(formula[index])) from None is_math = not is_math return ''.join(chunks) def replace_unicode_characters(characters, is_math, replace_alphabeticals=True): """Replace all non-ascii characters within the given string with their LaTeX equivalent. The boolean is_math indicates, whether text-mode commands (like in \\text{}) or the amsmath equivalents should be used. When replace_alphabeticals is False, alphabetical characters will not be replaced through their LaTeX command when in text mode, so that text within \\text{} (and similar) is not garbled. For instance, \\text{für} is be replaced by \\text{f\"{u}r} when replace_alphabeticals=True. This is useful for the alt attribute of an image, where the reader might want to read the normal text as such. This function raises a ValueError if a unicode point is not in the table. The first argument of the ValueError is the index within the string, where the unknown unicode character has been encountered.""" result = [] for idx, character in enumerate(characters): if ord(character) < 168: # ignore normal ascii character and unicode control sequences result.append(character) # treat alphanumerical characters differently when in text mode, see doc # string; don't replace alphabeticals if specified elif character.isalpha() and not replace_alphabeticals: result.append(character) else: mode = (unicode.LaTeXMode.mathmode if is_math else unicode.LaTeXMode.textmode) commands = unicode.unicode_table.get(ord(character)) if not commands: # unicode point missing in table # is catched one level above; provide index for more concise error output raise ValueError(characters.index(character)) # if math mode and only a text alternative exists, add \\text{} # around it if mode == unicode.LaTeXMode.mathmode and mode not in commands: result.append('\\text{%s}' % commands[unicode.LaTeXMode.textmode]) else: result.append(commands[mode]) # if the next character is alphabetical, add space if (idx+1) < len(characters) and characters[idx+1].isalpha() \ and commands[mode][-1].isalpha(): result.append(' ') return ''.join(result) def get_matching_brace(string, pos_of_opening_brace): if string[pos_of_opening_brace] != '{': raise ValueError("index %s in string %s: not a opening brace" % \ (pos_of_opening_brace, repr(string))) counter = 1 for index, ch in enumerate(string[pos_of_opening_brace + 1:]): if ch == '{': counter += 1 elif ch == '}': counter -= 1 if counter == 0: return pos_of_opening_brace + index + 1 if counter != 0: raise ValueError("Unbalanced braces in formula " + repr(string)) class LaTeXDocument: """This class represents a LaTeX document. It is intended to contain an equation as main content and properties to customize it. Its main purpose is to provide a str method which will serialize it to a full LaTeX document.""" def __init__(self, eqn): self.__encoding = None self.__equation = eqn self.__displaymath = False self._preamble = '' self.__maths_env = None self.__replace_nonascii = False def set_replace_nonascii(self, flag): """If True, all non-ascii character will be replaced through a LaTeX command.""" self.__replace_nonascii = flag def set_latex_environment(self, env): """Set maths environment name like `displaymath` or `flalign*`.""" self.__maths_env = env def get_latex_environment(self): return self.__maths_env def get_encoding(self): """Return encoding for the document (or None).""" return self.__encoding def set_preamble_string(self, p): """Set the string to add to the preamble of the LaTeX document.""" self._preamble = p def set_encoding(self, encoding): """Set the encoding as used by the inputenc package.""" if encoding.lower().startswith('utf') and '8' in encoding: self.__encoding = 'utf8' elif (encoding.lower().startswith('iso') and '8859' in encoding) or \ encoding.lower() == 'latin1': self.__encoding = 'latin1' else: # if you plan to add an encoding, you have to adjust the str # function, which also loads the fontenc package raise ValueError(("Encoding %s is not supported at the moment. If " "you want to use LaTeX 2e, you should report a bug at the home " "page of GladTeX.") % encoding) def set_displaymath(self, flag): """Set whether the formula is set in displaymath.""" if not isinstance(flag, bool): raise TypeError("Displaymath parameter must be of type bool.") self.__displaymath = flag def is_displaymath(self): return self.__displaymath def _get_encoding_preamble(self): # first check whether there are umlauts within the formula and if so, an # encoding has been set if any(ord(ch) > 128 for ch in self.__equation) and \ not self.__replace_nonascii: if not self.__encoding: raise ValueError(("No encoding set, but non-ascii characters " "present. Please specify an encoding.")) encoding_preamble = '' if self.__encoding: # try to guess language and hence character set (fontenc) import locale language = locale.getdefaultlocale() if language and language[0]: # extract just the language code language = language[0].split('_')[0] if not language or not language[0]: language = 'en' # check whether language on computer is within T1 and hence whether # it should be loaded; I know that this can be a misleading # assumption, but there's no better way that I know of if language in ['fr', 'es', 'it', 'de', 'nl', 'ro', 'en']: encoding_preamble += '\n\\usepackage[T1]{fontenc}' else: raise ValueError(("Language not supported by T1 fontenc " "encoding; please report this to the GladTeX project.")) return encoding_preamble def __str__(self): preamble = self._get_encoding_preamble() + \ ('\n\\usepackage[utf8]{inputenc}\n\\usepackage{amsmath, amssymb}' '\n') + (self._preamble if self._preamble else '') return self._format_document(preamble) def _format_document(self, preamble): """Return a formatted LaTeX document with the specified formula embedded.""" opening, closing = None,None if self.__maths_env: opening = '\\begin{%s}' % self.__maths_env closing = '\\end{%s}' % self.__maths_env else: # determine characters with which to surround the formula opening = '\\[' if self.__displaymath else '\\(' closing = '\\]' if self.__displaymath else '\\)' formula = self.__equation.lstrip().rstrip() if self.__replace_nonascii: formula = escape_unicode_in_formulas(formula, replace_alphabeticals=True) return ("\\documentclass[fontsize=12pt, fleqn]{scrartcl}\n\n%s\n" "\\usepackage[active,textmath,displaymath,tightpage]{preview} " "%% must be last one, see doc\n\n\\begin{document}\n" "\\noindent%%\n%s%s%s\n" "\\end{document}\n") % (preamble, opening, formula, closing) GladTeX-2.3.1/gleetex/htmlhandling.py000066400000000000000000000515721317106144100174750ustar00rootroot00000000000000"""Everything regarding parsing, generating and writing HTML belongs in here.""" import collections import enum import html.parser import os import posixpath import re from . import document class ParseException(Exception): """Exception to propagate a parsing error.""" def __init__(self, msg, pos): self.msg = msg self.pos = pos super().__init__(msg, pos) def __str__(self): return 'line {0.pos[0]}, {0.pos[1]}: {0.msg}'.format(self) def get_position(document, index): """This returns the line number and position on line for the given String. Note: lines and positions are counted from 0.""" line = document[:index+1].count('\n') if document[index] == '\n': return (line, 0) newline = document[:index+1].rfind('\n') newline = (newline if newline >= 0 else 0) return (line, len(document[newline:index])) def find_anycase(where, what): """Find with both lower or upper case.""" lower = where.find(what.lower()) upper = where.find(what.upper()) if lower >= 0: return lower else: return upper class EqnParser: """This parser parses ... our of a document. It's not an HTML parser, because the content within .* is parsed verbatim. It also parses comments, to not consider formulas within comments. All other cases are unhandled. Especially CData is problematic, although it seems like a rare use case.""" class State(enum.Enum): # ([\s\S]*?) also matches newlines Comment = re.compile(r'', re.MULTILINE) Equation = re.compile(r'<\s*(?:eq|EQ)\s*(.*?)?>([\s\S.]+?)<\s*/\s*(?:eq|EQ)>', re.MULTILINE) HTML_ENTITY = re.compile(r'(&(:?#\d+|[a-zA-Z]+);)') def __init__(self): self.__document = None self.__data = [] self.__encoding = None def feed(self, document): """Feed a string or a bytes instance. If a bytes instance is fed, an encoding header has to be present, so that the encoding can be extracted.""" if isinstance(document, bytes): # try to guess encoding encoding = "UTF-8" if b'charset=' in document: start = document.find(b'charset=') + 8 end = document[start:].find(b'"') if end > -1: encoding = document[start:start+end].decode("utf-8") document = document.decode(encoding) self.__encoding = encoding self.__document = document[:] self._parse() def find_with_offset(self, doc, start, what): """This find method searches in the document for a given string, staking the offset into account. REturned is the absolute position (so offset + relative match position) or -1 for no hit.""" if isinstance(what, str): pos = doc[start:].find(what) else: match = what.search(doc[start:]) pos = (-1 if not match else match.span()[0]) return (pos if pos == -1 else pos + start) def _parse(self): """This function parses the document, while maintaining state using the State enum.""" in_document = lambda x: (False if x == -1 else True) # maintain a lower-case copy, which eases searching, but doesn't affect # the handler methods doc = self.__document[:].lower() end = len(self.__document) - 1 eq_start = re.compile(r'<\s*eq\s*(.*?)>') start_pos = 0 while start_pos < end: comment = self.find_with_offset(doc, start_pos, '' % match.groups()[0]) return start_pos + match.span()[1] # return end of match def get_encoding(self): """Return the parsed encoding from the HTML meta data. If none was set, UTF-8 is assumed.""" return self.__encoding def get_data(self): """Return parsed chunks. These are either strings or tuples with formula information, see class documentation.""" return list(x for x in self.__data if x) # filter empty bits def gen_id(formula): """Generate an id for identifying a formula as an anchor in a document. The generated ID is guaranteed to be valid in an XML attribute and it won't exceed a certain length. If you happen to have a lot of formulas > 150 characters with exactly the same content in the document, that'll cause a clash of id's.""" # for some characters we just use a simple replacement (otherwise the # would be lost) mapped = {'{':'_', '}':'_', '(':'-', ')':'-', '\\':'.', '^':',', '*':'_'} id = [] prevchar = '' for c in formula: if prevchar == c: continue # avoid multiple same characters if c in mapped: id.append(mapped[c]) elif c.isalpha() or c.isdigit(): id.append(c) prevchar = c # id's must start with an alphabetical character, so prefix the formula with # "formula" to make it a valid html id if len(id) and not id[0].isalpha(): id = ['f', 'o', 'r', 'm', '_'] + id if not id: # is empty raise ValueError("For the formula '%s' no referencable id could be generated." \ % formula) return ''.join(id[:150]) class OutsourcedFormulaParser(html.parser.HTMLParser): """This HTML parser parses the head and tries to keep it close to the original document as possible. As soon as a formula is encountered, only the formulas are parsed. Everything in between and after the them will be fully ignored. A sample formula would look like:

stuff

""" def __init__(self): self.__head = [] self.__id = None self.__passed_head = False self.__equations = collections.OrderedDict() super().__init__(convert_charrefs=False) def handle_starttag(self, tag, attrs): if tag == 'p': attrs = dict(attrs) if attrs.get('id'): self.__id = attrs['id'] # marks beginning of a formula paragraph self.__equations[self.__id] = '' return elif tag == 'body': self.__passed_head = True self.__head.append('\n\n') if not self.__passed_head: self.__head.append(self.get_starttag_text()) def handle_startendtag(self, tag, attrs): if self.__id or self.__passed_head: return # skip everything inside a formula if attrs: self.__head.append('<{} {} />'.format(tag, ' '.join(['%s="%s"' % (x[0], x[1]) for x in attrs]))) else: self.__head.append('<%s />' % tag) def handle_endtag(self, tag): if self.__id: # inside a formula if tag == 'p': self.__id = None # end formula block elif not self.__passed_head: formatted = '' % tag self.__head.append(formatted) def handle_data(self, data): if self.__id: self.__equations[self.__id] += data elif not self.__passed_head: self.__head.append(data) def handle_entityref(self, name): if self.__id: self.__equations[self.__id] += '&%s;' % name elif not self.__passed_head: self.__head.append('&%s;' % name) def handle_charref(self, name): if self.__id: self.__equations[self.__id] += '&#%s;' % name elif not self.__passed_head: self.__head.append('&#%s;' % name) def handle_comment(self, blah): if not self.__passed_head: self.__head.append('' % blah) def handle_decl(self, declaration): if not self.__passed_head: self.__head.append('' % declaration) def get_head(self): """Return a string containing everything before the first formula.""" return ''.join(self.__head) def get_formulas(self): """Return an ordered dictionary with id : formula paragraph.""" return self.__equations def error(self, message): raise ParseException(message, ('unknown', 'unknown')) def format_formula_paragraph(formula): """Format a formula to appear as if it would have been outsourced into an external file.""" return '

%s

\n' % \ (gen_id(formula), formula) class HtmlImageFormatter: # ToDo: localisation """HtmlImageFormatter(exclusion_filepath='outsourced_formulas.html', encoding="UTF-8") Format converted formula to be included into the HTML. A typical image attribute will contain the path to the image, style information, a CSS class to be used in custom CSS style sheets and an alternative text (the LaTeX source) for people who disabled images or for blind screen reader users. If set, LaTeX formulas exceeding a configurable maximum length will be excluded. The image will be a link which leads to the excluded image text. The alt attribute is a text-only attribute and e.g. line breaks will be lost for screen reader users, so it makes sense for longer formulas to be external to be easily readable. Furthermore the alt attribute is limited to 255 characters, so formula blocks exceeding that limit need to be treated differently anyway. If that behavior is not wanted, it can be disabled and nothing will be excluded.""" EXCLUSION_FILE_NAME = 'outsourced-descriptions.html' FORMATTING_COMMANDS = ['\\ ', '\\,', '\\;', '\\big', '\\Big', '\\left', '\\right', '\\limits'] HTML_TEMPLATE_HEAD = ('\n\n\n' + '' + '\nOutsourced Formulas\n\n\n\n') def __init__(self, base_path='', link_path=None): self.__exclude_descriptions = False self.__link_path = (link_path if link_path else '') self.__base_path = (base_path if base_path else '') self.__exclusion_filepath = posixpath.join(self.__base_path, HtmlImageFormatter.EXCLUSION_FILE_NAME) if os.path.exists(self.__exclusion_filepath): if not os.access(self.__exclusion_filepath, os.W_OK): raise OSError('The file %s is not writable!' % self.__exclusion_filepath) self.__inline_maxlength=100 self.__file_head = HtmlImageFormatter.HTML_TEMPLATE_HEAD self.__cached_formula_pars = collections.OrderedDict() self.__url = '' self.initialized = False self.initialize() # read already written file, if any self.__css = {'inline' : 'inlinemath', 'display' : 'displaymath'} self.__replace_nonascii = False def set_replace_nonascii(self, flag): """If True, non-ascii characters will be replaced through their LaTeX command. Note that alphabetical characters will not be replaced, to allow easier readibility.""" self.__replace_nonascii = flag def set_max_formula_length(self, length): """Set maximum length of a formula before it gets outsourced into a separate file.""" self.__inline_maxlength = length def set_inline_math_css_class(self, css): """set css class for inline math.""" self.__css['inline'] = css def set_display_math_css_class(self, css): """set css class for display math.""" self.__css['display'] = css def set_exclude_long_formulas(self, flag): """When set, the LaTeX code of a formula longer than the configured maxlength will be excluded and written + linked into a separate file.""" self.__exclude_descriptions = flag def set_url(self, prefix): """Set URL prefix which is used as a prefix to the image file in the HTML link.""" self.__url = prefix def initialize(self): """Initialize the image writer. If a file with already written image descriptions exists, this one will be parsed first and new formulas appended to it. Otherwise a new file will be written upon ending the with-resources block.""" if self.initialized: return self.initialized = True if not os.path.exists(self.__exclusion_filepath): return self document = None with open(self.__exclusion_filepath, 'r', encoding='UTF-8') as f: document = f.read() # parse html document: parser = OutsourcedFormulaParser() parser.feed(document) self.__file_head = parser.get_head() self.__cached_formula_pars = parser.get_formulas() return self def __enter__(self): return self def __exit__(self, useless, unused, not_applicable): self.close() def close(self): """Write back file with excluded image descriptions, if any.""" def formula2paragraph(frml): return '

%s

' % (gen_id(frml), frml) if not len(self.__cached_formula_pars): return with open(self.__exclusion_filepath, 'w', encoding='utf-8') as f: f.write(self.__file_head) f.write('\n
\n'.join([formula2paragraph(formula) \ for formula in self.__cached_formula_pars.values()])) f.write('\n\n\n') def postprocess_formula(self, formula): """Formulas should not contain unicode characters or formatting instructions, if they are part of the alt attribute. This distracts the reader and stretches the formula. This method replaces non-ascii characters, if requested and strips a few formatting commands.""" if self.__replace_nonascii: formula = document.escape_unicode_in_formulas(formula, replace_alphabeticals=False) # replace formatting-only symbols which distract the reader formula_changed = True while formula_changed: formula_changed = False for command in HtmlImageFormatter.FORMATTING_COMMANDS: idx = formula.find(command) # only replace if it's not after a \\ and not part of a longer command if (idx > 0 and formula[idx-1] != '\\') or idx == 0: end = idx + len(command) # following conditions for replacement must be met: # command doesn't end on alphabet. char. and is followed by # same category; end of string reached or command does not # end on alphabet. char. at all if end >= len(formula) or not command[-1].isalpha() \ or not formula[end].isalpha(): formula = formula[:idx] + ' ' + formula[idx + len(command):] formula = formula.replace(' ', ' ') formula_changed = True return formula def get_html_img(self, pos, formula, img_path, displaymath=False): """:param pos dictionary containing keys depth, height and width :param formula LaTeX alternative text :param img_path: path to image :param displaymath display or inline math (default False, inline maths) :returns a string with the formatted HTML""" full_url = img_path if self.__url: if self.__url.endswith('/'): self.__url = self.__url[:-1] full_url = self.__url + '/' + img_path # depth is a negative offset depth = str(int(pos['depth']) * -1) css = (self.__css['display'] if displaymath else self.__css['inline']) return ('{1}').format(full_url, formula, pos, depth, css) def format_excluded(self, pos, formula, img_path, displaymath=False): """This method formats a formula and an formula image in HTML and additionally writes the formula to an external (configured) file to which the image links to. That's useful for blind screen reader users who can then easily have a look at the formula. :param pos dictionary containing keys depth, height and width :param formula LaTeX alternative text :param img_path: path to image :param displaymath if set to true, image is treated as display math formula (default False) :returns string with formatted HTML image which also links to excluded formula""" shortened = (formula[:100] + '...' if len(formula) > 100 else formula) img = self.get_html_img(pos, shortened, img_path, displaymath) identifier = gen_id(formula) # write formula out to external file if identifier not in self.__cached_formula_pars: self.__cached_formula_pars[identifier] = formula exclusion_filelink = posixpath.join(self.__link_path, self.__exclusion_filepath) return '{}'.format(exclusion_filelink, gen_id(formula), img) def format(self, pos, formula, img_path, displaymath=False): """This method formats a formula. If self.__exclude_descriptions is set and the formula igreater than the configured length, the formula will be outsourced, otherwise it'll be included in the IMG's alt tag. In either case, a string for the current document containing the formatted HTML is returned. :param pos dictionary containing keys depth, height and width :param formula LaTeX alternative text :param img_path: path to image :param displaymath whether or not formula is in display math (default: no) :returns string with formatted HTML image which also links to excluded formula""" formula = self.postprocess_formula(formula) if self.__exclude_descriptions and \ len(formula) > self.__inline_maxlength: return self.format_excluded(pos, formula, img_path, displaymath) else: return self.get_html_img(pos, formula, img_path, displaymath) GladTeX-2.3.1/gleetex/image.py000066400000000000000000000231421317106144100160760ustar00rootroot00000000000000""" This module takes care of the actual image creation process. """ import distutils.dir_util import os import re import shutil import subprocess import sys def remove_all(*files): """Guarded remove of files (rm -f); no exception is thrown if a file couldn't be removed.""" try: for file in files: os.remove(file) except OSError: pass def proc_call(cmd, cwd=None): """Execute cmd (list of arguments) as a subprocess. Returned is a tuple with stdout and stderr, decoded if not None. If the return value is not equal 0, a subprocess error is raised. Timeouts will happen after 20 seconds.""" with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1, universal_newlines=False, cwd=cwd) as proc: data = [] try: data = [d.decode(sys.getdefaultencoding(), errors="surrogateescape") for d in proc.communicate(timeout=20) if d] if proc.wait(): raise subprocess.SubprocessError("Error while executing %s\n%s\n" % (' '.join(cmd), '\n'.join(data))) except subprocess.TimeoutExpired as e: proc.kill() note = 'Subprocess expired with time out: ' + str(cmd) + '\n' poll = proc.poll() if poll: note += str(poll) + '\n' if data: raise subprocess.SubprocessError(str(data + '\n' + note)) else: raise subprocess.SubprocessError('execution timed out after ' + str(e.args[1]) + ' s: ' + ' '.join(e.args[0])) except KeyboardInterrupt as e: sys.stderr.write("\nInterrupted; ") import traceback traceback.print_exc(file=sys.stderr) if isinstance(data, list): return '\n'.join(data) else: return data class Tex2img: """ Convert a TeX document string into a png file. This class interacts with the LaTeX and dvipng sub processes. Upon error the methods throw a SubprocessError with all necessary information to fix the issue. The background of the PNG files will be transparent by default. """ call = proc_call DVIPNG_REGEX = re.compile(r"^ depth=(-?\d+) height=(\d+) width=(\d+)") def __init__(self, tex_document, output_fn, encoding="UTF-8"): """tex_document should be either a full TeX document as a string or a class which implements the __str__ method.""" self.tex_document = tex_document self.output_name = output_fn self.__encoding = encoding self.__parsed_data = None self.__dpi = 100 self.__background = 'transparent' self.__foreground = 'rgb 0 0 0' self.__keep_latex_source = False # create directory for image if that doesn't exist base_name = os.path.split(output_fn)[0] if base_name and not os.path.exists(base_name): distutils.dir_util.mkpath(base_name) def set_dpi(self, dpi): """Set output resolution for formula images.""" if not isinstance(dpi, (int, float)): raise TypeError("Dpi must be an integer or floating point number") self.__dpi = int(dpi) def set_transparency(self, flag): """Set whether or not the background of an image is transparent.""" if not isinstance(flag, bool): raise ValueError("Argument must be of type bool!") self.__background = ('transparent' if flag else 'rgb 1 1 1') def __check_rgb(self, rgb_list): """Check whether a list of RGB colors is correct. It must contain three broken decimals with 0 <= x <= 1.""" if not isinstance(rgb_list, (list, tuple)) or len(rgb_list) != 3: raise ValueError("A list with three broken decimals between 0 and 1 expected.") if not all(map((lambda x: x >= 0 and x <= 1), rgb_list)): raise ValueError("RGB values must between 0 and 1") def set_background_color(self, rgb_list): """set_background_color(rgb_values) The list rgb_values must contain three broken decimals between 0 and 1.""" self.__check_rgb(rgb_list) self.__background = 'rgb {0[0]} {0[1]} {0[2]}'.format(rgb_list) def set_foreground_color(self, rgb_list): """set_background_color(rgb_values) The list rgb_values must contain three broken decimals between 0 and 1.""" self.__check_rgb(rgb_list) self.__foreground = 'rgb {0[0]} {0[1]} {0[2]}'.format(rgb_list) def set_keep_latex_source(self, flag): """Set whether LaTeX source document should be kept.""" if not isinstance(flag, bool): raise TypeError("boolean object required, got %s." % repr(flag)) self.__keep_latex_source = flag def create_dvi(self, dvi_fn): """ Call LaTeX to produce a dvi file with the given LaTeX document. Temporary files will be removed, even in the case of a LaTeX error. This method raises a SubprocessError with the helpful part of LaTeX's error output.""" path = os.path.dirname(dvi_fn) if not path: path = os.getcwd() new_extension = lambda x: os.path.splitext(dvi_fn)[0] + '.' + x tex_fn = new_extension('tex') aux_fn = new_extension('aux') log_fn = new_extension('log') cmd = None cmd = ['latex', '-halt-on-error', os.path.basename(tex_fn)] encoding = self.__encoding with open(tex_fn, mode='w', encoding=encoding) as tex: tex.write(str(self.tex_document)) try: Tex2img.call(cmd, cwd=path) except subprocess.SubprocessError as e: remove_all(dvi_fn) msg = '' if e.args: data = self.parse_log(e.args[0]) if data: msg += data else: msg += str(e.args[0]) raise subprocess.SubprocessError(msg) # propagate subprocess error except FileNotFoundError: # `latex` is missing, give suggestions on how to install it text = "Command `%s` not found." % cmd[0] if shutil.which('dpkg'): text += ' Install it using `sudo apt install texlive-latex-recommended preview-latex-style`' else: text += ' Install a TeX distribution of your choice, e.g. MikTeX or TeXlive.' raise subprocess.SubprocessError(text) finally: if self.__keep_latex_source: remove_all(aux_fn, log_fn) else: remove_all(tex_fn, aux_fn, log_fn) def create_png(self, dvi_fn): """Create a PNG file from a given dvi file. The side effect is the PNG file being written to disk. :param dvi_fn Dvi file name :return dimensions for embedding into an HTML document :raises ValueError raised whenever dvipng output coudln't be parsed """ cmd = ['dvipng', '-q*', '-D', str(self.__dpi), # colors '-bg', self.__background, '-fg', self.__foreground, '--height*', '--depth*', '--width*', # print information for embedding '-o', self.output_name, dvi_fn] data = None try: data = Tex2img.call(cmd) except subprocess.SubprocessError: remove_all(self.output_name) raise except FileNotFoundError: # `dvipng` is missing, give suggestions on how to install it text = "Command `%s` not found." % cmd[0] if shutil.which('dpkg'): text += ' Install it using `sudo apt install dvipng`' else: text += ' Install a TeX distribution of your choice, e.g. MikTeX or TeXlive.' raise subprocess.SubprocessError(text) finally: remove_all(dvi_fn) for line in data.split('\n'): found = Tex2img.DVIPNG_REGEX.search(line) if found: return dict(zip(['depth', 'height', 'width'], found.groups())) raise ValueError("Could not parse dvi output: " + repr(data)) def convert(self): """Convert the TeX document into an image. This calls create_dvi and create_png but will not return anything. Thre result should be retrieved using get_positioning_info().""" dvi = os.path.join(os.path.splitext(self.output_name)[0] + '.dvi') try: self.create_dvi(dvi) self.__parsed_data = self.create_png(dvi) except OSError: remove_all(self.output_name) raise def get_positioning_info(self): """Return positioning information to position created image in the HTML page.""" return self.__parsed_data def parse_log(self, logdata): """Parse the LaTeX error output and return the relevant part of it.""" if not logdata: return None line = None for line in logdata.split('\n'): if line.startswith('! '): line = line[2:] break if line: # try to remove LaTeX line numbers lineno = re.search(r'\s*on input line \d+', line) if lineno: line = line[:lineno.span()[0]] + line[lineno.span()[1]:] return line def fontsize2dpi(size_pt): """This function calculates the DPI for the resulting image. Depending on the font size, a different resolution needs to be used. According to the dvipng manual page, the formula is: = * 72.27 / 10 [px * TeXpt/in / TeXpt]""" size_px = size_pt * 1.3333333 # and more 3s! return size_px * 72.27 / 10 GladTeX-2.3.1/gleetex/unicode.py000066400000000000000000004171001317106144100164430ustar00rootroot00000000000000""" DO NOT ALTER THIS FILE IN ANY WAY, IT IS GENERATED AUTOMATICALLY. SEE THE SCRIPT `update_unicode_table.py` FOR MORE INFORMATION. This file contains a table of unicode code point to LaTeX command mapping. It has 2369 entries and was derived from .""" #pylint: disable=too-many-lines,missing-docstring import enum class LaTeXMode(enum.Enum): """Represent either math or text mode. Math mode in LaTeX is e.g. everything between $ and $.""" mathmode = 1 textmode = 0 unicode_table = { 161: {LaTeXMode.textmode: '\\textexclamdown ', LaTeXMode.mathmode: '\\textexclamdown'}, 162: {LaTeXMode.textmode: '\\textcent ', LaTeXMode.mathmode: '\\mbox{\\textcent}'}, 163: {LaTeXMode.textmode: '\\textsterling ', LaTeXMode.mathmode: '\\sterling'}, 164: {LaTeXMode.textmode: '\\textcurrency ', LaTeXMode.mathmode: '\\mbox{\\textcurrency}'}, 165: {LaTeXMode.textmode: '\\textyen ', LaTeXMode.mathmode: '\\yen'}, 166: {LaTeXMode.textmode: '\\textbrokenbar '}, 167: {LaTeXMode.textmode: '\\textsection ', LaTeXMode.mathmode: '\\S'}, 168: {LaTeXMode.textmode: '\\textasciidieresis '}, 169: {LaTeXMode.textmode: '\\textcopyright ', LaTeXMode.mathmode: '\\copyright'}, 170: {LaTeXMode.textmode: '\\textordfeminine '}, 171: {LaTeXMode.textmode: '\\guillemotleft ', LaTeXMode.mathmode: '\\mbox{\\guillemotleft}'}, 172: {LaTeXMode.textmode: '\\lnot ', LaTeXMode.mathmode: '\\neg'}, 173: {LaTeXMode.textmode: '\\-'}, 174: {LaTeXMode.textmode: '\\textregistered ', LaTeXMode.mathmode: '\\circledR'}, 175: {LaTeXMode.textmode: '\\textasciimacron '}, 176: {LaTeXMode.textmode: '\\textdegree ', LaTeXMode.mathmode: '\\degree'}, 177: {LaTeXMode.textmode: '\\pm ', LaTeXMode.mathmode: '\\pm'}, 178: {LaTeXMode.textmode: '{^2}'}, 179: {LaTeXMode.textmode: '{^3}'}, 180: {LaTeXMode.textmode: '\\textasciiacute ', LaTeXMode.mathmode: '\\textasciiacute'}, 181: {LaTeXMode.textmode: '\\mathrm{\\mu}'}, 182: {LaTeXMode.textmode: '\\textparagraph ', LaTeXMode.mathmode: '\\P'}, 183: {LaTeXMode.textmode: '\\cdot ', LaTeXMode.mathmode: '\\cdotp'}, 184: {LaTeXMode.textmode: '\\c{}', LaTeXMode.mathmode: '\\mbox{\\c{}}'}, 185: {LaTeXMode.textmode: '{^1}'}, 186: {LaTeXMode.textmode: '\\textordmasculine '}, 187: {LaTeXMode.textmode: '\\guillemotright ', LaTeXMode.mathmode: '\\mbox{\\guillemotright}'}, 188: {LaTeXMode.textmode: '\\textonequarter '}, 189: {LaTeXMode.textmode: '\\textonehalf '}, 190: {LaTeXMode.textmode: '\\textthreequarters '}, 191: {LaTeXMode.textmode: '\\textquestiondown ', LaTeXMode.mathmode: '\\textquestiondown'}, 192: {LaTeXMode.textmode: '\\`{A}', LaTeXMode.mathmode: '\\grave{A}'}, 193: {LaTeXMode.textmode: "\\'{A}", LaTeXMode.mathmode: '\\acute{A}'}, 194: {LaTeXMode.textmode: '\\^{A}', LaTeXMode.mathmode: '\\hat{A}'}, 195: {LaTeXMode.textmode: '\\~{A}', LaTeXMode.mathmode: '\\tilde{A}'}, 196: {LaTeXMode.textmode: '\\"{A}', LaTeXMode.mathmode: '\\ddot{A}'}, 197: {LaTeXMode.textmode: '\\AA '}, 198: {LaTeXMode.textmode: '\\AE ', LaTeXMode.mathmode: '\\AE'}, 199: {LaTeXMode.textmode: '\\c{C}', LaTeXMode.mathmode: '\\mbox{\\c{C}}'}, 200: {LaTeXMode.textmode: '\\`{E}', LaTeXMode.mathmode: '\\grave{E}'}, 201: {LaTeXMode.textmode: "\\'{E}", LaTeXMode.mathmode: '\\acute{E}'}, 202: {LaTeXMode.textmode: '\\^{E}', LaTeXMode.mathmode: '\\hat{E}'}, 203: {LaTeXMode.textmode: '\\"{E}', LaTeXMode.mathmode: '\\ddot{E}'}, 204: {LaTeXMode.textmode: '\\`{I}', LaTeXMode.mathmode: '\\grave{I}'}, 205: {LaTeXMode.textmode: "\\'{I}", LaTeXMode.mathmode: '\\acute{I}'}, 206: {LaTeXMode.textmode: '\\^{I}', LaTeXMode.mathmode: '\\hat{I}'}, 207: {LaTeXMode.textmode: '\\"{I}', LaTeXMode.mathmode: '\\ddot{I}'}, 208: {LaTeXMode.textmode: '\\DH '}, 209: {LaTeXMode.textmode: '\\~{N}', LaTeXMode.mathmode: '\\tilde{N}'}, 210: {LaTeXMode.textmode: '\\`{O}', LaTeXMode.mathmode: '\\grave{O}'}, 211: {LaTeXMode.textmode: "\\'{O}", LaTeXMode.mathmode: '\\acute{O}'}, 212: {LaTeXMode.textmode: '\\^{O}', LaTeXMode.mathmode: '\\hat{O}'}, 213: {LaTeXMode.textmode: '\\~{O}', LaTeXMode.mathmode: '\\tilde{O}'}, 214: {LaTeXMode.textmode: '\\"{O}', LaTeXMode.mathmode: '\\ddot{O}'}, 215: {LaTeXMode.textmode: '\\texttimes ', LaTeXMode.mathmode: '\\times'}, 216: {LaTeXMode.textmode: '\\O ', LaTeXMode.mathmode: '\\O'}, 217: {LaTeXMode.textmode: '\\`{U}', LaTeXMode.mathmode: '\\grave{U}'}, 218: {LaTeXMode.textmode: "\\'{U}", LaTeXMode.mathmode: '\\acute{U}'}, 219: {LaTeXMode.textmode: '\\^{U}', LaTeXMode.mathmode: '\\hat{U}'}, 220: {LaTeXMode.textmode: '\\"{U}', LaTeXMode.mathmode: '\\ddot{U}'}, 221: {LaTeXMode.textmode: "\\'{Y}", LaTeXMode.mathmode: '\\acute{Y}'}, 222: {LaTeXMode.textmode: '\\TH '}, 223: {LaTeXMode.textmode: '\\ss ', LaTeXMode.mathmode: '\\ss'}, 224: {LaTeXMode.textmode: '\\`{a}', LaTeXMode.mathmode: '\\grave{a}'}, 225: {LaTeXMode.textmode: "\\'{a}", LaTeXMode.mathmode: '\\acute{a}'}, 226: {LaTeXMode.textmode: '\\^{a}', LaTeXMode.mathmode: '\\hat{a}'}, 227: {LaTeXMode.textmode: '\\~{a}', LaTeXMode.mathmode: '\\tilde{a}'}, 228: {LaTeXMode.textmode: '\\"{a}', LaTeXMode.mathmode: '\\ddot{a}'}, 229: {LaTeXMode.textmode: '\\aa '}, 230: {LaTeXMode.textmode: '\\ae ', LaTeXMode.mathmode: '\\ae'}, 231: {LaTeXMode.textmode: '\\c{c}', LaTeXMode.mathmode: '\\mbox{\\c{c}}'}, 232: {LaTeXMode.textmode: '\\`{e}', LaTeXMode.mathmode: '\\grave{e}'}, 233: {LaTeXMode.textmode: "\\'{e}", LaTeXMode.mathmode: '\\acute{e}'}, 234: {LaTeXMode.textmode: '\\^{e}', LaTeXMode.mathmode: '\\hat{e}'}, 235: {LaTeXMode.textmode: '\\"{e}', LaTeXMode.mathmode: '\\ddot{e}'}, 236: {LaTeXMode.textmode: '\\`{\\i}', LaTeXMode.mathmode: '\\grave{\\imath}'}, 237: {LaTeXMode.textmode: "\\'{\\i}", LaTeXMode.mathmode: '\\acute{\\imath}'}, 238: {LaTeXMode.textmode: '\\^{\\i}', LaTeXMode.mathmode: '\\hat{\\imath}'}, 239: {LaTeXMode.textmode: '\\"{\\i}', LaTeXMode.mathmode: '\\ddot{\\imath}'}, 240: {LaTeXMode.textmode: '\\dh ', LaTeXMode.mathmode: '\\eth'}, 241: {LaTeXMode.textmode: '\\~{n}', LaTeXMode.mathmode: '\\tilde{n}'}, 242: {LaTeXMode.textmode: '\\`{o}', LaTeXMode.mathmode: '\\grave{o}'}, 243: {LaTeXMode.textmode: "\\'{o}", LaTeXMode.mathmode: '\\acute{o}'}, 244: {LaTeXMode.textmode: '\\^{o}', LaTeXMode.mathmode: '\\hat{o}'}, 245: {LaTeXMode.textmode: '\\~{o}', LaTeXMode.mathmode: '\\tilde{o}'}, 246: {LaTeXMode.textmode: '\\"{o}', LaTeXMode.mathmode: '\\ddot{o}'}, 247: {LaTeXMode.textmode: '\\div ', LaTeXMode.mathmode: '\\div'}, 248: {LaTeXMode.textmode: '\\o ', LaTeXMode.mathmode: '\\o'}, 249: {LaTeXMode.textmode: '\\`{u}', LaTeXMode.mathmode: '\\grave{u}'}, 250: {LaTeXMode.textmode: "\\'{u}", LaTeXMode.mathmode: '\\acute{u}'}, 251: {LaTeXMode.textmode: '\\^{u}', LaTeXMode.mathmode: '\\hat{u}'}, 252: {LaTeXMode.textmode: '\\"{u}', LaTeXMode.mathmode: '\\ddot{u}'}, 253: {LaTeXMode.textmode: "\\'{y}", LaTeXMode.mathmode: '\\acute{y}'}, 254: {LaTeXMode.textmode: '\\th '}, 255: {LaTeXMode.textmode: '\\"{y}', LaTeXMode.mathmode: '\\ddot{y}'}, 256: {LaTeXMode.textmode: '\\={A}', LaTeXMode.mathmode: '\\bar{A}'}, 257: {LaTeXMode.textmode: '\\={a}', LaTeXMode.mathmode: '\\bar{a}'}, 258: {LaTeXMode.textmode: '\\u{A}', LaTeXMode.mathmode: '\\breve{A}'}, 259: {LaTeXMode.textmode: '\\u{a}', LaTeXMode.mathmode: '\\u{a}'}, 260: {LaTeXMode.textmode: '\\k{A}'}, 261: {LaTeXMode.textmode: '\\k{a}'}, 262: {LaTeXMode.textmode: "\\'{C}", LaTeXMode.mathmode: '\\acute{C}'}, 263: {LaTeXMode.textmode: "\\'{c}", LaTeXMode.mathmode: '\\acute{c}'}, 264: {LaTeXMode.textmode: '\\^{C}', LaTeXMode.mathmode: '\\hat{C}'}, 265: {LaTeXMode.textmode: '\\^{c}', LaTeXMode.mathmode: '\\hat{c}'}, 266: {LaTeXMode.textmode: '\\.{C}', LaTeXMode.mathmode: '\\dot{C}'}, 267: {LaTeXMode.textmode: '\\.{c}', LaTeXMode.mathmode: '\\dot{c}'}, 268: {LaTeXMode.textmode: '\\v{C}', LaTeXMode.mathmode: '\\check{C}'}, 269: {LaTeXMode.textmode: '\\v{c}', LaTeXMode.mathmode: '\\check{c}'}, 270: {LaTeXMode.textmode: '\\v{D}', LaTeXMode.mathmode: '\\check{D}'}, 271: {LaTeXMode.textmode: '\\v{d}', LaTeXMode.mathmode: '\\check{d}'}, 272: {LaTeXMode.textmode: '\\DJ '}, 273: {LaTeXMode.textmode: '\\dj '}, 274: {LaTeXMode.textmode: '\\={E}', LaTeXMode.mathmode: '\\bar{E}'}, 275: {LaTeXMode.textmode: '\\={e}', LaTeXMode.mathmode: '\\bar{e}'}, 276: {LaTeXMode.textmode: '\\u{E}', LaTeXMode.mathmode: '\\breve{E}'}, 277: {LaTeXMode.textmode: '\\u{e}', LaTeXMode.mathmode: '\\breve{e}'}, 278: {LaTeXMode.textmode: '\\.{E}', LaTeXMode.mathmode: '\\dot{E}'}, 279: {LaTeXMode.textmode: '\\.{e}', LaTeXMode.mathmode: '\\dot{e}'}, 280: {LaTeXMode.textmode: '\\k{E}', LaTeXMode.mathmode: '\\k{E}'}, 281: {LaTeXMode.textmode: '\\k{e}'}, 282: {LaTeXMode.textmode: '\\v{E}', LaTeXMode.mathmode: '\\check{E}'}, 283: {LaTeXMode.textmode: '\\v{e}', LaTeXMode.mathmode: '\\check{e}'}, 284: {LaTeXMode.textmode: '\\^{G}', LaTeXMode.mathmode: '\\hat{G}'}, 285: {LaTeXMode.textmode: '\\^{g}', LaTeXMode.mathmode: '\\hat{g}'}, 286: {LaTeXMode.textmode: '\\u{G}', LaTeXMode.mathmode: '\\breve{G}'}, 287: {LaTeXMode.textmode: '\\u{g}', LaTeXMode.mathmode: '\\breve{g}'}, 288: {LaTeXMode.textmode: '\\.{G}', LaTeXMode.mathmode: '\\dot{G}'}, 289: {LaTeXMode.textmode: '\\.{g}', LaTeXMode.mathmode: '\\dot{g}'}, 290: {LaTeXMode.textmode: '\\c{G}', LaTeXMode.mathmode: '\\mbox{\\c{G}}'}, 291: {LaTeXMode.textmode: '\\c{g}', LaTeXMode.mathmode: '\\mbox{\\c{g}}'}, 292: {LaTeXMode.textmode: '\\^{H}', LaTeXMode.mathmode: '\\hat{H}'}, 293: {LaTeXMode.textmode: '\\^{h}', LaTeXMode.mathmode: '\\hat{h}'}, 294: {LaTeXMode.textmode: '{\\fontencoding{LELA}\\selectfont\\char40}'}, 295: {LaTeXMode.textmode: '\\Elzxh '}, 296: {LaTeXMode.textmode: '\\~{I}', LaTeXMode.mathmode: '\\tilde{I}'}, 297: {LaTeXMode.textmode: '\\~{\\i}', LaTeXMode.mathmode: '\\tilde{\\imath}'}, 298: {LaTeXMode.textmode: '\\={I}', LaTeXMode.mathmode: '\\bar{I}'}, 299: {LaTeXMode.textmode: '\\={\\i}', LaTeXMode.mathmode: '\\bar{\\imath}'}, 300: {LaTeXMode.textmode: '\\u{I}', LaTeXMode.mathmode: '\\breve{I}'}, 301: {LaTeXMode.textmode: '\\u{\\i}', LaTeXMode.mathmode: '\\breve{\\imath}'}, 302: {LaTeXMode.textmode: '\\k{I}'}, 303: {LaTeXMode.textmode: '\\k{i}'}, 304: {LaTeXMode.textmode: '\\.{I}', LaTeXMode.mathmode: '\\dot{I}'}, 305: {LaTeXMode.textmode: '\\i ', LaTeXMode.mathmode: '\\imath'}, 306: {LaTeXMode.textmode: 'IJ'}, 307: {LaTeXMode.textmode: 'ij'}, 308: {LaTeXMode.textmode: '\\^{J}', LaTeXMode.mathmode: '\\hat{J}'}, 309: {LaTeXMode.textmode: '\\^{\\j}', LaTeXMode.mathmode: '\\hat{\\jmath}'}, 310: {LaTeXMode.textmode: '\\c{K}', LaTeXMode.mathmode: '\\mbox{\\c{K}}'}, 311: {LaTeXMode.textmode: '\\c{k}', LaTeXMode.mathmode: '\\mbox{\\c{k}}'}, 312: {LaTeXMode.textmode: '{\\fontencoding{LELA}\\selectfont\\char91}'}, 313: {LaTeXMode.textmode: "\\'{L}", LaTeXMode.mathmode: '\\acute{L}'}, 314: {LaTeXMode.textmode: "\\'{l}", LaTeXMode.mathmode: '\\acute{l}'}, 315: {LaTeXMode.textmode: '\\c{L}', LaTeXMode.mathmode: '\\mbox{\\c{L}}'}, 316: {LaTeXMode.textmode: '\\c{l}', LaTeXMode.mathmode: '\\mbox{\\c{l}}'}, 317: {LaTeXMode.textmode: '\\v{L}', LaTeXMode.mathmode: '\\check{L}'}, 318: {LaTeXMode.textmode: '\\v{l}', LaTeXMode.mathmode: '\\check{l}'}, 319: {LaTeXMode.textmode: '{\\fontencoding{LELA}\\selectfont\\char201}'}, 320: {LaTeXMode.textmode: '{\\fontencoding{LELA}\\selectfont\\char202}'}, 321: {LaTeXMode.textmode: '\\L ', LaTeXMode.mathmode: '\\L'}, 322: {LaTeXMode.textmode: '\\l ', LaTeXMode.mathmode: '\\l'}, 323: {LaTeXMode.textmode: "\\'{N}", LaTeXMode.mathmode: '\\acute{N}'}, 324: {LaTeXMode.textmode: "\\'{n}", LaTeXMode.mathmode: '\\acute{n}'}, 325: {LaTeXMode.textmode: '\\c{N}', LaTeXMode.mathmode: '\\mbox{\\c{N}}'}, 326: {LaTeXMode.textmode: '\\c{n}', LaTeXMode.mathmode: '\\mbox{\\c{n}}'}, 327: {LaTeXMode.textmode: '\\v{N}', LaTeXMode.mathmode: '\\check{N}'}, 328: {LaTeXMode.textmode: '\\v{n}', LaTeXMode.mathmode: '\\check{n}'}, 329: {LaTeXMode.textmode: "'n"}, 330: {LaTeXMode.textmode: '\\NG '}, 331: {LaTeXMode.textmode: '\\ng '}, 332: {LaTeXMode.textmode: '\\={O}', LaTeXMode.mathmode: '\\bar{O}'}, 333: {LaTeXMode.textmode: '\\={o}', LaTeXMode.mathmode: '\\bar{o}'}, 334: {LaTeXMode.textmode: '\\u{O}', LaTeXMode.mathmode: '\\breve{O}'}, 335: {LaTeXMode.textmode: '\\u{o}', LaTeXMode.mathmode: '\\breve{o}'}, 336: {LaTeXMode.textmode: '\\H{O}', LaTeXMode.mathmode: '\\mbox{\\H{O}}'}, 337: {LaTeXMode.textmode: '\\H{o}', LaTeXMode.mathmode: '\\mbox{\\H{o}}'}, 338: {LaTeXMode.textmode: '\\OE ', LaTeXMode.mathmode: '\\OE'}, 339: {LaTeXMode.textmode: '\\oe ', LaTeXMode.mathmode: '\\oe'}, 340: {LaTeXMode.textmode: "\\'{R}", LaTeXMode.mathmode: '\\acute{R}'}, 341: {LaTeXMode.textmode: "\\'{r}", LaTeXMode.mathmode: '\\acute{r}'}, 342: {LaTeXMode.textmode: '\\c{R}', LaTeXMode.mathmode: '\\mbox{\\c{R}}'}, 343: {LaTeXMode.textmode: '\\c{r}', LaTeXMode.mathmode: '\\mbox{\\c{r}}'}, 344: {LaTeXMode.textmode: '\\v{R}', LaTeXMode.mathmode: '\\check{R}'}, 345: {LaTeXMode.textmode: '\\v{r}', LaTeXMode.mathmode: '\\check{r}'}, 346: {LaTeXMode.textmode: "\\'{S}", LaTeXMode.mathmode: '\\acute{S}'}, 347: {LaTeXMode.textmode: "\\'{s}", LaTeXMode.mathmode: '\\acute{s}'}, 348: {LaTeXMode.textmode: '\\^{S}', LaTeXMode.mathmode: '\\hat{S}'}, 349: {LaTeXMode.textmode: '\\^{s}', LaTeXMode.mathmode: '\\hat{s}'}, 350: {LaTeXMode.textmode: '\\c{S}', LaTeXMode.mathmode: '\\mbox{\\c{S}}'}, 351: {LaTeXMode.textmode: '\\c{s}', LaTeXMode.mathmode: '\\mbox{\\c{s}}'}, 352: {LaTeXMode.textmode: '\\v{S}', LaTeXMode.mathmode: '\\check{S}'}, 353: {LaTeXMode.textmode: '\\v{s}', LaTeXMode.mathmode: '\\check{s}'}, 354: {LaTeXMode.textmode: '\\c{T}', LaTeXMode.mathmode: '\\mbox{\\c{T}}'}, 355: {LaTeXMode.textmode: '\\c{t}', LaTeXMode.mathmode: '\\mbox{\\c{t}}'}, 356: {LaTeXMode.textmode: '\\v{T}', LaTeXMode.mathmode: '\\check{T}'}, 357: {LaTeXMode.textmode: '\\v{t}', LaTeXMode.mathmode: '\\check{t}'}, 358: {LaTeXMode.textmode: '{\\fontencoding{LELA}\\selectfont\\char47}'}, 359: {LaTeXMode.textmode: '{\\fontencoding{LELA}\\selectfont\\char63}'}, 360: {LaTeXMode.textmode: '\\~{U}', LaTeXMode.mathmode: '\\tilde{U}'}, 361: {LaTeXMode.textmode: '\\~{u}', LaTeXMode.mathmode: '\\tilde{u}'}, 362: {LaTeXMode.textmode: '\\={U}', LaTeXMode.mathmode: '\\bar{U}'}, 363: {LaTeXMode.textmode: '\\={u}', LaTeXMode.mathmode: '\\bar{u}'}, 364: {LaTeXMode.textmode: '\\u{U}', LaTeXMode.mathmode: '\\breve{U}'}, 365: {LaTeXMode.textmode: '\\u{u}', LaTeXMode.mathmode: '\\breve{u}'}, 366: {LaTeXMode.textmode: '\\r{U}', LaTeXMode.mathmode: '\\mathring{U}'}, 367: {LaTeXMode.textmode: '\\r{u}', LaTeXMode.mathmode: '\\mathring{u}'}, 368: {LaTeXMode.textmode: '\\H{U}', LaTeXMode.mathmode: '\\mbox{\\H{U}}'}, 369: {LaTeXMode.textmode: '\\H{u}', LaTeXMode.mathmode: '\\mbox{\\H{u}}'}, 370: {LaTeXMode.textmode: '\\k{U}', LaTeXMode.mathmode: '\\k{U}'}, 371: {LaTeXMode.textmode: '\\k{u}'}, 372: {LaTeXMode.textmode: '\\^{W}', LaTeXMode.mathmode: '\\hat{W}'}, 373: {LaTeXMode.textmode: '\\^{w}', LaTeXMode.mathmode: '\\hat{w}'}, 374: {LaTeXMode.textmode: '\\^{Y}', LaTeXMode.mathmode: '\\hat{Y}'}, 375: {LaTeXMode.textmode: '\\^{y}', LaTeXMode.mathmode: '\\hat{y}'}, 376: {LaTeXMode.textmode: '\\"{Y}', LaTeXMode.mathmode: '\\ddot{Y}'}, 377: {LaTeXMode.textmode: "\\'{Z}", LaTeXMode.mathmode: '\\acute{Z}'}, 378: {LaTeXMode.textmode: "\\'{z}", LaTeXMode.mathmode: '\\acute{z}'}, 379: {LaTeXMode.textmode: '\\.{Z}', LaTeXMode.mathmode: '\\dot{Z}'}, 380: {LaTeXMode.textmode: '\\.{z}', LaTeXMode.mathmode: '\\dot{z}'}, 381: {LaTeXMode.textmode: '\\v{Z}', LaTeXMode.mathmode: '\\check{Z}'}, 382: {LaTeXMode.textmode: '\\v{z}', LaTeXMode.mathmode: '\\check{z}'}, 402: {LaTeXMode.textmode: 'f'}, 405: {LaTeXMode.textmode: '\\texthvlig '}, 414: {LaTeXMode.textmode: '\\textnrleg '}, 426: {LaTeXMode.textmode: '\\eth '}, 450: {LaTeXMode.textmode: '\\textdoublepipe '}, 501: {LaTeXMode.textmode: "\\'{g}", LaTeXMode.mathmode: '\\acute{g}'}, 592: {LaTeXMode.textmode: '\\Elztrna '}, 594: {LaTeXMode.textmode: '\\Elztrnsa '}, 596: {LaTeXMode.textmode: '\\Elzopeno '}, 598: {LaTeXMode.textmode: '\\Elzrtld '}, 601: {LaTeXMode.textmode: '\\Elzschwa '}, 603: {LaTeXMode.textmode: '\\varepsilon '}, 609: {LaTeXMode.textmode: 'g'}, 611: {LaTeXMode.textmode: '\\Elzpgamma '}, 612: {LaTeXMode.textmode: '\\Elzpbgam '}, 613: {LaTeXMode.textmode: '\\Elztrnh '}, 620: {LaTeXMode.textmode: '\\Elzbtdl '}, 621: {LaTeXMode.textmode: '\\Elzrtll '}, 623: {LaTeXMode.textmode: '\\Elztrnm '}, 624: {LaTeXMode.textmode: '\\Elztrnmlr '}, 625: {LaTeXMode.textmode: '\\Elzltlmr '}, 627: {LaTeXMode.textmode: '\\Elzrtln '}, 631: {LaTeXMode.textmode: '\\Elzclomeg '}, 632: {LaTeXMode.textmode: '\\textphi '}, 633: {LaTeXMode.textmode: '\\Elztrnr '}, 634: {LaTeXMode.textmode: '\\Elztrnrl '}, 635: {LaTeXMode.textmode: '\\Elzrttrnr '}, 636: {LaTeXMode.textmode: '\\Elzrl '}, 637: {LaTeXMode.textmode: '\\Elzrtlr '}, 638: {LaTeXMode.textmode: '\\Elzfhr '}, 642: {LaTeXMode.textmode: '\\Elzrtls '}, 643: {LaTeXMode.textmode: '\\Elzesh '}, 647: {LaTeXMode.textmode: '\\Elztrnt '}, 648: {LaTeXMode.textmode: '\\Elzrtlt '}, 650: {LaTeXMode.textmode: '\\Elzpupsil '}, 651: {LaTeXMode.textmode: '\\Elzpscrv '}, 652: {LaTeXMode.textmode: '\\Elzinvv '}, 653: {LaTeXMode.textmode: '\\Elzinvw '}, 654: {LaTeXMode.textmode: '\\Elztrny '}, 656: {LaTeXMode.textmode: '\\Elzrtlz '}, 658: {LaTeXMode.textmode: '\\Elzyogh '}, 660: {LaTeXMode.textmode: '\\Elzglst '}, 661: {LaTeXMode.textmode: '\\Elzreglst '}, 662: {LaTeXMode.textmode: '\\Elzinglst '}, 670: {LaTeXMode.textmode: '\\textturnk '}, 676: {LaTeXMode.textmode: '\\Elzdyogh '}, 679: {LaTeXMode.textmode: '\\Elztesh '}, 700: {LaTeXMode.textmode: "'", LaTeXMode.mathmode: '\\rasp'}, 711: {LaTeXMode.textmode: '\\textasciicaron '}, 712: {LaTeXMode.textmode: '\\Elzverts '}, 716: {LaTeXMode.textmode: '\\Elzverti '}, 720: {LaTeXMode.textmode: '\\Elzlmrk '}, 721: {LaTeXMode.textmode: '\\Elzhlmrk '}, 722: {LaTeXMode.textmode: '\\Elzsbrhr '}, 723: {LaTeXMode.textmode: '\\Elzsblhr '}, 724: {LaTeXMode.textmode: '\\Elzrais '}, 725: {LaTeXMode.textmode: '\\Elzlow '}, 728: {LaTeXMode.textmode: '\\textasciibreve ', LaTeXMode.mathmode: '\\u'}, 729: {LaTeXMode.textmode: '\\textperiodcentered ', LaTeXMode.mathmode: '\\dot{}'}, 730: {LaTeXMode.textmode: '\\r{}', LaTeXMode.mathmode: '\\mathring{}'}, 731: {LaTeXMode.textmode: '\\k{}', LaTeXMode.mathmode: '\\mbox{\\k{}}'}, 732: {LaTeXMode.textmode: '\\texttildelow '}, 733: {LaTeXMode.textmode: '\\H{}', LaTeXMode.mathmode: '\\mbox{\\H{}}'}, 741: {LaTeXMode.textmode: '\\tone{55}'}, 742: {LaTeXMode.textmode: '\\tone{44}'}, 743: {LaTeXMode.textmode: '\\tone{33}'}, 744: {LaTeXMode.textmode: '\\tone{22}'}, 745: {LaTeXMode.textmode: '\\tone{11}'}, 768: {LaTeXMode.textmode: '\\`', LaTeXMode.mathmode: '\\grave'}, 769: {LaTeXMode.textmode: "\\'", LaTeXMode.mathmode: '\\acute'}, 770: {LaTeXMode.textmode: '\\^', LaTeXMode.mathmode: '\\hat'}, 771: {LaTeXMode.textmode: '\\~', LaTeXMode.mathmode: '\\tilde'}, 772: {LaTeXMode.textmode: '\\=', LaTeXMode.mathmode: '\\bar'}, 774: {LaTeXMode.textmode: '\\u', LaTeXMode.mathmode: '\\breve'}, 775: {LaTeXMode.textmode: '\\.', LaTeXMode.mathmode: '\\dot'}, 776: {LaTeXMode.textmode: '\\"', LaTeXMode.mathmode: '\\ddot'}, 778: {LaTeXMode.textmode: '\\r', LaTeXMode.mathmode: '\\ocirc'}, 779: {LaTeXMode.textmode: '\\H', LaTeXMode.mathmode: '\\H'}, 780: {LaTeXMode.textmode: '\\v', LaTeXMode.mathmode: '\\check'}, 783: {LaTeXMode.textmode: '\\cyrchar\\C'}, 801: {LaTeXMode.textmode: '\\Elzpalh '}, 807: {LaTeXMode.textmode: '\\c', LaTeXMode.mathmode: '\\c'}, 810: {LaTeXMode.textmode: '\\Elzsbbrg '}, 824: {LaTeXMode.mathmode: '\\forks'}, 902: {LaTeXMode.textmode: "\\'{A}", LaTeXMode.mathmode: '\\acute{A}'}, 904: {LaTeXMode.textmode: "\\'{E}", LaTeXMode.mathmode: '\\acute{E}'}, 905: {LaTeXMode.textmode: "\\'{H}", LaTeXMode.mathmode: '\\grave{H}'}, 906: {LaTeXMode.textmode: "\\'{}{I}", LaTeXMode.mathmode: "\\mathrm{'I}"}, 908: {LaTeXMode.textmode: "\\'{}O", LaTeXMode.mathmode: "\\mathrm{'O}"}, 910: {LaTeXMode.textmode: "\\mathrm{'Y}"}, 911: {LaTeXMode.textmode: "\\mathrm{'\\Omega}"}, 912: {LaTeXMode.textmode: '\\acute{\\ddot{\\iota}}'}, 913: {LaTeXMode.textmode: '\\Alpha '}, 914: {LaTeXMode.textmode: '\\Beta '}, 915: {LaTeXMode.textmode: '\\Gamma ', LaTeXMode.mathmode: '\\Gamma'}, 916: {LaTeXMode.textmode: '\\Delta ', LaTeXMode.mathmode: '\\Delta'}, 917: {LaTeXMode.textmode: '\\Epsilon '}, 918: {LaTeXMode.textmode: '\\Zeta '}, 919: {LaTeXMode.textmode: '\\Eta '}, 920: {LaTeXMode.textmode: '\\Theta ', LaTeXMode.mathmode: '\\Theta'}, 921: {LaTeXMode.textmode: '\\Iota '}, 922: {LaTeXMode.textmode: '\\Kappa '}, 923: {LaTeXMode.textmode: '\\Lambda ', LaTeXMode.mathmode: '\\Lambda'}, 924: {LaTeXMode.textmode: 'M'}, 925: {LaTeXMode.textmode: 'N'}, 926: {LaTeXMode.textmode: '\\Xi ', LaTeXMode.mathmode: '\\Xi'}, 927: {LaTeXMode.textmode: 'O'}, 928: {LaTeXMode.textmode: '\\Pi ', LaTeXMode.mathmode: '\\Pi'}, 929: {LaTeXMode.textmode: '\\Rho '}, 931: {LaTeXMode.textmode: '\\Sigma ', LaTeXMode.mathmode: '\\Sigma'}, 932: {LaTeXMode.textmode: '\\Tau '}, 933: {LaTeXMode.textmode: '\\Upsilon '}, 934: {LaTeXMode.textmode: '\\Phi ', LaTeXMode.mathmode: '\\Phi'}, 935: {LaTeXMode.textmode: '\\Chi '}, 936: {LaTeXMode.textmode: '\\Psi ', LaTeXMode.mathmode: '\\Psi'}, 937: {LaTeXMode.textmode: '\\Omega ', LaTeXMode.mathmode: '\\Omega'}, 938: {LaTeXMode.textmode: '\\mathrm{\\ddot{I}}'}, 939: {LaTeXMode.textmode: '\\mathrm{\\ddot{Y}}'}, 940: {LaTeXMode.textmode: "\\'{$\\alpha$}", LaTeXMode.mathmode: '\\acute{\\alpha}'}, 941: {LaTeXMode.textmode: '\\acute{\\epsilon}'}, 942: {LaTeXMode.textmode: '\\acute{\\eta}'}, 943: {LaTeXMode.textmode: '\\acute{\\iota}'}, 944: {LaTeXMode.textmode: '\\acute{\\ddot{\\upsilon}}'}, 945: {LaTeXMode.textmode: '\\alpha ', LaTeXMode.mathmode: '\\alpha'}, 946: {LaTeXMode.textmode: '\\beta ', LaTeXMode.mathmode: '\\beta'}, 947: {LaTeXMode.textmode: '\\gamma ', LaTeXMode.mathmode: '\\gamma'}, 948: {LaTeXMode.textmode: '\\delta ', LaTeXMode.mathmode: '\\delta'}, 949: {LaTeXMode.textmode: '\\epsilon ', LaTeXMode.mathmode: '\\varepsilon'}, 950: {LaTeXMode.textmode: '\\zeta ', LaTeXMode.mathmode: '\\zeta'}, 951: {LaTeXMode.textmode: '\\eta ', LaTeXMode.mathmode: '\\eta'}, 952: {LaTeXMode.textmode: '\\texttheta ', LaTeXMode.mathmode: '\\theta'}, 953: {LaTeXMode.textmode: '\\iota ', LaTeXMode.mathmode: '\\iota'}, 954: {LaTeXMode.textmode: '\\kappa ', LaTeXMode.mathmode: '\\kappa'}, 955: {LaTeXMode.textmode: '\\lambda ', LaTeXMode.mathmode: '\\lambda'}, 956: {LaTeXMode.textmode: '\\mu ', LaTeXMode.mathmode: '\\mu'}, 957: {LaTeXMode.textmode: '\\nu ', LaTeXMode.mathmode: '\\nu'}, 958: {LaTeXMode.textmode: '\\xi ', LaTeXMode.mathmode: '\\xi'}, 959: {LaTeXMode.textmode: 'o'}, 960: {LaTeXMode.textmode: '\\pi ', LaTeXMode.mathmode: '\\pi'}, 961: {LaTeXMode.textmode: '\\rho ', LaTeXMode.mathmode: '\\rho'}, 962: {LaTeXMode.textmode: '\\varsigma ', LaTeXMode.mathmode: '\\varsigma'}, 963: {LaTeXMode.textmode: '\\sigma ', LaTeXMode.mathmode: '\\sigma'}, 964: {LaTeXMode.textmode: '\\tau ', LaTeXMode.mathmode: '\\tau'}, 965: {LaTeXMode.textmode: '\\upsilon ', LaTeXMode.mathmode: '\\upsilon'}, 966: {LaTeXMode.textmode: '\\varphi ', LaTeXMode.mathmode: '\\varphi'}, 967: {LaTeXMode.textmode: '\\chi ', LaTeXMode.mathmode: '\\chi'}, 968: {LaTeXMode.textmode: '\\psi ', LaTeXMode.mathmode: '\\psi'}, 969: {LaTeXMode.textmode: '\\omega ', LaTeXMode.mathmode: '\\omega'}, 970: {LaTeXMode.textmode: '\\ddot{\\iota}'}, 971: {LaTeXMode.textmode: '\\ddot{\\upsilon}'}, 972: {LaTeXMode.textmode: "\\'{o}", LaTeXMode.mathmode: '\\acute{o}'}, 973: {LaTeXMode.textmode: '\\acute{\\upsilon}'}, 974: {LaTeXMode.textmode: '\\acute{\\omega}'}, 977: {LaTeXMode.textmode: '\\textvartheta ', LaTeXMode.mathmode: '\\vartheta '}, 978: {LaTeXMode.textmode: '\\Upsilon ', LaTeXMode.mathmode: '\\Upsilon'}, 981: {LaTeXMode.textmode: '\\phi ', LaTeXMode.mathmode: '\\phi'}, 982: {LaTeXMode.textmode: '\\varpi ', LaTeXMode.mathmode: '\\varpi'}, 986: {LaTeXMode.textmode: '\\Stigma '}, 988: {LaTeXMode.textmode: '\\Digamma '}, 989: {LaTeXMode.textmode: '\\digamma ', LaTeXMode.mathmode: '\\digamma'}, 990: {LaTeXMode.textmode: '\\Koppa '}, 992: {LaTeXMode.textmode: '\\Sampi '}, 1008: {LaTeXMode.textmode: '\\varkappa ', LaTeXMode.mathmode: '\\varkappa'}, 1009: {LaTeXMode.textmode: '\\varrho ', LaTeXMode.mathmode: '\\varrho'}, 1014: {LaTeXMode.textmode: '\\backepsilon ', LaTeXMode.mathmode: '\\backepsilon'}, 1025: {LaTeXMode.textmode: '\\cyrchar\\CYRYO '}, 1026: {LaTeXMode.textmode: '\\cyrchar\\CYRDJE '}, 1027: {LaTeXMode.textmode: "\\cyrchar{\\'\\CYRG}"}, 1028: {LaTeXMode.textmode: '\\cyrchar\\CYRIE '}, 1029: {LaTeXMode.textmode: '\\cyrchar\\CYRDZE '}, 1030: {LaTeXMode.textmode: '\\cyrchar\\CYRII '}, 1031: {LaTeXMode.textmode: '\\cyrchar\\CYRYI '}, 1032: {LaTeXMode.textmode: '\\cyrchar\\CYRJE '}, 1033: {LaTeXMode.textmode: '\\cyrchar\\CYRLJE '}, 1034: {LaTeXMode.textmode: '\\cyrchar\\CYRNJE '}, 1035: {LaTeXMode.textmode: '\\cyrchar\\CYRTSHE '}, 1036: {LaTeXMode.textmode: "\\cyrchar{\\'\\CYRK}"}, 1038: {LaTeXMode.textmode: '\\cyrchar\\CYRUSHRT '}, 1039: {LaTeXMode.textmode: '\\cyrchar\\CYRDZHE '}, 1040: {LaTeXMode.textmode: '\\cyrchar\\CYRA '}, 1041: {LaTeXMode.textmode: '\\cyrchar\\CYRB '}, 1042: {LaTeXMode.textmode: '\\cyrchar\\CYRV '}, 1043: {LaTeXMode.textmode: '\\cyrchar\\CYRG '}, 1044: {LaTeXMode.textmode: '\\cyrchar\\CYRD '}, 1045: {LaTeXMode.textmode: '\\cyrchar\\CYRE '}, 1046: {LaTeXMode.textmode: '\\cyrchar\\CYRZH '}, 1047: {LaTeXMode.textmode: '\\cyrchar\\CYRZ '}, 1048: {LaTeXMode.textmode: '\\cyrchar\\CYRI '}, 1049: {LaTeXMode.textmode: '\\cyrchar\\CYRISHRT '}, 1050: {LaTeXMode.textmode: '\\cyrchar\\CYRK '}, 1051: {LaTeXMode.textmode: '\\cyrchar\\CYRL '}, 1052: {LaTeXMode.textmode: '\\cyrchar\\CYRM '}, 1053: {LaTeXMode.textmode: '\\cyrchar\\CYRN '}, 1054: {LaTeXMode.textmode: '\\cyrchar\\CYRO '}, 1055: {LaTeXMode.textmode: '\\cyrchar\\CYRP '}, 1056: {LaTeXMode.textmode: '\\cyrchar\\CYRR '}, 1057: {LaTeXMode.textmode: '\\cyrchar\\CYRS '}, 1058: {LaTeXMode.textmode: '\\cyrchar\\CYRT '}, 1059: {LaTeXMode.textmode: '\\cyrchar\\CYRU '}, 1060: {LaTeXMode.textmode: '\\cyrchar\\CYRF '}, 1061: {LaTeXMode.textmode: '\\cyrchar\\CYRH '}, 1062: {LaTeXMode.textmode: '\\cyrchar\\CYRC '}, 1063: {LaTeXMode.textmode: '\\cyrchar\\CYRCH '}, 1064: {LaTeXMode.textmode: '\\cyrchar\\CYRSH '}, 1065: {LaTeXMode.textmode: '\\cyrchar\\CYRSHCH '}, 1066: {LaTeXMode.textmode: '\\cyrchar\\CYRHRDSN '}, 1067: {LaTeXMode.textmode: '\\cyrchar\\CYRERY '}, 1068: {LaTeXMode.textmode: '\\cyrchar\\CYRSFTSN '}, 1069: {LaTeXMode.textmode: '\\cyrchar\\CYREREV '}, 1070: {LaTeXMode.textmode: '\\cyrchar\\CYRYU '}, 1071: {LaTeXMode.textmode: '\\cyrchar\\CYRYA '}, 1072: {LaTeXMode.textmode: '\\cyrchar\\cyra '}, 1073: {LaTeXMode.textmode: '\\cyrchar\\cyrb '}, 1074: {LaTeXMode.textmode: '\\cyrchar\\cyrv '}, 1075: {LaTeXMode.textmode: '\\cyrchar\\cyrg '}, 1076: {LaTeXMode.textmode: '\\cyrchar\\cyrd '}, 1077: {LaTeXMode.textmode: '\\cyrchar\\cyre '}, 1078: {LaTeXMode.textmode: '\\cyrchar\\cyrzh '}, 1079: {LaTeXMode.textmode: '\\cyrchar\\cyrz '}, 1080: {LaTeXMode.textmode: '\\cyrchar\\cyri '}, 1081: {LaTeXMode.textmode: '\\cyrchar\\cyrishrt '}, 1082: {LaTeXMode.textmode: '\\cyrchar\\cyrk '}, 1083: {LaTeXMode.textmode: '\\cyrchar\\cyrl '}, 1084: {LaTeXMode.textmode: '\\cyrchar\\cyrm '}, 1085: {LaTeXMode.textmode: '\\cyrchar\\cyrn '}, 1086: {LaTeXMode.textmode: '\\cyrchar\\cyro '}, 1087: {LaTeXMode.textmode: '\\cyrchar\\cyrp '}, 1088: {LaTeXMode.textmode: '\\cyrchar\\cyrr '}, 1089: {LaTeXMode.textmode: '\\cyrchar\\cyrs '}, 1090: {LaTeXMode.textmode: '\\cyrchar\\cyrt '}, 1091: {LaTeXMode.textmode: '\\cyrchar\\cyru '}, 1092: {LaTeXMode.textmode: '\\cyrchar\\cyrf '}, 1093: {LaTeXMode.textmode: '\\cyrchar\\cyrh '}, 1094: {LaTeXMode.textmode: '\\cyrchar\\cyrc '}, 1095: {LaTeXMode.textmode: '\\cyrchar\\cyrch '}, 1096: {LaTeXMode.textmode: '\\cyrchar\\cyrsh '}, 1097: {LaTeXMode.textmode: '\\cyrchar\\cyrshch '}, 1098: {LaTeXMode.textmode: '\\cyrchar\\cyrhrdsn '}, 1099: {LaTeXMode.textmode: '\\cyrchar\\cyrery '}, 1100: {LaTeXMode.textmode: '\\cyrchar\\cyrsftsn '}, 1101: {LaTeXMode.textmode: '\\cyrchar\\cyrerev '}, 1102: {LaTeXMode.textmode: '\\cyrchar\\cyryu '}, 1103: {LaTeXMode.textmode: '\\cyrchar\\cyrya '}, 1105: {LaTeXMode.textmode: '\\cyrchar\\cyryo '}, 1106: {LaTeXMode.textmode: '\\cyrchar\\cyrdje '}, 1107: {LaTeXMode.textmode: "\\cyrchar{\\'\\cyrg}"}, 1108: {LaTeXMode.textmode: '\\cyrchar\\cyrie '}, 1109: {LaTeXMode.textmode: '\\cyrchar\\cyrdze '}, 1110: {LaTeXMode.textmode: '\\cyrchar\\cyrii '}, 1111: {LaTeXMode.textmode: '\\cyrchar\\cyryi '}, 1112: {LaTeXMode.textmode: '\\cyrchar\\cyrje '}, 1113: {LaTeXMode.textmode: '\\cyrchar\\cyrlje '}, 1114: {LaTeXMode.textmode: '\\cyrchar\\cyrnje '}, 1115: {LaTeXMode.textmode: '\\cyrchar\\cyrtshe '}, 1116: {LaTeXMode.textmode: "\\cyrchar{\\'\\cyrk}"}, 1118: {LaTeXMode.textmode: '\\cyrchar\\cyrushrt '}, 1119: {LaTeXMode.textmode: '\\cyrchar\\cyrdzhe '}, 1120: {LaTeXMode.textmode: '\\cyrchar\\CYROMEGA '}, 1121: {LaTeXMode.textmode: '\\cyrchar\\cyromega '}, 1122: {LaTeXMode.textmode: '\\cyrchar\\CYRYAT '}, 1124: {LaTeXMode.textmode: '\\cyrchar\\CYRIOTE '}, 1125: {LaTeXMode.textmode: '\\cyrchar\\cyriote '}, 1126: {LaTeXMode.textmode: '\\cyrchar\\CYRLYUS '}, 1127: {LaTeXMode.textmode: '\\cyrchar\\cyrlyus '}, 1128: {LaTeXMode.textmode: '\\cyrchar\\CYRIOTLYUS '}, 1129: {LaTeXMode.textmode: '\\cyrchar\\cyriotlyus '}, 1130: {LaTeXMode.textmode: '\\cyrchar\\CYRBYUS '}, 1132: {LaTeXMode.textmode: '\\cyrchar\\CYRIOTBYUS '}, 1133: {LaTeXMode.textmode: '\\cyrchar\\cyriotbyus '}, 1134: {LaTeXMode.textmode: '\\cyrchar\\CYRKSI '}, 1135: {LaTeXMode.textmode: '\\cyrchar\\cyrksi '}, 1136: {LaTeXMode.textmode: '\\cyrchar\\CYRPSI '}, 1137: {LaTeXMode.textmode: '\\cyrchar\\cyrpsi '}, 1138: {LaTeXMode.textmode: '\\cyrchar\\CYRFITA '}, 1140: {LaTeXMode.textmode: '\\cyrchar\\CYRIZH '}, 1144: {LaTeXMode.textmode: '\\cyrchar\\CYRUK '}, 1145: {LaTeXMode.textmode: '\\cyrchar\\cyruk '}, 1146: {LaTeXMode.textmode: '\\cyrchar\\CYROMEGARND '}, 1147: {LaTeXMode.textmode: '\\cyrchar\\cyromegarnd '}, 1148: {LaTeXMode.textmode: '\\cyrchar\\CYROMEGATITLO '}, 1149: {LaTeXMode.textmode: '\\cyrchar\\cyromegatitlo '}, 1150: {LaTeXMode.textmode: '\\cyrchar\\CYROT '}, 1151: {LaTeXMode.textmode: '\\cyrchar\\cyrot '}, 1152: {LaTeXMode.textmode: '\\cyrchar\\CYRKOPPA '}, 1153: {LaTeXMode.textmode: '\\cyrchar\\cyrkoppa '}, 1154: {LaTeXMode.textmode: '\\cyrchar\\cyrthousands '}, 1160: {LaTeXMode.textmode: '\\cyrchar\\cyrhundredthousands '}, 1161: {LaTeXMode.textmode: '\\cyrchar\\cyrmillions '}, 1164: {LaTeXMode.textmode: '\\cyrchar\\CYRSEMISFTSN '}, 1165: {LaTeXMode.textmode: '\\cyrchar\\cyrsemisftsn '}, 1166: {LaTeXMode.textmode: '\\cyrchar\\CYRRTICK '}, 1167: {LaTeXMode.textmode: '\\cyrchar\\cyrrtick '}, 1168: {LaTeXMode.textmode: '\\cyrchar\\CYRGUP '}, 1169: {LaTeXMode.textmode: '\\cyrchar\\cyrgup '}, 1170: {LaTeXMode.textmode: '\\cyrchar\\CYRGHCRS '}, 1171: {LaTeXMode.textmode: '\\cyrchar\\cyrghcrs '}, 1172: {LaTeXMode.textmode: '\\cyrchar\\CYRGHK '}, 1173: {LaTeXMode.textmode: '\\cyrchar\\cyrghk '}, 1174: {LaTeXMode.textmode: '\\cyrchar\\CYRZHDSC '}, 1175: {LaTeXMode.textmode: '\\cyrchar\\cyrzhdsc '}, 1176: {LaTeXMode.textmode: '\\cyrchar\\CYRZDSC '}, 1177: {LaTeXMode.textmode: '\\cyrchar\\cyrzdsc '}, 1178: {LaTeXMode.textmode: '\\cyrchar\\CYRKDSC '}, 1179: {LaTeXMode.textmode: '\\cyrchar\\cyrkdsc '}, 1180: {LaTeXMode.textmode: '\\cyrchar\\CYRKVCRS '}, 1181: {LaTeXMode.textmode: '\\cyrchar\\cyrkvcrs '}, 1182: {LaTeXMode.textmode: '\\cyrchar\\CYRKHCRS '}, 1183: {LaTeXMode.textmode: '\\cyrchar\\cyrkhcrs '}, 1184: {LaTeXMode.textmode: '\\cyrchar\\CYRKBEAK '}, 1185: {LaTeXMode.textmode: '\\cyrchar\\cyrkbeak '}, 1186: {LaTeXMode.textmode: '\\cyrchar\\CYRNDSC '}, 1187: {LaTeXMode.textmode: '\\cyrchar\\cyrndsc '}, 1188: {LaTeXMode.textmode: '\\cyrchar\\CYRNG '}, 1189: {LaTeXMode.textmode: '\\cyrchar\\cyrng '}, 1190: {LaTeXMode.textmode: '\\cyrchar\\CYRPHK '}, 1191: {LaTeXMode.textmode: '\\cyrchar\\cyrphk '}, 1192: {LaTeXMode.textmode: '\\cyrchar\\CYRABHHA '}, 1193: {LaTeXMode.textmode: '\\cyrchar\\cyrabhha '}, 1194: {LaTeXMode.textmode: '\\cyrchar\\CYRSDSC '}, 1195: {LaTeXMode.textmode: '\\cyrchar\\cyrsdsc '}, 1196: {LaTeXMode.textmode: '\\cyrchar\\CYRTDSC '}, 1197: {LaTeXMode.textmode: '\\cyrchar\\cyrtdsc '}, 1198: {LaTeXMode.textmode: '\\cyrchar\\CYRY '}, 1199: {LaTeXMode.textmode: '\\cyrchar\\cyry '}, 1200: {LaTeXMode.textmode: '\\cyrchar\\CYRYHCRS '}, 1201: {LaTeXMode.textmode: '\\cyrchar\\cyryhcrs '}, 1202: {LaTeXMode.textmode: '\\cyrchar\\CYRHDSC '}, 1203: {LaTeXMode.textmode: '\\cyrchar\\cyrhdsc '}, 1204: {LaTeXMode.textmode: '\\cyrchar\\CYRTETSE '}, 1205: {LaTeXMode.textmode: '\\cyrchar\\cyrtetse '}, 1206: {LaTeXMode.textmode: '\\cyrchar\\CYRCHRDSC '}, 1207: {LaTeXMode.textmode: '\\cyrchar\\cyrchrdsc '}, 1208: {LaTeXMode.textmode: '\\cyrchar\\CYRCHVCRS '}, 1209: {LaTeXMode.textmode: '\\cyrchar\\cyrchvcrs '}, 1210: {LaTeXMode.textmode: '\\cyrchar\\CYRSHHA '}, 1211: {LaTeXMode.textmode: '\\cyrchar\\cyrshha '}, 1212: {LaTeXMode.textmode: '\\cyrchar\\CYRABHCH '}, 1213: {LaTeXMode.textmode: '\\cyrchar\\cyrabhch '}, 1214: {LaTeXMode.textmode: '\\cyrchar\\CYRABHCHDSC '}, 1215: {LaTeXMode.textmode: '\\cyrchar\\cyrabhchdsc '}, 1216: {LaTeXMode.textmode: '\\cyrchar\\CYRpalochka '}, 1219: {LaTeXMode.textmode: '\\cyrchar\\CYRKHK '}, 1220: {LaTeXMode.textmode: '\\cyrchar\\cyrkhk '}, 1223: {LaTeXMode.textmode: '\\cyrchar\\CYRNHK '}, 1224: {LaTeXMode.textmode: '\\cyrchar\\cyrnhk '}, 1227: {LaTeXMode.textmode: '\\cyrchar\\CYRCHLDSC '}, 1228: {LaTeXMode.textmode: '\\cyrchar\\cyrchldsc '}, 1236: {LaTeXMode.textmode: '\\cyrchar\\CYRAE '}, 1237: {LaTeXMode.textmode: '\\cyrchar\\cyrae '}, 1240: {LaTeXMode.textmode: '\\cyrchar\\CYRSCHWA '}, 1241: {LaTeXMode.textmode: '\\cyrchar\\cyrschwa '}, 1248: {LaTeXMode.textmode: '\\cyrchar\\CYRABHDZE '}, 1249: {LaTeXMode.textmode: '\\cyrchar\\cyrabhdze '}, 1256: {LaTeXMode.textmode: '\\cyrchar\\CYROTLD '}, 1257: {LaTeXMode.textmode: '\\cyrchar\\cyrotld '}, 8194: {LaTeXMode.textmode: '\\hspace{0.6em}', LaTeXMode.mathmode: '\\enspace'}, 8195: {LaTeXMode.textmode: '\\hspace{1em}', LaTeXMode.mathmode: '\\quad'}, 8196: {LaTeXMode.textmode: '\\hspace{0.33em}'}, 8197: {LaTeXMode.textmode: '\\hspace{0.25em}', LaTeXMode.mathmode: '\\thickspace'}, 8198: {LaTeXMode.textmode: '\\hspace{0.166em}'}, 8199: {LaTeXMode.textmode: '\\hphantom{0}'}, 8200: {LaTeXMode.textmode: '\\hphantom{,}'}, 8201: {LaTeXMode.textmode: '\\hspace{0.167em}', LaTeXMode.mathmode: '\\thinspace'}, 8202: {LaTeXMode.textmode: '\\mkern1mu ', LaTeXMode.mathmode: '\\hspace'}, 8208: {LaTeXMode.textmode: '-'}, 8211: {LaTeXMode.textmode: '\\textendash ', LaTeXMode.mathmode: '\\endash'}, 8212: {LaTeXMode.textmode: '\\textemdash ', LaTeXMode.mathmode: '\\emdash'}, 8213: {LaTeXMode.textmode: '\\rule{1em}{1pt}'}, 8214: {LaTeXMode.textmode: '\\Vert ', LaTeXMode.mathmode: '\\Vert'}, 8216: {LaTeXMode.textmode: '`', LaTeXMode.mathmode: '\\lq'}, 8217: {LaTeXMode.textmode: "'", LaTeXMode.mathmode: '\\rq'}, 8218: {LaTeXMode.textmode: ','}, 8219: {LaTeXMode.textmode: '\\Elzreapos '}, 8220: {LaTeXMode.textmode: '\\textquotedblleft ', LaTeXMode.mathmode: '\\textquotedblleft'}, 8221: {LaTeXMode.textmode: '\\textquotedblright ', LaTeXMode.mathmode: '\\textquotedblright'}, 8222: {LaTeXMode.textmode: ',,'}, 8224: {LaTeXMode.textmode: '\\textdagger ', LaTeXMode.mathmode: '\\dagger'}, 8225: {LaTeXMode.textmode: '\\textdaggerdbl ', LaTeXMode.mathmode: '\\ddagger'}, 8226: {LaTeXMode.textmode: '\\textbullet ', LaTeXMode.mathmode: '\\bullet'}, 8228: {LaTeXMode.textmode: '.'}, 8229: {LaTeXMode.textmode: '..'}, 8230: {LaTeXMode.textmode: '\\ldots ', LaTeXMode.mathmode: '\\dots'}, 8240: {LaTeXMode.textmode: '\\textperthousand '}, 8241: {LaTeXMode.textmode: '\\textpertenthousand '}, 8242: {LaTeXMode.textmode: "{'}", LaTeXMode.mathmode: '\\prime'}, 8243: {LaTeXMode.textmode: "{''}"}, 8244: {LaTeXMode.textmode: "{'''}"}, 8245: {LaTeXMode.textmode: '\\backprime ', LaTeXMode.mathmode: '\\backprime'}, 8279: {LaTeXMode.textmode: "''''"}, 8411: {LaTeXMode.textmode: '\\dddot ', LaTeXMode.mathmode: '\\dddot'}, 8412: {LaTeXMode.textmode: '\\ddddot ', LaTeXMode.mathmode: '\\ddddot'}, 8421: {LaTeXMode.textmode: '{\\rlap{\\textbackslash}{{/}\\!\\!{/}}}'}, 8450: {LaTeXMode.textmode: '\\mathbb{C}'}, 8459: {LaTeXMode.textmode: '\\mathscr{H}'}, 8460: {LaTeXMode.textmode: '\\mathfrak{H}'}, 8461: {LaTeXMode.textmode: '\\mathbb{H}'}, 8463: {LaTeXMode.textmode: '\\hslash ', LaTeXMode.mathmode: '\\hslash'}, 8464: {LaTeXMode.textmode: '\\mathscr{I}'}, 8465: {LaTeXMode.textmode: '\\mathfrak{I}', LaTeXMode.mathmode: '\\Im'}, 8466: {LaTeXMode.textmode: '\\mathscr{L}'}, 8467: {LaTeXMode.textmode: '\\mathscr{l}', LaTeXMode.mathmode: '\\ell'}, 8469: {LaTeXMode.textmode: '\\mathbb{N}'}, 8470: {LaTeXMode.textmode: '\\cyrchar\\textnumero ', LaTeXMode.mathmode: '\\textnumero'}, 8472: {LaTeXMode.textmode: '\\wp ', LaTeXMode.mathmode: '\\wp'}, 8473: {LaTeXMode.textmode: '\\mathbb{P}'}, 8474: {LaTeXMode.textmode: '\\mathbb{Q}'}, 8475: {LaTeXMode.textmode: '\\mathscr{R}'}, 8476: {LaTeXMode.textmode: '\\mathfrak{R}', LaTeXMode.mathmode: '\\Re'}, 8477: {LaTeXMode.textmode: '\\mathbb{R}'}, 8478: {LaTeXMode.textmode: '\\Elzxrat '}, 8482: {LaTeXMode.textmode: '\\texttrademark '}, 8484: {LaTeXMode.textmode: '\\mathbb{Z}'}, 8486: {LaTeXMode.textmode: '\\Omega '}, 8487: {LaTeXMode.textmode: '\\mho ', LaTeXMode.mathmode: '\\mho'}, 8488: {LaTeXMode.textmode: '\\mathfrak{Z}'}, 8489: {LaTeXMode.textmode: '\\ElsevierGlyph{2129}'}, 8491: {LaTeXMode.textmode: '\\AA ', LaTeXMode.mathmode: '\\AA'}, 8492: {LaTeXMode.textmode: '\\mathscr{B}'}, 8493: {LaTeXMode.textmode: '\\mathfrak{C}'}, 8495: {LaTeXMode.textmode: '\\mathscr{e}'}, 8496: {LaTeXMode.textmode: '\\mathscr{E}'}, 8497: {LaTeXMode.textmode: '\\mathscr{F}'}, 8499: {LaTeXMode.textmode: '\\mathscr{M}'}, 8500: {LaTeXMode.textmode: '\\mathscr{o}'}, 8501: {LaTeXMode.textmode: '\\aleph ', LaTeXMode.mathmode: '\\aleph'}, 8502: {LaTeXMode.textmode: '\\beth ', LaTeXMode.mathmode: '\\beth'}, 8503: {LaTeXMode.textmode: '\\gimel ', LaTeXMode.mathmode: '\\gimel'}, 8504: {LaTeXMode.textmode: '\\daleth ', LaTeXMode.mathmode: '\\daleth'}, 8512: {LaTeXMode.mathmode: '\\bbsum'}, 8531: {LaTeXMode.textmode: '\\textfrac{1}{3}'}, 8532: {LaTeXMode.textmode: '\\textfrac{2}{3}'}, 8533: {LaTeXMode.textmode: '\\textfrac{1}{5}'}, 8534: {LaTeXMode.textmode: '\\textfrac{2}{5}'}, 8535: {LaTeXMode.textmode: '\\textfrac{3}{5}'}, 8536: {LaTeXMode.textmode: '\\textfrac{4}{5}'}, 8537: {LaTeXMode.textmode: '\\textfrac{1}{6}'}, 8538: {LaTeXMode.textmode: '\\textfrac{5}{6}'}, 8539: {LaTeXMode.textmode: '\\textfrac{1}{8}'}, 8540: {LaTeXMode.textmode: '\\textfrac{3}{8}'}, 8541: {LaTeXMode.textmode: '\\textfrac{5}{8}'}, 8542: {LaTeXMode.textmode: '\\textfrac{7}{8}'}, 8592: {LaTeXMode.textmode: '\\leftarrow ', LaTeXMode.mathmode: '\\leftarrow'}, 8593: {LaTeXMode.textmode: '\\uparrow ', LaTeXMode.mathmode: '\\uparrow'}, 8594: {LaTeXMode.textmode: '\\rightarrow ', LaTeXMode.mathmode: '\\rightarrow'}, 8595: {LaTeXMode.textmode: '\\downarrow ', LaTeXMode.mathmode: '\\downarrow'}, 8596: {LaTeXMode.textmode: '\\leftrightarrow ', LaTeXMode.mathmode: '\\leftrightarrow'}, 8597: {LaTeXMode.textmode: '\\updownarrow ', LaTeXMode.mathmode: '\\updownarrow'}, 8598: {LaTeXMode.textmode: '\\nwarrow ', LaTeXMode.mathmode: '\\nwarrow'}, 8599: {LaTeXMode.textmode: '\\nearrow ', LaTeXMode.mathmode: '\\nearrow'}, 8600: {LaTeXMode.textmode: '\\searrow ', LaTeXMode.mathmode: '\\searrow'}, 8601: {LaTeXMode.textmode: '\\swarrow ', LaTeXMode.mathmode: '\\swarrow'}, 8602: {LaTeXMode.textmode: '\\nleftarrow ', LaTeXMode.mathmode: '\\nleftarrow'}, 8603: {LaTeXMode.textmode: '\\nrightarrow ', LaTeXMode.mathmode: '\\nrightarrow'}, 8604: {LaTeXMode.textmode: '\\arrowwaveleft ', LaTeXMode.mathmode: '\\leftsquigarrow'}, 8605: {LaTeXMode.textmode: '\\arrowwaveright ', LaTeXMode.mathmode: '\\rightsquigarrow'}, 8606: {LaTeXMode.textmode: '\\twoheadleftarrow ', LaTeXMode.mathmode: '\\twoheadleftarrow'}, 8608: {LaTeXMode.textmode: '\\twoheadrightarrow ', LaTeXMode.mathmode: '\\twoheadrightarrow'}, 8610: {LaTeXMode.textmode: '\\leftarrowtail ', LaTeXMode.mathmode: '\\leftarrowtail'}, 8611: {LaTeXMode.textmode: '\\rightarrowtail ', LaTeXMode.mathmode: '\\rightarrowtail'}, 8614: {LaTeXMode.textmode: '\\mapsto ', LaTeXMode.mathmode: '\\mapsto'}, 8617: {LaTeXMode.textmode: '\\hookleftarrow ', LaTeXMode.mathmode: '\\hookleftarrow'}, 8618: {LaTeXMode.textmode: '\\hookrightarrow ', LaTeXMode.mathmode: '\\hookrightarrow'}, 8619: {LaTeXMode.textmode: '\\looparrowleft ', LaTeXMode.mathmode: '\\looparrowleft'}, 8620: {LaTeXMode.textmode: '\\looparrowright ', LaTeXMode.mathmode: '\\looparrowright'}, 8621: {LaTeXMode.textmode: '\\leftrightsquigarrow ', LaTeXMode.mathmode: '\\leftrightsquigarrow'}, 8622: {LaTeXMode.textmode: '\\nleftrightarrow ', LaTeXMode.mathmode: '\\nleftrightarrow'}, 8624: {LaTeXMode.textmode: '\\Lsh ', LaTeXMode.mathmode: '\\Lsh'}, 8625: {LaTeXMode.textmode: '\\Rsh ', LaTeXMode.mathmode: '\\Rsh'}, 8627: {LaTeXMode.textmode: '\\ElsevierGlyph{21B3}'}, 8630: {LaTeXMode.textmode: '\\curvearrowleft ', LaTeXMode.mathmode: '\\curvearrowleft'}, 8631: {LaTeXMode.textmode: '\\curvearrowright ', LaTeXMode.mathmode: '\\curvearrowright'}, 8634: {LaTeXMode.textmode: '\\circlearrowleft '}, 8635: {LaTeXMode.textmode: '\\circlearrowright '}, 8636: {LaTeXMode.textmode: '\\leftharpoonup ', LaTeXMode.mathmode: '\\leftharpoonup'}, 8637: {LaTeXMode.textmode: '\\leftharpoondown ', LaTeXMode.mathmode: '\\leftharpoondown'}, 8638: {LaTeXMode.textmode: '\\upharpoonright ', LaTeXMode.mathmode: '\\upharpoonleft'}, 8639: {LaTeXMode.textmode: '\\upharpoonleft ', LaTeXMode.mathmode: '\\upharpoonright'}, 8640: {LaTeXMode.textmode: '\\rightharpoonup ', LaTeXMode.mathmode: '\\rightharpoonup'}, 8641: {LaTeXMode.textmode: '\\rightharpoondown ', LaTeXMode.mathmode: '\\rightharpoondown'}, 8642: {LaTeXMode.textmode: '\\downharpoonright ', LaTeXMode.mathmode: '\\downharpoonright'}, 8643: {LaTeXMode.textmode: '\\downharpoonleft ', LaTeXMode.mathmode: '\\downharpoonleft'}, 8644: {LaTeXMode.textmode: '\\rightleftarrows ', LaTeXMode.mathmode: '\\rightleftarrows'}, 8645: {LaTeXMode.textmode: '\\dblarrowupdown '}, 8646: {LaTeXMode.textmode: '\\leftrightarrows ', LaTeXMode.mathmode: '\\leftrightarrows'}, 8647: {LaTeXMode.textmode: '\\leftleftarrows ', LaTeXMode.mathmode: '\\leftleftarrows'}, 8648: {LaTeXMode.textmode: '\\upuparrows ', LaTeXMode.mathmode: '\\upuparrows'}, 8649: {LaTeXMode.textmode: '\\rightrightarrows ', LaTeXMode.mathmode: '\\rightrightarrows'}, 8650: {LaTeXMode.textmode: '\\downdownarrows ', LaTeXMode.mathmode: '\\downdownarrows'}, 8651: {LaTeXMode.textmode: '\\leftrightharpoons ', LaTeXMode.mathmode: '\\leftrightharpoons'}, 8652: {LaTeXMode.textmode: '\\rightleftharpoons ', LaTeXMode.mathmode: '\\rightleftharpoons'}, 8653: {LaTeXMode.textmode: '\\nLeftarrow ', LaTeXMode.mathmode: '\\nLeftarrow'}, 8654: {LaTeXMode.textmode: '\\nLeftrightarrow ', LaTeXMode.mathmode: '\\nLeftrightarrow'}, 8655: {LaTeXMode.textmode: '\\nRightarrow ', LaTeXMode.mathmode: '\\nRightarrow'}, 8656: {LaTeXMode.textmode: '\\Leftarrow ', LaTeXMode.mathmode: '\\Leftarrow'}, 8657: {LaTeXMode.textmode: '\\Uparrow ', LaTeXMode.mathmode: '\\Uparrow'}, 8658: {LaTeXMode.textmode: '\\Rightarrow ', LaTeXMode.mathmode: '\\Rightarrow'}, 8659: {LaTeXMode.textmode: '\\Downarrow ', LaTeXMode.mathmode: '\\Downarrow'}, 8660: {LaTeXMode.textmode: '\\Leftrightarrow ', LaTeXMode.mathmode: '\\Leftrightarrow'}, 8661: {LaTeXMode.textmode: '\\Updownarrow ', LaTeXMode.mathmode: '\\Updownarrow'}, 8666: {LaTeXMode.textmode: '\\Lleftarrow ', LaTeXMode.mathmode: '\\Lleftarrow'}, 8667: {LaTeXMode.textmode: '\\Rrightarrow ', LaTeXMode.mathmode: '\\Rrightarrow'}, 8669: {LaTeXMode.textmode: '\\rightsquigarrow '}, 8693: {LaTeXMode.textmode: '\\DownArrowUpArrow '}, 8701: {LaTeXMode.mathmode: '\\leftarrowtriangle'}, 8702: {LaTeXMode.mathmode: '\\rightarrowtriangle'}, 8703: {LaTeXMode.mathmode: '\\leftrightarrowtria*'}, 8704: {LaTeXMode.textmode: '\\forall ', LaTeXMode.mathmode: '\\forall'}, 8705: {LaTeXMode.textmode: '\\complement ', LaTeXMode.mathmode: '\\complement'}, 8706: {LaTeXMode.textmode: '\\partial ', LaTeXMode.mathmode: '\\partial'}, 8707: {LaTeXMode.textmode: '\\exists ', LaTeXMode.mathmode: '\\exists'}, 8708: {LaTeXMode.textmode: '\\nexists ', LaTeXMode.mathmode: '\\nexists'}, 8709: {LaTeXMode.textmode: '\\varnothing ', LaTeXMode.mathmode: '\\varnothing'}, 8711: {LaTeXMode.textmode: '\\nabla ', LaTeXMode.mathmode: '\\nabla'}, 8712: {LaTeXMode.textmode: '\\in '}, 8713: {LaTeXMode.textmode: '\\not\\in ', LaTeXMode.mathmode: '\\notin'}, 8714: {LaTeXMode.mathmode: '\\in'}, 8715: {LaTeXMode.textmode: '\\ni ', LaTeXMode.mathmode: '\\ni'}, 8716: {LaTeXMode.textmode: '\\not\\ni '}, 8719: {LaTeXMode.textmode: '\\prod ', LaTeXMode.mathmode: '\\prod'}, 8720: {LaTeXMode.textmode: '\\coprod ', LaTeXMode.mathmode: '\\coprod'}, 8721: {LaTeXMode.textmode: '\\sum ', LaTeXMode.mathmode: '\\sum'}, 8722: {LaTeXMode.textmode: '-', LaTeXMode.mathmode: '-'}, 8723: {LaTeXMode.textmode: '\\mp ', LaTeXMode.mathmode: '\\mp'}, 8724: {LaTeXMode.textmode: '\\dotplus ', LaTeXMode.mathmode: '\\dotplus'}, 8726: {LaTeXMode.textmode: '\\setminus ', LaTeXMode.mathmode: '\\setminus'}, 8727: {LaTeXMode.textmode: '{_\\ast}', LaTeXMode.mathmode: '\\ast'}, 8728: {LaTeXMode.textmode: '\\circ ', LaTeXMode.mathmode: '\\circ'}, 8729: {LaTeXMode.textmode: '\\bullet '}, 8730: {LaTeXMode.textmode: '\\surd ', LaTeXMode.mathmode: '\\surd'}, 8733: {LaTeXMode.textmode: '\\propto ', LaTeXMode.mathmode: '\\propto'}, 8734: {LaTeXMode.textmode: '\\infty ', LaTeXMode.mathmode: '\\infty'}, 8735: {LaTeXMode.textmode: '\\rightangle '}, 8736: {LaTeXMode.textmode: '\\angle ', LaTeXMode.mathmode: '\\angle'}, 8737: {LaTeXMode.textmode: '\\measuredangle ', LaTeXMode.mathmode: '\\measuredangle'}, 8738: {LaTeXMode.textmode: '\\sphericalangle ', LaTeXMode.mathmode: '\\sphericalangle'}, 8739: {LaTeXMode.textmode: '\\mid ', LaTeXMode.mathmode: '\\mid'}, 8740: {LaTeXMode.textmode: '\\nmid ', LaTeXMode.mathmode: '\\nmid'}, 8741: {LaTeXMode.textmode: '\\parallel ', LaTeXMode.mathmode: '\\parallel'}, 8742: {LaTeXMode.textmode: '\\nparallel ', LaTeXMode.mathmode: '\\nparallel'}, 8743: {LaTeXMode.textmode: '\\wedge ', LaTeXMode.mathmode: '\\wedge'}, 8744: {LaTeXMode.textmode: '\\vee ', LaTeXMode.mathmode: '\\vee'}, 8745: {LaTeXMode.textmode: '\\cap ', LaTeXMode.mathmode: '\\cap'}, 8746: {LaTeXMode.textmode: '\\cup ', LaTeXMode.mathmode: '\\cup'}, 8747: {LaTeXMode.textmode: '\\int ', LaTeXMode.mathmode: '\\int'}, 8748: {LaTeXMode.textmode: '\\int\\!\\int ', LaTeXMode.mathmode: '\\iint'}, 8749: {LaTeXMode.textmode: '\\int\\!\\int\\!\\int ', LaTeXMode.mathmode: '\\iiint'}, 8750: {LaTeXMode.textmode: '\\oint ', LaTeXMode.mathmode: '\\oint'}, 8751: {LaTeXMode.textmode: '\\surfintegral ', LaTeXMode.mathmode: '\\oiint'}, 8752: {LaTeXMode.textmode: '\\volintegral ', LaTeXMode.mathmode: '\\oiiint'}, 8753: {LaTeXMode.textmode: '\\clwintegral '}, 8754: {LaTeXMode.textmode: '\\ElsevierGlyph{2232}'}, 8755: {LaTeXMode.textmode: '\\ElsevierGlyph{2233}'}, 8756: {LaTeXMode.textmode: '\\therefore ', LaTeXMode.mathmode: '\\therefore'}, 8757: {LaTeXMode.textmode: '\\because ', LaTeXMode.mathmode: '\\because'}, 8759: {LaTeXMode.textmode: '\\Colon ', LaTeXMode.mathmode: '\\Colon'}, 8760: {LaTeXMode.textmode: '\\ElsevierGlyph{2238}', LaTeXMode.mathmode: '\\dotminus'}, 8762: {LaTeXMode.textmode: '\\mathbin{{:}\\!\\!{-}\\!\\!{:}}'}, 8763: {LaTeXMode.textmode: '\\homothetic ', LaTeXMode.mathmode: '\\kernelcontraction'}, 8764: {LaTeXMode.textmode: '\\sim ', LaTeXMode.mathmode: '\\sim'}, 8765: {LaTeXMode.textmode: '\\backsim ', LaTeXMode.mathmode: '\\backsim'}, 8766: {LaTeXMode.textmode: '\\lazysinv '}, 8768: {LaTeXMode.textmode: '\\wr ', LaTeXMode.mathmode: '\\wr'}, 8769: {LaTeXMode.textmode: '\\not\\sim ', LaTeXMode.mathmode: '\\nsim'}, 8770: {LaTeXMode.textmode: '\\NotEqualTilde ', LaTeXMode.mathmode: '\\neqsim'}, 8771: {LaTeXMode.textmode: '\\simeq ', LaTeXMode.mathmode: '\\simeq'}, 8772: {LaTeXMode.textmode: '\\not\\simeq ', LaTeXMode.mathmode: '\\nsime'}, 8773: {LaTeXMode.textmode: '\\cong ', LaTeXMode.mathmode: '\\cong'}, 8774: {LaTeXMode.textmode: '\\approxnotequal '}, 8775: {LaTeXMode.textmode: '\\not\\cong ', LaTeXMode.mathmode: '\\ncong'}, 8776: {LaTeXMode.textmode: '\\approx ', LaTeXMode.mathmode: '\\approx'}, 8777: {LaTeXMode.textmode: '\\not\\approx ', LaTeXMode.mathmode: '\\napprox'}, 8778: {LaTeXMode.textmode: '\\approxeq ', LaTeXMode.mathmode: '\\approxeq'}, 8779: {LaTeXMode.textmode: '\\not\\apid '}, 8780: {LaTeXMode.textmode: '\\allequal '}, 8781: {LaTeXMode.textmode: '\\asymp ', LaTeXMode.mathmode: '\\asymp'}, 8782: {LaTeXMode.textmode: '\\NotHumpDownHump ', LaTeXMode.mathmode: '\\nBumpeq'}, 8783: {LaTeXMode.textmode: '\\NotHumpEqual ', LaTeXMode.mathmode: '\\nbumpeq'}, 8784: {LaTeXMode.textmode: '\\not\\doteq'}, 8785: {LaTeXMode.textmode: '\\doteqdot ', LaTeXMode.mathmode: '\\Doteq'}, 8786: {LaTeXMode.textmode: '\\fallingdotseq ', LaTeXMode.mathmode: '\\fallingdotseq'}, 8787: {LaTeXMode.textmode: '\\risingdotseq ', LaTeXMode.mathmode: '\\risingdotseq'}, 8788: {LaTeXMode.textmode: ':=', LaTeXMode.mathmode: '\\coloneq'}, 8789: {LaTeXMode.textmode: '=:', LaTeXMode.mathmode: '\\eqcolon'}, 8790: {LaTeXMode.textmode: '\\eqcirc ', LaTeXMode.mathmode: '\\eqcirc'}, 8791: {LaTeXMode.textmode: '\\circeq ', LaTeXMode.mathmode: '\\circeq'}, 8793: {LaTeXMode.textmode: '\\estimates ', LaTeXMode.mathmode: '\\wedgeq'}, 8794: {LaTeXMode.textmode: '\\ElsevierGlyph{225A}'}, 8795: {LaTeXMode.textmode: '\\starequal '}, 8796: {LaTeXMode.textmode: '\\triangleq ', LaTeXMode.mathmode: '\\triangleq'}, 8799: {LaTeXMode.textmode: '\\ElsevierGlyph{225F}', LaTeXMode.mathmode: '\\questeq'}, 8800: {LaTeXMode.textmode: '\\not =', LaTeXMode.mathmode: '\\ne'}, 8801: {LaTeXMode.textmode: '\\equiv ', LaTeXMode.mathmode: '\\equiv'}, 8802: {LaTeXMode.textmode: '\\not\\equiv ', LaTeXMode.mathmode: '\\nequiv'}, 8804: {LaTeXMode.textmode: '\\leq ', LaTeXMode.mathmode: '\\le'}, 8805: {LaTeXMode.textmode: '\\geq ', LaTeXMode.mathmode: '\\ge'}, 8806: {LaTeXMode.textmode: '\\leqq ', LaTeXMode.mathmode: '\\leqq'}, 8807: {LaTeXMode.textmode: '\\geqq ', LaTeXMode.mathmode: '\\geqq'}, 8808: {LaTeXMode.textmode: '\\lvertneqq ', LaTeXMode.mathmode: '\\lvertneqq'}, 8809: {LaTeXMode.textmode: '\\gvertneqq ', LaTeXMode.mathmode: '\\gvertneqq'}, 8810: {LaTeXMode.textmode: '\\NotLessLess '}, 8811: {LaTeXMode.textmode: '\\NotGreaterGreater '}, 8812: {LaTeXMode.textmode: '\\between ', LaTeXMode.mathmode: '\\between'}, 8813: {LaTeXMode.textmode: '\\not\\kern-0.3em\\times '}, 8814: {LaTeXMode.textmode: '\\not<', LaTeXMode.mathmode: '\\nless'}, 8815: {LaTeXMode.textmode: '\\not>', LaTeXMode.mathmode: '\\ngtr'}, 8816: {LaTeXMode.textmode: '\\not\\leq ', LaTeXMode.mathmode: '\\nleq'}, 8817: {LaTeXMode.textmode: '\\not\\geq ', LaTeXMode.mathmode: '\\ngeq'}, 8818: {LaTeXMode.textmode: '\\lessequivlnt ', LaTeXMode.mathmode: '\\lesssim'}, 8819: {LaTeXMode.textmode: '\\greaterequivlnt ', LaTeXMode.mathmode: '\\gtrsim'}, 8820: {LaTeXMode.textmode: '\\ElsevierGlyph{2274}'}, 8821: {LaTeXMode.textmode: '\\ElsevierGlyph{2275}'}, 8822: {LaTeXMode.textmode: '\\lessgtr ', LaTeXMode.mathmode: '\\lessgtr'}, 8823: {LaTeXMode.textmode: '\\gtrless ', LaTeXMode.mathmode: '\\gtrless'}, 8824: {LaTeXMode.textmode: '\\notlessgreater '}, 8825: {LaTeXMode.textmode: '\\notgreaterless '}, 8826: {LaTeXMode.textmode: '\\prec ', LaTeXMode.mathmode: '\\prec'}, 8827: {LaTeXMode.textmode: '\\succ ', LaTeXMode.mathmode: '\\succ'}, 8828: {LaTeXMode.textmode: '\\preccurlyeq ', LaTeXMode.mathmode: '\\preccurlyeq'}, 8829: {LaTeXMode.textmode: '\\succcurlyeq ', LaTeXMode.mathmode: '\\succcurlyeq'}, 8830: {LaTeXMode.textmode: '\\NotPrecedesTilde ', LaTeXMode.mathmode: '\\nprecsim'}, 8831: {LaTeXMode.textmode: '\\NotSucceedsTilde ', LaTeXMode.mathmode: '\\nsuccsim'}, 8832: {LaTeXMode.textmode: '\\not\\prec ', LaTeXMode.mathmode: '\\nprec'}, 8833: {LaTeXMode.textmode: '\\not\\succ ', LaTeXMode.mathmode: '\\nsucc'}, 8834: {LaTeXMode.textmode: '\\subset ', LaTeXMode.mathmode: '\\subset'}, 8835: {LaTeXMode.textmode: '\\supset ', LaTeXMode.mathmode: '\\supset'}, 8836: {LaTeXMode.textmode: '\\not\\subset ', LaTeXMode.mathmode: '\\nsubset'}, 8837: {LaTeXMode.textmode: '\\not\\supset ', LaTeXMode.mathmode: '\\nsupset'}, 8838: {LaTeXMode.textmode: '\\subseteq ', LaTeXMode.mathmode: '\\subseteq'}, 8839: {LaTeXMode.textmode: '\\supseteq ', LaTeXMode.mathmode: '\\supseteq'}, 8840: {LaTeXMode.textmode: '\\not\\subseteq ', LaTeXMode.mathmode: '\\nsubseteq'}, 8841: {LaTeXMode.textmode: '\\not\\supseteq ', LaTeXMode.mathmode: '\\nsupseteq'}, 8842: {LaTeXMode.textmode: '\\varsubsetneqq ', LaTeXMode.mathmode: '\\varsubsetneqq'}, 8843: {LaTeXMode.textmode: '\\varsupsetneq ', LaTeXMode.mathmode: '\\varsupsetneq'}, 8846: {LaTeXMode.textmode: '\\uplus ', LaTeXMode.mathmode: '\\uplus'}, 8847: {LaTeXMode.textmode: '\\NotSquareSubset '}, 8848: {LaTeXMode.textmode: '\\NotSquareSuperset '}, 8849: {LaTeXMode.textmode: '\\sqsubseteq ', LaTeXMode.mathmode: '\\sqsubseteq'}, 8850: {LaTeXMode.textmode: '\\sqsupseteq ', LaTeXMode.mathmode: '\\sqsupseteq'}, 8851: {LaTeXMode.textmode: '\\sqcap ', LaTeXMode.mathmode: '\\sqcap'}, 8852: {LaTeXMode.textmode: '\\sqcup ', LaTeXMode.mathmode: '\\sqcup'}, 8853: {LaTeXMode.textmode: '\\oplus ', LaTeXMode.mathmode: '\\oplus'}, 8854: {LaTeXMode.textmode: '\\ominus ', LaTeXMode.mathmode: '\\ominus'}, 8855: {LaTeXMode.textmode: '\\otimes ', LaTeXMode.mathmode: '\\otimes'}, 8856: {LaTeXMode.textmode: '\\oslash ', LaTeXMode.mathmode: '\\oslash'}, 8857: {LaTeXMode.textmode: '\\odot ', LaTeXMode.mathmode: '\\odot'}, 8858: {LaTeXMode.textmode: '\\circledcirc ', LaTeXMode.mathmode: '\\circledcirc'}, 8859: {LaTeXMode.textmode: '\\circledast ', LaTeXMode.mathmode: '\\circledast'}, 8861: {LaTeXMode.textmode: '\\circleddash ', LaTeXMode.mathmode: '\\circleddash'}, 8862: {LaTeXMode.textmode: '\\boxplus ', LaTeXMode.mathmode: '\\boxplus'}, 8863: {LaTeXMode.textmode: '\\boxminus ', LaTeXMode.mathmode: '\\boxminus'}, 8864: {LaTeXMode.textmode: '\\boxtimes ', LaTeXMode.mathmode: '\\boxtimes'}, 8865: {LaTeXMode.textmode: '\\boxdot ', LaTeXMode.mathmode: '\\boxdot'}, 8866: {LaTeXMode.textmode: '\\vdash ', LaTeXMode.mathmode: '\\vdash'}, 8867: {LaTeXMode.textmode: '\\dashv ', LaTeXMode.mathmode: '\\dashv'}, 8868: {LaTeXMode.textmode: '\\top ', LaTeXMode.mathmode: '\\top'}, 8869: {LaTeXMode.textmode: '\\perp ', LaTeXMode.mathmode: '\\perp'}, 8871: {LaTeXMode.textmode: '\\truestate ', LaTeXMode.mathmode: '\\models'}, 8872: {LaTeXMode.textmode: '\\forcesextra ', LaTeXMode.mathmode: '\\vDash'}, 8873: {LaTeXMode.textmode: '\\Vdash ', LaTeXMode.mathmode: '\\Vdash'}, 8874: {LaTeXMode.textmode: '\\Vvdash ', LaTeXMode.mathmode: '\\Vvdash'}, 8875: {LaTeXMode.textmode: '\\VDash '}, 8876: {LaTeXMode.textmode: '\\nvdash ', LaTeXMode.mathmode: '\\nvdash'}, 8877: {LaTeXMode.textmode: '\\nvDash ', LaTeXMode.mathmode: '\\nvDash'}, 8878: {LaTeXMode.textmode: '\\nVdash ', LaTeXMode.mathmode: '\\nVdash'}, 8879: {LaTeXMode.textmode: '\\nVDash ', LaTeXMode.mathmode: '\\nVDash'}, 8882: {LaTeXMode.textmode: '\\vartriangleleft ', LaTeXMode.mathmode: '\\vartriangleleft'}, 8883: {LaTeXMode.textmode: '\\vartriangleright ', LaTeXMode.mathmode: '\\vartriangleright'}, 8884: {LaTeXMode.textmode: '\\trianglelefteq ', LaTeXMode.mathmode: '\\trianglelefteq'}, 8885: {LaTeXMode.textmode: '\\trianglerighteq ', LaTeXMode.mathmode: '\\trianglerighteq'}, 8886: {LaTeXMode.textmode: '\\original '}, 8887: {LaTeXMode.textmode: '\\image '}, 8888: {LaTeXMode.textmode: '\\multimap ', LaTeXMode.mathmode: '\\multimap'}, 8889: {LaTeXMode.textmode: '\\hermitconjmatrix '}, 8890: {LaTeXMode.textmode: '\\intercal ', LaTeXMode.mathmode: '\\intercal'}, 8891: {LaTeXMode.textmode: '\\veebar ', LaTeXMode.mathmode: '\\veebar'}, 8894: {LaTeXMode.textmode: '\\rightanglearc '}, 8896: {LaTeXMode.textmode: '\\ElsevierGlyph{22C0}', LaTeXMode.mathmode: '\\bigwedge'}, 8897: {LaTeXMode.textmode: '\\ElsevierGlyph{22C1}', LaTeXMode.mathmode: '\\bigvee'}, 8898: {LaTeXMode.textmode: '\\bigcap ', LaTeXMode.mathmode: '\\bigcap'}, 8899: {LaTeXMode.textmode: '\\bigcup ', LaTeXMode.mathmode: '\\bigcup'}, 8900: {LaTeXMode.textmode: '\\diamond ', LaTeXMode.mathmode: '\\diamond'}, 8901: {LaTeXMode.textmode: '\\cdot ', LaTeXMode.mathmode: '\\cdot'}, 8902: {LaTeXMode.textmode: '\\star ', LaTeXMode.mathmode: '\\star'}, 8903: {LaTeXMode.textmode: '\\divideontimes ', LaTeXMode.mathmode: '\\divideontimes'}, 8904: {LaTeXMode.textmode: '\\bowtie ', LaTeXMode.mathmode: '\\bowtie'}, 8905: {LaTeXMode.textmode: '\\ltimes ', LaTeXMode.mathmode: '\\ltimes'}, 8906: {LaTeXMode.textmode: '\\rtimes ', LaTeXMode.mathmode: '\\rtimes'}, 8907: {LaTeXMode.textmode: '\\leftthreetimes ', LaTeXMode.mathmode: '\\leftthreetimes'}, 8908: {LaTeXMode.textmode: '\\rightthreetimes ', LaTeXMode.mathmode: '\\rightthreetimes'}, 8909: {LaTeXMode.textmode: '\\backsimeq ', LaTeXMode.mathmode: '\\backsimeq'}, 8910: {LaTeXMode.textmode: '\\curlyvee ', LaTeXMode.mathmode: '\\curlyvee'}, 8911: {LaTeXMode.textmode: '\\curlywedge ', LaTeXMode.mathmode: '\\curlywedge'}, 8912: {LaTeXMode.textmode: '\\Subset ', LaTeXMode.mathmode: '\\Subset'}, 8913: {LaTeXMode.textmode: '\\Supset ', LaTeXMode.mathmode: '\\Supset'}, 8914: {LaTeXMode.textmode: '\\Cap ', LaTeXMode.mathmode: '\\Cap'}, 8915: {LaTeXMode.textmode: '\\Cup ', LaTeXMode.mathmode: '\\Cup'}, 8916: {LaTeXMode.textmode: '\\pitchfork ', LaTeXMode.mathmode: '\\pitchfork'}, 8918: {LaTeXMode.textmode: '\\lessdot ', LaTeXMode.mathmode: '\\lessdot'}, 8919: {LaTeXMode.textmode: '\\gtrdot ', LaTeXMode.mathmode: '\\gtrdot'}, 8920: {LaTeXMode.textmode: '\\verymuchless '}, 8921: {LaTeXMode.textmode: '\\verymuchgreater ', LaTeXMode.mathmode: '\\ggg'}, 8922: {LaTeXMode.textmode: '\\lesseqgtr ', LaTeXMode.mathmode: '\\lesseqgtr'}, 8923: {LaTeXMode.textmode: '\\gtreqless ', LaTeXMode.mathmode: '\\gtreqless'}, 8926: {LaTeXMode.textmode: '\\curlyeqprec ', LaTeXMode.mathmode: '\\curlyeqprec'}, 8927: {LaTeXMode.textmode: '\\curlyeqsucc ', LaTeXMode.mathmode: '\\curlyeqsucc'}, 8930: {LaTeXMode.textmode: '\\not\\sqsubseteq '}, 8931: {LaTeXMode.textmode: '\\not\\sqsupseteq '}, 8933: {LaTeXMode.textmode: '\\Elzsqspne '}, 8934: {LaTeXMode.textmode: '\\lnsim ', LaTeXMode.mathmode: '\\lnsim'}, 8935: {LaTeXMode.textmode: '\\gnsim ', LaTeXMode.mathmode: '\\gnsim'}, 8936: {LaTeXMode.textmode: '\\precedesnotsimilar ', LaTeXMode.mathmode: '\\precnsim'}, 8937: {LaTeXMode.textmode: '\\succnsim ', LaTeXMode.mathmode: '\\succnsim'}, 8938: {LaTeXMode.textmode: '\\ntriangleleft ', LaTeXMode.mathmode: '\\ntriangleleft'}, 8939: {LaTeXMode.textmode: '\\ntriangleright ', LaTeXMode.mathmode: '\\ntriangleright'}, 8940: {LaTeXMode.textmode: '\\ntrianglelefteq ', LaTeXMode.mathmode: '\\ntrianglelefteq'}, 8941: {LaTeXMode.textmode: '\\ntrianglerighteq ', LaTeXMode.mathmode: '\\ntrianglerighteq'}, 8942: {LaTeXMode.textmode: '\\vdots ', LaTeXMode.mathmode: '\\vdots'}, 8943: {LaTeXMode.textmode: '\\cdots ', LaTeXMode.mathmode: '\\cdots'}, 8944: {LaTeXMode.textmode: '\\upslopeellipsis ', LaTeXMode.mathmode: '\\adots'}, 8945: {LaTeXMode.textmode: '\\downslopeellipsis ', LaTeXMode.mathmode: '\\ddots'}, 8966: {LaTeXMode.textmode: '\\varperspcorrespond '}, 8968: {LaTeXMode.textmode: '\\lceil ', LaTeXMode.mathmode: '\\lceil'}, 8969: {LaTeXMode.textmode: '\\rceil ', LaTeXMode.mathmode: '\\rceil'}, 8970: {LaTeXMode.textmode: '\\lfloor ', LaTeXMode.mathmode: '\\lfloor'}, 8971: {LaTeXMode.textmode: '\\rfloor ', LaTeXMode.mathmode: '\\rfloor'}, 8981: {LaTeXMode.textmode: '\\recorder '}, 8982: {LaTeXMode.textmode: '\\mathchar"2208'}, 8988: {LaTeXMode.textmode: '\\ulcorner ', LaTeXMode.mathmode: '\\ulcorner'}, 8989: {LaTeXMode.textmode: '\\urcorner ', LaTeXMode.mathmode: '\\urcorner'}, 8990: {LaTeXMode.textmode: '\\llcorner ', LaTeXMode.mathmode: '\\llcorner'}, 8991: {LaTeXMode.textmode: '\\lrcorner ', LaTeXMode.mathmode: '\\lrcorner'}, 8994: {LaTeXMode.textmode: '\\frown ', LaTeXMode.mathmode: '\\frown'}, 8995: {LaTeXMode.textmode: '\\smile ', LaTeXMode.mathmode: '\\smile'}, 9021: {LaTeXMode.textmode: '\\ElsevierGlyph{E838}', LaTeXMode.mathmode: '\\obar'}, 9123: {LaTeXMode.textmode: '\\Elzdlcorn '}, 9136: {LaTeXMode.textmode: '\\lmoustache ', LaTeXMode.mathmode: '\\lmoustache'}, 9137: {LaTeXMode.textmode: '\\rmoustache ', LaTeXMode.mathmode: '\\rmoustache'}, 9251: {LaTeXMode.textmode: '\\textvisiblespace '}, 9312: {LaTeXMode.textmode: '\\ding{172}'}, 9313: {LaTeXMode.textmode: '\\ding{173}'}, 9314: {LaTeXMode.textmode: '\\ding{174}'}, 9315: {LaTeXMode.textmode: '\\ding{175}'}, 9316: {LaTeXMode.textmode: '\\ding{176}'}, 9317: {LaTeXMode.textmode: '\\ding{177}'}, 9318: {LaTeXMode.textmode: '\\ding{178}'}, 9319: {LaTeXMode.textmode: '\\ding{179}'}, 9320: {LaTeXMode.textmode: '\\ding{180}'}, 9321: {LaTeXMode.textmode: '\\ding{181}'}, 9416: {LaTeXMode.textmode: '\\circledS ', LaTeXMode.mathmode: '\\circledS'}, 9478: {LaTeXMode.textmode: '\\Elzdshfnc '}, 9497: {LaTeXMode.textmode: '\\Elzsqfnw '}, 9585: {LaTeXMode.textmode: '\\diagup ', LaTeXMode.mathmode: '\\diagup'}, 9586: {LaTeXMode.mathmode: '\\diagdown'}, 9632: {LaTeXMode.textmode: '\\ding{110}', LaTeXMode.mathmode: '\\blacksquare'}, 9633: {LaTeXMode.textmode: '\\square ', LaTeXMode.mathmode: '\\square'}, 9642: {LaTeXMode.textmode: '\\blacksquare '}, 9645: {LaTeXMode.textmode: '\\fbox{~~}'}, 9647: {LaTeXMode.textmode: '\\Elzvrecto '}, 9649: {LaTeXMode.textmode: '\\ElsevierGlyph{E381}'}, 9650: {LaTeXMode.textmode: '\\ding{115}'}, 9651: {LaTeXMode.textmode: '\\bigtriangleup ', LaTeXMode.mathmode: '\\bigtriangleup'}, 9652: {LaTeXMode.textmode: '\\blacktriangle ', LaTeXMode.mathmode: '\\blacktriangle'}, 9653: {LaTeXMode.textmode: '\\vartriangle ', LaTeXMode.mathmode: '\\vartriangle'}, 9656: {LaTeXMode.textmode: '\\blacktriangleright ', LaTeXMode.mathmode: '\\blacktriangleright'}, 9657: {LaTeXMode.textmode: '\\triangleright ', LaTeXMode.mathmode: '\\triangleright'}, 9660: {LaTeXMode.textmode: '\\ding{116}'}, 9661: {LaTeXMode.textmode: '\\bigtriangledown ', LaTeXMode.mathmode: '\\bigtriangledown'}, 9662: {LaTeXMode.textmode: '\\blacktriangledown ', LaTeXMode.mathmode: '\\blacktriangledown'}, 9663: {LaTeXMode.textmode: '\\triangledown ', LaTeXMode.mathmode: '\\triangledown'}, 9666: {LaTeXMode.textmode: '\\blacktriangleleft ', LaTeXMode.mathmode: '\\blacktriangleleft'}, 9667: {LaTeXMode.textmode: '\\triangleleft ', LaTeXMode.mathmode: '\\triangleleft'}, 9670: {LaTeXMode.textmode: '\\ding{117}'}, 9674: {LaTeXMode.textmode: '\\lozenge ', LaTeXMode.mathmode: '\\lozenge'}, 9675: {LaTeXMode.textmode: '\\bigcirc ', LaTeXMode.mathmode: '\\bigcirc'}, 9679: {LaTeXMode.textmode: '\\ding{108}'}, 9680: {LaTeXMode.textmode: '\\Elzcirfl '}, 9681: {LaTeXMode.textmode: '\\Elzcirfr '}, 9682: {LaTeXMode.textmode: '\\Elzcirfb '}, 9687: {LaTeXMode.textmode: '\\ding{119}'}, 9688: {LaTeXMode.textmode: '\\Elzrvbull '}, 9703: {LaTeXMode.textmode: '\\Elzsqfl '}, 9704: {LaTeXMode.textmode: '\\Elzsqfr '}, 9706: {LaTeXMode.textmode: '\\Elzsqfse '}, 9711: {LaTeXMode.textmode: '\\bigcirc '}, 9733: {LaTeXMode.textmode: '\\ding{72}', LaTeXMode.mathmode: '\\bigstar'}, 9742: {LaTeXMode.textmode: '\\ding{37}'}, 9755: {LaTeXMode.textmode: '\\ding{42}'}, 9758: {LaTeXMode.textmode: '\\ding{43}'}, 9792: {LaTeXMode.textmode: '\\venus '}, 9794: {LaTeXMode.textmode: '\\male '}, 9799: {LaTeXMode.textmode: '\\pluto '}, 9800: {LaTeXMode.textmode: '\\aries '}, 9801: {LaTeXMode.textmode: '\\taurus '}, 9802: {LaTeXMode.textmode: '\\gemini '}, 9803: {LaTeXMode.textmode: '\\cancer '}, 9804: {LaTeXMode.textmode: '\\leo '}, 9805: {LaTeXMode.textmode: '\\virgo '}, 9806: {LaTeXMode.textmode: '\\libra '}, 9807: {LaTeXMode.textmode: '\\scorpio '}, 9808: {LaTeXMode.textmode: '\\sagittarius '}, 9809: {LaTeXMode.textmode: '\\capricornus '}, 9810: {LaTeXMode.textmode: '\\aquarius '}, 9811: {LaTeXMode.textmode: '\\pisces '}, 9824: {LaTeXMode.textmode: '\\ding{171}', LaTeXMode.mathmode: '\\spadesuit'}, 9826: {LaTeXMode.textmode: '\\diamond ', LaTeXMode.mathmode: '\\diamondsuit'}, 9827: {LaTeXMode.textmode: '\\ding{168}', LaTeXMode.mathmode: '\\clubsuit'}, 9829: {LaTeXMode.textmode: '\\ding{170}'}, 9830: {LaTeXMode.textmode: '\\ding{169}'}, 9833: {LaTeXMode.textmode: '\\quarternote '}, 9834: {LaTeXMode.textmode: '\\eighthnote '}, 9837: {LaTeXMode.textmode: '\\flat ', LaTeXMode.mathmode: '\\flat'}, 9838: {LaTeXMode.textmode: '\\natural ', LaTeXMode.mathmode: '\\natural'}, 9839: {LaTeXMode.textmode: '\\sharp ', LaTeXMode.mathmode: '\\sharp'}, 9985: {LaTeXMode.textmode: '\\ding{33}'}, 9986: {LaTeXMode.textmode: '\\ding{34}'}, 9987: {LaTeXMode.textmode: '\\ding{35}'}, 9988: {LaTeXMode.textmode: '\\ding{36}'}, 9990: {LaTeXMode.textmode: '\\ding{38}'}, 9991: {LaTeXMode.textmode: '\\ding{39}'}, 9992: {LaTeXMode.textmode: '\\ding{40}'}, 9993: {LaTeXMode.textmode: '\\ding{41}'}, 9996: {LaTeXMode.textmode: '\\ding{44}'}, 9997: {LaTeXMode.textmode: '\\ding{45}'}, 9998: {LaTeXMode.textmode: '\\ding{46}'}, 9999: {LaTeXMode.textmode: '\\ding{47}'}, 10000: {LaTeXMode.textmode: '\\ding{48}'}, 10001: {LaTeXMode.textmode: '\\ding{49}'}, 10002: {LaTeXMode.textmode: '\\ding{50}'}, 10003: {LaTeXMode.textmode: '\\ding{51}', LaTeXMode.mathmode: '\\checkmark'}, 10004: {LaTeXMode.textmode: '\\ding{52}'}, 10005: {LaTeXMode.textmode: '\\ding{53}'}, 10006: {LaTeXMode.textmode: '\\ding{54}'}, 10007: {LaTeXMode.textmode: '\\ding{55}'}, 10008: {LaTeXMode.textmode: '\\ding{56}'}, 10009: {LaTeXMode.textmode: '\\ding{57}'}, 10010: {LaTeXMode.textmode: '\\ding{58}'}, 10011: {LaTeXMode.textmode: '\\ding{59}'}, 10012: {LaTeXMode.textmode: '\\ding{60}'}, 10013: {LaTeXMode.textmode: '\\ding{61}'}, 10014: {LaTeXMode.textmode: '\\ding{62}'}, 10015: {LaTeXMode.textmode: '\\ding{63}'}, 10016: {LaTeXMode.textmode: '\\ding{64}', LaTeXMode.mathmode: '\\maltese'}, 10017: {LaTeXMode.textmode: '\\ding{65}'}, 10018: {LaTeXMode.textmode: '\\ding{66}'}, 10019: {LaTeXMode.textmode: '\\ding{67}'}, 10020: {LaTeXMode.textmode: '\\ding{68}'}, 10021: {LaTeXMode.textmode: '\\ding{69}'}, 10022: {LaTeXMode.textmode: '\\ding{70}'}, 10023: {LaTeXMode.textmode: '\\ding{71}'}, 10025: {LaTeXMode.textmode: '\\ding{73}'}, 10026: {LaTeXMode.textmode: '\\ding{74}'}, 10027: {LaTeXMode.textmode: '\\ding{75}'}, 10028: {LaTeXMode.textmode: '\\ding{76}'}, 10029: {LaTeXMode.textmode: '\\ding{77}'}, 10030: {LaTeXMode.textmode: '\\ding{78}'}, 10031: {LaTeXMode.textmode: '\\ding{79}'}, 10032: {LaTeXMode.textmode: '\\ding{80}'}, 10033: {LaTeXMode.textmode: '\\ding{81}'}, 10034: {LaTeXMode.textmode: '\\ding{82}'}, 10035: {LaTeXMode.textmode: '\\ding{83}'}, 10036: {LaTeXMode.textmode: '\\ding{84}'}, 10037: {LaTeXMode.textmode: '\\ding{85}'}, 10038: {LaTeXMode.textmode: '\\ding{86}'}, 10039: {LaTeXMode.textmode: '\\ding{87}'}, 10040: {LaTeXMode.textmode: '\\ding{88}'}, 10041: {LaTeXMode.textmode: '\\ding{89}'}, 10042: {LaTeXMode.textmode: '\\ding{90}'}, 10043: {LaTeXMode.textmode: '\\ding{91}'}, 10044: {LaTeXMode.textmode: '\\ding{92}'}, 10045: {LaTeXMode.textmode: '\\ding{93}'}, 10046: {LaTeXMode.textmode: '\\ding{94}'}, 10047: {LaTeXMode.textmode: '\\ding{95}'}, 10048: {LaTeXMode.textmode: '\\ding{96}'}, 10049: {LaTeXMode.textmode: '\\ding{97}'}, 10050: {LaTeXMode.textmode: '\\ding{98}'}, 10051: {LaTeXMode.textmode: '\\ding{99}'}, 10052: {LaTeXMode.textmode: '\\ding{100}'}, 10053: {LaTeXMode.textmode: '\\ding{101}'}, 10054: {LaTeXMode.textmode: '\\ding{102}'}, 10055: {LaTeXMode.textmode: '\\ding{103}'}, 10056: {LaTeXMode.textmode: '\\ding{104}'}, 10057: {LaTeXMode.textmode: '\\ding{105}'}, 10058: {LaTeXMode.textmode: '\\ding{106}'}, 10059: {LaTeXMode.textmode: '\\ding{107}'}, 10061: {LaTeXMode.textmode: '\\ding{109}'}, 10063: {LaTeXMode.textmode: '\\ding{111}'}, 10064: {LaTeXMode.textmode: '\\ding{112}'}, 10065: {LaTeXMode.textmode: '\\ding{113}'}, 10066: {LaTeXMode.textmode: '\\ding{114}'}, 10070: {LaTeXMode.textmode: '\\ding{118}'}, 10072: {LaTeXMode.textmode: '\\ding{120}'}, 10073: {LaTeXMode.textmode: '\\ding{121}'}, 10074: {LaTeXMode.textmode: '\\ding{122}'}, 10075: {LaTeXMode.textmode: '\\ding{123}'}, 10076: {LaTeXMode.textmode: '\\ding{124}'}, 10077: {LaTeXMode.textmode: '\\ding{125}'}, 10078: {LaTeXMode.textmode: '\\ding{126}'}, 10081: {LaTeXMode.textmode: '\\ding{161}'}, 10082: {LaTeXMode.textmode: '\\ding{162}'}, 10083: {LaTeXMode.textmode: '\\ding{163}'}, 10084: {LaTeXMode.textmode: '\\ding{164}'}, 10085: {LaTeXMode.textmode: '\\ding{165}'}, 10086: {LaTeXMode.textmode: '\\ding{166}'}, 10087: {LaTeXMode.textmode: '\\ding{167}'}, 10102: {LaTeXMode.textmode: '\\ding{182}'}, 10103: {LaTeXMode.textmode: '\\ding{183}'}, 10104: {LaTeXMode.textmode: '\\ding{184}'}, 10105: {LaTeXMode.textmode: '\\ding{185}'}, 10106: {LaTeXMode.textmode: '\\ding{186}'}, 10107: {LaTeXMode.textmode: '\\ding{187}'}, 10108: {LaTeXMode.textmode: '\\ding{188}'}, 10109: {LaTeXMode.textmode: '\\ding{189}'}, 10110: {LaTeXMode.textmode: '\\ding{190}'}, 10111: {LaTeXMode.textmode: '\\ding{191}'}, 10112: {LaTeXMode.textmode: '\\ding{192}'}, 10113: {LaTeXMode.textmode: '\\ding{193}'}, 10114: {LaTeXMode.textmode: '\\ding{194}'}, 10115: {LaTeXMode.textmode: '\\ding{195}'}, 10116: {LaTeXMode.textmode: '\\ding{196}'}, 10117: {LaTeXMode.textmode: '\\ding{197}'}, 10118: {LaTeXMode.textmode: '\\ding{198}'}, 10119: {LaTeXMode.textmode: '\\ding{199}'}, 10120: {LaTeXMode.textmode: '\\ding{200}'}, 10121: {LaTeXMode.textmode: '\\ding{201}'}, 10122: {LaTeXMode.textmode: '\\ding{202}'}, 10123: {LaTeXMode.textmode: '\\ding{203}'}, 10124: {LaTeXMode.textmode: '\\ding{204}'}, 10125: {LaTeXMode.textmode: '\\ding{205}'}, 10126: {LaTeXMode.textmode: '\\ding{206}'}, 10127: {LaTeXMode.textmode: '\\ding{207}'}, 10128: {LaTeXMode.textmode: '\\ding{208}'}, 10129: {LaTeXMode.textmode: '\\ding{209}'}, 10130: {LaTeXMode.textmode: '\\ding{210}'}, 10131: {LaTeXMode.textmode: '\\ding{211}'}, 10132: {LaTeXMode.textmode: '\\ding{212}'}, 10136: {LaTeXMode.textmode: '\\ding{216}'}, 10137: {LaTeXMode.textmode: '\\ding{217}'}, 10138: {LaTeXMode.textmode: '\\ding{218}'}, 10139: {LaTeXMode.textmode: '\\ding{219}'}, 10140: {LaTeXMode.textmode: '\\ding{220}'}, 10141: {LaTeXMode.textmode: '\\ding{221}'}, 10142: {LaTeXMode.textmode: '\\ding{222}'}, 10143: {LaTeXMode.textmode: '\\ding{223}'}, 10144: {LaTeXMode.textmode: '\\ding{224}'}, 10145: {LaTeXMode.textmode: '\\ding{225}'}, 10146: {LaTeXMode.textmode: '\\ding{226}'}, 10147: {LaTeXMode.textmode: '\\ding{227}'}, 10148: {LaTeXMode.textmode: '\\ding{228}'}, 10149: {LaTeXMode.textmode: '\\ding{229}'}, 10150: {LaTeXMode.textmode: '\\ding{230}'}, 10151: {LaTeXMode.textmode: '\\ding{231}'}, 10152: {LaTeXMode.textmode: '\\ding{232}'}, 10153: {LaTeXMode.textmode: '\\ding{233}'}, 10154: {LaTeXMode.textmode: '\\ding{234}'}, 10155: {LaTeXMode.textmode: '\\ding{235}'}, 10156: {LaTeXMode.textmode: '\\ding{236}'}, 10157: {LaTeXMode.textmode: '\\ding{237}'}, 10158: {LaTeXMode.textmode: '\\ding{238}'}, 10159: {LaTeXMode.textmode: '\\ding{239}'}, 10161: {LaTeXMode.textmode: '\\ding{241}'}, 10162: {LaTeXMode.textmode: '\\ding{242}'}, 10163: {LaTeXMode.textmode: '\\ding{243}'}, 10164: {LaTeXMode.textmode: '\\ding{244}'}, 10165: {LaTeXMode.textmode: '\\ding{245}'}, 10166: {LaTeXMode.textmode: '\\ding{246}'}, 10167: {LaTeXMode.textmode: '\\ding{247}'}, 10168: {LaTeXMode.textmode: '\\ding{248}'}, 10169: {LaTeXMode.textmode: '\\ding{249}'}, 10170: {LaTeXMode.textmode: '\\ding{250}'}, 10171: {LaTeXMode.textmode: '\\ding{251}'}, 10172: {LaTeXMode.textmode: '\\ding{252}'}, 10173: {LaTeXMode.textmode: '\\ding{253}'}, 10174: {LaTeXMode.textmode: '\\ding{254}'}, 10229: {LaTeXMode.textmode: '\\longleftarrow ', LaTeXMode.mathmode: '\\longleftarrow'}, 10230: {LaTeXMode.textmode: '\\longrightarrow ', LaTeXMode.mathmode: '\\longrightarrow'}, 10231: {LaTeXMode.textmode: '\\longleftrightarrow ', LaTeXMode.mathmode: '\\longleftrightarrow'}, 10232: {LaTeXMode.textmode: '\\Longleftarrow ', LaTeXMode.mathmode: '\\Longleftarrow'}, 10233: {LaTeXMode.textmode: '\\Longrightarrow ', LaTeXMode.mathmode: '\\Longrightarrow'}, 10234: {LaTeXMode.textmode: '\\Longleftrightarrow ', LaTeXMode.mathmode: '\\Longleftrightarrow'}, 10236: {LaTeXMode.textmode: '\\longmapsto ', LaTeXMode.mathmode: '\\longmapsto'}, 10239: {LaTeXMode.textmode: '\\sim\\joinrel\\leadsto'}, 10501: {LaTeXMode.textmode: '\\ElsevierGlyph{E212}'}, 10502: {LaTeXMode.mathmode: '\\Mapsfrom'}, 10503: {LaTeXMode.mathmode: '\\Mapsto'}, 10506: {LaTeXMode.mathmode: '\\Uuparrow'}, 10507: {LaTeXMode.mathmode: '\\Ddownarrow'}, 10511: {LaTeXMode.mathmode: '\\dbkarow'}, 10512: {LaTeXMode.mathmode: '\\drbkarrow'}, 10514: {LaTeXMode.textmode: '\\UpArrowBar '}, 10515: {LaTeXMode.textmode: '\\DownArrowBar '}, 10518: {LaTeXMode.mathmode: '\\twoheadrightarrowtail'}, 10531: {LaTeXMode.textmode: '\\ElsevierGlyph{E20C}'}, 10532: {LaTeXMode.textmode: '\\ElsevierGlyph{E20D}'}, 10533: {LaTeXMode.textmode: '\\ElsevierGlyph{E20B}', LaTeXMode.mathmode: '\\hksearow'}, 10534: {LaTeXMode.textmode: '\\ElsevierGlyph{E20A}', LaTeXMode.mathmode: '\\hkswarow'}, 10535: {LaTeXMode.textmode: '\\ElsevierGlyph{E211}', LaTeXMode.mathmode: '\\tona'}, 10536: {LaTeXMode.textmode: '\\ElsevierGlyph{E20E}', LaTeXMode.mathmode: '\\toea'}, 10537: {LaTeXMode.textmode: '\\ElsevierGlyph{E20F}', LaTeXMode.mathmode: '\\tosa'}, 10538: {LaTeXMode.textmode: '\\ElsevierGlyph{E210}', LaTeXMode.mathmode: '\\towa'}, 10539: {LaTeXMode.mathmode: '\\rdiagovfdiag'}, 10540: {LaTeXMode.mathmode: '\\fdiagovrdiag'}, 10541: {LaTeXMode.mathmode: '\\seovnearrow'}, 10542: {LaTeXMode.mathmode: '\\neovsearrow'}, 10543: {LaTeXMode.mathmode: '\\fdiagovnearrow'}, 10544: {LaTeXMode.mathmode: '\\rdiagovsearrow'}, 10545: {LaTeXMode.mathmode: '\\neovnwarrow'}, 10546: {LaTeXMode.mathmode: '\\nwovnearrow'}, 10547: {LaTeXMode.textmode: '\\ElsevierGlyph{E21D}'}, 10550: {LaTeXMode.textmode: '\\ElsevierGlyph{E21A}'}, 10551: {LaTeXMode.textmode: '\\ElsevierGlyph{E219}'}, 10560: {LaTeXMode.textmode: '\\Elolarr ', LaTeXMode.mathmode: '\\circlearrowleft'}, 10561: {LaTeXMode.textmode: '\\Elorarr ', LaTeXMode.mathmode: '\\circlearrowright'}, 10562: {LaTeXMode.textmode: '\\ElzRlarr '}, 10564: {LaTeXMode.textmode: '\\ElzrLarr '}, 10567: {LaTeXMode.textmode: '\\Elzrarrx '}, 10574: {LaTeXMode.textmode: '\\LeftRightVector '}, 10575: {LaTeXMode.textmode: '\\RightUpDownVector '}, 10576: {LaTeXMode.textmode: '\\DownLeftRightVector '}, 10577: {LaTeXMode.textmode: '\\LeftUpDownVector '}, 10578: {LaTeXMode.textmode: '\\LeftVectorBar '}, 10579: {LaTeXMode.textmode: '\\RightVectorBar '}, 10580: {LaTeXMode.textmode: '\\RightUpVectorBar '}, 10581: {LaTeXMode.textmode: '\\RightDownVectorBar '}, 10582: {LaTeXMode.textmode: '\\DownLeftVectorBar '}, 10583: {LaTeXMode.textmode: '\\DownRightVectorBar '}, 10584: {LaTeXMode.textmode: '\\LeftUpVectorBar '}, 10585: {LaTeXMode.textmode: '\\LeftDownVectorBar '}, 10586: {LaTeXMode.textmode: '\\LeftTeeVector '}, 10587: {LaTeXMode.textmode: '\\RightTeeVector '}, 10588: {LaTeXMode.textmode: '\\RightUpTeeVector '}, 10589: {LaTeXMode.textmode: '\\RightDownTeeVector '}, 10590: {LaTeXMode.textmode: '\\DownLeftTeeVector '}, 10591: {LaTeXMode.textmode: '\\DownRightTeeVector '}, 10592: {LaTeXMode.textmode: '\\LeftUpTeeVector '}, 10593: {LaTeXMode.textmode: '\\LeftDownTeeVector '}, 10606: {LaTeXMode.textmode: '\\UpEquilibrium '}, 10607: {LaTeXMode.textmode: '\\ReverseUpEquilibrium '}, 10608: {LaTeXMode.textmode: '\\RoundImplies '}, 10620: {LaTeXMode.textmode: '\\ElsevierGlyph{E214}'}, 10621: {LaTeXMode.textmode: '\\ElsevierGlyph{E215}'}, 10624: {LaTeXMode.textmode: '\\Elztfnc ', LaTeXMode.mathmode: '\\Vvert'}, 10629: {LaTeXMode.textmode: '\\ElsevierGlyph{3018}'}, 10630: {LaTeXMode.textmode: '\\Elroang '}, 10643: {LaTeXMode.textmode: '<\\kern-0.58em('}, 10644: {LaTeXMode.textmode: '\\ElsevierGlyph{E291}'}, 10649: {LaTeXMode.textmode: '\\Elzddfnc '}, 10652: {LaTeXMode.textmode: '\\Angle '}, 10656: {LaTeXMode.textmode: '\\Elzlpargt '}, 10677: {LaTeXMode.textmode: '\\ElsevierGlyph{E260}'}, 10678: {LaTeXMode.textmode: '\\ElsevierGlyph{E61B}'}, 10680: {LaTeXMode.mathmode: '\\obslash'}, 10692: {LaTeXMode.mathmode: '\\boxdiag'}, 10693: {LaTeXMode.mathmode: '\\boxbslash'}, 10694: {LaTeXMode.mathmode: '\\boxast'}, 10695: {LaTeXMode.mathmode: '\\boxcircle'}, 10698: {LaTeXMode.textmode: '\\ElzLap '}, 10699: {LaTeXMode.textmode: '\\Elzdefas '}, 10703: {LaTeXMode.textmode: '\\NotLeftTriangleBar '}, 10704: {LaTeXMode.textmode: '\\NotRightTriangleBar '}, 10716: {LaTeXMode.textmode: '\\ElsevierGlyph{E372}'}, 10719: {LaTeXMode.mathmode: '\\dualmap'}, 10722: {LaTeXMode.mathmode: '\\shuffle'}, 10731: {LaTeXMode.textmode: '\\blacklozenge ', LaTeXMode.mathmode: '\\blacklozenge'}, 10740: {LaTeXMode.textmode: '\\RuleDelayed '}, 10752: {LaTeXMode.mathmode: '\\bigodot'}, 10753: {LaTeXMode.mathmode: '\\bigoplus'}, 10754: {LaTeXMode.mathmode: '\\bigotimes'}, 10755: {LaTeXMode.mathmode: '\\bigcupdot'}, 10756: {LaTeXMode.textmode: '\\Elxuplus ', LaTeXMode.mathmode: '\\biguplus'}, 10757: {LaTeXMode.textmode: '\\ElzThr ', LaTeXMode.mathmode: '\\bigsqcap'}, 10758: {LaTeXMode.textmode: '\\Elxsqcup ', LaTeXMode.mathmode: '\\bigsqcup'}, 10759: {LaTeXMode.textmode: '\\ElzInf ', LaTeXMode.mathmode: '\\conjquant'}, 10760: {LaTeXMode.textmode: '\\ElzSup ', LaTeXMode.mathmode: '\\disjquant'}, 10761: {LaTeXMode.mathmode: '\\bigtimes'}, 10765: {LaTeXMode.textmode: '\\ElzCint ', LaTeXMode.mathmode: '\\intbar'}, 10766: {LaTeXMode.mathmode: '\\intBar'}, 10767: {LaTeXMode.textmode: '\\clockoint '}, 10768: {LaTeXMode.textmode: '\\ElsevierGlyph{E395}'}, 10774: {LaTeXMode.textmode: '\\sqrint '}, 10776: {LaTeXMode.mathmode: '\\intx'}, 10777: {LaTeXMode.mathmode: '\\intcap'}, 10778: {LaTeXMode.mathmode: '\\intcup'}, 10779: {LaTeXMode.mathmode: '\\upint'}, 10780: {LaTeXMode.mathmode: '\\lowint'}, 10789: {LaTeXMode.textmode: '\\ElsevierGlyph{E25A}', LaTeXMode.mathmode: '\\plusdot'}, 10794: {LaTeXMode.textmode: '\\ElsevierGlyph{E25B}', LaTeXMode.mathmode: '\\minusdot'}, 10797: {LaTeXMode.textmode: '\\ElsevierGlyph{E25C}'}, 10798: {LaTeXMode.textmode: '\\ElsevierGlyph{E25D}'}, 10799: {LaTeXMode.textmode: '\\ElzTimes '}, 10802: {LaTeXMode.mathmode: '\\btimes'}, 10804: {LaTeXMode.textmode: '\\ElsevierGlyph{E25E}'}, 10805: {LaTeXMode.textmode: '\\ElsevierGlyph{E25E}'}, 10812: {LaTeXMode.textmode: '\\ElsevierGlyph{E259}', LaTeXMode.mathmode: '\\intprod'}, 10813: {LaTeXMode.mathmode: '\\intprodr'}, 10815: {LaTeXMode.textmode: '\\amalg ', LaTeXMode.mathmode: '\\amalg'}, 10835: {LaTeXMode.textmode: '\\ElzAnd '}, 10836: {LaTeXMode.textmode: '\\ElzOr '}, 10837: {LaTeXMode.textmode: '\\ElsevierGlyph{E36E}'}, 10838: {LaTeXMode.textmode: '\\ElOr '}, 10846: {LaTeXMode.textmode: '\\perspcorrespond ', LaTeXMode.mathmode: '\\doublebarwedge'}, 10847: {LaTeXMode.textmode: '\\Elzminhat '}, 10851: {LaTeXMode.textmode: '\\ElsevierGlyph{225A}'}, 10862: {LaTeXMode.textmode: '\\stackrel{*}{=}'}, 10869: {LaTeXMode.textmode: '\\Equal '}, 10871: {LaTeXMode.mathmode: '\\ddotseq'}, 10877: {LaTeXMode.textmode: '\\nleqslant ', LaTeXMode.mathmode: '\\nleqslant'}, 10878: {LaTeXMode.textmode: '\\ngeqslant ', LaTeXMode.mathmode: '\\ngeqslant'}, 10885: {LaTeXMode.textmode: '\\lessapprox ', LaTeXMode.mathmode: '\\lessapprox'}, 10886: {LaTeXMode.textmode: '\\gtrapprox ', LaTeXMode.mathmode: '\\gtrapprox'}, 10887: {LaTeXMode.textmode: '\\lneq ', LaTeXMode.mathmode: '\\lneq'}, 10888: {LaTeXMode.textmode: '\\gneq ', LaTeXMode.mathmode: '\\gneq'}, 10889: {LaTeXMode.textmode: '\\lnapprox ', LaTeXMode.mathmode: '\\lnapprox'}, 10890: {LaTeXMode.textmode: '\\gnapprox ', LaTeXMode.mathmode: '\\gnapprox'}, 10891: {LaTeXMode.textmode: '\\lesseqqgtr ', LaTeXMode.mathmode: '\\lesseqqgtr'}, 10892: {LaTeXMode.textmode: '\\gtreqqless ', LaTeXMode.mathmode: '\\gtreqqless'}, 10901: {LaTeXMode.textmode: '\\eqslantless ', LaTeXMode.mathmode: '\\eqslantless'}, 10902: {LaTeXMode.textmode: '\\eqslantgtr ', LaTeXMode.mathmode: '\\eqslantgtr'}, 10909: {LaTeXMode.textmode: '\\Pisymbol{ppi020}{117}'}, 10910: {LaTeXMode.textmode: '\\Pisymbol{ppi020}{105}'}, 10913: {LaTeXMode.textmode: '\\NotNestedLessLess '}, 10914: {LaTeXMode.textmode: '\\NotNestedGreaterGreater '}, 10915: {LaTeXMode.mathmode: '\\partialmeetcontraction'}, 10926: {LaTeXMode.mathmode: '\\bumpeqq'}, 10927: {LaTeXMode.textmode: '\\not\\preceq ', LaTeXMode.mathmode: '\\npreceq'}, 10928: {LaTeXMode.textmode: '\\not\\succeq ', LaTeXMode.mathmode: '\\nsucceq'}, 10933: {LaTeXMode.textmode: '\\precneqq ', LaTeXMode.mathmode: '\\precneqq'}, 10934: {LaTeXMode.textmode: '\\succneqq ', LaTeXMode.mathmode: '\\succneqq'}, 10935: {LaTeXMode.textmode: '\\precapprox ', LaTeXMode.mathmode: '\\precapprox'}, 10936: {LaTeXMode.textmode: '\\succapprox ', LaTeXMode.mathmode: '\\succapprox'}, 10937: {LaTeXMode.textmode: '\\precnapprox ', LaTeXMode.mathmode: '\\precnapprox'}, 10938: {LaTeXMode.textmode: '\\succnapprox ', LaTeXMode.mathmode: '\\succnapprox'}, 10949: {LaTeXMode.textmode: '\\nsubseteqq ', LaTeXMode.mathmode: '\\nsubseteqq'}, 10950: {LaTeXMode.textmode: '\\nsupseteqq'}, 10955: {LaTeXMode.textmode: '\\subsetneqq ', LaTeXMode.mathmode: '\\subsetneqq'}, 10956: {LaTeXMode.textmode: '\\supsetneqq ', LaTeXMode.mathmode: '\\supsetneqq'}, 10971: {LaTeXMode.mathmode: '\\mlcp'}, 10973: {LaTeXMode.mathmode: '\\forks'}, 10979: {LaTeXMode.mathmode: '\\dashV'}, 10980: {LaTeXMode.mathmode: '\\Dashv'}, 10987: {LaTeXMode.textmode: '\\ElsevierGlyph{E30D}'}, 10996: {LaTeXMode.mathmode: '\\interleave'}, 10998: {LaTeXMode.textmode: '\\Elztdcol '}, 11005: {LaTeXMode.textmode: '{\\rlap{\\textbackslash}{{/}\\!\\!{/}}}'}, 12298: {LaTeXMode.textmode: '\\ElsevierGlyph{300A}'}, 12299: {LaTeXMode.textmode: '\\ElsevierGlyph{300B}'}, 12312: {LaTeXMode.textmode: '\\ElsevierGlyph{3018}'}, 12313: {LaTeXMode.textmode: '\\ElsevierGlyph{3019}'}, 12314: {LaTeXMode.textmode: '\\openbracketleft '}, 12315: {LaTeXMode.textmode: '\\openbracketright '}, 64256: {LaTeXMode.textmode: 'ff'}, 64257: {LaTeXMode.textmode: 'fi'}, 64258: {LaTeXMode.textmode: 'fl'}, 64259: {LaTeXMode.textmode: 'ffi'}, 64260: {LaTeXMode.textmode: 'ffl'}, 65024: {LaTeXMode.textmode: '\\varsupsetneq ', LaTeXMode.mathmode: '\\varsupsetneq'}, 119808: {LaTeXMode.textmode: '\\mathbf{A}'}, 119809: {LaTeXMode.textmode: '\\mathbf{B}'}, 119810: {LaTeXMode.textmode: '\\mathbf{C}'}, 119811: {LaTeXMode.textmode: '\\mathbf{D}'}, 119812: {LaTeXMode.textmode: '\\mathbf{E}'}, 119813: {LaTeXMode.textmode: '\\mathbf{F}'}, 119814: {LaTeXMode.textmode: '\\mathbf{G}'}, 119815: {LaTeXMode.textmode: '\\mathbf{H}'}, 119816: {LaTeXMode.textmode: '\\mathbf{I}'}, 119817: {LaTeXMode.textmode: '\\mathbf{J}'}, 119818: {LaTeXMode.textmode: '\\mathbf{K}'}, 119819: {LaTeXMode.textmode: '\\mathbf{L}'}, 119820: {LaTeXMode.textmode: '\\mathbf{M}'}, 119821: {LaTeXMode.textmode: '\\mathbf{N}'}, 119822: {LaTeXMode.textmode: '\\mathbf{O}'}, 119823: {LaTeXMode.textmode: '\\mathbf{P}'}, 119824: {LaTeXMode.textmode: '\\mathbf{Q}'}, 119825: {LaTeXMode.textmode: '\\mathbf{R}'}, 119826: {LaTeXMode.textmode: '\\mathbf{S}'}, 119827: {LaTeXMode.textmode: '\\mathbf{T}'}, 119828: {LaTeXMode.textmode: '\\mathbf{U}'}, 119829: {LaTeXMode.textmode: '\\mathbf{V}'}, 119830: {LaTeXMode.textmode: '\\mathbf{W}'}, 119831: {LaTeXMode.textmode: '\\mathbf{X}'}, 119832: {LaTeXMode.textmode: '\\mathbf{Y}'}, 119833: {LaTeXMode.textmode: '\\mathbf{Z}'}, 119834: {LaTeXMode.textmode: '\\mathbf{a}'}, 119835: {LaTeXMode.textmode: '\\mathbf{b}'}, 119836: {LaTeXMode.textmode: '\\mathbf{c}'}, 119837: {LaTeXMode.textmode: '\\mathbf{d}'}, 119838: {LaTeXMode.textmode: '\\mathbf{e}'}, 119839: {LaTeXMode.textmode: '\\mathbf{f}'}, 119840: {LaTeXMode.textmode: '\\mathbf{g}'}, 119841: {LaTeXMode.textmode: '\\mathbf{h}'}, 119842: {LaTeXMode.textmode: '\\mathbf{i}'}, 119843: {LaTeXMode.textmode: '\\mathbf{j}'}, 119844: {LaTeXMode.textmode: '\\mathbf{k}'}, 119845: {LaTeXMode.textmode: '\\mathbf{l}'}, 119846: {LaTeXMode.textmode: '\\mathbf{m}'}, 119847: {LaTeXMode.textmode: '\\mathbf{n}'}, 119848: {LaTeXMode.textmode: '\\mathbf{o}'}, 119849: {LaTeXMode.textmode: '\\mathbf{p}'}, 119850: {LaTeXMode.textmode: '\\mathbf{q}'}, 119851: {LaTeXMode.textmode: '\\mathbf{r}'}, 119852: {LaTeXMode.textmode: '\\mathbf{s}'}, 119853: {LaTeXMode.textmode: '\\mathbf{t}'}, 119854: {LaTeXMode.textmode: '\\mathbf{u}'}, 119855: {LaTeXMode.textmode: '\\mathbf{v}'}, 119856: {LaTeXMode.textmode: '\\mathbf{w}'}, 119857: {LaTeXMode.textmode: '\\mathbf{x}'}, 119858: {LaTeXMode.textmode: '\\mathbf{y}'}, 119859: {LaTeXMode.textmode: '\\mathbf{z}'}, 119860: {LaTeXMode.textmode: '\\mathmit{A}'}, 119861: {LaTeXMode.textmode: '\\mathmit{B}'}, 119862: {LaTeXMode.textmode: '\\mathmit{C}'}, 119863: {LaTeXMode.textmode: '\\mathmit{D}'}, 119864: {LaTeXMode.textmode: '\\mathmit{E}'}, 119865: {LaTeXMode.textmode: '\\mathmit{F}'}, 119866: {LaTeXMode.textmode: '\\mathmit{G}'}, 119867: {LaTeXMode.textmode: '\\mathmit{H}'}, 119868: {LaTeXMode.textmode: '\\mathmit{I}'}, 119869: {LaTeXMode.textmode: '\\mathmit{J}'}, 119870: {LaTeXMode.textmode: '\\mathmit{K}'}, 119871: {LaTeXMode.textmode: '\\mathmit{L}'}, 119872: {LaTeXMode.textmode: '\\mathmit{M}'}, 119873: {LaTeXMode.textmode: '\\mathmit{N}'}, 119874: {LaTeXMode.textmode: '\\mathmit{O}'}, 119875: {LaTeXMode.textmode: '\\mathmit{P}'}, 119876: {LaTeXMode.textmode: '\\mathmit{Q}'}, 119877: {LaTeXMode.textmode: '\\mathmit{R}'}, 119878: {LaTeXMode.textmode: '\\mathmit{S}'}, 119879: {LaTeXMode.textmode: '\\mathmit{T}'}, 119880: {LaTeXMode.textmode: '\\mathmit{U}'}, 119881: {LaTeXMode.textmode: '\\mathmit{V}'}, 119882: {LaTeXMode.textmode: '\\mathmit{W}'}, 119883: {LaTeXMode.textmode: '\\mathmit{X}'}, 119884: {LaTeXMode.textmode: '\\mathmit{Y}'}, 119885: {LaTeXMode.textmode: '\\mathmit{Z}'}, 119886: {LaTeXMode.textmode: '\\mathmit{a}'}, 119887: {LaTeXMode.textmode: '\\mathmit{b}'}, 119888: {LaTeXMode.textmode: '\\mathmit{c}'}, 119889: {LaTeXMode.textmode: '\\mathmit{d}'}, 119890: {LaTeXMode.textmode: '\\mathmit{e}'}, 119891: {LaTeXMode.textmode: '\\mathmit{f}'}, 119892: {LaTeXMode.textmode: '\\mathmit{g}'}, 119894: {LaTeXMode.textmode: '\\mathmit{i}'}, 119895: {LaTeXMode.textmode: '\\mathmit{j}'}, 119896: {LaTeXMode.textmode: '\\mathmit{k}'}, 119897: {LaTeXMode.textmode: '\\mathmit{l}'}, 119898: {LaTeXMode.textmode: '\\mathmit{m}'}, 119899: {LaTeXMode.textmode: '\\mathmit{n}'}, 119900: {LaTeXMode.textmode: '\\mathmit{o}'}, 119901: {LaTeXMode.textmode: '\\mathmit{p}'}, 119902: {LaTeXMode.textmode: '\\mathmit{q}'}, 119903: {LaTeXMode.textmode: '\\mathmit{r}'}, 119904: {LaTeXMode.textmode: '\\mathmit{s}'}, 119905: {LaTeXMode.textmode: '\\mathmit{t}'}, 119906: {LaTeXMode.textmode: '\\mathmit{u}'}, 119907: {LaTeXMode.textmode: '\\mathmit{v}'}, 119908: {LaTeXMode.textmode: '\\mathmit{w}'}, 119909: {LaTeXMode.textmode: '\\mathmit{x}'}, 119910: {LaTeXMode.textmode: '\\mathmit{y}'}, 119911: {LaTeXMode.textmode: '\\mathmit{z}'}, 119912: {LaTeXMode.textmode: '\\mathbit{A}'}, 119913: {LaTeXMode.textmode: '\\mathbit{B}'}, 119914: {LaTeXMode.textmode: '\\mathbit{C}'}, 119915: {LaTeXMode.textmode: '\\mathbit{D}'}, 119916: {LaTeXMode.textmode: '\\mathbit{E}'}, 119917: {LaTeXMode.textmode: '\\mathbit{F}'}, 119918: {LaTeXMode.textmode: '\\mathbit{G}'}, 119919: {LaTeXMode.textmode: '\\mathbit{H}'}, 119920: {LaTeXMode.textmode: '\\mathbit{I}'}, 119921: {LaTeXMode.textmode: '\\mathbit{J}'}, 119922: {LaTeXMode.textmode: '\\mathbit{K}'}, 119923: {LaTeXMode.textmode: '\\mathbit{L}'}, 119924: {LaTeXMode.textmode: '\\mathbit{M}'}, 119925: {LaTeXMode.textmode: '\\mathbit{N}'}, 119926: {LaTeXMode.textmode: '\\mathbit{O}'}, 119927: {LaTeXMode.textmode: '\\mathbit{P}'}, 119928: {LaTeXMode.textmode: '\\mathbit{Q}'}, 119929: {LaTeXMode.textmode: '\\mathbit{R}'}, 119930: {LaTeXMode.textmode: '\\mathbit{S}'}, 119931: {LaTeXMode.textmode: '\\mathbit{T}'}, 119932: {LaTeXMode.textmode: '\\mathbit{U}'}, 119933: {LaTeXMode.textmode: '\\mathbit{V}'}, 119934: {LaTeXMode.textmode: '\\mathbit{W}'}, 119935: {LaTeXMode.textmode: '\\mathbit{X}'}, 119936: {LaTeXMode.textmode: '\\mathbit{Y}'}, 119937: {LaTeXMode.textmode: '\\mathbit{Z}'}, 119938: {LaTeXMode.textmode: '\\mathbit{a}'}, 119939: {LaTeXMode.textmode: '\\mathbit{b}'}, 119940: {LaTeXMode.textmode: '\\mathbit{c}'}, 119941: {LaTeXMode.textmode: '\\mathbit{d}'}, 119942: {LaTeXMode.textmode: '\\mathbit{e}'}, 119943: {LaTeXMode.textmode: '\\mathbit{f}'}, 119944: {LaTeXMode.textmode: '\\mathbit{g}'}, 119945: {LaTeXMode.textmode: '\\mathbit{h}'}, 119946: {LaTeXMode.textmode: '\\mathbit{i}'}, 119947: {LaTeXMode.textmode: '\\mathbit{j}'}, 119948: {LaTeXMode.textmode: '\\mathbit{k}'}, 119949: {LaTeXMode.textmode: '\\mathbit{l}'}, 119950: {LaTeXMode.textmode: '\\mathbit{m}'}, 119951: {LaTeXMode.textmode: '\\mathbit{n}'}, 119952: {LaTeXMode.textmode: '\\mathbit{o}'}, 119953: {LaTeXMode.textmode: '\\mathbit{p}'}, 119954: {LaTeXMode.textmode: '\\mathbit{q}'}, 119955: {LaTeXMode.textmode: '\\mathbit{r}'}, 119956: {LaTeXMode.textmode: '\\mathbit{s}'}, 119957: {LaTeXMode.textmode: '\\mathbit{t}'}, 119958: {LaTeXMode.textmode: '\\mathbit{u}'}, 119959: {LaTeXMode.textmode: '\\mathbit{v}'}, 119960: {LaTeXMode.textmode: '\\mathbit{w}'}, 119961: {LaTeXMode.textmode: '\\mathbit{x}'}, 119962: {LaTeXMode.textmode: '\\mathbit{y}'}, 119963: {LaTeXMode.textmode: '\\mathbit{z}'}, 119964: {LaTeXMode.textmode: '\\mathscr{A}'}, 119966: {LaTeXMode.textmode: '\\mathscr{C}'}, 119967: {LaTeXMode.textmode: '\\mathscr{D}'}, 119970: {LaTeXMode.textmode: '\\mathscr{G}'}, 119973: {LaTeXMode.textmode: '\\mathscr{J}'}, 119974: {LaTeXMode.textmode: '\\mathscr{K}'}, 119977: {LaTeXMode.textmode: '\\mathscr{N}'}, 119978: {LaTeXMode.textmode: '\\mathscr{O}'}, 119979: {LaTeXMode.textmode: '\\mathscr{P}'}, 119980: {LaTeXMode.textmode: '\\mathscr{Q}'}, 119982: {LaTeXMode.textmode: '\\mathscr{S}'}, 119983: {LaTeXMode.textmode: '\\mathscr{T}'}, 119984: {LaTeXMode.textmode: '\\mathscr{U}'}, 119985: {LaTeXMode.textmode: '\\mathscr{V}'}, 119986: {LaTeXMode.textmode: '\\mathscr{W}'}, 119987: {LaTeXMode.textmode: '\\mathscr{X}'}, 119988: {LaTeXMode.textmode: '\\mathscr{Y}'}, 119989: {LaTeXMode.textmode: '\\mathscr{Z}'}, 119990: {LaTeXMode.textmode: '\\mathscr{a}'}, 119991: {LaTeXMode.textmode: '\\mathscr{b}'}, 119992: {LaTeXMode.textmode: '\\mathscr{c}'}, 119993: {LaTeXMode.textmode: '\\mathscr{d}'}, 119995: {LaTeXMode.textmode: '\\mathscr{f}'}, 119997: {LaTeXMode.textmode: '\\mathscr{h}'}, 119998: {LaTeXMode.textmode: '\\mathscr{i}'}, 119999: {LaTeXMode.textmode: '\\mathscr{j}'}, 120000: {LaTeXMode.textmode: '\\mathscr{k}'}, 120001: {LaTeXMode.textmode: '\\mathscr{l}'}, 120002: {LaTeXMode.textmode: '\\mathscr{m}'}, 120003: {LaTeXMode.textmode: '\\mathscr{n}'}, 120005: {LaTeXMode.textmode: '\\mathscr{p}'}, 120006: {LaTeXMode.textmode: '\\mathscr{q}'}, 120007: {LaTeXMode.textmode: '\\mathscr{r}'}, 120008: {LaTeXMode.textmode: '\\mathscr{s}'}, 120009: {LaTeXMode.textmode: '\\mathscr{t}'}, 120010: {LaTeXMode.textmode: '\\mathscr{u}'}, 120011: {LaTeXMode.textmode: '\\mathscr{v}'}, 120012: {LaTeXMode.textmode: '\\mathscr{w}'}, 120013: {LaTeXMode.textmode: '\\mathscr{x}'}, 120014: {LaTeXMode.textmode: '\\mathscr{y}'}, 120015: {LaTeXMode.textmode: '\\mathscr{z}'}, 120016: {LaTeXMode.textmode: '\\mathbcal{A}'}, 120017: {LaTeXMode.textmode: '\\mathbcal{B}'}, 120018: {LaTeXMode.textmode: '\\mathbcal{C}'}, 120019: {LaTeXMode.textmode: '\\mathbcal{D}'}, 120020: {LaTeXMode.textmode: '\\mathbcal{E}'}, 120021: {LaTeXMode.textmode: '\\mathbcal{F}'}, 120022: {LaTeXMode.textmode: '\\mathbcal{G}'}, 120023: {LaTeXMode.textmode: '\\mathbcal{H}'}, 120024: {LaTeXMode.textmode: '\\mathbcal{I}'}, 120025: {LaTeXMode.textmode: '\\mathbcal{J}'}, 120026: {LaTeXMode.textmode: '\\mathbcal{K}'}, 120027: {LaTeXMode.textmode: '\\mathbcal{L}'}, 120028: {LaTeXMode.textmode: '\\mathbcal{M}'}, 120029: {LaTeXMode.textmode: '\\mathbcal{N}'}, 120030: {LaTeXMode.textmode: '\\mathbcal{O}'}, 120031: {LaTeXMode.textmode: '\\mathbcal{P}'}, 120032: {LaTeXMode.textmode: '\\mathbcal{Q}'}, 120033: {LaTeXMode.textmode: '\\mathbcal{R}'}, 120034: {LaTeXMode.textmode: '\\mathbcal{S}'}, 120035: {LaTeXMode.textmode: '\\mathbcal{T}'}, 120036: {LaTeXMode.textmode: '\\mathbcal{U}'}, 120037: {LaTeXMode.textmode: '\\mathbcal{V}'}, 120038: {LaTeXMode.textmode: '\\mathbcal{W}'}, 120039: {LaTeXMode.textmode: '\\mathbcal{X}'}, 120040: {LaTeXMode.textmode: '\\mathbcal{Y}'}, 120041: {LaTeXMode.textmode: '\\mathbcal{Z}'}, 120042: {LaTeXMode.textmode: '\\mathbcal{a}'}, 120043: {LaTeXMode.textmode: '\\mathbcal{b}'}, 120044: {LaTeXMode.textmode: '\\mathbcal{c}'}, 120045: {LaTeXMode.textmode: '\\mathbcal{d}'}, 120046: {LaTeXMode.textmode: '\\mathbcal{e}'}, 120047: {LaTeXMode.textmode: '\\mathbcal{f}'}, 120048: {LaTeXMode.textmode: '\\mathbcal{g}'}, 120049: {LaTeXMode.textmode: '\\mathbcal{h}'}, 120050: {LaTeXMode.textmode: '\\mathbcal{i}'}, 120051: {LaTeXMode.textmode: '\\mathbcal{j}'}, 120052: {LaTeXMode.textmode: '\\mathbcal{k}'}, 120053: {LaTeXMode.textmode: '\\mathbcal{l}'}, 120054: {LaTeXMode.textmode: '\\mathbcal{m}'}, 120055: {LaTeXMode.textmode: '\\mathbcal{n}'}, 120056: {LaTeXMode.textmode: '\\mathbcal{o}'}, 120057: {LaTeXMode.textmode: '\\mathbcal{p}'}, 120058: {LaTeXMode.textmode: '\\mathbcal{q}'}, 120059: {LaTeXMode.textmode: '\\mathbcal{r}'}, 120060: {LaTeXMode.textmode: '\\mathbcal{s}'}, 120061: {LaTeXMode.textmode: '\\mathbcal{t}'}, 120062: {LaTeXMode.textmode: '\\mathbcal{u}'}, 120063: {LaTeXMode.textmode: '\\mathbcal{v}'}, 120064: {LaTeXMode.textmode: '\\mathbcal{w}'}, 120065: {LaTeXMode.textmode: '\\mathbcal{x}'}, 120066: {LaTeXMode.textmode: '\\mathbcal{y}'}, 120067: {LaTeXMode.textmode: '\\mathbcal{z}'}, 120068: {LaTeXMode.textmode: '\\mathfrak{A}'}, 120069: {LaTeXMode.textmode: '\\mathfrak{B}'}, 120071: {LaTeXMode.textmode: '\\mathfrak{D}'}, 120072: {LaTeXMode.textmode: '\\mathfrak{E}'}, 120073: {LaTeXMode.textmode: '\\mathfrak{F}'}, 120074: {LaTeXMode.textmode: '\\mathfrak{G}'}, 120077: {LaTeXMode.textmode: '\\mathfrak{J}'}, 120078: {LaTeXMode.textmode: '\\mathfrak{K}'}, 120079: {LaTeXMode.textmode: '\\mathfrak{L}'}, 120080: {LaTeXMode.textmode: '\\mathfrak{M}'}, 120081: {LaTeXMode.textmode: '\\mathfrak{N}'}, 120082: {LaTeXMode.textmode: '\\mathfrak{O}'}, 120083: {LaTeXMode.textmode: '\\mathfrak{P}'}, 120084: {LaTeXMode.textmode: '\\mathfrak{Q}'}, 120086: {LaTeXMode.textmode: '\\mathfrak{S}'}, 120087: {LaTeXMode.textmode: '\\mathfrak{T}'}, 120088: {LaTeXMode.textmode: '\\mathfrak{U}'}, 120089: {LaTeXMode.textmode: '\\mathfrak{V}'}, 120090: {LaTeXMode.textmode: '\\mathfrak{W}'}, 120091: {LaTeXMode.textmode: '\\mathfrak{X}'}, 120092: {LaTeXMode.textmode: '\\mathfrak{Y}'}, 120094: {LaTeXMode.textmode: '\\mathfrak{a}'}, 120095: {LaTeXMode.textmode: '\\mathfrak{b}'}, 120096: {LaTeXMode.textmode: '\\mathfrak{c}'}, 120097: {LaTeXMode.textmode: '\\mathfrak{d}'}, 120098: {LaTeXMode.textmode: '\\mathfrak{e}'}, 120099: {LaTeXMode.textmode: '\\mathfrak{f}'}, 120100: {LaTeXMode.textmode: '\\mathfrak{g}'}, 120101: {LaTeXMode.textmode: '\\mathfrak{h}'}, 120102: {LaTeXMode.textmode: '\\mathfrak{i}'}, 120103: {LaTeXMode.textmode: '\\mathfrak{j}'}, 120104: {LaTeXMode.textmode: '\\mathfrak{k}'}, 120105: {LaTeXMode.textmode: '\\mathfrak{l}'}, 120106: {LaTeXMode.textmode: '\\mathfrak{m}'}, 120107: {LaTeXMode.textmode: '\\mathfrak{n}'}, 120108: {LaTeXMode.textmode: '\\mathfrak{o}'}, 120109: {LaTeXMode.textmode: '\\mathfrak{p}'}, 120110: {LaTeXMode.textmode: '\\mathfrak{q}'}, 120111: {LaTeXMode.textmode: '\\mathfrak{r}'}, 120112: {LaTeXMode.textmode: '\\mathfrak{s}'}, 120113: {LaTeXMode.textmode: '\\mathfrak{t}'}, 120114: {LaTeXMode.textmode: '\\mathfrak{u}'}, 120115: {LaTeXMode.textmode: '\\mathfrak{v}'}, 120116: {LaTeXMode.textmode: '\\mathfrak{w}'}, 120117: {LaTeXMode.textmode: '\\mathfrak{x}'}, 120118: {LaTeXMode.textmode: '\\mathfrak{y}'}, 120119: {LaTeXMode.textmode: '\\mathfrak{z}'}, 120120: {LaTeXMode.textmode: '\\mathbb{A}'}, 120121: {LaTeXMode.textmode: '\\mathbb{B}'}, 120123: {LaTeXMode.textmode: '\\mathbb{D}'}, 120124: {LaTeXMode.textmode: '\\mathbb{E}'}, 120125: {LaTeXMode.textmode: '\\mathbb{F}'}, 120126: {LaTeXMode.textmode: '\\mathbb{G}'}, 120128: {LaTeXMode.textmode: '\\mathbb{I}'}, 120129: {LaTeXMode.textmode: '\\mathbb{J}'}, 120130: {LaTeXMode.textmode: '\\mathbb{K}'}, 120131: {LaTeXMode.textmode: '\\mathbb{L}'}, 120132: {LaTeXMode.textmode: '\\mathbb{M}'}, 120134: {LaTeXMode.textmode: '\\mathbb{O}'}, 120138: {LaTeXMode.textmode: '\\mathbb{S}'}, 120139: {LaTeXMode.textmode: '\\mathbb{T}'}, 120140: {LaTeXMode.textmode: '\\mathbb{U}'}, 120141: {LaTeXMode.textmode: '\\mathbb{V}'}, 120142: {LaTeXMode.textmode: '\\mathbb{W}'}, 120143: {LaTeXMode.textmode: '\\mathbb{X}'}, 120144: {LaTeXMode.textmode: '\\mathbb{Y}'}, 120146: {LaTeXMode.textmode: '\\mathbb{a}'}, 120147: {LaTeXMode.textmode: '\\mathbb{b}'}, 120148: {LaTeXMode.textmode: '\\mathbb{c}'}, 120149: {LaTeXMode.textmode: '\\mathbb{d}'}, 120150: {LaTeXMode.textmode: '\\mathbb{e}'}, 120151: {LaTeXMode.textmode: '\\mathbb{f}'}, 120152: {LaTeXMode.textmode: '\\mathbb{g}'}, 120153: {LaTeXMode.textmode: '\\mathbb{h}'}, 120154: {LaTeXMode.textmode: '\\mathbb{i}'}, 120155: {LaTeXMode.textmode: '\\mathbb{j}'}, 120156: {LaTeXMode.textmode: '\\mathbb{k}'}, 120157: {LaTeXMode.textmode: '\\mathbb{l}'}, 120158: {LaTeXMode.textmode: '\\mathbb{m}'}, 120159: {LaTeXMode.textmode: '\\mathbb{n}'}, 120160: {LaTeXMode.textmode: '\\mathbb{o}'}, 120161: {LaTeXMode.textmode: '\\mathbb{p}'}, 120162: {LaTeXMode.textmode: '\\mathbb{q}'}, 120163: {LaTeXMode.textmode: '\\mathbb{r}'}, 120164: {LaTeXMode.textmode: '\\mathbb{s}'}, 120165: {LaTeXMode.textmode: '\\mathbb{t}'}, 120166: {LaTeXMode.textmode: '\\mathbb{u}'}, 120167: {LaTeXMode.textmode: '\\mathbb{v}'}, 120168: {LaTeXMode.textmode: '\\mathbb{w}'}, 120169: {LaTeXMode.textmode: '\\mathbb{x}'}, 120170: {LaTeXMode.textmode: '\\mathbb{y}'}, 120171: {LaTeXMode.textmode: '\\mathbb{z}'}, 120172: {LaTeXMode.textmode: '\\mathbfrak{A}'}, 120173: {LaTeXMode.textmode: '\\mathbfrak{B}'}, 120174: {LaTeXMode.textmode: '\\mathbfrak{C}'}, 120175: {LaTeXMode.textmode: '\\mathbfrak{D}'}, 120176: {LaTeXMode.textmode: '\\mathbfrak{E}'}, 120177: {LaTeXMode.textmode: '\\mathbfrak{F}'}, 120178: {LaTeXMode.textmode: '\\mathbfrak{G}'}, 120179: {LaTeXMode.textmode: '\\mathbfrak{H}'}, 120180: {LaTeXMode.textmode: '\\mathbfrak{I}'}, 120181: {LaTeXMode.textmode: '\\mathbfrak{J}'}, 120182: {LaTeXMode.textmode: '\\mathbfrak{K}'}, 120183: {LaTeXMode.textmode: '\\mathbfrak{L}'}, 120184: {LaTeXMode.textmode: '\\mathbfrak{M}'}, 120185: {LaTeXMode.textmode: '\\mathbfrak{N}'}, 120186: {LaTeXMode.textmode: '\\mathbfrak{O}'}, 120187: {LaTeXMode.textmode: '\\mathbfrak{P}'}, 120188: {LaTeXMode.textmode: '\\mathbfrak{Q}'}, 120189: {LaTeXMode.textmode: '\\mathbfrak{R}'}, 120190: {LaTeXMode.textmode: '\\mathbfrak{S}'}, 120191: {LaTeXMode.textmode: '\\mathbfrak{T}'}, 120192: {LaTeXMode.textmode: '\\mathbfrak{U}'}, 120193: {LaTeXMode.textmode: '\\mathbfrak{V}'}, 120194: {LaTeXMode.textmode: '\\mathbfrak{W}'}, 120195: {LaTeXMode.textmode: '\\mathbfrak{X}'}, 120196: {LaTeXMode.textmode: '\\mathbfrak{Y}'}, 120197: {LaTeXMode.textmode: '\\mathbfrak{Z}'}, 120198: {LaTeXMode.textmode: '\\mathbfrak{a}'}, 120199: {LaTeXMode.textmode: '\\mathbfrak{b}'}, 120200: {LaTeXMode.textmode: '\\mathbfrak{c}'}, 120201: {LaTeXMode.textmode: '\\mathbfrak{d}'}, 120202: {LaTeXMode.textmode: '\\mathbfrak{e}'}, 120203: {LaTeXMode.textmode: '\\mathbfrak{f}'}, 120204: {LaTeXMode.textmode: '\\mathbfrak{g}'}, 120205: {LaTeXMode.textmode: '\\mathbfrak{h}'}, 120206: {LaTeXMode.textmode: '\\mathbfrak{i}'}, 120207: {LaTeXMode.textmode: '\\mathbfrak{j}'}, 120208: {LaTeXMode.textmode: '\\mathbfrak{k}'}, 120209: {LaTeXMode.textmode: '\\mathbfrak{l}'}, 120210: {LaTeXMode.textmode: '\\mathbfrak{m}'}, 120211: {LaTeXMode.textmode: '\\mathbfrak{n}'}, 120212: {LaTeXMode.textmode: '\\mathbfrak{o}'}, 120213: {LaTeXMode.textmode: '\\mathbfrak{p}'}, 120214: {LaTeXMode.textmode: '\\mathbfrak{q}'}, 120215: {LaTeXMode.textmode: '\\mathbfrak{r}'}, 120216: {LaTeXMode.textmode: '\\mathbfrak{s}'}, 120217: {LaTeXMode.textmode: '\\mathbfrak{t}'}, 120218: {LaTeXMode.textmode: '\\mathbfrak{u}'}, 120219: {LaTeXMode.textmode: '\\mathbfrak{v}'}, 120220: {LaTeXMode.textmode: '\\mathbfrak{w}'}, 120221: {LaTeXMode.textmode: '\\mathbfrak{x}'}, 120222: {LaTeXMode.textmode: '\\mathbfrak{y}'}, 120223: {LaTeXMode.textmode: '\\mathbfrak{z}'}, 120224: {LaTeXMode.textmode: '\\mathsf{A}'}, 120225: {LaTeXMode.textmode: '\\mathsf{B}'}, 120226: {LaTeXMode.textmode: '\\mathsf{C}'}, 120227: {LaTeXMode.textmode: '\\mathsf{D}'}, 120228: {LaTeXMode.textmode: '\\mathsf{E}'}, 120229: {LaTeXMode.textmode: '\\mathsf{F}'}, 120230: {LaTeXMode.textmode: '\\mathsf{G}'}, 120231: {LaTeXMode.textmode: '\\mathsf{H}'}, 120232: {LaTeXMode.textmode: '\\mathsf{I}'}, 120233: {LaTeXMode.textmode: '\\mathsf{J}'}, 120234: {LaTeXMode.textmode: '\\mathsf{K}'}, 120235: {LaTeXMode.textmode: '\\mathsf{L}'}, 120236: {LaTeXMode.textmode: '\\mathsf{M}'}, 120237: {LaTeXMode.textmode: '\\mathsf{N}'}, 120238: {LaTeXMode.textmode: '\\mathsf{O}'}, 120239: {LaTeXMode.textmode: '\\mathsf{P}'}, 120240: {LaTeXMode.textmode: '\\mathsf{Q}'}, 120241: {LaTeXMode.textmode: '\\mathsf{R}'}, 120242: {LaTeXMode.textmode: '\\mathsf{S}'}, 120243: {LaTeXMode.textmode: '\\mathsf{T}'}, 120244: {LaTeXMode.textmode: '\\mathsf{U}'}, 120245: {LaTeXMode.textmode: '\\mathsf{V}'}, 120246: {LaTeXMode.textmode: '\\mathsf{W}'}, 120247: {LaTeXMode.textmode: '\\mathsf{X}'}, 120248: {LaTeXMode.textmode: '\\mathsf{Y}'}, 120249: {LaTeXMode.textmode: '\\mathsf{Z}'}, 120250: {LaTeXMode.textmode: '\\mathsf{a}'}, 120251: {LaTeXMode.textmode: '\\mathsf{b}'}, 120252: {LaTeXMode.textmode: '\\mathsf{c}'}, 120253: {LaTeXMode.textmode: '\\mathsf{d}'}, 120254: {LaTeXMode.textmode: '\\mathsf{e}'}, 120255: {LaTeXMode.textmode: '\\mathsf{f}'}, 120256: {LaTeXMode.textmode: '\\mathsf{g}'}, 120257: {LaTeXMode.textmode: '\\mathsf{h}'}, 120258: {LaTeXMode.textmode: '\\mathsf{i}'}, 120259: {LaTeXMode.textmode: '\\mathsf{j}'}, 120260: {LaTeXMode.textmode: '\\mathsf{k}'}, 120261: {LaTeXMode.textmode: '\\mathsf{l}'}, 120262: {LaTeXMode.textmode: '\\mathsf{m}'}, 120263: {LaTeXMode.textmode: '\\mathsf{n}'}, 120264: {LaTeXMode.textmode: '\\mathsf{o}'}, 120265: {LaTeXMode.textmode: '\\mathsf{p}'}, 120266: {LaTeXMode.textmode: '\\mathsf{q}'}, 120267: {LaTeXMode.textmode: '\\mathsf{r}'}, 120268: {LaTeXMode.textmode: '\\mathsf{s}'}, 120269: {LaTeXMode.textmode: '\\mathsf{t}'}, 120270: {LaTeXMode.textmode: '\\mathsf{u}'}, 120271: {LaTeXMode.textmode: '\\mathsf{v}'}, 120272: {LaTeXMode.textmode: '\\mathsf{w}'}, 120273: {LaTeXMode.textmode: '\\mathsf{x}'}, 120274: {LaTeXMode.textmode: '\\mathsf{y}'}, 120275: {LaTeXMode.textmode: '\\mathsf{z}'}, 120276: {LaTeXMode.textmode: '\\mathsfbf{A}'}, 120277: {LaTeXMode.textmode: '\\mathsfbf{B}'}, 120278: {LaTeXMode.textmode: '\\mathsfbf{C}'}, 120279: {LaTeXMode.textmode: '\\mathsfbf{D}'}, 120280: {LaTeXMode.textmode: '\\mathsfbf{E}'}, 120281: {LaTeXMode.textmode: '\\mathsfbf{F}'}, 120282: {LaTeXMode.textmode: '\\mathsfbf{G}'}, 120283: {LaTeXMode.textmode: '\\mathsfbf{H}'}, 120284: {LaTeXMode.textmode: '\\mathsfbf{I}'}, 120285: {LaTeXMode.textmode: '\\mathsfbf{J}'}, 120286: {LaTeXMode.textmode: '\\mathsfbf{K}'}, 120287: {LaTeXMode.textmode: '\\mathsfbf{L}'}, 120288: {LaTeXMode.textmode: '\\mathsfbf{M}'}, 120289: {LaTeXMode.textmode: '\\mathsfbf{N}'}, 120290: {LaTeXMode.textmode: '\\mathsfbf{O}'}, 120291: {LaTeXMode.textmode: '\\mathsfbf{P}'}, 120292: {LaTeXMode.textmode: '\\mathsfbf{Q}'}, 120293: {LaTeXMode.textmode: '\\mathsfbf{R}'}, 120294: {LaTeXMode.textmode: '\\mathsfbf{S}'}, 120295: {LaTeXMode.textmode: '\\mathsfbf{T}'}, 120296: {LaTeXMode.textmode: '\\mathsfbf{U}'}, 120297: {LaTeXMode.textmode: '\\mathsfbf{V}'}, 120298: {LaTeXMode.textmode: '\\mathsfbf{W}'}, 120299: {LaTeXMode.textmode: '\\mathsfbf{X}'}, 120300: {LaTeXMode.textmode: '\\mathsfbf{Y}'}, 120301: {LaTeXMode.textmode: '\\mathsfbf{Z}'}, 120302: {LaTeXMode.textmode: '\\mathsfbf{a}'}, 120303: {LaTeXMode.textmode: '\\mathsfbf{b}'}, 120304: {LaTeXMode.textmode: '\\mathsfbf{c}'}, 120305: {LaTeXMode.textmode: '\\mathsfbf{d}'}, 120306: {LaTeXMode.textmode: '\\mathsfbf{e}'}, 120307: {LaTeXMode.textmode: '\\mathsfbf{f}'}, 120308: {LaTeXMode.textmode: '\\mathsfbf{g}'}, 120309: {LaTeXMode.textmode: '\\mathsfbf{h}'}, 120310: {LaTeXMode.textmode: '\\mathsfbf{i}'}, 120311: {LaTeXMode.textmode: '\\mathsfbf{j}'}, 120312: {LaTeXMode.textmode: '\\mathsfbf{k}'}, 120313: {LaTeXMode.textmode: '\\mathsfbf{l}'}, 120314: {LaTeXMode.textmode: '\\mathsfbf{m}'}, 120315: {LaTeXMode.textmode: '\\mathsfbf{n}'}, 120316: {LaTeXMode.textmode: '\\mathsfbf{o}'}, 120317: {LaTeXMode.textmode: '\\mathsfbf{p}'}, 120318: {LaTeXMode.textmode: '\\mathsfbf{q}'}, 120319: {LaTeXMode.textmode: '\\mathsfbf{r}'}, 120320: {LaTeXMode.textmode: '\\mathsfbf{s}'}, 120321: {LaTeXMode.textmode: '\\mathsfbf{t}'}, 120322: {LaTeXMode.textmode: '\\mathsfbf{u}'}, 120323: {LaTeXMode.textmode: '\\mathsfbf{v}'}, 120324: {LaTeXMode.textmode: '\\mathsfbf{w}'}, 120325: {LaTeXMode.textmode: '\\mathsfbf{x}'}, 120326: {LaTeXMode.textmode: '\\mathsfbf{y}'}, 120327: {LaTeXMode.textmode: '\\mathsfbf{z}'}, 120328: {LaTeXMode.textmode: '\\mathsfsl{A}'}, 120329: {LaTeXMode.textmode: '\\mathsfsl{B}'}, 120330: {LaTeXMode.textmode: '\\mathsfsl{C}'}, 120331: {LaTeXMode.textmode: '\\mathsfsl{D}'}, 120332: {LaTeXMode.textmode: '\\mathsfsl{E}'}, 120333: {LaTeXMode.textmode: '\\mathsfsl{F}'}, 120334: {LaTeXMode.textmode: '\\mathsfsl{G}'}, 120335: {LaTeXMode.textmode: '\\mathsfsl{H}'}, 120336: {LaTeXMode.textmode: '\\mathsfsl{I}'}, 120337: {LaTeXMode.textmode: '\\mathsfsl{J}'}, 120338: {LaTeXMode.textmode: '\\mathsfsl{K}'}, 120339: {LaTeXMode.textmode: '\\mathsfsl{L}'}, 120340: {LaTeXMode.textmode: '\\mathsfsl{M}'}, 120341: {LaTeXMode.textmode: '\\mathsfsl{N}'}, 120342: {LaTeXMode.textmode: '\\mathsfsl{O}'}, 120343: {LaTeXMode.textmode: '\\mathsfsl{P}'}, 120344: {LaTeXMode.textmode: '\\mathsfsl{Q}'}, 120345: {LaTeXMode.textmode: '\\mathsfsl{R}'}, 120346: {LaTeXMode.textmode: '\\mathsfsl{S}'}, 120347: {LaTeXMode.textmode: '\\mathsfsl{T}'}, 120348: {LaTeXMode.textmode: '\\mathsfsl{U}'}, 120349: {LaTeXMode.textmode: '\\mathsfsl{V}'}, 120350: {LaTeXMode.textmode: '\\mathsfsl{W}'}, 120351: {LaTeXMode.textmode: '\\mathsfsl{X}'}, 120352: {LaTeXMode.textmode: '\\mathsfsl{Y}'}, 120353: {LaTeXMode.textmode: '\\mathsfsl{Z}'}, 120354: {LaTeXMode.textmode: '\\mathsfsl{a}'}, 120355: {LaTeXMode.textmode: '\\mathsfsl{b}'}, 120356: {LaTeXMode.textmode: '\\mathsfsl{c}'}, 120357: {LaTeXMode.textmode: '\\mathsfsl{d}'}, 120358: {LaTeXMode.textmode: '\\mathsfsl{e}'}, 120359: {LaTeXMode.textmode: '\\mathsfsl{f}'}, 120360: {LaTeXMode.textmode: '\\mathsfsl{g}'}, 120361: {LaTeXMode.textmode: '\\mathsfsl{h}'}, 120362: {LaTeXMode.textmode: '\\mathsfsl{i}'}, 120363: {LaTeXMode.textmode: '\\mathsfsl{j}'}, 120364: {LaTeXMode.textmode: '\\mathsfsl{k}'}, 120365: {LaTeXMode.textmode: '\\mathsfsl{l}'}, 120366: {LaTeXMode.textmode: '\\mathsfsl{m}'}, 120367: {LaTeXMode.textmode: '\\mathsfsl{n}'}, 120368: {LaTeXMode.textmode: '\\mathsfsl{o}'}, 120369: {LaTeXMode.textmode: '\\mathsfsl{p}'}, 120370: {LaTeXMode.textmode: '\\mathsfsl{q}'}, 120371: {LaTeXMode.textmode: '\\mathsfsl{r}'}, 120372: {LaTeXMode.textmode: '\\mathsfsl{s}'}, 120373: {LaTeXMode.textmode: '\\mathsfsl{t}'}, 120374: {LaTeXMode.textmode: '\\mathsfsl{u}'}, 120375: {LaTeXMode.textmode: '\\mathsfsl{v}'}, 120376: {LaTeXMode.textmode: '\\mathsfsl{w}'}, 120377: {LaTeXMode.textmode: '\\mathsfsl{x}'}, 120378: {LaTeXMode.textmode: '\\mathsfsl{y}'}, 120379: {LaTeXMode.textmode: '\\mathsfsl{z}'}, 120380: {LaTeXMode.textmode: '\\mathsfbfsl{A}'}, 120381: {LaTeXMode.textmode: '\\mathsfbfsl{B}'}, 120382: {LaTeXMode.textmode: '\\mathsfbfsl{C}'}, 120383: {LaTeXMode.textmode: '\\mathsfbfsl{D}'}, 120384: {LaTeXMode.textmode: '\\mathsfbfsl{E}'}, 120385: {LaTeXMode.textmode: '\\mathsfbfsl{F}'}, 120386: {LaTeXMode.textmode: '\\mathsfbfsl{G}'}, 120387: {LaTeXMode.textmode: '\\mathsfbfsl{H}'}, 120388: {LaTeXMode.textmode: '\\mathsfbfsl{I}'}, 120389: {LaTeXMode.textmode: '\\mathsfbfsl{J}'}, 120390: {LaTeXMode.textmode: '\\mathsfbfsl{K}'}, 120391: {LaTeXMode.textmode: '\\mathsfbfsl{L}'}, 120392: {LaTeXMode.textmode: '\\mathsfbfsl{M}'}, 120393: {LaTeXMode.textmode: '\\mathsfbfsl{N}'}, 120394: {LaTeXMode.textmode: '\\mathsfbfsl{O}'}, 120395: {LaTeXMode.textmode: '\\mathsfbfsl{P}'}, 120396: {LaTeXMode.textmode: '\\mathsfbfsl{Q}'}, 120397: {LaTeXMode.textmode: '\\mathsfbfsl{R}'}, 120398: {LaTeXMode.textmode: '\\mathsfbfsl{S}'}, 120399: {LaTeXMode.textmode: '\\mathsfbfsl{T}'}, 120400: {LaTeXMode.textmode: '\\mathsfbfsl{U}'}, 120401: {LaTeXMode.textmode: '\\mathsfbfsl{V}'}, 120402: {LaTeXMode.textmode: '\\mathsfbfsl{W}'}, 120403: {LaTeXMode.textmode: '\\mathsfbfsl{X}'}, 120404: {LaTeXMode.textmode: '\\mathsfbfsl{Y}'}, 120405: {LaTeXMode.textmode: '\\mathsfbfsl{Z}'}, 120406: {LaTeXMode.textmode: '\\mathsfbfsl{a}'}, 120407: {LaTeXMode.textmode: '\\mathsfbfsl{b}'}, 120408: {LaTeXMode.textmode: '\\mathsfbfsl{c}'}, 120409: {LaTeXMode.textmode: '\\mathsfbfsl{d}'}, 120410: {LaTeXMode.textmode: '\\mathsfbfsl{e}'}, 120411: {LaTeXMode.textmode: '\\mathsfbfsl{f}'}, 120412: {LaTeXMode.textmode: '\\mathsfbfsl{g}'}, 120413: {LaTeXMode.textmode: '\\mathsfbfsl{h}'}, 120414: {LaTeXMode.textmode: '\\mathsfbfsl{i}'}, 120415: {LaTeXMode.textmode: '\\mathsfbfsl{j}'}, 120416: {LaTeXMode.textmode: '\\mathsfbfsl{k}'}, 120417: {LaTeXMode.textmode: '\\mathsfbfsl{l}'}, 120418: {LaTeXMode.textmode: '\\mathsfbfsl{m}'}, 120419: {LaTeXMode.textmode: '\\mathsfbfsl{n}'}, 120420: {LaTeXMode.textmode: '\\mathsfbfsl{o}'}, 120421: {LaTeXMode.textmode: '\\mathsfbfsl{p}'}, 120422: {LaTeXMode.textmode: '\\mathsfbfsl{q}'}, 120423: {LaTeXMode.textmode: '\\mathsfbfsl{r}'}, 120424: {LaTeXMode.textmode: '\\mathsfbfsl{s}'}, 120425: {LaTeXMode.textmode: '\\mathsfbfsl{t}'}, 120426: {LaTeXMode.textmode: '\\mathsfbfsl{u}'}, 120427: {LaTeXMode.textmode: '\\mathsfbfsl{v}'}, 120428: {LaTeXMode.textmode: '\\mathsfbfsl{w}'}, 120429: {LaTeXMode.textmode: '\\mathsfbfsl{x}'}, 120430: {LaTeXMode.textmode: '\\mathsfbfsl{y}'}, 120431: {LaTeXMode.textmode: '\\mathsfbfsl{z}'}, 120432: {LaTeXMode.textmode: '\\mathtt{A}'}, 120433: {LaTeXMode.textmode: '\\mathtt{B}'}, 120434: {LaTeXMode.textmode: '\\mathtt{C}'}, 120435: {LaTeXMode.textmode: '\\mathtt{D}'}, 120436: {LaTeXMode.textmode: '\\mathtt{E}'}, 120437: {LaTeXMode.textmode: '\\mathtt{F}'}, 120438: {LaTeXMode.textmode: '\\mathtt{G}'}, 120439: {LaTeXMode.textmode: '\\mathtt{H}'}, 120440: {LaTeXMode.textmode: '\\mathtt{I}'}, 120441: {LaTeXMode.textmode: '\\mathtt{J}'}, 120442: {LaTeXMode.textmode: '\\mathtt{K}'}, 120443: {LaTeXMode.textmode: '\\mathtt{L}'}, 120444: {LaTeXMode.textmode: '\\mathtt{M}'}, 120445: {LaTeXMode.textmode: '\\mathtt{N}'}, 120446: {LaTeXMode.textmode: '\\mathtt{O}'}, 120447: {LaTeXMode.textmode: '\\mathtt{P}'}, 120448: {LaTeXMode.textmode: '\\mathtt{Q}'}, 120449: {LaTeXMode.textmode: '\\mathtt{R}'}, 120450: {LaTeXMode.textmode: '\\mathtt{S}'}, 120451: {LaTeXMode.textmode: '\\mathtt{T}'}, 120452: {LaTeXMode.textmode: '\\mathtt{U}'}, 120453: {LaTeXMode.textmode: '\\mathtt{V}'}, 120454: {LaTeXMode.textmode: '\\mathtt{W}'}, 120455: {LaTeXMode.textmode: '\\mathtt{X}'}, 120456: {LaTeXMode.textmode: '\\mathtt{Y}'}, 120457: {LaTeXMode.textmode: '\\mathtt{Z}'}, 120458: {LaTeXMode.textmode: '\\mathtt{a}'}, 120459: {LaTeXMode.textmode: '\\mathtt{b}'}, 120460: {LaTeXMode.textmode: '\\mathtt{c}'}, 120461: {LaTeXMode.textmode: '\\mathtt{d}'}, 120462: {LaTeXMode.textmode: '\\mathtt{e}'}, 120463: {LaTeXMode.textmode: '\\mathtt{f}'}, 120464: {LaTeXMode.textmode: '\\mathtt{g}'}, 120465: {LaTeXMode.textmode: '\\mathtt{h}'}, 120466: {LaTeXMode.textmode: '\\mathtt{i}'}, 120467: {LaTeXMode.textmode: '\\mathtt{j}'}, 120468: {LaTeXMode.textmode: '\\mathtt{k}'}, 120469: {LaTeXMode.textmode: '\\mathtt{l}'}, 120470: {LaTeXMode.textmode: '\\mathtt{m}'}, 120471: {LaTeXMode.textmode: '\\mathtt{n}'}, 120472: {LaTeXMode.textmode: '\\mathtt{o}'}, 120473: {LaTeXMode.textmode: '\\mathtt{p}'}, 120474: {LaTeXMode.textmode: '\\mathtt{q}'}, 120475: {LaTeXMode.textmode: '\\mathtt{r}'}, 120476: {LaTeXMode.textmode: '\\mathtt{s}'}, 120477: {LaTeXMode.textmode: '\\mathtt{t}'}, 120478: {LaTeXMode.textmode: '\\mathtt{u}'}, 120479: {LaTeXMode.textmode: '\\mathtt{v}'}, 120480: {LaTeXMode.textmode: '\\mathtt{w}'}, 120481: {LaTeXMode.textmode: '\\mathtt{x}'}, 120482: {LaTeXMode.textmode: '\\mathtt{y}'}, 120483: {LaTeXMode.textmode: '\\mathtt{z}'}, 120488: {LaTeXMode.textmode: '\\mathbf{\\Alpha}'}, 120489: {LaTeXMode.textmode: '\\mathbf{\\Beta}'}, 120490: {LaTeXMode.textmode: '\\mathbf{\\Gamma}'}, 120491: {LaTeXMode.textmode: '\\mathbf{\\Delta}'}, 120492: {LaTeXMode.textmode: '\\mathbf{\\Epsilon}'}, 120493: {LaTeXMode.textmode: '\\mathbf{\\Zeta}'}, 120494: {LaTeXMode.textmode: '\\mathbf{\\Eta}'}, 120495: {LaTeXMode.textmode: '\\mathbf{\\Theta}'}, 120496: {LaTeXMode.textmode: '\\mathbf{\\Iota}'}, 120497: {LaTeXMode.textmode: '\\mathbf{\\Kappa}'}, 120498: {LaTeXMode.textmode: '\\mathbf{\\Lambda}'}, 120499: {LaTeXMode.textmode: '\\mathbf{M}'}, 120500: {LaTeXMode.textmode: 'N'}, 120501: {LaTeXMode.textmode: '\\mathbf{\\Xi}'}, 120502: {LaTeXMode.textmode: 'O'}, 120503: {LaTeXMode.textmode: '\\mathbf{\\Pi}'}, 120504: {LaTeXMode.textmode: '\\mathbf{\\Rho}'}, 120505: {LaTeXMode.textmode: '\\mathbf{\\vartheta}'}, 120506: {LaTeXMode.textmode: '\\mathbf{\\Sigma}'}, 120507: {LaTeXMode.textmode: '\\mathbf{\\Tau}'}, 120508: {LaTeXMode.textmode: '\\mathbf{\\Upsilon}'}, 120509: {LaTeXMode.textmode: '\\mathbf{\\Phi}'}, 120510: {LaTeXMode.textmode: '\\mathbf{\\Chi}'}, 120511: {LaTeXMode.textmode: '\\mathbf{\\Psi}'}, 120512: {LaTeXMode.textmode: '\\mathbf{\\Omega}'}, 120513: {LaTeXMode.textmode: '\\mathbf{\\nabla}'}, 120514: {LaTeXMode.textmode: '\\mathbf{\\alpha}'}, 120515: {LaTeXMode.textmode: '\\mathbf{\\beta}'}, 120516: {LaTeXMode.textmode: '\\mathbf{\\gamma}'}, 120517: {LaTeXMode.textmode: '\\mathbf{\\delta}'}, 120518: {LaTeXMode.textmode: '\\mathbf{\\epsilon}'}, 120519: {LaTeXMode.textmode: '\\mathbf{\\zeta}'}, 120520: {LaTeXMode.textmode: '\\mathbf{\\eta}'}, 120521: {LaTeXMode.textmode: '\\mathbf{\\theta}'}, 120522: {LaTeXMode.textmode: '\\mathbf{\\iota}'}, 120523: {LaTeXMode.textmode: '\\mathbf{\\kappa}'}, 120524: {LaTeXMode.textmode: '\\mathbf{\\lambda}'}, 120525: {LaTeXMode.textmode: '\\mathbf{\\mu}'}, 120526: {LaTeXMode.textmode: '\\mathbf{\\nu}'}, 120527: {LaTeXMode.textmode: '\\mathbf{\\xi}'}, 120528: {LaTeXMode.textmode: '\\mathbf{o}'}, 120529: {LaTeXMode.textmode: '\\mathbf{\\pi}'}, 120530: {LaTeXMode.textmode: '\\mathbf{\\rho}'}, 120531: {LaTeXMode.textmode: '\\mathbf{\\varsigma}'}, 120532: {LaTeXMode.textmode: '\\mathbf{\\sigma}'}, 120533: {LaTeXMode.textmode: '\\mathbf{\\tau}'}, 120534: {LaTeXMode.textmode: '\\mathbf{\\upsilon}'}, 120535: {LaTeXMode.textmode: '\\mathbf{\\phi}'}, 120536: {LaTeXMode.textmode: '\\mathbf{\\chi}'}, 120537: {LaTeXMode.textmode: '\\mathbf{\\psi}'}, 120538: {LaTeXMode.textmode: '\\mathbf{\\omega}'}, 120539: {LaTeXMode.textmode: '\\partial '}, 120540: {LaTeXMode.textmode: '\\mathbf{\\varepsilon}'}, 120541: {LaTeXMode.textmode: '\\mathbf{\\vartheta}'}, 120542: {LaTeXMode.textmode: '\\mathbf{\\varkappa}'}, 120543: {LaTeXMode.textmode: '\\mathbf{\\phi}'}, 120544: {LaTeXMode.textmode: '\\mathbf{\\varrho}'}, 120545: {LaTeXMode.textmode: '\\mathbf{\\varpi}'}, 120546: {LaTeXMode.textmode: '\\mathmit{\\Alpha}'}, 120547: {LaTeXMode.textmode: '\\mathmit{\\Beta}'}, 120548: {LaTeXMode.textmode: '\\mathmit{\\Gamma}'}, 120549: {LaTeXMode.textmode: '\\mathmit{\\Delta}'}, 120550: {LaTeXMode.textmode: '\\mathmit{\\Epsilon}'}, 120551: {LaTeXMode.textmode: '\\mathmit{\\Zeta}'}, 120552: {LaTeXMode.textmode: '\\mathmit{\\Eta}'}, 120553: {LaTeXMode.textmode: '\\mathmit{\\Theta}'}, 120554: {LaTeXMode.textmode: '\\mathmit{\\Iota}'}, 120555: {LaTeXMode.textmode: '\\mathmit{\\Kappa}'}, 120556: {LaTeXMode.textmode: '\\mathmit{\\Lambda}'}, 120557: {LaTeXMode.textmode: '\\mathmit{M}'}, 120558: {LaTeXMode.textmode: 'N'}, 120559: {LaTeXMode.textmode: '\\mathmit{\\Xi}'}, 120560: {LaTeXMode.textmode: 'O'}, 120561: {LaTeXMode.textmode: '\\mathmit{\\Pi}'}, 120562: {LaTeXMode.textmode: '\\mathmit{\\Rho}'}, 120563: {LaTeXMode.textmode: '\\mathmit{\\vartheta}'}, 120564: {LaTeXMode.textmode: '\\mathmit{\\Sigma}'}, 120565: {LaTeXMode.textmode: '\\mathmit{\\Tau}'}, 120566: {LaTeXMode.textmode: '\\mathmit{\\Upsilon}'}, 120567: {LaTeXMode.textmode: '\\mathmit{\\Phi}'}, 120568: {LaTeXMode.textmode: '\\mathmit{\\Chi}'}, 120569: {LaTeXMode.textmode: '\\mathmit{\\Psi}'}, 120570: {LaTeXMode.textmode: '\\mathmit{\\Omega}'}, 120571: {LaTeXMode.textmode: '\\mathmit{\\nabla}'}, 120572: {LaTeXMode.textmode: '\\mathmit{\\alpha}'}, 120573: {LaTeXMode.textmode: '\\mathmit{\\beta}'}, 120574: {LaTeXMode.textmode: '\\mathmit{\\gamma}'}, 120575: {LaTeXMode.textmode: '\\mathmit{\\delta}'}, 120576: {LaTeXMode.textmode: '\\mathmit{\\epsilon}'}, 120577: {LaTeXMode.textmode: '\\mathmit{\\zeta}'}, 120578: {LaTeXMode.textmode: '\\mathmit{\\eta}'}, 120579: {LaTeXMode.textmode: '\\mathmit{\\theta}'}, 120580: {LaTeXMode.textmode: '\\mathmit{\\iota}'}, 120581: {LaTeXMode.textmode: '\\mathmit{\\kappa}'}, 120582: {LaTeXMode.textmode: '\\mathmit{\\lambda}'}, 120583: {LaTeXMode.textmode: '\\mathmit{\\mu}'}, 120584: {LaTeXMode.textmode: '\\mathmit{\\nu}'}, 120585: {LaTeXMode.textmode: '\\mathmit{\\xi}'}, 120586: {LaTeXMode.textmode: '\\mathmit{o}'}, 120587: {LaTeXMode.textmode: '\\mathmit{\\pi}'}, 120588: {LaTeXMode.textmode: '\\mathmit{\\rho}'}, 120589: {LaTeXMode.textmode: '\\mathmit{\\varsigma}'}, 120590: {LaTeXMode.textmode: '\\mathmit{\\sigma}'}, 120591: {LaTeXMode.textmode: '\\mathmit{\\tau}'}, 120592: {LaTeXMode.textmode: '\\mathmit{\\upsilon}'}, 120593: {LaTeXMode.textmode: '\\mathmit{\\phi}'}, 120594: {LaTeXMode.textmode: '\\mathmit{\\chi}'}, 120595: {LaTeXMode.textmode: '\\mathmit{\\psi}'}, 120596: {LaTeXMode.textmode: '\\mathmit{\\omega}'}, 120597: {LaTeXMode.textmode: '\\partial '}, 120598: {LaTeXMode.textmode: '\\in'}, 120599: {LaTeXMode.textmode: '\\mathmit{\\vartheta}'}, 120600: {LaTeXMode.textmode: '\\mathmit{\\varkappa}'}, 120601: {LaTeXMode.textmode: '\\mathmit{\\phi}'}, 120602: {LaTeXMode.textmode: '\\mathmit{\\varrho}'}, 120603: {LaTeXMode.textmode: '\\mathmit{\\varpi}'}, 120604: {LaTeXMode.textmode: '\\mathbit{\\Alpha}'}, 120605: {LaTeXMode.textmode: '\\mathbit{\\Beta}'}, 120606: {LaTeXMode.textmode: '\\mathbit{\\Gamma}'}, 120607: {LaTeXMode.textmode: '\\mathbit{\\Delta}'}, 120608: {LaTeXMode.textmode: '\\mathbit{\\Epsilon}'}, 120609: {LaTeXMode.textmode: '\\mathbit{\\Zeta}'}, 120610: {LaTeXMode.textmode: '\\mathbit{\\Eta}'}, 120611: {LaTeXMode.textmode: '\\mathbit{\\Theta}'}, 120612: {LaTeXMode.textmode: '\\mathbit{\\Iota}'}, 120613: {LaTeXMode.textmode: '\\mathbit{\\Kappa}'}, 120614: {LaTeXMode.textmode: '\\mathbit{\\Lambda}'}, 120615: {LaTeXMode.textmode: '\\mathbit{M}'}, 120616: {LaTeXMode.textmode: '\\mathbit{N}'}, 120617: {LaTeXMode.textmode: '\\mathbit{\\Xi}'}, 120618: {LaTeXMode.textmode: 'O'}, 120619: {LaTeXMode.textmode: '\\mathbit{\\Pi}'}, 120620: {LaTeXMode.textmode: '\\mathbit{\\Rho}'}, 120621: {LaTeXMode.textmode: '\\mathbit{O}'}, 120622: {LaTeXMode.textmode: '\\mathbit{\\Sigma}'}, 120623: {LaTeXMode.textmode: '\\mathbit{\\Tau}'}, 120624: {LaTeXMode.textmode: '\\mathbit{\\Upsilon}'}, 120625: {LaTeXMode.textmode: '\\mathbit{\\Phi}'}, 120626: {LaTeXMode.textmode: '\\mathbit{\\Chi}'}, 120627: {LaTeXMode.textmode: '\\mathbit{\\Psi}'}, 120628: {LaTeXMode.textmode: '\\mathbit{\\Omega}'}, 120629: {LaTeXMode.textmode: '\\mathbit{\\nabla}'}, 120630: {LaTeXMode.textmode: '\\mathbit{\\alpha}'}, 120631: {LaTeXMode.textmode: '\\mathbit{\\beta}'}, 120632: {LaTeXMode.textmode: '\\mathbit{\\gamma}'}, 120633: {LaTeXMode.textmode: '\\mathbit{\\delta}'}, 120634: {LaTeXMode.textmode: '\\mathbit{\\epsilon}'}, 120635: {LaTeXMode.textmode: '\\mathbit{\\zeta}'}, 120636: {LaTeXMode.textmode: '\\mathbit{\\eta}'}, 120637: {LaTeXMode.textmode: '\\mathbit{\\theta}'}, 120638: {LaTeXMode.textmode: '\\mathbit{\\iota}'}, 120639: {LaTeXMode.textmode: '\\mathbit{\\kappa}'}, 120640: {LaTeXMode.textmode: '\\mathbit{\\lambda}'}, 120641: {LaTeXMode.textmode: '\\mathbit{\\mu}'}, 120642: {LaTeXMode.textmode: '\\mathbit{\\nu}'}, 120643: {LaTeXMode.textmode: '\\mathbit{\\xi}'}, 120644: {LaTeXMode.textmode: '\\mathbit{o}'}, 120645: {LaTeXMode.textmode: '\\mathbit{\\pi}'}, 120646: {LaTeXMode.textmode: '\\mathbit{\\rho}'}, 120647: {LaTeXMode.textmode: '\\mathbit{\\varsigma}'}, 120648: {LaTeXMode.textmode: '\\mathbit{\\sigma}'}, 120649: {LaTeXMode.textmode: '\\mathbit{\\tau}'}, 120650: {LaTeXMode.textmode: '\\mathbit{\\upsilon}'}, 120651: {LaTeXMode.textmode: '\\mathbit{\\phi}'}, 120652: {LaTeXMode.textmode: '\\mathbit{\\chi}'}, 120653: {LaTeXMode.textmode: '\\mathbit{\\psi}'}, 120654: {LaTeXMode.textmode: '\\mathbit{\\omega}'}, 120655: {LaTeXMode.textmode: '\\partial '}, 120656: {LaTeXMode.textmode: '\\in'}, 120657: {LaTeXMode.textmode: '\\mathbit{\\vartheta}'}, 120658: {LaTeXMode.textmode: '\\mathbit{\\varkappa}'}, 120659: {LaTeXMode.textmode: '\\mathbit{\\phi}'}, 120660: {LaTeXMode.textmode: '\\mathbit{\\varrho}'}, 120661: {LaTeXMode.textmode: '\\mathbit{\\varpi}'}, 120662: {LaTeXMode.textmode: '\\mathsfbf{\\Alpha}'}, 120663: {LaTeXMode.textmode: '\\mathsfbf{\\Beta}'}, 120664: {LaTeXMode.textmode: '\\mathsfbf{\\Gamma}'}, 120665: {LaTeXMode.textmode: '\\mathsfbf{\\Delta}'}, 120666: {LaTeXMode.textmode: '\\mathsfbf{\\Epsilon}'}, 120667: {LaTeXMode.textmode: '\\mathsfbf{\\Zeta}'}, 120668: {LaTeXMode.textmode: '\\mathsfbf{\\Eta}'}, 120669: {LaTeXMode.textmode: '\\mathsfbf{\\Theta}'}, 120670: {LaTeXMode.textmode: '\\mathsfbf{\\Iota}'}, 120671: {LaTeXMode.textmode: '\\mathsfbf{\\Kappa}'}, 120672: {LaTeXMode.textmode: '\\mathsfbf{\\Lambda}'}, 120673: {LaTeXMode.textmode: '\\mathsfbf{M}'}, 120674: {LaTeXMode.textmode: '\\mathsfbf{N}'}, 120675: {LaTeXMode.textmode: '\\mathsfbf{\\Xi}'}, 120676: {LaTeXMode.textmode: 'O'}, 120677: {LaTeXMode.textmode: '\\mathsfbf{\\Pi}'}, 120678: {LaTeXMode.textmode: '\\mathsfbf{\\Rho}'}, 120679: {LaTeXMode.textmode: '\\mathsfbf{\\vartheta}'}, 120680: {LaTeXMode.textmode: '\\mathsfbf{\\Sigma}'}, 120681: {LaTeXMode.textmode: '\\mathsfbf{\\Tau}'}, 120682: {LaTeXMode.textmode: '\\mathsfbf{\\Upsilon}'}, 120683: {LaTeXMode.textmode: '\\mathsfbf{\\Phi}'}, 120684: {LaTeXMode.textmode: '\\mathsfbf{\\Chi}'}, 120685: {LaTeXMode.textmode: '\\mathsfbf{\\Psi}'}, 120686: {LaTeXMode.textmode: '\\mathsfbf{\\Omega}'}, 120687: {LaTeXMode.textmode: '\\mathsfbf{\\nabla}'}, 120688: {LaTeXMode.textmode: '\\mathsfbf{\\alpha}'}, 120689: {LaTeXMode.textmode: '\\mathsfbf{\\beta}'}, 120690: {LaTeXMode.textmode: '\\mathsfbf{\\gamma}'}, 120691: {LaTeXMode.textmode: '\\mathsfbf{\\delta}'}, 120692: {LaTeXMode.textmode: '\\mathsfbf{\\epsilon}'}, 120693: {LaTeXMode.textmode: '\\mathsfbf{\\zeta}'}, 120694: {LaTeXMode.textmode: '\\mathsfbf{\\eta}'}, 120695: {LaTeXMode.textmode: '\\mathsfbf{\\theta}'}, 120696: {LaTeXMode.textmode: '\\mathsfbf{\\iota}'}, 120697: {LaTeXMode.textmode: '\\mathsfbf{\\kappa}'}, 120698: {LaTeXMode.textmode: '\\mathsfbf{\\lambda}'}, 120699: {LaTeXMode.textmode: '\\mathsfbf{\\mu}'}, 120700: {LaTeXMode.textmode: '\\mathsfbf{\\nu}'}, 120701: {LaTeXMode.textmode: '\\mathsfbf{\\xi}'}, 120702: {LaTeXMode.textmode: '\\mathsfbf{o}'}, 120703: {LaTeXMode.textmode: '\\mathsfbf{\\pi}'}, 120704: {LaTeXMode.textmode: '\\mathsfbf{\\rho}'}, 120705: {LaTeXMode.textmode: '\\mathsfbf{\\varsigma}'}, 120706: {LaTeXMode.textmode: '\\mathsfbf{\\sigma}'}, 120707: {LaTeXMode.textmode: '\\mathsfbf{\\tau}'}, 120708: {LaTeXMode.textmode: '\\mathsfbf{\\upsilon}'}, 120709: {LaTeXMode.textmode: '\\mathsfbf{\\phi}'}, 120710: {LaTeXMode.textmode: '\\mathsfbf{\\chi}'}, 120711: {LaTeXMode.textmode: '\\mathsfbf{\\psi}'}, 120712: {LaTeXMode.textmode: '\\mathsfbf{\\omega}'}, 120713: {LaTeXMode.textmode: '\\partial '}, 120714: {LaTeXMode.textmode: '\\mathsfbf{\\varepsilon}'}, 120715: {LaTeXMode.textmode: '\\mathsfbf{\\vartheta}'}, 120716: {LaTeXMode.textmode: '\\mathsfbf{\\varkappa}'}, 120717: {LaTeXMode.textmode: '\\mathsfbf{\\phi}'}, 120718: {LaTeXMode.textmode: '\\mathsfbf{\\varrho}'}, 120719: {LaTeXMode.textmode: '\\mathsfbf{\\varpi}'}, 120720: {LaTeXMode.textmode: '\\mathsfbfsl{\\Alpha}'}, 120721: {LaTeXMode.textmode: '\\mathsfbfsl{\\Beta}'}, 120722: {LaTeXMode.textmode: '\\mathsfbfsl{\\Gamma}'}, 120723: {LaTeXMode.textmode: '\\mathsfbfsl{\\Delta}'}, 120724: {LaTeXMode.textmode: '\\mathsfbfsl{\\Epsilon}'}, 120725: {LaTeXMode.textmode: '\\mathsfbfsl{\\Zeta}'}, 120726: {LaTeXMode.textmode: '\\mathsfbfsl{\\Eta}'}, 120727: {LaTeXMode.textmode: '\\mathsfbfsl{\\vartheta}'}, 120728: {LaTeXMode.textmode: '\\mathsfbfsl{\\Iota}'}, 120729: {LaTeXMode.textmode: '\\mathsfbfsl{\\Kappa}'}, 120730: {LaTeXMode.textmode: '\\mathsfbfsl{\\Lambda}'}, 120731: {LaTeXMode.textmode: '\\mathsfbfsl{M}'}, 120732: {LaTeXMode.textmode: '\\mathsfbfsl{N}'}, 120733: {LaTeXMode.textmode: '\\mathsfbfsl{\\Xi}'}, 120734: {LaTeXMode.textmode: 'O'}, 120735: {LaTeXMode.textmode: '\\mathsfbfsl{\\Pi}'}, 120736: {LaTeXMode.textmode: '\\mathsfbfsl{\\Rho}'}, 120737: {LaTeXMode.textmode: '\\mathsfbfsl{\\vartheta}'}, 120738: {LaTeXMode.textmode: '\\mathsfbfsl{\\Sigma}'}, 120739: {LaTeXMode.textmode: '\\mathsfbfsl{\\Tau}'}, 120740: {LaTeXMode.textmode: '\\mathsfbfsl{\\Upsilon}'}, 120741: {LaTeXMode.textmode: '\\mathsfbfsl{\\Phi}'}, 120742: {LaTeXMode.textmode: '\\mathsfbfsl{\\Chi}'}, 120743: {LaTeXMode.textmode: '\\mathsfbfsl{\\Psi}'}, 120744: {LaTeXMode.textmode: '\\mathsfbfsl{\\Omega}'}, 120745: {LaTeXMode.textmode: '\\mathsfbfsl{\\nabla}'}, 120746: {LaTeXMode.textmode: '\\mathsfbfsl{\\alpha}'}, 120747: {LaTeXMode.textmode: '\\mathsfbfsl{\\beta}'}, 120748: {LaTeXMode.textmode: '\\mathsfbfsl{\\gamma}'}, 120749: {LaTeXMode.textmode: '\\mathsfbfsl{\\delta}'}, 120750: {LaTeXMode.textmode: '\\mathsfbfsl{\\epsilon}'}, 120751: {LaTeXMode.textmode: '\\mathsfbfsl{\\zeta}'}, 120752: {LaTeXMode.textmode: '\\mathsfbfsl{\\eta}'}, 120753: {LaTeXMode.textmode: '\\mathsfbfsl{\\vartheta}'}, 120754: {LaTeXMode.textmode: '\\mathsfbfsl{\\iota}'}, 120755: {LaTeXMode.textmode: '\\mathsfbfsl{\\kappa}'}, 120756: {LaTeXMode.textmode: '\\mathsfbfsl{\\lambda}'}, 120757: {LaTeXMode.textmode: '\\mathsfbfsl{\\mu}'}, 120758: {LaTeXMode.textmode: '\\mathsfbfsl{\\nu}'}, 120759: {LaTeXMode.textmode: '\\mathsfbfsl{\\xi}'}, 120760: {LaTeXMode.textmode: '\\mathsfbfsl{o}'}, 120761: {LaTeXMode.textmode: '\\mathsfbfsl{\\pi}'}, 120762: {LaTeXMode.textmode: '\\mathsfbfsl{\\rho}'}, 120763: {LaTeXMode.textmode: '\\mathsfbfsl{\\varsigma}'}, 120764: {LaTeXMode.textmode: '\\mathsfbfsl{\\sigma}'}, 120765: {LaTeXMode.textmode: '\\mathsfbfsl{\\tau}'}, 120766: {LaTeXMode.textmode: '\\mathsfbfsl{\\upsilon}'}, 120767: {LaTeXMode.textmode: '\\mathsfbfsl{\\phi}'}, 120768: {LaTeXMode.textmode: '\\mathsfbfsl{\\chi}'}, 120769: {LaTeXMode.textmode: '\\mathsfbfsl{\\psi}'}, 120770: {LaTeXMode.textmode: '\\mathsfbfsl{\\omega}'}, 120771: {LaTeXMode.textmode: '\\partial '}, 120772: {LaTeXMode.textmode: '\\in'}, 120773: {LaTeXMode.textmode: '\\mathsfbfsl{\\vartheta}'}, 120774: {LaTeXMode.textmode: '\\mathsfbfsl{\\varkappa}'}, 120775: {LaTeXMode.textmode: '\\mathsfbfsl{\\phi}'}, 120776: {LaTeXMode.textmode: '\\mathsfbfsl{\\varrho}'}, 120777: {LaTeXMode.textmode: '\\mathsfbfsl{\\varpi}'}, 120782: {LaTeXMode.textmode: '\\mathbf{0}'}, 120783: {LaTeXMode.textmode: '\\mathbf{1}'}, 120784: {LaTeXMode.textmode: '\\mathbf{2}'}, 120785: {LaTeXMode.textmode: '\\mathbf{3}'}, 120786: {LaTeXMode.textmode: '\\mathbf{4}'}, 120787: {LaTeXMode.textmode: '\\mathbf{5}'}, 120788: {LaTeXMode.textmode: '\\mathbf{6}'}, 120789: {LaTeXMode.textmode: '\\mathbf{7}'}, 120790: {LaTeXMode.textmode: '\\mathbf{8}'}, 120791: {LaTeXMode.textmode: '\\mathbf{9}'}, 120792: {LaTeXMode.textmode: '\\mathbb{0}'}, 120793: {LaTeXMode.textmode: '\\mathbb{1}'}, 120794: {LaTeXMode.textmode: '\\mathbb{2}'}, 120795: {LaTeXMode.textmode: '\\mathbb{3}'}, 120796: {LaTeXMode.textmode: '\\mathbb{4}'}, 120797: {LaTeXMode.textmode: '\\mathbb{5}'}, 120798: {LaTeXMode.textmode: '\\mathbb{6}'}, 120799: {LaTeXMode.textmode: '\\mathbb{7}'}, 120800: {LaTeXMode.textmode: '\\mathbb{8}'}, 120801: {LaTeXMode.textmode: '\\mathbb{9}'}, 120802: {LaTeXMode.textmode: '\\mathsf{0}'}, 120803: {LaTeXMode.textmode: '\\mathsf{1}'}, 120804: {LaTeXMode.textmode: '\\mathsf{2}'}, 120805: {LaTeXMode.textmode: '\\mathsf{3}'}, 120806: {LaTeXMode.textmode: '\\mathsf{4}'}, 120807: {LaTeXMode.textmode: '\\mathsf{5}'}, 120808: {LaTeXMode.textmode: '\\mathsf{6}'}, 120809: {LaTeXMode.textmode: '\\mathsf{7}'}, 120810: {LaTeXMode.textmode: '\\mathsf{8}'}, 120811: {LaTeXMode.textmode: '\\mathsf{9}'}, 120812: {LaTeXMode.textmode: '\\mathsfbf{0}'}, 120813: {LaTeXMode.textmode: '\\mathsfbf{1}'}, 120814: {LaTeXMode.textmode: '\\mathsfbf{2}'}, 120815: {LaTeXMode.textmode: '\\mathsfbf{3}'}, 120816: {LaTeXMode.textmode: '\\mathsfbf{4}'}, 120817: {LaTeXMode.textmode: '\\mathsfbf{5}'}, 120818: {LaTeXMode.textmode: '\\mathsfbf{6}'}, 120819: {LaTeXMode.textmode: '\\mathsfbf{7}'}, 120820: {LaTeXMode.textmode: '\\mathsfbf{8}'}, 120821: {LaTeXMode.textmode: '\\mathsfbf{9}'}, 120822: {LaTeXMode.textmode: '\\mathtt{0}'}, 120823: {LaTeXMode.textmode: '\\mathtt{1}'}, 120824: {LaTeXMode.textmode: '\\mathtt{2}'}, 120825: {LaTeXMode.textmode: '\\mathtt{3}'}, 120826: {LaTeXMode.textmode: '\\mathtt{4}'}, 120827: {LaTeXMode.textmode: '\\mathtt{5}'}, 120828: {LaTeXMode.textmode: '\\mathtt{6}'}, 120829: {LaTeXMode.textmode: '\\mathtt{7}'}, 120830: {LaTeXMode.textmode: '\\mathtt{8}'}, 120831: {LaTeXMode.textmode: '\\mathtt{9}'}, } GladTeX-2.3.1/manpage.md000066400000000000000000000135231317106144100147410ustar00rootroot00000000000000% GLADTEX(1) % Sebastian Humenda % 28th of September 2016 # NAME **GladTeX** - generate HTML with LaTeX formulas embedded as images # SYNOPSIS **gladtex** [OPTIONS] [INPUT FILE NAME] # DESCRIPTION **GladTeX** is a formula preprocessor for HTML files. It recognizes a special tag (`...`) and will convert the contained LaTeX formulas into images. The resulting images will be linked into the resulting HTML document. This eases the process of creating HTML documents (or web sites) containing formulas.\ The generated images are saved in a cache to not render the same image over and over again. This speeds up the process when formulas occur multiple times or when a document is extended gradually. The LaTeX formulas are preserved in the alt attribute of the embedded images. Hence screen reader users benefit from an accessible HTML version of the document. Furthermore it can be used with Pandoc to convert Markdown documents with LaTeX formulas to HTML. See [FILE FORMAT](#file-format) for an explanation of the file format and [EXAMPLES](#examples) for examples on how to use GladTeX on its own or with Pandoc. # OPTIONS **INPUT FILE NAME** : Input .htex file with LaTeX formulas (if omitted or -, stdin will be read). **-h** **--help** : Show this help message and exit. **-a** : Save text alternatives for images which are too long for the alt attribute into a single separate file and link images to it. **-b** _BACKGROUND_COLOR_ : Set background color for resulting images (default transparent). **-c** _`FOREGROUND_COLOR`_ : Set foreground color for resulting images (default 0,0,0). **-d** _DIRECTORY_ : Directory in which to store the generated images in (relative path). **-e** _`LATEX_MATHS_ENV`_ : Set custom maths environment to surround the formula (e.g. flalign). **-E** _ENCODING_ : Overwrite encoding to use (default UTF-8). **-i** _CLASS_ : CSS class to assign to inline math (default: 'inlinemath'). **-K** : keep LaTeX file(s) when converting formulas By default, the generated LaTeX document, containing the formula to be converted, are removed after the conversion (no matter whether it was successful or not). If it wasn't successful, it is sometimes helpful to look at the complete document. This option will keep the file. **-l** _CLASS_ : CSS class to assign to block-level math (default: 'displaymath'). **-n** : Purge unreadable caches along with all eqn*.png files. Caches can be unreadable if the used GladTeX version is incompatible. If this option is unset, GladTeX will simply fail when the cache is unreadable. **-m** : Print error output in machine-readable format (less concise, better parseable). Each line will start with a key, followed by a colon, followed by the value, i.e. `line: 5`. **-o** _FILENAME_ : Set output file name. '-' will print text to stdout. Bydefault, input file name is used and the `.htex` extension is replaced by `.html`. **-p** _`LATEX_STATEMENT`_ : Add given LaTeX code to preamble of document. That'll affect the conversion of every image. **-r** _DPI_ : Set resolution (size of images) to 'dpi' (100 by default). **-R** : Replace non-ascii (unicode) characters by LaTeX commands. GladTeX can automatically detect non-ascii characters in formulas and replace them through their appropriate LaTeX commands. In the alt attribute of the resulting image, alphabetical characters won't be replaced. That means that the alt text from the image is not exactly the same than the code used for generating the image, but it is far more readable. For instance, the formula \$\\text{für alle} a\$, would be compiled as \$\\text{f\\ddot{u}r alle} a\$ and displayed as "\\text{für alle} a" in the alt attribute. **-u** _URL_ : Base URL to image files (relative links are default). # FILE FORMAT A .htex file is essentially a HTML file containing LaTeX formulas. The formulas have to be surrounded by `` and ``. By default, formulas are rendered as inline maths, so they are squeezed to the height of the line. It is possible to render a formula as display maths by setting the env attribute to displaymath, i.e. `...`. # EXAMPLES ## Sample HTEX document A sample HTEX document could look like this: ~~~~

Some text

Circumference of a circle: u = \pi\cdot d

A useful matrix: \begin{pmatrix} 1 &2 &3 &4\\ 5 &6 &7 &8\\ 9 &10&11&12 \end{pmatrix}

~~~~ This can be converted using gladtex file.htex and the result will be a HTML document called `file.html` along with two files `eqn0000.png` and `eqn0001.png` in the same directory. ## Markdown to HTML GladTeX can be used together with Pandoc. That can be handy to create an online version of a scientific paper written in Markdown. The MarkDown document would look like this: ~~~~ Some text ========= Circumference of a circle: $u = \pi\cdot d$ A useful matrix: $$\begin{pmatrix} 1 &2 &3 &4\\ 5 &6 &7 &8\\ 9 &10&11&12 \end{pmatrix}$$ ~~~~ The conversion is as easy as: pandoc -s -t html --gladtex file.md | gladtex -o file.html # KNOWN LIMITATIONS LaTeX2e is ***NOT*** unicode aware. If you have any unicode (more precisely, non-ascii characters) signs in your documents, you have the choice to do one of the following: 1. Look up the symbol in one of the many LaTeX formula listings and replace the symbol with the appropriate command. 2. Use the `-R` switch to let GladTeX replace the Umlauts for you. Please note that it is not possible to use LuaLaTeX. At the time of writing, dvipng does not support the extended font features of the LuaLaTeX engine. # PROJECT HOME The project home is at . The source can be found at . GladTeX-2.3.1/runtests000077500000000000000000000004321317106144100146170ustar00rootroot00000000000000#!/bin/sh # change above to python, if your system doesn't have the 3 suffix for python 3 set -e PYTHON=python # check whether a program called "python3" exists, else use "python" if command -v python3 >/dev/null 2>&1 then PYTHON=python3 fi $PYTHON -m unittest discover tests GladTeX-2.3.1/setup.py000066400000000000000000000071621317106144100145230ustar00rootroot00000000000000import distutils.command.install_scripts, distutils.command.build, distutils.command.clean from distutils.core import setup import os import shutil import sys #pylint: disable=unused-import try: import py2exe # only works on windows except ImportError: pass from gleetex import VERSION class ScriptInstaller(distutils.command.install_scripts.install_scripts): """Custom script installer. Stript .py extension if not on Windows.""" def run(self): distutils.command.install_scripts.install_scripts.run(self) for script in self.get_outputs(): if script.endswith(".py") and not ('wind' in sys.platform or 'win32' in sys.platform): # strip file ending (if not on windows) to make it executable as # a command shutil.move(script, script[:-3]) #pylint: disable=attribute-defined-outside-init class CleanCommand(distutils.command.clean.clean): description = "clean all build files, including __pycache__ and others" user_options = [] def initialize_options(self): self.cwd = None def finalize_options(self): self.cwd = os.getcwd() def run(self): assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd for directory in ['build', '__pycache__', 'dist', os.path.join('gleetex', '__pycache')]: if os.path.exists(directory): shutil.rmtree(directory) if os.path.exists('gladtex.1'): os.remove('gladtex.1') class CustomBuild(distutils.command.build.build): """Also build manpage to build/gladtex.1; it is not installed automatically.""" def initialize_options(self): self.cwd = None super().initialize_options() def finalize_options(self): self.cwd = os.getcwd() super().finalize_options() def run(self): if not self.cwd: if not 'manpage.md' in os.listdir('.'): print("setup.py must be run from the source root") sys.exit(91) else: assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd super().run() if shutil.which('pandoc'): # only build man page, if pandoc present self.build_manpage('manpage.md', os.path.join('build', 'gladtex.1')) else: print("w: pandoc not found, skipping man page conversion.") def build_manpage(self, input_fn, output_fn): """Convert `input_fn` from markdown into manpage format and save it to `output_fn`. Pandoc is required.""" import subprocess try: cmd = ['pandoc', input_fn, '-s', '-t', 'man', '-o', output_fn] proc = subprocess.Popen(cmd) ret = proc.wait() if ret: raise subprocess.SubprocessError("Exit status %d when running '%s'" % (ret, ' '.join(cmd))) except FileNotFoundError: sys.stderr.write("Pandoc was not found on the system, skipping man " + "page creation.") setup(name='GladTeX', version=VERSION, description='generate html with LaTeX equations embedded as images', author='Sebastian Humenda', author_email='shumenda |at| gmx |dot| de', url='https://humenda.github.io/GladTeX', packages=['gleetex'], console=['gladtex.py'], # Windows-only option, use python instead of pythonw setup_requires=['py2app'], # require py2app on Mac OS scripts=['gladtex.py'], license = "LGPL3.0", cmdclass = {"install_scripts": ScriptInstaller, 'clean': CleanCommand, 'build': CustomBuild} ) GladTeX-2.3.1/tests/000077500000000000000000000000001317106144100141455ustar00rootroot00000000000000GladTeX-2.3.1/tests/test_caching.py000066400000000000000000000133601317106144100171550ustar00rootroot00000000000000#pylint: disable=too-many-public-methods,import-error,too-few-public-methods,missing-docstring,unused-variable import os import shutil import tempfile import unittest from gleetex import caching def write(path, content): with open(path, 'w', encoding='utf-8') as f: f.write(content) class test_caching(unittest.TestCase): def setUp(self): self.pos = {'height' : 8, 'depth' : 2, 'width' : 666} self.original_directory = os.getcwd() self.tmpdir = tempfile.mkdtemp() os.chdir(self.tmpdir) def tearDown(self): os.chdir(self.original_directory) shutil.rmtree(self.tmpdir, ignore_errors=True) def test_differently_spaced_formulas_are_the_same(self): form1 = r'\tau \pi' form2 = '\tau\\pi' self.assertTrue(caching.normalize_formula(form1), caching.normalize_formula(form2)) def test_trailing_and_leading_spaces_and_tabs_are_no_problem(self): u = caching.normalize_formula form1 = ' hi' form2 = 'hi ' form3 = '\thi' self.assertEqual(u(form1), u(form2)) self.assertEqual(u(form1), u(form3)) def test_that_empty_braces_are_ignored(self): u = caching.normalize_formula form1 = r'\sin{}x' form2 = r'\sin x' form3 = r'\sin{} x' self.assertEqual(u(form1), u(form2)) self.assertEqual(u(form1), u(form3)) self.assertEqual(u(form2), u(form3)) def test_empty_cache_works_fine(self): write('foo.png', 'muha') c = caching.ImageCache('file.png') formula = r"f(x) = \ln(x)" c.add_formula(formula, self.pos, 'foo.png') self.assertTrue(c.contains(formula, False)) def test_that_invalid_cach_entries_are_detected(self): # entry is invalid if file doesn't exist c = caching.ImageCache() formula = r"f(x) = \ln(x)" self.assertRaises(OSError, c.add_formula, formula, self.pos, 'file.png') def test_that_correct_pos_and_path_are_returned_after_writing_the_cache_back(self): c = caching.ImageCache() formula = r"g(x) = \ln(x)" write('file.png', 'dummy') c.add_formula(formula, self.pos, 'file.png', displaymath=False) c.write() c = caching.ImageCache() self.assertTrue(c.contains(formula, False)) data = c.get_data_for(formula, False) self.assertEqual(data['pos'], self.pos) self.assertEqual(data['path'], 'file.png') def test_formulas_are_not_added_twice(self): form1 = r'\ln(x) \neq e^x' write('spass.png', 'binaryBinary_binary') c = caching.ImageCache() for i in range(1,10): c.add_formula(form1, self.pos, 'spass.png') self.assertEqual(len(c), 1) def test_that_remove_actually_removes(self): form1 = '\\int e^x dy' write('happyness.png', 'binaryBinary_binary') c = caching.ImageCache() c.add_formula(form1, self.pos, 'happyness.png') c.remove_formula(form1, False) self.assertEqual(len(c), 0) def test_removal_of_non_existing_formula_raises_exception(self): c = caching.ImageCache() self.assertRaises(KeyError, c.remove_formula, 'Haha!', False) def test_that_invalid_version_is_detected(self): c = caching.ImageCache('gladtex.cache') c._ImageCache__set_version('invalid.stuff') c.write() self.assertRaises(caching.JsonParserException, caching.ImageCache, 'gladtex.cache') def test_that_invalid_style_is_detected(self): write('foo.png', "dummy") c = caching.ImageCache('gladtex.cache') c.add_formula('\\tau', self.pos, 'foo.png', False) c.add_formula('\\theta', self.pos, 'foo.png', True) self.assertRaises(ValueError, c.add_formula, '\\gamma', self.pos, 'foo.png', 'some stuff') def test_that_backslash_in_path_is_replaced_through_slash(self): c = caching.ImageCache('gladtex.cache') os.mkdir('bilder') write(os.path.join('bilder', 'foo.png'), str(0xdeadbeef)) c.add_formula('\\tau', self.pos, 'bilder\\foo.png', False) self.assertTrue('/' in c.get_data_for('\\tau', False)['path']) def test_that_absolute_paths_trigger_OSError(self): c = caching.ImageCache('gladtex.cache') write('foo.png', "dummy") fn = os.path.abspath('foo.png') self.assertRaises(OSError, c.add_formula, '\\tau', self.pos, fn, False) def test_that_invalid_caches_are_removed_automatically_if_desired(self): file_was_removed = lambda x: self.assertFalse(os.path.exists(x), "expected that file %s was removed, but it still exists" % x) write('gladtex.cache', 'some non-json rubbish') c = caching.ImageCache('gladtex.cache', keep_old_cache=False) file_was_removed('gladtex.cache') # try the same in a subdirectory os.mkdir('foo') cache_path = os.path.join('foo', 'gladtex.cache') eqn1_path = os.path.join('foo', 'eqn000.png') eqn2_path = os.path.join('foo', 'eqn003.png') write(cache_path, 'some non-json rubbish') write(eqn1_path, 'binary') write(eqn2_path, 'more binary') c = caching.ImageCache(cache_path, keep_old_cache=False) file_was_removed(cache_path) file_was_removed(eqn1_path) file_was_removed(eqn2_path) def test_that_formulas_in_cache_with_no_file_raise_key_error(self): c = caching.ImageCache('gladtex.cache', keep_old_cache=False) write('foo.png', 'dummy') c.add_formula('\\tau', self.pos, 'foo.png') c.write() os.remove('foo.png') c = caching.ImageCache('gladtex.cache', keep_old_cache=False) with self.assertRaises(KeyError): c.get_data_for('foo.png', 'False') GladTeX-2.3.1/tests/test_convenience.py000066400000000000000000000137121317106144100200560ustar00rootroot00000000000000#pylint: disable=too-many-public-methods,import-error,too-few-public-methods,missing-docstring,unused-variable import distutils import os import shutil import tempfile import unittest from gleetex import convenience, image from gleetex.convenience import ConversionException from gleetex.caching import JsonParserException def get_number_of_files(path): return len(os.listdir(path)) def mk_eqn(eqn, count=0, pos=(1,1)): """Create formula. Each formula must look like this: (eqn, pos, path, dsp, count) for self._convert_concurrently, this is a shorthand with mocking a few values.""" return (eqn, pos, 'eqn%03d.png' % count, False, count) def turn_into_orig_formulas(formulas): """Turn a list of formulas as accepted by CachedConverter._convert_concurrently() into a list accepted by CachedConverter._get_formulas_to_convert().""" return [(e[1], e[3], e[0]) for e in formulas] def write(path, content='dummy'): with open(path, 'w', encoding='utf-8') as f: f.write(content) class Tex2imgMock(): """Could use a proper mock, but this one allows a bit more tricking.""" def __init__(self, _tex_document, output_fn, _encoding="UTF-8"): self.output_name = output_fn base_name = os.path.split(output_fn)[0] if base_name and not os.path.exists(base_name): distutils.dir_util.mkpath(base_name) self.set_dpi = self.set_transparency = self.set_foreground_color \ = self.set_background_color = lambda x: None # do nothing def create_dvi(self, dvi_fn): """ Call LaTeX to produce a dvi file with the given LaTeX document. Temporary files will be removed, even in the case of a LaTeX error. This method raises a SubprocessError with the helpful part of LaTeX's error output.""" with open(dvi_fn, 'w') as f: f.write('dummy') def create_png(self, dvi_fn): if os.path.exists(dvi_fn): os.remove(dvi_fn) write(self.output_name) def convert(self): self.create_png(self.output_name) def get_positioning_info(self): return {'depth': 9, 'height': 8, 'width': 7} def parse_log(self, _logdata): return {} class TestCachedConverter(unittest.TestCase): #pylint: disable=protected-access def setUp(self): self.original_directory = os.getcwd() self.tmpdir = tempfile.mkdtemp() os.chdir(self.tmpdir) convenience.CachedConverter._converter = Tex2imgMock #pylint: disable=protected-access def tearDown(self): # restore static reference to converter convenience.CachedConverter._converter = image.Tex2img os.chdir(self.original_directory) shutil.rmtree(self.tmpdir, ignore_errors=True) def test_that_subdirectory_is_created(self): c = convenience.CachedConverter(os.getcwd(), 'subdirectory') formula = '\\textbf{FOO!}' c.convert(formula, 'subdirectory/eqn000.png') # one directory exists self.assertEqual(get_number_of_files('.'), 1, "Found the following files, expected only 'subdirectory': " + \ ', '.join(os.listdir('.'))) # subdirectory contains 1 image and a cache self.assertEqual(get_number_of_files('subdirectory'), 1, "expected one"+\ " files, found only " + repr(os.listdir('subdirectory'))) def test_that_unknown_options_trigger_exception(self): c = convenience.CachedConverter('subdirectory') self.assertRaises(ValueError, c.set_option, 'cxzbiucxzbiuxzb', 'muh') def test_that_invalid_caches_trigger_error_by_default(self): with open('gladtex.cache', 'w') as f: f.write('invalid cache') with self.assertRaises(JsonParserException): c = convenience.CachedConverter('') def test_that_invalid_caches_get_removed_if_specified(self): formulas = [mk_eqn('tau')] with open('gladtex.cache', 'w') as f: f.write('invalid cache') c = convenience.CachedConverter('', keep_old_cache=False) c._convert_concurrently(formulas) # cache got overridden with open('gladtex.cache') as f: self.assertFalse('invalid' in f.read()) def test_that_converted_formulas_are_cached(self): formulas = [mk_eqn('tau')] c = convenience.CachedConverter('') c._convert_concurrently(formulas) formulas.append(mk_eqn('\\gamma')) formulas = turn_into_orig_formulas(formulas) self.assertTrue(len(c._get_formulas_to_convert('', formulas)), 1) def test_that_file_names_are_correctly_picked(self): formulas = turn_into_orig_formulas([mk_eqn('\\tau')]) write('eqn000.png') write('eqn001.png') c = convenience.CachedConverter('') to_convert = c._get_formulas_to_convert('', formulas) self.assertTrue(len(to_convert), 1) self.assertEqual(to_convert[0][2], 'eqn002.png') def test_that_all_converted_formulas_are_in_cache_and_meta_info_correct(self): formulas = [mk_eqn('a_{%d}' % i, pos=(i,i), count=i) for i in range(100)] c = convenience.CachedConverter('') c._convert_concurrently(formulas) # expect all formulas and a gladtex cache to exist self.assertEqual(get_number_of_files('.'), len(formulas)+1) for formula, pos, fn, dsp, count in formulas: data = c.get_data_for(formula, False) self.assertEqual(data['pos'], {'depth': 9, 'height': 8, 'width': 7}, "expected the pos as defined in the dummy class") def test_that_inline_math_and_display_math_results_in_different_formulas(self): # two formulas, second is displaymath formula = r'\sum_{i=0}^n x_i' formulas = [((1,1), False, formula), ((3,1), True, formula)] c = convenience.CachedConverter('.') c.convert_all('.', formulas) # expect all formulas and a gladtex cache to exist self.assertEqual(get_number_of_files('.'), len(formulas)+1) GladTeX-2.3.1/tests/test_document.py000066400000000000000000000166441317106144100174070ustar00rootroot00000000000000#pylint: disable=too-many-public-methods,import-error,too-few-public-methods,missing-docstring,unused-variable import unittest from gleetex.document import LaTeXDocument import gleetex.document as document class test_document(unittest.TestCase): def test_formula_is_embedded(self): formula = 'E = m \\cdot c^2' doc = LaTeXDocument(formula) self.assertTrue(formula in str(doc), "formula must be contained in LaTeX document as it was inserted.") def test_if_displaymath_unset_correct_env_used(self): doc = LaTeXDocument(r'A = \pi r^2') doc.set_displaymath(False) self.assertTrue('\\(' in str(doc)) self.assertTrue('\\)' in str(doc)) def test_if_displaymath_is_set_correct_env_used(self): doc = LaTeXDocument(r'A = \pi r^2') doc.set_displaymath(True) self.assertTrue('\\[' in str(doc)) self.assertTrue('\\]' in str(doc)) def test_preamble_is_included(self): preamble = '\\usepackage{eurosym}' doc = LaTeXDocument('moooo') doc.set_preamble_string(preamble) self.assertTrue(preamble in str(doc)) def test_obviously_wrong_encoding_trigger_exception(self): doc = LaTeXDocument('f00') self.assertRaises(ValueError, doc.set_encoding, 'latin1:') self.assertRaises(ValueError, doc.set_encoding, 'utf66') # the following passes (assertRaisesNot) doc.set_encoding('utf-8') def test_that_latex_maths_env_is_used(self): doc = LaTeXDocument('f00') doc.set_latex_environment('flalign*') self.assertTrue(r'\begin{flalign*}' in str(doc)) self.assertTrue(r'\end{flalign*}' in str(doc)) ################################################################################ class test_replace_unicode_characters(unittest.TestCase): def test_that_ascii_strings_are_returned_verbatim(self): for string in ['abc.\\', '`~[]}{:<>']: textmode = document.replace_unicode_characters(string, False) self.assertEqual(textmode, string, 'expected %s, got %s' % (string, textmode)) mathmode = document.replace_unicode_characters(string, True) self.assertEqual(textmode, string, 'expected %s, got %s' % (string, mathmode)) def test_that_alphabetical_characters_are_replaced_by_default(self): textmode = document.replace_unicode_characters('ö', False) self.assertTrue('\\"' in textmode) mathmode = document.replace_unicode_characters('ö', True) self.assertTrue('\\ddot' in mathmode) def test_that_alphabetical_characters_are_kept_in_text_mode_if_specified(self): self.assertEqual(document.replace_unicode_characters('ö', False, # text mode replace_alphabeticals=False), 'ö') self.assertEqual(document.replace_unicode_characters('æ', False, replace_alphabeticals=False), 'æ') def test_that_alphanumericals_are_replaced_in_mathmode_even_if_replace_alphabeticals_set(self): self.assertNotEqual(document.replace_unicode_characters('öäü', True, replace_alphabeticals=True), 'öäü') self.assertNotEqual(document.replace_unicode_characters('æø', True, replace_alphabeticals=True), 'æø') def test_that_charachters_not_present_in_file_raise_exception(self): with self.assertRaises(ValueError): document.replace_unicode_characters('€', True) def test_that_formulas_are_replaced(self): self.assertNotEqual(document.replace_unicode_characters('π', True), 'π') self.assertNotEqual(document.replace_unicode_characters('π', False), 'π') class test_get_matching_brace(unittest.TestCase): def test_closing_brace_found_when_only_one_brace_present(self): text = 'text{ok}' self.assertEqual(document.get_matching_brace(text, 4), len(text) - 1) self.assertEqual(document.get_matching_brace(text + 'foo', 4), len(text) - 1) def test_outer_brace_found(self): text = 'text{o, bla\\"{o}dfdx.}ds' self.assertEqual(document.get_matching_brace(text, 4), len(text)-3) def test_inner_brace_is_matched(self): text = 'text{o, bla\\"{o}dfdx.}ds' self.assertEqual(document.get_matching_brace(text, 13), 15) def test_that_unmatched_braces_raise_exception(self): with self.assertRaises(ValueError): document.get_matching_brace('text{foooooooo', 4) with self.assertRaises(ValueError): document.get_matching_brace('text{jo\"{o....}', 4) def test_wrong_position_for_opening_brace_raises(self): with self.assertRaises(ValueError): document.get_matching_brace('moo', 1) class test_escape_unicode_in_formulas(unittest.TestCase): """These tests assume that the tests written above work!""" def test_that_mathmode_and_textmode_are_treated_differently(self): math = document.escape_unicode_in_formulas('ö') self.assertNotEqual(math, 'ö') text = document.escape_unicode_in_formulas('\\text{ö}') self.assertFalse('ö' in text) # check whether characters got transcribed differently; it's enough to # check one character of the generated sequence, they should differ self.assertNotEqual(math[:2], text[6:8]) def test_that_flag_to_preserve_alphas_is_passed_through(self): res = document.escape_unicode_in_formulas('\\text{ö}', replace_alphabeticals=False) self.assertEqual(res, '\\text{ö}') def test_that_all_characters_are_preserved_when_no_replacements_happen(self): text = 'This is a \\text{test} mate.' self.assertEqual(document.escape_unicode_in_formulas(text), text) self.assertEqual(document.escape_unicode_in_formulas(text, replace_alphabeticals=False), text) text = 'But yeah but no' * 20 + ', oh my god!' self.assertEqual(document.escape_unicode_in_formulas(text), text) self.assertEqual(document.escape_unicode_in_formulas(text, replace_alphabeticals=False), text) def test_that_everything_around_surrounded_character_is_preserved(self): text = 'This is a \\text{über} test. ;)' result = document.escape_unicode_in_formulas(text, replace_alphabeticals=True) ue_pos = text.index('ü') # text in front is unchanged self.assertEqual(result[:ue_pos], text[:ue_pos]) # find b character, which is the start of the remaining string b_pos = result[ue_pos:].find('b') + ue_pos # check that text after umlaut matches self.assertEqual(result[b_pos:], text[ue_pos+1:]) text = 'But yeah but no' * 20 + ', oh my god!ø' o_strok_pos = text.index('ø') res = document.escape_unicode_in_formulas(text) self.assertEqual(res[:o_strok_pos], text[:o_strok_pos]) def test_that_unknown_unicode_characters_raise_exception(self): # you know that Santa Clause character? Seriously, if you don't know it, # you should have a look. LaTeX does indeed not have command for this # (2016, one never knows) santa = chr(127877) with self.assertRaises(document.DocumentSerializationException): document.escape_unicode_in_formulas(santa) def test_that_two_text_environments_preserve_all_characters(self): text = r'a\cdot b \text{equals} b\cdot c} \mbox{ is not equal } u^{v\cdot k}' self.assertEqual(document.escape_unicode_in_formulas(text), text) GladTeX-2.3.1/tests/test_htmlhandling.py000066400000000000000000000416641317106144100202420ustar00rootroot00000000000000#pylint: disable=too-many-public-methods from functools import reduce import os, re, shutil, tempfile import unittest from gleetex import htmlhandling excl_filename = htmlhandling.HtmlImageFormatter.EXCLUSION_FILE_NAME HTML_SKELETON = ''' {1}''' def read(file_name, mode='r', encoding='utf-8'): """Read the file, return the string. Close file properly.""" with open(file_name, mode, encoding=encoding) as handle: return handle.read() class HtmlparserTest(unittest.TestCase): def setUp(self): self.p = htmlhandling.EqnParser() def test_start_tags_are_parsed_literally(self): self.p.feed("

") self.assertEqual(self.p.get_data()[0], "

", "The HTML parser should copy start tags literally.") def test_that_end_tags_are_copied_literally(self): self.p.feed("

") self.assertEqual(''.join(self.p.get_data()), "

") def test_entities_are_unchanged(self): self.p.feed(" ") self.assertEqual(self.p.get_data()[0], ' ') def test_charsets_are_copied(self): self.p.feed('>→') self.assertEqual(''.join(self.p.get_data()[0]), '>→') def test_without_eqn_all_blocks_are_strings(self): self.p.feed("\n

42

blah

") self.assertTrue(reduce(lambda x,y: x and isinstance(y, str), self.p.get_data()), "all chunks have to be strings") def test_equation_is_detected(self): self.p.feed('foo \\pi') self.assertTrue(isinstance(self.p.get_data()[0], (tuple, list))) self.assertEqual(self.p.get_data()[0][2], 'foo \\pi') def test_tag_followed_by_eqn_is_correctly_recognized(self): self.p.feed('

bar') self.assertEqual(self.p.get_data()[0], '

') self.assertTrue(isinstance(self.p.get_data(), list), "second item of data must be equation data list") def test_document_with_tag_then_eqn_then_tag_works(self): self.p.feed('

bar
baz') eqn = None # test should not depend on a specific position of equation, search for # it data = self.p.get_data() for chunk in data: if isinstance(chunk, (tuple, list)): eqn = chunk break self.assertTrue(isinstance(data[0], str)) self.assertTrue(eqn is not None, "No equation found, must be tuple/list object.") self.assertTrue(isinstance(data[-1], str)) def test_equation_is_copied_literally(self): self.p.feed('my\nlittle\n\\tau') self.assertEqual(self.p.get_data()[0][2], 'my\nlittle\n\\tau') def test_unclosed_eqns_are_detected(self): self.assertRaises(htmlhandling.ParseException, self.p.feed, '

\\endless\\formula') def test_nested_formulas_trigger_exception(self): self.assertRaises(htmlhandling.ParseException, self.p.feed, "\\pi") self.assertRaises(htmlhandling.ParseException, self.p.feed, "\\pi

") def test_formulas_without_displaymath_attribute_are_detected(self): self.p.feed('

\frac12
bar

') formulas = [c for c in self.p.get_data() if isinstance(c, (tuple, list))] self.assertEqual(len(formulas), 2) # there should be _2_ formulas self.assertEqual(formulas[0][1], False) # no displaymath self.assertEqual(formulas[1][1], False) # no displaymath def test_that_unclosed_formulas_detected(self): self.assertRaises(htmlhandling.ParseException, self.p.feed, "\\pi

") self.assertRaises(htmlhandling.ParseException, self.p.feed, "\\pi") def test_formula_contains_only_formula(self): p = htmlhandling.EqnParser() p.feed("

1

") formula = next(e for e in p.get_data() if isinstance(e, (list, tuple))) self.assertEqual(formula[-1], "1test

') formula = next(e for e in p.get_data() if isinstance(e, (list, tuple))) self.assertEqual(formula[-1], "test") p = htmlhandling.EqnParser() p.feed("

1

") formula = next(e for e in p.get_data() if isinstance(e, (list, tuple))) self.assertEqual(formula[-1], "1a>b
') formula = self.p.get_data()[0] self.assertEqual(formula[-1], "a>b") def test_displaymath_is_recognized(self): self.p.feed('\\sum\limits_{n=1}^{e^i} a^nl^n') self.assertEqual(self.p.get_data()[0][1], True) # displaymath flag set def test_encodings_are_parsed_from_file(self): iso8859_1 = HTML_SKELETON.format('iso-8859-15', 'öäüß').encode('iso-8859-1') self.p.feed(iso8859_1) def test_strings_can_be_passed_tO_parser_as_well(self): # no exception - everything is working as expected self.p.feed(HTML_SKELETON.format('utf-8', 'æø')) class GetPositionTest(unittest.TestCase): def test_that_line_number_is_correct(self): self.assertEqual(htmlhandling.get_position('jojo', 0)[0], 0) self.assertEqual(htmlhandling.get_position('jojo', 3)[0], 0) self.assertEqual(htmlhandling.get_position('a\njojo', 3)[0], 1) self.assertEqual(htmlhandling.get_position('a\n\njojo', 3)[0], 2) def test_that_position_on_line_is_correct(self): self.assertEqual(htmlhandling.get_position('jojo', 0)[1], 0) self.assertEqual(htmlhandling.get_position('jojo', 3)[1], 3) self.assertEqual(htmlhandling.get_position('a\njojo', 3)[1], 2) self.assertEqual(htmlhandling.get_position('a\n\njojo', 3)[1], 1) class HtmlImageTest(unittest.TestCase): def setUp(self): self.pos = {'depth':'99', 'height' : '88', 'width' : '77'} self.original_directory = os.getcwd() self.tmpdir = tempfile.mkdtemp() os.chdir(self.tmpdir) def tearDown(self): os.chdir(self.original_directory) shutil.rmtree(self.tmpdir, ignore_errors=True) def test_that_no_file_is_written_if_no_content(self): with htmlhandling.HtmlImageFormatter('foo.html'): pass self.assertFalse(os.path.exists('foo.html') ) def test_file_if_written_when_content_exists(self): with htmlhandling.HtmlImageFormatter() as img: img.format_excluded(self.pos, '\\tau\\tau', 'foo.png') self.assertTrue(os.path.exists(excl_filename) ) def test_written_file_starts_and_ends_more_or_less_properly(self): with htmlhandling.HtmlImageFormatter('.') as img: img.format_excluded(self.pos, '\\tau\\tau', 'foo.png') data = read(htmlhandling.HtmlImageFormatter.EXCLUSION_FILE_NAME, 'r', encoding='utf-8') self.assertTrue('' in data) self.assertTrue('' in data) # make sure encoding is specified self.assertTrue('
%s

\n' % (\ ('
' if hr else ''), htmlhandling.gen_id(formula), formula) class OutsourcingParserTest(unittest.TestCase): def setUp(self): self.html = ('\n\n\n' + '' + 'Outsourced Formulas\n\n

heading

') def get_html(self, string): """Create html string with head / tail und put the specified string into it.""" return self.html + string + '\n\n' def test_formulas_are_recognized(self): data = self.get_html(htmleqn('\\tau')) parser = htmlhandling.OutsourcedFormulaParser() parser.feed(data) self.assertEqual(len(parser.get_formulas()), 1) def test_formula_doesnt_contain_surrounding_rubbish(self): data = self.get_html(htmleqn('\\gamma')) parser = htmlhandling.OutsourcedFormulaParser() parser.feed(data) self.assertEqual(len(parser.get_formulas()), 1) key = next(iter(parser.get_formulas())) par = parser.get_formulas()[key] self.assertFalse('' in par) self.assertFalse('hr' in par) def test_that_header_is_parsed_correctly(self): p = htmlhandling.OutsourcedFormulaParser() p.feed(self.get_html(htmleqn('test123', False))) head = p.get_head() self.assertTrue('DOCTYPE' in head) self.assertTrue(' patch level 3 Babel <3.9r> and hyphenation patterns for 10 language(s) loaded. (/usr/share/texlive/texmf-dist/tex/latex/base/article.cls Document Class: article 2014/09/29 v1.4h Standard LaTeX document class (/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo)) (./bla.aux) ! Undefined control sequence. \foo l.3 $\foo $ No pages of output. Transcript written on bla.log. """ def call_dummy(_lklklklklk, cwd=None): """Dummy to prohibit subprocess execution.""" return str(cwd) #pylint: disable=unused-argument def latex_error_mock(_cmd, cwd=None): """Mock an error case.""" raise SubprocessError(LATEX_ERROR_OUTPUT) #pylint: disable=unused-argument def dvipng_mock(cmd, cwd=None): """Mock an error case.""" fn = None try: fn = next(e for e in cmd if e.endswith('.png')) except StopIteration: try: fn = next(e for e in cmd if e.endswith('.dvi')) except StopIteration: pass if fn: with open(fn, 'w') as f: f.write("test case") return 'This is dvipng 1.14 Copyright 2002-2010 Jan-Ake Larsson\n ' + \ 'depth=3 height=9 width=22' class test_imagecreation(unittest.TestCase): def setUp(self): self.original_directory = os.getcwd() self.tmpdir = tempfile.mkdtemp() os.chdir(self.tmpdir) image.Tex2img.call = call_dummy def tearDown(self): os.chdir(self.original_directory) shutil.rmtree(self.tmpdir, ignore_errors=True) def test_that_incorrect_latex_formula_raises_subprocess_exception(self): i = image.Tex2img(doc("\\foo"), 'foo.png') image.Tex2img.call = latex_error_mock self.assertRaises(SubprocessError, i.create_dvi, 'useless.dvi') def test_that_incorrect_formula_is_displayed(self): i = image.Tex2img(doc("\\foo"), 'foo.png') try: i.create_dvi('foo.dvi') except SubprocessError as e: # expect undefined control sequence in error output self.assertTrue('Undefined' in e.args[0]) def test_that_intermediate_files_are_removed_after_successful_run(self): files = ['foo.log', 'foo.aux', 'foo.tex'] i = image.Tex2img(doc("\\frac\\pi\\tau"), 'foo.png') i.create_dvi('foo.dvi') for intermediate_file in files: self.assertFalse(os.path.exists(intermediate_file), "File " + intermediate_file + " should not exist.") def test_that_intermediate_files_are_removed_when_exception_is_raised(self): files = ['foo.log', 'foo.aux', 'foo.tex'] # error case i = image.Tex2img(doc("\\foo"), 'foo.png') try: i.create_dvi('foo.dvi') except SubprocessError as e: for intermediate_file in files: self.assertFalse(os.path.exists(intermediate_file), "File " + intermediate_file + " should not exist.") def test_that_png_is_created(self): i = image.Tex2img(doc("\\sum\\limits_{i=0}^{\\infty} i^ie^i"), 'foo.png') i.create_dvi('foo.dvi') image.Tex2img.call = dvipng_mock i.create_png('foo.dvi') self.assertTrue(os.path.exists('foo.png')) def create_intermediate_files(self, file_name): files = ['tex', 'log', 'aux', 'dvi'] for ending in files: with open(file_name + '.' + ending, 'w') as f: f.write("blah blah") def test_intermediate_files_are_removed(self): files = ['foo.tex', 'foo.log', 'foo.aux', 'foo.dvi'] i = image.Tex2img(doc('\\hat{x}'), 'foo.png') self.create_intermediate_files('foo') i.create_dvi('foo.dvi') image.Tex2img.call = dvipng_mock i.create_png('foo.dvi') for intermediate_file in files: self.assertFalse(os.path.exists(intermediate_file)) def test_intermediate_files_are_removed_when_exception_raised(self): files = ['foo.tex', 'foo.log', 'foo.aux', 'foo.dvi'] i = image.Tex2img(doc('\\hat{x}'), 'foo.png') self.create_intermediate_files('foo') # pretend that LaTeX was run # let call() raise an arbitrari SubprocessError image.Tex2img.call = latex_error_mock try: i.create_dvi('foo.dvi') except SubprocessError: self.assertFalse(os.path.exists('foo.tex')) self.assertFalse(os.path.exists('foo.dvi')) self.assertFalse(os.path.exists('foo.log')) self.assertFalse(os.path.exists('foo.aux')) try: i.create_png('foo.dvi') except SubprocessError: self.assertFalse(os.path.exists('foo.dvi')) def test_that_values_for_positioning_png_are_returned(self): i = image.Tex2img(doc("\\sum\\limits_{i=0}^{\\infty} i^ie^i"), 'foo.png') i.create_dvi('foo.dvi') # set dvi output call image.Tex2img.call = lambda x, y=9: \ 'This is dvipng 1.14 Copyright 2002-2010 Jan-Ake Larsson\n depth=3 height=9 width=22' posdata = i.create_png('foo.dvi') self.assertTrue('height' in posdata) self.assertTrue('width' in posdata) def test_that_output_file_names_with_paths_are_ok_and_log_is_removed(self): t = image.Tex2img(doc(r"\hat{es}\pi\pi\ldots"), "bilder/farce.png") image.Tex2img.call = dvipng_mock t.convert() self.assertFalse(os.path.exists("farce.log")) self.assertTrue(os.path.exists("bilder/farce.png")) class TestImageResolutionCorrectlyCalculated(unittest.TestCase): def test_sizes_are_correctly_calculated(self): self.assertEqual(int(image.fontsize2dpi(12)), 115) self.assertEqual(int(image.fontsize2dpi(10)), 96) GladTeX-2.3.1/update_unicode_table.py000066400000000000000000000133321317106144100175160ustar00rootroot00000000000000"""This script auto-generates gleetex/unicode_data.py. The purpose is to provide a table with mappings from unicode points to their LaTeX equivalent. This way, formulas can be converted using LaTeX2e, but the end-user can still use unicode in it's formulas. The unicode version can also be used to make the alternative text more readable.""" import collections import enum import os import urllib.request import xml.etree.ElementTree as ET # URL to XML file, which is used to generate the python source file UNICODE_TABLE_URL = "https://raw.githubusercontent.com/w3c/xml-entities/gh-pages/unicode.xml" # a list of commands to replace, if found BAD_COMMANDS = {'\\minus': '-'} class LaTeXMode(enum.Enum): """Represent either math or text mode. Math mode in LaTeX is e.g. everything between $ and $.""" textmode = 0 mathmode = 1 def get_unicode_table_xml(): with urllib.request.urlopen(UNICODE_TABLE_URL) as u: return ET.fromstring(u.read()) def create_unicode_latex_table(root): """This function iterates over the XML tree and extracts all characters for the unicode table. The resulting table will have the decimal unicode point as key. The value is again a dict with the possible keys from LaTeX and the LaTeX commands as string. Certain unicode points are ignored, to prevent replacing normal or control characters.""" unicode_table = {} for character in root.find('charlist').iterfind('character'): childtags = set(node.tag for node in character.getchildren()) # skip characters without LaTeX alternative if 'latex' not in childtags and 'AMS' not in childtags and \ 'mathlatex' not in childtags: continue # skip this character attr = character.attrib # if no mode (text or math) was specified, ignore character if attr.get('mode') not in ('text', 'math', 'mixed', 'other'): continue # a defined character may have multiple codepoints (called ids); add # each of the ids as a separate entry to the table ids = tuple(map(int, attr['dec'].split('-'))) if any(elem for elem in ids if elem < 161): continue # ignore characters from ascii and a few unicode control characters # extract textmode, mathmode and AMS commands: commands = {} if 'latex' in childtags: commands[LaTeXMode.textmode] =\ next(character.iterfind('latex')).text if 'AMS' in childtags: commands[LaTeXMode.mathmode] = next(character.iterfind('AMS')).text # only take LaTeX command from , if no AMS tag present and # no set was specified. A `set` is a attempt to specify the LaTeX # package which needs to be loaded. if 'mathlatex' in childtags and LaTeXMode.mathmode not in commands: mathnode = next(character.iterfind('mathlatex')) if 'set' not in mathnode.attrib: commands[LaTeXMode.mathmode] = mathnode.text if commands: # if a usable textmode and a mathmode without unicode-math found: # replace bad commands for mode in commands: if commands[mode] in BAD_COMMANDS: commands[mode] = BAD_COMMANDS[commands[mode]] for item in ids: unicode_table[item] = commands return unicode_table def serialize_table(table): """Serialize the given unicode table to a python table, which could be directly executed by eval. The decimal code points, serving as a key in the dictionary, are sorted for the output.""" ordered_table = collections.OrderedDict() for key in sorted(table.keys()): ordered_table[key] = table[key] python_string = ['unicode_table = {'] reprmode = lambda m, v: 'LaTeXMode.%s: %s' % (m.name, repr(v[m])) for code_point, replacements in ordered_table.items(): # serialize by hand to have a fixed order of items; helpful for a # minimal git diff commands = '' if LaTeXMode.textmode in replacements: commands = reprmode(LaTeXMode.textmode, replacements) if LaTeXMode.mathmode in replacements: if commands: commands += ', ' commands += reprmode(LaTeXMode.mathmode, replacements) python_string.append('%s: {%s},' % (code_point, commands)) return '\n '.join(python_string) + '\n }\n' def generate_python_src_file(table, python_table): """Generate a fully importable python source file, by dumping the enum declarations, python imports, doc strings and the given python string with the unicode table into the source and returning it as a whole string.""" enum_def = 'class LaTeXMode(enum.Enum):\n """%s"""\n ' % LaTeXMode.__doc__ enum_values = tuple(e for e in dir(LaTeXMode) if not e.startswith('_')) enum_def += '\n '.join('%s = %s' % (name, getattr(LaTeXMode, name).value) for name in enum_values) return """\"\"\" DO NOT ALTER THIS FILE IN ANY WAY, IT IS GENERATED AUTOMATICALLY. SEE THE SCRIPT `update_unicode_table.py` FOR MORE INFORMATION. This file contains a table of unicode code point to LaTeX command mapping. It has %s entries and was derived from <%s>.\"\"\" #pylint: disable=too-many-lines,missing-docstring\n\n import enum\n %s\n\n%s\n""" % (len(table), UNICODE_TABLE_URL, enum_def, python_table) def main(): if not os.path.exists('gleetex'): print("Error: Generator script must be run from GladTeX source root.") table = create_unicode_latex_table(get_unicode_table_xml()) python_table = serialize_table(table) with open('gleetex/unicode.py', 'w', encoding='utf-8') as f: f.write(generate_python_src_file(table, python_table)) if __name__ == '__main__': main()