Browse Source

Syntax highlighting and miscellaneous fixes.

pull/28/head
Jan Černohorský 1 year ago
parent
commit
a5e87aefde
  1. 7
      command.py
  2. 24
      context.py
  3. 2
      formatitko.py
  4. 21
      html.py
  5. 4
      test-import.md
  6. 5
      test-partial.md
  7. 6
      test.md
  8. 13
      transform.py

7
command.py

@ -33,9 +33,10 @@ def handle_command_define(e: Element, c: Context):
return nullify(e) return nullify(e)
else: else:
raise NameError(f"Command already defined: '{e.attributes['define']}'") raise NameError(f"Command already defined: '{e.attributes['define']}'")
if "redefine" in e.attributes: if "redefine" in e.attributes:
c.set_command(e.attributes["redefine"], compile(e.text, '<string>', 'exec')) c.set_command(e.attributes["redefine"], compile(e.text, '<string>', 'exec'))
return nullify(e) return nullify(e)
return e
def executeCommand(source, element: Element, ctx: Context) -> List[Element]: def executeCommand(source, element: Element, ctx: Context) -> List[Element]:

24
context.py

@ -2,11 +2,13 @@
from panflute import Doc from panflute import Doc
class Context: class Context:
def __init__(self, doc: Doc=None, parent: 'Context'=None): def __init__(self, doc: Doc, path: str, parent: 'Context'=None):
self.parent = parent self.parent = parent
self._commands = {} self._commands = {}
self._flags = {}
self.doc = doc self.doc = doc
self.path = path
if self.get_metadata("flags", immediate=True) is None:
self.set_metadata("flags", {})
def get_command(self, command: str): def get_command(self, command: str):
if command in self._commands: if command in self._commands:
@ -23,24 +25,27 @@ class Context:
del self._commands[command] del self._commands[command]
def is_flag_set(self, flag: str): def is_flag_set(self, flag: str):
if flag in self._flags and self._flags[flag]: if self.get_metadata("flags."+flag):
return True if self.get_metadata("flags."+flag):
return True
else:
return False
elif self.parent: elif self.parent:
return self.parent.is_set(flag) return self.parent.is_flag_set(flag)
else: else:
return False return False
def set_flag(self, flag: str, val: bool): def set_flag(self, flag: str, val: bool):
self._flags[flag] = val self.set_metadata("flags."+flag, val)
def unset_flag(self, flag): def unset_flag(self, flag):
del self._flags[flag] self.unset_metadata("flags."+flag)
def get_metadata(self, key, simple=True): def get_metadata(self, key, simple=True, immediate=False):
value = self.doc.get_metadata(key, None, simple) value = self.doc.get_metadata(key, None, simple)
if value is not None: if value is not None:
return value return value
elif self.parent: elif self.parent and not immediate:
return self.parent.get_metadata(key) return self.parent.get_metadata(key)
else: else:
return None return None
@ -57,6 +62,5 @@ class Context:
key = key.split(".") key = key.split(".")
for k in key[:-1]: for k in key[:-1]:
meta = meta[k] meta = meta[k]
print(type(meta))
del meta.content[key[-1]] # A hack because MetaMap doesn't have a __delitem__ del meta.content[key[-1]] # A hack because MetaMap doesn't have a __delitem__

2
formatitko.py

@ -18,7 +18,7 @@ doc = import_md(open(sys.argv[1], "r").read())
print(show(doc)) print(show(doc))
context = Context(doc) context = Context(doc, sys.argv[1])
doc = doc.walk(transform, context) doc = doc.walk(transform, context)
print("---------------------") print("---------------------")
#print(show(doc)) #print(show(doc))

21
html.py

@ -1,4 +1,9 @@
from panflute import * from panflute import *
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
from pygments.util import ClassNotFound
from whitespace import NBSP from whitespace import NBSP
from transform import FQuoted from transform import FQuoted
from katex import KatexClient from katex import KatexClient
@ -64,8 +69,20 @@ def html(e: Element, k: KatexClient, indent_level: int=0, indent_str: str="\t")
attributes += f' class="{" ".join(e.classes)}"' attributes += f' class="{" ".join(e.classes)}"'
if isinstance(e, CodeBlock): if isinstance(e, CodeBlock):
# TODO: Syntax highlighting if e.attributes["highlight"] == True or e.attributes["highlight"] == 'True':
tag = "pre" for cl in e.classes:
try:
lexer = get_lexer_by_name(cl)
except ClassNotFound:
continue
break
formatter = HtmlFormatter(style=e.attributes["style"])
result = highlight(e.text, lexer, formatter)
style = formatter.get_style_defs(".highlight")
return f'<style>{style}</style>{result}'
else:
return f'<pre>{e.text}</pre>'
if isinstance(e, Figure): if isinstance(e, Figure):
content_foot = html(e.caption, k, indent_level+1, indent_str) content_foot = html(e.caption, k, indent_level+1, indent_str)

4
test-import.md

@ -1,7 +1,7 @@
``` {.python define=nop} ```python {define=nop}
appendChildren(element.content) appendChildren(element.content)
``` ```
``` {.python define=opendatatask} ```python {define=opendatatask}
println("Toto je praktická open-data úloha. V [odevzdávátku](https://ksp.mff.cuni.cz/h/odevzdavatko/) si necháte vygenerovat vstupy a odevzdáte příslušné výstupy. Záleží jen na vás, jak výstupy vyrobíte.") println("Toto je praktická open-data úloha. V [odevzdávátku](https://ksp.mff.cuni.cz/h/odevzdavatko/) si necháte vygenerovat vstupy a odevzdáte příslušné výstupy. Záleží jen na vás, jak výstupy vyrobíte.")
``` ```

5
test-partial.md

@ -7,6 +7,10 @@ I am a little piece of content
And things... And things...
:::{if=cat}
:::
``` {.python .run} ``` {.python .run}
# I set my own flags! # I set my own flags!
ctx.set_flag("cat", True) ctx.set_flag("cat", True)
@ -40,3 +44,4 @@ I am a duck.
:::{if=cat} :::{if=cat}
This should be only shown to included cats. This should be only shown to included cats.
::: :::

6
test.md

@ -16,18 +16,18 @@ This should only be shown to cats
::: :::
``` {.python .run} ```python {.run}
ctx.set_flag("cat", True) ctx.set_flag("cat", True)
``` ```
``` {.python .run} ```python {.run}
println(f"The main document's title is '{ctx.get_metadata('title')}'") println(f"The main document's title is '{ctx.get_metadata('title')}'")
ctx.set_metadata("a", {}) ctx.set_metadata("a", {})
ctx.set_metadata("a.b", {}) ctx.set_metadata("a.b", {})
ctx.set_metadata("a.b.c", "Bruh **bruh** bruh") ctx.set_metadata("a.b.c", "Bruh **bruh** bruh")
``` ```
```python ```python {style=native}
def bruh(no): def bruh(no):
wat wat
``` ```

13
transform.py

@ -15,7 +15,6 @@ class FQuoted(Quoted):
def transform(e: Element, c: Context) -> Element: # Returns next sibling element to transform def transform(e: Element, c: Context) -> Element: # Returns next sibling element to transform
"""Transform the AST, making format-agnostic changes.""" """Transform the AST, making format-agnostic changes."""
if isinstance(e, Whitespace) and bavlna(e, c): if isinstance(e, Whitespace) and bavlna(e, c):
e = NBSP() e = NBSP()
@ -41,7 +40,7 @@ def transform(e: Element, c: Context) -> Element: # Returns next sibling element
# commands without affecting the state of the current document. # commands without affecting the state of the current document.
if (isinstance(e, Div)) and "partial" in e.attributes: if (isinstance(e, Div)) and "partial" in e.attributes:
includedDoc = import_md(open(e.attributes["partial"], "r").read()) includedDoc = import_md(open(e.attributes["partial"], "r").read())
nContext = Context(includedDoc, c) nContext = Context(includedDoc, e.attributes["partial"], c)
includedDoc = includedDoc.walk(transform, nContext) includedDoc = includedDoc.walk(transform, nContext)
e = Div(*includedDoc.content) e = Div(*includedDoc.content)
@ -60,9 +59,17 @@ def transform(e: Element, c: Context) -> Element: # Returns next sibling element
## Command defines ## Command defines
# possible TODO: def/longdef? # possible TODO: def/longdef?
if isinstance(e, CodeBlock) and hasattr(e, "classes") and "python" in e.classes and hasattr(e, "attributes"): if isinstance(e, CodeBlock) and hasattr(e, "classes") and "python" in e.classes and hasattr(e, "attributes")\
and ("define" in e.attributes or "redefine" in e.attributes):
e = handle_command_define(e, c) e = handle_command_define(e, c)
# Pass down metadata 'highlight' and 'highlight_style' as attribute to CodeBlocks
if isinstance(e, CodeBlock):
if not "highlight" in e.attributes:
e.attributes["highlight"] = c.get_metadata("highlight") if c.get_metadata("highlight") is not None else True
if not "style" in e.attributes:
e.attributes["style"] = c.get_metadata("highlight_style") if c.get_metadata("highlight_style") is not None else "default"
## Shorthands ## Shorthands
if isinstance(e, Span) and len(e.content) == 1 and isinstance(e.content[0], Str): if isinstance(e, Span) and len(e.content) == 1 and isinstance(e.content[0], Str):
## Handle special command shorthand [!commandname]{} ## Handle special command shorthand [!commandname]{}

Loading…
Cancel
Save