page: add a dumb rendering mode
Dumb mode affects Gemtext parsing (gotta keep those empty lines) and rendering (render empty lines, do not attempt to put smart margins).
This commit is contained in:
parent
46ec9879e6
commit
1468e6ef10
|
@ -54,7 +54,7 @@ class ListItem:
|
||||||
ParsedGemtext = namedtuple("ParsedGemtext", ("elements", "links", "title"))
|
ParsedGemtext = namedtuple("ParsedGemtext", ("elements", "links", "title"))
|
||||||
|
|
||||||
|
|
||||||
def parse_gemtext(text: str) -> ParsedGemtext:
|
def parse_gemtext(text: str, dumb=False) -> ParsedGemtext:
|
||||||
"""Parse a string of Gemtext into a list of elements."""
|
"""Parse a string of Gemtext into a list of elements."""
|
||||||
elements = []
|
elements = []
|
||||||
links = Links()
|
links = Links()
|
||||||
|
@ -63,7 +63,9 @@ def parse_gemtext(text: str) -> ParsedGemtext:
|
||||||
preformatted = None
|
preformatted = None
|
||||||
for line in text.splitlines():
|
for line in text.splitlines():
|
||||||
line = line.rstrip()
|
line = line.rstrip()
|
||||||
if not line:
|
# In standard mode, discard empty lines. In dumb mode, empty lines are
|
||||||
|
# kept as basic text.
|
||||||
|
if not line and not dumb:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if line.startswith(Preformatted.FENCE):
|
if line.startswith(Preformatted.FENCE):
|
||||||
|
|
|
@ -35,18 +35,23 @@ class LineType(IntEnum):
|
||||||
LIST_ITEM = 8
|
LIST_ITEM = 8
|
||||||
|
|
||||||
|
|
||||||
def generate_metalines(elements, width):
|
def generate_metalines(elements, width, dumb=False):
|
||||||
"""Format elements into a list of lines with metadata.
|
"""Format elements into a list of lines with metadata.
|
||||||
|
|
||||||
The returned list ("metalines") are tuples (meta, line), meta being a
|
The returned list ("metalines") are tuples (meta, line), meta being a
|
||||||
dict of metadata and line a text line to display. Currently the only
|
dict of metadata and a text line to display. Currently the only metadata
|
||||||
metadata keys used are:
|
keys used are:
|
||||||
- type: one of the Renderer.TYPE constants.
|
- type: one of the Renderer.TYPE constants.
|
||||||
- url: only for links, the URL the link on this line refers to. Note
|
- url: only for links, the URL the link on this line refers to. Note
|
||||||
that this key is present only for the first line of the link, i.e.
|
that this key is present only for the first line of the link, i.e.
|
||||||
long link descriptions wrapped on multiple lines will not have a this
|
long link descriptions wrapped on multiple lines will not have a this
|
||||||
key except for the first line.
|
key except for the first line.
|
||||||
- link_id: only alongside "url" key, ID generated for this link.
|
- link_id: only alongside "url" key, ID generated for this link.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
- elements: list of elements to use.
|
||||||
|
- width: max text width to use.
|
||||||
|
- dumb: if True, standard presentation margins are ignored.
|
||||||
"""
|
"""
|
||||||
metalines = []
|
metalines = []
|
||||||
context = {"width": width}
|
context = {"width": width}
|
||||||
|
@ -78,12 +83,17 @@ def generate_metalines(elements, width):
|
||||||
thin_type = LineType.LIST_ITEM
|
thin_type = LineType.LIST_ITEM
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
# In dumb mode, elements producing no metalines still need to be
|
||||||
|
# rendered as empty lines.
|
||||||
|
if dumb:
|
||||||
|
if not element_metalines:
|
||||||
|
element_metalines = [({"type": LineType.PARAGRAPH}, "")]
|
||||||
# If current element requires margins and is not the first elements,
|
# If current element requires margins and is not the first elements,
|
||||||
# separate from previous element. Also do it if the current element does
|
# separate from previous element. Also do it if the current element does
|
||||||
# not require margins but follows an element that required it (e.g. link
|
# not require margins but follows an element that required it (e.g. link
|
||||||
# after a paragraph). Also do it if both the current and previous
|
# after a paragraph). Also do it if both the current and previous
|
||||||
# elements do not require margins but differ in type.
|
# elements do not require margins but differ in type.
|
||||||
if (
|
elif (
|
||||||
(has_margins and index > 0)
|
(has_margins and index > 0)
|
||||||
or (not has_margins and previous_had_margins)
|
or (not has_margins and previous_had_margins)
|
||||||
or (not has_margins and thin_type != last_thin_type)
|
or (not has_margins and thin_type != last_thin_type)
|
||||||
|
|
|
@ -28,10 +28,10 @@ class Page:
|
||||||
encoding: str = ""
|
encoding: str = ""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_gemtext(gemtext: str, wrap_at: int):
|
def from_gemtext(gemtext: str, wrap_at: int, dumb: bool =False):
|
||||||
"""Produce a Page from a Gemtext file or string."""
|
"""Produce a Page from a Gemtext file or string."""
|
||||||
elements, links, title = parse_gemtext(gemtext)
|
elements, links, title = parse_gemtext(gemtext, dumb=dumb)
|
||||||
metalines = generate_metalines(elements, wrap_at)
|
metalines = generate_metalines(elements, wrap_at, dumb=dumb)
|
||||||
return Page(gemtext, metalines, links, title)
|
return Page(gemtext, metalines, links, title)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
Reference in a new issue