Syntax highlighting and miscellaneous fixes.
This commit is contained in:
parent
be2d8ed723
commit
a5e87aefde
8 changed files with 58 additions and 24 deletions
|
@ -33,9 +33,10 @@ def handle_command_define(e: Element, c: Context):
|
|||
return nullify(e)
|
||||
else:
|
||||
raise NameError(f"Command already defined: '{e.attributes['define']}'")
|
||||
if "redefine" in e.attributes:
|
||||
c.set_command(e.attributes["redefine"], compile(e.text, '<string>', 'exec'))
|
||||
return nullify(e)
|
||||
if "redefine" in e.attributes:
|
||||
c.set_command(e.attributes["redefine"], compile(e.text, '<string>', 'exec'))
|
||||
return nullify(e)
|
||||
return e
|
||||
|
||||
|
||||
def executeCommand(source, element: Element, ctx: Context) -> List[Element]:
|
||||
|
|
24
context.py
24
context.py
|
@ -2,11 +2,13 @@
|
|||
from panflute import Doc
|
||||
|
||||
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._commands = {}
|
||||
self._flags = {}
|
||||
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):
|
||||
if command in self._commands:
|
||||
|
@ -23,24 +25,27 @@ class Context:
|
|||
del self._commands[command]
|
||||
|
||||
def is_flag_set(self, flag: str):
|
||||
if flag in self._flags and self._flags[flag]:
|
||||
return True
|
||||
if self.get_metadata("flags."+flag):
|
||||
if self.get_metadata("flags."+flag):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
elif self.parent:
|
||||
return self.parent.is_set(flag)
|
||||
return self.parent.is_flag_set(flag)
|
||||
else:
|
||||
return False
|
||||
|
||||
def set_flag(self, flag: str, val: bool):
|
||||
self._flags[flag] = val
|
||||
self.set_metadata("flags."+flag, val)
|
||||
|
||||
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)
|
||||
if value is not None:
|
||||
return value
|
||||
elif self.parent:
|
||||
elif self.parent and not immediate:
|
||||
return self.parent.get_metadata(key)
|
||||
else:
|
||||
return None
|
||||
|
@ -57,6 +62,5 @@ class Context:
|
|||
key = key.split(".")
|
||||
for k in key[:-1]:
|
||||
meta = meta[k]
|
||||
print(type(meta))
|
||||
del meta.content[key[-1]] # A hack because MetaMap doesn't have a __delitem__
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ doc = import_md(open(sys.argv[1], "r").read())
|
|||
|
||||
|
||||
print(show(doc))
|
||||
context = Context(doc)
|
||||
context = Context(doc, sys.argv[1])
|
||||
doc = doc.walk(transform, context)
|
||||
print("---------------------")
|
||||
#print(show(doc))
|
||||
|
|
21
html.py
21
html.py
|
@ -1,4 +1,9 @@
|
|||
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 transform import FQuoted
|
||||
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)}"'
|
||||
|
||||
if isinstance(e, CodeBlock):
|
||||
# TODO: Syntax highlighting
|
||||
tag = "pre"
|
||||
if e.attributes["highlight"] == True or e.attributes["highlight"] == 'True':
|
||||
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):
|
||||
content_foot = html(e.caption, k, indent_level+1, indent_str)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
``` {.python define=nop}
|
||||
```python {define=nop}
|
||||
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.")
|
||||
```
|
||||
|
|
|
@ -7,6 +7,10 @@ I am a little piece of content
|
|||
|
||||
And things...
|
||||
|
||||
:::{if=cat}
|
||||
|
||||
:::
|
||||
|
||||
``` {.python .run}
|
||||
# I set my own flags!
|
||||
ctx.set_flag("cat", True)
|
||||
|
@ -40,3 +44,4 @@ I am a duck.
|
|||
:::{if=cat}
|
||||
This should be only shown to included cats.
|
||||
:::
|
||||
|
||||
|
|
6
test.md
6
test.md
|
@ -16,18 +16,18 @@ This should only be shown to cats
|
|||
:::
|
||||
|
||||
|
||||
``` {.python .run}
|
||||
```python {.run}
|
||||
ctx.set_flag("cat", True)
|
||||
```
|
||||
|
||||
``` {.python .run}
|
||||
```python {.run}
|
||||
println(f"The main document's title is '{ctx.get_metadata('title')}'")
|
||||
ctx.set_metadata("a", {})
|
||||
ctx.set_metadata("a.b", {})
|
||||
ctx.set_metadata("a.b.c", "Bruh **bruh** bruh")
|
||||
```
|
||||
|
||||
```python
|
||||
```python {style=native}
|
||||
def bruh(no):
|
||||
wat
|
||||
```
|
||||
|
|
13
transform.py
13
transform.py
|
@ -15,7 +15,6 @@ class FQuoted(Quoted):
|
|||
|
||||
def transform(e: Element, c: Context) -> Element: # Returns next sibling element to transform
|
||||
"""Transform the AST, making format-agnostic changes."""
|
||||
|
||||
if isinstance(e, Whitespace) and bavlna(e, c):
|
||||
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.
|
||||
if (isinstance(e, Div)) and "partial" in e.attributes:
|
||||
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)
|
||||
e = Div(*includedDoc.content)
|
||||
|
||||
|
@ -60,9 +59,17 @@ def transform(e: Element, c: Context) -> Element: # Returns next sibling element
|
|||
|
||||
## Command defines
|
||||
# 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)
|
||||
|
||||
# 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
|
||||
if isinstance(e, Span) and len(e.content) == 1 and isinstance(e.content[0], Str):
|
||||
## Handle special command shorthand [!commandname]{}
|
||||
|
|
Loading…
Reference in a new issue