Closed pietroppeter closed 2 years ago
other expected enhancements from this:
nbImage
nbBlocks
such as nbSkip
(do not execute code, but show it), nbBase
(no capture and no rendering, a base code block from which customization can be made; e.g. nbImage
will be built from nbBase
)recent development notes on the topic (closing obsolete PR #35, will be redone from scratch):
rendering of a single block:
restricting scope:
show api for:
template nbText(body: untyped) =
nb.blk = newBlock("nbText"): body # save code as string in nb.blk.code (we did not use to do this for nbText)
nb.blk.output = body # body must be an expression that evaluates as string
nb.blk.renderPlan = nb.renderPlan["nbText"]
nb.blk.partial = "nbText"
assert nb.renderPlan["nbText"] == @["mdTextToHtml"] # adds "textAsHtml" to context with text converted to Html through markdown
# we could other steps to process headers for generating a Toc (or for collecting link that could be check for validity)
assert nb.partials["nbText"] == """
{{&textAsHtml}}"""
template nbCode(body: untyped) =
nb.blk = newBlock("nbCode"): body
captureStdout(nb.blk.output):
body
nb.blk.renderPlan = nb.renderPlan["nbCode"]
nb.blk.partial = "nbCode"
assert nb.renderPlan["nbCode"] == @["highlightCode"]
assert nb.partials["nbCode"] == """
{{>nbCodeSource}}
{{>nbCodeOutput}}"""
assert nb.partials["nbCodeSource"] == """
<pre><code class="nim hljs">{{&codeHighlighted}}</code></pre>
""" # note new line here, note codeHighlighted can (and will) contain html
assert nb.partials["nbCodeOutput"] == """
<pre><samp>{{codeOutput}}</samp></pre>
""" # note new line here, note output is escaped
template nbImage(url, caption: string) =
nb.blk = newBlock("NbImage"): body
nb.blk.context["image"] = %* {"url": url, "caption": caption}
nb.blk.partial = "nbImage"
assert nb.partials["nbImage"] == """
<figure>
<img src="{{image.url}}" alt="{{image.caption}}">
<figcaption>{caption}</figcaption>
</figure>
"""
# function that renders the single block
func render(nb: var NbDoc, blk: var NbBlock): string =
for step in blk.renderPlan:
if step in nb.renderProc:
nb.renderProc[step](nb, blk)
# else raise some warning?
nb.blk.partial.render(blk.context)
# to use markdown backend? change partials, change renderProc, change also renderPlans?
# at the moment I should care the absolute minimum for the second backend if api for main backend is sound
Looks great! I really like the separation and modularity of the population of the contexts (renderPlan
) and what is actually rendered (blk.partial
). This should suffice in making custom versions of the basic templates of nimib like nbCode
by just using a different partial to render :D
A nitpick, but should the partials be nb.blk.partial = nb.partials["nbText"]
or is there some magic that you just provide the name of the partial that is stored in nb.partials
? :)
@pietroppeter What's the time span we are talking about before something like this is released in a new version of nimib? I'm thinking about announcing nimib-reveal, but if it is in the next few weeks I'm thinking about postponing it until then. 😄
It is really overdue so yes, I plan to get it done before the end of the year
Great to hear! I'll wait 'til then, then :D
Did not manage end of year but this my number one priority now
No worries 😄 I haven't had time for much either this Christmas. It will be finished when it is finished 👌
big milestone in new #78: refactor now is able to regenerate correctly hello.nim! 🥳
with respect to API published above a few changes in particular nbText
and nbCode
now are simpler:
template nbText*(body: untyped) =
newNbBlock("nbText", nb, nb.blk, body):
nb.blk.output = block:
body
template nbCode*(body: untyped) =
newNbBlock("nbCode", nb, nb.blk, body):
captureStdout(nb.blk.output):
body
a big refactor in rendering is ongoing (branch refactor-render).
I will add render objects and separte the rendering part from the block part. blocks will be generic (no block kind anymore) to simplify creation of custom blocks. also it will simplify how to add or customize a rendering backend.
Basically every block will have only a renderPlan (just a seq of strings). and according to backend it will execute the different steps. block renderPlan can be customized and rendering backend also will be customizable.