Digging Deeper¶
More info on the Hykup API.
Creating Tags with Functions¶
Macros are great for end-users, but not fantastic for writing composable
code. Hykup includes a tag
function which allows for tags to be
created from a function rather than a macro.
Its signature is
(defn tag [tag-name &rest children &kwargs properties] ...)
The first argument is the tag name, which will be converted to a string
with str
. Positonal arguments will become the children to tag; they
will be passed along unchanged.
Keyword arguments will become the properties. They keywords themselves will
automatically be unmangled. Both the keywords and the values will be
converted to a string with str
when the tag is rendered.
The tag
function has no spacing rules. Spacing is preserved exactly
as it was given.
A sample tag creation looks like:
(tag 'p :id 'my-fancy-p-tag
:class "very-large very-small"
(tag 'span "Text nodes")
" are passed as strings.")
; <p id="my-fancy-p-tag" class="very-large very-small">
; <span>Text nodes</span> are passed as strings</p>
Creating Custom Tags (Components)¶
Hykup would be close to useless if you weren’t able to create your own components. Luckily, you can!
Components are actually just functions. They accept a number of positional
arguments, the last of which is the children to the component, as well as
keyword arguments (the tag attributes). Classes are passed in as the
class
keyword, but this is likely to change in the future.
The functions must be named component-
and then the name of the
component. For instance, the component for the <p>
tag is named
component-p
.
For examples:
; We'll define a "quote" component which adds fancy quotes before and after
; the inner text.
; We'll also accept attributes which will be placed on the tag.
(defn component-quote [children &kwargs attributes]
; (Dashes surpress whitespace)
#kup [span #** ~properties / “ - ~@children - ”])
(.render #kup [quote :style "color: red" / I am quoted!])
; <span style="color: red">“I am quoted!”</span>
; But perhaps fancy quotes don't always work, and we want to
; be able to choose between normal and fancy quotes?
(defn component-quote [fancy? children &kwargs attributes]
(if fancy?
#kup [span #** ~attributes / “ - ~@children - ”]
#kup [span #** ~attributes / " - ~@children - "]))
(.render #kup [quote ~false ; Must unqote otherwise the function would be passed the
; string "flase" rather than the value `false`.
I have normal quotes])
; <span>"I have normal quotes"</span>
; Or maybe we want the caller to be able to supply their own
; start and end quotes, with defaults?
(defn component-quote [children
&kwonly [start-quote "“"] [end-quote "”"]
&kwargs attributes]
#kup [span / ~start-quote - ~@children - ~end-quote]
(.render #kup [quote :start-quote [[ :end-quote ]] / I have custom quotes])
; <span>[[I have custom quotes]]</span>
Spacing Rules¶
If a Hykup form is supplied such as
#kup [p / I am some text]
There need to be some rules to decide how the symbols I am some text
should be rendered. In this particular example, it’s simple: a space is placed
between each symbol, rendering
<p>I am some text</p>
If children are nested elements or interpolated expressions, they are still surrounded with spaces:
(setv pronoun "I")
#kup [p / ~pronoun am [em / emphasized]]
; <p>I am <em>emphasized</em></em>
Strings allow for exact control of spaces:
#kup [p / "one two three four "]
; <p>one two three four </p>
but are still surrounded if placed next to other children:
#kup [p / "left" "middle" right]
; <p>left middle right</p>
Spaces may be explicitly surpressed with -
:
#kup [p / "no" - "spaces" - "please"]
; </p>nospacesplease</p>
If text (symbol or string) starts with any of ,.;:)]}?!
, a space
will not implicitly be placed before it:
; Note that the comma after the em is parsed as its own symbol
#kup [p / well, well, [em / well], what do we have here?]
; <p>well, well, <em>well</em>, what do we have here?</p>
Similarly, if text (symbol or string) ends with any of ([{~#
,
a space will not implicitly be placed after it:
#kup [p / I own "~" (how-many-hamsters?) hamsters]
; <p>I own ~14 hamsters</p>