Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation #98

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
fswatch
gnumake
pandoc
nodePackages.browser-sync
];
};
});
Expand Down
10 changes: 8 additions & 2 deletions public/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ HTML_OPTIONS=--to html5\
--section-divs\
--reference-location=section\
--lua-filter=assets/anchor-links.lua\
--template=assets/template.html
--template=assets/template.html\
--katex\
--reference-location=section

.PHONY: all clean watch

Expand All @@ -24,7 +26,11 @@ website/man.html: man.md

# Reruns make on file change
watch:
@fswatch $(WATCH) | xargs -I{} make -s
@fswatch $(WATCH) | xargs -I{} make all -s

# Serves the website with live-reloading
serve:
@make watch -s& cd website; browser-sync start --no-open --server --watch "**/*"

clean:
@rm $(OUT)\
Expand Down
19 changes: 13 additions & 6 deletions public/assets/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
property="og:description"
content="A lovingly designed tool for your Zettelkasten needs"
/>
<!-- Inter -->
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&amp;display=swap"
rel="stylesheet"
/>
<!-- Source Sans Pro -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap" rel="stylesheet">

<!-- JetBrains Mono -->
<link
Expand All @@ -34,19 +33,27 @@
hljs.highlightAll();
</script>

<!-- Math support -->
$if(math)$
$math$
$endif$

<style>
/* Bamboo */
:root{--b-font-main: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--b-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--b-txt: #2e3440;--b-bg-1: #fff;--b-bg-2: #eceff4;--b-line: #eceff4;--b-link: #bf616a;--b-btn-bg: #242933;--b-btn-txt: #fff;--b-focus: #88c0d0}*,::before,::after{box-sizing:border-box}html:focus-within{scroll-behavior:smooth}body{max-width:70ch;padding:0 1rem;margin:auto;background:var(--b-bg-1);font-family:var(--b-font-main);text-rendering:optimizeSpeed;line-height:1.5;color:var(--b-txt);-moz-tab-size:4;tab-size:4;word-break:break-word;-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:100%}h1,h2,h3,h4,h5,h6,p,ul,ol,dl,dd,details,blockquote,pre,figure,table,address,hr,fieldset,iframe,audio,video{margin:0 0 1.5rem}h1,h2,h3,h4,h5,h6{line-height:1.25;margin-top:2rem}h1{font-size:2rem}h2{font-size:1.5rem}h3{font-size:1.25rem}h4{font-size:1rem}h5{font-size:.875rem}h6{font-size:.75rem}a{color:var(--b-link);text-decoration:none}a:hover{text-decoration:underline}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none}abbr[title]{text-decoration:underline;text-decoration:underline dotted}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--b-txt)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}hr{height:0;overflow:visible;border:0;border-bottom:1px solid var(--b-line)}pre,code,kbd,samp,tt,var{background:var(--b-bg-2);border-radius:.25rem;padding:.125rem .25rem;font-family:var(--b-font-mono);font-size:.875rem}pre{padding:1rem;border-radius:0;overflow:auto;white-space:pre}pre code{padding:0}details{display:block;padding:.5rem 1rem;background:var(--b-bg-2);border:1px solid var(--b-line);border-radius:.25rem}details>:last-child{margin-bottom:0}details[open]>summary{margin-bottom:1.5rem}summary{display:list-item;cursor:pointer;font-weight:bold}summary:focus{box-shadow:none}table{border-collapse:collapse;width:100%;text-indent:0}table caption{margin-bottom:.5rem}tr{border-bottom:1px solid var(--b-line)}td,th{padding:.5rem 0}th{text-align:left}ul,ol,dd{padding-left:2rem}li>ul,li>ol{margin-bottom:0}fieldset{padding:.5rem .75rem;border:1px solid var(--b-line);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}button,input,select,textarea{margin:0;padding:.5rem .75rem;max-width:100%;background:var(--b-bg-2);border:0;border-radius:.25rem;font:inherit;line-height:1.125;color:var(--b-txt)}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}button,[type=button i],[type=submit i],[type=reset i]{-webkit-appearance:button;display:inline-block;text-align:center;white-space:nowrap;background:var(--b-btn-bg);color:var(--b-btn-txt);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}progress{vertical-align:middle}[type=search i]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.5}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}:-moz-ui-invalid{box-shadow:none}[aria-busy=true i]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true i],[disabled]{cursor:not-allowed}:focus,details:focus-within{outline:none;box-shadow:0 0 0 2px var(--b-focus)}@media(prefers-reduced-motion: reduce){html:focus-within{scroll-behavior:auto}*,::before,::after{animation-delay:-1ms !important;animation-duration:1ms !important;animation-iteration-count:1 !important;background-attachment:initial !important;scroll-behavior:auto !important;transition-delay:0 !important;transition-duration:0 !important}}select:not([multiple]):not([size]){background-image:url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%232e3440'%3E%3Cpath d='M5 6l5 5 5-5 2 1-7 7-7-7 2-1z'/%3E%3C/svg%3E")}

/* Custom */
:root {
--b-font-main: "Inter", sans-serif;
--b-font-main: "Source Sans Pro", sans-serif;
--b-font-mono: "IBM Plex Mono", monospace;
--b-link-rgb: 46, 52, 64;
--b-link: rgb(var(--b-link-rgb));
--transition-length: 80ms;
scroll-behavior: smooth;
}
body {
max-width: 80ch;
}
header h1 {
text-align: center;
margin-top: 0;
Expand Down
89 changes: 69 additions & 20 deletions public/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,70 @@ An mdzk binary for your system will now be available in `./target/release`.
---


# Getting started

Getting started with mdzk is very simple. You only need a directory of Markdown files, linked together with `[[wiki style]]` links (you can read more about the syntax [here](#arc)). From a terminal, you can then run

```shell
$ mdzk
```

inside the directory in question. This will spit out a bunch of JSON to the terminal. This JSON represents your vault, it's structure, and the notes it contains along with their metadata. The goal of mdzk is to allow interoperability by piping the JSON into other tools which can process it into something useful. As an example, this one-liner will produce data that lets you visualize your vault with [D3.js](https://d3js.org/):

```shell
$ <one-liner here>
```

## Static site generation

### Publishing with GitHub Pages

## Language server and tree-sitter


# Core concepts

At it's core, mdzk operates on a *vault* with *notes* containing optional *internal links*. Let's unpack these terms:
At it's core, mdzk creates a *vault* of *notes* containing *arcs*. Let's unpack these terms:

- A **vault** is a [directed graph](https://en.wikipedia.org/wiki/Directed_graph).
- A **vault** is a [simple directed graph](https://en.wikipedia.org/wiki/Directed_graph).
- **Notes** are the nodes in a vault.
- **Internal links** create edges connecting each note.
- An **arc** is a directed edge connecting two notes.

## Vault

Mathematically we can define a vault as the tuple $V = (N, A)$, where

In the filesystem, a vault is represented by directory, the notes being Markdown-files. mdzk takes a directory as input, recursively finds any Markdown-files in it and loads each of them as a node in the graph. It then parses every file and establishes edges between the nodes based on the links contained in it.
- $N = \{n_i\}$ is a set of [notes](#note);
- $A \subseteq \{(n_i, n_j)$ where $(n_i, n_j)\in N^2\}$ is a set of [arcs](#arc).[^arcs-def]

The *vault* data structure is a very efficient and useful concept in dealing with notes and their relation together. mdzk models a vault as an [adjacency matrix](https://mathworld.wolfram.com/AdjacencyMatrix.html) and does custom hashing on each note to obtain unique note IDs. This means that we get incredibly fast lookups on note adjacencies.
mdzk represents a vault in memory as an [adjacency matrix](https://mathworld.wolfram.com/AdjacencyMatrix.html). This gives us very fast lookup times on arcs, and simplifies finding inversed arcs ([backlinks](https://en.wikipedia.org/wiki/Backlink)).

## Vaults
In the filesystem, a vault is simply a directory with a bunch of Markdown files. You may structure this directory however you want and include any other filetypes - mdzk does not care. Something to keep in mind: mdzk does not have any notion of a directory hierarchy. You may bury a note in a subdirectory of a subdirectory of a subdirectory if you want, mdzk will still handle it the same way as a note placed in the root.

As a user, you can think of a vault simply as a directory with a bunch of Markdown-files. You may structure this directory however you want and include any other filetypes - mdzk does not care. The major difference to keep in mind, is that a vault does not include the notion of any hierarchy. You may bury a note in a subdirectory of a subdirectory of a subdirectory if you want, mdzk will still handle it the same way as a note placed in the root.
## Note

A note is a node in a vault, represented by a single Markdown file inside the vault's source directory. mdzk recursively finds all Markdown files in a directory and creates notes from them. Notes also contain some metadata:

- An [ID](#note-ids);
- The original content of the source file;
- The processed content of the source file;
- A relative path from the vault root;
- An optional date;
- Optional tags.

Since mdzk only processes front matter and links, there is no limitation on what Markdown extensions you can use in a note's content. However, mdzk adheres to [CommonMark](https://commonmark.org/), so links inside e.g. code blocks and raw HTML will not get touched. If you are unfamiliar with CommonMark, I strongly recommend you check out [this quick guide](https://commonmark.org/help/) to get the gist of it, and stick to it's conventions where possible. We also support [tables](https://github.github.com/gfm/#tables-extension-), [task lists](https://github.github.com/gfm/#task-list-items-extension-), [strikethrough](https://github.github.com/gfm/#strikethrough-extension-) and [footnotes](https://talk.commonmark.org/t/how-should-footnotes-behave/1106).

### Note IDs

Each note is uniquely identified by a 16-digit hexidecimal ID (64 bits). This ID is gained from the [Fowler-Noll-Vo hash](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) of the relative path from the vault root to the note's source file. This means that you can change the title, metadata and content of your note as much as you want without changing it's ID - as long as the filepath remains the same.

As a user, you will likely never need to care about a note's ID; it is only a way for mdzk and external programs to handle uniqueness in cases like name changes or note's with the same title.

## Arc

An arc is created by writing a [wiki-style](https://www.mediawiki.org/wiki/Help:Links#Internal_links) link inside a note, namely by surrounding a note identifier by double square brackets like this: `[[link to a note]]`. The note identifier can be both the title of a note or a path.

---

Consider the vault with the following tree:

Expand All @@ -68,11 +117,7 @@ Producing a visualization of this vault, might look like this:
<!-- Using http://bl.ocks.org/rkirsling/5001347 to produce illustrative graphs atm. -->
![](images/vaults_01.png){ width=50% }

As you can see, the paths were totally ignored; *[internal links](#internal-links) are the only constructs that define the vault structure*. The filepaths are still stored as metadata, so custom workflows using directory hierarchies can still be made if one wants.

## Notes

## Internal links
As you can see, the paths were totally ignored; *[arcs](#arc) define the vault structure, not filepaths*. Paths are still stored as metadata, so custom workflows using directory hierarchies can still be made if one wants.


---
Expand Down Expand Up @@ -106,18 +151,22 @@ As you can see, the paths were totally ignored; *[internal links](#internal-link

// The content of the note. All internal links are
// converted to CommonMark and the front matter
// is stripped.
// is stripped
"content": string,

// A set of note IDs, each representing an
// outgoing internal link
"links": [string],

// A set of note IDs, each representing an
// incoming internal link
"backlinks": [string]
"arcs": {
// An array of note IDs that are the
// destination of an arc starting at the
// current note
"outgoing": [string],
// An array of note IDs where the current
// note is the destination
"incoming": [string]
},
}
],
// Not yet implemented: "tags": []
}
```

[^arcs-def]: Note that this definition permits loops, meaning notes can link to themselves. This does not provide any real practical benefits, but it simplifies how we model the vault and gives some flexibility in linkage.