Repository: pietroppeter/nimib Branch: main Commit: b8a20221e58e Files: 47 Total size: 77.8 KB Directory structure: gitextract_n9678sdq/ ├── .git/ │ ├── HEAD │ ├── config │ ├── description │ ├── hooks/ │ │ ├── applypatch-msg.sample │ │ ├── commit-msg.sample │ │ ├── fsmonitor-watchman.sample │ │ ├── post-update.sample │ │ ├── pre-applypatch.sample │ │ ├── pre-commit.sample │ │ ├── pre-merge-commit.sample │ │ ├── pre-push.sample │ │ ├── pre-rebase.sample │ │ ├── pre-receive.sample │ │ ├── prepare-commit-msg.sample │ │ ├── push-to-checkout.sample │ │ ├── sendemail-validate.sample │ │ └── update.sample │ ├── index │ ├── info/ │ │ └── exclude │ ├── logs/ │ │ ├── HEAD │ │ └── refs/ │ │ ├── heads/ │ │ │ └── main │ │ └── remotes/ │ │ └── origin/ │ │ └── HEAD │ ├── objects/ │ │ └── pack/ │ │ ├── pack-62e2fb9434711e9a7e8675eb3152bb80cbb84291.idx │ │ ├── pack-62e2fb9434711e9a7e8675eb3152bb80cbb84291.pack │ │ ├── pack-62e2fb9434711e9a7e8675eb3152bb80cbb84291.promisor │ │ ├── pack-62e2fb9434711e9a7e8675eb3152bb80cbb84291.rev │ │ ├── pack-bfc15b21f9bdd2385245f680d4c27a0b69cc2673.idx │ │ ├── pack-bfc15b21f9bdd2385245f680d4c27a0b69cc2673.pack │ │ ├── pack-bfc15b21f9bdd2385245f680d4c27a0b69cc2673.promisor │ │ └── pack-bfc15b21f9bdd2385245f680d4c27a0b69cc2673.rev │ ├── packed-refs │ ├── refs/ │ │ ├── heads/ │ │ │ └── main │ │ └── remotes/ │ │ └── origin/ │ │ └── HEAD │ └── shallow ├── .gitattributes ├── .github/ │ └── workflows/ │ ├── docs.yml │ ├── netlify_build_docs.yml │ ├── netlify_deploy_preview.yml │ ├── netlify_pr_task.yml │ └── test.yml ├── .gitignore ├── CONTRIBUTING.md ├── README.md ├── changelog.md ├── config.nims ├── nimib.nimble └── nimib.toml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .git/HEAD ================================================ ref: refs/heads/main ================================================ FILE: .git/config ================================================ [core] repositoryformatversion = 1 filemode = true bare = false logallrefupdates = true [remote "origin"] url = https://github.com/pietroppeter/nimib tagOpt = --no-tags fetch = +refs/heads/main:refs/remotes/origin/main promisor = true partialclonefilter = blob:limit=1048576 [branch "main"] remote = origin merge = refs/heads/main ================================================ FILE: .git/description ================================================ Unnamed repository; edit this file 'description' to name the repository. ================================================ FILE: .git/hooks/applypatch-msg.sample ================================================ #!/bin/sh # # An example hook script to check the commit log message taken by # applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. The hook is # allowed to edit the commit message file. # # To enable this hook, rename this file to "applypatch-msg". . git-sh-setup commitmsg="$(git rev-parse --git-path hooks/commit-msg)" test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} : ================================================ FILE: .git/hooks/commit-msg.sample ================================================ #!/bin/sh # # An example hook script to check the commit log message. # Called by "git commit" with one argument, the name of the file # that has the commit message. The hook should exit with non-zero # status after issuing an appropriate message if it wants to stop the # commit. The hook is allowed to edit the commit message file. # # To enable this hook, rename this file to "commit-msg". # Uncomment the below to add a Signed-off-by line to the message. # Doing this in a hook is a bad idea in general, but the prepare-commit-msg # hook is more suited to it. # # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" # This example catches duplicate Signed-off-by lines. test "" = "$(grep '^Signed-off-by: ' "$1" | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { echo >&2 Duplicate Signed-off-by lines. exit 1 } ================================================ FILE: .git/hooks/fsmonitor-watchman.sample ================================================ #!/usr/bin/perl use strict; use warnings; use IPC::Open2; # An example hook script to integrate Watchman # (https://facebook.github.io/watchman/) with git to speed up detecting # new and modified files. # # The hook is passed a version (currently 2) and last update token # formatted as a string and outputs to stdout a new update token and # all files that have been modified since the update token. Paths must # be relative to the root of the working tree and separated by a single NUL. # # To enable this hook, rename this file to "query-watchman" and set # 'git config core.fsmonitor .git/hooks/query-watchman' # my ($version, $last_update_token) = @ARGV; # Uncomment for debugging # print STDERR "$0 $version $last_update_token\n"; # Check the hook interface version if ($version ne 2) { die "Unsupported query-fsmonitor hook version '$version'.\n" . "Falling back to scanning...\n"; } my $git_work_tree = get_working_dir(); my $retry = 1; my $json_pkg; eval { require JSON::XS; $json_pkg = "JSON::XS"; 1; } or do { require JSON::PP; $json_pkg = "JSON::PP"; }; launch_watchman(); sub launch_watchman { my $o = watchman_query(); if (is_work_tree_watched($o)) { output_result($o->{clock}, @{$o->{files}}); } } sub output_result { my ($clockid, @files) = @_; # Uncomment for debugging watchman output # open (my $fh, ">", ".git/watchman-output.out"); # binmode $fh, ":utf8"; # print $fh "$clockid\n@files\n"; # close $fh; binmode STDOUT, ":utf8"; print $clockid; print "\0"; local $, = "\0"; print @files; } sub watchman_clock { my $response = qx/watchman clock "$git_work_tree"/; die "Failed to get clock id on '$git_work_tree'.\n" . "Falling back to scanning...\n" if $? != 0; return $json_pkg->new->utf8->decode($response); } sub watchman_query { my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') or die "open2() failed: $!\n" . "Falling back to scanning...\n"; # In the query expression below we're asking for names of files that # changed since $last_update_token but not from the .git folder. # # To accomplish this, we're using the "since" generator to use the # recency index to select candidate nodes and "fields" to limit the # output to file names only. Then we're using the "expression" term to # further constrain the results. my $last_update_line = ""; if (substr($last_update_token, 0, 1) eq "c") { $last_update_token = "\"$last_update_token\""; $last_update_line = qq[\n"since": $last_update_token,]; } my $query = <<" END"; ["query", "$git_work_tree", {$last_update_line "fields": ["name"], "expression": ["not", ["dirname", ".git"]] }] END # Uncomment for debugging the watchman query # open (my $fh, ">", ".git/watchman-query.json"); # print $fh $query; # close $fh; print CHLD_IN $query; close CHLD_IN; my $response = do {local $/; }; # Uncomment for debugging the watch response # open ($fh, ">", ".git/watchman-response.json"); # print $fh $response; # close $fh; die "Watchman: command returned no output.\n" . "Falling back to scanning...\n" if $response eq ""; die "Watchman: command returned invalid output: $response\n" . "Falling back to scanning...\n" unless $response =~ /^\{/; return $json_pkg->new->utf8->decode($response); } sub is_work_tree_watched { my ($output) = @_; my $error = $output->{error}; if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { $retry--; my $response = qx/watchman watch "$git_work_tree"/; die "Failed to make watchman watch '$git_work_tree'.\n" . "Falling back to scanning...\n" if $? != 0; $output = $json_pkg->new->utf8->decode($response); $error = $output->{error}; die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; # Uncomment for debugging watchman output # open (my $fh, ">", ".git/watchman-output.out"); # close $fh; # Watchman will always return all files on the first query so # return the fast "everything is dirty" flag to git and do the # Watchman query just to get it over with now so we won't pay # the cost in git to look up each individual file. my $o = watchman_clock(); $error = $output->{error}; die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; output_result($o->{clock}, ("/")); $last_update_token = $o->{clock}; eval { launch_watchman() }; return 0; } die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; return 1; } sub get_working_dir { my $working_dir; if ($^O =~ 'msys' || $^O =~ 'cygwin') { $working_dir = Win32::GetCwd(); $working_dir =~ tr/\\/\//; } else { require Cwd; $working_dir = Cwd::cwd(); } return $working_dir; } ================================================ FILE: .git/hooks/post-update.sample ================================================ #!/bin/sh # # An example hook script to prepare a packed repository for use over # dumb transports. # # To enable this hook, rename this file to "post-update". exec git update-server-info ================================================ FILE: .git/hooks/pre-applypatch.sample ================================================ #!/bin/sh # # An example hook script to verify what is about to be committed # by applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. # # To enable this hook, rename this file to "pre-applypatch". . git-sh-setup precommit="$(git rev-parse --git-path hooks/pre-commit)" test -x "$precommit" && exec "$precommit" ${1+"$@"} : ================================================ FILE: .git/hooks/pre-commit.sample ================================================ #!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git commit" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message if # it wants to stop the commit. # # To enable this hook, rename this file to "pre-commit". if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=$(git hash-object -t tree /dev/null) fi # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --type=bool hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ASCII filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff-index --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then cat <<\EOF Error: Attempt to add a non-ASCII file name. This can cause problems if you want to work with people on other platforms. To be portable it is advisable to rename the file. If you know what you are doing you can disable this check using: git config hooks.allownonascii true EOF exit 1 fi # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against -- ================================================ FILE: .git/hooks/pre-merge-commit.sample ================================================ #!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git merge" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message to # stderr if it wants to stop the merge commit. # # To enable this hook, rename this file to "pre-merge-commit". . git-sh-setup test -x "$GIT_DIR/hooks/pre-commit" && exec "$GIT_DIR/hooks/pre-commit" : ================================================ FILE: .git/hooks/pre-push.sample ================================================ #!/bin/sh # An example hook script to verify what is about to be pushed. Called by "git # push" after it has checked the remote status, but before anything has been # pushed. If this script exits with a non-zero status nothing will be pushed. # # This hook is called with the following parameters: # # $1 -- Name of the remote to which the push is being done # $2 -- URL to which the push is being done # # If pushing without using a named remote those arguments will be equal. # # Information about the commits which are being pushed is supplied as lines to # the standard input in the form: # # # # This sample shows how to prevent push of commits where the log message starts # with "WIP" (work in progress). remote="$1" url="$2" zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" exit 1 fi fi done exit 0 ================================================ FILE: .git/hooks/pre-rebase.sample ================================================ #!/bin/sh # # Copyright (c) 2006, 2008 Junio C Hamano # # The "pre-rebase" hook is run just before "git rebase" starts doing # its job, and can prevent the command from running by exiting with # non-zero status. # # The hook is called with the following parameters: # # $1 -- the upstream the series was forked from. # $2 -- the branch being rebased (or empty when rebasing the current branch). # # This sample shows how to prevent topic branches that are already # merged to 'next' branch from getting rebased, because allowing it # would result in rebasing already published history. publish=next basebranch="$1" if test "$#" = 2 then topic="refs/heads/$2" else topic=`git symbolic-ref HEAD` || exit 0 ;# we do not interrupt rebasing detached HEAD fi case "$topic" in refs/heads/??/*) ;; *) exit 0 ;# we do not interrupt others. ;; esac # Now we are dealing with a topic branch being rebased # on top of master. Is it OK to rebase it? # Does the topic really exist? git show-ref -q "$topic" || { echo >&2 "No such branch $topic" exit 1 } # Is topic fully merged to master? not_in_master=`git rev-list --pretty=oneline ^master "$topic"` if test -z "$not_in_master" then echo >&2 "$topic is fully merged to master; better remove it." exit 1 ;# we could allow it, but there is no point. fi # Is topic ever merged to next? If so you should not be rebasing it. only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` only_next_2=`git rev-list ^master ${publish} | sort` if test "$only_next_1" = "$only_next_2" then not_in_topic=`git rev-list "^$topic" master` if test -z "$not_in_topic" then echo >&2 "$topic is already up to date with master" exit 1 ;# we could allow it, but there is no point. else exit 0 fi else not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` /usr/bin/perl -e ' my $topic = $ARGV[0]; my $msg = "* $topic has commits already merged to public branch:\n"; my (%not_in_next) = map { /^([0-9a-f]+) /; ($1 => 1); } split(/\n/, $ARGV[1]); for my $elem (map { /^([0-9a-f]+) (.*)$/; [$1 => $2]; } split(/\n/, $ARGV[2])) { if (!exists $not_in_next{$elem->[0]}) { if ($msg) { print STDERR $msg; undef $msg; } print STDERR " $elem->[1]\n"; } } ' "$topic" "$not_in_next" "$not_in_master" exit 1 fi <<\DOC_END This sample hook safeguards topic branches that have been published from being rewound. The workflow assumed here is: * Once a topic branch forks from "master", "master" is never merged into it again (either directly or indirectly). * Once a topic branch is fully cooked and merged into "master", it is deleted. If you need to build on top of it to correct earlier mistakes, a new topic branch is created by forking at the tip of the "master". This is not strictly necessary, but it makes it easier to keep your history simple. * Whenever you need to test or publish your changes to topic branches, merge them into "next" branch. The script, being an example, hardcodes the publish branch name to be "next", but it is trivial to make it configurable via $GIT_DIR/config mechanism. With this workflow, you would want to know: (1) ... if a topic branch has ever been merged to "next". Young topic branches can have stupid mistakes you would rather clean up before publishing, and things that have not been merged into other branches can be easily rebased without affecting other people. But once it is published, you would not want to rewind it. (2) ... if a topic branch has been fully merged to "master". Then you can delete it. More importantly, you should not build on top of it -- other people may already want to change things related to the topic as patches against your "master", so if you need further changes, it is better to fork the topic (perhaps with the same name) afresh from the tip of "master". Let's look at this example: o---o---o---o---o---o---o---o---o---o "next" / / / / / a---a---b A / / / / / / / / c---c---c---c B / / / / \ / / / / b---b C \ / / / / / \ / ---o---o---o---o---o---o---o---o---o---o---o "master" A, B and C are topic branches. * A has one fix since it was merged up to "next". * B has finished. It has been fully merged up to "master" and "next", and is ready to be deleted. * C has not merged to "next" at all. We would want to allow C to be rebased, refuse A, and encourage B to be deleted. To compute (1): git rev-list ^master ^topic next git rev-list ^master next if these match, topic has not merged in next at all. To compute (2): git rev-list master..topic if this is empty, it is fully merged to "master". DOC_END ================================================ FILE: .git/hooks/pre-receive.sample ================================================ #!/bin/sh # # An example hook script to make use of push options. # The example simply echoes all push options that start with 'echoback=' # and rejects all pushes when the "reject" push option is used. # # To enable this hook, rename this file to "pre-receive". if test -n "$GIT_PUSH_OPTION_COUNT" then i=0 while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" do eval "value=\$GIT_PUSH_OPTION_$i" case "$value" in echoback=*) echo "echo from the pre-receive-hook: ${value#*=}" >&2 ;; reject) exit 1 esac i=$((i + 1)) done fi ================================================ FILE: .git/hooks/prepare-commit-msg.sample ================================================ #!/bin/sh # # An example hook script to prepare the commit log message. # Called by "git commit" with the name of the file that has the # commit message, followed by the description of the commit # message's source. The hook's purpose is to edit the commit # message file. If the hook fails with a non-zero status, # the commit is aborted. # # To enable this hook, rename this file to "prepare-commit-msg". # This hook includes three examples. The first one removes the # "# Please enter the commit message..." help message. # # The second includes the output of "git diff --name-status -r" # into the message, just before the "git status" output. It is # commented because it doesn't cope with --amend or with squashed # commits. # # The third example adds a Signed-off-by line to the message, that can # still be edited. This is rarely a good idea. COMMIT_MSG_FILE=$1 COMMIT_SOURCE=$2 SHA1=$3 /usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" # case "$COMMIT_SOURCE,$SHA1" in # ,|template,) # /usr/bin/perl -i.bak -pe ' # print "\n" . `git diff --cached --name-status -r` # if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; # *) ;; # esac # SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" # if test -z "$COMMIT_SOURCE" # then # /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" # fi ================================================ FILE: .git/hooks/push-to-checkout.sample ================================================ #!/bin/sh # An example hook script to update a checked-out tree on a git push. # # This hook is invoked by git-receive-pack(1) when it reacts to git # push and updates reference(s) in its repository, and when the push # tries to update the branch that is currently checked out and the # receive.denyCurrentBranch configuration variable is set to # updateInstead. # # By default, such a push is refused if the working tree and the index # of the remote repository has any difference from the currently # checked out commit; when both the working tree and the index match # the current commit, they are updated to match the newly pushed tip # of the branch. This hook is to be used to override the default # behaviour; however the code below reimplements the default behaviour # as a starting point for convenient modification. # # The hook receives the commit with which the tip of the current # branch is going to be updated: commit=$1 # It can exit with a non-zero status to refuse the push (when it does # so, it must not modify the index or the working tree). die () { echo >&2 "$*" exit 1 } # Or it can make any necessary changes to the working tree and to the # index to bring them to the desired state when the tip of the current # branch is updated to the new commit, and exit with a zero status. # # For example, the hook can simply run git read-tree -u -m HEAD "$1" # in order to emulate git fetch that is run in the reverse direction # with git push, as the two-tree form of git read-tree -u -m is # essentially the same as git switch or git checkout that switches # branches while keeping the local changes in the working tree that do # not interfere with the difference between the branches. # The below is a more-or-less exact translation to shell of the C code # for the default behaviour for git's push-to-checkout hook defined in # the push_to_deploy() function in builtin/receive-pack.c. # # Note that the hook will be executed from the repository directory, # not from the working tree, so if you want to perform operations on # the working tree, you will have to adapt your code accordingly, e.g. # by adding "cd .." or using relative paths. if ! git update-index -q --ignore-submodules --refresh then die "Up-to-date check failed" fi if ! git diff-files --quiet --ignore-submodules -- then die "Working directory has unstaged changes" fi # This is a rough translation of: # # head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX if git cat-file -e HEAD 2>/dev/null then head=HEAD else head=$(git hash-object -t tree --stdin &2 exit 1 } unset GIT_DIR GIT_WORK_TREE cd "$worktree" && if grep -q "^diff --git " "$1" then validate_patch "$1" else validate_cover_letter "$1" fi && if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" then git config --unset-all sendemail.validateWorktree && trap 'git worktree remove -ff "$worktree"' EXIT && validate_series fi ================================================ FILE: .git/hooks/update.sample ================================================ #!/bin/sh # # An example hook script to block unannotated tags from entering. # Called by "git receive-pack" with arguments: refname sha1-old sha1-new # # To enable this hook, rename this file to "update". # # Config # ------ # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # hooks.allowdeletetag # This boolean sets whether deleting tags will be allowed in the # repository. By default they won't be. # hooks.allowmodifytag # This boolean sets whether a tag may be modified after creation. By default # it won't be. # hooks.allowdeletebranch # This boolean sets whether deleting branches will be allowed in the # repository. By default they won't be. # hooks.denycreatebranch # This boolean sets whether remotely creating branches will be denied # in the repository. By default this is allowed. # # --- Command line refname="$1" oldrev="$2" newrev="$3" # --- Safety check if [ -z "$GIT_DIR" ]; then echo "Don't run this script from the command line." >&2 echo " (if you want, you could supply GIT_DIR then run" >&2 echo " $0 )" >&2 exit 1 fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then echo "usage: $0 " >&2 exit 1 fi # --- Config allowunannotated=$(git config --type=bool hooks.allowunannotated) allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) denycreatebranch=$(git config --type=bool hooks.denycreatebranch) allowdeletetag=$(git config --type=bool hooks.allowdeletetag) allowmodifytag=$(git config --type=bool hooks.allowmodifytag) # check for no description projectdesc=$(sed -e '1q' "$GIT_DIR/description") case "$projectdesc" in "Unnamed repository"* | "") echo "*** Project description file hasn't been set" >&2 exit 1 ;; esac # --- Check types # if $newrev is 0000...0000, it's a commit to delete a ref. zero=$(git hash-object --stdin &2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,delete) # delete tag if [ "$allowdeletetag" != "true" ]; then echo "*** Deleting a tag is not allowed in this repository" >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 then echo "*** Tag '$refname' already exists." >&2 echo "*** Modifying a tag is not allowed in this repository." >&2 exit 1 fi ;; refs/heads/*,commit) # branch if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then echo "*** Creating a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/heads/*,delete) # delete branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/remotes/*,commit) # tracking branch ;; refs/remotes/*,delete) # delete tracking branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a tracking branch is not allowed in this repository" >&2 exit 1 fi ;; *) # Anything else (is there anything else?) echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac # --- Finished exit 0 ================================================ FILE: .git/info/exclude ================================================ # git ls-files --others --exclude-from=.git/info/exclude # Lines that start with '#' are comments. # For a project mostly in C, the following would be a good set of # exclude patterns (uncomment them if you want to use them): # *.[oa] # *~ ================================================ FILE: .git/logs/HEAD ================================================ 0000000000000000000000000000000000000000 b8a20221e58ea38cd2f7dd75ad9ea7a3408e0f32 appuser 1778238322 +0000 clone: from https://github.com/pietroppeter/nimib ================================================ FILE: .git/logs/refs/heads/main ================================================ 0000000000000000000000000000000000000000 b8a20221e58ea38cd2f7dd75ad9ea7a3408e0f32 appuser 1778238322 +0000 clone: from https://github.com/pietroppeter/nimib ================================================ FILE: .git/logs/refs/remotes/origin/HEAD ================================================ 0000000000000000000000000000000000000000 b8a20221e58ea38cd2f7dd75ad9ea7a3408e0f32 appuser 1778238322 +0000 clone: from https://github.com/pietroppeter/nimib ================================================ FILE: .git/objects/pack/pack-62e2fb9434711e9a7e8675eb3152bb80cbb84291.promisor ================================================ ================================================ FILE: .git/objects/pack/pack-bfc15b21f9bdd2385245f680d4c27a0b69cc2673.promisor ================================================ b8a20221e58ea38cd2f7dd75ad9ea7a3408e0f32 refs/heads/main ================================================ FILE: .git/packed-refs ================================================ # pack-refs with: peeled fully-peeled sorted b8a20221e58ea38cd2f7dd75ad9ea7a3408e0f32 refs/remotes/origin/main ================================================ FILE: .git/refs/heads/main ================================================ b8a20221e58ea38cd2f7dd75ad9ea7a3408e0f32 ================================================ FILE: .git/refs/remotes/origin/HEAD ================================================ ref: refs/remotes/origin/main ================================================ FILE: .git/shallow ================================================ b8a20221e58ea38cd2f7dd75ad9ea7a3408e0f32 ================================================ FILE: .gitattributes ================================================ assets/* linguist-vendored ================================================ FILE: .github/workflows/docs.yml ================================================ on: push: branches: - main jobs: gh-docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: install nim id: install_nim uses: iffy/install-nim@v5 - name: install library dependencies run: nimble install -y - name: install doc dependencies run: nimble docsdeps - name: build docs run: nimble docs - name: deploy on github pages uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: docs ================================================ FILE: .github/workflows/netlify_build_docs.yml ================================================ # build docs and uploads saves output as artifact for netlify_deploy_preview pipeline to be used name: netlify_build_docs on: pull_request: branches: - main jobs: tests: runs-on: ubuntu-latest steps: - name: apt install run: sudo apt install -y libpcre3 libblas-dev liblapack-dev - uses: actions/checkout@v2 - name: install nim id: install_nim uses: iffy/install-nim@v5 - name: install library dependencies run: nimble install -y - name: install doc dependencies run: nimble docsdeps - name: build docs run: nimble docs - run: echo Commit hash = ${{ github.event.pull_request.head.sha }} - uses: actions/upload-artifact@v4 with: name: build-${{ github.event.pull_request.head.sha }} path: docs/ retention-days: 1 if-no-files-found: error ================================================ FILE: .github/workflows/netlify_deploy_preview.yml ================================================ # runs when netlify_build_docs is completed # reason for the split: we do not want to run user code in an environment that has access to netlify secrets name: netlify_deploy_preview on: workflow_run: workflows: - netlify_build_docs types: - completed jobs: deploy: name: Deploy Preview runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: potiuk/get-workflow-origin@v1_1 id: source-run-info with: token: ${{ secrets.GITHUB_TOKEN }} sourceRunId: ${{ github.event.workflow_run.id }} - run: echo sourceHeadSha = ${{ steps.source-run-info.outputs.sourceHeadSha }} - name: Set env run: echo "GITHUB_SHA_SHORT=$(echo ${{ steps.source-run-info.outputs.sourceHeadSha }} | cut -c 1-20)" >> $GITHUB_ENV - run: echo Short hash = ${{ env.GITHUB_SHA_SHORT }} - name: Show pending status check uses: Sibz/github-status-action@v1.1.5 with: authToken: ${{ secrets.GITHUB_TOKEN }} context: Netlify preview sha: ${{ steps.source-run-info.outputs.sourceHeadSha }} description: Deploying site to Netlify. Please wait... state: pending - run: rm -rf docs - name: 'Download artifacts' uses: dawidd6/action-download-artifact@v2 with: github_token: ${{secrets.GITHUB_TOKEN}} workflow: netlify_build_docs.yml # Name of the workflow that created the artifact name: "build-${{ steps.source-run-info.outputs.sourceHeadSha }}" # Name of the artifact path: docs/ - run: echo Deploy Alias = ${{ env.GITHUB_SHA_SHORT }} - uses: jsmrcaga/action-netlify-deploy@master with: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} deploy_alias: ${{ env.GITHUB_SHA_SHORT }} build_directory: docs/ install_command: ls build_command: ls - name: Status check uses: Sibz/github-status-action@v1.1.5 with: authToken: ${{ secrets.GITHUB_TOKEN }} context: Netlify preview description: Click link to preview ⇒ sha: ${{ steps.source-run-info.outputs.sourceHeadSha }} state: success # customize with netlify site name target_url: https://${{ env.GITHUB_SHA_SHORT }}--nimib.netlify.app ================================================ FILE: .github/workflows/netlify_pr_task.yml ================================================ # creates a task saying that it is waiting for the build to finish, does nothing else name: netlify PR task on: pull_request_target: # runs for activity on pr but does not use code from pr and only from pr target branches: - main jobs: tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - run: echo Commit hash = ${{ github.event.pull_request.head.sha }} - name: Show pending status check uses: Sibz/github-status-action@v1.1.5 with: authToken: ${{ secrets.GITHUB_TOKEN }} context: Netlify preview sha: ${{ github.event.pull_request.head.sha }} description: Waiting for build to finish... state: pending ================================================ FILE: .github/workflows/test.yml ================================================ name: Run tests on: push: branches: - main pull_request: jobs: tests: runs-on: ubuntu-latest strategy: matrix: nim: - 'stable' - 'devel' fail-fast: false name: Nim ${{ matrix.nim }} steps: - uses: actions/checkout@v3 - uses: jiro4989/setup-nim-action@v2.2.2 with: nim-version: ${{ matrix.nim }} - run: sudo apt install libpcre3 libpcre3-dev - run: nimble -y install - run: nimble docsdeps - run: nimble test ================================================ FILE: .gitignore ================================================ * !/**/ !*.* .DS_store *.exe *.tmp.html # let's try using this to test around with stuff: x_* # ignore build of docs docs/*.html docs/images/*.png ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to nimib You are interested in contributing to nimib? The you have come to the right place! Note that using nimib and sharing more nim code around is **already** contributing to nimib. But this is the guide for contributing code to nimib! ## What can I help with? Both small and large contributions are welcomed! If you have an idea, open an issue and discuss it with us. Otherwise, have a look at the [open issues](https://github.com/pietroppeter/nimib/issues) and see if anything peaks your interest. There might be some issues marked as [good first issue](https://github.com/pietroppeter/nimib/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22): those are issues where we have already a clear idea on what needs to be done and sometimes even code for the fix; they are especially good to familiarize oneself with the codebase and the process of contributing to open source. You can also use github [discussion forum](https://github.com/pietroppeter/nimib/discussions) if you are not sure about what to ask. We also organize [Nimib speaking hours](https://github.com/pietroppeter/nimib/discussions/categories/nimib-speaking-hours), a semi regular meeting of nimib's maintainers (Pietro and Hugo) where we welcome users and contributors (even potential ones). These are announced on the discussion forum, [look at the special forum category](https://github.com/pietroppeter/nimib/discussions/categories/nimib-speaking-hours) for when we have the next one (or ask if it is not yet planned). ## Project Structure There are 4 main folders in the project: - `docsrc/`: Here the source files for the documentation are located. - `docs/`: Here the built documentation is located. You will only find committed some static files. - `tests`: All unit-tests are located here. - `src`: Here the implementation of `nimib` is located - `nimib.nim`: This file is the glue that exports the entire library. Most of the exported procs and templates are implemented here. - `nimib/` - `blocks.nim`: Here the `newNbBlock` template is defined. - `boost.nim`: Here functionality related to nimiBoost is defined. For example the string-highlighting templates like `hlMd`. - `capture.nim`: The logic of the `captureStdout` template which allows you to capture everything that is `echo`'d in a code block. - `config.nim`: Logic related to loading `nimib.toml`. - `docs.nim`: Procs acting on `NbDoc`. For example `write` to write a document to file and `open` to open the written file in a browser. - `gits.nim`: Git-related logic. - `highlight.nim`: Logic related to static highlighting of Nim code. - `jsutils.nim`: Here the underlying logic of the `nbJs` blocks are located. - `options.nim`: Logic related to parsing runtime options when building a document. - `paths.nim`: Wrapper on top of the compiler's `pathutils`. - `renders.nim`: Here all the backends are defined. `partials`, `renderPlans` and `renderProcs` are defined here. - `sources.nim`: The logic of `codeAsInSource` is located here. - `themes.nim`: Here the default theme is located. If you are making your own theme, this is a good reference to start from. - `types.nim`: The core types like `NbDoc`, `NbBlock` are defined. ## How to add a new block - add the logic in `nimib.nim` - add the rendering in `nimib\renders.nim` - add some test in `tests` (if it make sense) - add an example in `allblocks.nim` - ⚠️ currently `README.md` depends on `docsrc\index.nim`, you will have to modify `docsrc\index.nim` and run `nimble readme` to update the readme. we will remove this dependency, see https://github.com/pietroppeter/nimib/issues/141 ## CI and deploy preview documentation is built in CI and we have **deploy preview** built with netlify. Once all checks have run succesfully the last one will contain a link to the deploy preview. This is very useful to make sure the documents still build so make sure to check it when you work on the internals of nimib. ================================================ FILE: README.md ================================================ # nimib 🐳 - nim 👑 driven ⛵ publishing ✍ Nimib provides an API to convert your Nim code and its outputs to html documents. The type of html output that is obtained by default is similar to html notebooks produced by tools like [Jupyter](https://nbviewer.jupyter.org/url/norvig.com/ipython/Advent%20of%20Code.ipynb) or [RMarkdown](https://rmarkdown.rstudio.com/lesson-10.html), but nimib provides this starting directly from standard nim files. It currently does not provide any type of interactivity or automatic reloading. If you have some nim code lying around that echoes stuff you can try how nimib works with following these steps: * run in shell `nimble install nimib` * add `import nimib` at the top of your nim file * add a `nbInit` command right after that * split your code into one or more `nbCode:` blocks * add some text commentary in markdown through `nbText:` blocks * add a `nbSave` command at the end * compile and run * open the html file that has been generated next to your nim file (same name) * (you can use runtime option `--nbShow` to open the html file automatically in your default browser) See below for an example of this. Nimib strives for: * a simple API * sane defaults * easy customization The main goal of Nimib is to empower people to explore nim and its ecosystem and share with others. This document is generated though nimib both as an index.html file and as a README.md, you should be reading one of the two, for the other: * [README.md](https://github.com/pietroppeter/nimib) * [index.html](https://pietroppeter.github.io/nimib) Nimib was presented at [NimConf2022](https://nim-lang.org/nimconf2022/), see the [slides](https://github.com/pietroppeter/nimconf22-nimib/) and click thumbnail to see video. [![nimib nimconf2022 thumbnail](https://github.com/pietroppeter/nimib/raw/d4399747aa4c4435d27e0038046ad0311a92f21d/assets/nimib-nimconf-thumbnail.png)](https://www.youtube.com/watch?v=hZ7wX1kgnuc) Nimib was also presented in [NimConf2021](https://conf.nim-lang.org), see [video](https://www.youtube.com/watch?v=sWA58Wtk6L8) and [slides](https://github.com/pietroppeter/nimconf2021). The VS Codium / Code extension [nimiboost](https://marketplace.visualstudio.com/items?itemName=hugogranstrom.nimiboost) ([Open VSX](https://open-vsx.org/extension/hugogranstrom/nimiboost)) provides syntax highlighting of embedded languages in nimib documents (eg. markdown, python, html) and a preview window of nimib documents inside the editor. ## 👋 🌍 Example Usage First have a look at the following html document: [hello.html](https://pietroppeter.github.io/nimib/hello.html) This was produced with `nim r docsrc/hello`, where [docsrc/hello.nim](https://github.com/pietroppeter/nimib/blob/main/docsrc/hello.nim) is: ```nim import strformat, strutils import nimib nbInit nbText: """ ## Secret talk with a computer Let me show you how to talk with the computer like a [real hacker](https://mango.pdf.zone/) and incidentally you might learn the basics of [nimib](https://github.com/pietroppeter/nimib). ### A secret message Inside this document is hidden a secret message. I will ask the computer to spit it out: """ let secret = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100] nbCode: echo secret nbText: fmt""" what does this integer sequence mean? Am I supposed to [recognize it](https://oeis.org/search?q={secret.join("%2C+")}&language=english&go=Search)? ### A cryptoanalytic weapon Luckily I happen to have a [nim](https://nim-lang.org/) implementation of a recently declassified top-secret cryptoanalytic weapon:""" nbCode: func decode(secret: openArray[int]): string = ## classified by NSA as TOP SECRET for c in secret: result.add char(c) nbText: """ ### The great revelation Now I can just apply it to my secret message and finally decrypt what the computer wants to tell me:""" nbCode: let msg = decode secret echo msg # what will it say? nbText: fmt"_Hey_, there must be a bug somewhere, the message (`{msg}`) is not even addressed to me!" nbSave ``` ### Other examples of usage in this repo: * [index](https://pietroppeter.github.io/nimib/index.html): generate an HTML and a README.md at the same time (you are reading one of the two). * [penguins](https://pietroppeter.github.io/nimib/penguins.html): explore palmer penguins dataset using ggplotnim (example of showing images). * [numerical](https://pietroppeter.github.io/nimib/numerical.html): example usage of NumericalNim (example of custom style, usage of latex). * [cheatsheet](https://pietroppeter.github.io/nimib/cheatsheet.html): markdown cheatsheet (example of a custom block, custom highlighting and a simple TOC). * [mostaccio](https://pietroppeter.github.io/nimib/mostaccio.html): examples of usage of nim-mustache and of dark mode. * [interactivity](https://pietroppeter.github.io/nimib/interactivity.html): shows the basic API of creating interactive elements using `nbJsFromCode`. * [counter](https://pietroppeter.github.io/nimib/counters.html): shows how to create reusable interactive widgets by creating a counter button. * [caesar](https://pietroppeter.github.io/nimib/caesar.html): a Caesar cipher implemented using `nbKaraxCode` and `karax`. elsewhere: * [adventofnim](https://pietroppeter.github.io/adventofnim/index.html): solutions for advent of code in nim * [intro to binarylang](https://ajusa.github.io/binarylang-fun/intro.html): a introduction to library [binarylang](https://github.com/sealmove/binarylang) (first public usage of nimib I was aware of) * [nblog](https://github.com/pietroppeter/nblog): a blog about nimib and its ecosystem * [nimibook](https://github.com/pietroppeter/nimibook): a port of mdbook to nim(ib) * [SciNim Getting Started](https://scinim.github.io/getting-started/): tutorials for nim in scientific computing * [Norm documentation](https://norm.nim.town): documentation of a Nim ORM library. * [NimiSlides](https://github.com/HugoGranstrom/nimib-reveal): a [reveal.js](https://revealjs.com) theme for nimib. you are welcome to add here what you have built with nimib! ## 🛠 Features > “I try all things, I achieve what I can.” ― Herman Melville, Moby-Dick or, the Whale The following are the main elements of a default nimib document: * `nbInit`: initializes a nimib document, required for all other commands to work. In particular it creates and injects into scope a `nb` object used by all other blocks (see below section API for internal details). * `nbCode`: code blocks with automatic stdout capture and capture of code source * `nbText`: text blocks with automatic conversion from markdown to html (thanks to [nim-markdown](https://github.com/soasme/nim-markdown)) * `nbSave`: save the document (by default to html) * styling with [water.css](https://watercss.kognise.dev/), light mode is default, dark mode available (`nb.darkMode` after `nbInit`). * static highlighting of nim code. Highlight styling classes are the same of [highlightjs](https://highlightjs.org/) and you can pick a different styling (`atom-one-light` is default for light mode, `androidstudio` is default for dark mode). * (optional) latex rendering through [katex](https://katex.org/) (see below) * a header with navigation to a home page, a minimal title and an automatic detection of github repo (with link) * a footer with a "made with nimib" line and a `Show source` button that shows the full source to create the document. * (optional) possibility to create a markdown version of the same document (see this document for an example: [docsrc/index.nim](https://github.com/pietroppeter/nimib/blob/main/docsrc/index.nim)) Customization over the default is mostly achieved through nim-mustache or changing `NbDoc` and `NbBlock` elements (see below api). Currently most of the documentation on customization is given by the examples. ### other blocks You can find a complete description of the code blocks along with examples in [allblocks](https://pietroppeter.github.io/nimib/allblocks.html). ### creating custom blocks * `newNbCodeBlock(cmd: string, body, blockImpl: untyped)`: template that can be used to create custom code block that will need both a `body` and an implementation which might make use of `body`. Also, the source code in `body` is read. Example blocks created with `newNbCodeBlock` are `nbCode` and `nbTextWithCode`. * `newNbSlimBlock(cmd: string, blockImpl: untyped)`: template that can be used to create a custom block that does not need a separate `body`. Example blocks created with `newNbSlimBlock` are `nbText`, `nbImage`. See `src/nimib.nim` for examples on nimib blocks that are built using these two templates. * a `newId` proc is available for `nb: NbDoc` object and provides an incremental integer. It can be used in some custom blocks (it is used in `nbJsFromCode` described below). ### interactivity using nim js backend Nimib can incorporate javascript code generated from nim code using template `nbJsFromCode`. It also provides a template `nbKaraxCode` to add code based on [karax](https://github.com/karaxnim/karax). See [interactivity](https://pietroppeter.github.io/nimib/interactivity.html) for an explanation of the api and [counter](https://pietroppeter.github.io/nimib/counters.html) for examples of how to create widgets using it. In [caesar](https://pietroppeter.github.io/nimib/caesar.html) we have an example of a karax app that implements [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher). ### highlighting Code blocks produced by `nbCode` are statically highlighted, but code in markdown code blocks are dynamically highlighted using [highlightjs](https://highlightjs.org/). The dynamic highlighting can be disabled by running `nb.disableHighlightJs()`. The supported languages are the ones listed as "common" [here](https://highlightjs.org/download/) plus Nim, Julia and Latex. Highlight styling classes are the same of [highlightjs](https://highlightjs.org/) and you can pick a different styling (`atom-one-light` is default for light mode, `androidstudio` is default for dark mode). ### latex See [numerical](https://pietroppeter.github.io/nimib/numerical.html) for an example of latex usage. To add latex support: * add a `nb.useLatex` command somewhere between `nbInit` and `nbSave` * use delimiters `$` for inline-math or `$$` for display math inside nbText blocks. Latex is rendered with [katex](https://katex.org/) through an autodetection during document loading. ### config, command line options and interaction with filesystem In the default situation a single nimib document that writes or reads from filesystem will behave as a normal nim file: the current directory is the directory from where you launch the executable. When nimib is used to produce a website or in general a collection of document it is useful to set up a **configuration file**. A nimib configuration file is a file named `nimib.toml` and it is a [toml](https://github.com/toml-lang/toml) file. Every time `nbInit` is called nimib tries to find a config file in current directory or in any parent directory. Inside a config file you can define two special directory: * `homeDir`: the directory to set as current directory. It can be given as an absolute directory or as a relative directory. When it is given as a relative directory it is relative with respect to the directory of config file. * `srcDir`: the directory where all the sources resides. It is used to create the output filename that includes a relative path. In this way the folder structure of nim files can be recreated in the output. As `homeDir`, it can be set as absolute or relative (to config). `nbInit` also parses command line options that start with `nb` or `nimib` that allow to override the above value, skip the config file or other options. All the options available can be seen by running any nimib file with option `nbHelp` (execution will stop after `nbInit`). ```nim import osproc withDir nb.doc.srcDir: echo execProcess("nim r --verbosity:0 --hints:off --warnings:off hello --nbHelp") ``` ``` Nimib options: --nbHelp, --nimibHelp print this help --nbSkipCfg, --nimibSkipCfg skip nimib config file --nbCfgName, --nimibCfgName change name of config file (default "nimib.toml") --nbSrcDir, --nimibSrcDir set srcDir as relative (to CfgDir) or absolute; overrides config --nbHomeDir, --nimibHomeDir set homeDir as relative (to CfgDir) or absolute; overrides config --nbFilename, --nimibFilename overrides name of output file (e.g. somefile --nbFilename:othername.html) --nbShow, --nimibShow open in browser at the end of nbSave ``` The value of options are available in `nb.options` field which also tracks further options in `nb.options.other: seq[tuple[kind: CmdLineKind; name, value: string]]`. ### define flags nimib's behavior can be further turned via Nim's define flags: * `-d:nimibQuiet`: Completely disables nimib's logging to stdout * `-d:nimibCodeFromAst`: Makes nimib capture block code from AST of body (as opposed to from file source; see next section). Available since version 0.3 ### Code capture The code capture of a block like `nbCode` (or other custom blocks) can happen in two different ways: * `CodeAsInSource` (default since version 0.3): code for a single block is parsed from file source (available in `nb.source`). * `CodeFromAst` (default in versions 0.1 and 0.2): code for a single block is rendered from AST of body. This means that only documentation comments are shown (since normal comments are not part of the AST) and that the source show might be different from original source. ## 🐝 API * `nbInit` template creates and injects a `nb` variable of type `NbDoc`. * templates like `nbCode` and `nbText` create a new object of type `NbBlock`, these objects are added to a sequence of blocks accessible in `nb.blocks` * the last processed block is available as `nb.blk` * `nb.blk.output` contains the (non rendered) output of block * `nb.blk.code` contains the source code of the block (if it was created with `newNbCodeBlock`) * `NbBlock` is a ref object, so changing `nb.blk`, changes the last block in `nb.blocks`. Here are two examples that show how to hijack the api: * [nolan](https://pietroppeter.github.io/nimib/nolan.html): how to mess up the timeline of blocks ⏳ * [pythno](https://pietroppeter.github.io/nimib/pythno.html): a reminder that nim is not python 😜 ## Rendering * rendering is currently based on [nim-mustache](https://github.com/soasme/nim-mustache). This will likely be changed in a next release and in fact refactoring the rendering part of nimib is the main target for next breaking change, see [#111](https://github.com/pietroppeter/nimib/issues/111) * there are two rendering backends, a html one and a markdown backend. In order to use the markdown backend one must initialize its document with `nbInitMd` instead of `nbInit` * rendering happens during the call to `nbSave`, and two steps are performed: 1. rendering all blocks and adding them to a sequence of blocks (added to `nb.context["blocks"]`) 2. rendering the document starting from `document` partial using * rendering of a single block depends on a number of fields of `nb` object: - `partials`: a `Table[string, string]` that contains the templates/partials for every command (e.g. `nb.partials["nbCode"]`); - `templateDirs`: a `seq[string]` of folders where to look for `.mustache` templates that can complement/override the templates in `partials`. A common usage is to add a `head_other.mustache` template that contain additional content added to head section of **every** document (in many repositories - including nimib - it is used to add a [plausible analytics](https://plausible.io) script) - `renderPlans`: a `Table[string, seq[string]]` that contains the render plan (a `seq[string]`) for every step of render plan an associated `renderProc` is called; - `renderProcs`: a `Table[string, NbRenderProc]` that contains all available render procs by name. (`type NbRenderProc = proc (doc: var NbDoc, blk: var NbBlock) {. nimcall .}`) * the above fields are initialized during `nbInit` with a call to `render` backend and can be customized by a call to `theme` (`render` and `theme` have default values). ## Changelog and 🙏 Thanks In the [changelog](https://github.com/pietroppeter/nimib/blob/main/changelog.md) you find all recent changes, some early history of nimib, pointers to relevant examples of usage of nimib and heartfelt thanks to some of the fine folks that made this development possible. ## 🌅 Roadmap - add more themes such as [nimibook](https://github.com/pietroppeter/nimibook). In particular themes for blogging and for creating general websites. - can I use nimib to build a library directly from documentation (like in [nbdev](https://github.com/fastai/nbdev))? - nimib executable for scaffolding and to support different publishing workflows - server-side dynamic sites (streamlit style? take advantage of caching instead of hot code reloading) - possibility of editing document in the browser (similar to jupyter UI, not necessarily taking advantage of hot code reloading) - ... completed in 0.3: - [x] refactor rendering of blocks and simplify api extensions ([#24](https://github.com/pietroppeter/nimib/issues/24)) - [x] client-side dynamic site: interactivity of documents, e.g. a dahsboard (possibly taking advantage of nim js backend) ## ❓ ❗ Q & A ### why the name? corruption of [ninib](https://www.vocabulary.com/dictionary/Ninib): > a solar deity; firstborn of Bel and consort was Gula; > god of war and the _chase_ and agriculture; sometimes identified with biblical *Nimrod* also: > He explains that the seven directions were interpreted by the Babylonian theologians > as a reference to the seven great celestial bodies, the sun and moon, Ishtar, Marduk, Ninib, Nergal and Nabu. > > This process, which reached its culmination in the post-Khammurabic period, led to identifying > the planet Jupiter with Marduk, Venus with Ishtar, Mars with Nergal, Mercury with Nebo, and Saturn with Ninib. and I should not need to tell you what [Marduk](https://jupyter.org/) is and why [Saturn is the best planet](https://www.theatlantic.com/science/archive/2016/01/a-major-correction/422514/). ### why the whale 🐳? why do you need a logo when you have emojis? no particular meaning about the whale apart the fact that I like the emoji and this project is something I have been [chasing](https://en.wikipedia.org/wiki/Captain_Ahab) for a while (and I expect to be chasing it indefinitely). also googling `nimib whale` you might discover the existence of a cool place: [Skeleton Coast](https://en.wikipedia.org/wiki/Skeleton_Coast). ### why the emojis? because I made a [package](https://github.com/pietroppeter/nimoji) for that and someone has to use it ### why the Q & A? because [someone made it into an art form](https://github.com/oakes/vim_cubed#q--a) and they tell me [imitation is the sincerest form of flattery](https://www.goodreads.com/quotes/558084-imitation-is-the-sincerest-form-of-flattery-that-mediocrity-can) ================================================ FILE: changelog.md ================================================ # Changelog The changelog includes a bit of the early history of nimib, pointers to relevant examples of usage of nimib and heartfelt thanks to some of the fine folks that made this development possible. For contributors: make sure to have a relevant and clear message for your PR and when merging update the first PR message with relevant notes regarding the PR (these notes will be used by maintainers during release, see below). Notes for maintainers: - When a maintainer merges a PR, they should make sure that the squashed commit message is relevant and clear. - When we tag a new release, we should auto generate the release notes. It does not hurt if we add more context to the release notes (e.g. taking notable elements from PR discussion). We might also want to add a release discussion post. - finally, after a release, we update this changelog (and bump version) using the same wording from release notes: https://github.com/pietroppeter/nimib/releases ## v 0.4.0 todo after release ## v0.3.12 ### What's Changed * Update changelog.md with 3.11 release notes and bump 3.12 by @pietroppeter in https://github.com/pietroppeter/nimib/pull/239 * Make Nimib logging to stdout optional (`-d:nimibQuiet`) by @neroist in https://github.com/pietroppeter/nimib/pull/242 * Add nbVideo & nbAudio (revive #153) by @neroist in https://github.com/pietroppeter/nimib/pull/244 * Create homeDir if it doesn't exist alredy by @neroist in https://github.com/pietroppeter/nimib/pull/246 **Full Changelog**: https://github.com/pietroppeter/nimib/compare/v0.3.11...v0.3.12 ## v0.3.11 ### What's Changed * Update changelog.md and bumping to 3.11 by @pietroppeter in https://github.com/pietroppeter/nimib/pull/231 * paths.nim: Fix import for FreeBSD by @lbartoletti in https://github.com/pietroppeter/nimib/pull/238 ### New Contributors * @lbartoletti made their first contribution in https://github.com/pietroppeter/nimib/pull/238 **Full Changelog**: https://github.com/pietroppeter/nimib/compare/v0.3.10...v0.3.11 ## v0.3.10 ### What's Changed * bump 0.3.10 and update changelog with 0.3.9 release notes by @pietroppeter in https://github.com/pietroppeter/nimib/pull/199 * Enlarge figure and center figure captions by @dlesnoff in https://github.com/pietroppeter/nimib/pull/201 * Refactor tests and remove hints to better visualize success/failure by @dlesnoff in https://github.com/pietroppeter/nimib/pull/202 * Complete Allblocks by @dlesnoff in https://github.com/pietroppeter/nimib/pull/203 * Automatically change file ext to `md` when using `nbInitMd` (and add a `thisFileRel` param) by @neroist in https://github.com/pietroppeter/nimib/pull/206 * Allblocks: add nbShow, nbCodeWithText, nbCodeInBlock by @dlesnoff in https://github.com/pietroppeter/nimib/pull/208 * update to numericalnim 0.8.8 by @HugoGranstrom in https://github.com/pietroppeter/nimib/pull/214 * Fix std/random bug (#204) by @sent44 in https://github.com/pietroppeter/nimib/pull/211 * Happyx support by @quimt in https://github.com/pietroppeter/nimib/pull/212 * Add nbFile overload for file embedding by @PhilippMDoerner in https://github.com/pietroppeter/nimib/pull/219 * fix issue#229: skip nimble INFO logs when dumping json by @lost22git in https://github.com/pietroppeter/nimib/pull/230 ### New Contributors :heart: * @sent44 made their first contribution in https://github.com/pietroppeter/nimib/pull/211 * @quimt made their first contribution in https://github.com/pietroppeter/nimib/pull/212 * @PhilippMDoerner made their first contribution in https://github.com/pietroppeter/nimib/pull/219 * @lost22git made their first contribution in https://github.com/pietroppeter/nimib/pull/230 **Full Changelog**: https://github.com/pietroppeter/nimib/compare/v0.3.9...v0.3.10 ## v0.3.9 * Update water.css and fix code output by @dlesnoff in https://github.com/pietroppeter/nimib/pull/185 * Add `nbCodeSkip` and `allblocks.nim` by @neroist in https://github.com/pietroppeter/nimib/pull/187 * fix typo in CONTRIBUTING.md by @neroist in https://github.com/pietroppeter/nimib/pull/188 * Add `nbCapture`, closes #156 by @neroist in https://github.com/pietroppeter/nimib/pull/189 * Add meta tag with generator, closes #170 by @neroist in https://github.com/pietroppeter/nimib/pull/190 * Fix special chars escaped by the markdown renderer, close #159 by @neroist in https://github.com/pietroppeter/nimib/pull/191 * Make "figure:" not show up when using nbImage with no caption by @neroist in https://github.com/pietroppeter/nimib/pull/192 * Add seperate `alt` param to `nbImage`, close #193 by @neroist in https://github.com/pietroppeter/nimib/pull/195 * Fix `getNimibVersion()` by @neroist in https://github.com/pietroppeter/nimib/pull/196 ### New Contributors * @dlesnoff made their first contribution in https://github.com/pietroppeter/nimib/pull/185 * @neroist made their first contribution in https://github.com/pietroppeter/nimib/pull/187 **Full Changelog**: https://github.com/pietroppeter/nimib/compare/v0.3.8...v0.3.9 ## v0.3.8 - Fix nim-markdown not exporting escapeTag anymore * remove export escapeTag by @HugoGranstrom in https://github.com/pietroppeter/nimib/pull/181 * [nim-markdown](https://github.com/soasme/nim-markdown) released a new version which doesn't export `escapeTag` anymore, so we remove it. Not sure why we did it to begin with tbh. ## v0.3.7 - All code shall be highlighted * Implement nbShow and highlight.js support for code in markdown by @HugoGranstrom in https://github.com/pietroppeter/nimib/pull/179 * `nbShow` can be used to pretty print any type which implements a `toHtml` proc that returns a string of HTML to be rendered. * Code blocks in markdown are now highlighted dynamically using [highlight.js](https://highlightjs.org). * updated changelog with 0.3.6 release notes + change in changelog workflow by @pietroppeter in https://github.com/pietroppeter/nimib/pull/176 ## v0.3.6 - nim 2.0 compatibility! * Change toml lib + fix macro bug on devel by @HugoGranstrom in https://github.com/pietroppeter/nimib/pull/173 with this PR nimib is finally compatible with the upcoming 2.0. Two things needed fixing: - a nim compiler orc macro bug (reported here: https://github.com/nim-lang/Nim/issues/21326), fixed with a [workaround] - there was an issue with toml serialization on orc (reported here: https://github.com/status-im/nim-toml-serialization/issues/62) fixed by removing the dependency from [toml_serialization] and using [parsetoml] instead - some custom code in order to support direct to object conversion was needed, see https://github.com/NimParsers/parsetoml/issues/59 - we also added a dependency to [jsony] to support a loose direct to object conversion from toml * Adding devel to CI, fix #161, fix #149 by @pietroppeter in https://github.com/pietroppeter/nimib/pull/169 - added both stable (which will become 2.0) and devel (which is currently the 2.0 rc) to CI, also update the versions of actions we depend on **Full Changelog**: https://github.com/pietroppeter/nimib/compare/v0.3.5...v0.3.6 **release discussion**: https://github.com/pietroppeter/nimib/discussions/175 [workaround]: https://github.com/pietroppeter/nimib/pull/173/commits/f1966097da91d4ba7b2711dbe44223e871927b42 [toml_serialization]: https://github.com/status-im/nim-toml-serialization [parsetoml]: https://github.com/NimParsers/parsetoml [jsony]: https://github.com/treeform/jsony ## 0.3.5 * codeAsInSource has been reworked to work better with templates and uses of `nbCode` in different files. The cases that still don't work is when code from different places are combined in a single `nbCode`, like here: ```nim template foo(body: untyped) = nbCode: body # This code is from line 7 echo "Hello world" # this code is from line 4 foo: echo "Goodbye world" ``` * If you don't use any nbJs, now nimib won't build an empty nim file in those cases. * The temporary js files generated by nbJs now has unique names to allow parallel builds. ## 0.3.4 * added `nbCodeDisplay` and `nbCodeAnd` (#158). They provide an easy way to: - display code in `nbJsFromCode` and friends - run code both in js and c backend They are also generic templates that can be used with other templates and do not depend on any specificities of `nbJsFromCode` templates. ## 0.3.3 * Refactored nbJs (#148) * **Breaking**: All `nbJsFromCode` blocks are now inserted into the same file (Compared to previously when each block was compiled as its own file). So this will break any reusable components as you will get `redefinition of variable` errors. The solution is to use `nbJsFromCodeInBlock` which puts the code inside a `block`. Imports can't be done in there though so you must do them in a separate `nbJsFromCode` or `nbJsFromCodeGlobal` before. * See [https://pietroppeter.github.io/nimib/interactivity.html](https://pietroppeter.github.io/nimib/interactivity.html) for a more detailed guide on how to use the new API. * Added `nimibCode` template. One problem with using `nbCode` is that you can't show *nimib* code using it because it nests blocks and wrecks havoc. So `nimibCode` allows you to show *nimib* code but at the cost of not capturing output of the code. ## 0.3.2 * Add `hlHtml` and `hlHtml` to nimiBoost * fix rarely occuring issue of terminal output not being captured (windows only, see example in https://github.com/pietroppeter/nimib/pull/132) * compress line height in nbCode output (using class `nb-output`), see #133 * Fixed a case when capturing a global in `nbJsFromCode` didn't gensym the symbols, causing the same variable names in the generated code. #136 ## 0.3.1 * fix "Did not parse stylesheet at 'https://unpkg.com/normalize.css/' in strict mode" (#120) * Split untyped and string versions of `nbCodeToJs` into `nbJsFromCode` and `nbJsFromString`. Same for `nbCodeToJsInit` → `nbJsFromCodeInit`, `nbJsFromStringInit` (#125) * Add `postRender` template to `nbKaraxCode` (#125) * `nbJsFromCode` now respects `exportc` pragma (#125) * rename `rawOutput` (deprecated) to `rawHtml` ## 0.3 "Block Maker" (July 2022) This release started with the aim of making the construction of custom blocks as easy as the construction of native blocks. A wide refactoring of the codebase was required for this (#78) and further adjustments were made along the way (#80, #81). Some new blocks are introduced taking advantage of this (e.g. `nbRawOutput`, `nbPython`) (#80, #83). Contributing to the codebase is made easier through introduction of proper testing (#80) docs are now built in CI (#89, #90, #91) and deploy previews have been added (#92, #93). Documentation has been updated to include all changes so far and contextually the changelog has been updated (#103). A big milestone is reached (#88) by introducing templates to add interactivity to documents taking advantage of nim js backend (`nbCodeToJs` allows to incorporate javascript scripts in the document derived from nim code). In particular templates to reduce boilerplate when developing karax based apps or widgets are introduced (`nbKaraxCode`, `karaxHtml`). Three new example documents are introduced for documenting this change (`interactivity`, `counters`, `caesar`). Another major change is setting as default the `CodeAsInSource` introduced in 0.2.4 (a number of fixes are made: #105, #106, #108). Most of these contributions are due to @HugoGranstrom (thanks for all the awesome work on this ❤️) which joins @pietroppeter as maintainer and co-creator of nimib! 🥳 List of detailed changes: * refactoring of `NbBlock` type and rendering of blocks (#78, fixes #24): * `NbBlock` type is completely refactored. Instead of having a `kind` with a fixed number of values, a block behaviour is specified by a `command` string which is set to the name of the command template used to create a block (e.g. `nbCode`, `nbText`, `nbImage`, ...) - * `newNbBlock` is now the main template to create a new block * Every block now has a `context` field and the rendering backend (either html or markdown) has a mechanism to retrieve a `partial` for every command. * as an additional mechanism to be able to perform other computations when rendering, a sequence of `renderProc`s can be assigned for every command (for a specific backend). * `nimib / renders` module completely refactored to take into account the above changes * some other accidental or not so welcome changes that happened during the refactoring: - `sugar` is now exported _(accidental)_ - `nb: NbDoc` is mutated when rendered _(unwelcome, will be changed later)_ - cannot use both Html and Md backend at the same time _(unwelcome, will be changed later)_ * logging has been improved (see changes in `nimib.blocks.newNbBlock`) (#78) * new `main` partial introduced (#78) * fixed cheatsheet document (#78, fixes #52) * tests are added and ptest document is removed (#78) * aliases to minimize breaking changes that happened in 0.2 (`nbDoc`, `nbBlock`, `nbHomeDir`) are noew removed (#78) * added a new `readCode: bool` parameter to `newNbBlock` (with an overload that sets it as true) (#80) * new template `nbRawOutput` that renders raw html (#80) * new command `nbClearOutput` that removes output from last block processed (#80) * new templates for creating code blocks `newNbCodeBlock` and `newNbSlimBlock` for creating custom blocks and related changes (#81): - `newNbCodeBlock`: captures source code of `body` - `newNbSlimBlock`: block without a `body` (and in particular no capture of source) - all nimib "native" blocks now use one of the two mechanism above - now `nbText` does NOT contain its source - new `nbTextWithCode` that does contain code source * new example document `files.nim`, changed the rendering of `nbFile` (no more "writing file ..." only the name of file is added) (#81) * added `loadNimibCfg` proc that can be used for themes (used by nimibook) (#81) * added `nbInitPython` and `nbPython` templates to support running python in nimib documents using `nimpy` (#83) - `md` and `fmd` from `nimib / boost` now deprecated and replaced by `hlMd` and `hlMdF` - new `hlPy` and `hlPyF` in `nimib / boost` * docs now are built in CI (#89, #90, #91) - sources of docs are now in folder `docsrc` - outputs are in `docs` * add deploy preview through netlify (#92, #93) * new templates to introduce interactivity in documents taking advantage of nim's javascript backend (#88) - `nbCodeToJs`: a block of nim code is compiled to javascript and added as a script to html file (and allows capturing of variables) - `nbCodeToJsInit`, `addCodeToJs`, `addToDocAsJs`: templates to allow splitting in multiple blocks the code in `nbCodeToJs` - `nbCodeToJsShowSource`: template to show the nim source of a `nbCodeToJs` block. - `nbKaraxCode` (with `karaxHtml`): template to create a karax app/widget with minimal boilerplate (based on `nbCodeToJs`) - new example document `interactivity.nim`: explains the basic of `nbCodeToJs` and related templates - new example document `counters.nim`: shows how to create counter widgets using `nbCodeToJs` - new example document `caesar.nim`: a caesar cipher app built using `nbKaraxCode` - new module `nimib / jsutils` to support the implementation of the above * `newId` proc for `NbDoc` that gives a new incremental integer every time it is called (#88) * `CodeAsInSource` is made default: - new `nimibCodeFromAst` flag to revert to old default - added a warning to `nimibPreviewCodeAsInSource` (now obsolete) * various fixes to `CodeAsInSource` (#105, #106, #108) * changelog updated and separated from documentation (#103) * updated documentation to include most recent changes (#103) * turned off warning for unused imports in `nimib.nim` (#103) * fix markdown backend, it was broken since html theme was overiding render backend (#103): - new `nbInitMd` to use markdown backend - new `themes.noTheme` for empty theme (used by `nbInitMd`) Thanks to @metagn for improving our CI/nimble file! Every contribution counts! Relevant examples of usage: * [nimislides](https://github.com/HugoGranstrom/nimib-reveal): a new nimib theme that allows to create slides using [reveal.js](https://revealjs.com) html presentation framework * some posts in nblog are relevant example of new blocks and customization of nimib: - [Making Diagrams using mermaid.js](https://pietroppeter.github.io/nblog/drafts/mermaid_diagram.html) - [Plotly in nimib](https://pietroppeter.github.io/nblog/drafts/show_plotly.html) ## 0.2.x (November 2021) ### 0.2.4 - CodeAsInSource * Update penguins example which now uses datamancer and shows Simpson's paradaox, by @Vindaar (#70) * code as in source for nbCode (`-d:nimibPreviewCodeAsInSource`) by @HugoGranstrom (#63): with this option the code shown is not derived from Ast but it is read from source code. * ptest document is turned off from CI ### 0.2.3 * align version in nimble file and tagged version ### 0.2.2 - nbFile * add `nbFile` by @Clonkk (#64) ### 0.2.1 * fix to `path_to_root` (renamed from `home_path`, also `here_path` renamed to `path_to_here`) (#67) ## 0.2 "Theme Maker" (November 2021) this release aims to simplify creating Nimib themes such as nimibook. It does this through the following changes: * instead of creating and injecting multiple variables (`nbDoc`, `nbBlock`, `nbHomeDir`, ...), nimib now only injects a `nb` variable that is a `NbDoc`. Some aliases are provided to minimize breakage. * handling of paths (`srcDir` and `homeDir`) is changed and is based on the presence of a new config file `nimib.toml` * command line options are now processed and can be used to skip/override the config process. Run any nimib file with option `--nbHelp` to see available options. * note in particular new `--nbShow` option which will automatically open the file in your default browser. * `nbPostInit` and `nbPreSave` customization mechanism based on includes are now removed * documentation has been updated to reflect the above changes and also to add other Nimib references (NimConf video, nimibook, getting-started, ...) most of the changes break the api relevant external example: * [norm](https://norm.nim.town) starts to use nimibook for its documentation Special thanks again to to @Vindaar, @Clonkk and @HugoGranstrom for this release. ## 0.1.x (March-June 2021) a growing ecosystem drives most of the development of the 0.1.x series: * [intro to binarylang](https://ajusa.github.io/binarylang-fun/intro.html) by @ajusa (March 2021): first public use of nimib by someone other than @pietroppeter * [SciNim Getting Started](https://scinim.github.io/getting-started/) decided to use nimib and for that purpose [nimibook](https://github.com/pietroppeter/nimibook), a book theme (based of mdbook) developments was started * [nblog](https://github.com/pietroppeter/nblog), a nimib blog, was started as a way to use nimib to explore nim ecosystem and experiment the various features of nimib * [nimiboost](https://github.com/HugoGranstrom/nimiBoost) is a vs code extension to provide markdown highlighting and a preview mechanism. changes: * 0.1.1: - add nbPostInit mechanism to customize document (#32) - fix (breaking): code output is escaped by default - fix (breaking): code output is not stripped anymore - fix: nbDoc.write will create directories if not existing (#44) * 0.1.2: release to align tag and nimble version * 0.1.3: added compile-time switches to override nbHomeDir (#53) * 0.1.4: fix for `nbImage` path (#56) * 0.1.5: new template `nbCodeInBlock` (#59) * 0.1.6: added `nimib / boost` module with `md` and `fmd` helpers to support markdown highlight with nimiboost Thanks for this release series to @Vindaar, @Clonkk and @HugoGranstrom who decided to adopt nimib in scinim/getting-started and motivated and directly contributed to nimib and nimibook development to support this use case. At the end June 2021, nimib was presented at [NimConf2021](https://conf.nim-lang.org). ## 0.1 (March 2021) * initial version with essential templates `nbInit`, `nbText`, `nbCode`, `nbImage`, `nbSave` - capture of output in `nbCode` based on code by @Clonkk * html backend based on mustache and markdown by @soasme * default theme using water.css - header with home button, minimal title (filename by default), automatic detection of github repo - footer with "made with nimib" and Show Source button * static highlighting of nim code (by @yardanico) * latex rendering through katex * markdown backend * essential documentation in `index.nim` - sections: intro, example usage, features, api, roadmap, thanks, Q&A - also generates `README.md` and serves as an example of usage of markdown backend * possibility to customize theme (dark mode, custom stylesheet, add other scripts, ...) * example documents: - `penguins`: data exploration, adding images - `numerical`: latex usage, theme customization - `cheatsheet`: toc creation, new text block which shows source, custom highlighting - also documents the markdown to html generator - `mostaccio`: example of using dark mode - also documents the templating system mustache - `ptest`: print testing for nimib * deployed using github pages. html files committed in repo. relevant external examples: * adventofnim (2020) by @pietroppeter - first appeareance of nimib in public (before 0.1 release), see [commit on Dec 1st, 2020](https://github.com/pietroppeter/adventofnim/commit/973f9a2472d41188bb37650c082f115fc5787687#diff-a21a437c51bd7babb945c8291588853296387c7e1950997e05f1eb62d18b54f7) Initial commit of nimib was on Nov, 25, 2020. On the same day the [first milestone](https://github.com/pietroppeter/nimib/commit/b02ec7be4663956167701a81a96246d8e528fff3) reached was the working hello world example. For this release, thanks to: * [soasme](https://github.com/soasme) for the excellent libraries nim-markdown and nim-mustache, which provide the backbone of nimib rendering and customization * [Clonkk](https://github.com/Clonkk) for help in a critical piece of code early on (see [this Stack Overflow answer](https://stackoverflow.com/a/64032172/4178189)) * [yardanico](https://github.com/yardanico) for being the first contributor and great sponsor of this library, even before an official release ================================================ FILE: config.nims ================================================ switch("d","nimibHomeDir=docs") ================================================ FILE: nimib.nimble ================================================ # Package version = "0.4.0" author = "Pietro Peterlongo & Hugo Granström" description = "nimib 🐳 - nim 👑 driven ⛵ publishing ✍" license = "MIT" srcDir = "src" # Dependencies requires "nim >= 1.4.0" requires "fusion >= 1.2" requires "markdown >= 0.8.1" requires "parsetoml >= 0.7.0" requires "jsony >= 1.1.5" task docsdeps, "install dependendencies required for doc building": exec "nimble -y install ggplotnim@0.5.9 numericalnim@0.8.8 nimoji nimpy karax@1.3.3 happyx@2.0.0 mustache@0.4.3" task test, "General tests": for file in ["tsources.nim", "tblocks.nim", "tnimib.nim", "trenders.nim"]: exec "nim r --hints:off tests/" & file for file in ["tblocks.nim", "tnimib.nim", "trenders.nim"]: exec "nim r --hints:off -d:nimibCodeFromAst tests/" & file task readme, "update readme": exec "nim -d:mdOutput r docsrc/index.nim" task docs, "Build documentation": for file in ["allblocks", "hello", "mostaccio", "numerical", "nolan", "pythno", "cheatsheet", "files", "index", "interactivity", "counters", "caesar"]: exec "nim r --hints:off docsrc/" & file & ".nim" when not defined(nimibDocsSkipPenguins): exec "nim r --hints:off docsrc/penguins.nim" exec "nimble readme" ================================================ FILE: nimib.toml ================================================ [nimib] srcDir = "docsrc" homeDir = "docs"