Browse Source

Velmi nedodělaný a neotestovaný draft TransformProcessoru. #21

pull/28/head
Jan Černohorský 10 months ago
parent
commit
08da8e5de4
  1. 9
      src/formatitko/output_generator.py
  2. 421
      src/formatitko/transform_processor.py

9
src/formatitko/output_generator.py

@ -11,7 +11,7 @@ from .context import Group
import re
class UnknownElementError(Exception):
"An unknown Element has been passed to the Output_generator, probably because panflute introduced a new one."
"An unknown Element has been passed to the OutputGenerator, probably because panflute introduced a new one."
pass
class OutputGenerator:
@ -92,8 +92,7 @@ class OutputGenerator:
old_context = self.current_context
self.current_context = e.context
if isinstance(e, list):
for el in e:
self.generate(el)
self.generate_list(e)
elif isinstance(e, ListContainer):
self.generate_ListContainer(e)
elif isinstance(e, Inline):
@ -218,6 +217,10 @@ class OutputGenerator:
for child in e:
self.generate(child)
def generate_list(self, e: list):
for el in e:
self.generate(el)
def generate_Inline(self, e: Inline):
self.TYPE_DICT_INLINE[type(e)](e)

421
src/formatitko/transform_processor.py

@ -0,0 +1,421 @@
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
from .whitespace import NBSP
from .elements import FQuoted
from .context import Group
ELCl = Union[Element, ListContainer, list[Union[Element, ListContainer]]]
class UnknownElementError(Exception):
"An unknown Element has been passed to the TransformProcessor, probably because panflute introduced a new one."
pass
class TransformProcessor:
def __init__(self):
self.context = None
self.TYPE_DICT = {
TableRow: self.transform_TableRow,
TableCell: self.transform_TableCell,
Caption: self.transform_Caption,
Doc: self.transform_Doc,
LineItem: self.transform_LineItem,
ListItem: self.transform_ListItem,
BlockQuote: self.transform_BlockQuote,
BulletList: self.transform_BulletList,
Citation: self.transform_Citation,
CodeBlock: self.transform_CodeBlock,
Definition: self.transform_Definition,
DefinitionItem: self.transform_DefinitionItem,
DefinitionList: self.transform_DefinitionList,
Div: self.transform_Div,
Figure: self.transform_Figure,
Header: self.transform_Header,
HorizontalRule: self.transform_HorizontalRule,
LineBlock: self.transform_LineBlock,
MetaBlocks: self.transform_MetaBlocks,
MetaBool: self.transform_MetaBool,
MetaInlines: self.transform_MetaInlines,
MetaList: self.transform_MetaList,
MetaMap: self.transform_MetaMap,
MetaString: self.transform_MetaString,
Null: self.transform_Null,
OrderedList: self.transform_OrderedList,
Para: self.transform_Para,
Plain: self.transform_Plain,
RawBlock: self.transform_RawBlock,
Table: self.transform_Table,
TableBody: self.transform_TableBody,
TableFoot: self.transform_TableFoot,
TableHead: self.transform_TableHead,
Group: self.transform_Group,
Cite: self.transform_Cite,
Code: self.transform_Code,
Emph: self.transform_Emph,
Image: self.transform_Image,
LineBreak: self.transform_LineBreak,
Link: self.transform_Link,
Math: self.transform_Math,
Note: self.transform_Note,
Quoted: self.transform_Quoted,
RawInline: self.transform_RawInline,
SmallCaps: self.transform_SmallCaps,
SoftBreak: self.transform_SoftBreak,
Space: self.transform_Space,
Span: self.transform_Span,
Str: self.transform_Str,
Strikeout: self.transform_Strikeout,
Strong: self.transform_Strong,
Subscript: self.transform_Subscript,
Superscript: self.transform_Superscript,
Underline: self.transform_Underline,
NBSP: self.transform_NBSP,
FQuoted: self.transform_FQuoted
}
def get_pretransformers(self) -> list[Callable[[ELCl],ELCl]]:
return [self.handle_if_attribute, self.handle_ifnot_attribute]
def get_posttransformers(self) -> list[Callable[[ELCl],ELCl]]:
return []
def transform(self, e: ELCl) -> ELCl:
if isinstance(e, list):
return self.transform_list(e)
elif isinstance(e, ListContainer):
return self.transform_ListContainer(e)
for transformer in self.get_pretransformers():
e = transformer(e)
try:
e = self.TYPE_DICT[type(e)](e)
except KeyError:
raise UnknownElementError(type(e))
for transformer in self.get_posttransformers():
e = transformer(e)
return e
def handle_if_attribute(self, e: ELCl) -> ELCl:
# `if` attribute. Only show this element if flag is set.
if hasattr(e, "attributes") and "if" in e.attributes:
if not self.context.is_flag_set(e.attributes["if"]):
return nullify(e)
def handle_ifnot_attribute(self, e: ELCl) -> ELCl:
# `ifnot` attribute. Only show this element if flag is NOT set
if hasattr(e, "attributes") and "ifnot" in e.attributes:
if self.context.is_flag_set(e.attributes["ifnot"]):
return nullify(e)
def transform_list(e: list[ELCl]) -> list[ELCl]:
for i in range(len(e)):
e[i] = self.transform(e[i])
return e
def transform_ListContainer(e: ListContainer) -> ListContainer:
for i in range(len(e)):
e[i] = self.transform(e[i])
return e
def transform_TableRow(e: TableRow) -> TableRow:
e.content = self.transform(e.content)
return e
def transform_TableCell(e: TableCell) -> TableCell:
e.content = self.transform(e.content)
return e
def transform_Caption(e: Caption) -> Caption:
e.content = self.transform(e.content)
return e
def transform_Doc(e: Doc) -> Doc:
e.content = self.transform(e.content)
return e
def transform_LineItem(e: LineItem) -> LineItem:
e.content = self.transform(e.content)
return e
def transform_ListItem(e: ListItem) -> ListItem:
e.content = self.transform(e.content)
return e
def transform_BlockQuote(e: BlockQuote) -> BlockQuote:
e.content = self.transform(e.content)
return e
def transform_BulletList(e: BulletList) -> BulletList:
e.content = self.transform(e.content)
return e
def transform_Citation(e: Citation) -> Citation:
e.content = self.transform(e.content)
return e
def transform_Definition(e: Definition) -> Definition:
e.content = self.transform(e.content)
return e
def transform_DefinitionItem(e: DefinitionItem) -> DefinitionItem:
e.content = self.transform(e.content)
return e
def transform_DefinitionList(e: DefinitionList) -> DefinitionList:
e.content = self.transform(e.content)
return e
def transform_Header(e: Header) -> Header:
e.content = self.transform(e.content)
return e
def transform_LineBlock(e: LineBlock) -> LineBlock:
e.content = self.transform(e.content)
return e
def transform_MetaBlocks(e: MetaBlocks) -> MetaBlocks:
e.content = self.transform(e.content)
return e
def transform_MetaBool(e: MetaBool) -> MetaBool:
e.content = self.transform(e.content)
return e
def transform_MetaInlines(e: MetaInlines) -> MetaInlines:
e.content = self.transform(e.content)
return e
def transform_MetaList(e: MetaList) -> MetaList:
e.content = self.transform(e.content)
return e
def transform_MetaMap(e: MetaMap) -> MetaMap:
e.content = self.transform(e.content)
return e
def transform_MetaString(e: MetaString) -> MetaString:
e.content = self.transform(e.content)
return e
def transform_OrderedList(e: OrderedList) -> OrderedList:
e.content = self.transform(e.content)
return e
def transform_Para(e: Para) -> Para:
e.content = self.transform(e.content)
return e
def transform_Plain(e: Plain) -> Plain:
e.content = self.transform(e.content)
return e
def transform_TableBody(e: TableBody) -> TableBody:
e.content = self.transform(e.content)
return e
def transform_TableFoot(e: TableFoot) -> TableFoot:
e.content = self.transform(e.content)
return e
def transform_TableHead(e: TableHead) -> TableHead:
e.content = self.transform(e.content)
return e
def transform_Group(e: Group) -> Group:
e.content = self.transform(e.content)
return e
def transform_Cite(e: Cite) -> Cite:
e.content = self.transform(e.content)
return e
def transform_Emph(e: Emph) -> Emph:
e.content = self.transform(e.content)
return e
def transform_Image(e: Image) -> Image:
e.content = self.transform(e.content)
return e
def transform_Link(e: Link) -> Link:
e.content = self.transform(e.content)
return e
def transform_Note(e: Note) -> Note:
e.content = self.transform(e.content)
return e
def transform_Quoted(e: Quoted) -> Quoted:
e.content = self.transform(e.content)
return e
def transform_SmallCaps(e: SmallCaps) -> SmallCaps:
e.content = self.transform(e.content)
return e
def transform_Strikeout(e: Strikeout) -> Strikeout:
e.content = self.transform(e.content)
return e
def transform_Strong(e: Strong) -> Strong:
e.content = self.transform(e.content)
return e
def transform_Subscript(e: Subscript) -> Subscript:
e.content = self.transform(e.content)
return e
def transform_Superscript(e: Superscript) -> Superscript:
e.content = self.transform(e.content)
return e
def transform_Underline(e: Underline) -> Underline:
e.content = self.transform(e.content)
return e
def transform_FQuoted(e: FQuoted) -> FQuoted:
e.content = self.transform(e.content)
return e
def transform_Figure(e: Figure) -> Figure:
e.content = self.transform(e.content)
e.caption = self.transform(e.caption)
return e
def transform_Table(e: Table) -> Table:
e.head = self.transform(e.head)
e.content = self.transform(e.content)
e.foot = self.transform(e.foot)
return e
def create_Group(*content, new_context: Context) -> Group:
old_context = self.context
self.context = new_context
content = self.transform(content)
self.context = old_context
return Group(*content, context=new_context)
def transform_Div(e: Div) -> Div:
e.content = self.transform(e.content)
if "group" in e.classes:
# `.group` class for Divs
# Content of Div is enclosed in a separate context, all attributes are passed as metadata
new_context = Context(Doc(), self.context.path, self.context, trusted=self.context.trusted)
for attribute, value in e.attributes:
new_context.set_metadata(attribute, value)
return self.create_Group(*e.content, new_context)
if "c" in e.attributes:
# Commands can be called multiple ways, this handles the following syntax:
# :::{c=commandname}
# :::
e = BlockCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
return self.transform(e)
if "partial" in e.attributes:
# `partial` attribute
# Used to include a file which is executed in a different (child) Context.
if not self.context.trusted: # If we're in an untrusted context, we shouldn't allow inclusion of files outside the PWD.
full_path = os.path.abspath(self.context.dir + "/" + e.attributes["partial"])
pwd = os.path.abspath(".")
if os.path.commonpath([full_path, pwd]) != os.path.commonpath([pwd]):
return nullify(e)
text = open(self.context.dir + "/" + e.attributes["partial"], "r").read()
path = self.context.dir + "/" + e.attributes["partial"]
includedDoc = import_md(text)
trusted = True
if "untrusted" in e.attributes and (e.attributes["untrusted"] == True or e.attributes["untrusted"] == 'True'):
trusted = False
if not self.context.trusted:
trusted = False
return self.create_Group(*e.content, Context(includedDoc, path, self.context, trusted=trusted))
return e
def transform_Span(e: Span) -> Span:
e.content = self.transform(e.content)
if "group" in e.classes:
# `.group` class for Spans
# Content of Span is enclosed in a separate context, all attributes are passed as metadata
# FIXME: This probably doesn't work... Will we error?
new_context = Context(Doc(), self.context.path, self.context, trusted=self.context.trusted)
for attribute, value in e.attributes:
new_context.set_metadata(attribute, value)
return self.create_Group(*e.content, new_context)
if "c" in e.attributes:
# Commands can be called multiple ways, this handles the following syntax:
# []{c=commandname} and
e = InlineCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
return self.transform(e)
return e
def transform_CodeBlock(e: CodeBlock) -> CodeBlock:
if "markdown" in e.classes and "group" in e.classes:
includedDoc = import_md(e.text)
return self.create_Group(*includedDoc.content, context=Context(includedDoc, self.context.path, self.context, self.context.trusted))
return e
def transform_Whitespace(e: Whitespace) -> Whitespace:
if bavlna(e, self.context):
return NBSP()
else:
return e
def transform_SoftBreak(e: SoftBreak) -> SoftBreak:
return self.transform_Whitespace(e)
def transform_Space(e: Space) -> Space:
return self.transform_Whitespace(e)
def transform_NBSP(e: NBSP) -> NBSP:
return e
def transform_Str(e: Str) -> Str:
return e
def transform_RawInline(e: RawInline) -> RawInline:
return e
def transform_Math(e: Math) -> Math:
return e
def transform_LineBreak(e: LineBreak) -> LineBreak:
return e
def transform_Code(e: Code) -> Code:
return e
def transform_RawBlock(e: RawBlock) -> RawBlock:
return e
def transform_Null(e: Null) -> Null:
return e
def transform_HorizontalRule(e: HorizontalRule) -> HorizontalRule:
return e
Loading…
Cancel
Save