diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a2c20d9..b87ce23 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -12,11 +12,17 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: iffy/install-nim@v4 + - name: apt install + run: sudo apt install -y libpcre3 libblas-dev liblapack-dev + - uses: iffy/install-nim@v5 - name: Generate run: | - nimble install -y - nimble docsDeps + set -e + nimble install -g nimble + nimble install -y -g https://github.com/zetashift/fontim + nimble install -y -g https://github.com/HugoGranstrom/cdt@0.1.1 + nimble sync -y + nimble setup nimble docs nimble buildDocs nimble buildBook diff --git a/.github/workflows/valid.yml b/.github/workflows/valid.yml index d7e5c2c..d4f5d07 100644 --- a/.github/workflows/valid.yml +++ b/.github/workflows/valid.yml @@ -11,21 +11,28 @@ jobs: strategy: matrix: nim: - - '1.6.x' - 'stable' - 'devel' fail-fast: false name: Nim ${{ matrix.nim }} steps: - uses: actions/checkout@v2 - - uses: jiro4989/setup-nim-action@v1 + - uses: jiro4989/setup-nim-action@v2.2.2 with: nim-version: ${{ matrix.nim }} repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: sudo apt install libpcre3 libpcre3-dev liblapack-dev + - run: nimble install nimble -g + - name: Pre-Install deps + run: | + set -e + nimble install -y https://github.com/zetashift/fontim -g + nimble install -y -g https://github.com/HugoGranstrom/cdt@0.1.1 - name: Install deps run: | - nimble install -y - nimble docsDeps + set -e + nimble sync -y + nimble setup - name: Build compiler-docs run: nimble docs - name: Build slideshows diff --git a/changelog.md b/changelog.md index 6899294..b628180 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,8 @@ # Changelog +## v0.4.0 +- Adapted the code to work with Nimib v0.4.0. + ## v0.2.2 - `columns` now create equally sized columns, no matter the content. (A empty column takes up as much width as one full of content). - `adaptiveColumns` has the behavior of the old `columns` where columns only are as big as their content needs. diff --git a/config.nims b/config.nims new file mode 100644 index 0000000..8ee48d2 --- /dev/null +++ b/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 2) +when withDir(thisDir(), system.fileExists("nimble.paths")): + include "nimble.paths" +# end Nimble config diff --git a/docsrc/nimconf2022.nim b/docsrc/nimconf2022.nim index 63092ac..a704c59 100644 --- a/docsrc/nimconf2022.nim +++ b/docsrc/nimconf2022.nim @@ -6,71 +6,6 @@ import nimiSlides nbInit(theme = revealTheme) nb.useLatex -template nbCodeDontRun*(body: untyped) = - newNbCodeBlock("nbCodeDontRun", body): - discard - -template nimibCode*(body: untyped) = - #nbText: "Nimib code:" - newNbCodeBlock("nimibCode", body): - discard - fragmentFadeIn: - nbRawHtml: "
" - #nbText: "Output:" - body - -template nimibCodeAnimate*(lines: varargs[seq[HSlice[int, int]]], body: untyped) = - ## Shows code and its output just like nbCode, but highlights different lines of the code in the order specified in `lines`. - ## lines: Specify which lines to highlight and in which order. (Must be specified as a seq[HSlice]) - ## Ex: - ## ```nim - ## animateCode(@[1..1], @[3..4, 6..6]): body - ## ``` - ## This will first highlight line 1, then lines 3, 4 and 6. - newNbCodeBlock("nimibCodeAnimate", body): - var linesString: string - if lines.len > 0: - linesString &= "|" - for lineBundle in lines: - for line in lineBundle: - linesString &= $line.a & "-" & $line.b & "," - linesString &= "|" - if lines.len > 0: - linesString = linesString[0 .. ^3] - nb.blk.context["highlightLines"] = linesString - fragmentFadeIn: - nbRawHtml: "
" - body - -template nimibCodeAnimate*(lines: varargs[HSlice[int, int], toHSlice], body: untyped) = - ## Shows code and its output just like nbCode, but highlights different lines of the code in the order specified in `lines`. - ## lines: Specify which lines to highlight and in which order. (Must be specified as a HSlice) - ## Ex: - ## ```nim - ## animateCode(1..1, 2..3, 5..5, 4..4): body - ## ``` - ## This will first highlight line 1, then lines 2 and 3, then line 5 and last line 4. - var s: seq[seq[HSlice[int, int]]] - for line in lines: - s.add @[line] - nimibCodeAnimate(s): - body - -nb.partials["nimibCode"] = nb.partials["nbCode"] -nb.renderPlans["nimibCode"] = nb.renderPlans["nbCode"] -nb.partials["nimibCodeAnimate"] = nb.partials["animateCode"] -nb.renderPlans["nimibCodeAnimate"] = nb.renderPlans["animateCode"] - -template nbCodeDontRunAnimateImpl(body: untyped) = - discard - -newAnimateCodeBlock(nbCodeDontRunAnimate, nbCodeDontRunAnimateImpl) - -nb.partials["nbCodeDontRun"] = nb.partials["nbCode"] -nb.renderPlans["nbCodeDontRun"] = nb.renderPlans["nbCode"] -nb.partials["nimibCode"] = nb.partials["nbCode"] -nb.renderPlans["nimibCode"] = nb.renderPlans["nbCode"] - template nimConfSlide(body: untyped) = slide: cornerImage("https://github.com/nim-lang/assets/raw/master/Art/logo-crown.png", UpperRight, size=100, animate=false) @@ -252,12 +187,12 @@ Text can be *italic*, **bold** or ~~crossed over~~. nimConfSlide: nbText: """### Installation""" - nbCodeDontRun: + nbCodeSkip: nimble install nimiSlides nimConfSlide: nbText: "### Setting up" - nbCodeDontRun: + nbCodeSkip: import nimib, nimiSlides nbInit(theme = revealTheme) @@ -273,7 +208,7 @@ Text can be *italic*, **bold** or ~~crossed over~~. columns: column: fragmentFadeIn: - nbCodeDontRunAnimate(1..4, 1..2, 3..4, 6..12, 6, 7..8, 9..10, 11..12): + animateCodeSkip(1..4, 1..2, 3..4, 6..12, 6, 7..8, 9..10, 11..12): slide: nbText: "1" slide: @@ -431,7 +366,7 @@ slide: listItem: nbText: "Back again" nimConfSlide: - nimibCodeAnimate(1, 2..3, 4, 5..6, 7, 9): + animateCode(1, 2..3, 4, 5..6, 7, 9): unorderedList: listItem: nbText: "First item" @@ -460,7 +395,7 @@ slide: nimConfAutoSlide: nbText: "## Columns" - nimibCodeAnimate(1, 2..3, 4..5, 6..7): + animateCode(1, 2..3, 4..5, 6..7): columns: column: nbText: "Left" @@ -509,7 +444,7 @@ slide: slide(slideOptions(colorBackground = "darkviolet")): nbText: "## Color Background" - nbCodeDontRun: + nbCodeSkip: slide(slideOptions(colorBackground = "darkviolet")): nbText: "## Color Background" @@ -518,7 +453,7 @@ slide: nimConfSlide: nbText: "## Image Background" - nbCodeDontRun: + nbCodeSkip: slide(slideOptions(imageBackground = "https://github.com/nim-lang/assets/raw/master/Art/logo-crown.png")): discard @@ -527,13 +462,13 @@ slide: nimConfSlide: nbText: "## Iframe Background" - nbCodeDontRun: + nbCodeSkip: slide(slideOptions(iframeBackground = "https://nim-lang.org/")): discard nimConfSlide: nbText: "## Video Background" - nbCodeDontRun: + nbCodeSkip: slide(slideOptions(videoBackground = "link/to/videofile.mp4")): discard fragmentFadeIn: @@ -575,7 +510,7 @@ slide: """ nimConfSlide: - nbCodeDontRunAnimate(1..4, 6..10, 12..17): + animateCodeSkip(1..4, 6..10, 12..17): slide(slideOptions(autoAnimate=true)): nbText: """ - First @@ -639,7 +574,7 @@ slide: nbText: "## Using Templates" nimConfAutoSlide: nbText: "## Using Templates" - nbCodeDontRunAnimate({1, 3, 6}): + animateCodeSkip({1, 3, 6}): slide(slideOptions(autoAnimate=true)): nbText: "## Animate header" slide(slideOptions(autoAnimate=true)): @@ -654,7 +589,7 @@ slide: nimConfAutoSlide: nbText: "## Using Templates" - nbCodeDontRunAnimate(1, 2..3, 3, 5..6): + animateCodeSkip(1, 2..3, 3, 5..6): template slideAutoAnimate(body: untyped) = slide(slideOptions(autoAnimate=true)): body @@ -667,7 +602,7 @@ slide: stackElements: fragment(fadeInThenOut): nbText: "#### Without template" - nbCodeDontRun: + nbCodeSkip: slide(slideOptions(autoAnimate=true)): nbText: "## Animate header" slide(slideOptions(autoAnimate=true)): @@ -679,7 +614,7 @@ slide: nbText: "And this" fragmentFadeIn: nbText: "#### With template" - nbCodeDontRun: + nbCodeSkip: slideAutoAnimate: nbText: "## Animate header" slideAutoAnimate: @@ -698,10 +633,10 @@ slide: nbText: "Example: Histogram of Gaussian for different N" nimConfAutoSlide: nbText: "## Loops ♻️ + Generate images 🖼️" - nbCodeDontRunAnimate(1, 2, 3, 4..7, 9, 10, 11): + animateCodeSkip(1, 2, 3, 4..7, 9, 10, 11): for n in [50, 100, 1000, 10000]: let filename = &"images/gauss-{n}.png" - let samples = newSeqWith[float](n, gauss(0.0, 1.0)) + let samples = newSeqWith(n, gauss(0.0, 1.0)) let df = toDf(samples) ggplot(df, aes("samples")) + geom_histogram(fillColor="green") + @@ -714,7 +649,7 @@ slide: slide: for n in [50, 100, 1000, 10000]: let filename = &"images/gauss-{n}.png" - let samples = newSeqWith[float](n, gauss(0.0, 1.0)) + let samples = newSeqWith(n, gauss(0.0, 1.0)) let df = toDf(samples) ggplot(df, aes("samples")) + geom_histogram(fillColor="green") + diff --git a/docsrc/nimconf2026.nim b/docsrc/nimconf2026.nim new file mode 100644 index 0000000..eab4784 --- /dev/null +++ b/docsrc/nimconf2026.nim @@ -0,0 +1,284 @@ +import std / [strutils, random, sequtils, math, strformat, json] +import nimib, nimib / [capture] +import nimiSlides + +nbInit(theme = revealTheme) +nb.useLatex + +template nimSlide(body: untyped) = + slide: + cornerImage("https://github.com/nim-lang/assets/raw/master/Art/logo-crown.png", UpperRight, size=100, animate=false) + body + +template nimSlide(options: SlideOptions, body: untyped) = + slide(options): + cornerImage("https://github.com/nim-lang/assets/raw/master/Art/logo-crown.png", UpperRight, size=100, animate=false) + body + +template nimConfTheme*() = + setSlidesTheme(Black) + let nimYellow = "#FFE953" + nb.addStyle: """ +:root { + --r-background-color: #181922; + --r-heading-color: $1; + --r-link-color: $1; + --r-selection-color: $1; + --r-link-color-dark: darken($1 , 15%) +} + +.reveal ul, .reveal ol { + display: block; + text-align: left; +} + +li::marker { + color: $1; + content: "»"; +} + +li { + padding-left: 12px; +} +""" % [nimYellow] + +nimConfTheme() + +proc liText(s: string) = + listItem: + nbText: + s + +newNbBlock(FieldSet of NbContainer): + title: string + toHtml: + let renderedBlocks = nbContainerToHtml(blk, nb) + hlHtmlF""" +
+ {blk.title} + {renderedBlocks} +
+ """ + +template fieldSet(ttitle: string, body: untyped) = + let blk = newFieldSet(title=ttitle) + nb.withContainer(blk): + body + nb.add blk + +newNbBlock(JsonShow of NbContainer): + toHtml: + let blocksSerialized = blk.blocks.toJson().fromJson().pretty() + preCodeTag("json", blocksSerialized) + +template jsonShow(body: untyped) = + let blk = newJsonShow() + nb.withContainer(blk): + body + nb.add blk + +template showJsonSerialized(body: untyped) = + let code = getCode(body) + autoAnimateSlidesCustom(nimSlide, 3): + fieldSet("Nim"): + nbRawHtml: preCodeTag("nim", code) + showAt(2): + fieldSet("Rendered"): + body + showAt(3): + fieldSet("JSON"): + jsonShow: + body + +template intro = + slide: + nimSlide: + nbText: "## Nimib v0.4" + nbText: "## internals ref-actoring" + nbText: "Hugo Granström" + nbText: "NimConf 2026" + autoAnimateSlidesCustom(nimSlide, 3): + nbText: "## Story time" + showAt(1): + unorderedList: + liText: "Spirit of Nimib past" + unorderedList: + liText: "Rendering: Mustache templates" + liText: "Single NbBlock type" + showAt(2): + unorderedList: + liText: "Spirit of Nimib present" + unorderedList: + liText: "Rendering: normal Nim functions" + unorderedList: + liText: "Breaking change" + liText: "Different type for each block" + unorderedList: + liText: "Container blocks" + liText: "Sugar" + liText: "JSON" + showAt(3): + unorderedList: + liText: "Spirit of Nimib future" + unorderedList: + liText: "NimiSlides + NimiBook" + liText: "Static site generator" + liText: "Nimibex" + + +template defineBlockExamples = + nimSlide: + nbText: "## Defining a block" + unorderedList: + liText: "Simple example - usage bar" + liText: "Container example - collapsible section" + slide: + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Usage bar" + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Usage bar" + for i in [20, 40, 60, 80]: + nbDiv(): + nbRawHtml: hlHtml""" + + """ % [$i, $(i / 100)] + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Usage bar" + nbRawHtml: preCodeTag("html", hlHtml""" +""") + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Usage bar" + animateCode(1, 2..6, 7..8, 9..19, 21..28, 29..33, 34): + newNbBlock(UsageBar): + label: string + altText: string + value: float + minValue: float + maxValue: float + toHtml: + # injects `blk: UsageBar` + &""" + +""" + + proc usageBar( + nb: var Nb, + label: string, + value: float, + altText: string = $value, + minValue: float = 0.0, + maxValue: float = 1.0 + ) = + let blk = newUsageBar( + label=label, value=value, + altText=altText, minValue=minValue, + maxValue=maxValue + ) + nb.add blk + + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Usage bar" + nbCode: + nb.usageBar( + label="Storage usage:", + value=0.8, + altText="80% of storage used" + ) + let exampleCollapsible = hlHtml""" +
+ + What is hidden inside? + + Super secret text! +
+""" + slide: + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Collapsible section" + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Collapsible section" + nbRawHtml: exampleCollapsible + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Collapsible section" + nbRawHtml: preCodeTag("html", exampleCollapsible) + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Collapsible section" + animateCode(1, 2, 3, 4, 5..11, 13..16, 17, 18..19, 20): + newNbBlock(CollapsibleSection of NbContainer): + summary: string + toHtml: + let renderedBlocks = nbContainerToHtml(blk, nb) + &""" +
+ + {blk.summary} + + {renderedBlocks} +
""" + + template collapsibleSection( + text: string, + body: untyped + ) = + let blk = newCollapsibleSection(summary=text) + nb.withContainer(blk): + body + nb.add blk + nimSlide(slideOptions(autoAnimate = true)): + nbText: "## Collapsible section" + let secretMessage = "Never gonna give you up, never gonna let you down..." + nbCode: + collapsibleSection("Top secret"): + nbText(secretMessage) + + +template jsonShowcase = + autoAnimateSlidesCustom(nimSlide, 3): + nbText: "## JSON serialization" + showAt(2): + unorderedList: + liText: "Uses Jsony" + liText: "Individual blocks or entire documents" + showAt(3): + animateCode(1, 2..3, 4..5): + let blk = newNbText(text="Hello JSON!") + # Serialize + echo blk.toJson() + # Deserialize + echo blk.toJson().fromJson(NbBlock).NbText.text + nimSlide: + showJsonSerialized: + nbText: "*Hello* **there**" + nimSlide: + showJsonSerialized: + nbCode: + echo "General Kenobi" + nimSlide: + showJsonSerialized: + nbDiv(classes="cool", styles="color: green"): + nbText: "This is nested" + +template outro = + nimSlide: + typewriter("Thank you for watching!" & ' '.repeat(30) & "\nSee you in NimibLand!") + +intro +defineBlockExamples +jsonShowcase +outro + +nbSave diff --git a/docsrc/showcase.nim b/docsrc/showcase.nim index 0fdaa5a..5315751 100644 --- a/docsrc/showcase.nim +++ b/docsrc/showcase.nim @@ -5,7 +5,7 @@ nbInit(theme = revealTheme) nb.useLatex() when defined(themeWhite): - nb.filename = "./showcase_white.html" + nb.doc.filename = "./showcase_white.html" setSlidesTheme(White) else: setSlidesTheme(Moon) diff --git a/docsrc/utils/embeddedReveal.nim b/docsrc/utils/embeddedReveal.nim index a514a0c..8dcea98 100644 --- a/docsrc/utils/embeddedReveal.nim +++ b/docsrc/utils/embeddedReveal.nim @@ -22,33 +22,14 @@ table tbody tr:nth-child(2n) { """ - nb.partials["nbCodeSource"] = "
{{&codeHighlighted}}
" - nb.partials["nbCodeOutput"] = "{{#output}}
{{output}}
{{/output}}" + nb.populateNimiSlidesBlockPartials() - nb.partials["animateCode"] = "
{{&codeHighlighted}}
\n" & nb.partials["nbCodeOutput"] - nb.renderPlans["animateCode"] = nb.renderPlans["nbCode"] - - nb.partials["fragmentStart"] = """ -{{#fragments}} -
-{{/fragments}} - """ - - nb.partials["fragmentEnd"] = """ -{{#fragments}} -
-{{/fragments}} - """ - - nb.partials["bigText"] = """

{{&outputToHtml}}

""" - nb.renderPlans["bigText"] = nb.renderPlans["nbText"] - - nb.context["disableHighlightJs"] = true + nb.disableHighlightJs() template embeddedSlides*(body: untyped) = currentFragment = 0 currentSlideNumber = 0 - let id = "revealId" & $nb.newId() + let id = "revealId" & $nb.doc.newId() nbRawHtml: hlHtmlF"""
diff --git a/nimble.lock b/nimble.lock new file mode 100644 index 0000000..063cd92 --- /dev/null +++ b/nimble.lock @@ -0,0 +1,571 @@ +{ + "version": 2, + "packages": { + "nim": { + "version": "2.2.10", + "vcsRevision": "9fe2137fa2f3f66cf5a44f357d461829ac9e20c4", + "url": "https://github.com/nim-lang/Nim.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "17ec440fdb89f8903db29a17898af590087d2b64" + } + }, + "chroma": { + "version": "1.0.0", + "vcsRevision": "8bf4a0933ff405f83dc3a176199f528601e5b796", + "url": "https://github.com/treeform/chroma", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "76a12834f1b7e211e4232c1e13960accba6bd477" + } + }, + "seqmath": { + "version": "0.2.2", + "vcsRevision": "74767bc93d5ef460a607c5224df82237cdb39ac5", + "url": "https://github.com/Vindaar/seqmath", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "734340a5e463353b96c988e776df8b8760c099ec" + } + }, + "parsetoml": { + "version": "0.7.2", + "vcsRevision": "d297f5a81be2472905d367aa675dcbbca6e7a5d2", + "url": "https://github.com/NimParsers/parsetoml.git", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "2a9fb57ef1f6460fd61b1cfab2d83af44f788a25" + } + }, + "cairo": { + "version": "1.1.1", + "vcsRevision": "50ca8ed54554eae686024c0dc88490502af31cb8", + "url": "https://github.com/nim-lang/cairo", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "f2c13e59ce9658b2ae6fa0c89173f6012a23fafc" + } + }, + "vmath": { + "version": "3.0.0", + "vcsRevision": "7bd9f6e6b23ca3b751be42f20c8025d320881a00", + "url": "https://github.com/treeform/vmath", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "d88141c3844bbb2bb2d6146ebb96e570ca863067" + } + }, + "bumpy": { + "version": "1.1.3", + "vcsRevision": "edc6e19ddbe6b9e46c3384e9a4131d7063a3f610", + "url": "https://github.com/treeform/bumpy", + "downloadMethod": "git", + "dependencies": [ + "nim", + "vmath" + ], + "checksums": { + "sha1": "8a55667a7585612b7cefecd9a25ac3e761f03097" + } + }, + "opencl": { + "version": "1.0.1", + "vcsRevision": "7b138ac19d7f5452a74742392ffadac3d26ee397", + "url": "https://github.com/nim-lang/opencl", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "89c70044ee474834a4f7dcd6bf05a9082b0886bb" + } + }, + "clblast": { + "version": "0.0.2", + "vcsRevision": "cdadb10dd85b95c9e7248f0b9661ad1e7616efe6", + "url": "https://github.com/numforge/nim-clblast", + "downloadMethod": "git", + "dependencies": [ + "nim", + "opencl" + ], + "checksums": { + "sha1": "0b4514b483f83492c49bb0629e5b45ffdf8e7aa3" + } + }, + "nimcl": { + "version": "0.1.3", + "vcsRevision": "f2f963ff043a364386888f8a6cf91646cd583e99", + "url": "https://github.com/andreaferretti/nimcl", + "downloadMethod": "git", + "dependencies": [ + "nim", + "opencl" + ], + "checksums": { + "sha1": "fb304e3b75503fb359ffe649d019a2fac7e2b3dc" + } + }, + "fontim": { + "version": "0.2.0", + "vcsRevision": "eae55734dbf316bd428524a1e29974ac17fda711", + "url": "https://github.com/zetashift/fontim", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "3aa3f5f541ecd9d24aaf4d56620b3c00fa668884" + } + }, + "threading": { + "version": "0.2.1", + "vcsRevision": "ee77a27eca7042a2b68061d0bcee691e5b56aa10", + "url": "https://github.com/nim-lang/threading", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "594ec27a467847166ef78767ff60e1c87d0f743f" + } + }, + "fusion": { + "version": "1.2", + "vcsRevision": "0b0a0273b8df860cd54e3fcca7bb4c617244ac77", + "url": "https://github.com/nim-lang/fusion", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "408bde8679bce63dfb6f424e107eb37c5eb31510" + } + }, + "nimlapack": { + "version": "0.3.1", + "vcsRevision": "231430b3d2156f5cbe8fe16bb8967cd9a93964c5", + "url": "https://github.com/andreaferretti/nimlapack", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "fcb25795c6fb43f9251b7f34c3ad84c39e645afd" + } + }, + "zip": { + "version": "0.3.1", + "vcsRevision": "bdc5783fefc1afb8eb622ff13d464a832ce1d507", + "url": "https://github.com/nim-lang/zip", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "747aab3c43ecb7b50671cdd0ec3b2edc2c83494c" + } + }, + "webview": { + "version": "0.1.0", + "vcsRevision": "ca3e25ee93a63c3a819a1bfa17386dad6ad41b1a", + "url": "https://github.com/oskca/webview", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "2d714d280055de9d0a33e6a730f1099feb1261aa" + } + }, + "nimpy": { + "version": "0.2.1", + "vcsRevision": "d559f7bcb8fb877b4eae4bd116b8fbc9e16560ef", + "url": "https://github.com/yglukhov/nimpy", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "0e88588fb093806b3e2d9f2a4b7e507abf863958" + } + }, + "shell": { + "version": "0.6.0", + "vcsRevision": "cdd98b9d6e0715fc13a62b1de3f82450cc463679", + "url": "https://github.com/Vindaar/shell", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "ce4bd02e0fbe71a56753821b4162ecad488cec66" + } + }, + "latexdsl": { + "version": "0.2.2", + "vcsRevision": "5586b8f0181264b61fed86957e7af082dfcd3870", + "url": "https://github.com/Vindaar/LatexDSL", + "downloadMethod": "git", + "dependencies": [ + "nim", + "shell" + ], + "checksums": { + "sha1": "938592e63aa305f184d5bf6d7c9816ec9cf5aa06" + } + }, + "nimcuda": { + "version": "0.2.2", + "vcsRevision": "319b8deb31812fd9277c6232f0ae3fca31c6d55d", + "url": "https://github.com/andreaferretti/nimcuda", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "630aaaad24b7f817f6c576bca246141919870cb8" + } + }, + "flatty": { + "version": "0.4.0", + "vcsRevision": "c7091b096bcf275f47b666ef74bce73eda187ee3", + "url": "https://github.com/treeform/flatty", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "2105eef6c8aa1bd84bf92ace7fbad63c0110c82a" + } + }, + "stb_image": { + "version": "2.5", + "vcsRevision": "ba5f45286bfa9bed93d8d6b941949cd6218ec888", + "url": "https://gitlab.com/define-private-public/stb_image-Nim.git", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "abf5fd03e72ee4c316c50a0538b973e355dcb175" + } + }, + "jsony": { + "version": "1.1.6", + "vcsRevision": "bb647e1ca21af25ffdc423bcb96feeeeae963ca2", + "url": "https://github.com/treeform/jsony", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "b28964a93a3cf7248126ba39047593cd63a3aa6d" + } + }, + "nimsimd": { + "version": "1.3.2", + "vcsRevision": "3f6b2668ffb0867d0bf786a658b817763e611350", + "url": "https://github.com/guzba/nimsimd", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "5202ce48d46eaf593da54e884774cdb2a884e717" + } + }, + "crunchy": { + "version": "0.1.11", + "vcsRevision": "98eb6526982bb8aae8eec6e8781f4539fa19e049", + "url": "https://github.com/guzba/crunchy", + "downloadMethod": "git", + "dependencies": [ + "nim", + "nimsimd" + ], + "checksums": { + "sha1": "d34f03fc0f6876dbf53f99601096728ec31f47a3" + } + }, + "markdown": { + "version": "0.8.8", + "vcsRevision": "5a7a7bafd1da23b25332316a7b888e6586f4177a", + "url": "https://github.com/soasme/nim-markdown", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "a59d1205efe2e0bbc3657481e188ce7e7de3d943" + } + }, + "nimib": { + "version": "0.4.1", + "vcsRevision": "99ac3477f6a9d421ea65aeda1c9682d343c5bc35", + "url": "https://github.com/pietroppeter/nimib", + "downloadMethod": "git", + "dependencies": [ + "nim", + "fusion", + "markdown", + "parsetoml", + "jsony" + ], + "checksums": { + "sha1": "08d25173ed4987eb7e65472dad37f3a2671783c0" + } + }, + "nimibook": { + "version": "0.4.0", + "vcsRevision": "b02b02f3ddce3c5f765b1ef274115a689c6ecf9f", + "url": "https://github.com/pietroppeter/nimibook", + "downloadMethod": "git", + "dependencies": [ + "nim", + "nimib", + "jsony" + ], + "checksums": { + "sha1": "5db15f36d37ea935e9f4bf4dd5ceff0110b274d8" + } + }, + "cdt": { + "version": "0.1.1", + "vcsRevision": "2437955da338f409aaa762596d686975b06eeb8e", + "url": "https://github.com/HugoGranstrom/cdt", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "195f0270aaf5d363925f7fdf8a4cc125e4832417" + } + }, + "dotenv": { + "version": "2.0.2", + "vcsRevision": "a3c6726147276ea1447dee292fd27bb036242b78", + "url": "https://github.com/euantorano/dotenv.nim", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "1e70fc63c286ca3da7592d61dbe501fcea35bc72" + } + }, + "untar": { + "version": "0.1.0", + "vcsRevision": "b49f6ac94974fe11cb3d396a8a9c533824a497a7", + "url": "https://github.com/dom96/untar", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "ceb12634783156ddd511410242dc7855ae2f4a14" + } + }, + "ws": { + "version": "0.6.0", + "vcsRevision": "c9c0c7b51e2e83cc9305a895a0b144a297b4bea8", + "url": "https://github.com/treeform/ws", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "b854365c3c985dc6be7cf36337aa0d4dce7e1f33" + } + }, + "karax": { + "version": "1.5.0", + "vcsRevision": "a1eaaa87af756c21db4524c38cad4a004218f740", + "url": "https://github.com/karaxnim/karax/", + "downloadMethod": "git", + "dependencies": [ + "nim", + "ws", + "dotenv" + ], + "checksums": { + "sha1": "58dfc7a459d631d0416b3dd43609ce6bc4b96c92" + } + }, + "nimblas": { + "version": "0.3.1", + "vcsRevision": "93ffdd705496990983eefa0507d52f6a6c533ca7", + "url": "https://github.com/andreaferretti/nimblas", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "e1ecdea4bb8176f12d66efd4aa0c7b3bea970027" + } + }, + "arraymancer": { + "version": "0.7.33", + "vcsRevision": "873ac940bd5df50e1f7d587a91eeb7cf4ebf4a7e", + "url": "https://github.com/mratsim/Arraymancer", + "downloadMethod": "git", + "dependencies": [ + "nim", + "nimblas", + "nimlapack", + "nimcuda", + "nimcl", + "clblast", + "stb_image", + "zip", + "untar" + ], + "checksums": { + "sha1": "c37fb5d98fce8661ade439d89d0a6a3c9d65c8fc" + } + }, + "polynumeric": { + "version": "0.2.1", + "vcsRevision": "c45ae36b3c40c3c332bcf159a6ed21ae53aab66e", + "url": "https://github.com/SciNim/polynumeric", + "downloadMethod": "git", + "dependencies": [ + "nim", + "arraymancer" + ], + "checksums": { + "sha1": "25d14a718148352a3ab9db4dc8b53bf73dc669ab" + } + }, + "scinim": { + "version": "0.2.5", + "vcsRevision": "67207e89a11a62ceb671da45e8032039f20eef12", + "url": "https://github.com/SciNim/scinim", + "downloadMethod": "git", + "dependencies": [ + "nim", + "threading", + "arraymancer", + "polynumeric", + "nimpy" + ], + "checksums": { + "sha1": "123625cbd61116b14d229ace3cd62269e4b63f7e" + } + }, + "numericalnim": { + "version": "0.8.10", + "vcsRevision": "5156285dc74bfd994627e2dc451632164b6b0632", + "url": "https://github.com/SciNim/numericalnim/", + "downloadMethod": "git", + "dependencies": [ + "nim", + "arraymancer", + "cdt" + ], + "checksums": { + "sha1": "6c968fec52347dc351d6e376a076fa02c876bb9e" + } + }, + "datamancer": { + "version": "0.5.1", + "vcsRevision": "ea8fa6cacd158b7e2ff9116521e0a5ee3aadc7d2", + "url": "https://github.com/SciNim/datamancer", + "downloadMethod": "git", + "dependencies": [ + "nim", + "seqmath", + "arraymancer" + ], + "checksums": { + "sha1": "c54db7077924522db8af5fe74f0bb850285332c6" + } + }, + "zippy": { + "version": "0.10.19", + "vcsRevision": "bcb8c1e1be6abb0a0e35a3c6040cdd9391cc993f", + "url": "https://github.com/guzba/zippy", + "downloadMethod": "git", + "dependencies": [ + "nim" + ], + "checksums": { + "sha1": "706d8c10778f32d28b060dbcc84143ca4bfb9bcd" + } + }, + "pixie": { + "version": "6.1.0", + "vcsRevision": "de230f6d061d0b6d6288fc7988de753f22cdd366", + "url": "https://github.com/treeform/pixie", + "downloadMethod": "git", + "dependencies": [ + "nim", + "vmath", + "chroma", + "zippy", + "flatty", + "nimsimd", + "bumpy", + "crunchy" + ], + "checksums": { + "sha1": "c55039a4ec400a6197b12c6c645dcb8bef45c019" + } + }, + "ginger": { + "version": "0.3.13", + "vcsRevision": "ca471eaea4393bfd65e1b04e20c0e9b4873d366f", + "url": "https://github.com/Vindaar/ginger", + "downloadMethod": "git", + "dependencies": [ + "nim", + "chroma", + "seqmath", + "cairo", + "latexdsl", + "pixie", + "shell", + "fontim" + ], + "checksums": { + "sha1": "4f7c989ddb9489d39d7c81bf5a6966d603cf3a60" + } + }, + "ggplotnim": { + "version": "0.5.6", + "vcsRevision": "6e0d6c320725e2a5a8c753663e9d0176eb0665cd", + "url": "https://github.com/Vindaar/ggplotnim", + "downloadMethod": "git", + "dependencies": [ + "nim", + "seqmath", + "ginger", + "datamancer", + "arraymancer", + "shell", + "webview", + "scinim" + ], + "checksums": { + "sha1": "8d2415726a676f313147da26e8c021f583007d55" + } + } + }, + "tasks": {} +} diff --git a/nimiSlides.nimble b/nimiSlides.nimble index f528715..97bde61 100644 --- a/nimiSlides.nimble +++ b/nimiSlides.nimble @@ -1,6 +1,6 @@ # Package -version = "0.2.6" +version = "0.4.0" author = "Hugo Granström" description = "Reveal.js theme for nimib" license = "MIT" @@ -8,13 +8,19 @@ srcDir = "src" # Dependencies -requires "nim >= 1.4.0" -requires "nimib >= 0.3.9" +requires "nim >= 2.0.0" +requires "nimib >= 0.4.1" + +dev: + requires "ggplotnim == 0.5.6" + requires "karax" + requires "numericalnim >= 0.8.9" + requires "nimibook >= 0.4.0" import os task docsDeps, "install dependencies required to build docs": - exec "nimble -y install ggplotnim@0.5.6 karax numericalnim nimibook@#head" + exec "nimble -y install ggplotnim@0.5.6 karax numericalnim nimibook@0.4.0" task buildDocs, "build all .nim files in docsrc/": for path in ["showcase.nim", "nimconf2022.nim", "miscSlides.nim", "index_old.nim", "fragments.nim"]: @@ -31,5 +37,5 @@ task buildBook, "Builds the nimiBook docs": selfExec(" r nbook.nim build") task docs, "Generate automatic docs": - exec "nim doc --project --index:on --git.url:https://github.com/HugoGranstrom/nimiSlides --git.commit:main --outdir:docs/docs src/nimiSlides.nim" + selfExec " doc --project --index:on --git.url:https://github.com/HugoGranstrom/nimiSlides --git.commit:main --outdir:docs/docs src/nimiSlides.nim" diff --git a/src/nimiSlides.nim b/src/nimiSlides.nim index a0e8802..8927b19 100644 --- a/src/nimiSlides.nim +++ b/src/nimiSlides.nim @@ -1,4 +1,4 @@ -import std/[strutils, strformat, sequtils, os] +import std/[strutils, strformat, sequtils, os, json] export os import nimib import nimib/[capture, config] @@ -28,6 +28,10 @@ type highlightCurrentGreen = "highlight-current-green" highlightCurrentBlue = "highlight-current-blue" + FragmentItem* = object + classStr: string + fragIndex: int + SlidesTheme* = enum Black, Beige, Blood, Dracula, League, Moon, Night, Serif, Simple, Sky, Solarized, White @@ -56,198 +60,278 @@ proc slideOptions*(autoAnimate = false, iframeInteractive = true, colorBackgroun const reveal_version* = "5.0.4" -const document = """ - - - {{> head}} - - {{> main}} - - -""" - -const head = """ - - - {{> revealCSS }} - {{#nb_style}} - - {{/nb_style}} - -""" - -const main = """ +func revealMainToHtml*(doc: NbDoc, nb: Nb): string = + let docJson = %[] # it's unused + let renderedBlocks = nbContainerToHtml(doc, nb) + result = withNewlines: + hlHtmlF"""
- {{#blocks}} - {{&.}} - {{/blocks}} -
- {{#revealFooter}} - - {{/revealFooter}}
-{{> revealJS }} - -""" - -const revealCSS = """ - - - - -""" - -const revealJS = """ - - - -{{#latex}} - -{{/latex}} + """ + nb.renderPartial("revealJS", docJson) + "" + +func revealNbDocToHtml*(blk: NbBlock, nb: Nb): string = + let doc = blk.NbDoc + let docJson = %[] # it's unused + result = withNewlines: + "" + """""" + nb.renderPartial("head", docJson) + "" + revealMainToHtml(doc, nb) + "" + "" + +func revealHeadToHtml*(blk: JsonNode, nb: Nb): string = + let nbStyle = nb.doc.context{"nb_style"}.getStr + result = withNewLines: + "" + """""" + nb.renderPartial("revealCSS", blk) + if nbStyle.len > 0: + fmt""" + + """ + "" + +func revealCSSToHtml*(blk: JsonNode, nb: Nb): string = + let revealVersion = nb.doc.context{"reveal_version"}.getStr + let slidesTheme = nb.doc.context{"slidesTheme"}.getStr + result = hlHtmlF""" + + + """ -proc useLocalReveal*(nb: var NbDoc, path: string) = - let path = nb.homeDir.string / path - let themeString = "{{{slidesTheme}}}" - nb.partials["revealCSS"] = fmt""" +func revealJSToHtml*(blk: JsonNode, nb: Nb): string = + let revealVersion = nb.doc.context{"reveal_version"}.getStr + result = withNewLines: + hlHtmlF""" + + + + """ + if nb.doc.context{"latex"}.getBool: + hlHtmlF"""""" + +func localRevealCss*(blk: JsonNode, nb: Nb): string = + {.cast(noSideEffect).}: + let path = nb.doc.homeDir.string / nb.doc.context{"local_reveal_path"}.getStr + result = fmt""" - + """ - - let latexStart = "{{#latex}}" - let latexEnd = "{{/latex}}" - nb.partials["revealJS"] = fmt""" + +func localRevealJs*(blk: JsonNode, nb: Nb): string = + {.cast(noSideEffect).}: + let path = nb.doc.homeDir.string / nb.doc.context{"local_reveal_path"}.getStr + result = withNewlines: + fmt""" -{latexStart} - -{latexEnd} - """ + """ + if nb.doc.context{"latex"}.getBool(true): + fmt"""""" + +func nimiSlidesNbCodeSourcePartial*(blk: JsonNode, nb: Nb): string = + let code = blk{"code"}.getStr + if code.len > 0: + &"
{code.highlightNim}
" + else: + "" + +func nimiSlidesNbCodeOutputPartial*(blk: JsonNode, nb: Nb): string = + let output = blk{"output"}.getStr + if output.len > 0: + #&"
{output}
" + &"
{output}
" + else: + "" + +newNbBlock(NbAnimateCode of NbCode): + highlightedLines: seq[seq[int]] + toHtml: + withNewLines: + nb.renderPartial("animateCodeSource", jsonutils.toJson(blk)) + nbContainerToHtml(blk, nb) + nb.renderPartial("nbCodeOutput", jsonutils.toJson(blk)) + +# "
{{&codeHighlighted}}
\n" & nb.backend.partials["nbCodeOutput"] +func highlightedLinesToString*(lines: seq[seq[int]]): string = + var linesString: string + if lines.len > 0: + linesString &= "|" + for lineBundle in lines: + for line in lineBundle: + linesString &= $line & "," + linesString &= "|" + if lines.len > 0: + linesString = linesString[0 .. ^3] + return linesString + +func nimiSlidesAnimateCodeSourcePartial*(blk: JsonNode, nb: Nb): string = + let highlightedLinesString = blk{"highlightedLines"}.to(seq[seq[int]]).highlightedLinesToString() + result = nimiSlidesNbCodeSourcePartial(blk, nb).replace("data-line-numbers", &"data-line-numbers=\"{highlightedLinesString}\"") + +newNbBlock(NbSlide of NbContainer): + options: SlideOptions + slideNumber: int + toHtml: + withNewLines: + nb.renderPartial("slideStart", jsonutils.toJson(blk)) + nbContainerToHtml(blk, nb) + nb.renderPartial("slideEnd", jsonutils.toJson(blk)) + +proc slideOptionsToAttributes*(options: SlideOptions, slideNumber: int): string = + result.add """data-nimib-slide-number="$1" """ % [$slideNumber] + if options.autoAnimate: + result.add "data-auto-animate " + if options.colorBackground.len > 0: + result.add """data-background-color="$1" """ % [options.colorBackground] + elif options.imageBackground.len > 0: + result.add """data-background-image="$1" """ % [options.imageBackground] + elif options.videoBackground.len > 0: + result.add """data-background-video="$1" """ % [options.videoBackground] + elif options.iframeBackground.len > 0: + result.add """data-background-iframe="$1" """ % [options.iframeBackground] + if options.iframeInteractive: + result.add "data-background-interactive " + elif options.gradientBackground.len > 0: + result.add """data-background-gradient="$1" """ % [options.gradientBackground] + +func nimiSlidesSlideStartPartial*(blk: JsonNode, nb: Nb): string = + let optionsStr = blk{"options"}.to(SlideOptions).slideOptionsToAttributes(blk{"slideNumber"}.getInt) + result = &"
" + +func nimiSlidesSlideEndPartial*(blk: JsonNode, nb: Nb): string = + "
" + +newNbBlock(NbFragment of NbContainer): + fragments: seq[FragmentItem] + toHtml: + withNewLines: + nb.renderPartial("fragmentStart", jsonutils.toJson(blk)) + nbContainerToHtml(blk, nb) + nb.renderPartial("fragmentEnd", jsonutils.toJson(blk)) + +func nimiSlidesFragmentStartPartial*(blk: JsonNode, nb: Nb): string = + if blk{"fragments"}.len > 0: + result = "" + for fragment in blk{"fragments"}: + let classStr = fragment{"classStr"}.getStr + let fragIndex = fragment{"fragIndex"}.getInt + result &= hlHtmlF""" +
+ """ + result &= "\n" + else: + result = "" + +func nimiSlidesFragmentEndPartial*(blk: JsonNode, nb: Nb): string = + "
\n".repeat(blk{"fragments"}.len) + +newNbBlock(NbBigText of NbText): + toHtml: + withNewlines: + "

" + nb.renderPartial("nbText", jsonutils.toJson(blk)) + "

" + +func useLocalReveal*(nb: var Nb, path: string) = + nb.doc.context["local_reveal_path"] = %path + nb.backend.partials["revealCSS"] = localRevealCss + nb.backend.partials["revealJS"] = localRevealJs template setSlidesTheme*(theme: SlidesTheme) = - nb.context["slidesTheme"] = ($theme).toLower + nb.doc.context["slidesTheme"] = %($theme).toLower template useScrollWheel*() = ## Enable using the scroll-wheel to step forward in slides. - nb.context["useScrollWheel"] = true + nb.doc.context["useScrollWheel"] = %true template showSlideNumber*() = - nb.context["showSlideNumber"] = true + nb.doc.context["showSlideNumber"] = %true template disableVerticalCentering*() = - nb.context["disableCentering"] = true + nb.doc.context["disableCentering"] = %true template useScrollView*() = - nb.context["useScrollView"] = true + nb.doc.context["useScrollView"] = %true -proc addStyle*(doc: NbDoc, style: string) = - doc.context["nb_style"] = doc.context["nb_style"].vString & "\n" & style +proc addStyle*(nb: var Nb, style: string) = + nb.doc.context["nb_style"] = %(nb.doc.context{"nb_style"}.getStr & "\n" & style) -proc revealTheme*(doc: var NbDoc) = - doc.partials["document"] = document - doc.partials["head"] = head - doc.partials["main"] = main - doc.partials["nbCodeSource"] = "
{{&codeHighlighted}}
" - doc.partials["nbCodeOutput"] = "{{#output}}
{{output}}
{{/output}}" +proc populateNimiSlidesBlockPartials*(nb: var Nb) = + nb.backend.partials["nbCodeSource"] = nimiSlidesNbCodeSourcePartial + nb.backend.partials["nbCodeOutput"] = nimiSlidesNbCodeOutputPartial - doc.partials["revealCSS"] = revealCSS - doc.partials["revealJS"] = revealJS + nb.backend.partials["animateCodeSource"] = nimiSlidesAnimateCodeSourcePartial - doc.partials["animateCode"] = "
{{&codeHighlighted}}
\n" & doc.partials["nbCodeOutput"] - doc.renderPlans["animateCode"] = doc.renderPlans["nbCode"] + nb.backend.partials["revealCSS"] = revealCSSToHtml + nb.backend.partials["revealJS"] = revealJSToHtml - doc.partials["fragmentStart"] = """ -{{#fragments}} -
-{{/fragments}} - """ + nb.backend.partials["slideStart"] = nimiSlidesSlideStartPartial + nb.backend.partials["slideEnd"] = nimiSlidesSlideEndPartial - doc.partials["fragmentEnd"] = """ -{{#fragments}} -
-{{/fragments}} - """ + nb.backend.partials["fragmentStart"] = nimiSlidesFragmentStartPartial + nb.backend.partials["fragmentEnd"] = nimiSlidesFragmentEndPartial - doc.partials["bigText"] = """

{{&outputToHtml}}

""" - doc.renderPlans["bigText"] = doc.renderPlans["nbText"] +proc revealTheme*(nb: var Nb) = + nb.backend.funcs["NbDoc"] = revealNbDocToHtml + nb.backend.partials["head"] = revealHeadToHtml + + nb.populateNimiSlidesBlockPartials() - doc.context["slidesTheme"] = "black" - doc.context["nb_style"] = "" - doc.context["reveal_version"] = reveal_version + nb.doc.context["slidesTheme"] = %"black" + nb.doc.context["nb_style"] = %"" + nb.doc.context["reveal_version"] = %reveal_version try: - let slidesConfig = loadTomlSection(doc.rawCfg, "nimislides", NimiSlidesConfig) + let slidesConfig = loadTomlSection(nb.doc.rawCfg, "nimislides", NimiSlidesConfig) if slidesConfig.localReveal != "": echo "Using local Reveal.js installation specified in nimib.toml " - doc.useLocalReveal(slidesConfig.localReveal) + nb.useLocalReveal(slidesConfig.localReveal) except CatchableError: discard # if it doesn't exists, just let it be var currentFragment*, currentSlideNumber*: int -proc slideOptionsToAttributes*(options: SlideOptions): string = - result.add """data-nimib-slide-number="$1" """ % [$currentSlideNumber] - if options.autoAnimate: - result.add "data-auto-animate " - if options.colorBackground.len > 0: - result.add """data-background-color="$1" """ % [options.colorBackground] - elif options.imageBackground.len > 0: - result.add """data-background-image="$1" """ % [options.imageBackground] - elif options.videoBackground.len > 0: - result.add """data-background-video="$1" """ % [options.videoBackground] - elif options.iframeBackground.len > 0: - result.add """data-background-iframe="$1" """ % [options.iframeBackground] - if options.iframeInteractive: - result.add "data-background-interactive " - elif options.gradientBackground.len > 0: - result.add """data-background-gradient="$1" """ % [options.gradientBackground] - -template slide*(options: untyped, body: untyped): untyped = +template slide*(toptions: untyped, body: untyped): untyped = currentSlideNumber += 1 - - nbRawHtml: "
" % [slideOptionsToAttributes(options)] + let blk = newNbSlide(slideNumber=currentSlideNumber, options=toptions) + when declaredInScope(CountVarNimiSlide): when CountVarNimiSlide < 2: static: inc CountVarNimiSlide - body + nb.withContainer(blk): + body static: dec CountVarNimiSlide else: {.error: "You can only nest slides once!".} else: var CountVarNimiSlide {.inject, compileTime.} = 1 # we just entered the first level - body + nb.withContainer(blk): + body static: dec CountVarNimiSlide - nbRawHtml: "
" + nb.add blk template slide*(body: untyped) = slide(slideOptions()): @@ -257,6 +341,23 @@ template slideAutoAnimate*(body: untyped) = slide(slideOptions(autoAnimate=true)): body +template fragmentCoreOld*(animations: openArray[seq[FragmentAnimation]], endAnimations: openArray[seq[FragmentAnimation]], indexOffset: untyped, incrementCounter: untyped, body: untyped) = + ## Creates a fragment of the content of body. Nesting works. + ## animations: each seq in animations are animations that are to be applied at the same time. The first seq's animations + ## are applied on the first button click, and the second seq's animations on the second click etc. + ## endAnimations: animations that should be applied AT THE END of block. + ## Example: + ## `fragment(@[@[fadeIn, highlightBlue], @[shrinks, semiFadeOut]]): block` will at the first click of a button fadeIn and highlightBlue + ## the content of the block. At the second click the same content will shrink and semiFadeOut. This code is also equivilent with + ## `fragment(@[@[fadeIn, highlightBlue]]): fragment(@[@[shrinks, semiFadeOut]]): block`. + ## `fragment(@[@[fadeIn]], @[@[fadeOut]]): block` will first fadeIn the entire block and perform eventual animations in nested fragments. Once + ## all of those are finished, it will run fadeOut on the entire block and its subfragments. + var fragments: seq[Table[string, string]] + fragmentStartBlock(fragments, animations, endAnimations, indexOffset, incrementCounter) + var startBlock = nb.blk # this *should* be the block created by fragmentStartBlock + body + fragmentEndBlock(fragments, animations, endAnimations, startBlock) + template fragmentStartBlock(fragments: seq[Table[string, string]], animations: openArray[seq[FragmentAnimation]], endAnimations: openArray[seq[FragmentAnimation]], indexOffset: int, incrementCounter: bool) = newNbSlimBlock("fragmentStart"): for level in animations: @@ -296,11 +397,21 @@ template fragmentCore*(animations: openArray[seq[FragmentAnimation]], endAnimati ## `fragment(@[@[fadeIn, highlightBlue]]): fragment(@[@[shrinks, semiFadeOut]]): block`. ## `fragment(@[@[fadeIn]], @[@[fadeOut]]): block` will first fadeIn the entire block and perform eventual animations in nested fragments. Once ## all of those are finished, it will run fadeOut on the entire block and its subfragments. - var fragments: seq[Table[string, string]] - fragmentStartBlock(fragments, animations, endAnimations, indexOffset, incrementCounter) - var startBlock = nb.blk # this *should* be the block created by fragmentStartBlock - body - fragmentEndBlock(fragments, animations, endAnimations, startBlock) + let blk = newNbFragment() + for level in animations: + if level.len > 1 and fadeIn in level: + # Add a fadeIn fragment at the same frame + blk.fragments.add FragmentItem(classStr: "", fragIndex: currentFragment + indexOffset) + blk.fragments.add FragmentItem(classStr: level.join(" "), fragIndex: currentFragment + indexOffset) + if incrementCounter: + currentFragment += 1 + + withContainer(nb, blk): + body + + for level in endAnimations: + blk.fragments.add FragmentItem(classStr: level.join(" "), fragIndex: currentFragment) + nb.add blk template fragmentCore*(animations: openArray[seq[FragmentAnimation]], endAnimations: openArray[seq[FragmentAnimation]], body: untyped) = fragmentCore(animations, endAnimations, 0, true, body) @@ -400,12 +511,6 @@ template listItem*(animation: FragmentAnimation, body: untyped) = template listItem*(body: untyped) = listItem(fadeInThenSemiOut, body) -template animateCode*(lines: string, body: untyped) = - newNbCodeBlock("animateCode", body): - nb.blk.context["highlightLines"] = lines - captureStdout(nb.blk.output): - body - template animateCode*(lines: varargs[set[range[0..65535]], toSet], body: untyped) = ## Shows code and its output just like nbCode, but highlights different lines of the code in the order specified in `lines`. ## lines: Specify which lines to highlight and in which order. The lines can be specified using either: @@ -417,39 +522,39 @@ template animateCode*(lines: varargs[set[range[0..65535]], toSet], body: untyped ## animateCode(1, 2..3, {4, 6}): body ## ``` ## This will first highlight line 1, then lines 2 and 3, and lastly line 4 and 6. - newNbCodeBlock("animateCode", body): - var linesString: string - if lines.len > 0: - linesString &= "|" - for lineBundle in lines: - for line in lineBundle: - linesString &= $line & "," - linesString &= "|" - if lines.len > 0: - linesString = linesString[0 .. ^3] - nb.blk.context["highlightLines"] = linesString - captureStdout(nb.blk.output): + var highlightedLines: seq[seq[int]] + for line in lines: + var lineSeq: seq[int] + for l in line: + lineSeq.add l + highlightedLines.add lineSeq + let blk = newNbAnimateCode(highlightedLines=highlightedLines) + blk.code = getCode(body) + nb.withContainer(blk): + captureStdout(blk.output): body + nb.add blk -template newAnimateCodeBlock*(cmd: untyped, impl: untyped) = - const cmdStr = astToStr(cmd) - - template `cmd`*(lines: varargs[set[range[0..65535]], toSet], body: untyped) = - newNbCodeBlock(cmdStr, body): - var linesString: string - if lines.len > 0: - linesString &= "|" - for lineBundle in lines: - for line in lineBundle: - linesString &= $line & "," - linesString &= "|" - if lines.len > 0: - linesString = linesString[0 .. ^3] - nb.blk.context["highlightLines"] = linesString - impl(body) - - nb.partials[cmdStr] = nb.partials["animateCode"] - nb.renderPlans[cmdStr] = nb.renderPlans["animateCode"] +template animateCodeSkip*(lines: varargs[set[range[0..65535]], toSet], body: untyped) = + ## Shows code and its output just like nbCode, but highlights different lines of the code in the order specified in `lines`. + ## lines: Specify which lines to highlight and in which order. The lines can be specified using either: + ## - An `int` (highlight single line) + ## - A slice `x..y` (highlight a range of consequative lines) + ## - A set {x, y..z} (highlight any combination of lines) + ## Ex: + ## ```nim + ## animateCode(1, 2..3, {4, 6}): body + ## ``` + ## This will first highlight line 1, then lines 2 and 3, and lastly line 4 and 6. + var highlightedLines: seq[seq[int]] + for line in lines: + var lineSeq: seq[int] + for l in line: + lineSeq.add l + highlightedLines.add lineSeq + let blk = newNbAnimateCode(highlightedLines=highlightedLines) + blk.code = getCode(body) + nb.add blk template typewriter*(textMessage: string, typeSpeed = 50, alignment = "center") = let localText = textMessage @@ -458,23 +563,29 @@ template typewriter*(textMessage: string, typeSpeed = 50, alignment = "center") # HTML and add eventlistener # check what we get back from reveal's event let fragIndex = currentFragment # important it is before fragmentFadeIn! - let id = "typewriter" & $nb.newId() + let id = "typewriter" & $nb.doc.newId() fragmentFadeIn: - nbKaraxCode(id, localText, fragIndex, speed, align): + nbRawHtml: hlHTml""" +

$3

+ """ % [id, align, localText] + nbJsFromCodeOwnFile(id, localText, fragIndex, speed, align): + import std / [dom] import nimiSlides/revealFFI - import karax / vstyles var i = 0 var timeout: Timeout proc typewriterLocal() = echo "Typing ", fragindex var el = getElementById(id.cstring) if i < localText.len: - el.innerHtml &= $localText[i] + var c = localText[i] + let s = + if c == '\n': + "
" + else: + $c + el.innerHtml &= s inc i timeout = setTimeout(typewriterLocal, speed) - karaxHtml: - p(id = id, style=style(textAlign, align.kstring)): - text localText.cstring window.addEventListener("load", proc (event: Event) = echo "Loading ", fragIndex @@ -504,9 +615,9 @@ template typewriter*(textMessage: string, typeSpeed = 50, alignment = "center") discard )) -template bigText*(text: string) = - newNbSlimBlock("bigText"): - nb.blk.output = text +template bigText*(ttext: string) = + let blk = newNbBigText(text=ttext) + nb.add blk template fitImage*(src: string) = nbRawHtml: hlHtml"""""" % [src] @@ -519,47 +630,40 @@ template speakerNote*(text: string) = """ % [markdown(text)] template align*(text: string, body: untyped) = - nbRawHtml: """ -
-""" % text - body - nbRawHtml: "
" + nbDiv(styles="text-align: $1;" % text, classes=""): + body #templates can't have default args and untyped args at the same time #so we use overloading to get the same effect template columns*(columnGap: float, body: untyped) = #tempted to use fmt"", but strformat doesn't support template args in the format string - nbRawHtml: """
- """ % $columnGap - body - nbRawHtml: "
" + nbDiv(styles="display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); overflow-wrap: break-word; column-gap: $1 em;" % $columnGap, classes=""): + body template columns*(body: untyped) = columns(1.0,body) template adaptiveColumns*(columnGap: float, body: untyped) = - nbRawHtml: """
- """ % $columnGap - body - nbRawHtml: "
" + nbDiv(styles="display: grid; grid-auto-flow: column; overflow-wrap: break-word; column-gap: $1 em;" % $columnGap, classes=""): + body + template adaptiveColumns*(body: untyped) = adaptiveColumns(1.0,body) template column*(bodyInner: untyped) = ## column should always be used inside a `columns` block - nbRawHtml: "
" - bodyInner - nbRawHtml: "
" + nbDiv: + bodyInner template footer*(text: string, fontSize: int = 20, opacity: range[0.0 .. 1.0] = 0.6, rawHtml = false) = - nb.context["footerFontSize"] = fontSize - nb.context["footerOpacity"] = opacity + nb.doc.context["footerFontSize"] = %fontSize + nb.doc.context["footerOpacity"] = %opacity if rawHtml: - nb.context["revealFooter"] = text + nb.doc.context["revealFooter"] = %text else: - nb.context["revealFooter"] = markdown(text, config=initGfmConfig()).dup(removeSuffix) + nb.doc.context["revealFooter"] = %markdown(text, config=initGfmConfig()).dup(removeSuffix) nbJsFromCodeGlobal: import nimiSlides/revealFFI @@ -602,7 +706,7 @@ template cornerImage*(image: string, corner: Corner, size: int = 100, animate = "transition: all 0.2s ease-out;" else: "" - let id = "cornerImage-" & $nb.newId() + let id = "cornerImage-" & $nb.doc.newId() let html = &"""""" % [image, id, $size, vertical, horizontal, animateString] let currentSlideNr = currentSlideNumber diff --git a/src/nimiSlides/autoAnimation.nim b/src/nimiSlides/autoAnimation.nim index e866205..87a3572 100644 --- a/src/nimiSlides/autoAnimation.nim +++ b/src/nimiSlides/autoAnimation.nim @@ -2,11 +2,14 @@ import std/[strutils] import nimib import ./[conversions] -template autoAnimateSlides*(nSlides: int, body: untyped) = +template autoAnimateSlidesCustom*(slideTemplate: untyped, nSlides: int, body: untyped) = for autoAnimateCounter {.inject.} in 1 .. nSlides: - slide(slideOptions(autoAnimate=true)): + slideTemplate(slideOptions(autoAnimate=true)): body +template autoAnimateSlides*(nSlides: int, body: untyped) = + autoAnimateSlidesCustom(slide, nSlides, body) + template showAt*(slideNrs: varargs[set[range[0..65535]], toSet], body: untyped) = # how to auto convert to set like in varargs? # use vararg and union all results! # This way you don't need to use the set syntax but can pass in `showOn(1, 2, 3)` instead.