git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@15590 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
@ -25,6 +25,7 @@ import re
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
|
||||
class Markup(object):
|
||||
BOLD_START = "["
|
||||
BOLD_END = "]"
|
||||
@ -77,6 +78,7 @@ class Markup(object):
|
||||
text = text.replace('\"%s\"_%s' % (name, link), href, 1)
|
||||
return text
|
||||
|
||||
|
||||
class HTMLMarkup(Markup):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@ -101,6 +103,7 @@ class HTMLMarkup(Markup):
|
||||
|
||||
return "<A HREF = \"" + href + "\">" + content + "</A>"
|
||||
|
||||
|
||||
class Formatting(object):
|
||||
UNORDERED_LIST_MODE = "unordered-list"
|
||||
ORDERED_LIST_MODE = "ordered-list"
|
||||
@ -435,6 +438,7 @@ class Formatting(object):
|
||||
|
||||
return rows
|
||||
|
||||
|
||||
class HTMLFormatting(Formatting):
|
||||
def __init__(self, markup):
|
||||
super().__init__(markup)
|
||||
@ -448,6 +452,7 @@ class HTMLFormatting(Formatting):
|
||||
def raw_html(self, content):
|
||||
return content
|
||||
|
||||
|
||||
class TxtParser(object):
|
||||
def __init__(self):
|
||||
self.markup = HTMLMarkup()
|
||||
@ -630,6 +635,7 @@ class TxtParser(object):
|
||||
|
||||
i += 1
|
||||
|
||||
|
||||
class Txt2Html(TxtParser):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@ -641,6 +647,7 @@ class Txt2Html(TxtParser):
|
||||
line.startswith(".. END_HTML_ONLY") or \
|
||||
super().is_paragraph_separator(line)
|
||||
|
||||
|
||||
class TxtConverter:
|
||||
def get_argument_parser(self):
|
||||
return None
|
||||
@ -665,7 +672,15 @@ class TxtConverter:
|
||||
print("Converting", filename, "...", file=err)
|
||||
content = f.read()
|
||||
converter = self.create_converter(parsed_args)
|
||||
result = converter.convert(content)
|
||||
|
||||
try:
|
||||
result = converter.convert(content)
|
||||
except Exception as e:
|
||||
msg = "###########################################################################\n" \
|
||||
" ERROR: " + e.args[0] + "\n" \
|
||||
"###########################################################################\n"
|
||||
print(msg, file=err)
|
||||
result = msg
|
||||
|
||||
if write_to_files:
|
||||
output_filename = self.get_output_filename(filename)
|
||||
@ -674,6 +689,7 @@ class TxtConverter:
|
||||
else:
|
||||
print(result, end='', file=out)
|
||||
|
||||
|
||||
class Txt2HtmlConverter(TxtConverter):
|
||||
def get_argument_parser(self):
|
||||
parser = argparse.ArgumentParser(description='converts a text file with simple formatting & markup into HTML.\n'
|
||||
|
||||
@ -24,6 +24,7 @@ import argparse
|
||||
from lammpsdoc import lammps_filters
|
||||
from lammpsdoc.txt2html import Markup, Formatting, TxtParser, TxtConverter
|
||||
|
||||
|
||||
class RSTMarkup(Markup):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@ -65,6 +66,7 @@ class RSTMarkup(Markup):
|
||||
def escape_rst_chars(self, text):
|
||||
text = text.replace('*', '\\*')
|
||||
text = text.replace('^', '\\^')
|
||||
text = text.replace('|', '\\|')
|
||||
text = re.sub(r'([^"])_', r'\1\\_', text)
|
||||
return text
|
||||
|
||||
@ -72,6 +74,7 @@ class RSTMarkup(Markup):
|
||||
text = text.replace('\\*', '*')
|
||||
text = text.replace('\\^', '^')
|
||||
text = text.replace('\\_', '_')
|
||||
text = text.replace('\\|', '|')
|
||||
return text
|
||||
|
||||
def inline_math(self, text):
|
||||
@ -112,13 +115,18 @@ class RSTMarkup(Markup):
|
||||
|
||||
return "`%s <%s>`_" % (content, href)
|
||||
|
||||
|
||||
class RSTFormatting(Formatting):
|
||||
RST_HEADER_TYPES = '#*=-^"'
|
||||
|
||||
def __init__(self, markup):
|
||||
super().__init__(markup)
|
||||
self.indent_level = 0
|
||||
|
||||
def paragraph(self, content):
|
||||
if self.indent_level > 0:
|
||||
return '\n' + self.list_indent(content.strip(), self.indent_level)
|
||||
|
||||
return content.strip() + "\n"
|
||||
|
||||
def center(self, content):
|
||||
@ -128,7 +136,9 @@ class RSTFormatting(Formatting):
|
||||
return content.strip()
|
||||
|
||||
def preformat(self, content):
|
||||
return ".. parsed-literal::\n\n" + self.indent(content.rstrip())
|
||||
if self.indent_level > 0:
|
||||
return self.list_indent("\n.. parsed-literal::\n\n" + self.indent(content.rstrip()), self.indent_level)
|
||||
return "\n.. parsed-literal::\n\n" + self.indent(content.rstrip())
|
||||
|
||||
def horizontal_rule(self, content):
|
||||
return "\n----------\n\n" + content.strip()
|
||||
@ -159,7 +169,7 @@ class RSTFormatting(Formatting):
|
||||
|
||||
def header(self, content, level):
|
||||
header_content = content.strip()
|
||||
header_content = re.sub(r'[0-9]+\.[0-9]*\s+', '', header_content)
|
||||
header_content = re.sub(r'[0-9]+\.([0-9]*\.?)*\s+', '', header_content)
|
||||
header_underline = RSTFormatting.RST_HEADER_TYPES[level-1] * len(header_content)
|
||||
return header_content + "\n" + header_underline + "\n"
|
||||
|
||||
@ -178,14 +188,17 @@ class RSTFormatting(Formatting):
|
||||
return self.indent(paragraph.strip())
|
||||
|
||||
def unordered_list_begin(self, paragraph):
|
||||
self.indent_level += 1
|
||||
return paragraph
|
||||
|
||||
def unordered_list_end(self, paragraph):
|
||||
self.indent_level -= 1
|
||||
return paragraph.rstrip() + '\n'
|
||||
|
||||
def ordered_list_begin(self, paragraph):
|
||||
if paragraph.startswith('* '):
|
||||
paragraph = '#. ' + paragraph[2:]
|
||||
self.indent_level += 1
|
||||
return paragraph
|
||||
|
||||
def definition_list_begin(self, paragraph):
|
||||
@ -195,6 +208,7 @@ class RSTFormatting(Formatting):
|
||||
return paragraph
|
||||
|
||||
def ordered_list_end(self, paragraph):
|
||||
self.indent_level -= 1
|
||||
return paragraph.rstrip() + '\n'
|
||||
|
||||
def ordered_list(self, paragraph):
|
||||
@ -228,6 +242,12 @@ class RSTFormatting(Formatting):
|
||||
indented += " %s\n" % line
|
||||
return indented
|
||||
|
||||
def list_indent(self, content, level=1):
|
||||
indented = ""
|
||||
for line in content.splitlines():
|
||||
indented += " " * level + ("%s\n" % line)
|
||||
return indented
|
||||
|
||||
def get_max_column_widths(self, rows):
|
||||
num_columns = max([len(row) for row in rows])
|
||||
max_widths = [0] * num_columns
|
||||
@ -321,6 +341,7 @@ class RSTFormatting(Formatting):
|
||||
|
||||
return text + post
|
||||
|
||||
|
||||
class Txt2Rst(TxtParser):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@ -354,6 +375,11 @@ class Txt2Rst(TxtParser):
|
||||
return commands
|
||||
return super().order_commands(commands)
|
||||
|
||||
def transform_paragraphs(self, content):
|
||||
if self.format.indent_level > 0:
|
||||
raise Exception("unbalanced number of ulb,ule or olb,ole pairs!")
|
||||
return super().transform_paragraphs(content)
|
||||
|
||||
|
||||
class Txt2RstConverter(TxtConverter):
|
||||
def get_argument_parser(self):
|
||||
@ -370,6 +396,7 @@ class Txt2RstConverter(TxtConverter):
|
||||
filename, ext = os.path.splitext(path)
|
||||
return filename + ".rst"
|
||||
|
||||
|
||||
def main():
|
||||
app = Txt2RstConverter()
|
||||
app.run()
|
||||
|
||||
@ -81,6 +81,10 @@ class TestMarkup(unittest.TestCase):
|
||||
s = self.markup.convert("[*bold] and {italic*}")
|
||||
self.assertEqual("**\*bold** and *italic\**", s)
|
||||
|
||||
def test_escape_rst_characters(self):
|
||||
s = self.markup.convert("[|bold|] and {|italic|}")
|
||||
self.assertEqual("**\|bold\|** and *\|italic\|*", s)
|
||||
|
||||
def test_escape_hat_character(self):
|
||||
s = self.markup.convert("x^2")
|
||||
self.assertEqual("x\^2", s)
|
||||
@ -155,13 +159,13 @@ class TestFormatting(unittest.TestCase):
|
||||
|
||||
def test_preformat_formatting(self):
|
||||
s = self.txt2rst.convert("Hello :pre\n")
|
||||
self.assertEqual(".. parsed-literal::\n\n"
|
||||
self.assertEqual("\n.. parsed-literal::\n\n"
|
||||
" Hello\n\n", s)
|
||||
|
||||
def test_preformat_formatting_with_indentation(self):
|
||||
s = self.txt2rst.convert(" Hello\n"
|
||||
" World :pre\n")
|
||||
self.assertEqual(".. parsed-literal::\n\n"
|
||||
self.assertEqual("\n.. parsed-literal::\n\n"
|
||||
" Hello\n"
|
||||
" World\n\n", s)
|
||||
|
||||
@ -196,6 +200,16 @@ class TestFormatting(unittest.TestCase):
|
||||
self.assertEqual("Level\n"
|
||||
"#####\n\n", s)
|
||||
|
||||
def test_filter_header_numbers_deep(self):
|
||||
s = self.txt2rst.convert("1.1.1.1.1 Level :h1\n")
|
||||
self.assertEqual("Level\n"
|
||||
"#####\n\n", s)
|
||||
|
||||
def test_no_filter_date(self):
|
||||
s = self.txt2rst.convert("9 Sept 2016 version :h1\n")
|
||||
self.assertEqual("9 Sept 2016 version\n"
|
||||
"###################\n\n", s)
|
||||
|
||||
def test_all_breaks(self):
|
||||
s = self.txt2rst.convert("one\n"
|
||||
"two\n"
|
||||
@ -308,8 +322,6 @@ class TestListFormatting(unittest.TestCase):
|
||||
"* third\n"
|
||||
" paragraph\n\n", s)
|
||||
|
||||
|
||||
|
||||
def test_definition_list(self):
|
||||
s = self.txt2rst.convert("A\n"
|
||||
"first\n"
|
||||
@ -322,6 +334,39 @@ class TestListFormatting(unittest.TestCase):
|
||||
" second\n"
|
||||
"\n\n", s)
|
||||
|
||||
def test_multi_paragraph_lists(self):
|
||||
s = self.txt2rst.convert("first\n"
|
||||
"paragraph of first bullet :ulb,l\n\n"
|
||||
"second paragraph of first bullet\n\n"
|
||||
"first paragraph of second bullet :l\n\n"
|
||||
":ule\n")
|
||||
self.assertEqual("* first\n"
|
||||
" paragraph of first bullet\n"
|
||||
"\n"
|
||||
" second paragraph of first bullet\n"
|
||||
"\n"
|
||||
"* first paragraph of second bullet\n\n\n", s)
|
||||
|
||||
def test_multi_paragraph_lists_with_listing(self):
|
||||
s = self.txt2rst.convert("first\n"
|
||||
"paragraph of first bullet :ulb,l\n\n"
|
||||
"code1 :pre\n"
|
||||
"or\n"
|
||||
"\n"
|
||||
"first paragraph of second bullet :l\n\n"
|
||||
":ule\n")
|
||||
self.assertEqual("* first\n"
|
||||
" paragraph of first bullet\n"
|
||||
" \n"
|
||||
" .. parsed-literal::\n"
|
||||
" \n"
|
||||
" code1\n"
|
||||
"\n\n"
|
||||
" or\n"
|
||||
"\n"
|
||||
"* first paragraph of second bullet\n\n\n", s)
|
||||
|
||||
|
||||
class TestSpecialCommands(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.txt2rst = txt2rst.Txt2Rst()
|
||||
|
||||
Reference in New Issue
Block a user