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):
When no line break-related options are specified, “softbreaks” are rendered as line breaks.
When CMARK_OPT_NOBREAKS
is specified, “softbreaks” are rendered as spaces.
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.
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.
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")
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.
This blog is about things I encounter while doing web and non-web software development.