Skip to content

Commit

Permalink
v0.2 - update to recent Nimib (0.2) (#39)
Browse files Browse the repository at this point in the history
* fix error when publishing markdown files
* update to more recent nimib
* add config during init
* update documentation
* will release as a new version
  • Loading branch information
pietroppeter authored Nov 6, 2021
1 parent aadbc09 commit 728af92
Show file tree
Hide file tree
Showing 14 changed files with 84 additions and 93 deletions.
49 changes: 32 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,43 +24,58 @@ nimibook currently provides minimal functionality to create a book and support a

## Installation

To install Nimibook simply use : ``nimble install nimibook``
To install Nimibook simply use : `nimble install nimibook`

## Usage

1. Write your content using [nimib] or simple markdown files in the ``book`` folder.
1. Write your content using [nimib] or simple markdown files in the `book` folder.
The basic template for an empty page is:
```nim
import nimib, nimibook
nbInit(theme = useNimibook)
# content here
nbSave
```

2. Use the Table of Content (ToC) DSL to link chapters to content in ``nbook.nim``.
2. Use the Table of Content (ToC) DSL to link chapters to content in `nbook.nim`.
Example :
```nim
import nimibook
var book = newBookFromToc("Dummy Book", "book"): # Create a new book called "Dummy", whose content is in the folder "book"
section("Dummy", "index"): # Create a new section called "Dummy", its content is the file "index.nim". Notice how the .nim extensions is optionnal
entry("Simple example", "page_1.nim") # Create a new entry called "Simple example", its content is the file "page_1.nim"
# Create a new book called "Dummy", whose content is in the folder "book"
var book = newBookFromToc("Dummy Book", "book"):
# Create a new section called "Dummy", its content is the file "index.nim"
section("Dummy", "index"): # Note how the .nim extensions is optional
# Create a new entry called "Simple example", its content is the file "page_1.nim"
entry("Simple example", "page_1.nim")
# access to nimibook cli which will allow to build the book
nimibookCli(book)
```
See [nimibook] or [Nimibook repo](https://github.com/pietroppeter/nimibook
) for more documentations and examples.

3. Generate your very own CLI tools or use Nimble tasks with ``nim c -d:release nbook.nim``.
* ``./nbook init`` to init your book structure. **This command must be ran at least once**.
* ``./nbook build`` to build your book.
3. Generate your very own CLI tools or use Nimble tasks with `nim c -d:release nbook.nim`.
* `./nbook init` to init your book structure. **This command must be ran at least once**.
* `./nbook build` to build your book.

4. Whenever your Table of Content changes (add/remove files, changes sections organization), recompile your ``nbook`` and run the ``build`` command : ``nim c -d:release nbook.nim && ./nbook build``
* It is also doable in one command : ``nim r -d:release nbook.nim build``
* You don't need to call the ``init`` command again.
* Rinse and repeat until your ToC is done ! Then you can just edit files and call ``build`` without recompiling.
4. Whenever your Table of Content changes (add/remove files, changes sections organization), recompile your `nbook` and run the `build` command : `nim c -d:release nbook.nim && ./nbook build`
* It is also doable in one command : `nim r -d:release nbook.nim build`
* You don't need to call the `init` command again.
* Rinse and repeat until your ToC is done ! Then you can just edit files and call `build` without recompiling.

## Tips and Tricks

* to build a single page (e.g. `book/mypage.nim`) run first `./nbook dump`
(which dumps a `book.json` file that contains a table of contents and other context data).
If `book.json` is present, then you can build your page with: `nim r book/mypage.nim`
* Each book requires its own ToC and thus will be its own CLI Apps
* ``nbook.nim`` is the default name used - it is possible to use another name.
* Multiple books ``nbook.nim`` cannot share the same folder. Instead, either split them into two separate books, or merge them into one.
* `nbook.nim` is the default name used - it is possible to use another name.
* Multiple books `nbook.nim` cannot share the same folder. Instead, either split them into two separate books, or merge them into one.
* Some commands :
* ``./nbook clean`` will remove generated files and restart from a clean state.
* ``./nbook update`` will update assets and mustache template.
* `./nbook clean` will remove generated files and restart from a clean state.
* `./nbook update` will update assets and mustache template.
* These two commands will modify installed files, use them with caution if you customized files locally.

### Analytics
Expand Down
3 changes: 1 addition & 2 deletions book/configuration.nim
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import nimib, nimibook
import std / [os, strutils, strscans, strformat]

nbInit
nbUseNimibook
nbInit(theme = useNimibook)

# the following is very dependent on how source is written
proc readBookConfigFields: seq[string] =
Expand Down
3 changes: 1 addition & 2 deletions book/content.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import nimib, nimibook
nbInit
nbUseNimibook
nbInit(theme = useNimibook)

nbText: """
# Content
Expand Down
3 changes: 1 addition & 2 deletions book/index.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import nimib, nimibook
import strutils
nbInit
nbUseNimibook # overrides nimib defaults with nimibooks and loads book configuration
nbInit(theme = useNimibook)

proc readFileUntil(filename: string, text: string): string =
for line in filename.lines:
Expand Down
3 changes: 1 addition & 2 deletions book/tasks.nim
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import nimib, nimibook
import osproc, sugar, strutils, strformat

nbInit
nbUseNimibook
nbInit(theme = useNimibook)

var tasks: string
withDir("..".AbsoluteDir):
Expand Down
4 changes: 2 additions & 2 deletions book/tocdsl.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import nimib, nimibook
nbInit
nbUseNimibook

nbInit(theme = useNimibook)

nbText: """
# Table of Contents DSL
Expand Down
3 changes: 3 additions & 0 deletions examples/nimib.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[nimib]
srcDir = "book"
homeDir = "docs"
3 changes: 3 additions & 0 deletions nimib.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[nimib]
srcDir = "book"
homeDir = "docs"
4 changes: 2 additions & 2 deletions nimibook.nimble
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package

version = "0.1.0"
version = "0.2.0"
author = "Pietro Peterlongo"
description = "A port of mdbook to nim"
license = "MIT"
Expand All @@ -10,7 +10,7 @@ srcDir = "src"
# Dependencies

requires "nim >= 1.4.0"
requires "nimib >= 0.1.3 & < 0.2"
requires "nimib >= 0.2"
requires "jsony >= 1.0.3"

import os
Expand Down
2 changes: 1 addition & 1 deletion src/nimibook.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import nimibook / [types, render, tocs, publishers, defaults, docs, books]
export types, render, tocs, publishers, defaults, docs, books

template nbUseNimibook* =
nbDoc.useNimibook
nb.useNimibook

proc printHelp() =
echo """
Expand Down
15 changes: 13 additions & 2 deletions src/nimibook/books.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ proc cleanRootFolder(book: Book) =
for f in walkDirRec(book.toc.path):
let ext = f.splitFile().ext
if f notin srcurls and ext != ".mustache" and ext != ".nims" and ext != ".cfg" and not f.contains(".git"):
# debugEcho(" >> removeFile ", f)
echo "[nimibook] remove file: ", f
removeFile(f)

proc shouldDelete(book: Book, dir, f: string): bool =
Expand All @@ -51,7 +51,7 @@ proc cleanDocFolder(book: Book) =
# debugEcho("walkDirRec ", docDir)
for f in walkDirRec(docDir):
if shouldDelete(book, docDir, f):
# debugEcho(" >> removeFile ", f)
echo "[nimibook] remove file: ", f
removeFile(f)

for f in walkDirRec(docDir, yieldFilter = {pcDir}):
Expand Down Expand Up @@ -90,7 +90,18 @@ proc initBookFile(book: Book) =
echo "[nimibook] creating file ", f
file.close()

proc addConfig() =
const cfg = """
[nimib]
srcDir = "book"
homeDir = "docs"
"""
if not fileExists("nimib.toml"):
echo "[nimibook] adding nimib.toml"
writeFile("nimib.toml", cfg)

proc init*(book: Book) =
addConfig()
populateAssets(book.toc.path, false)
initBookFile(book)

Expand Down
66 changes: 19 additions & 47 deletions src/nimibook/docs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,37 @@ import std / [strutils, os, enumerate]
import nimib, nimib / paths
import nimibook / [types, books, entries, render]

proc useNimibook*(nbDoc: var NbDoc) =
# Between separate process variable env do not gets passed so I use this little trick.
# This means :
# Nim Files in books are not meant to be compiled indiviually
# But you can do so with -d:nimibSrcDir=... option passed manually
const nimibSrcDir {.strdefine.} = currentSourcePath()
var pathSrcDir = ""
if existsEnv("nimibSrcDir"):
pathSrcDir = getEnv("nimibSrcDir")
else:
pathSrcDir = nimibSrcDir

# path handling (fix upstream in nimib)
let
nbThisFile = changeFileExt(nbDoc.filename.AbsoluteFile, ".nim")
thisTuple = nbThisFile.splitFile
# Use non-compile time value; this means it is dependent upon where the binary is called from instead of where it gets compiled

let
nbThisDir = (thisTuple.dir)
nbSrcDir: AbsoluteDir = pathSrcDir.toAbsoluteDir
nbHomeDir: AbsoluteDir = nbSrcDir / RelativeDir("..") / "docs".RelativeDir

# Are these two actually needed? well, home_path is needed in path_to_root, but other than that?
nbDoc.context["here_path"] = (nbThisFile.relativeTo nbSrcDir).string
nbDoc.context["home_path"] = (nbSrcDir.relativeTo nbThisDir).string
nbDoc.filename = relativeTo(changeFileExt(nbThisFile, ".html"), nbSrcDir).string
nbDoc.context["path_to_root"] = nbDoc.context["home_path"].castStr & "/" # I probably should make sure to have / at the end
# debugEcho "Current directory: ", getCurrentDir()
# debugEcho "Output file: ", nbDoc.filename
proc useNimibook*(doc: var NbDoc) =
doc.context["path_to_root"] = doc.homeDirRel.string & "/" # I probably should make sure to have / at the end
doc.context["title"] = doc.thisFileRel.string

# templates are in nbSrcDir
nbDoc.templateDirs = @[nbSrcDir.string]
nbDoc.context["title"] = nbDoc.context["here_path"]
doc.templateDirs = @[doc.srcDir.string]

# Use nbSrcDir instead another relative path
let bookPath = nbSrcDir.string / "book.json"
let bookPath = doc.srcDir.string / "book.json"
# load book object
var book = load(bookPath)

# book configuration
nbDoc.context["language"] = book.language
nbDoc.context["default_theme"] = book.default_theme
nbDoc.context["description"] = book.description
nbDoc.context["favicon_escaped"] = book.favicon_escaped
nbDoc.context["preferred_dark_theme"] = book.preferred_dark_theme
nbDoc.context["theme_option"] = book.theme_option
nbDoc.context["book_title"] = book.book_title
nbDoc.context["git_repository_url"] = book.git_repository_url
nbDoc.context["git_repository_icon"] = book.git_repository_icon
nbDoc.context["plausible_analytics_url"] = book.plausible_analytics_url
doc.context["language"] = book.language
doc.context["default_theme"] = book.default_theme
doc.context["description"] = book.description
doc.context["favicon_escaped"] = book.favicon_escaped
doc.context["preferred_dark_theme"] = book.preferred_dark_theme
doc.context["theme_option"] = book.theme_option
doc.context["book_title"] = book.book_title
doc.context["git_repository_url"] = book.git_repository_url
doc.context["git_repository_icon"] = book.git_repository_icon
doc.context["plausible_analytics_url"] = book.plausible_analytics_url

# process toc
for i, entry in enumerate(book.toc.entries.mitems):
if entry.url == nbDoc.filename.replace('\\', '/'): # replace needed for windows
if entry.url == doc.filename.replace('\\', '/'): # replace needed for windows
entry.isActive = true
if i > 0:
nbDoc.context["previous"] = book.toc.entries[i-1].url
doc.context["previous"] = book.toc.entries[i-1].url
if i < book.toc.entries.high:
nbDoc.context["next"] = book.toc.entries[i+1].url
doc.context["next"] = book.toc.entries[i+1].url
break
nbDoc.partials["toc"] = render book.toc
doc.partials["toc"] = render book.toc
18 changes: 5 additions & 13 deletions src/nimibook/publishers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,16 @@ import nimib
proc nimPublish*(entry: Entry) =
let
cmd = "nim"
# Apparently when used as a binary this generate a process in another shell
# Which means env variable are not going to be available
# So here's a little trick to propagate the info
# See comment in docs.nim useNimibook() proc
nimibSrcDir = getEnv("nimibSrcDir")
nimibOutDir = nimibSrcDir.parentDir() / "docs"
args = ["r", "-d:release", "-f", &"-d:nimibSrcDir={nimibSrcDir}", &"-d:nimibOutDir={nimibOutDir}", "--verbosity:0", "--hints:off", entry.path]
args = ["r", "-d:release", "-f", "--verbosity:0", "--hints:off", entry.path]
debugEcho "[Executing] ", cmd, " ", args.join(" ")
if execShellCmd(cmd & " " & args.join(" ")) != 0:
quit(1)

proc mdPublish*(entry: Entry) =
nbInit
nbDoc.filename = (nbThisDir / ("../../" & entry.path).RelativeDir).string
nbDoc.useNimibook
withDir(nbHomeDir / "..".RelativeDir):
nbText entry.path.readFile
nbInit(theme = useNimibook, thisFileRel = ".." / entry.path) # entry path contains srcDir (why? should fix that!)
nbText nb.source
nbSave
setCurrentDir nbInitDir # reset current directory
setCurrentDir nb.initDir

proc publish*(entry: Entry) =
let splitted = entry.path.splitFile()
Expand All @@ -37,6 +28,7 @@ proc publish*(entry: Entry) =
proc publish*(book: Book) =
dump book
for entry in book.toc.entries:
echo "[nimibook] publish entry: ", entry.path
entry.publish()
cleanjson book
check book
1 change: 0 additions & 1 deletion src/nimibook/tocs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ template newBookFromToc*(booklabel: string, rootfolder: string, body: untyped):
var book = Book(book_title: booklabel)
book.setDefaults
book.path_to_root = rootfolder
putEnv("nimibSrcDir", getCurrentDir() / rootfolder)

var toc = Toc(path: rootfolder)
var levels: seq[int] = @[1]
Expand Down

0 comments on commit 728af92

Please sign in to comment.