Resolve #23.
This commit is contained in:
parent
bec8100786
commit
7769b12cda
6 changed files with 103 additions and 100 deletions
|
@ -1,5 +1,4 @@
|
|||
from panflute import Div, Span, Para, Element
|
||||
from typing import List
|
||||
|
||||
# Import local files
|
||||
from .util import nullify, import_md
|
||||
|
@ -11,7 +10,7 @@ class Command:
|
|||
# This distinction is needed because while transforming the tree, inline
|
||||
# elements cannot be replaced with block ones
|
||||
class InlineCommand(Span, Command):
|
||||
def replaceSelf(self, content: List[Element]) -> Span:
|
||||
def replaceSelf(self, content: list[Element]) -> Span:
|
||||
try:
|
||||
return Span(*content)
|
||||
except TypeError:
|
||||
|
@ -22,7 +21,7 @@ class InlineCommand(Span, Command):
|
|||
pass
|
||||
|
||||
class BlockCommand(Div, Command):
|
||||
def replaceSelf(self, content: List[Element]) -> Div:
|
||||
def replaceSelf(self, content: list[Element]) -> Div:
|
||||
return Div(*content)
|
||||
pass
|
||||
|
||||
|
@ -58,7 +57,7 @@ def handle_command_define(e: Element, c: Context):
|
|||
#
|
||||
# These two types, appending and printing, cannot be mixed.
|
||||
|
||||
def executeCommand(source, element: Element, ctx: Context) -> List[Element]:
|
||||
def executeCommand(source, element: Element, ctx: Context) -> list[Element]:
|
||||
mode = 'empty'
|
||||
text = ""
|
||||
content = []
|
||||
|
@ -79,7 +78,7 @@ def executeCommand(source, element: Element, ctx: Context) -> List[Element]:
|
|||
mode = 'elements'
|
||||
content.append(e)
|
||||
|
||||
def appendChildren(l: List[Element]):
|
||||
def appendChildren(l: list[Element]):
|
||||
for e in l:
|
||||
appendChild(e)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from panflute import Cite, Emph, Image, LineBreak, Link, Math, Note, RawInline,
|
|||
from panflute import BulletList, Citation, CodeBlock, Definition, DefinitionItem, DefinitionList, Header, HorizontalRule, LineBlock, LineItem, ListItem, Null, OrderedList, Para, Plain, RawBlock, TableBody, TableFoot, TableHead
|
||||
from panflute import TableRow, TableCell, Caption, Doc
|
||||
from panflute import ListContainer, Element
|
||||
from typing import Union, Dict
|
||||
from typing import Union
|
||||
|
||||
import os
|
||||
import io
|
||||
|
@ -40,16 +40,16 @@ class HTMLGenerator(OutputGenerator):
|
|||
# text = text.replace(" ", " ") # Don't replace no-break spaces with HTML escapes, because we trust unicode?
|
||||
return text
|
||||
|
||||
def start_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def start_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
words = [tag]
|
||||
for key, value in attributes.items():
|
||||
words.append(f"{key}=\"{self.escape_special_chars(value)}\"")
|
||||
return "<" + " ".join(words) + ">"
|
||||
|
||||
def end_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def end_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
return "</" + tag + ">"
|
||||
|
||||
def single_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def single_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
return self.start_tag(tag, attributes)
|
||||
|
||||
def tagname(self, e) -> str:
|
||||
|
@ -82,7 +82,7 @@ class HTMLGenerator(OutputGenerator):
|
|||
except KeyError:
|
||||
return type(e).__name__.lower()
|
||||
|
||||
def common_attributes(self, e) -> Dict[str,str]:
|
||||
def common_attributes(self, e) -> dict[str,str]:
|
||||
attributes = {}
|
||||
if hasattr(e, "identifier") and e.identifier != "":
|
||||
attributes["id"] = e.identifier
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Union, Tuple
|
||||
from typing import Union
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
@ -14,7 +14,7 @@ class ImageMagickError(Exception):
|
|||
pass
|
||||
|
||||
class ImageProcessor:
|
||||
def __init__(self, public_dir: str, web_path: str, cache_dir: str, *lookup_dirs: List[str]):
|
||||
def __init__(self, public_dir: str, web_path: str, cache_dir: str, *lookup_dirs: list[str]):
|
||||
self.public_dir = public_dir
|
||||
self.cache_dir = cache_dir
|
||||
self.lookup_dirs = lookup_dirs
|
||||
|
@ -24,7 +24,7 @@ class ImageProcessor:
|
|||
if not os.path.exists(self.cache_dir):
|
||||
os.mkdir(self.cache_dir)
|
||||
|
||||
def process_image(self, input_filename: str, format: str, source_dir: str, width: int=None, height:int=None, quality: int=None, dpi: int=None, fit: bool=True, deps: List[str]=[]) -> str:
|
||||
def process_image(self, input_filename: str, format: str, source_dir: str, width: int=None, height:int=None, quality: int=None, dpi: int=None, fit: bool=True, deps: list[str]=[]) -> str:
|
||||
name = os.path.basename(input_filename)
|
||||
base, ext = os.path.splitext(name)
|
||||
ext = ext[1:]
|
||||
|
@ -85,7 +85,7 @@ class ImageProcessor:
|
|||
|
||||
return target_name
|
||||
|
||||
def is_outdated(self, target: str, deps: List[str]):
|
||||
def is_outdated(self, target: str, deps: list[str]):
|
||||
target_timestamp = os.path.getmtime(target)
|
||||
for dep in deps:
|
||||
dep_timestamp = os.path.getmtime(dep)
|
||||
|
@ -113,7 +113,7 @@ class ImageProcessor:
|
|||
raise e
|
||||
return target_name if relative else target_path
|
||||
|
||||
def get_image_size(self, input_filename: str, additional_dirs: List[str]=[]) -> Tuple[int, int]:
|
||||
def get_image_size(self, input_filename: str, additional_dirs: list[str]=[]) -> tuple[int, int]:
|
||||
full_path = self.find_image(input_filename, additional_dirs)
|
||||
if full_path is None:
|
||||
raise FileNotFoundError(f'Image {input_filename} not found.')
|
||||
|
@ -121,7 +121,7 @@ class ImageProcessor:
|
|||
return Image.open(full_path).size
|
||||
|
||||
|
||||
def find_image(self, input_filename: str, additional_dirs: List[str]=[]) -> Union[str, None]:
|
||||
def find_image(self, input_filename: str, additional_dirs: list[str]=[]) -> Union[str, None]:
|
||||
for dir in [*self.lookup_dirs, *additional_dirs]:
|
||||
if os.path.isfile(dir + "/" + input_filename):
|
||||
return dir + "/" + input_filename
|
||||
|
|
|
@ -3,8 +3,6 @@ import subprocess
|
|||
import tempfile
|
||||
import json
|
||||
import os
|
||||
from typing import Dict
|
||||
|
||||
|
||||
class KatexError(Exception):
|
||||
pass
|
||||
|
@ -45,7 +43,7 @@ class KatexClient:
|
|||
|
||||
self._client.connect(self._socket_file)
|
||||
|
||||
def render(self, tex: str, options: Dict={}):
|
||||
def render(self, tex: str, options: dict={}):
|
||||
# Send formulas to translate
|
||||
self._client.sendall((json.dumps({"formulas":[{"tex":tex}], "options":options})+"\n").encode("utf-8"))
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from panflute import Element, ListContainer, Inline, Block
|
|||
from panflute import Cite, Code, Emph, Image, LineBreak, Link, Math, Note, Quoted, RawInline, SmallCaps, SoftBreak, Space, Span, Str, Strikeout, Strong, Subscript, Superscript, Underline
|
||||
from panflute import BlockQuote, BulletList, Citation, CodeBlock, Definition, DefinitionItem, DefinitionList, Div, Figure, Header, HorizontalRule, LineBlock, LineItem, ListItem, MetaBlocks, MetaBool, MetaInlines, MetaList, MetaMap, MetaString, Null, OrderedList, Para, Plain, RawBlock, Table, TableBody, TableFoot, TableHead
|
||||
from panflute import TableRow, TableCell, Caption, Doc
|
||||
from typing import Union, Dict
|
||||
from typing import Union
|
||||
|
||||
from .whitespace import NBSP
|
||||
from .transform import FQuoted
|
||||
|
@ -34,13 +34,13 @@ class LaTeXGenerator(OutputGenerator):
|
|||
text = text.replace(" ", "~") # We use unicode no-break spaces to force nbsp in output
|
||||
return text
|
||||
|
||||
def start_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def start_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
return "\\" + tag + "{"
|
||||
|
||||
def end_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def end_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
return "}"
|
||||
|
||||
def single_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def single_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
return "\\" + tag + "{}"
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from panflute import Element, ListContainer, Inline, Block
|
|||
from panflute import Cite, Code, Emph, Image, LineBreak, Link, Math, Note, Quoted, RawInline, SmallCaps, SoftBreak, Space, Span, Str, Strikeout, Strong, Subscript, Superscript, Underline
|
||||
from panflute import BlockQuote, BulletList, Citation, CodeBlock, Definition, DefinitionItem, DefinitionList, Div, Figure, Header, HorizontalRule, LineBlock, LineItem, ListItem, MetaBlocks, MetaBool, MetaInlines, MetaList, MetaMap, MetaString, Null, OrderedList, Para, Plain, RawBlock, Table, TableBody, TableFoot, TableHead
|
||||
from panflute import TableRow, TableCell, Caption, Doc
|
||||
from typing import Union, Dict, List
|
||||
from typing import Union
|
||||
|
||||
from .whitespace import NBSP
|
||||
from .transform import FQuoted
|
||||
|
@ -20,9 +20,74 @@ class OutputGenerator:
|
|||
self.indent_str = indent_str
|
||||
self.indent_level = initial_indent_level
|
||||
self._at_start_of_line = True
|
||||
|
||||
def generate(self, e: Union[Element, ListContainer, List[Union[Element, ListContainer]]]):
|
||||
if isinstance(e, List):
|
||||
|
||||
self.TYPE_DICT_MISC = {
|
||||
TableRow: self.generate_TableRow,
|
||||
TableCell: self.generate_TableCell,
|
||||
Caption: self.generate_Caption,
|
||||
Doc: self.generate_Doc,
|
||||
LineItem: self.generate_LineItem,
|
||||
ListItem: self.generate_ListItem
|
||||
}
|
||||
|
||||
self.TYPE_DICT_BLOCK = {
|
||||
BlockQuote: self.generate_BlockQuote,
|
||||
BulletList: self.generate_BulletList,
|
||||
Citation: self.generate_Citation,
|
||||
CodeBlock: self.generate_CodeBlock,
|
||||
Definition: self.generate_Definition,
|
||||
DefinitionItem: self.generate_DefinitionItem,
|
||||
DefinitionList: self.generate_DefinitionList,
|
||||
Div: self.generate_Div,
|
||||
Figure: self.generate_Figure,
|
||||
Header: self.generate_Header,
|
||||
HorizontalRule: self.generate_HorizontalRule,
|
||||
LineBlock: self.generate_LineBlock,
|
||||
MetaBlocks: self.generate_MetaBlocks,
|
||||
MetaBool: self.generate_MetaBool,
|
||||
MetaInlines: self.generate_MetaInlines,
|
||||
MetaList: self.generate_MetaList,
|
||||
MetaMap: self.generate_MetaMap,
|
||||
MetaString: self.generate_MetaString,
|
||||
Null: self.generate_Null,
|
||||
OrderedList: self.generate_OrderedList,
|
||||
Para: self.generate_Para,
|
||||
Plain: self.generate_Plain,
|
||||
RawBlock: self.generate_RawBlock,
|
||||
Table: self.generate_Table,
|
||||
TableBody: self.generate_TableBody,
|
||||
TableFoot: self.generate_TableFoot,
|
||||
TableHead: self.generate_TableHead,
|
||||
Group: self.generate_Group
|
||||
}
|
||||
|
||||
self.TYPE_DICT_INLINE = {
|
||||
Cite: self.generate_Cite,
|
||||
Code: self.generate_Code,
|
||||
Emph: self.generate_Emph,
|
||||
Image: self.generate_Image,
|
||||
LineBreak: self.generate_LineBreak,
|
||||
Link: self.generate_Link,
|
||||
Math: self.generate_Math,
|
||||
Note: self.generate_Note,
|
||||
Quoted: self.generate_Quoted,
|
||||
RawInline: self.generate_RawInline,
|
||||
SmallCaps: self.generate_SmallCaps,
|
||||
SoftBreak: self.generate_SoftBreak,
|
||||
Space: self.generate_Space,
|
||||
Span: self.generate_Span,
|
||||
Str: self.generate_Str,
|
||||
Strikeout: self.generate_Strikeout,
|
||||
Strong: self.generate_Strong,
|
||||
Subscript: self.generate_Subscript,
|
||||
Superscript: self.generate_Superscript,
|
||||
Underline: self.generate_Underline,
|
||||
NBSP: self.generate_NBSP,
|
||||
FQuoted: self.generate_FQuoted
|
||||
}
|
||||
|
||||
def generate(self, e: Union[Element, ListContainer, list[Union[Element, ListContainer]]]):
|
||||
if isinstance(e, list):
|
||||
for el in e:
|
||||
self.generate(el)
|
||||
elif isinstance(e, ListContainer):
|
||||
|
@ -33,14 +98,7 @@ class OutputGenerator:
|
|||
self.generate_Block(e)
|
||||
else:
|
||||
try:
|
||||
{
|
||||
TableRow: self.generate_TableRow,
|
||||
TableCell: self.generate_TableCell,
|
||||
Caption: self.generate_Caption,
|
||||
Doc: self.generate_Doc,
|
||||
LineItem: self.generate_LineItem,
|
||||
ListItem: self.generate_ListItem
|
||||
}[type(e)](e)
|
||||
self.TYPE_DICT_MISC[type(e)](e)
|
||||
except KeyError:
|
||||
raise UnknownElementError(type(e))
|
||||
|
||||
|
@ -80,22 +138,22 @@ class OutputGenerator:
|
|||
self.output_file.write("\n")
|
||||
self._at_start_of_line = True
|
||||
|
||||
def start_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def start_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
return tag
|
||||
|
||||
def end_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def end_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
return "/" + tag
|
||||
|
||||
def single_tag(self, tag: str, attributes: Dict[str,str]={}) -> str:
|
||||
def single_tag(self, tag: str, attributes: dict[str,str]={}) -> str:
|
||||
return "/" + tag + "/"
|
||||
|
||||
def tagname(self, e) -> str:
|
||||
return type(e).__name__
|
||||
|
||||
def common_attributes(self, e: Element) -> Dict[str,str]:
|
||||
def common_attributes(self, e: Element) -> dict[str,str]:
|
||||
return {}
|
||||
|
||||
def generate_simple_tag(self, e: Union[Element, None]=None, tag: str="", attributes: Union[Dict[str,str],None]=None, content: Union[ListContainer, Element, List[Union[Element, ListContainer]], str, None]=None, inline: Union[bool, None]=None):
|
||||
def generate_simple_tag(self, e: Union[Element, None]=None, tag: str="", attributes: Union[dict[str,str],None]=None, content: Union[ListContainer, Element, list[Union[Element, ListContainer]], str, None]=None, inline: Union[bool, None]=None):
|
||||
if not tag and e:
|
||||
tag = self.tagname(e)
|
||||
if attributes is None and e:
|
||||
|
@ -124,29 +182,29 @@ class OutputGenerator:
|
|||
else:
|
||||
self.generate_simple_block_tag(tag, content, attributes)
|
||||
|
||||
def generate_simple_inline_tag(self, tag: str, content: Union[ListContainer, Element, List[Union[Element, ListContainer]]], attributes: Dict[str,str]={}):
|
||||
def generate_simple_inline_tag(self, tag: str, content: Union[ListContainer, Element, list[Union[Element, ListContainer]]], attributes: dict[str,str]={}):
|
||||
self.write(self.start_tag(tag, attributes))
|
||||
self.generate(content)
|
||||
self.write(self.end_tag(tag))
|
||||
|
||||
def generate_simple_block_tag(self, tag: str, content: Union[ListContainer, Element, List[Union[Element, ListContainer]]], attributes: Dict[str,str]={}):
|
||||
def generate_simple_block_tag(self, tag: str, content: Union[ListContainer, Element, list[Union[Element, ListContainer]]], attributes: dict[str,str]={}):
|
||||
self.writeln(self.start_tag(tag, attributes))
|
||||
self.indent_more()
|
||||
self.generate(content)
|
||||
self.indent_less()
|
||||
self.writeln(self.end_tag(tag))
|
||||
|
||||
def generate_raw_inline_tag(self, tag: str, text: str, attributes: Dict[str,str]={}):
|
||||
def generate_raw_inline_tag(self, tag: str, text: str, attributes: dict[str,str]={}):
|
||||
self.write(self.start_tag(tag, attributes))
|
||||
self.write(text)
|
||||
self.write(self.end_tag(tag))
|
||||
|
||||
def generate_raw_block_tag(self, tag: str, text: str, attributes: Dict[str,str]={}):
|
||||
def generate_raw_block_tag(self, tag: str, text: str, attributes: dict[str,str]={}):
|
||||
self.writeln(self.start_tag(tag, attributes))
|
||||
self.writeraw(text)
|
||||
self.writeln(self.end_tag(tag))
|
||||
|
||||
def generate_empty_block_tag(self, tag: str, attributes: Dict[str,str]={}):
|
||||
def generate_empty_block_tag(self, tag: str, attributes: dict[str,str]={}):
|
||||
self.writeln(self.single_tag(tag, attributes))
|
||||
|
||||
def generate_ListContainer(self, e: ListContainer):
|
||||
|
@ -154,30 +212,7 @@ class OutputGenerator:
|
|||
self.generate(child)
|
||||
|
||||
def generate_Inline(self, e: Inline):
|
||||
{
|
||||
Cite: self.generate_Cite,
|
||||
Code: self.generate_Code,
|
||||
Emph: self.generate_Emph,
|
||||
Image: self.generate_Image,
|
||||
LineBreak: self.generate_LineBreak,
|
||||
Link: self.generate_Link,
|
||||
Math: self.generate_Math,
|
||||
Note: self.generate_Note,
|
||||
Quoted: self.generate_Quoted,
|
||||
RawInline: self.generate_RawInline,
|
||||
SmallCaps: self.generate_SmallCaps,
|
||||
SoftBreak: self.generate_SoftBreak,
|
||||
Space: self.generate_Space,
|
||||
Span: self.generate_Span,
|
||||
Str: self.generate_Str,
|
||||
Strikeout: self.generate_Strikeout,
|
||||
Strong: self.generate_Strong,
|
||||
Subscript: self.generate_Subscript,
|
||||
Superscript: self.generate_Superscript,
|
||||
Underline: self.generate_Underline,
|
||||
NBSP: self.generate_NBSP,
|
||||
FQuoted: self.generate_FQuoted
|
||||
}[type(e)](e)
|
||||
self.TYPE_DICT_INLINE[type(e)](e)
|
||||
|
||||
def generate_Str(self, e: Str):
|
||||
self.write(self.escape_special_chars(e.text))
|
||||
|
@ -278,36 +313,7 @@ class OutputGenerator:
|
|||
|
||||
|
||||
def generate_Block(self, e: Block):
|
||||
{
|
||||
BlockQuote: self.generate_BlockQuote,
|
||||
BulletList: self.generate_BulletList,
|
||||
Citation: self.generate_Citation,
|
||||
CodeBlock: self.generate_CodeBlock,
|
||||
Definition: self.generate_Definition,
|
||||
DefinitionItem: self.generate_DefinitionItem,
|
||||
DefinitionList: self.generate_DefinitionList,
|
||||
Div: self.generate_Div,
|
||||
Figure: self.generate_Figure,
|
||||
Header: self.generate_Header,
|
||||
HorizontalRule: self.generate_HorizontalRule,
|
||||
LineBlock: self.generate_LineBlock,
|
||||
MetaBlocks: self.generate_MetaBlocks,
|
||||
MetaBool: self.generate_MetaBool,
|
||||
MetaInlines: self.generate_MetaInlines,
|
||||
MetaList: self.generate_MetaList,
|
||||
MetaMap: self.generate_MetaMap,
|
||||
MetaString: self.generate_MetaString,
|
||||
Null: self.generate_Null,
|
||||
OrderedList: self.generate_OrderedList,
|
||||
Para: self.generate_Para,
|
||||
Plain: self.generate_Plain,
|
||||
RawBlock: self.generate_RawBlock,
|
||||
Table: self.generate_Table,
|
||||
TableBody: self.generate_TableBody,
|
||||
TableFoot: self.generate_TableFoot,
|
||||
TableHead: self.generate_TableHead,
|
||||
Group: self.generate_Group
|
||||
}[type(e)](e)
|
||||
self.TYPE_DICT_BLOCK[type(e)](e)
|
||||
|
||||
|
||||
# Block elements
|
||||
|
@ -420,7 +426,7 @@ class OutputGenerator:
|
|||
self.generate_simple_tag(e)
|
||||
|
||||
# Maybe move this to ImageProcessor?
|
||||
def get_image_processor_args(self, attributes:Dict[str,str]) -> Dict:
|
||||
def get_image_processor_args(self, attributes:dict[str,str]) -> dict:
|
||||
# Attributes → image processor args
|
||||
additional_args = {}
|
||||
if "file-width" in attributes:
|
||||
|
|
Loading…
Reference in a new issue