1. b.93z.org
  2. Notes

Adding hard line breaks to paka.cmark

Recently I’ve been working on support for CMARK_OPT_HARDBREAKS in paka.cmark, and I’ve been thinking about design of API for paka.cmark.to_html. In particular, how to conveniently allow library user to specify hard breaks via breaks keyword argument without breaking compatibility with existing interface that accepts True (to render “softbreak” elements as line breaks) or False (to render “softbreak” elements as spaces) for breaks.

There are three option specification cases related to line breaks and HTML in cmark (C library):

  1. When no line break-related options are specified, “softbreaks” are rendered as line breaks.

  2. When CMARK_OPT_NOBREAKS is specified, “softbreaks” are rendered as spaces.

  3. Finally, on CMARK_OPT_HARDBREAKS, “softbreaks” are rendered as <br>s.

In paka.cmark, first case is handled by breaks=True, and the second case by breaks=False. So the question is, what’s the best way (in this case) to handle third one. I don’t want to get rid of booleans, they are natural for “yes” and “no”, so let’s see how range of possible argument values can be augmented.

Enum

In addition to to_html user will have to import Breaks class (probably a subclass of enum.Enum):

>>> from paka.cmark import Breaks, to_html
>>> to_html(..., breaks=Breaks.soft)
>>> to_html(..., breaks=Breaks.no)
>>> to_html(..., breaks=Breaks.hard)

Though constants (e.g. HARD_BREAKS, NO_BREAKS) can be used instead, they’d still have to be imported, so there would be no real benefits comparing to use of enumeration.

String

Like “enum” variant, but no need to import anything except to_html:

>>> from paka.cmark import to_html
>>> to_html(..., breaks="soft")
>>> to_html(..., breaks="no")
>>> to_html(..., breaks="hard")

Combined approach

There’ll be Breaks class with two members:

class Breaks:
    soft = "soft"
    hard = "hard"

Breaks.no will not exist (so it will not be member of Breaks), as False is good enough, no need to reinvent it :) Then in to_html this will be handled in a way that does not set any cmark options when Breaks.soft is used:

opts = lib.CMARK_OPT_DEFAULT
if breaks:
    if breaks == "hard":
        opts |= lib.CMARK_OPT_HARDBREAKS
else:
    opts |= lib.CMARK_OPT_NOBREAKS

“Combined” variant will allow for enough flexibility, giving library user freedom to choose most suitable way to use paka.cmark:

>>> from paka.cmark import to_html
>>> to_html(..., breaks="hard")
>>> from paka.cmark import Breaks, to_html
>>> to_html(..., breaks=Breaks.hard)

So this is, roughly speaking, what I have implemented.

© 2008–2017 93z.org