pietroppeter / nimib

nimib 🐳 - nim 👑 driven ⛵ publishing ✍
https://pietroppeter.github.io/nimib/
MIT License
181 stars 10 forks source link

refactor rendering #24

Closed pietroppeter closed 2 years ago

pietroppeter commented 3 years ago

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.

pietroppeter commented 3 years ago

other expected enhancements from this:

pietroppeter commented 2 years ago

recent development notes on the topic (closing obsolete PR #35, will be redone from scratch):

current rendering process

process to be

rendering of a single block:

restricting scope:

example of API

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
HugoGranstrom commented 2 years ago

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? :)

HugoGranstrom commented 2 years ago

@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. 😄

pietroppeter commented 2 years ago

It is really overdue so yes, I plan to get it done before the end of the year

HugoGranstrom commented 2 years ago

Great to hear! I'll wait 'til then, then :D

pietroppeter commented 2 years ago

Did not manage end of year but this my number one priority now

HugoGranstrom commented 2 years ago

No worries 😄 I haven't had time for much either this Christmas. It will be finished when it is finished 👌

pietroppeter commented 2 years ago

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