gemtext: handle list items
This commit is contained in:
parent
4cb8ac11d6
commit
15f56289b9
|
@ -34,6 +34,12 @@ class Blockquote:
|
|||
RE = re.compile(r">\s*(.*)")
|
||||
|
||||
|
||||
@dataclass
|
||||
class ListItem:
|
||||
text: str
|
||||
RE = re.compile(r"\*\s(.*)")
|
||||
|
||||
|
||||
def parse_gemtext(data):
|
||||
"""Parse UTF-8 encoded Gemtext as a list of elements."""
|
||||
text = data.decode(encoding="utf8", errors="ignore")
|
||||
|
@ -71,6 +77,12 @@ def parse_gemtext(data):
|
|||
elements.append(Blockquote(text))
|
||||
continue
|
||||
|
||||
match = ListItem.RE.match(line)
|
||||
if match:
|
||||
text = match.groups()[0]
|
||||
elements.append(ListItem(text))
|
||||
continue
|
||||
|
||||
if preformatted:
|
||||
preformatted.lines.append(line)
|
||||
else:
|
||||
|
|
|
@ -3,11 +3,13 @@ import string
|
|||
from enum import IntEnum
|
||||
|
||||
from bebop.colors import ColorPair
|
||||
from bebop.gemtext import Blockquote, Link, Paragraph, Preformatted, Title
|
||||
from bebop.gemtext import (Blockquote, Link, ListItem, Paragraph, Preformatted,
|
||||
Title)
|
||||
|
||||
|
||||
SPLIT_CHARS = " \t-"
|
||||
JOIN_CHAR = "-"
|
||||
LIST_ITEM_MARK = "• "
|
||||
|
||||
|
||||
class LineType(IntEnum):
|
||||
|
@ -24,6 +26,7 @@ class LineType(IntEnum):
|
|||
LINK = 5
|
||||
PREFORMATTED = 6
|
||||
BLOCKQUOTE = 7
|
||||
LIST_ITEM = 8
|
||||
|
||||
|
||||
def format_elements(elements, width):
|
||||
|
@ -60,6 +63,8 @@ def format_elements(elements, width):
|
|||
elif isinstance(element, Blockquote):
|
||||
element_metalines = format_blockquote(element, context)
|
||||
has_margins = True
|
||||
elif isinstance(element, ListItem):
|
||||
element_metalines = format_list_item(element, context)
|
||||
else:
|
||||
continue
|
||||
# If current element requires margins and is not the first elements,
|
||||
|
@ -131,6 +136,15 @@ def format_blockquote(blockquote: Blockquote, context: dict):
|
|||
return [({"type": LineType.BLOCKQUOTE}, line) for line in lines]
|
||||
|
||||
|
||||
def format_list_item(item: ListItem, context: dict):
|
||||
"""Return metalines for this list item."""
|
||||
indent = len(LIST_ITEM_MARK)
|
||||
lines = wrap_words(item.text, context["width"], indent=indent)
|
||||
first_line = LIST_ITEM_MARK + lines[0][indent:]
|
||||
lines[0] = first_line
|
||||
return [({"type": LineType.LIST_ITEM}, line) for line in lines]
|
||||
|
||||
|
||||
def wrap_words(text, width, indent=0):
|
||||
"""Wrap a text in several lines according to the renderer's width."""
|
||||
lines = []
|
||||
|
|
Reference in a new issue