-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add simplified Moire, font; fix GitHub Actions
We add simplified version of Moire parser instead of installing it from the index, since it is small enough and has no dependencies. We also embed Doulos SIL, Noto Sans Korean and CMU Serif Roman fonts for XeLaTeX build. This should fix GitHub actions.
- Loading branch information
Showing
10 changed files
with
749 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import sys | ||
from argparse import ArgumentParser, Namespace | ||
from typing import Any, Dict, List, Set, Tuple | ||
from textwrap import dedent | ||
|
||
from moire.moire import Moire | ||
|
||
__author__ = "Sergey Vartanov" | ||
__email__ = "[email protected]" | ||
|
||
depth = 0 | ||
status = {} | ||
BLOCK_TAGS: Set[str] = { | ||
"block", "body", "code", "title", "number", "list", "image", "table" | ||
} # fmt: skip | ||
Arguments = List[Any] | ||
|
||
|
||
class TagNotImplementedError(NotImplementedError): | ||
"""Tag is not implemented in the parser.""" | ||
|
||
def __init__(self, tag: str = "") -> None: | ||
self.tag: str = tag | ||
|
||
def __str__(self) -> str: | ||
return f"Tag \\{self.tag} is not implemented in the parser" | ||
|
||
|
||
class Default(Moire): | ||
"""Default tag declaration.""" | ||
|
||
def __init__(self) -> None: | ||
super().__init__() | ||
|
||
def title(self, arg: Arguments) -> str: | ||
"""Document title.""" | ||
return "" | ||
|
||
def header(self, arg: Arguments, level: int) -> str: | ||
"""Header. | ||
Arguments: <header text> <header identifier>? | ||
""" | ||
raise TagNotImplementedError("header") | ||
|
||
def m(self, arg: Arguments) -> str: | ||
"""Monospaced text.""" | ||
raise TagNotImplementedError("m") | ||
|
||
|
||
class DefaultTeX(Default): | ||
"""TeX syntax.""" | ||
|
||
name = "Tex" | ||
id_: str = "tex" | ||
extension = "tex" | ||
|
||
escape_symbols = { | ||
"_": "\\_", | ||
} | ||
block_tags = BLOCK_TAGS | ||
headers: List[str] = [ | ||
"section", "subsection", "subsubsection", "paragraph", "subparagraph" | ||
] # fmt: skip | ||
|
||
def body(self, arg: Arguments) -> str: | ||
s = dedent( | ||
"""\ | ||
\\documentclass[twoside,psfig]{article} | ||
\\usepackage[utf8]{inputenc} | ||
\\usepackage[russian]{babel} | ||
\\usepackage{enumitem} | ||
\\usepackage{float} | ||
\\usepackage[margin=3cm,hmarginratio=1:1,top=32mm,columnsep=20pt] | ||
{geometry} | ||
\\usepackage{graphicx} | ||
\\usepackage{hyperref} | ||
\\usepackage{multicol} | ||
\\begin{document} | ||
""" | ||
) | ||
s += self.parse(arg[0], in_block=True) | ||
s += "\\end {document}" | ||
return s | ||
|
||
def title(self, arg: Arguments) -> str: | ||
s = f"\\title{{{self.parse(arg[0])}}}\n" | ||
s += "\\maketitle" | ||
return s | ||
|
||
def author(self, arg: Arguments) -> str: | ||
return f"\\author{{{self.parse(arg[0])}}}" | ||
|
||
def header(self, arg: Arguments, number: int) -> str: | ||
if number < 6: | ||
return f"\\{self.headers[number - 1]}{{{self.parse(arg[0])}}}" | ||
return self.parse(arg[0]) | ||
|
||
def table(self, arg: Arguments) -> str: | ||
s = "\\begin{table}[h]\n\\begin{center}\n\\begin{tabular}{|" | ||
max_tds = 0 | ||
for tr in arg: | ||
if isinstance(tr, list): | ||
tds = 0 | ||
for td in tr: | ||
if isinstance(td, list): | ||
tds += 1 | ||
if tds > max_tds: | ||
max_tds = tds | ||
for k in range(max_tds): | ||
s += "l|" | ||
s += "}\n\\hline\n" | ||
for tr in arg: | ||
if isinstance(tr, list): | ||
tds = [] | ||
for td in tr: | ||
if isinstance(td, list): | ||
tds.append(td) | ||
for td in tds[:-1]: | ||
s += self.parse(td) + " & " | ||
s += self.parse(tds[-1]) | ||
s += " \\\\\n\\hline\n" | ||
s += "\\end{tabular}\n\\end{center}\n\\end{table}\n" | ||
return s | ||
|
||
def list__(self, arg: Arguments) -> str: | ||
s = "\\begin{itemize}\n" | ||
for item in arg: | ||
s += f"\\item {self.parse(item)}\n\n" | ||
s += "\\end{itemize}\n" | ||
return s | ||
|
||
def abstract(self, arg: Arguments) -> str: | ||
return ( | ||
"\\begin{abstract}\n\n" | ||
+ self.parse(arg[0], in_block=True) | ||
+ "\\end{abstract}\n\n" | ||
) | ||
|
||
def date(self, arg: Arguments) -> str: | ||
pass | ||
|
||
def text(self, arg: Arguments) -> str: | ||
return self.parse(arg[0]) + "\n\n" | ||
|
||
def m(self, arg: Arguments) -> str: | ||
return "{\\tt " + self.parse(arg[0]) + "}" | ||
|
||
|
||
if __name__ == "__main__": | ||
parser: ArgumentParser = ArgumentParser() | ||
|
||
parser.add_argument("-i", "--input", help="Moire input file", required=True) | ||
parser.add_argument("-o", "--output", help="output file", required=True) | ||
parser.add_argument("-f", "--format", help="output format", required=True) | ||
|
||
options: Namespace = parser.parse_args(sys.argv[1:]) | ||
|
||
with open(options.input, "r") as input_file: | ||
converter: Moire = getattr(sys.modules[__name__], options.format)() | ||
output: str = converter.convert(input_file.read()) | ||
|
||
if not output: | ||
print("Fatal: output was no produced.") | ||
sys.exit(1) | ||
|
||
with open(options.output, "w+") as output_file: | ||
output_file.write(output) | ||
print(f"Converted to {options.output}.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
""" | ||
Command line Python tool for file conversion from Moire markup language to other | ||
formats, such as HTML, TeX, etc. | ||
""" | ||
|
||
import logging | ||
import sys | ||
from argparse import ArgumentParser, Namespace | ||
from pathlib import Path | ||
from typing import List, Optional | ||
|
||
from moire.default import Default | ||
from moire.moire import Moire | ||
|
||
__author__ = "Sergey Vartanov" | ||
__email__ = "[email protected]" | ||
|
||
|
||
def main(arguments: List[str] = None, top_class=None): | ||
if not arguments: | ||
arguments = sys.argv[1:] | ||
if not top_class: | ||
top_class = Default | ||
|
||
logging.basicConfig(level=logging.INFO, format="%(message)s") | ||
|
||
parser: ArgumentParser = ArgumentParser() | ||
|
||
parser.add_argument("-i", "--input", help="Moire input file", required=True) | ||
parser.add_argument("-o", "--output", help="output file") | ||
parser.add_argument("-f", "--format", help="output format", required=True) | ||
parser.add_argument("--wrap", action="store_true", default=True) | ||
|
||
options: Namespace = parser.parse_args(arguments) | ||
|
||
converter: Optional[Moire] = None | ||
for class_ in top_class.__subclasses__(): | ||
if class_.id_ == options.format: | ||
converter = class_() | ||
|
||
if not converter: | ||
logging.fatal( | ||
f"No converter class found for format `{options.format}`." | ||
) | ||
exit(1) | ||
|
||
with Path(options.input).open() as input_file: | ||
converter.file_name = options.input | ||
output: str = converter.convert(input_file.read(), wrap=options.wrap) | ||
|
||
if not output: | ||
logging.fatal("No output was produced.") | ||
sys.exit(1) | ||
|
||
if options.output: | ||
with open(options.output, "w") as output_file: | ||
output_file.write(output) | ||
logging.info(f"Converted to {options.output}.") | ||
else: | ||
sys.stdout.write(output) | ||
|
||
|
||
if __name__ == "__main__": | ||
main(sys.argv[1:], Default) |
Oops, something went wrong.