This file contains the formal file format specification of the Norg syntax version 1.0. This document is written in the Norg format in its original form and, thus, attempts to be self-documenting.
Please note that this is not a reference implementation - this is an established rule set that should be strictly followed.
Before diving into the details we will start with an introduction. The Norg file format was designed as part of the Neorg plugin for Neovim which was started by Vhyrro (@vhyrro) in April 2021. Soon after starting this work, Max Rossmannek (@mrossinek) joined the development team, and, with the help of the Neorg community, the two have shaped the Norg syntax to what it has become today.
The Norg syntax is a structured plain-text file format which aims to be human-readable when viewed standalone while also providing a suite of markup utilities for typesetting structured documents. Compared to other plain-text file formats like e.g. Markdown, Org, RST or AsciiDoc, it sets itself apart most notably by following a strict philosophy to abide by the following simple rules:
Consistency the syntax should be consistent. Even if you know only a part of the syntax, learning new parts should not be surprising and rather feel predictable and intuitive.
Unambiguity the syntax should leave no room for ambiguity. This is especially motivated by the use of tree-sitter for the original syntax parser, which takes a strict left-to-right parsing approach and only has single-character look-ahead.
Free-form whitespace is only used to delimit tokens but has no other significance! This is probably the most contrasting feature to other plain-text formats which often adhere to the off-side rule, meaning that the syntax relies on whitespace-indentation to carry meaning.
Although built with Neorg in mind, Norg can be utilized in a wide range of applications, from external note-taking plugins to even messaging applications. Thanks to its layer system one can choose the feature set they'd like to support and can ignore the higher levels.
First, we define some basic concepts which will be used in this specification.
A Norg file is made up of characters. A character is any Unicode code point or grapheme.
A character is considered whitespace if it is any of the following:
The regular space U+0020
A tab U+0009
Any code point in the Unicode Zs general category
Any combination of the above is also considered whitespace.
Tabs are not expanded to spaces and since whitespace has no semantic meaning there is no need to define a default tab stop. However, if a parser must (for implementation reasons) define a tab stop, we suggest setting it to 4 spaces.
Line endings in Norg serve as a termination character. They are used e.g. to terminate paragraph segments, paragraphs and other elements like the endings of range-able detached modifiers. They are not considered whitespace.
The following chars are considered line endings:
A line feed U+000A
A form feed U+000C
A carriage return U+000D
The following line ending combinations are permitted:
A single line feed
A single carriage return
A carriage return immediately followed by a line feed
A character is considered punctuation if it is any of the following:
A standard ASCII punctuation character: |!"#$%&'()*+,-./:;<=>?@[\]^_
|~|`
Anything in the general Unicode categories Pc
, Pd
, Pe
, Pf
, Pi
, Po
or Ps
.
A single character can be escaped if it is immediately preceded by a backslash, |\|
(U+005C
). Any character may be escaped apart from characters within free-form and ranged verbatim segments (see free-form attached modifiers and verbatim ranged tags). For more information about precedence, take a look at the precedence section.
Any other character not described by the preceding sections is treated as a generic code point/character.
The Norg format is designed to be parsed on a word-by-word basis from left-to-right through the entire document in a single pass. This is possible because the language is free-form, meaning that whitespace has no semantic meaning, and because the markup follows strict rules which are outlined in the later sections of this document.
A word is considered to be any combination of characters which are neither whitespace nor punctuation (see regular characters).
Words are first combined into paragraph segments. A paragraph segment may then contain any inline element of type:
Usually, a line ending terminates the paragraph segment. This means that a paragraph segment is for the most part just a line of text: |example I am a paragraph segment. I am another paragraph segment. Together we form a paragraph. |end
The exception to the rule is whenever a linkable or attached modifier within the paragraph segment spans more than a single line, in which case the paragraph segment also spans that distance. For example: |example I am a long paragraph segment! |end
Paragraphs are then formed of consecutive paragraph segments. A paragraph is terminated by:
A paragraph break (two consecutive line endings)
Any of the detached modifiers
Any of the delimiting modifiers
Any of the ranged tags
Any of the strong carryover tags
Norg has several detached modifiers. The name originates from their differentiation to the attached modifiers, which will be discussed later.
All detached modifiers must abide by the following rules:
A detached modifier can only occur at the beginning of the line (arbitrary whitespace (but nothing else!) may precede it)
A detached modifier must be immediately followed by whitespace or another detached modifier of the same type
NOTE in general a line ending is not allowed as the whitespace following a detached modifier. The only case where this is valid is for the closing modifier of the range-able detached modifiers.
The following table outlines all valid detached modifiers. It also adds various possible properties to each category which will be explained in more detail below. : . : Character : > : Name : > : Categories : _ : *
: > : Headings :: >
Structural
Nestable :: : _ : -
: > : Unordered Lists :: >
Nestable :: : _ : ~
: > : Ordered Lists :: >
Nestable :: : _ : >
: > : Quotes :: >
Nestable :: : _ : $
: > : Definitions :: >
Range-able :: : _ : ^
: > : Footnotes :: >
Range-able :: : _ : :
: > : Table cells :: >
Range-able :: : _ : %
: > : Attributes :: >
Nestable ::
The first detached modifier type is the structural modifier type. As the name suggests, modifiers under this category structure the Norg document in some form or another.
After a structural modifier, one paragraph segment is consumed as the title of the modifier.
A property of structural detached modifiers is that they consume all other non-structural detached modifiers, lower-level structural modifiers, inline markup and paragraphs; they are the most important detached modifier in the hierarchy of modifiers.
To manually terminate a structural detached modifier (like a heading) you must use a delimiting modifier. Structural detached modifiers are automatically closed when you use another structural modifier of the same or lower level.
|example
|end
Although headings are both structural and nestable (see next section), the former takes precedence over the latter, meaning that headings only affect a single paragraph segment as their title. This is for user convenience as it does not require an empty line right below a heading. Because of this precedence, headings are also non-grouping.
Headings serve as a way to categorize and organize other elements into smaller chunks for better readability. They are currently the only structural detached modifier present in the Norg syntax.
Nestable detached modifiers are a kind which may be repeated multiple times in order to produce a nested object of the given type. The nesting levels are capped at 6 in the tree-sitter parser but longer repetitions of the same modifier are allowed, falling back to the sixth nesting level. Other parsers may choose to support higher (or infinite) nesting levels.
Furthermore, in contrast to most other (standard) detached modifiers, this detached modifier type has no title, and affects the following paragraph
instead of only the next paragraph segment. Said paragraph then becomes the modifier's content. This means that in order to terminate the detached modifier contents, you need two consecutive line endings (see paragraph break).
Below you will find some examples of nestable detached modifiers.
|example
Unordered list level 1
Unordered list level 2
Unordered list level 3
Unordered list level 4
Unordered list level 5
Unordered list level 6
Unordered list level 7 (falls back to level 6 in the tree-sitter parser)
Unordered list level 1 This text is still part of the level 1 list item.
Unordered list level 2 This text is still part of the level 2 list item.
Unordered list level 3 This text is still part of the level 3 list item.
Unordered list level 4 This text is still part of the level 4 list item.
Unordered list level 5 This text is still part of the level 5 list item.
Unordered list level 6 This text is still part of the level 6 list item.
Unordered list level 7 (falls back to level 6 in the tree-sitter parser) This text is still part of the level 7 list item. |end
Unordered lists provide an easy way to enumerate items in an unordered fashion. Useful for data that's categorically similar but doesn't need to follow a strict order.
|example
Ordered list level 1
Ordered list level 2
Ordered list level 3
Ordered list level 4
Ordered list level 5
Ordered list level 6
Ordered list level 7 (falls back to level 6 in the tree-sitter parser)
Ordered list level 1 This text is still part of the level 1 list item.
Ordered list level 2 This text is still part of the level 2 list item.
Ordered list level 3 This text is still part of the level 3 list item.
Ordered list level 4 This text is still part of the level 4 list item.
Ordered list level 5 This text is still part of the level 5 list item.
Ordered list level 6 This text is still part of the level 6 list item.
Ordered list level 7 (falls back to level 6 in the tree-sitter parser) This text is still part of the level 7 list item. |end
This list type is only useful for data that needs to be kept in sequence. In contrast to other formats which may use a syntax like 1.
/1)
, Norg counts the items automatically - this reduces complexity and makes reordering items simple.
|example
Quote level 1
Quote level 2
Quote level 3
Quote level 4
Quote level 5
Quote level 6
Quote level 7 (falls back to level 6 in the tree-sitter parser)
Quote level 1 This text is still part of the level 1 quote.
Quote level 2 This text is still part of the level 2 quote.
Quote level 3 This text is still part of the level 3 quote.
Quote level 4 This text is still part of the level 4 quote.
Quote level 5 This text is still part of the level 5 quote.
Quote level 6 This text is still part of the level 6 quote.
Quote level 7 (falls back to level 6 in the tree-sitter parser) This text is still part of the level 7 quote. |end
Quotes are rather self-explanatory - they allow you to cite e.g. a passage from another source.
|example % attrib1 %% attrib2 %%% attrib3 %%%% attrib4 %%%%% attrib5 %%%%%% attrib6 |end Attributes are detached modifiers that exist solely for the purpose of having altered behavior through carryover tags. These can then be referenced within attached modifier extensions and the tags applied to the attribute will be applied to the attached modifier with said attribute.
These modifiers can be nested to create a hierarchy of attributes. Below is an example of this in action: |example % color
You can impose limits on where the attribute can be used through the attribute-limits
tag, which should be placed before the attribute definition. The tag takes in a list of the following parameters:
none
- no limits
verbatim
- can be used only for the `verbatim` attached modifier
math
- can be only used on the $mathematics$ attached modifier
macro
- can be only used on the inline ¯o& attached modifier
links
- can only be used on links (this includes anchors)
non-verbatim
- for all the other non-verbatim attached modifiers (bold, italic, subscript, superscript, underline, the null modifier etc.)
These limits can be chained, i.e. #attribute-limits links non-verbatim
.
|example >I am not a quote
some preceding text > I am also not a quote
>- I am not a valid detached modifier
> I am only a level 1 quote
* I am not a valid heading title. |end
Range-able detached modifiers can occur in two forms:
As a single detached modifier in which case they affect:
The next paragraph_segment
which becomes the title
Any following paragraph which becomes the content
As a pair of two detached modifiers in which case:
The next paragraph_segment
also becomes the title
The content continues until the "closing" detached modifier is found
The closing modifier has the same rules as an opening detached modifier except it must be directly succeeded by a line ending in contrast to the whitespace character which must follow the opening modifier.
Definitions are primarily of use to people who write technical documents. They consist of a term, and then are followed by a definition of that term.
|example
Definition content. |end
To create longer definitions, use the ranged definition syntax instead: |example
Content of the definition.
Which scans up to the closing modifier.
|end
Footnotes allow the user to give supplementary information related to some text without polluting the paragraph itself. Footnotes can be linked to using linkables.
|example
To create longer footnotes, use the ranged footnote syntax instead: |example
|end
Table cells are used to, well, build up a table. Here are a few examples of table cells: |example : A1 Content of table cell at A1
. :: A2
Content of table cell at
A2
(in a quote). :: |end Their semantics are described in more detail in the semantics document, which we recommend reading if you are interested in the behavior of objects as opposed to how they are defined.
NOTE In order to make tables more aesthetically pleasing, they're commonly mixed with the intersecting modifier syntax to produce the following: |example : A1 : Content of table cell at A1
. |end
Both nestable and range-able detached modifiers have a unique quality - when several consecutive modifiers of the same type are encountered (by consecutive we mean NOT separated via a paragraph break), they are treated as one whole object. This is crucial to understand as it is required for the many types of carryover tags to function.
|example The following items naturally group because they are range-able, for example forming a definition list:
Definition 1!
Definition 2! |end
|example Together, these form one whole unordered list:
List item 1
List item 2 |end
|example
List item in one list
This item is in another list, because we used a paragraph break to split these items |end
In Norg, structural detached modifiers and indent segments may be terminated by a delimiting modifier. This kind of modifier must abide by the following rules:
A delimiting modifier can only occur at the beginning of the line (arbitrary whitespace (but nothing else!) may precede it)
A delimiting modifier must consist of two or more consecutive modifiers of the same type (a single character cannot be used to avoid false-positives during the typing process; plus a single character can look quite confusing/ugly when used like this...)
A delimiting modifier must be followed by an immediate line ending (without any extra whitespace; this disambiguates them from nestable detached modifiers like for example an unordered list item vs. the --
delimiting modifier)
This modifier uses the -
character and immediately closes the current nesting level (decreases the current nesting level by one). |example
Text under first level heading.
Text under second level heading.
Text under first level heading again. |end
This modifier uses the =
character and immediately closes all nesting levels. |example
Text under first level heading.
Text under second level heading.
Text belonging to no heading level (i.e. belonging to the document's root). |end
This modifier uses the _
character and simply renders a horizontal line. It does NOT affect the heading level but immediately terminates any paragraph. |example
Text under first level heading.
This is a new paragraph separated from the previous one by a horizontal line. This text still belongs to the first level heading. |end
Detached modifiers support extensions which must immediately follow the detached modifier (or another extension). Note that detached modifiers must be succeeded with whitespace, therefore by "immediately followed" we mean after the whitespace character in the detached modifier, e.g. - (x) List item
(lang:norg).
The syntax is as follows:
An extension starts with a (
char
Immediately a special character must follow. This character determines the type of extension.
Some extensions can support parameters - if this is the case, the special character must be followed with whitespace after which the parameters (a sequence of words and/or newlines) ensue. Not all extensions support parameters and for good reason. There is no need to attach extra metadata to a done or undone state for instance. Several extensions should be delimited with the contextual `|` delimiter.
A \|
character may be matched, which allows the user to chain many extensions together, e.g. (x|# A)
(lang:norg) (done with a priority of A).
Finally a )
char closes the extension.
NOTE: The whole detached modifier extension must be followed by whitespace.
The TODO item extension assigns a task status to a certain modifier. You probably know this concept from Org where unordered lists can become tasks. In Norg we take this concept to the next level because any detached modifier can be assigned a task status. This can for example be useful for the author of a document to keep track of the status of certain sections.
The following characters are reserved for the TODO status extension:
| |
undone (a literal space)
x
done
?
needs further input/clarification
!
urgent
+
recurring (with an optional timestamp)
-
in-progress/pending
=
on hold
_
put down/cancelled
Some examples include: |example
Undone
Done
Undone with a priority of B
Recurring
5th Jan) Recurring every 5th of January |end
Apart from just being able to assign a TODO state it is also possible to apply more complex states with parameters to certain indicators. Such examples are the timestamp extension and the priority extension. In the following sections you will find descriptions for a few other extensions supported within Norg.
The timestamp extension allows you to associate a detached modifier with a date/time. The syntax for a timestamp is as follows: <day>,? <day-of-month> <month> <year> <time> <timezone>
The <day>
value is reliant on the current locale, but the following alterations of that value are permitted:
Full version (e.g. Tuesday
, Wednesday
)
An unambiguous shorthand (a shorthand that can uniquely identify the day), e.g. Tue
, We
, M
(Monday), Frid
. Something like T
is not allowed, as both Tuesday
and Thursday
could satisfy the input.
The ,?
expression means that a ,
character may optionally exist in that location.
The <day-of-month>
value is simply a numeric value with at most 3 digits (to disambiguate it from the <year>
value).
The <month>
value is a word-based representation of the current month (i.e. October
, January
etc.) dependent on the current locale. The same shorthand rules apply as in the <day>
value.
The <year>
value must be a numeric value with at least 4 digits.
The <time>
value must consist of this format (in regex): |\d{1,2}:\d{2}(\.\d{1,2})?|
. Some examples would be: 18:00
, 5:32
, 00:12.32
.
Obviously, you're not required to type the whole syntax out every time. Any of the elements in angled brackets (<>
) can be dropped/ignored, but the order of those values may not change! Some examples of valid timestamps include:
Sat, 29 Oct 1994 19:43.31 GMT
We 12th Jan 2022
Apart from just being able to supply a timestamp, you are also permitted to provide a range. The syntax is simple, and is contained within the extension: |example <- Also valid |end You can even omit some fields from either one of the sides like so: |example |end The matching fields will be automatically completed based on the information of the other half.
This extension allows you to specify a priority of your detached modifier extension.
Syntax: |example
|end Note that Norg does not specify strict semantics for this detached modifier extension, and as such there is no set-in-stone way to specify priorities. The most common (and recommended) way to specify priorities is to go from A-Z
, but many also prefer 0-9
or even named priorities like LOW
/MEDIUM
/HIGH
.
Neorg's GTD implementation even repurposes the priority for use as contexts, so yes, this detached modifier extension is very versatile.
As the name suggests, this extension marks something as "due before x", where x is a timestamp. Especially useful in GTD and other forms of note-taking and time management applications.
Syntax: |example
Do this before the 5th of February. |end
A counterpart to the due date extension - defines when a task begins, also useful in GTD.
Syntax: |example
This task starts after the 5th of February. |end
Since nestable detached modifiers can only contain a paragraph this can cause severe limitations because the insertion of e.g. code blocks is not possible. To alleviate this deficiency, the detached modifier suffix exists, which temporarily increases the current indentation level to allow complex nested items within.
There are two variations of the indent segment, the slide and the indent segment. NOTE After a detached modifier suffix is matched (either :
or ::
) a line ending must follow instantly.
The slide, denoted with a single :
, allows for a single complex item below: |example
This is the term's definition. |end
This complex item may be any non-structural detached modifier, tag or paragraph.
The indent segment, denoted with two colons (::
), creates a ranged version of the slide. This indent segment must be closed with any of the delimiting modifiers, or an element of the same type with the same or lower nesting level. By "lower" nesting level we mean higher up in the hierarchy of nodes, or in other words unordered_list_level_1
is "lower" than an unordered_list_level_2
item, because it is nested less.
The indent segment may contain an arbitrary amount of complex items.
Examples: |example
This is some content.
Definition.
This is the second item of the list. The indent segment did not need to be terminated.
This is another list.
|details
hello world! |end
This is a nested item in the indent segment
And so is this.
But you can still continue your content here.
Since there was no other item of the same type after the indent segment it must be closed with ---
or ===
. |end
|end |end
|comment
|example |comment This is a very long comment with some content and with some markup!
italic and bold. |end |end
|details
|example |details
And this. |end |end
A commonly arising question is "how are these interpreted at parse time?" - can you link to elements within |comment
tags? What governs the behavior of these differing tags?
The answer may be illustrated simply by showing how these tags are implemented. As mentioned in the macro tags section, all tag types (apart from the macro tag) are a macro invocation under the hood. Below are the implementations for |comment
and |group
, respectively:
|example =comment ... =end |end
|example =group ... =end |end
The |comment
tag evaluates to no value. Anything that is placed within a comment during invocation (the ...
parameter) is simply dropped. Because of this it is not possible to link to elements within comment tags. The |group
tag returns everything that you give it, because of this it is possible to freely link to any element within a |group
.
To summarize - the behavior of each individual standard ranged tag is fully governed by its implementation - see the semantics document for more details.
This is some content. (which is still red)
This is also some content. (which is normal-colored) |end
Special behavior for indent segments: |example
List item 1
List item 2 (which is red)
But this isn't red
Neither is this
This is green.
This is also green
And so is this.
|end
This is some content.
This is also some content. |end
The infirm tag is the simplest form of executing a macro. It is a single-line, embeddable macro invocation with the ability to supply parameters. It is denoted with the .
character.
Below is an example: |example =LoremIpsum Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. =end
This is a paragraph, and below you will find the lorem ipsum text: .LoremIpsum This is still the same paragraph (assuming the macro invocation only inserted text; which it did in this specific example). |end
This section discusses attached modifiers (which originally gave rise to the name of detached modifiers as their natural counter-parts). Attached modifiers encapsulate some text within a paragraph and change the way it is displayed in the document. An attached modifier consists of two parts: the opening modifier and the closing modifier.
Below are the general rules for attached modifiers:
An opening modifier may only be preceded by whitespace or punctuation
An opening modifier may NOT be succeeded by whitespace
A closing modifier may NOT be preceded by whitespace
A closing modifier may only be succeeded by whitespace or punctuation
Attached modifiers can only span at maximum a single paragraph, i.e. they get terminated as soon as they encounter a paragraph break.
This means that this: |example
*this text* |end will not result in any bold text, as it's divided by a paragraph break. However, this: |example this text |end is fine, and will result in this text
being bold.
Nested attached modifiers should be closed in the opposite order they were opened.
Two or more consecutive attached modifiers of the same type (i.e. **
, //
etc.) should be instantly "disqualified" and parsed as raw text in all circumstances and without any exceptions.
Their name should be rather self-explanatory - both the opening and closing modifier are attached to one another.
The following attached modifiers exist and have respective meaning:
*bold*: bold
/italic/: italic
_underline_: underline
-strike-through-: strike-through
!spoiler!: spoiler
^superscript^: superscript (cannot be nested into subscript
)
,subscript,: subscript (cannot be nested into superscript
)
`inline code`: inline code
(disables any nested markup - verbatim)
$inline math$: $f(x) = y$ (verbatim)
&variable&: (verbatim)
|example Bold text
Bold text, .Bold text,
Bold text
Bold and italic <- closing modifiers closed in the opposite order they were opened Bold and italic and only bold Text with different markup types |end
|example
*Bold text * other text*Bold text*
*Bold text*other text * Bold text*
*Bold text * *Bold text*
Closed in the wrong order: /Bold and italic/
Also closed in the wrong order: /Bold and italic and only italic/ |end
This section expands a bit on the concept of the %null modifier%
in order to understand some of its use cases.
When used in a standalone fashion, the null modifier nullifies (removes) all of the text inside. This means that on its own it behaves like a comment, which is never rendered: |example Cats are very cute animals. |end
In higher layers, this modifier can have its behaviour extended with the attached modifier extension syntax, which essentially makes it a configurable modifier suit for many occasions. For example, if you wanted to make an arbitrary part of your text red, you may do: |example This part of the text is (color:red)! |end
Variables are a layer 5 attached modifier that allow a user to invoke a macro without any parameters and place the result inside e.g. a paragraph. For more information on their behavior see the semantics document.
Even with all the rules described in the above sections there are still some evident limitations with attached modifiers, namely:
Arbitrary whitespace within attached modifiers is not permitted: * bold *
is invalid and thus not bold.
Representing verbatim attached modifier chars within the corresponding verbatim blocks is not possible: |`I cannot place a (
) char inside here without accidentally terminating the block.|.
Free-form modifiers fix this with a special syntax to specify the beginning and end of a ranged
block. For example:
|example
Here, I can write `| leading and trailing whitespace (with a ` char) |
within a verbatim block without accidentally terminating it.
Here, I can use a literal $
inside inline math: $| 10$ + 10$ = 20$ |$.
|end
The use of pipes is special because the position of the pipe (i.e. whether it's before or after the
attached modifier) can unambiguously tell us whether that symbol is an opening attached modifier
or a closing one. It's thanks to this that whitespace is freely allowed within its content.
Aside from the details described above, free-form attached modifiers have the following properties:
- Backslashes (`\`) are treated as verbatim and do not mean an {*** escaping}[escape sequence]
(see {* precedence}).
- Despite being called "free-form" they can still only span a single paragraph (see {# attached
modifier range}).
** Link Modifier
The link modifier, `:`, is a special modifier type - it puts a twist on the original attached
modifier rules - in fact, it's the polar opposite.
As described in the {* attached modifiers} section, attached modifier types may not exist
in between words like so:
|example
abso/freaking/lutely!
|end
It's entirely plausible to want to do this however, which is why the {** link modifier}[link
modifier] was devised. With it, you can bridge attached modifiers and regular text together:
|example
abso:/freaking/:lutely!
|end
It is important to note that link modifiers do not need to occur in pairs. This:
|example
Ex:*ample* text
|end
Will also result in `ample` becoming *bold*. In fact, using a link modifier at the end will not
give the desired result (it will be rendered as a regular `:` char). To understand why keep
reading.
Through the examples above it is evident that there are two link modifier types: one where the
link modifier is an /opening/ link modifier (i.e. it appears before an opening attached modifier)
and one where it's a /closing/ link modifier (i.e. it appears after a closing attached modifier).
This distinction is visible even when they don't occur in pairs.
In the case that the link modifier is opening (the attached modifier appears on the right):
- The link modifier may only be preceded by a {# regular characters}[regular character]
(or, in other words, may /not/ be preceded by a {*** punctuation} character nor by a
{*** whitespace} character).
- The link modifier may only be succeeded by an opening attached modifier.
In the case that the link modifier is closing (the attached modifier appears on the left):
- The link modifier may only be preceded by a closing attached modifier.
- The link modifier may only be succeeded by a {# regular characters}[regular character].
If the above conditions are not met, then the character should be treated as a literal `:`.
** Attached Modifier Extensions
Similarly to {** detached modifier extensions}, attached modifier extensions serve as a way
to attach metadata to {* attached modifiers}.
The metadata that you can attach, however, differs from {** detached modifier extensions}, as they
serve different use cases.
The content of attached modifier extensions consists of a set of references to many
{*** attributes}. These attributes are delimited by the {* contextual `|` delimiter}.
If the attribute is part of a hierarchy (see {*** attributes}), you may use the `:`
character to link them together. Some inbuilt attributes are the `lang` and `color` hierarchies
(a comprehensive list can be found in the [semantics document]).
*** Examples
|example
`print("This is some python")`(lang:python) <- The lang:python attribute highlights the text as python
*some green and bold text!*(color:green) <- some green and bold text
{* Link location}[this is an important link](important|color:red) <- Highlights the link as big,
bold (important) and red.
|end
* Contextual `|` Delimiter
The pipe (`|`) character is a really nice character - it can be applied to many problems
and expressively represent certain behaviors, specifically /delimiting/. While also used for
{*** standard ranged tags} and {** free-form attached modifiers}, the pipe symbol is also used as
a delimiter for {** Detached Modifier Extensions}[detached] and {** Attached Modifier
Extensions}[attached] modifier extensions. Even though it's used 3 times for different purposes,
the contexts in which they are used in allows for them to be unambiguous. It also keeps intent
consistent across the format.
* Intersecting Modifiers
Norg is a syntax designed to be used by many - this includes many styles and preferences. Although
it's impossible to satisfy everyone, there are some variations of syntax that can be used to
"beautify" Norg markup.
The intersecting modifier does just that - it's a way to intersect two different paragraph
segments (and *only* paragraph segments) together on the same line.
The syntax is as follows:
- First, a {*** whitespace} character must be matched
- Next, the actual modifier (currently only `:`) must be matched.
- The token ends with another {*** whitespace} character.
The use case for the intersecting modifier is best illustrated by example:
|example
$ Term
This is a definition of that term.
|end
This is perfectly normal syntax that you would write day to day in Norg. But what if you're more
of a fan of one-liners? The `| : |` intersecting modifier (currently the only modifier of this
type) can be used to do just this:
|example
$ Term : This is a definition of that term.
|end
This syntax is especially favored for {*** table cells}:
|example
: A1 : Content of the cell at A1
: A2 : Content of the cell at A2
|end
The `| : |` syntax expands to a newline, which means that after expansion you get:
|example
: A1
Content of the cell at A1
: A2
Content of the cell at A2
|end
* Linkables
Finally, there is one more kind of inline syntax which is the {# linkables} kind.
Linkables can link to any element /anywhere/ in the document.
When resolving links, the first match should always be the only match, starting from the top of
the document and heading towards the bottom. This means that if there are two matches, the one at
the topmost part of the document should be chosen as the target.
Linkables are comprised of many segments, and can change meaning depending on the order those
segments were defined in.
Linkables are essentially a more lenient version of the {* attached
modifiers}[attached modifier] syntax. Below are the rules for linkables:
- An opening modifier may be instantly succeeded with anything /but/ a {#
line endings}[line ending].
- A closing modifier may *not* be preceded by a {# line endings}[line ending].
Below are a few examples of invalid linkables:
|example
this is not a {
* linkable}
nor is this a [linkable
]
<
this certainly isn't a linkable
>
|end
*An unclosed linkable may be treated as an error in the resulting syntax tree*.
** Link Location
The link location is defined through curly braces (`{}`) and contains the physical location
that the user would like to link to. Inside these curly braces you can find one (or more; with
limited inter-compatibility) of the following types of data:
- A {# file location}
- A {# line number}
- A {# URL} (most commonly to an external resource)
- A {# detached modifier} followed by the name of the linkable
-- {# nestable detached modifiers} can:*NOT* be linked to
- A {# custom detached modifiers}[custom detached modifier] specifically made for links (`/`,
`#`, `?`, `=`)
- A {**** Timestamps (`@`)}[timestamp]
*** File Location
The file location is a construct that allows you to specify the /target file/ into which you
want to link to. This allows you to *link to targets within other files* or just link to other
Norg files entirely.
When standalone, the link syntax will simply point to another `.norg` file relative to the
current file the link is contained in:
|example
{:path/to/other-file:}
|end
Note that you do *not* provide the `.norg` extension within the path.
+name path modifiers
You may use traditional modifiers in your path, like `/` (in e.g. `/my/file`) to signify the
root of your file system, `~` (in e.g. `~/Documents/my-file`) to signify the current user's home
directory, /or/ you can use the [Neorg]-specific `$` (in e.g. $/my/file
) to signify the root of the Neorg workspace. Since not all Norg files will be used strictly by Neorg, the workspace root can be implementation-specific - for git repos the workspace root could be simply the root of the repository, and for other note-taking apps it could simply be the root of the directory where all the notes are stored.
A file location may only be accompanied by a detached modifier, line number or the magic char, in which case the links look like so:
|example path/to/file##l-123 path/to/file# path/to/file##h2-level-2-heading |end
/
, @
and URLs are not allowed in combination with file locations:
|example path#file <- invalid path# <- invalid path#https://my-url <- also invalid |end
You can also link to a set line number within the current (or other Norg) file.
The syntax is as follows: |example Line 1 Line 2
This is a reference to line #l-2. This is a reference to line file##l-4 in a different file. |end
Disambiguating line numbers and URIs is quite simple - URIs do not begin with digits.
You can define a link to an external resource by simply putting in the URL:
|example https://github.com/nvim-neorg/neorg |end
Actions related to schemas like https://
, ftp://
etc. (when attempting to open the link) are handled by a lower level component running Norg, e.g. Neorg or the underlying Operating System.
Norg allows you to link to any structural or range-able detached modifier:
|example
Strict link to a level 1 heading: I am a level 1 heading |end
The inside of the link location looks just like a detached modifier definition, and that is because it pretty much is. You can substitute the *
char for any other structural or range-able detached modifier, except "ranged" versions of said modifiers - those are disallowed within the link syntax. By this we mean that syntax like {$$ Text}
is invalid. To link to a ranged definition you would still use {$ Text}
, there is no reason to make a distinction between a ranged and non-ranged detached modifier as both have the same meaning, one just allows more content to exist within itself.
Apart from linking to the detached modifiers outlined above, you can also link to a set of custom modifiers specifically designed for links. These are the #
(magic), /
(file), @
(timestamp), ?
(wiki link) and =
(extended) linkable locations.
#
) Sometimes you simply want to be lazy, or you want to link to an inline linkable that does not have a dedicated modifier to denote it - in these scenarios you would use the magic char: #
. It links to any item type. The syntax is exactly the same as with the other modifiers: {# My Location}
.
/
) Sometimes you may want to link to an external file that is not a Norg file. In that case you may use {/ /path/to/my/file.txt}
(notice the mandatory space after the /
char, just like with the detached modifiers). Paths are relative to the Norg file that contains the link unless started with a /
to denote your file system root.
In addition to just providing a path, you may also specify a line number at the end via a colon :
. Example: |example my-file.txt##l-123 <- This is a link to my-file.txt
at line 123 |end As with the path modifier syntax, the file linkable also supports special characters like ~
for the user's home directory and the special $
character to denote the root of the current workspace.
@
)The syntax for timestamps within links is the same as the syntax used in the timestamp extension.
Example: |example Frank's birthday is on . |end
?
)When building large knowledge bases it's sensible to want to quickly create links between files without worrying about the location of said file. The wiki link allows you to link to any heading in any file in the current workspace. You don't specify any file paths within the link, just the title of the heading you want to search for.
Syntax: |example Cats are mammals, they make for great house pets too! |end
For developers implementing this behavior: there are no restrictions in which order you parse your files to hop between wiki links, as long as the following conditions are met:
The current file is the first file that is searched (this allows for ?
to also work as a generic catchall link for all heading levels)
All files in the current workspace are parsed/enumerated (including subdirectories)
{:file:}
The wiki link can also be used with the {:file:}
to limit the search. It can actually double as a "heading catchall" operator as mentioned in the previous section - it will match all headings regardless of nesting level in the file provided.
=
) Apart from having links with set behaviors Norg also features an extendable link marked with the =
character. This link has its behaviors governed by attached modifier extensions supplied to the link and by the software running the Norg format (e.g. Neorg).
Syntax: |example
For a more detailed explanation of the behavior of this link consult the semantics document.
Although most linkable items are either structural or range-able, there are also syntax elements in Norg that are inline - these are the #name
carryover tag and the inline link target. Both of these can only be linked to through the the magic char.
You may have realized that there are many ways to reference a file:
{:my/file:}
{/ my/file.norg}
{file://my/file.norg}
Why are there this many?
{:my/file:}
is strictly to access .norg
files and nothing else. More specifically, it's designed to access a resource within a file ({:my/file:* Heading}
), with the side effect of being able to also exist in a standalone fashion ({:my/file:}
).
{/ my/file.norg}
is used to link to a file and a file only (vs {:my/file:* Heading}
which links to an element within a file). Although it can link to .norg
files, its main use is to link to non-.norg
files instead. Using the /
syntax also disallows you from accessing items within the file.
{file://my/file.norg}
is simply utilizing the file://
schema to access a file. This isn't the recommended way to link to files, but it exists simply because of URI schemas.
Within linkables it is possible to narrow down the search of the link via the | : |
scoping modifier. This modifier can exist because under normal circumstances when parsing e.g. the title of a heading a | : |
sequence of characters would be considered an intersecting modifier.
Below is an example of the scoping modifier in use: |example Heading Name : *** Level 3 heading |end
The search narrows the search to a Level 3 heading
within a level 1 heading called Heading
Name
. This search is descending in terms of nesting, in other words, you cannot do {*** Heading3 : * Heading1}
.
This scoping is not limited to any item type. You are free to perform searches like {$ Definition : $ Nested Definition : ^ Footnote}
, which searches for a footnote within a definition called Nested Definition
within a definition called Definition
.
Link descriptions are denoted by square brackets: []
. They contain the description for either a link location (by placing the description after the link location or an anchor declaration), an anchor definition (by placing the description before the link location) or an anchor declaration (where the only syntax item is the link description). Anchors are described later on.
Links in Norg can exist as a standalone link location in which case their text is used as the link title (often makes sense for headings):
|example I am a standalone link |end
When a custom description is required, it must be placed after the link location. This makes sense in terms of writing as you first define where you link to, and then annotate it afterwards:
|example Click here to find out more. |end
Norg also has a concept called anchors. These allow you to place a standalone link description inside of text (referred to as an anchor declaration). The target which this anchor links to can then be defined at another place in the document with an anchor definition which is an initial link description followed by a link location. This is especially useful when you want to link to the same target very often, like for example a specific website.
Below are a few usage examples: |example Neorg is a fancy organizational tool for everyone.
I like shilling Neorg sorry :( |end Here, we declare the anchor once at the top, then define the anchor at the very bottom. The [Neorg]
declaration points directly to the website, just like the definition does. It's like a copy + paste of the link location without needing to type it out.
Other than the declaration behavior described above anchors have no other special meaning and/or semantics, and behave just like regular links do. This means they can be used as a substitute for regular links should the user prefer the "description + location" syntax versus the "location + description" syntax.
Anchors (like links) may also be described by using [...]
, in which case the syntax looks like this: [anchor name][anchor description]
.
Finally, Norg also has the possibility of placing link targets at arbitrary inline positions in your document. We call these inline link targets which are formatted inside angled brackets: <>
.
|example One thing to mention is inline link targets - they allow you to link to any location in a document.
...
Refer to inline link targets if you are interested in learning more. |end
An important thing to note is that since inline link targets are - well - inline, they cannot be directly linked to with a dedicated char in the link syntax. To link to these syntax elements you may only use the magic char.
Unlike links and anchors, inline link targets may not have a description.
|example link
|example text
file#https://github.com file#file.txt file#
{
{
}
{ * text}
text[ text ]
text[ text] |end
Norg comes loaded with a predetermined set of attributes and macro tags for different layers of the syntax. These are defined in the semantics document.
Precedence in Norg is rather simple and intuitive.
All non-inline elements have direct precedence over all inline elements.
Inline elements with a deterministic start and end have greater priority than those that don't.
Verbatim elements have greater priority than non-verbatim elements.
Here's the full list ordered by decreasing precedence:
Tags (#infecting
, +carryover
, .infirm
, \|standard
, @verbatim
and =macro
)
Nestable detached modifiers and range-able detached modifiers (there is no such case where these could overlap)
Linkables ({}
, []
, <>
)
Verbatim free-form attached modifiers (\|
|
, \|
|
)
Verbatim attached modifiers
Standard (non-verbatim) free-form attached modifiers (|**|
, |//|
etc.)
Standard (non-verbatim) attached modifiers
Should any extra precedence problems arise (let us know if you find any) they can be disambiguated through a simple left-to-right precedence approach.
Note that although e.g. linkables are above standard attached modifiers, this does not mean that standard attached modifiers cannot contain linkables, but in case there is an overlap the linkable will have higher precedence.
For example, this is valid: |example i am a bold link! |end
However, in this case: |example *am I bold? - no! |end The link takes precedence, and no bold is rendered.
Norg is built up of layers, or in other words a set of features that a parser/tool can support depending on how much of the specification they'd like to deal with.
It's recommended to stick to these layers when implementing Norg in your own application (as it's easy to tell end users that an application supports e.g. "layer 2" of the Norg specification), but of course these can't apply to every possible use case. In such case you can use a custom layer and pick and choose what you want to support. Just make sure to let your users know which features you've implemented, so they don't get confused!
The first layers contains a very low level implementation of Norg's markup for use in e.g. a messaging application. This includes:
Attached Modifiers (excluding variables, inline mathematics and the null detached modifier)
The second layer outlines the basic structure for a document:
Nestable Detached Modifiers (only quotes, lists)
Linkables (broader support for links (minus timestamps (`@`), wiki links (`?`) and extendable links (`=`)), anchors)
Verbatim Ranged Tags (@code
, etc.)
This layer is for documents of medium/high complexity:
Support for timestamps (`@`) and wiki links (`?`) in links
Carryover Tags (#name
, #color
+name
, +color
etc.)
Range-able Detached Modifiers (excluding table cells)
The fourth layer supports 80% of the most commonly used features for writing high level and typeset Norg documents.
Support for extendable links (`=`) and scoping
Standard Ranged Tags (\|comment
, etc.)
The inline mathematics ($$
) and variable (&&
) attached modifiers
Layer five can be seen as the ultimate boss - it features the dynamic elements of Norg documents, including macros, variables and parsing of eval blocks.
Interpretation/Execution of macro tags
Semantic understanding/execution of all other tag types
Evaluation of @code
blocks for the NIP language (if they are marked with #eval
).
Optional footnote content. |end
↩︎Content of the footnote.
Which scans up to the closing modifier.
↩︎It should be mentioned that a parser of the Norg format is not required to perform any timestamp analysis further than detecting what set of characters contain a timestamp. The actual interpretation of its internal fields and the interpretation of a range are the responsibility of the semantic analyzer (see also the semantics document).
↩︎