def testDef2(self): s = TeX() s.input(r"\def\row#1{(#1_1,\ldots,#1_n)}\row{{x'}}") output = [x for x in s] text = [x for x in output if x.nodeType == Node.TEXT_NODE] assert text == list('(x\'_1,,x\'_n)'), text assert output[0].nodeName == 'def' assert output[6] == '_' assert output[9].nodeName == 'ldots'
def testComment(self): tokens = [x for x in TeX().input('line % comment').itertokens()] expected = [ Letter('l'), Letter('i'), Letter('n'), Letter('e'), Space(' ') ] self.assertEqual(tokens, expected)
def testListTypes(self): s = TeX() s.input(r'''\newcount\mycount\mycount=120 \newdimen\mydimen\mydimen=12sp \newskip\myglue\myglue=10sp plus1pt minus2pt''') s.parse() s.input(r'{1, \mycount, 3}') arg = s.readArgument(type='list', subtype='int') assert arg == [1, 120, 3], arg
def testDictArgument2(self): s = TeX() s.input(r'{one=1, two={\par}, three={$(x,y)$}, four=4}') arg = s.readArgument(type='dict') keys = list(arg.keys()) keys.sort() expectkeys = ['four', 'one', 'three', 'two'] assert keys == expectkeys, '"%s" != "%s"' % (keys, expectkeys) assert arg['one'] == '1' assert arg['four'] == '4'
def test_modify_charsub(): config = base_config.copy() config["document"]["disable-charsub"] = "'" doc = TeXDocument(config=config) tex = TeX(doc) p = tex.input(r'''{``'' '---}''').parse()[0] p.paragraphs() assert p.textContent == "“” '—"
def testNewCommandWithOptional(self): s = TeX() s.input(r'\newcommand{\mycommand}[2][opt]{#1:#2}\mycommand{bar}\mycommand[foo]{bar}') for key, value in self.macros.items(): s.ownerDocument.context[key] = value output = [x for x in s] assert s.ownerDocument.context['mycommand'].definition == list('#1:#2') assert s.ownerDocument.context['mycommand'].opt == list('opt'), '"%s" != "opt"' % (s.ownerDocument.context['mycommand'].opt) text = [x for x in output if x.nodeType == Node.TEXT_NODE] assert text == list('opt:barfoo:bar'), text
def testExercises(self): """ Exercises in the TeX book """ # 8.4 tokens = [x for x in TeX().input(r' $x^2$~ \TeX ^^C').itertokens()] expected = [ MathShift('$'), Letter('x'), Superscript('^'), Other('2'), MathShift('$'), EscapeSequence('active::~'), Space(' '), EscapeSequence('TeX'), Other('\x03') ] self.assertEqual(tokens, expected) # 8.5 tokens = [x for x in TeX().input('Hi!\n\n\n').itertokens()] expected = [ Letter('H'), Letter('i'), Other('!'), Space(' '), EscapeSequence('par') ] self.assertEqual(tokens, expected) # 8.6 tokens = [ x for x in TeX().input(r'^^B^^BM^^A^^B^^C^^M^^@\M ').itertokens() ] expected = [ Other('\x02'), Other('\x02'), Letter('M'), Other('\x01'), Other('\x02'), Other('\x03'), Space(' '), EscapeSequence('M') ] self.assertEqual(tokens, expected)
def testLabel(self): s = TeX() s.input(r'\section{hi\label{one}} text \section{bye\label{two}}') output = s.parse() one = output[0] two = output[-1] __traceback_info__ = one.__dict__ assert_that(one, has_property('id', 'one')) __traceback_info__ = two.__dict__ assert_that(two, has_property('id', 'two'))
def parseLaTeX(string): # PlasTeX bug - this variable doent get reinitialised MathShift.inEnv = [] # Instantiate a TeX processor and parse the input text tex = TeX() tex.disableLogging() # Parse the LaTeX tex.input(string) return tex.parse()
def testSection(self): tex_input = r'\section{Heading 1} foo one \subsection{Heading 2} bar two' s = TeX() s.input(tex_input) output = s.parse() source = normalize(output.source) assert_that(source, is_(tex_input)) tex_input = r'\subsection{Heading 2} bar two' item = output[0].lastChild source = normalize(item.source)
def test_intro_snippet(tmpdir): (Path(tmpdir) / 'test.tex').write_text(r""" \documentclass{article} \begin{document} Hello. \end{document} """) with tmpdir.as_cwd(): Renderer().render(TeX(myfile='test.tex').parse()) assert (Path(tmpdir) / 'index.html').exists() assert 'Hello' in (Path(tmpdir) / 'index.html').read_text()
def test_textrm(): tex = TeX() tex.input(r''' \documentclass{article} \begin{document} $\textrm{plastex}$ \end{document} ''') nodes = tex.parse().getElementsByTagName('math') assert len(nodes) == 1 assert nodes[0].textContent == 'plastex'
def test_builtin_packages(): doc = TeXDocument() tex = TeX(doc) tex.input(r""" \documentclass{article} \usepackage{float} \begin{document} \floatstyle{ruled} \end{document} """) tex.parse() assert doc.getElementsByTagName('floatstyle')
def testSimpleNewEnvironmentWithArgs(self): s = TeX() s.input(r'\newenvironment{myenv}[2]{#1:#2}{}\begin{myenv}{foo}{bar}hi\end{myenv}') for key, value in self.macros.items(): s.ownerDocument.context[key] = value output = [x for x in s] definition = s.ownerDocument.context['myenv'].definition enddefinition = s.ownerDocument.context['endmyenv'].definition assert definition == list('#1:#2'), definition assert enddefinition == [], enddefinition text = [x for x in output if x.nodeType == Node.TEXT_NODE] assert text == list('foo:barhi'), text
def test_at_letter_verb(monkeypatch): mock_logger = Mock() monkeypatch.setattr('plasTeX.Context.log.warning', mock_logger) tex = TeX() tex.input(r''' \documentclass{article} \begin{document} \verb@test@ \end{document} ''') output = tex.parse() assert mock_logger.call_count == 0
def testDictTypes(self): s = TeX() s.input(r'''\newcount\mycount\mycount=120 \newdimen\mydimen\mydimen=12sp \newskip\myglue\myglue=10sp plus1pt minus2pt''') s.parse() s.input(r'{one=1, two={\mycount} , three={3}}') arg = s.readArgument(type='dict', expanded=True) keys = list(arg.keys()) keys.sort() assert keys == ['one', 'three', 'two']
def test_single_paragraph_theorem(): """Check single paragraph theorem does contain a paragraph""" tex = TeX() tex.input(r''' \newtheorem{thm}{Theorem} \begin{thm} a b c \end{thm} ''') nodes = tex.parse().getElementsByTagName('thm')[0].childNodes assert len(nodes) == 1 assert isinstance(nodes[0], par)
def testSection(self): input = r'\section{Heading 1} foo one \subsection{Heading 2} bar two' s = TeX() s.input(input) output = s.parse() source = normalize(output.source) assert input == source, '"%s" != "%s"' % (input, source) input = r'\subsection{Heading 2} bar two' item = output[0].lastChild source = normalize(item.source) assert input == source, '"%s" != "%s"' % (input, source)
def testParagraph(self): tokens = [x for x in TeX().input('1\n 2\n \n 3\n').itertokens()] expected = [ Other('1'), Space(' '), Other('2'), Space(' '), EscapeSequence('par'), Other('3'), Space(' ') ] self.assertEqual(tokens, expected)
def test_index_entries_are_there(): tex = TeX() tex.input(r''' \documentclass{article} \begin{document} \index{test} \index{test2} \printindex \end{document} ''') output = tex.parse() assert len(output.userdata['index']) == 2
def testList(self): input = r'\begin{enumerate} \item one \item two \item three \end{enumerate}' s = TeX() s.input(input) output = s.parse() source = normalize(output.source) assert input == source, '"%s" != "%s"' % (input, source) input = r'\item one' item = output[0].firstChild source = normalize(item.source) assert input == source, '"%s" != "%s"' % (input, source)
def test_index_grouping(): tex = TeX() tex.input(r''' \documentclass{article} \makeindex \begin{document} \index{Abc!a}\index{Bbcd}\index{Abc!b}\index{Cdd} \printindex \end{document} ''') output = tex.parse() assert len(output.userdata['links']['index']) == 3
def testList(self): tex_input = r'\begin{enumerate} \item one \item two \item three \end{enumerate}' s = TeX() s.input(tex_input) output = s.parse() source = normalize(output.source) assert_that(source, is_(tex_input)) tex_input = r'\item one' item = output[0].firstChild source = normalize(item.source) assert_that(source, is_(tex_input))
def testTokens(self): tokens = [x for x in TeX().input(r'{\hskip 36 pt}').itertokens()] expected = [ BeginGroup('{'), EscapeSequence('hskip'), Other('3'), Other('6'), Space(' '), Letter('p'), Letter('t'), EndGroup('}') ] self.assertEqual(tokens, expected)
def testSimpleNewEnvironmentWithOptional(self): s = TeX() s.input(r'\newenvironment{myenv}[2][opt]{#1:#2}{;}\begin{myenv}{foo}hi\end{myenv}\begin{myenv}[one]{blah}bye\end{myenv}') for key, value in self.macros.items(): s.ownerDocument.context[key] = value output = [x for x in s] definition = s.ownerDocument.context['myenv'].definition enddefinition = s.ownerDocument.context['endmyenv'].definition assert definition == list('#1:#2'), definition assert enddefinition == list(';'), enddefinition assert s.ownerDocument.context['myenv'].opt == list('opt') text = [x for x in output if x.nodeType == Node.TEXT_NODE] assert text == list('opt:foohi;one:blahbye;'), text
def test_book_toc(): t = TeX() t.input(r''' \documentclass{book} \begin{document} \chapter{A} \part{B} \chapter{C} \end{document} ''') p = t.parse() print(p.getElementsByTagName("chapter")) assert ['1', '2'] == [x.ref.source for x in p.getElementsByTagName("chapter")]
def __init__(self, fn, imdir="static/images", imurl="", fp=None, extra_filters=None, latex_string=None, add_wrap=False, fix_plastex_optarg_bug=True, verbose=False): ''' fn = tex filename (should end in .tex) imdir = directory where images are to be stored imurl = web root for images fp = file object (optional) - used instead of open(fn), if provided extra_filters = dict with key=regular exp, value=function for search-replace, for post-processing of XHTML output latex_string = latex string (overrides fp and fn) add_wrap = if True, then assume latex is partial, and add preamble and postfix fix_plastex_optarg_bug = if True, then filter the input latex to fix the plastex bug triggered e.g. by \begin{edXchapter} and \begin{edXsection} being placed with no empty newline inbetween verbose = if True, then do verbose logging ''' if fn.endswith('.tex'): ofn = fn[:-4] + '.xhtml' else: ofn = fn + ".xhtml" self.input_fn = fn self.output_fn = ofn self.fp = fp self.latex_string = latex_string self.add_wrap = add_wrap self.verbose = verbose self.renderer = MyRenderer(imdir, imurl, extra_filters) self.fix_plastex_optarg_bug = fix_plastex_optarg_bug # Instantiate a TeX processor and parse the input text tex = TeX() tex.ownerDocument.config['files']['split-level'] = -100 tex.ownerDocument.config['files']['filename'] = self.output_fn tex.ownerDocument.config['general']['theme'] = 'plain' plasTeXconfig.add_section('logging') plasTeXconfig['logging'][''] = CRITICAL self.tex = tex if not self.verbose: tex.disableLogging()
def runPlastex(self, item): logger.debug("PlasTeX: " + str(item.source)) root_dir = self.get_root_dir() outPath = item.temp_path() outPaux = self.temp_path().resolve() inPath = root_dir / item.source wd = os.getcwd() plastex_config['files']['filename'] = item.out_file rname = plastex_config['general']['renderer'] = 'makecourse' plastex_config['document']['base-url'] = self.get_web_root() document = TeXDocument(config=plastex_config) document.userdata['working-dir'] = '.' tikzPath = self.config.get('tikz_template') if tikzPath: logger.debug('Using tikz template: ' + tikzPath) document.userdata['tikz-template'] = tikzPath document.context.importMacros(vars(macros)) document.context.importMacros(vars(overrides)) f = open(str(Path(wd) / inPath)) tex = TeX(document, myfile=f) document.userdata['jobname'] = tex.jobname pauxname = os.path.join( document.userdata.get('working-dir', '.'), '%s.paux' % document.userdata.get('jobname', '')) for fname in glob.glob(str(outPaux / '*.paux')): if os.path.basename(fname) == pauxname: continue document.context.restore(fname, 'makecourse') sys.excepthook = PlastexRunner.exception_handler tex.parse() f.close() os.chdir(str(outPath)) renderer = Renderer() renderer.loadTemplates(document) renderer.importDirectory(str(Path(wd) / self.theme.source / 'plastex')) renderer.render(document) os.chdir(wd) original_paux_path = item.temp_path() / item.base_file.with_suffix( '.paux') collated_paux_path = self.temp_path() / ( str(item.out_path).replace('/', '-') + '.paux') shutil.copyfile(str(original_paux_path), str(collated_paux_path))
def testLocalCatCodes2(self): class code(Macro): args = 'self' s = TeX() s.input(r"{\catcode`\#=11\catcode`\$=11\catcode`\&=11\catcode`\_=11{this # is $ some & nasty _ text}}&_2") s.ownerDocument.context['code'] = code tokens = [x for x in s] text = tokens[6:-5] assert not [x for x in text if x.catcode not in [10,11]], [x.catcode for x in text] tok = type(tokens[-3]) tab = type(s.ownerDocument.createElement('active::&')) assert tok is tab, '"%s" != "%s"' % (tok, tab)
def runDocument(self, content): """ Compile a document with the given content Arguments: content - string containing the content of the document Returns: TeX document """ tex = TeX() tex.disableLogging() tex.input(ur'''\document{article}\begin{document}%s\end{document}''' % content) return tex.parse()