OurBigBook
The OurBigBook Project creates writing tools to help anyone publish textbooks, with a strong focus on the natural sciences.
Mission: to live in a world where you can learn university-level mathematics, physics, chemistry, biology and engineering from perfect free open source books that anyone can write to get famous.
How to get there: create a website that incentivizes learners (notably university students taking courses) to write freely licensed university-level natural science books in their own words for free. Their motivation for doing that are:
  • getting their knowledge globally recognized and thus better jobs
  • improving the world
  • learning by teaching
Figure 1. Logo of the OurBigBook Project.
The OurBigBook Web website is the main tool of the project. OurBigBook CLI is another complementary tool.
You can donate to the OurBigBook Project to sponsor its development in the following ways:
  • cirosantilli.com/sponsor: give money directly to Ciro Santilli, who is currently the sole maintainer and developer of the project. If things ever grow in scope we will set up a foundation and register a charity for it. One may dream.
  • by project merchandise, see: Section 12.14.2. "Merchandise"
We are happy to discuss paid contracts to implement specific features, to get in touch see: contact.
The following sections cover different ways to use tools from the OurBigBook:
  • cross references to any header (including e.g. h2, h3, etc. in other files), images, etc. with amazing error checking and reporting: never break internal links without knoing again, and quickly find out what broke when you do. E.g.:
    animal.bigb
    = Animal
    
    <Bats> are <flying animals>.
    Mammal.bigb
    = Flying animal
    
    == Bat
    Animal.bigb would render something like:
    <a href="flying-animal.html#bat">Bats</a> are <a href="flying-animal.html">flying animals</a>.
    The following would fail and point you out the file and line of the failure:
    • nonexistent id:
      <Weird animal not documented>
    • duplicate IDs:
      = Animal
      
      == Dog
      
      == Cat
      
      == Dog
  • KaTeX server side mathematics, works on browsers with JavaScript disabled:
    I like $\sqrt{2}$, but I adore this \x[equation-quadratic-equation]:
    
    $$
    x^2 + 2x + 1
    $$
    {title=Quadratic equation}
  • multi-file features out of the box so you don't need a separate wrapper like Jekyll to make a multi-page website:
    • cross file references
    • single-source multi-format output based on includes and build options:
      • by default, one HTML per source with includes rendered as links between pages, e.g.:
        README.bigb
        = My website
        
        == h2
        
        \Include[not-readme]
        not-readme.bigb
        = Not readme
        
        == Not readme h2
        produces index.html and not-readme.html
      • with the -S, --split-headers option, you can output each header of an input file into a separate output file. The previous filesystem would produce:
        • index.html: which contains the full README.bigb output
        • split.html: split version of the above containing only the = My website header and not h2
        • h2.html: only contains the h2 header
        • not-readme.html contains the full output of not-readme.bigb
        • not-readme-split.html: only contains the = Not readme header
        • not-readme-h2.html: only contains the = Not readme h2 header
        Each of those pages automatically gets a table of contents
      • --embed-includes single file output from multiple input files. Includes are parsed smartly, not just source copy pasted, e.g. included headers are shifted from h1 to h2 correctly.
        On the previous sample filesystem, it would produce a single output file index.html which would contain a header structure like:
        = My website
        
        == h2
        
        === Not readme
        
        ==== Not readme h2
      • supports both local serverless rendering to HTML files for local viewing, and server oriented rendering such as GitHub pages, e.g. cross references automatically get .html extension and or not. E.g.:
        • locally, a link \x[not-readme] would render as <a href="not-readme.html"> and not-readme.bigb produces not-readme.html
        • when publishing, \x[not-readme] would render as <a href="not-readme"> and not-readme.bigb also produces not-readme.html, which the server converts to just http://my-website.com/not-readme
    • cross file configuration files to factor out common page parts like headers, footers and other metadata, e.g.:
    • table of contents that crosses input files via includes. E.g. in:
      README.bigb
      = My website
      
      == h2
      
      \Include[not-readme]
      not-readme.bigb
      = Not readme
      
      == Not readme h2
      the table of contents for index.html also contains the headers for not-readme.bigb producing:
      • My website
        • h2
          • Not readme
            • Not readme h2
      This means that you can split large splitDefault input files if rendering starts to slow you down, and things will still render exactly the same.
    • check that local files and images linked to actually exist: \a external argument. E.g.:
      \a[i-don-exist.txt]
      would lead to a build error.
    • associate headers to files with the \H file argument e.g.:
      Here's an example of a nice image: \x[file/path/to/my/image.png].
      
      = path/to/my/image.png
      {file}
      
      This image was taken when I was on vacation!
      would automatically add a preview of the image on the output.
  • advanced header/ID related features:
    • ID-based header levels:
      = Furry animal
      
      I like \x[furry-animal]{p}, especially my cat, here is his photo: \x[image-my-cat].
      
      == Cat
      
      \Image[My_cat.jpg]
      {title=My cat}
    • scopes either with directories or with within a single file:
      See the important conclusion of my experiment: \x[report-of-my-experiment/conclusion]
      
      = Report of my experiment
      {scope}
      
      == Introduction
      
      == Middle
      
      == Conclusion
    • cross reference title inflection for capitalization and pluralization, e.g.;
      = Dog
      
      == Snoopy
      {c}
      
      \x[dog]{c}{p} are fun. But the \x[dog] I like the most is \x[snoopy]!
      would render:
      • \x[dog]{c}{p} as Dogs: capitalized because of {c} and pluralized because of {p}
      • \x[dog] as dogs: auto lowercased because its header = Dog does not have {c}
      • \x[snoopy] as Snoopy: title capitalization kept to upper case due to {c} on the header == Snoopy
    • synonyms, e.g.:
      = User interface
      
      = UI
      {c}
      {synonym}
      {title2}
      
      \x[user-interface]{c} is too long, I just say \x[ui].
      would render something like:
      <a href="#user-interface">User interface</a> is too long, I just say <a href="user-interface">UI</a>
      Furthermore, this also generates a output file:
      ui.html
      which redirects to the ain user-interface.html, so it serves as a way to have backward compatibility on page renames.
      And the title2 makes it appears on the main title under parenthesis, something like:
      <h1>User interface (UI)</h1>
    • header disambiguation, e.g.:
      My favorite fruits are \x[apple-fruit]{p}!
      
      My favorite least favorite brand is is \x[apple-company]! \x[apple] computers are too expensive.
      
      == Apple
      {disambiguate=fruit}
      
      == Apple
      {c}
      {disambiguate=company}
      
      = Apple
      {c}
      {synonym}
      which renders something like:
      • \x[apple-fruit]{p}: <a href="apple-fruit">apples</a>
      • \x[apple-company]: <a href="apple-company">Apple</a>
      • \x[apple]: also <a href="apple-company">Apple</a> because of the synonym
      • == Apple\n{disambiguate=fruit}: <h2 id="apple-fruit">Apple (fruit)</h2>
      • == Apple\n{disambiguate=company}: <h2 id="apple-company">Apple (company)</h2>
    • tags are regular headers: \H child argument, \x child argument
      = Animal
      
      == Dog
      {tag=domestic}
      {tag=cute}
      
      == Cat
      {tag=domestic}
      {tag=cute}
      
      == Bat
      {tag=flying}
      
      = Flying
      
      = Cute
      
      = Domestic
    • unlimited header levels, levels higher than 6 are rendered in HTML as an appropriately styled divs with an ID:
      = h1
      
      == h2
      
      === h3
      
      ==== h4
      
      ===== h5
      
      ====== h6
      
      ======= h7
      
      ======== h8
    • generate lists of incoming links between internal headers: it shows every internal link coming into the current page
  • automatic file upload and directory listing of non OurBigBook files: _raw directory, e.g.:
    • link to a file:
      The file \a[index.js] is cool.
      which renders as:
      The file index.js is cool.
    • link to a directory:
      The directory \a[file_demo] is cooler.
      which renders as:
      The directory file_demo is cooler.
  • is written in JavaScript and therefore runs natively on the browser to allow live previews as shown at: docs.ourbigbook.com/editor
  • helps you with the publishing:
    • ourbigbook --publish publishes in a single command to the configured target (default GitHub Pages)
    • OurBigBook tries to deal with media such as images and video intelligently for you, e.g.: Section 4.2.7.3. "Where to store images". E.g. you can keep media in a separate media repository, my-media-repository, and then by configuring on ourbigbook.json:
      "media-providers": {
        "github": {
          "default-for": ["image", "video"],
          "path": "media",
          "remote": "yourname/myproject-media"
        }
      }
      you can use images in that repository with:
      \Image[My_image_basename.jpg]
      instead of:
      \Image[https://raw.githubusercontent.com/cirosantilli/myproject--media/master/My_image_basename.jpg]
    • inotifywait watch and automatically rebuild with -w, --watch:
      ourbigbook --watch input-file.bigb
  • automatic code formatting: --format-source
OurBigBook is designed entirely to allow writing complex professional HTML and PDF scientific books, blogs, articles and encyclopedias.
OurBigBook aims to be the ultimate LaTeX "killer", allowing books to be finally published as either HTML or PDF painlessly (LaTeX being only a backend to PDF generation).
It aims to be more powerful and saner and than Markdown and Asciidoctor.
Originally, OurBigBook was is meant to be both saner and more powerful than Markdown and Asciidoctor.
But alas, as Ciro started implementing and using it, he started to bring some Markdown insanity he missed back in.
And so this "degraded" slightly into a language slightly saner than Asciidoctor but with an amazing Node.js implementation that makes it better for book writing and website publishing.
Notably, we hope that our escaping will be a bit saner backslash escapes everything instead of Asciidoctor's "different escapes for every case" approach: github.com/asciidoctor/asciidoctor/issues/901
But hopefully, having starting from a saner point will still produce a saner end result, e.g. there are sane constructs for every insane one.
It is intended that this will be an acceptable downside as OurBigBook will be used primarily large complex content such as books rather than forum posts, and will therefore primarily written either:
For example, originally OurBigBook had exactly five magic characters, with similar functions as in LaTeX:
  • \ backslash to start a macro, like LaTeX
  • { and }: left and right square brackets to delimit optional macro arguments
  • [ and ]: left and right curly braces bracket to start an optional arguments
and double blank newlines for paragraphs if you are pedantic, but this later degenerated into many more with insane macro shortcuts.
We would like to have only square brackets for both optional and mandatory to have even less magic characters, but that would make the language difficult to parse for computer and humans. LaTeX was right for once!
This produces a very regular syntax that is easy to learn, including doing:
  • arbitrary nesting of elements
  • adding arbitrary properties to elements
This sanity also makes the end tail learning curve of the endless edge cases found in Markdown and Asciidoctor disappear.
The language is designed to be philosophically isomorphic to HTML to:
  • further reduce the learning curve
  • ensure that most of HTML constructs can be reached, including arbitrary nesting
More precisely:
  • macro names map to tag names, e.g.: \\a to <a
  • one of the arguments of macros, maps to the content of the HTML element, and the others map to attributes.
    E.g., in a link:
    \a[http://example.com][Link text\]
    the first macro argument:
    http://example.com
    maps to the href of <a, and the second macro argument:
    Link text
    maps to the internal content of <a>Link text<>.
The high sanity of OurBigBook, also makes creating new macro extensions extremely easy and intuitive.
All built-in language features use the exact same API as new extensions, which ensures that the extension API is sane forever.
Markdown is clearly missing many key features such as block attributes and cross references, and has no standardized extension mechanism.
The "more powerful than Asciidoctor" part is only partially true, since Asciidoctor is very featureful can do basically anything through extensions.
The difference is mostly that OurBigBook is completely and entirely focused on making amazing scientific books, and so will have key features for that application out-of-the box, notably:
and we feel that some of those features have required specialized code that could not be easily implemented as a standalone macro.
Another advantage over Asciidoctor is that the reference implementation of OurBigBook is in JavaScript, and can therefore be used on browser live preview out of the box. Asciidoctor does Transpile to JS with Opal, but who wants to deal with that layer of complexity?
Static wiki generators: this is perhaps the best way of classifying this project :-)
Static book generators:
Less related but of interest, similar philosophy to what Ciro wants, but no explicitly reusable system:
Ciro Santilli developed OurBigBook to perfectly satisfy his writing style, which is basically "create one humongous document where you document everything you know about a subject so everyone can understand it, and just keep adding to it".
cirosantilli.com is the first major document that he has created in OurBigBook.
He decided to finally create this new system after having repeatedly facing limitations of Asciidoctor which were ignored/wontfixed upstream, because Ciro's writing style is not as common/targeted by Asciidoctor.
Following large documents Ciro worked extensively on:
made the limitations of Asciidoctor clear to Ciro, and were major motivation in this work.
The key limitations have repeatedly annoyed Ciro were:
  • cannot go over header level 6, addressed at: unlimited header levels
  • the need for -S, --split-headers to avoid one too large HTML output that will never get indexed properly by search engines, and takes a few seconds to load on any browser, which is unacceptable user experience
OurBigBook Markup is the lightweight markup language used in the OurBigBook Project project.
It works both on the OurBigBook Web dynamic website, and on OurBigBook CLI static websites from the command line.
OurBigBook Markup files use the .bigb extension.
Paragraphs are made by simplying adding an empty line, e.g.:
My first paragraph.

And now my second paragraph.

Third one to finish.
which renders as:
My first paragraph.
And now my second paragraph.
Third one to finish.
Headers are created by starting the line with equal signs. The more equal signs the deeper you are, e.g.:
= Animal

== Mammal

=== Dog

=== Cat

== Bird

=== Pigeon

=== Chicken
On OurBigBook Web, the toplevel header of each page goes into a separate title box, so there things would just look like:
  • title box: "Animal"
  • body:
    == Mammal
    
    === Dog
    
    === Cat
    
    == Bird
    
    === Pigeon
    
    === Chicken
You can can use any header as a tag of any other header, e.g.:
= Animal

== Dog
{tag=Cute animal}

== Turtle
{tag=Ugly animal}

== Animal cuteness

=== Cute animal

=== Ugly animal
Headers have several powerful features that you can read more about under \H arguments, e.g. \H synonym argument and \H disambiguate argument.
To link to any of your other pages, you can use angle brackets (less than/greater than) signs:
I have a <cute animal>. <Birds> are too noisy.
Note how capitalization and pluralization generally just work.
To use a custom link text on a reference, use the following syntax:
I have a <cute animal>[furry animal]. <Birds>[feathery animals] are too noisy.
External links can be input directly as:
This is a great website: https://example.com

I really like https://example.com[this website].
which renders as:
This is a great website: example.com
I really like this website.
Code blocks are done with backticks `. With just one backtick, you get a code block inside the text:
The function call `f(x + 1, "abc")` is wrong.
which renders as:
The function call f(x + 1, "abc") is wrong.
and with two ore more backticks you get a code block on its own line, and possibly with multiple code lines:
The function:
``
function f(x, s) {
  return x + s
}
``
is wrong.
which renders as:
The function:
function f(x, s) {
  return x + s
}
is wrong.
Mathematics syntax is very similar to code blocks, you can just enter you LaTeX code in it:
The number $\sqrt{2}$ is irrational.

The same goes for:
$$
\frac{1}{\sqrt{2}}
$$
which renders as:
The number is irrational.
The same goes for:
We also have a bunch of predefined macros from popular packages, e.g. \dv from the physics package for derivatives:
$$
\dv{x^2}{x} = 2x
$$
which renders as:
You can refer to specific equations like this:
As shown in <equation Very important equation>, this is true.

$$
\frac{1}{\sqrt{2}}
$$
{title=Very important equation}
which renders as:
As shown in Equation 3. "Very important equation", this is true.
Equation 3. Very important equation.
Images and videos are also easy to add and refer to:
As shown at <image Cute chicken chick>, chicks are cute.

\Image[https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/H%C3%BChnerk%C3%BCken_02.jpg/800px-H%C3%BChnerk%C3%BCken_02.jpg?20200716091201]
{title=Cute chicken chick}

\Video[https://www.youtube.com/watch?v=j_fl4xoGTKU]
{title=Top Down 2D Continuous Game by Ciro Santilli (2018)}
which renders as:
As shown at Figure 2. "Cute chicken chick", chicks are cute.
Figure 2. Cute chicken chick. Source.
Video 1. Top Down 2D Continuous Game by Ciro Santilli (2018) Source.
Images can take a bunch of options, about which you can read more about at image arguments. Most should be self explanatory, here is an image with a bunch of useful arguments:
\Image[https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/H%C3%BChnerk%C3%BCken_02.jpg/800px-H%C3%BChnerk%C3%BCken_02.jpg?20200716091201]
{title=Ultra cute chicken chick}
{description=
The chicken is yellow, and the hand is brown.

The background is green.
}
{border}
{height=400}
{source=https://commons.wikimedia.org/wiki/File:H%C3%BChnerk%C3%BCken_02.jpg}
which renders as:
Figure 3. Ultra cute chicken chick. Source.
The chicken is yellow, and the hand is brown.
The background is green.
Lists are written by starting the line with an asterisk *:
* first item
* second item
* and the third
which renders as:
  • first item
  • second item
  • and the third
A nested list:
* first item
  * first item version 1
  * first item version 2
    * first item version 2 1
    * first item version 2 2
* second item
* and the third
which renders as:
  • first item
    • first item version 1
    • first item version 2
      • first item version 2 1
      • first item version 2 2
  • second item
  • and the third
Lists items can contain any markup, e.g. paragraphs. You just need to keep the same number of spaces, e.g.:
* first item.

  Second paragraph of first item.

  And a third one.
* second item
  * second item v1

    Another paragraph in second item v1
  * second item v2
which renders as:
  • first item.
    Second paragraph of first item.
    And a third one.
  • second item
    • second item v1
      Another paragraph in second item v1
    • second item v2
Tables are not very different from lists. We use double pipes for headers ||, and a single pipe | for regular rows:
|| City
|| Sales

| Salt Lake City
| 124,00

| New York
| 1,000,000
which renders as:
City Sales
Salt Lake City 124,00
New York 1,000,000
To add a title we need to use an explicit \Table macro as in:
See <table Sales per city> for more information.

\Table
{title=Sales per city}
[
|| City
|| Sales

| Salt Lake City
| 124,00

| New York
| 1,000,000
]
which renders as:
See Table 1. "Sales per city" for more information.
Table 1. Sales per city.
City Sales
Salt Lake City 124,00
New York 1,000,000
This section documents all OurBigBook macros.
Macros are magic commands that do cool stuff, e.g. \Image to create an image.
The most common macros also have insane macro shortcuts to keep the syntax shorter.
The general macro syntax is described at Section 4.3. "OurBigBook Markup syntax".
Insane autolink, i.e. the link text is the same as the link address:
The website http://example.com is cool. See also:

\Q[http://example.com/2]
which renders as:
The website example.com is cool. See also:
example.com/2
Exact parsing rules described at: Section 4.2.1.4. "Insane link parsing rules".
Note that the prefixes http:// and https:// are automatically removed from the displayed link, since they are so common that they woudly simply add noise.
Equivalent sane version:
The website \a[http://example.com] is cool.

\Q[\a[http://example.com/2]]
which renders as:
The website example.com is cool.
example.com/2
Insane link with custom text:
The website http://example.com[example.com] is cool.
which renders as:
The website example.com is cool.
Equivalent sane version:
The website \a[http://example.com][example.com] is cool.
which renders as:
The website example.com is cool.
If the custom text is empty, an autolink is generated. This is often useful if you want your link to be followed by punctuation:
The website is really cool: http://example.com[].
which renders as:
The website is really cool: example.com.
This could also be achieved with the sane syntax of course, but this pattern saves a tiny bit of typing.
Link with multiple paragraphs inside it:
\a[http://example.com][Multiple

paragraphs]
which renders as:
Link to a file in the current repository:
The file \a[index.js] is cool.
which renders as:
The file index.js is cool.
This links to a raw view of that file.
Link to a directory in the current repository:
The directory \a[file_demo] is cooler.
which renders as:
The directory file_demo is cooler.
This links to an output file that contains a generated directory listing of that directory.
The link target, e.g. in:
\a[http://example.com]
href equals http://example.com.
Important behaviours associated with this property for local links are detailed at Section 4.2.1.3. "\a external argument":
Analogous to the \x ref argument, e.g.:
Trump said this and that.https://en.wikipedia.org/wiki/Donald_Trump_Access_Hollywood_tape#Trump's_responses{ref}https://web.archive.org/web/20161007210105/https://www.donaldjtrump.com/press-releases/statement-from-donald-j.-trump{ref} Then he said that and this.https://en.wikipedia.org/wiki/Donald_Trump_Access_Hollywood_tape#Trump's_responses{ref}https://web.archive.org/web/20161007210105/https://www.donaldjtrump.com/press-releases/statement-from-donald-j.-trump{ref}
which renders as:
Trump said this and that.[ref][ref] Then he said that and this.[ref][ref]
If given and true, forces a the link to be an external link.
Otherwise, the external is automatically guessed based on the address given as explained at Section 4.2.1.3.3. "External link".
Common use cases for the external argument is to link to non OurBigBook content in the curent domain, e.g.:
The \a external argument can be used to refer to the root of the domain. E.g. suppose that we have a subdirectory deployment under https://mydomain.com/subdir/. Then:
  • \a[/somepath] refers to the directory /subdir/somepath
  • \a[/somepath]{external} refers t othe directory /somepath
TODO test if it works. But we want it to be possible to deploy OurBigBook CLI static websites on subdirectories, e.g.:
https://mydomain.com/subdir/
https://mydomain.com/subdir/mathematics
If it doesn't work, it should be easy to make it work, as we use relative links almost everywhere already. Likely there would only be some minor fixes to the --template arguments.
An external link is a link that points to a resource that is not present in the curent OurBigBook project sources.
By default, most links are internal links, e.g. it is often the case in computer programming tutorials that we want to refer to source files in the current directory. So from our README.bigb, we could want to write something like:
Have a look at this amazing source file: \a[index.js].
which renders as:
Have a look at this amazing source file: index.js.
and here \a[ourbigbook] is a internal link.
A typicial external link is something like:
This is great website: https://cirosantilli.com
which renders as:
This is great website: cirosantilli.com
which points to an absolute URL.
OurBigBook considers a link relative by default if:
Therefore, the following links are external by default:
  • http://cirosantilli.com
  • https://cirosantilli.com
  • file:///etc/fstab
  • ftp://cirosantilli.com
and the following are internal by default:
  • index.js
  • ../index.js
  • path/to/index.js
  • /path/to/index.js. Note that paths starting with / refer to the root of the OurBigBook CLI deployment, not the root of the domain, see: link to the domain root path.
  • //example.com/path/to/index.js
A link being internal has the following effects
  • the correct relative path to the file is used when using nested scopes with -S, --split-headers. For example, if we have:
    = h1
    
    == h2
    {scope}
    
    === h3
    
    \a[index.js]
    then in split header mode, h3 will be rendered to h2/h3.html.
    Therefore, if we didn't do anything about it, the link to index.js would render as href="index.js" and thus point to h2/index.js instead of the correct index.js.
    Instead, OurBigBook automatically converts it to the correct href="../index.js"
  • the _raw directory prefix is added to the link
  • existence of the file is checked on compilation. If it does not exist, an error is given.
Implemented at: github.com/ourbigbook/ourbigbook/issues/87 as relative, and subsequently modified to the more accurate/useful external.
The _dir directory tree contains file listings of files in the _raw directory.
We originally wanted to place these listings under _raw itself, but this leads to unsolvable conflicts when there are files called index.html present vs the index.
OurBigBook Project places output files that are not the output of .bigb to .html conversion (i.e. .html output files) under the _raw/ prefix of the output.
Internal links then automatically add the _raw/ prefix to every link.
For example, consider an input directory that contains:
notindex.bigb
= Hello

Check out \a[myfile.c].

The source code for this file is at: \a[notindex.bigb].

\Image[myimg.png]
myfile.c
int i = 1;
myimg.png
Binary!
After conversion with:
ourbigbook .
the following files would exist in the output directory:
  • notindex.html: converted output of notindex.bigb
  • _raw/notindex.bigb: a copy of the input source code notindex.bigb
  • _raw/myfile.c: a copy of the input file myfile.c
  • _raw/myimg.png: a copy of the input file myimg.c
and all links/image references would work and automtically point to the correct locations under _raw.
Some live examples:
  • link to a file:
    The file \a[index.js] is cool.
    which renders as:
    The file index.js is cool.
  • link to a directory:
    The directory \a[file_demo] is cooler.
    which renders as:
    The directory file_demo is cooler.
The reason why a _raw prefix is needed it to avoid naming conflicts with OurBigBook outputs, e.g. suppose we had the files:
  • configure
  • configure.bigb
Then, in a server that omits the .html extension, if we didn't have _raw/ both configure.html and configure would be present under /configure. With _raw we instead get:
  • _raw/configure: the input /configure file
  • configure: the HTML
A URL with protocol is a URL that matches the regular expression ^[a-zA-Z]+://. The following are examples of URLs with protocol:
  • http://cirosantilli.com
  • https://cirosantilli.com
  • file:///etc/fstab
  • ftp://cirosantilli.com
The following aren't:
  • index.js
  • ../index.js
  • path/to/index.js
  • /path/to/index.js
  • //example.com/path/to/index.js. This one is a bit tricky. Web browsers would consider this as a protocol-relative URL, which technically implies a protocol, although that protocol would be different depending how you are viewing the file, e.g. locally through file:// vs on a with website https://.
    For simplicity's sake, we just consider it as a URL without protocol.
Insane start at any of the recognized protocols are the ones shown at: Section 4.4.3. "Known URL protocols".
  • http://
  • https://
absolutely anywhere if not escaped, e.g.:
ahttp://example.com
renders something like:
a <a href="http://example.com">
To prevent expansion, you have to escape the protocol with a backslash \\, e.g.:
\http://example.com
Empty domains like:
http://
don't becomes links however. But this one does:
http://a
Insane links end when either the end of the document or one of the following characters is found:
  • space
  • newline \n
  • open or close square bracket [ or ]
  • open or close curly braces { or }
As a consequence, to have an insane link followed immediately by a punctuation like a period you should use an empty argument as in:
Check out this website: http://example.com[].
which renders as:
Check out this website: example.com.
otherwise the punctuation will go in it. Another common use case is:
As mentioned on the tutorial (http://example.com[see this link]).
which renders as:
As mentioned on the tutorial (see this link).
If you want your link to include one of the terminating characters, e.g. ], all characters can be escaped with a backslash, e.g.:
Hello http://example.com/\]a\}b\\c\ d world.
which renders as:
Note that the http://example.com inside \a[http://example.com] only works because we do some post-processing magic that prevents its expansion, otherwise the link would expand twice:
\P[http://example.com]

\a[http://example.com]
which renders as:
This magic can be observed with --help-macros by seeing that the href argument of the a macro has the property:
"elide_link_only": true,
Some \b[bold] text.
which renders as:
Some bold text.
There is basically one application for this: poetry, which would be too ugly with code block due to fixed width font:
Paragraph 1 Line 1\br
Paragraph 1 Line 2\br

Paragraph 2 Line 1\br
Paragraph 2 Line 2\br
which renders as:
Paragraph 1 Line 1
Paragraph 1 Line 2
Paragraph 2 Line 1
Paragraph 2 Line 2
Inline code (code that should appear in the middle of a paragraph rather than on its own line) is done with a single backtick (`) insane macro shortcut:
My inline `x = 'hello\n'` is awesome.
which renders as:
My inline x = 'hello\n' is awesome.
and block code (code that should appear on their own line) is done with two or more backticks (``):
``
f() {
  return 'hello\n';
}
``
which renders as:
f() {
  return 'hello\n';
}
The sane version of inline code is a lower case c:
My inline \c[[x = 'hello\n']] is awesome.
which renders as:
My inline x = 'hello\n' is awesome.
and the sane version of block math is with an upper case C:
\C[[
f() {
  return 'hello\n';
}
]]
which renders as:
f() {
  return 'hello\n';
}
The capital vs lower case theme is also used in other elements, see: block vs inline macros.
If the content of the sane code block has many characters that you would need to escape, you will often want to use literal arguments, which work just like the do for any other argument. For example:
\C[[[
A paragraph.

\C[[
And now, some long, long code, with lots
of chars that you would need to escape:
\ [  ] {  }
]]

A paragraph.
]]]
which renders as:
A paragraph.

\C[[
And now, some long, long code, with lots
of chars that you would need to escape:
\ [  ] {  }
]]

A paragraph.
Note that the initial newline is skipped automatically in code blocks, just as for any other element, due to: argument leading newline removal, so you don't have to worry about it.
The distinction between inline \c and block \C code blocks is needed because in HTML, pre cannot go inside P.
We could have chosen to do some magic to differentiate between them, e.g. checking if the block is the only element in a paragraph, but we decided not to do that to keep the language saner.
And now a code block outside of \OurBigBookExample to test how it looks directly under the \Toplevel implicit macro:
Hello

Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
    HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello
Hello
And nos a very long inline code: Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
Block code can have a title, e.g. see this one: Code 1. "My nice code block":
``
ab
cd
``
{id=code-my-nice-code}
{title=My nice code block}
which renders as:
Code 1. My nice code block.
ab
cd
The Comment and comment macros are regular macros that does not produce any output. Capitalization is explained at: Section 4.4.2. "Block vs inline macros".
You will therefore mostly want to use it with a literal argument, which will, as for any other macro, ignore any macros inside of it.
Before comment.

\Comment[[
Inside comment.
]]

After comment.
which renders as:
Before comment.
After comment.
And an inline one:
My inline \comment[[inside comment]] is awesome.

\comment[[inside comment]] inline at the start.
which renders as:
My inline is awesome.
inline at the start.
Insane with = (equal sign space):
= My h1

== My h2

=== My h3
Insane headers end at the first newline found. They cannot therefore contain raw newline tokens.
Equivalent sane:
\H[1][My h1]

\H[2][My h2]

\H[3][My h3]
Custom ID for cross references on insane headers:
= My h1
{id=h1}

== My h2
{id=h2}

=== My h3
{id=h3}
Sane equivalent:
\H[1][My h1]{id=h1}

\H[2][My h2]{id=h2}

\H[3][My h3]{id=h3}
There is no limit to how many levels we can have, for either sane or insane headers!
HTML is randomly limited to h6, so OurBigBook just renders higher levels as an h6 with a data-level attribute to indicate the actual level for possible CSS styling:
<h6 data-level="7">My title</h6>
The recommended style is to use insane headers up to h6, and then move to sane one for higher levels though, otherwise it becomes very hard to count the = signs.
To avoid this, we considered making the insane syntax be instead:
= 1 My h1
= 2 My h2
= 3 My h3
but it just didn't feel as good, and is a bit harder to type than just smashing = n times for lower levels, which is the most common use case. So we just copied markdown.
The very first header of a document can be of any level, although we highly recommend your document to start with a \H[1], and to contain exactly just one \H[1], as this has implications such as:
After the initial header however, you must not skip a header level, e.g. the following would give an error because it skips level 3:
= my 1

== my 1

==== my 4
If the document has only a single header of the highest level, e.g. like the following has only a single h2:
== My 2

=== My 3 1

=== My 3 2
then this has some magical effects.
Header IDs won't show for the toplevel level. For example, the headers would render like:
My 2

1. My 3 1

2. My 3 2
rather than:
1. My 2

1.2. My 3 1

1.2. My 3 2
This is because in this case, we guess that the h2 is the toplevel.
TODO: we kind of wanted this to be the ID of the toplevel header instead of the first header, but this would require an extra postprocessing pass (to determine if the first header is toplevel or not), which might affect performance, so we are not doing it right now.
When the OurBigBook input comes from a file (and not e.g. stdin), the default ID of the first header in the document is derived from the basename of the OurBigBook input source file rather than from its title.
This is specially relevant when including other files.
For example, in file named my-file.bigb which contains:
= Awesome ourbigbook file
]]
the ID of the header is my-file rather than awesome-ourbigbook-file. See also: automatic ID from title.
If the file is an index file other than the toplevel index file, then the basename of the parent directory is used instead, e.g. the toplevel ID of a file:
my-subdir/README.bigb
would be:
#my-subdir
rather than:
#README.bigb
For the toplevel index file however, the ID is just taken from the header itself as usual. This is done because you often can't general control the directory name of a project.
For example, a GitHub pages root directory must be named as <username>.github.io. And users may need to rename directories to avoid naming conflicts.
As a consequence of this, the toplevel index file cannot be included in other files.
If given, makes the header capitalized by default on cross file references.
This multiple argument marks given IDs as being children of the current page.
The effect is the same as adding the \x child argument argument to an under the header. Notably, such marked target IDs will show up on the tagged autogenerated header metadata section.
Example:
= Animal

== Mammal

=== Bat

=== Cat

== Wasp

== Flying animal
{child=bat}
{child=wasp}

\x[bat]

\x[wasp]
renders exactly as:
= Animal

== Mammal

=== Bat

=== Cat

== Wasp

== Flying animal

\x[bat]{child}

\x[wasp]{child}
The header child syntax is generally preferred because at some point while editing the content of the header, you might accidentally remove mentions to e.g. \x[bat]{child}, and then the relationship would be lost.
The \H tag argument does the same as the \x child argument but in the opposite direction.
If given, the current section contains metadata about file or other resource with the given URL.
If empty, the URL of the file is extracted directly from the header. Otherwise, the given URL is used.
for example:
The file \x[file/path/to/myfile.c] is very useful.

= path/to/myfile.c
{file}

An explanation of what this file is about.
renders the same as:
The file \x[file/path/to/myfile.c] is very useful.

= path/to/myfile.c
{file}
{id=file/path/to/myfile.c}

An explanation of what this file is about.

\a[path/to/myfile.c][View file]
so note how:
  • automatic ID from title does not normalize the path, e.g. it does not convert / to -.
    Also, a _file/ prefix is automatically added to the ID. This is needed with -S, --split-headers to avoid a collision between:
    • path/to/myfile.c: the actual file
    • _file/path/to/myfile.c: the metadata about that file. Note that locally the .html extension is added as in file/path/to/myfile.c.html which avoids the collision. But on a server deployment, the .html is not present, and there would be a conflict if we didn't add that file/ prefix.
  • a link to the is added automatically, since users won't be able to click it from the header, as clicking on the header will just link to the header itself
  • a preview is added. The type of preview is chosen as follows:
    • if the URL has an image extension, do an image preview
    • otherwise if the URL has a video extension, or is a YouTube URL, do a video preview
    • otherwise, don't show a preview, as we don't know anything sensible to show
In some cases however, especially when dealing with external URLs, we might want to have a more human readable title with a file specified as in:
The video \x[tank-man-by-cnn-1989] is very useful.

To make <internal cross references> to `{file}` headers, use the <`\x` `file` argument>.

= Tank Man by CNN (1989)
{file=https://www.youtube.com/watch?v=YeFzeNAHEhU}

An explanation of what this video is about.
which renders something like:
The video \x[tank-man-by-cnn-1989] is very useful.

= Tank Man by CNN (1989)

\a[https://www.youtube.com/watch?v=YeFzeNAHEhU][View file]

An explanation of what this video is about.

\Video[https://www.youtube.com/watch?v=YeFzeNAHEhU]
This section is about the directory: file_demo
An explanation of what this directory is about.
This section is about the directory: file_demo/file_demo_subdir
Going deeper.
This section is about the file: file_demo/hello_world.js
An explanation of what this text file is about.
Another line.
file_demo/hello_world.js
#!/usr/bin/env node
console.log('hello world')
This section is about the file: file_demo/file_demo_subdir/hello_world.js
Going deeper.
file_demo/file_demo_subdir/hello_world.js
#!/usr/bin/env node
console.log('hello world subdir')
This section is about the file: index.js
Large text files are not previewed, as they would take up too much useless vertical space and disk memory/bandwidth.
index.js was not rendered because it is too large (> 2000 bytes)
This section is about the file: file_demo/my.bin
Binary files are not rendered.
file_demo/my.bin was not rendered because it is a binary file (contains \x00) of unsupported type (e.g. not an image).
This section is about the file: Tank_man_standing_in_front_of_some_tanks.jpg
Tank_man_standing_in_front_of_some_tanks.jpg
An explanation of what this image is about.
Another line.
This section is about the video: www.youtube.com/watch?v=YeFzeNAHEhU
Video 2. Source.
An explanation of what this video is about.
This boolean argument determines whether renderings of a header will have section numbers or not. This affects all of:
This option can be set by default for all files with:
By default, headers are numbered as in a book, e.g.:
= h1

== h2

=== h3

==== h4
renders something like:
= h1

Table of contents
* 1. h2
  * 1.1. h3
    * 1.1.1. h4

== 1. h2

=== 1.1. h3

==== 1.1.1. h4
However, for documents with a very large number of sections, or deeply nested headers those numbers start to be more noise than anything else, especially in the table of contents and you are better off just referring to IDs. E.g. imagine:
1.3.1.4.5.1345.3.2.1. Some deep level
When documents reach this type of scope, you can disable numbering with the numbered option.
This option can be set on any header, and it is inherited by all descendants.
The option only affects descendants.
E.g., if in the above example turn numbering off at h2:
= h1

== h2
{numbered=0}

=== h3

==== h4
then it renders something like:
= h1

Table of contents
* 1. h2
  * h3
    * h4

== 1. h2

=== h3

==== h4
The more common usage pattern to disable it on toplevel and enable it only for specific "tutorial-like sections". An example can be seen at:
which is something like:
= Huge toplevel wiki
{numbered=0}

== h2

=== A specific tutorial
{numbered}
{scope}

==== h4

===== h5
then it renders something like:
= Huge toplevel wiki

Table of contents
* h2
  * A specific tutorial
    * 1. h4
      * 1.1.  h5

== h2

=== A specific tutorial

==== 1. h4

===== 1.1. h5
Note how in this case the number for h4 is just 1. rather than 1.1.1.. We only show numberings relative to the first non-numbered header, because the 1.1. wouldn't be very meaningful otherwise.
In addition to the basic way of specifying header levels with an explicit level number as mentioned at Section 4.2.6. "Header (\H)", OurBigBook also supports a more indirect ID-based mechanism with the parent argument of the \H element.
We hightly recommend using parent for all but the most trivial documents.
For example, the following fixed level syntax:
= My h1

== My h2 1

== My h2 2

=== My h3 2 1
is equivalent to the following ID-based version:
= My h1

= My h2 1
{parent=my-h1}

= My h2 2
{parent=my-h1}

= My h3 2 1
{parent=my-h2-h}
The main advantages of this syntax are felt when you have a huge document with very large header depths. In that case:
  • it becomes easy to get levels wrong with so many large level numbers to deal with. It is much harder to get an ID wrong.
  • when you want to move headers around to improve organization, things are quite painful without a refactoring tool (which we intend to provide in the browser editor with preview), as you need to fix up the levels of every single header.
    If you are using the ID-based syntax however, you only have to move the chunk of headers, and change the parent argument of a single top-level header being moved.
Note that when the parent= argument is given, the header level must be 1, otherwise OurBigBook assumes that something is weird and gives an error. E.g. the following gives an error:
= My h1

== My h2
{parent=my-h1}
because the second header has level 2 instead of the required = My h2.
When scopes are involved, the rules are the same as those of internal reference resolution, including the leading / to break out of the scope in case of conflicts.
Like the \H child argument, parent also performs ID target from title on the argument, allowing you to use the original spaces and capitalization in the target as in:
= Flying animal

= Bat
{parent=Flying animal}
which is equivalent to:
= Flying animal

= Bat
{parent=flying-animal}
When mixing both \H parent argument and scopes, things get a bit complicated, because when writing or parsing, we have to first determine the parent header before resolving scopes.
As a result, the follow simple rules are used:
  • start from the last header of the highest level
  • check if the {parent=XXX} is a suffix of its ID
  • if not, proceed to the next smaller level, and so on, until a suffix is found
Following those rules for example, a file tmp.bigb:
= h1
{scope}

= h1 1
{parent=h1}
{scope}

= h1 1 1
{parent=h1-1}

= h1 1 2
{parent=h1-1}

= h1 1 3
{parent=h1/h1-1}

= h1 2
{parent=h1}
{scope}

= h1 2 1
{parent=h1-2}
{scope}

= h1 2 1 1
{parent=h1-2/h1-2-1}
will lead to the following header tree with --log headers:
= h1  tmp
== h2 1 tmp/h1-1
=== h3 1.1 tmp/h1-1/h1-1-1
=== h3 1.2 tmp/h1-1/h1-1-2
=== h3 1.3 tmp/h1-1/h1-1-3
== h2 2 tmp/h1-2
=== h3 2.1 tmp/h1-2/h1-2-1
==== h4 2.1.1 tmp/h1-2/h1-2-1/h1-2-1-1
Arguably, the language would be even saner if we did:
\H[My h1][

Paragraph.

\H[My h2][]
]
rather than having explicit levels as in \H[1][My h1] and so on.
But we chose not to do it like most markups available because it leads to too many nesting levels, and hard to determine where you are without tooling.
Ciro later "invented" (?) \H parent argument, which he feels reaches the perfect balance between the advantages of those two options.
In some use cases, the sections under a section describe inseparable parts of something.
For example, when documenting an experiment you executed, you will generally want an "Introduction", then a "Materials" section, and then a "Results" section for every experiment.
On their own, those sections don't make much sense: they are always referred to in the context of the given experiment.
The problem is then how to get unique IDs for those sections.
One solution, would be to manually add the experiment ID as prefix to every subsection, as in:
= Experiments

See: \x[full-and-unique-experiment-name/materials]

== Introduction

== Full and unique experiment name

=== Introduction
{id=full-and-unique-experiment-name/introduction}

See our awesome results: \x[full-and-unique-experiment-name/results]

For a more general introduction to all experiments, see: \x[introduction].

=== Materials
{id=full-and-unique-experiment-name/materials}

=== Results
{id=full-and-unique-experiment-name/results}
but this would be very tedious.
To keep those IDs shorter, OurBigBook provides the scope boolean argument property of headers, which works analogously to C++ namespaces with the header IDs.
Using scope, the previous example could be written more succinctly as:
= Experiments

See: \x[full-and-unique-experiment-name/materials]

== Introduction

== Full and unique experiment name
{scope}

=== Introduction

See our awesome results: \x[results]

For a more general introduction to all experiments, see: \x[/introduction].

=== Materials

=== Results
Note how:
  • full IDs are automatically prefixed by the parent scopes prefixed and joined with a slash /
  • we can refer to other IDs withing the current scope without duplicating the scope. E.g. \x[results] in the example already refers to the ID full-and-unique-experiment-name/materials
  • to refer to an ID outside of the scope and avoid name conflicts with IDs inside of the current scope, we start a reference with a slash /
    So in the example above, \x[/introduction] refers to the ID introduction, and not full-and-unique-experiment-name/introduction.
When nested scopes are involved, cross references resolution peels off the scopes one by one trying to find the closes match, e.g. the following works as expected:
= h1
{scope}

== h2
{scope}

=== h3
{scope}

\x[h2]
Here OurBigBook:
  • first tries to loop for an h1/h2/h3/h2, since h1/h2/h3 is the current scope, but that ID does not exist
  • so it removes the h3 from the current scope, and looks for h1/h2/h2, which is still not found
  • then it removes the h2, leading to h1/h2, and that one is found, and therefore is taken
Putting files in subdirectories of the build has the same effect as adding a scope to their top level header.
Notably, all headers inside that directory get the directory prepended to their IDs.
The toplevel directory is determined as described at: the toplevel index file.
For fun and profit.
Let's break this local link: ourbigbook.
When the toplevel header is given the scope property OurBigBook automatically uses the file path for the scope and heaves fragments untouched.
For example, suppose that file full-and-unique-experiment-name contains:
= Full and unique experiment name
{scope}

== Introduction

== Materials
In this case, multi-file output will generate a file called full-and-unique-experiment-name.html, and the URL of the subsections will be just:
  • full-and-unique-experiment-name.html#introduction
  • full-and-unique-experiment-name.html#materials
instead of
  • full-and-unique-experiment-name.html#full-and-unique-experiment-name/introduction
  • full-and-unique-experiment-name.html#full-and-unique-experiment-name/materials
Some quick interactive cross file link tests:
When using -S, --split-headers, cross references always point to non-split pages as mentioned at cross reference targets in split headers.
If the splitDefault boolean argument is given however:
  • the split header becomes the default, e.g. index.html is now the split one, and nosplit.html is the non-split one
  • the header it is given for, and all of its descendant headers will use the split header as the default internal cross target, unless the header is already rendered in the current page. This does not propagate across includes however.
For example, consider README.bigb:
= Toplevel
{splitDefault}

\x[h2][toplevel to h2]

\x[notreadme][toplevel to notreadme]

\Include[notreadme]

== h2
and notreadme.bigb:
= Notreadme

\x[h2][notreadme to h2]

\x[notreadme][notreadme to notreadme h2]

== Notreadme h2
Then the following links would be generated:
  • index.html: split version of README.bigb, i.e. does not contain h2
    • toplevel to h2: h2.html. Links to the split version of h2, since h2 is also affected by the splitDefault of its parent, and therefore links to it use the split version by default
    • toplevel to notreadme: notreadme.html. Links to non-split version of notreadme.html since that header is not splitDefault, because splitDefault does not propagate across includes
  • nosplit.html non-split version of README.bigb, i.e. contains h2
    • toplevel to h2: #h2, because even though h2 is splitDefault, that header is already present in the current page, so it would be pointless to reload the split one
    • toplevel to notreadme: notreadme.html
  • h2.html split version of h2 from README.bigb
  • notreadme.html: non-split version of notreadme.bigb
    • notreadme to h2: h2.html, because h2 is splitDefault
    • notreadme to notreadme h2: #notreadme-h2
  • notreadme-split.html: split version of notreadme.bigb
    • notreadme to h2: h2.html, because h2 is splitDefault
    • notreadme to notreadme h2: notreadme.html#notreadme-h2, because notreadme-h2 is not splitDefault
The major application of this if you like work with a huge README.bigb containing thousands of random small topics.
Splitting those into separate source files would be quite laborious, as it would require duplicating IDs on the filename, and setting up includes.
However, after this README reaches a certain size, page loads start becoming annoyingly slow, even despite already loading large assets like images video videos only on hover or click: the annoying slowness comes from the loading of the HTML itself before the browser can jump to the ID.
And even worse: this README corresponds to the main index page of the website, which will make what a large number of users will see be that slowness.
Therefore, once this README reaches a certain size, you can add the splitDefault attribute to it, to make things smoother for readers.
And if you have a smaller, more self-contained, and highly valuable tutorial such as cirosantilli.com/x86-paging, you can just split that into a separate .bigb source file.
This way, any links into the smaller tutorial will show the entire page as generally desired.
And any links from the tutorial, back to the main massive README will link back to split versions, leading to fast loads.
This feature was implemented at: github.com/ourbigbook/ourbigbook/issues/131
Note that this huge README style is not recommended however. Ciro Santilli used to do it, but moved away from it. The currently recommended approach is to manually create not too large subtrees in each page. This way, readers can easily view several nearby sections without having to load a new page every time.
If given, add a custom suffix to the output filename of the header when using -S, --split-headers.
If the given suffix is empty, it defaults to -split.
For example, given:
= my h1

== my h2
a --split-headers conversion would normally place my h2 into a file called:
my-h2.html
However, if we instead wrote:
== my h2
{splitSuffix}
it would not be placed under:
my-h2-split.html
and if we set a custom one as:
== my h2
{splitSuffix=asdf}
it would go instead to:
my-h2-asdf.html
This option is useful if the root of your website is written in OurBigBook, and you want to both:
  • have a section that talks about some other project
  • host the documentation of that project inside the project source tree
For example, cirosantilli.com with source at github.com/cirosantilli/cirosantilli.github.io has a quick section about OurBigBook: cirosantilli.com#ourbigbook.
Therefore, without a custom suffix, the split header version of that header would go to docs.ourbigbook.com, which would collide with this documentation, that is present in a separate repository: github.com/ourbigbook/ourbigbook.
Therefore a splitSuffix property is used, making the split header version fall under /ourbigbook-split, and leaving the nicer /ourbigbook for the more important project toplevel.
If given on the the toplevel headers, which normally gets a suffix by default to differentiate from the non-split version, it replaces the default -split suffix with a custom one.
For example if you had notindex.bigb as:
= Not index
then it would render to:
notindex-split.bigb
but if you used instead:
= Not index
{splitSuffix=asdf}
then it would instead be:
notindex-asdf.bigb
This option is similar to \H title2 argument but it additionally:
  • creates a new ID that you can refer to, and renders it with the alternate chosen title
  • the rendered ID on cross references is the same as what it is a synonym for
  • the synonym header is not rendered at all, including in the table of contents
  • when using -S, --split-headers, a redirect output file is generated from the synonym to the main ID
Example:
= Parent

== GNU Debugger
{c}

= GDB
{c}
{synonym}

I like to say \x[gdb] because it is shorter than \x[gnu-debugger].
renders something like:
= GNU Debugger

I like to say \a[#gnu-debugger][GDB] because it is shorter than \x[#gnu-debugger][GNU Debugger].
Furthermore, if -S, --split-headers is used, another file is generated:
gdb.html
which contains a redirection from gdb.html to gnu-debugger.html.
Contains the main content of the header. The insane syntax:
= My title
is equivalent to the sane:
\H[1][My title]
and in both cases My title is the title argument.
The title argument is also notably used for automatic ID from title.
If a non-toplevel macro has the title argument is present but no explicit id argument is given, an Element ID is created automatically from the title, by applying the following transformations:
  • do a id output format conversion on the title to remove for example any HTML tags that would be present in the conversion output
  • convert all characters to lowercase. This uses JavaScript case conversion. Note that this does convert non-ASCII characters to lowercase, e.g. É to é.
  • if id normalize latin is true (the default) do Latin normalization. This converts e.g. é to e.
  • if id normalize punctuation is true (the default) do Punctuation normalization. This converts e.g. + to plus.
  • convert consecutive sequences of all non a-z0-9 ASCII characters to a single hyphen -. Note that this leaves non-ASCII characters untouched.
  • strip leading or trailing hyphens
Note how those rules leave non-ASCII Unicode characters untouched, except for:
  • capitalization changes wher applicable, e.g. É to é
as capitalization and determining if something "is a letter or not" in those cases can be tricky.
So for example, the following automatic IDs would be generated: Table 2. "Examples of automatically generated IDs".
Table 2. Examples of automatically generated IDs.
title id latin normalization punctuation normalization comments
My favorite title my-favorite-title
Ciro's markdown is awesome ciro-s-markdown-is-awesome ' is an ASCII character, but it is not in a-z0-9, therefore it gets converted to a hyphen -
É你 e你 true
The Latin acute accented e, É, is converted to its lower case form é as per the JavaScript case conversion.
Then, due to Latin normalization, é is converted to e.
The Chinese character is left untouched as Chinese characters have no case, and no ASCII analogue.
É你 é你 false Same as the previous, but é is not converted to e since Latin normalization is turned off.
C++ is great c-plus-plus-is-great true This is the effect of Punctuation normalization.
I love dogs. i-love-dogs love is extracted from the italic tags <i>love</i> with id output format conversion.
For the toplevel header, its ID is derived from the basename of the OurBigBook file without extension instead of from the title argument.
This conversion type is similar to Automatic ID from title, but it is used in certain cases where we are targeting IDs rather than setting them, notably:
Unlike \H title2 argument, the synonym does not show up by default next to the title. This is because we sometimes want that, and sometimes not. To make the title appear, you can simply add an empty title2 argument to the synonym header as in:
= GNU Debugger
{c}

= GDB
{c}
{synonym}
{title2}

= Quantum computing

= Quantum computer
{synonym}
which renders something like:
= GNU Debugger (GDB)

= Quantum computing
Note how we added the synonym to the title only when it is not just a simple flexion variant, since Quantum computing (Quantum computer) would be kind of useless would be kind of useless.
Same as \x child argument but in the opposite direction, e.g.:
== Mammal

=== Bat
{tag=flying-animal}

=== Cat

== Flying animal
is equivalent in every way to:
== Mammal

=== Bat

=== Cat

== Flying animal
{child=bat}
Naming rationale:
  • parent as the opposite of child is already taken to be then "main parent" via the "\H parent argument"
  • we could have renamed the \H child argument to tags as in "this header tags that one", but it would be a bit confusing tags vs tag
So child vs tag it is for now.
You generally want to use tag instead of the \H child argument because otherwise some very large header categories are going to contain Huge lists of children, which is not very nice when editing.
It is possible to enforce the \H child argument or the \H tag argument in a given project with the lint h-tag option.
The title2 argument can be given to any element that has the title argument.
Its usage is a bit like the description= argument of images, allowing you to add some extra content to the header without affecting its ID.
Unlike description= however, title2 shows up on all full references, including appearances in the table of contents, which make it more searchable.
Its primary use cases are:
  • give acronyms, or other short names names of fuller titles such as mathematical/programming notation
    One primary reason to not use the acronyms as the main section name is to avoid possible ID ambiguities with other acronyms.
  • give the header in different languages
For example, given the OurBigBook input:
= Toplevel

The Toc follows:

== North Atlantic Treaty Organization
{c}
{title2=NATO}

\x[north-atlantic-treaty-organization]

\x[north-atlantic-treaty-organization]{full}
the rendered output looks like:
= Toplevel

The ToC follows:

* North Atlantic Treaty Organization (NATO)

== North Atlantic Treaty Organization (NATO)

North Atlantic Treaty Organization

Section 1. "North Atlantic Treaty Organization (NATO)"
Related alternatives to title2 include:
Parenthesis are added automatically around all rendered title2.
The title2 argument has a special meaning when applied to a header with the \H synonym argument, see \H title2 argument of a synonym header.
When the \H toplevel argument is set, the header and its descendants will be automatically output to a separate file, even without -S, --split-headers.
For example given:
animal.bigb
= Animal

== Vertebrate

=== Dog
{toplevel}

==== Bulldog

== Invertebrate
and if you convert as:
ourbigbook animal.bigb
we get the following output files:
  • animal.html: contains the headers: "Animal", "Vertebrate" and "Invertebrate", but not "Dog" and "Bulldog"
  • dog.html: contains only the headers: "Dog" and "Bulldog"
This option is intended to produce output identical to using includes and separate files, i.e. the above is equivalent to:
animal.bigb
= Animal

== Vertebrate

\Include[dog]

== Invertebrate
dog.bigb
= Dog
{toplevel}

== Bulldog
Or in other words: the toplevel header of each source file gets {toplevel} set implicitly for it by default.
This design choice might change some day. Arguably, the most awesome setup is on in which source files and outputs are completely decoupled. OurBigBook Web also essentially wants this, as ideally we want to store one source per header there in each DB entry. We shall see.
If given, show a link to the Wikipedia article that corresponds to the header.
If a value is not given, automatically link to the Wiki page that matches the header exactly with spaces converted to underscores.
Here is an example with an explicit wiki argument:
==== Tiananmen Square
{wiki=Tiananmen_Square}
which looks like:
or equivalently with the value deduced from the title:
= Tiananmen Square
{wiki}
which looks like:
You can only link to subsections of wiki pages with explicit links as in:
= History of Tiananmen Square
{wiki=Tiananmen_Square#History}
which looks like:
OurBigBook adds some header metadata to the toplevel header at the bottom of each page. this section describes this metadata.
Although the table of contents has a macro to specify its placement, it is also automatically placed at the bottom of the page, and could be considered a header metadata section.
Lists other sections that link to the current section.
E.g. in:
= tmp

== tmp 1

=== tmp 1 1

=== tmp 1 2

\x[tmp-1]

== tmp 2

\x[tmp-1]
the page tmp-1.html would contain a list of incoming links as:
  • tmp-1-2
  • tmp-2
since those pages link to the tmp-1 ID.
Lists sections that are secondary children of the current section, i.e. tagged under the current section.
The main header tree hierarchy descendants already show under the table of contents instead.
E.g. in:
= tmp

== Mammal

== Flying

== Animal

=== Bat
{tag=mammal}
{tag=flying}

=== Bee
{tag=flying}

=== Dog
{tag=mammal}
the tagged sections for:
  • Mammal will contain Bat and Dog
  • Flying will contain Bat and Bee
Shows a list of ancestors of the page. E.g. in:
= Asia

== China

=== Beijing

==== Tiananmen Square

=== Hong Kong
the ancestor lists would be for:
  • Hong Kong: China, Asia
  • Tiananmen Square: Beijing, China, Asia
  • Beijing: China, Asia
  • China: Asia
so we see that this basically provides a type of breadcrumb navigation.
A block image with capital 'i' Image showcasing most of the image properties Figure 4. "The title of my image".
Have a look at this amazing image: \x[image-my-test-image].

\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
{title=The title of my image}
{id=image-my-test-image}
{width=600}
{height=200}
{source=https://en.wikipedia.org/wiki/File:Tianasquare.jpg}
{description=The description of my image.}
which renders as:
Have a look at this amazing image: Figure 4. "The title of my image".
Figure 4. The title of my image. Source. The description of my image.
This exemplifies the following parameters:
  • title: analogous to the \H title argument. Shows up preeminently, and sets a default ID if one is not given. It is recommended that you don't add a period . to it, as that would show in cross references
  • image description argument
  • source: a standardized way to credit an image by linking to a URL that contains further image metadata
For further discussion on the effects of ID see: Section 4.2.7.2. "Image ID".
And this is how you make an inline image inline one with lower case i:
My inline \image[Tank_man_standing_in_front_of_some_tanks.jpg][test image] is awesome.
which renders as:
My inline test image is awesome.
Inline images can't have captions.
And now for an image outside of \OurBigBookExample to test how it looks directly under the \Toplevel implicit macro: Figure 5.
Figure 5
By default, we fix image heights to height=315, and let the width be calculated proportionally once the image loads. We therefore ignore the actual image size. This is done to:
  • prevent reflows as the page loads images and can determine their actual sizes, especially is the user opens the page at a given ID in the middle of the page
  • create a more uniform media experience by default, unless a custom image size is actually needed e.g. if the image needs to be larger
Here is an image without a description but with an ID so we can link to it: Figure 6.
Have a look at this amazing image: \x[image-my-test-image-2].

\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
{id=image-my-test-image-2}
which renders as:
Have a look at this amazing image: Figure 6.
Figure 6
This works because full is the default cross reference style for Image, otherwise the link text would be empty since there is no title, and OurBigBook would raise an error.
OurBigBook can optionally deduce the title from the basename of the src argument if the titleFromSrc boolean argument is given, or if title-from-src is set as the default media provider for the media type:
Have a look at this amazing image: \x[image-tank-man-standing-in-front-of-some-tanks].

\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
{titleFromSrc}
which renders as:
Have a look at this amazing image: Figure 7. "Tank man standing in front of some tanks.".
Figure 7. Tank man standing in front of some tanks.
If the image has neither ID nor title nor description nor source, then it does not get a caption at all:
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
which renders as:
Tank_man_standing_in_front_of_some_tanks.jpg
If the image does not have an ID nor title, then it gets an automatically generated ID, just like every other OurBigBook output HTML element, and it is possible for readers to link to that ID on the rendered version, e.g. as:
#_123
Note that the 123 is not linked to the Figure <number>., but just a sequential ID that runs over all elements.
This type of ID is of course not stable across document revisions however, since if an image is added before that one, the link will break. So give an ID or title for anything that you expect users to link to.
Also, it is not possible to link to such images with an cross reference, like any other OurBigBook element with autogenerated temporary IDs.
Another issue to consider is that in paged output formats like PDF, the image could float away from the text that refers to the image, so you basically always want to refer to image by ID, and not just by saying "the following image".
We can also see that such an image does not increment the Figure count:
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]{id=image-my-test-image-count-before}
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]{id=image-my-test-image-count-after}
which renders as:
If the image has any visible metadata such as source or description however, then the caption does show and the Figure count gets incremented:
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]{source=https://en.wikipedia.org/wiki/File:Tianasquare.jpg}
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]{description=This is the description of my image.}
which renders as:
Figure 10. Source.
Figure 11. This is the description of my image.
If you are making a limited repository that will not have a ton of images, then you can get away with simply git tracking your images in the main repository.
With this setup, no further action is needed. For example, with a file structure of:
./README.bigb
./Tank_man_standing_in_front_of_some_tanks.jpg
just use the image from README.bigb as:
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
which renders as:
Tank_man_standing_in_front_of_some_tanks.jpg
However, if you are making a huge tutorial, which can have a huge undefined number of images (i.e. any scientific book), then you likely don't want to git track your images in the git repository.
In this approach, you create a separate GitHub repository in addition to the main one containing the text to contain only media such as images.
This approach is more suitable than store images inside the repository itself if you are going to have a lot of images.
When using this approach, you could of course just point directly to the final image URL, e.g. as in:
\Image[https://raw.githubusercontent.com/ourbigbook/ourbigbook-media/master/Fundamental_theorem_of_calculus_topic_page_arrow_to_full_article.png]
which renders as:
https://raw.githubusercontent.com/ourbigbook/ourbigbook-media/master/Fundamental_theorem_of_calculus_topic_page_arrow_to_full_article.png
but OurBigBook allows you use configurations that allow you to enter just the image basename: Fundamental_theorem_of_calculus_topic_page_arrow_to_full_article.png which we will cover next.
In order to get this to work, the recommended repository setup is:
The directory and repository names are not mandatory, but if you place media in data/media and name its repository by adding the *-media suffix, then ourbigbook will handle everything for you without any further configuration in media-providers.
This particular documentation repository does have a different setup as can be seen from its ourbigbook.json. Then, when everything is setup correctly, we can refer to images simply as:
\Image[Fundamental_theorem_of_calculus_topic_page_arrow_to_full_article.png]{provider=github}
which renders as:
https://raw.githubusercontent.com/ourbigbook/ourbigbook-media/master/Fundamental_theorem_of_calculus_topic_page_arrow_to_full_article.png
In this example, we also needed to set {provider=github} explicitly since it was not set as the default image provider in our ourbigbook.json. In most projects however, all of your images will be in the default repository, so this won't be needed.
provider must not be given when a full URL is given because we automatically detect providers from URLs, e.g.:
\Image[https://raw.githubusercontent.com/ourbigbook/ourbigbook-media/master/Fundamental_theorem_of_calculus_topic_page.png]{provider=github}
is an error.
TODO implement: ourbigbook will even automatically add and push used images in the my-tutorial-media repository for you during publishing!
You should then use the following rules inside my-tutorial-media:
  • give every file a very descriptive and unique name as a full English sentence
  • never ever delete any files, nor change their content, unless it is an improvement in format that does change the information contained of the image TODO link to nice Wikimedia Commons guideline page
This way, even though the repositories are not fully in sync, anyone who clones the latest version of the *-media directory will be able to view any version of the main repository.
Then, if one day the media repository ever blows up GitHub's limit, you can just migrate the images to another image server that allows arbitrary basenames, e.g. AWS, and just configure your project to use that new media base URL with the media-providers option.
The reason why images should be kept in a separate repository is that images are hundreds or thousands of times larger than hand written text.
Therefore, images could easily fill up the maximum repository size you are allowed: webapps.stackexchange.com/questions/45254/file-size-and-storage-limits-on-github#84746 and then what will you do when GitHub comes asking you to reduce the repository size?
Git LFS is one approach to deal with this, but we feel that it adds too much development overhead.
This is likely the sanest approach possible, as it clearly specifies which media version matches which repository version through the submodule link.
Furthermore, it is possible to make the submodule clone completely optional by setting things up as follows. For your OurBigBook project yourname/myproject create a yourname/myproject-media with the media, and track it as a submodule under yourname/myproject/media.
Then, add to media-providers:
"media-providers": {
  "github": {
    "default-for": ["image", "video"],
    "path": "media",
    "remote": "yourname/myproject-media"
  }
}
Now, as mentioned at media-providers, everything will work beautifully:
  • ourbigbook . local conversion will use images from media/ if it exists, e.g.:
    \Image[myimage.jpg]
    will render media/myimage.jpg. So after cloning the submodule, you will be able to see the images on the rendered pages without an internet connection.
    But if the submodule is not cloned, not problem, renders will detect that and automatically use GitHub images.
    Then, when you do:
    ourbigbook --publish
    the following happen:
    • \Image[myimage.jpg] uses the GitHub URL
    • automatically push media/ to GitHub in case there were any updates
    • also, that directory is automatically gitignore, so it won't be pushed as part of the main render and thus duplicate things
Wikimedia Commons is another great possibility to upload your images to:
\Image[https://upload.wikimedia.org/wikipedia/commons/thumb/5/5b/Gel_electrophoresis_insert_comb.jpg/450px-Gel_electrophoresis_insert_comb.jpg]
{source=https://commons.wikimedia.org/wiki/File:Gel_electrophoresis_insert_comb.jpg}
which renders as:
Figure 12. Source.
OurBigBook likes Wikimedia Commons so much that we automatically parse the image URL and if it is from Wikimedia Commons, automatically deduce the source for you. So the above image renders the same without the source argument:
\Image[https://upload.wikimedia.org/wikipedia/commons/5/5b/Gel_electrophoresis_insert_comb.jpg]
which renders as:
Figure 13. Source.
And like for non-Wikimedia images, you can automatically generate a title from the src by setting the titleFromSrc boolean argument or if title-from-src is set as the default media provider for the media type:
\Image[https://upload.wikimedia.org/wikipedia/commons/5/5b/Gel_electrophoresis_insert_comb.jpg]
{titleFromSrc}
which renders as:
Figure 14. Gel electrophoresis insert comb. Source.
And a quick test for a more complex thumb resized URL:
\Image[https://upload.wikimedia.org/wikipedia/commons/thumb/5/5b/Gel_electrophoresis_insert_comb.jpg/450px-Gel_electrophoresis_insert_comb.jpg]
which renders as:
Figure 15. Source.
If you really absolutely want to turn off the source, you can explicitly set:
\Image[https://upload.wikimedia.org/wikipedia/commons/5/5b/Gel_electrophoresis_insert_comb.jpg]
{source=}
which renders as:
https://upload.wikimedia.org/wikipedia/commons/5/5b/Gel_electrophoresis_insert_comb.jpg
but you don't want to do that for the most commonly Wikimedia Commons used license of CC BY+, do you? :-)
Upsides of using Wikimedia Commons for your images:
  • makes it easier for other writers to find and reuse your images
  • automatically generates resized versions of the uploaded images into several common dimensions so you can pick the smallest one that fits your desired image height to reduce bandwidth usage
  • if you have so many images that they would blow even the size of a separate media repository, this will still work
Downsides:
  • forces you to use the Creative Commons license
  • requires the content to be educational in nature
  • uploading a bunch of images to Wikimedia Commons does feel a bit more laborious than it should because you have to write down so much repeated metadata for them
We do this by default because OurBigBook is meant to allow producing huge single page documents like Ciro likes it, and in this way:
  • images that the user is looking at will load first
  • we save a lot of bandwidth for the user who only wants to browse one section
TODO: maybe create a mechanism to disable this for the entire build with ourbigbook.json.
For the love of God, there is no standardized for SVG to set its background color without a rectangle? stackoverflow.com/questions/11293026/default-background-color-of-svg-root-element viewport-fill was just left in limbo?
And as a result, many many many SVG online images that you might want to reuse just rely on white pages and don't add that background rectangle.
Therefore for now we just force white background on our default CSS, which is what most SVGs will work with. Otherwise, you can lose the entire image to our default black background.
Then if someone ever has an SVG that needs another background color, we can add an image attribute to set that color as a local style.
TODO implement: mechanism where you enter a textual description of the image inside the code body, and it then converts to an image, adds to the -media repo and pushes all automatically. Start with dot.
Adds a border around the image. This can be useful to make it clearer where images start and end when the image background color is the same as the background color of the OurBigBook document.
\Image[logo.svg]
{border}
{height=150}
{title=Logo of the OurBigBook Project with a border around it.}
which renders as:
Figure 16. Logo of the OurBigBook Project with a border around it.
The description argument similar to the image title argument argument, but allows allowing longer explanations without them appearing in cross references to the image.
For example, consider:
See this image: \x[image-description-argument-test-1].

\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
{title=Tank man standing in front of some tanks}
{id=image-description-argument-test-1}
{description=Note how the tanks are green.}
{source=https://en.wikipedia.org/wiki/File:Tianasquare.jpg}
which renders as:
Figure 17. Tank man standing in front of some tanks. Source. Note how the tanks are green.
In this example, the reference \x[image-description-argument-test-1] expands just to
Tank man standing in front of some tanks
and does not include the description, which only shows on the image.
The description can be as large as you like. If it gets really large however, you might want to consider moving the image to its own header to keep things slightly saner. This will be especially true after we eventually do: github.com/ourbigbook/ourbigbook/issues/180.
If the description contains any element that would take its own separate line, like multiple paragraphs or a list, we automatically add a line grouping the description with the corresponding image to make that clearer, otherwise it can be hard to know which title corresponds to a far away image. Example with multiple paragraphs:
Stuff before the image.

\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
{title=Tank man standing in front of some tanks}
{id=image-description-argument-test-2}
{source=https://en.wikipedia.org/wiki/File:Tianasquare.jpg}
{description=Note how the tanks are green.

But the shirt is white.}

Stuff after the image description.
which renders as:
Stuff before the image.
Figure 18. Tank man standing in front of some tanks. Source.
Note how the tanks are green.
But the shirt is white.
Stuff after the image description.
We recommend adding a period or other punctuation to the end of every description.
Analogous to the \a external argument when checking if the image src argument exists or not.
If given, make clicking an image go to the specified URL rather than the image's URL as is the default.
By default, clicking on a rendered image links to the URL of the image itself. E.g. clicking:
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
which renders as:
Tank_man_standing_in_front_of_some_tanks.jpg
would open Tank_man_standing_in_front_of_some_tanks.jpg as produces img surrounded by something like a href="Tank_man_standing_in_front_of_some_tanks.jpg".
If insetad we want the image to point to a custom URL, e.g. ourbigbook.com we could instead write:
\Image[Tank_man_standing_in_front_of_some_tanks.jpg]{link=https://ourbigbook.com}
which renders as:
Tank_man_standing_in_front_of_some_tanks.jpg
and now clicking the image leads to ourbigbook.com instead.
Where the image was taken from, e.g.:
\Image[https://upload.wikimedia.org/wikipedia/commons/6/68/Akha_cropped_hires.JPG]
{title=A couple}
{source=https://en.wikipedia.org/wiki/Human}
which renders as:
Figure 19. A couple. Source.
The source is automatically inferred for certain known websites, e.g.:
The address of the image, e.g. in:
\Image[image.png]
the src is image.png.
Analogous to the \a href argument.
Analogous to the \H title argument.
The \Include macro allows including an external OurBigBook headers under the current header.
It exists to allow optional single page HTML output while still retaining the ability to:
  • split up large input files into multiple files to make renders faster during document development
  • suggest an optional custom output split with one HTML output per OurBigBook input, in order to avoid extremely large HTML pages which could be slow to load
\Include takes one mandatory argument: the ID of the section to be included, much like cross references.
There is however one restriction: only the toplevel headers can be pointed to. This restriction allows us to easily find the included file in the filesystem, and dispenses the need to do a first ./ourbigbook run to generate the ID database. This works because the ID of the first header is derived from the filename.
Headers of the included document are automatically shifted to match the level of the child of the level where they are being included.
If --embed-includes is given, the external document is rendered embedded into the current document directly, essentially as if the source had been copy pasted (except for small corrections such as the header offsets).
Otherwise, the following effects happen:
  • The headers of the included tree appear in the table of contents of the document as links to the corresponding external files.
    This is implemented simply by reading a previously generated database file much like cross file reference internals, which avoids the slowdown of parsing all included files every time.
    As a result, you have to do an initial parse of all files in the project to extract their headers however, just as you would need to do when linking to those headers.
  • the include itself renders as a link to the included document
  • --embed-includes
Here is an example of inclusion of the files not-readme.bigb and not-readme-2.bigb:
\Include[not-readme]
\Include[not-readme-2]
\Include[not-readme-with-scope]
The above is the recommended and slightly insaner version of:
\Include[not-readme]

\Include[not-readme-2]

\Include[not-readme-with-scope]
The insaner version is a bit insaner because the \Include magically discards the following newline node that follows it if it just a plaintext node containing exactly a newline. With a double newline, the newline would already have been previously taken out on the lexing stage as part of a paragraph.
Section 4.2.8.3. "\Include example" shows what those actually render like.
When you are in a subdirectory, include resolution just is simply relative to the subdirectory. E.g. we could do:
subdir/index.bigb
= Subdir

\Include[notindex]
\Include[subdir2/notindex]
subdir/notindex.bigb
= Notindex
subdir/subdir2/notindex.bigb
= Notindex
It is not currently possible to include from ancestor directories: github.com/ourbigbook/ourbigbook/issues/214.
This option is analogous to \H parent argument, but for includes.
For example, consider you have:
= Animal

== Dog

== Cat

== Bat
and now you want to split Cat to cat.bigb.
If you wrote:
= Animal

== Dog

\Include[cat]

== Bat
Cat would be a child of Dog, since that is the previous header, which is not what we want.
Instead, we want to write:
= Animal

== Dog

\Include[cat]{parent=animal}

== Bat
and now Cat will be a child of Animal as desired.
This shows what includes render as.
Some \i[italic] text.
which renders as:
Some italic text.
The JsCanvasDemo macro allows you to create interactive HTML/JavaScript canvas demos easily.
These demos:
  • only start running when the user scrolls over them for the first time
  • stop automatically when they leave the viewport
so you can stuff as many of them as you want on a page, and they won't cause the reader's CPU to fry an egg.
\JsCanvasDemo[[
new class extends OurbigbookCanvasDemo {
  init() {
    super.init('hello');
    this.pixel_size_input = this.addInputAfterEnable(
      'Pixel size',
      {
        'min': 1,
        'type': 'number',
        'value': 1,
      }
    );
  }
  draw() {
    var pixel_size = parseInt(this.pixel_size_input.value);
    for (var x = 0; x < this.width; x += pixel_size) {
      for (var y = 0; y < this.height; y += pixel_size) {
        var b = ((1.0 + Math.sin(this.time * Math.PI / 16)) / 2.0);
        this.ctx.fillStyle =
          'rgba(' +
          (x / this.width) * 255 + ',' +
          (y / this.height) * 255 + ',' +
          b * 255 +
          ',255)'
        ;
        this.ctx.fillRect(x, y, pixel_size, pixel_size);
      }
    }
  }
}
]]
which renders as:
new class extends OurbigbookCanvasDemo {
  init() {
    super.init('hello');
    this.pixel_size_input = this.addInputAfterEnable(
      'Pixel size',
      {
        'min': 1,
        'type': 'number',
        'value': 1,
      }
    );
  }
  draw() {
    var pixel_size = parseInt(this.pixel_size_input.value);
    for (var x = 0; x < this.width; x += pixel_size) {
      for (var y = 0; y < this.height; y += pixel_size) {
        var b = ((1.0 + Math.sin(this.time * Math.PI / 16)) / 2.0);
        this.ctx.fillStyle =
          'rgba(' +
          (x / this.width) * 255 + ',' +
          (y / this.height) * 255 + ',' +
          b * 255 +
          ',255)'
        ;
        this.ctx.fillRect(x, y, pixel_size, pixel_size);
      }
    }
  }
}
And another one showing off some WebGL:
new class extends OurbigbookCanvasDemo {
  init() {
    super.init('webgl', {context_type: 'webgl'});
    this.ctx.viewport(0, 0, this.ctx.drawingBufferWidth, this.ctx.drawingBufferHeight);
    this.ctx.clearColor(0.0, 0.0, 0.0, 1.0);
    this.vertexShaderSource = `
#version 100
precision highp float;
attribute float position;
void main() {
  gl_Position = vec4(position, 0.0, 0.0, 1.0);
  gl_PointSize = 64.0;
}
`;

    this.fragmentShaderSource = `
#version 100
precision mediump float;
void main() {
  gl_FragColor = vec4(0.18, 0.0, 0.34, 1.0);
}
`;
    this.vertexShader = this.ctx.createShader(this.ctx.VERTEX_SHADER);
    this.ctx.shaderSource(this.vertexShader, this.vertexShaderSource);
    this.ctx.compileShader(this.vertexShader);
    this.fragmentShader = this.ctx.createShader(this.ctx.FRAGMENT_SHADER);
    this.ctx.shaderSource(this.fragmentShader, this.fragmentShaderSource);
    this.ctx.compileShader(this.fragmentShader);
    this.program = this.ctx.createProgram();
    this.ctx.attachShader(this.program, this.vertexShader);
    this.ctx.attachShader(this.program, this.fragmentShader);
    this.ctx.linkProgram(this.program);
    this.ctx.detachShader(this.program, this.vertexShader);
    this.ctx.detachShader(this.program, this.fragmentShader);
    this.ctx.deleteShader(this.vertexShader);
    this.ctx.deleteShader(this.fragmentShader);
    if (!this.ctx.getProgramParameter(this.program, this.ctx.LINK_STATUS)) {
      console.log('error ' + this.ctx.getProgramInfoLog(this.program));
      return;
    }
    this.ctx.enableVertexAttribArray(0);
    var buffer = this.ctx.createBuffer();
    this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, buffer);
    this.ctx.vertexAttribPointer(0, 1, this.ctx.FLOAT, false, 0, 0);
    this.ctx.useProgram(this.program);
  }
  draw() {
    this.ctx.clear(this.ctx.COLOR_BUFFER_BIT);
    this.ctx.bufferData(this.ctx.ARRAY_BUFFER, new Float32Array([Math.sin(this.time / 60.0)]), this.ctx.STATIC_DRAW);
    this.ctx.drawArrays(this.ctx.POINTS, 0, 1);
  }
}
Insane with * (asterisk space):
* a
* b
* c
which renders as:
  • a
  • b
  • c
Equivalent saner with implicit ul container:
\L[a]
\L[b]
\L[c]
which renders as:
  • a
  • b
  • c
Equivalent fully sane with explicit container:
\Ul[
\L[a]
\L[b]
\L[c]
]
which renders as:
  • a
  • b
  • c
The explicit container is required if you want to pass extra arguments properties to the ul list macro, e.g. a title and an ID: Ul 1:
\Ul
{id=list-my-id}
[
\L[a]
\L[b]
\L[c]
]
which renders as:
  • a
  • b
  • c
This is the case because without the explicit container in an implicit ul list, the arguments would stick to the last list item instead of the list itself.
It is also required if you want ordered lists:
\Ol[
\L[first]
\L[second]
\L[third]
]
which renders as:
  1. first
  2. second
  3. third
Insane nested list with two space indentation:
* a
  * a1
  * a2
  * a2
* b
* c
which renders as:
  • a
    • a1
    • a2
    • a2
  • b
  • c
The indentation must always be exactly equal to two spaces, anything else leads to errors or unintended output.
Equivalent saner nested lists with implicit containers:
\L[
a
\L[a1]
\L[a2]
\L[a2]
]
\L[b]
\L[c]
which renders as:
  • a
    • a1
    • a2
    • a2
  • b
  • c
Insane list item with a paragraph inside of it:
* a
* I have

  Multiple paragraphs.

  * And
  * also
  * a
  * list
* c
which renders as:
  • a
  • I have
    Multiple paragraphs.
    • And
    • also
    • a
    • list
  • c
Equivalent sane version:
\L[a]
\L[
I have

Multiple paragraphs.

\L[And]
\L[also]
\L[a]
\L[list]
]
\L[c]
which renders as:
  • a
  • I have
    Multiple paragraphs.
    • And
    • also
    • a
    • list
  • c
Insane lists may be escaped with a backslash as usual:
\* paragraph starting with an asterisk.
which renders as:
* paragraph starting with an asterisk.
You can also start insane lists immediately at the start of a positional or named argument, e.g.:
\P[* a
* b
* c
]
which renders as:
  • a
  • b
  • c
And now a list outside of \OurBigBookExample to test how it looks directly under the \Toplevel implicit macro:
  • a
  • b
  • c
Via KaTeX server side, oh yes!
Inline math is done with the dollar sign ($) insane macro shortcut:
My inline $\sqrt{1 + 1}$ is awesome.
which renders as:
My inline is awesome.
and block math is done with two or more dollar signs ($$):
$$
\sqrt{1 + 1} \\
\sqrt{1 + 1}
$$
which renders as:
The sane version of inline math is a lower case m:
My inline \m[[\sqrt{1 + 1}]] is awesome.
which renders as:
My inline is awesome.
and the sane version of block math is with an upper case M:
\M[[
\sqrt{1 + 1} \\
\sqrt{1 + 1}
]]
which renders as:
The capital vs lower case theme is also used in other elements, see: block vs inline macros.
In the sane syntax, as with any other argument, you have to either escape any closing square brackets ] with a backslash \:
My inline \m[1 - \[1 + 1\] = -1] is awesome.
which renders as:
My inline is awesome.
or with the equivalent double open and close:
My inline \m[[1 - [1 + 1] = -1]] is awesome.
HTML escaping happens as you would expect, e.g. < shows fine in:
$$
1 < 2
$$
which renders as:
Equation IDs and titles and linking to equations works identically to images, see that section for full details. Here is one equation reference example that links to the following insane syntax equation: Equation 7. "My first insane equation":
$$
\sqrt{1 + 1}
$$
{title=My first insane equation}
which renders as:
Equation 7. My first insane equation.
and the sane equivalent Equation 8. "My first sane equation":
\M{title=My first sane equation}[[
\sqrt{1 + 1}
]]
which renders as:
Equation 8. My first sane equation.
Here is a raw one just to test the formatting outside of a ourbigbook_comment:
OurBigBook ships with several commonly used math macros enabled by default.
The full list of built-in macros can be seen at: default.tex.
Here's one example of using \dv from the physics package for derivatives:
$$
\dv{x^2}{x} = 2x
$$
which renders as:
Our goal is to collect the most popular macros from the most popular pre-existing LaTeX packages and make them available with this mechanism.
The built-in macros are currently only available on OurBigBook CLI and OurBigBook Web, not when using the JavaScript API directly. We should likely make that possible as well at some point.
If your project has multiple .bigb input files, you can share Mathematics definitions across all files by adding them to the ourbigbook.tex file on the toplevel directory.
For example, if ourbigbook.tex contains:
\newcommand{\foo}[0]{bar}
then from any .bigb file we in the project can use:
$$
\foo
$$
Note however that this is not portable to OurBigBook Web and will likely never be, as we want Web source to be reusable across authors. So the ony way to avoid macro definition conflicts would be to have a namespace system in place, which sounds hard/impossible.
Ideally, you should only use this as a temporary mechanism while you make a pull request to modify the built-in math macros :-)
Besides using ourbigbook.tex, you can also define your own math macros directly in the source code.
This is generally fragile however because it doesn't work:
If you still want to do it for some reason, first create an invisible block (with {show=0}) defining with a \newcommand definition:
$$
\newcommand{\foo}[0]{bar}
$${show=0}
which renders as:
We make it invisible because this block only contains KaTeX definitions, and should not render to anything.
Then the second math block uses those definitions:
$$
\foo
$$
which renders as:
Analogously with \def, definition:
$$
\gdef\foogdef{bar}
$${show=0}
which renders as:
and the second block using it:
$$
\foogdef
$$
which renders as:
And just to test that {show=1} actually shows, although it is useless, and that {show=0} skips incrementing the equation count:
$$1 + 1$${show=1}
$$2 + 2$${show=0}
$$3 + 3$${show=1}
which renders as:
Shows both the OurBigBook code and its rendered output, e.g.:
\OurBigBookExample[[
Some `ineline` code.
]]
which renders as:
Some `ineline` code.
which renders as:
Some ineline code.
Its input should be thought of as a literal code string, and it then injects the rendered output in the document.
This macro is used extensively in the OurBigBook documentation.
OK, this is too common, so we opted for some insanity here: double newline is a paragraph!
Paragraph 1.

Paragraph 2.
which renders as:
Paragraph 1.
Paragraph 2.
Equivalently however, you can use an explicit \P macros as well, which is required for example to add properties to a paragraph, e.g.:
\P{id=paragraph-1}[Paragraph 1]
\P{id=paragraph-2}[Paragraph 2]
which renders as:
Paragraph 1
Paragraph 2
Paragraphs are created automatically inside macro argument whenever a double newline appears.
Note that OurBigBook paragraphs render in HTML as div with class="p" and not as p. This means that you can add basically anything inside them, e.g. a list:
My favorite list is:
\Ul[
\li[aa]
\li[bb]
]
because it is simple.
which renders as a single paragraph.
One major advantage of this, is that when writing documentation, you often want to keep lists or code blocks inside a given paragraph, so that it is easy to reference the entire paragraph with an ID. Think for example of paragraphs in the C++ standard.
Dumps its contents directly into the rendered output.
This construct is not XSS safe, see: Section 10.2. "unsafe-xss (--unsafe-xss)".
Here for example we define a paragraph in raw HTML:
\passthrough[[
<p>Hello <b>raw</b> HTML!</p>
]]
which renders as:

Hello raw HTML!

And for an inline passthrough:
Hello \passthrough[[<b>raw</b>]] world!
which renders as:
Hello raw world!
With q:
And so he said:

\Q[
Something very smart

And with multiple paragraphs.
]

and it was great.
which renders as:
And so he said:
Something very smart
And with multiple paragraphs.
and it was great.
The insane syntax marks:
  • headers with || (pipe, pipe space) at the start of a line
  • regular cells with | (pipe, space) at the start of a line
  • separates rows with double newline
For example:
|| Header 1
|| Header 2

| 1 1
| 1 2

| 2 1
| 2 2
which renders as:
Header 1 Header 2
1 1 1 2
2 1 2 2
Empty cells are allowed without the trailing space however:
| 1 1
|
| 1 3

| 2 1
|
| 2 3
which renders as:
1 1 1 3
2 1 2 3
Equivalent fully explicit version:
\Table[
\Tr[
  \Th[Header 1]
  \Th[Header 2]
]
\Tr[
  \Td[1 1]
  \Td[1 2]
]
\Tr[
  \Td[2 1]
  \Td[2 2]
]
]
which renders as:
Header 1 Header 2
1 1 1 2
2 1 2 2
Any white space indentation inside an explicit \Tr can make the code more readable, and is automatically removed from final output due to remove_whitespace_children which is set for \Table.
To pass further arguments to an implicit table such as title or id, you need to use an explicit table macro as in: Table 3. "My table title".
\Table
{title=My table title}
{id=table-my-table}
[
|| Header 1
|| Header 2

| 1 1
| 1 2

| 2 1
| 2 2
]
which renders as:
Table 3. My table title.
Header 1 Header 2
1 1 1 2
2 1 2 2
We would like to remove that explicit toplevel requirement as per: github.com/ourbigbook/ourbigbook/issues/186 The rules of when the caption shows up or not similar to those of images as mentioned at Section 4.2.7.2.1. "Image caption".
Multiple source lines, including paragraphs, can be added to a single cell with insane syntax by indenting the cell with exactly two spaces just as for lists, e.g.:
|| h1
|| h2
|| h3

  h3 2

| 11
| 12

  12 2
| 13

| 21
| 22
| 23
which renders as:
h1 h2
h3
h3 2
11
12
12 2
13
21 22 23
Arbitrarily complex nested constructs may be used, e.g. a table inside a list inside table:
| 00
| 01

  * l1
  * l2

    | 20
    | 21

    | 30
    | 31

| 10
| 11
which renders as:
00
01
  • l1
  • l2
    20 21
    30 31
10 11
And now a table outside of \OurBigBookExample to test how it looks directly under the \Toplevel implicit macro:
Table 4. My table title.
Header 1 Header 2
1 1 1 2
2 1 2 2
And a fully insane one:
Header 1 Header 2
1 1 1 2
2 1 2 2
JavaScript interactive on-click table sorting is enabled by default, try it out by clicking on the header row:
|| String col
|| Integer col
|| Float col

| ab
| 2
| 10.1

| a
| 10
| 10.2

| c
| 2
| 3.4
which renders as:
String col Integer col Float col
ab 2 10.1
a 10 10.2
c 2 3.4
Powered by: github.com/tristen/tablesort
OurBigBook automatically adds a table of contents at the end of the first non-toplevel header of every document.
For example, on a standard document with a single toplevel header:
= Animal

Animals are cute!

== Dog

== Cat
the ToC is rendered something like:
= Animal

Animals are cute!

Table of Contents
* Dog
* Cat

== Dog

== Cat
The ToC ignores the toplevel header if you have one.
For when you want a quick outline of the header tree on the terminal, also consider the --log headers option.
To the left of table of content entries you can click on an open/close icon to toggle the visibility of different levels of the table of contents.
The main use case covered by the expansion algorithm is as follows:
  • the page starts with all nodes open to facilitate Ctrl + F queries
  • if you click on a node in that sate, you close all its children, to get a summarized overview of the contents
  • if you click one of those children, it opens only its own children, so you can interactively continue exploring the tree
The exact behaviour is:
  • the clicked node is open:
    • state 1 all children are closed. Action: open all children recursively, which puts us in state 2
    • state 2: not all children are closed. Action close all children, which puts us in state 1. This gives a good overview of the children, without any children of children getting in the way.
  • state 3: the clicked node is closed (not showing any children). Action: open it to show all direct children, but not further descendants (i.e. close those children). This puts us in state 1.
Note that those rules make it impossible to close a node by clicking on it, the only way to close a node os to click on its parent, the state transitions are:
  • 3 -> 1
  • 1 -> 2
  • 2 -> 1
but we feel that it is worth it to do things like this to cover the main use case described above without having to add two buttons per entry.
Clicking on the link from a header up to the table of contents also automatically opens up the node for you in case it had been previously closed manually.
Very analogous to images, only differences will be documented here.
In the case of videos, where to store images becomes even more critical since videos are even larger than images, such that the following storage approaches are impractical off the bat:
As a result, then Wikimedia Commons is one of the best options much like for images:
\Video[https://upload.wikimedia.org/wikipedia/commons/8/85/Vacuum_pump_filter_cut_and_place_in_eppendorf.webm]
{id=sample-video-in-wikimedia-commons}
{title=Nice sample video stored in Wikimedia Commons}
{start=5}
which renders as:
Video 3. Nice sample video stored in Wikimedia Commons. Source.
We also handle more complex transcoded video URLs just fine:
\Video[https://upload.wikimedia.org/wikipedia/commons/transcoded/1/19/Scientific_Industries_Inc_Vortex-Genie_2_running.ogv/Scientific_Industries_Inc_Vortex-Genie_2_running.ogv.480p.vp9.webm]
{id=sample-video-in-wikimedia-commons-transcoded}
{title=Nice sample video stored in Wikimedia Commons transcoded}
which renders as:
Video 4. Nice sample video stored in Wikimedia Commons transcoded. Source.
Commons is better than YouTube if your content is on-topic there because:
If your video does not fit the above Wikimedia Commons requirements, YouTube could be a good bet. OurBigBook automatically detects YouTube URLs for you, so the following should just work:
\Video[https://youtube.com/watch?v=YeFzeNAHEhU&t=38]
{id=sample-video-from-youtube-implicit-youtube}
{title=Nice sample video embedded from YouTube implicit from `youtube.com` URL}
which renders as:
Video 5. Nice sample video embedded from YouTube implicit from youtube.com URL. Source.
The youtu.be domain hack URLs also work;
\Video[https://youtu.be/YeFzeNAHEhU?t=38]
{id=sample-video-from-youtube-implicit-youtu-be}
{title=Nice sample video embedded from YouTube implicit from `youtu.be` URL}
which renders as:
Video 6. Nice sample video embedded from YouTube implicit from youtu.be URL. Source.
Alternatively, you can reach the same result in a more explicit and minimal way by setting {provider=youtube} and the start arguments:
\Video[YeFzeNAHEhU]{provider=youtube}
{id=sample-video-from-youtube-explicit}
{title=Nice sample video embedded from YouTube with explicit `youtube` argument}
{start=38}
which renders as:
Video 7. Nice sample video embedded from YouTube with explicit youtube argument. Source.
When the youtube provider is selected, the Video address should only to contain the YouTube video ID, which shows in the YouTube URL for the video as:
https://www.youtube.com/watch?v=<video-id>
Remember that you can also enable the youtube provider by default on your ourbigbook.json with:
"media-provider" {
  "youtube": {"default-for": "video"}
}
But you can also use raw video files from any location that can serve them of course, e.g. here is one stored in this repository: Video 8. "Nice sample video stored in this repository".
\Video[Tank_man_side_hopping_in_front_of_some_tanks.mp4]
{id=sample-video-in-repository}
{title=Nice sample video stored in this repository}
{source=https://www.youtube.com/watch?v=YeFzeNAHEhU}
{start=3}
which renders as:
Video 8. Nice sample video stored in this repository. Source.
And as for images, setting titleFromSrc automatically calculates a title for you:
\Video[Tank_man_side_hopping_in_front_of_some_tanks.mp4]
{titleFromSrc}
{source=https://www.youtube.com/watch?v=YeFzeNAHEhU}
which renders as:
Video 9. Tank man side hopping in front of some tanks. Source.
Unlike image lazy loading, we don't support video lazy loading yet because:
  • non-youtube videos use the video tag which has no loading property yet
  • youtube videos are embedded with iframe and iframe has no loading property yet
Both of this cases could be worked around with JavaScript:
The time to start playing the video at in seconds. Works for both youtube and non-YouTube videos.
Every macro in OurBigBook can have an optional id and many also have a reserved title property.
When a macro in the document has a title argument but no id argument given, get an auto-generated ID from the title: automatic ID from title.
Usually, the most convenient way to write cross references is with the insane syntax with delimited angled braces:
<Cross references> are awesome.
which renders as:
Cross references are awesome.
More details at: insane cross reference.
The sane equivalent to this is:
\x[cross-reference]{c}{p} are awesome section.
which renders as:
Cross references are awesome section.
Note how that is more verbose, especially because here we use both the \x c argument and \x p argument to capitalize and pluraize as desired.
Another sane equivalent would be to add an explicit link body as in:
\x[cross-reference][Cross references] are awesome.
which renders as:
Cross references are awesome.
When you use an insane cross reference (<>) such as in:
<Cross references> are awesome.
which renders as:
Cross references are awesome.
it gets expanded exactly to the sane equivalent:
\x[Cross references]{magic} are alwasome
so we see that the \x magic argument gets added. It is that argument that for example adds the missing -, and removes the pluralization to find the correct ID cross-reference. For more details, see the documentation of the \x magic argument.
Like other insane constructs, insane cross references are exactly equivalent to the sane version, so you can just add other arguments after the construct, e.g.:
<Cross references>{full} are awesome.
which renders as:
which gets converted to exact the same as the sane:
\x[cross-reference]{full} are awesome.
which renders as:
In most cases it is generally more convenient to simply use the \x magic argument through insane cross references instead of the c and p arguments as described on the rest of this section, see also: Section 4.2.20.3. "Inflection vs magic".
A common usage pattern is that we want to use header titles in non-full cross references as the definition of a concept without repeating the title, for example:
== Dog

Cute animal.

\x[cats][Cats] are its natural enemies.

== Cats

This is the natural enemy of a \x[dog][dog].

\x[dog][Dogs] are cute, but they are still the enemy.

One example of a cat is \x[felix-the-cat].

=== Felix the Cat

Felix is not really a \x[cats][cat], just a carton character.
However, word inflection makes it much harder to avoid retyping the definition again.
For example, in the previous example, without any further intelligent behaviour we would be forced to re-type \x[dog][dog] instead of the desired \x[dog].
OurBigBook can take care of some inflection cases for you.
For capitalization, both headers and cross reference macros have the c boolean argument which stands for "capitalized":
  • for headers, c means that the header title has fixed capitalization as given in the title, i.e.
    • if the title has a capital first character, it will always show as a capital, as is the case for most proper noun
    • if it is lower case, it will also always remain lower case, as is the case for some rare proper nouns, notably the name of certain companies
    This means that for such headers, c in the x has no effect. Maybe we should give an error in that case. But lazy now, send PR.
  • for cross reference macros, c means that the first letter of the title should be capitalized.
    Using this option is required when you are starting a sentence with a non-proper noun.
Capitalization is handled by a JavaScript case conversion.
For pluralization, cross reference macros have the p boolean argument which stands for "pluralize":
  • if given and true, this automatically pluralizes the last word of the target title by using the github.com/blakeembrey/pluralize library
  • if given and false, automatically singularize
  • if not given, don't change the number of elements
If your desired pluralization is any more complex than modifying the last word of the title, you must do it manually however.
With those rules in mind, the previous OurBigBook example can be written with less repetition as:
== Dog

Cute animal.

\x[cats]{c} are its natural enemies.

== Cats

This is the natural enemy of a \x[dog].

\x[dog]{p} are cute, but they are still the enemy.

One example of a cat is \x[Felix the Cat].

=== Felix the Cat
{c}

Felix is not really a \x[cats][cat], just a carton character.
If plural and capitalization don't handle your common desired inflections, you can also just create custom ones with the \H synonym argument.
Now for a live example for quick and dirty interactive testing.
\x[inflection-example-not-proper]
which renders as:
\x[inflection-example-not-proper]{c}
which renders as:
\x[inflection-example-not-proper]{full}
which renders as:
\x[inflection-example-proper]
which renders as:
\x[inflection-example-proper]{c}
which renders as:
\x[inflection-example-not-proper-lower]
which renders as:
\x[inflection-example-not-proper-lower]{c}
which renders as:
\x[inflection-example-proper-lower]
which renders as:
\x[not-readme]
which renders as:
\x[not-readme]{c}
which renders as:
\x[inflection-example-not-proper]{p}
which renders as:
\x[inflection-plural-examples]
which renders as:
\x[inflection-plural-examples]{p}
which renders as:
\x[inflection-plural-examples]{p=0}
which renders as:
\x[inflection-plural-examples]{p=1}
which renders as:
\x[not-the-readme-header-with-fixed-case]
which renders as:
The \x magic argument was introduced later, and basically became a better alternative to cross reference title inflection in all but the following cases:
  • \H disambiguate argument: disambiguate prevents the determination of plural inflection, e.g. in:
    = Python
    {disambiguate=animal}
    
    I like <python animal>.
    there is currently no way to make it output Pythons in the plural without resorting to either \x p argument or an explicit content, because if you wrote:
    I like <pythons animal>.
    it would just lead to Id not found, as we would try the plural vs singular on animal only.
    Maybe one day we can implement an even insaner system that understands that parenthesis should skipped for the inflection as in:
    I like <pythons (animal)>.
    github.com/ourbigbook/ourbigbook/issues/244
  • plural headers. We only attempt to singularize arguments for now, not pluralize them. So if you had:
    My <dog> is nice.
    
    == Dogs
    you would instead need to write:
    My <dog>{p=0} is nice.
    or:
    My <dog>[dog] is nice.
If you use \x within a title, which most commonly happens for image titles, that can generate complex dependencies between IDs, which would either be harder to implement, or lead to infinite recursion.
To prevent such problems, OurBigBook emits an error if you use an \x without content in the title of one of the following elements:
  • any header. For example, the following gives an error:
    = h1
    {id=myh1}
    
    == \x[myh1]
    This could be solved by either adding a content to the reference:
    = h1
    {id=myh1}
    
    == \x[myh1][mycontent]
    or by adding an explicit ID to the header:
    = h1
    {id=myh1}
    
    == \x[myh1]
    {id=myh2}
  • non-header (e.g. an image) that links to the title of another non-header
    For non-headers, things are a bit more relaxed, and we can link to headers, e.g.:
    = h1
    
    \Image[myimg.jpg]
    {title=my \x[h1]}
    This is allowed because OurBigBook calculates IDs in two stages: first for all headers, and only later non non-headers.
    What you cannot do is link to another image e.g.:
    \Image[myimg.jpg]
    {id=myimage1}
    {title=My image 1}
    
    \Image[myimg.jpg]
    {title=my \x[h1]}
    and there the workaround are much the same as for headers: either explicitly set the cross reference content:
    \Image[myimg.jpg]
    {id=myimage1}
    {title=My image 1}
    
    \Image[myimg.jpg]
    {title=my \x[h1][My image 1]}
    or explicitly set an ID:
    \Image[myimg.jpg]
    {id=myimage1}
    {title=My image 1}
    
    \Image[myimg.jpg]
    {id=myimage2}
    {title=my \x[h1]}
    TODO both workaround are currently broken Image title with x to image with content incorrectly disallowed, we forgot to add a test earlier on, and things inevitably broke... Should not be hard to fix though, we are just overchecking.
While it is technically possible relax the above limitations and give an error only in case of loops, it would require a bit of extra work which we don't want to put in right now: github.com/ourbigbook/ourbigbook/issues/95.
Furthermore, the above rules do not exclude infinite rendering loops, but OurBigBook detects such loops and gives a nice error message, this has been fixed at: github.com/ourbigbook/ourbigbook/issues/34
For example this would contain an infinite loop:
\Image[myimg.jpg]
{id=myimage1}
{title=\x[myimage2]}

\Image[myimg.jpg]
{id=myimage2}
{title=\x[myimage1]}
This infinite recursion is fundamentally not technically solved: the user has to manually break the loop by providing an x content explicitly, e.g. in either:
\Image[myimg.jpg]
{id=myimage1}
{title=\x[myimage2][my content 2]}

\Image[myimg.jpg]
{id=myimage2}
{title=\x[myimage1]}
or:
\Image[myimg.jpg]
{id=myimage1}
{title=\x[myimage2]}

\Image[myimg.jpg]
{id=myimage2}
{title=\x[myimage1][my content 1]}
A closely related limitation is the simplistic approach to \x id output format.
Reference to the first header of another file:
\x[not-readme]
which renders as:
Reference to a non-first header of another file:
\x[h2-in-not-the-readme]
which renders as:
To make toplevel links cleaner, if the target header is the very first element of the other page, then the link does not get a fragment, e.g.: \x[not-readme] rendered as:
<a href="not-readme"
and not:
<a href="not-readme#not-readme"
while \x[h2-in-not-the-readme] is rendered with the fragment:
<a href="not-readme#h2-in-not-the-readme"
Reference to the first header of another file that is a second inclusion:
\x[included-by-not-readme]
which renders as:
Reference to another header of another file, with full:
\x[h2-in-not-the-readme]{full}.
which renders as:
Note that when full is used with references in another file in multi page mode, the number is not rendered as explained at: Section 4.2.20.6.4.1. "\x full argument in cross file references".
Reference to an image in another file:
\x[image-not-readme-xi]{full}.
which renders as:
Reference to an image in another file:
\x[image-figure-in-not-the-readme-without-explicit-id]{full}.
which renders as:
Remember that the ID of the toplevel header is automatically derived from its file name, that's why we have to use:
\x[not-readme]
which renders as:
instead of:
\x[not-the-readme]
Reference to a subdirectory:
\x[subdir]

\x[subdir/h2]

\x[subdir/notindex]

\x[subdir/notindex-h2]
which renders as:
Implemented at: github.com/ourbigbook/ourbigbook/issues/116
Reference to an internal header of another file: h2 in not the README. By default, That header ID gets prefixed by the ID of the top header.
When using --embed-includes mode, the cross file references end up pointing to an ID inside the current HTML element, e.g.:
<a href="#not-readme">
rather than:
<a href="not-readme.html/#not-readme">
This is why IDs must be unique for elements across all pages.
When running in Node.js, OurBigBook dumps the IDs of all processed files to a out/db.sqlite3 file in the out directory, and then reads from that file when IDs are needed.
When converting under a directory that contains ourbigbook.json, out/db.sqlite3 is placed inside the same directory as the ourbigbook.json file.
If there is no ourbigbook.json in parent directories, then out/db.sqlite3 is placed in the current working directory.
db.sqlite3 is not created or used when handling input from stdin.
When running in the browser, the same JavaScript API will send queries to the server instead of a local SQLite database.
To inspect the ID database to debug it, you can use:
sqlite3 out/db.sqlite3 .dump
It is often useful to dump a single table, e.g. to dump the ids table:
sqlite3 out/db.sqlite3 '.dump ids'
and one particularly important query is to dump a list of all known IDs:
sqlite3 out/db.sqlite3 'select id from ids'
You can force ourbigbook to not use the ID database with the --no-db command line option
This section describes the philosophy of internal cross references.
In many static website generators, you just link to URL specific paths of internal headers.
In OurBigBook, internal cross references point to IDs, not paths.
For example, suppose "Superconductivity" is a descendant of "Condensed Matter Physics", and that the source for both is located at condensed-matter-physics.bigb, so that both appear on the same .html page condensed-matter-physics.html.
When linking to Superconductivity from an external page such as statistical-physics.bigb you write just <superconductivity> and NOT <condensed-matter-physics#superconductivity>. OurBigBook then automatically trakcs where superconductivity is located and produces href="condensed-matter-physics#superconductivity" for you.
This is important because on a static website, the location of headers might change. E.g. if you start writing a lot about superconductivity you would eventually want to split it to its own page, superconductivity.html otherwise page loads for condensed-matter-physics.html would become too slow as that file would become too large.
But if your links read <condensed-matter-physics#superconductivity>, and all links would break when you move things around.
So instead, you simply link to the ID <superconductivity>, and ourbigbook renders links correctly for you wherever the output lands.
When moving headers to separate pages, it is true that existing links to subheaders will break, but that simply cannot be helped. Large pages must be split into smaller ones. The issue can be mitigated in the following ways:
For OurBigBook Web, this is even more important, as we have dynamic article trees, so every header can appear on top.
If you really want to to use scopes, e.g. enforce the ID of "superconductivity" to be "condensed-matter-physics/superconductivity", then you can use the scope feature. However, this particular case would likely be a bad use case for that feature. You want your IDs to be as short as possible, which causes less need for refactoring, and makes topics on OurBigBook Web more likely to have matches from other users.
If the target title argument contains a link from either another cross references or a regular external hyperlink, OurBigBook automatically prevents that link from rendering as a link when no explicit body is given.
This is done because nested links are illegal in HTML, and the result would be confusing.
This use case is most common when dealing with media such as images. For example in:
= afds

\x[image-aa-zxcv-lolol-bb]

== qwer

\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
{title=aa \x[zxcv][zxcv] \a[http://example.com][lolol] bb}

== zxcv
the \x[image-aa-zxcv-lolol-bb] renders something like:
<a href="#image-aa-zxcv-lolol-bb">aa zxcv lolol bb</a>
and not:
<a href="#image-aa-zxcv-lolol-bb">aa <a href="zxcv">zxcv</a> <a href="http://example.com">lolol</a> bb</a>
Live example:
This is a nice image: \x[image-aa-zxcv-lolol-bb].

\Image[Tank_man_standing_in_front_of_some_tanks.jpg]
{title=aa \x[cross-reference-title-link-removal][zxcv] \a[http://example.com][lolol] bb}
which renders as:
This is a nice image: Figure 21. "aa zxcv lolol bb".
Figure 21. aa zxcv lolol bb.
Capitalizes the first letter of the target title.
Setting the child boolean argument on a cross reference to a header as in:
\x[my-header]{child}
makes that header show up on the list of extra parents of the child.
This allows a section to have multiple parents, e.g. to include it into multiple categories. For example:
= Animal

== Mammal

=== Bat

=== Cat

== Flying animal

These animals fly:
* \x[bat]{child}

These animals don't fly:
* \x[cat]
would render something like:
= Animal

== Mammal

=== Bat (Parent section: Mammal)
(Tags: Flying animal)

=== Cat (Parent section: Mammal)

== Flying animal (Parent section: Animal)

These animals fly:
* \x[bat]

These animals don't fly:
* \x[cat]
so note how "Bat" has a list of tags including "Flying animal", but Cat does not, due to the child.
This property does not affect how the table of contents is rendered. We could insert elements sections there multiple times, but it has the downside that browser Ctrl + F searches would hit the same thing multiple times on the table of contents, which might make finding things harder.
== My title{id=my-id}

Read this \x[my-id][amazing section].
If the second argument, the content argument, is not present, it expand to the header title, e.g.:
== My title{id=my-id}

Read this \x[my-id].
is the same as:
== My title{id=my-id}

Read this \x[my-id][My title].
A live demo can be seen at: \x child argument demo.
Generally, a better alternative to this argument is to use \H child argument.
The term refers to sections that have a parent/child relationship via either of the:
rather than via the usual header hierarchy.
Secondary children show up for example on the tagged metadata section, but not on the table of contents, which is what the header hierarchy already shows.
Secondary children are normally basically used as "tags": a header such as Bat can be a direct child of Mammal, and a secondary child of Flying animal, or vice versa. Both Mammal and Flying animal are then basically ancestors. But we have to chose one main ancestor as "the parent", and other secondary ancestors will be seen as tags.
This option first does ID target from title conversion on the argument, so you can e.g. keep any spaces or use capitalization in the title as in:
= Animal

== Flying animal
{child=Big bat}

== Big bat
TODO the fact that this transformation is done currently makes it impossible to use "non-standard IDs" that contain spaces or uppercase letters. If someone ever wants that, we could maybe add a separate argument that does not do the expansion e.g.:
= Animal

== Flying animal
{childId=Big bat}

== Big bat
{id=Big bat}
but definitely the most important use case is having easier to type and read source with the standard IDs.
Oh, and cows are also mammals.
Bats can fly.
But cats can't.
Allows to link to headers with the \H file argument, e.g.:
= My header

Check out this amazing file: <path/to/myfile.txt>

== path/to/myfile.txt
To also show the section auto-generated number as in "Section X.Y My title" we add the optional {full} boolean argument to the cross reference, for example:
\x[x-full-argument]{full}.
which renders as:
{full} is not needed for cross references to most macros besides headers, which use full by default as seen by the default_x_style_full macro property in --help-macros. This is for example the case for images. You can force this to be disabled with {full=0}:
Compare \x[image-my-test-image]{full=0} vs \x[image-my-test-image]{full=1}.
which renders as:
For example in the following cross file reference:
\x[h2-in-not-the-readme]{full}.
which renders as:
we get just something like:
Section "h2 in not the readme"
instead of:
Section 1.2 "h2 in not the readme"
This is because the number "Section 1.2" might already have been used in the current page, leading to confusion.
This argument makes writing many internal links more convenient, and it was notably introduced because it serves as the sane version of insane cross references.
If given e.g. as in:
= Internal reference

\x[Internal references]{magic}
the link treated magically as follows:
  • content capitalization and pluralization are detected from the string, and implicitly set the \x c argument and \x p argument. In the example:
    • {c} capitalization is set because Internal references starts with an upper case character I
    • {p} pluralization is set because Internal references ends in a plural word
    In this simple example, the content therefore will be exactly Internal references as in the source. But note that this does not necessarily need to be the case, e.g. if we had done:
    \x[Internal Reference]{magic}
    then the content would be:
    Internal reference
    without capital R, i.e. everything except capitalization and pluralization is ignored. This forgiving way of doing things means that writers don't need to remember the exact ideal capitalization of everything, which is very hard to remember.
    It also means that any more complex elements will be automatically rendered as usual, e.g. if we had:
    = \i[Internal] reference
    
    \x[internal reference]{magic}
    then the output would still contain the <i> italic tag.
    If we had a scope as in \x[my scope/Internal references], then each scope part is checked separately. E.g. in this case we would have upper case Internal references, even though my scope is lowercase, and so {c} would be set.
  • the ID is calculated as follows:
    • automatic ID from title conversion is performed, with you exception: forwards slashs / are kept, in order to make scopes work.
      In our case, there aren't any slashes /, so it just gives internal-references. But if instead we had e.g.: \x[my scope/internal reference]{magic}, then we would reach my-scope/internal-reference and not my-scope-internal-reference.
    • if there is a match to an existing ID use it. internal-references in the plural does not match, so go to the next step
    • if the above failed, try singularizing the last word as in the \x p argument with p=0 before doing automatic ID from title conversion. This gives internal-reference, which does exist, and so we use that.
There may be some cases where you might still want to use cross reference title inflection however, see: Section 4.2.20.3. "Inflection vs magic".
Pluralizes or singularizes the last word of the target title.
The parent argument is exactly like the \x child argument, but it reverses the direction of the parent/child relation.
The ref argument of \x marks the link as reference, e.g.:
Trump said this and that.\x[donald-trump-access-hollywood-tape]{ref}

= Donald Trump Access Hollywood tape
renders something like:
Trump said this and that.<a href="donald-trump-access-hollywood-tape">*</a>
This could currently be replicated without ref by just using:
Trump said this and that.\x[donald-trump-access-hollywood-tape][*]
but later on we might add more precise reference fields like the page of a book or date fetched as Wikipedia supports.
Certain commonly used macros have insane macro shortcuts that do not start with backslash (\).
Originally, Ciro wanted to avoid those, but they just feel too good to avoid.
Every insane syntax does however have an equivalent sane syntax.
The style recommendation is: use the insane version which is shorter, unless you have a specific reason to use the sane version.
Insane in our context does not mean worse. It just mean "harder for the computer to understand". But it is more important that humans can understand in the first place! It is find to make the computer work a bit more for us when we are able to.
The insane code and math shortcuts work very analogously and are therefore described together in this section.
The insane inline code syntax:
a `b c` d
which renders as:
a b c d
and is equivalent to the sane:
a \c[[b c]] d
The insane block code:
a

``
b c
``

d
which renders as:
a
b c
d
and is equivalent to the sane:
a

\C[[
b c
]]

d
Insane arguments always work by abbreviating:
  • the macro name
  • one or more of its positional arguments, which are fixed as either literal or non-literal for a given insane construct
This means that you can add further arguments as usual.
For example, an insane code block with an id can be written as:
a `b c`{id=ef} g
because that is the same as:
a \c[b c]{id=ef} g
which renders as:
a
b c
g
So we see that the b c argument is the very first argument of \c.
Extra arguments must come after the insane opening, e.g. the following does not work:
a {id=ef}`b c` g
This restriction things easy to parse for humans and machines alike.
Literal backticks and dollar signs can be produced witha backslash escape as in:
a \` \$ b
which renders as:
a ` $ b
It is not possible to escape backticks (`) inside an insane inline code, or dollar signs ($) in insane math.
The design reason for that is because multiple backticks produce block code.
The upside is that then you don't have to escape anything else, e.g. backslashes (\) are rendered literally.
The only way to do it is to use the sane syntax instead:
a \c[[b ` c]] d

a \m[[\sqrt{\$4}]] d
which renders as:
a b ` c d
a d
Within block code and math, you can just add more separators:
```
code with two backticks
``
nice
```
which renders as:
code with two backticks
``
nice
OurBigBook Markup macro identifiers can consist of the following letters:
  • a-z lowercase
  • A-Z uppercase
  • 0-9
Since underscores _ or hyphens = are not allowed, camel case macro names are recommended, e.g. for \OurBigBookExample we use the name:
OurBigBookExample
Every argument in OurBigBook is either positional or named.
For example, in a header definition with an ID:
= My asdf
{id=asdf qwer}
{scope}
which is equivalent to the sane version:
\H[1][My asdf]
{id=asdf qwer}
{scope}
we have:
  • two positional argument: [1] and [My asdf]. Those are surrounded by square brackets [] and have no name
  • two named arguments: {id=asdf qwer} and {scope}.
    The first one has name id, followed by the separator =, followed by the value asdf qwer.
    The separator = always is optional. If not given, it is equivalent to an empty value, e.g.:
    {id=}
    is the same as:
    {id}
You can determine if a macro is positional or named by using --help-macros. Its output contains something like:
  "h": {
    "name": "h",
    "positional_args": [
      {
        "name": "level"
      },
      {
        "name": "content"
      }
    ],
    "named_args": {
      "id": {
        "name": "id"
      }
      "scope": {
        "name": "scope"
      }
    },
and so we see that level and the content argument are positional arguments, and id and scope are named arguments.
Generally, positional arguments are few (otherwise it would be hard to know which is which is which), and are almost always used for a given element so that they save us from typing the name too many times.
The order of positional arguments must of course be fixed, but named arguments can go anywhere. We can even mix positional and named arguments however we want, although this is not advised for clarity.
The following are therefore all equivalent:
\H[1][My asdf]{id=asdf qwer}{scope}
\H[1][My asdf]{scope}{id=asdf qwer}
\H{id=asdf qwer}{scope}[1][My asdf]
\H{scope}[1]{id=asdf qwer}[My asdf]
Just like named arguments, positional arguments are never mandatory.
Most positional arguments will default to an empty string if not given.
However, some positional arguments can have special effects if not given.
For example, an anchor with the first positional argument present (the URL), but not the second positional argument (the link text) as in:
\a[http://example.com]
which renders as:
has the special effect of generating automatic links as in:
\a[http://example.com][http://example.com]
This can be contrasted with named arguments, for which there is always a default value, notably for boolean arguments.
Some positional arguments are required, and if not given OurBigBook reports an error and does not render the node.
This is for example the level of a header.
These arguments marked with the mandatory: true --help-macros argument property.
Name arguments marked in --help-macros as boolean: true must either:
  • take no value and no = sign, in which case the value is implicitly set to 1
  • take value exactly 0 or 1
  • not be given, in which case a custom per-macro default is used. That value is the default from --help-macros, or 0 if such default is not given
For example, the \x full argument of cross references is correctly written as:
\x[boolean-argument]{full}
which renders as:
without the = sign, or equivalently:
\x[boolean-argument]{full=1}
which renders as:
The full=0 version is useful in the case of reference targets that unlike headers expand the title on the cross reference by default, e.g. images:
\x[boolean-argument]{full=1}
which renders as:
The name "boolean argument" is given by analogy to the "boolean attribute" concept in HTML5.
Common arguments are argument names that are present in all macros.
Explicitly sets the ID of a macro.
In OurBigBook Markup, every single macro has an ID, which can be either:
  • explicit: extracted from some input given by the user, either the id argument or the title argument. Explicit IDs can be referenced in Internal cross references and must be unique
  • implicit: automatically generated numerical ID. Implicit IDs cannot be referenced in Internal cross references and don't need to be unique. Their primary application is generating on hover links next to everything you hover, e.g. arbitrary paragraphs.
The most common way to assign an ID is implicitly with automatic ID from title conversion for macros that have a title argument.
The id argument allows to either override the automatic ID from title, or provide an explicit ID for elements that don't have a title argument.
Sometimes the short version of a name is ambiguous, and you need to add some extra text to make both its title and ID unique.
For example, the word "Python" could either refer to: