adrdox syntax

This document describes the syntax recognized by my documentation generator. It uses a hybrid of ddoc and markdown syntax, with some customizations and pre-defined styles I like, while not supporting things I feel aren't worth the hassle.

It has support for enough legacy ddoc that Phobos still works, but is really a different language - I think ddoc made a lot of mistakes (and markdown made mistakes too).

Paragraphs just work.

Automatically.

$(LIST
	* Lists can be displayed
	* in bracketed markdown style
)

$(SMALL_TABLE
	markdown | style
	tables   | work (if bracketed)
)

---
void d_code() {
  is formatted brilliantly;
}
---

```
Markdown-style code blocks work too for other languages
or convenient <pre> blocks.
```

```java
public static void Main() {
	return "With some syntax highlighting."
}
```

We also have `inline code`.

$(TIP and various content boxes.)

$(MATH \int \text{LaTeX} too! dx)

Paragraphs just work.

Automatically.

  • Lists can be displayed
  • in bracketed markdown style
markdownstyle
tableswork (if bracketed)
void d_code() {
  is formatted brilliantly;
}
Markdown-style code blocks work too for other languages
or convenient <pre> blocks.
public static void Main() {
	return "With some syntax highlighting."
}

We also have inline code.

and various content boxes.

\int \text{LaTeX} too! dx

Members

Functions

a_huge_complex_function
void a_huge_complex_function()

This huge complex function needs a complex footnote[1].

test
void test()

Document outline

Your comment consists of three parts: the first paragraph, which is meant to be a stand-alone summary which is shown out-of-context in search results, the synopsis, which is displayed "above the fold" - before the function prototype, member list, or automatically generated table of contents, and finally, the rest of the documentation.

The fold is inserted at the first "\n\n\n" it finds in your comment (the first time it sees two blank lines:


This is the summary. It is shown in search results and
at the top of your generated document.

This is the synopsis, still displayed above the fold.

So is this.


The two blank lines above is the placeholder where the
table of contents is inserted. This paragraph, and
everything below it, is the bulk body of the page.

Line breaks in the middle of a paragraph, except in code
blocks, are ignored. You can format your comments however you like.

This is the summary. It is shown in search results and at the top of your generated document.

This is the synopsis, still displayed above the fold.

So is this.

The two blank lines above is the placeholder where the table of contents is inserted. This paragraph, and everything below it, is the bulk body of the page.

Line breaks in the middle of a paragraph, except in code blocks, are ignored. You can format your comments however you like.

Symbol grouping

You can optionally group symbols together by defining groups in a special section in your module definition comment, then tagging the doc comments on the items.

1 /++
2 	This demos symbol grouping.
3 
4 	Symbol_groups:
5 
6 	group_name =
7 		Introductory and explanatory text for the group. It may
8 		include any kind of 
9 
10 	drawing =
11 		## Drawing
12 
13 		This library supports several drawing functions. You
14 		draw them all on a "surface" of sorts, derived from
15 		[Drawable].
16 +/
17 module test;
18 
19 /++ Group: group_name
20 	Introductory text
21 
22 	and paragraphs like normal.
23 
24 
25 	This goes below the fold.
26 +/
27 void foo() {}
28 
29 /++
30 	This is in the [drawing] group.
31 
32 	Group: drawing
33 +/
34 interface Drawable {
35 	/// Group: group_name
36 	void whatever() {}
37 }

The Symbol_groups: section should only appear on the module commment. The Group: name line MUST be the first thing to appear in a comment, or be on the very last line of the comment. It can only appear once. Putting a function in multiple groups is not current supported.

If there is no header at the start of the group definition, one will be automatically inserted based on the group name.

For cross referencing purposes, the groups are considered pseudo-symbols at module scope. This means you can refer to them with the shortcut [symbol] syntax from anywhere in the module, or from outside the module if used with a fully-qualified name.

However, for best results, it should not conflict with any real names in the module, nor with any link references, which also introduce pseudo-symbols. If there is a conflict, the reference result is currently undefined (it may be any one of them, in no particular order). I will define that precedence order at some other time - so for now, avoid name conflicts!

Macros

adrdox inherits ddoc's macro syntax, but uses it differently than ddoc: it does not support user-defined macros, and sometimes uses them to bracket special syntax.

Any time you see me show ddoc macro syntax, $(NAME ), be aware that you can also use ${NAME }. For example, if you have unbalanced parenthesis inside the thing, you may prefer to use ${}.

$(B this is bold)
${B so is this}
${I this has unbalanced paren :) }

this is bold so is this this has unbalanced paren :)

Code snippets

Inline code

Inline code can be marked with Markdown (and Ddoc) style `code here `, which will render as code here. Text inside the backticks suppress all other documentation generator processing - it will just be escaped for literal output.

If you need to display a literal `, use the $(BACKTICK) macro or a doubled backtick: ``.

Code inside backticks may only span one line. If a line has an unmatched backtick, it is not processed as code.

If you want syntax-highlighted inline D code, use $(D d code here), such as $(D if(a is true)) will result in if(a is true) - notice the syntax highlighting on the D keywords.

Block code

There are three syntaxes for code blocks: Markdown style ```, ddoc style ---, and a magic macro called $(CONSOLE).

All code blocks are outdented and leading and trailing blank lines are removed, but all other whitespace is left intact. This means you may indent it as much as you like inside your comments without breaking the output.

Markdown style - for generic code

The Markdown style block is meant to be used with generic code or preformatted text that is not D.

```
Code here 	which preserves
   whitespace
```
Code here 	which preserves
   whitespace

You can optionally include a language name after the opening ticks and it will label and attempt syntax highlighting (the syntax highlighter is not as precise as the D highlighter, but often should be good enough):

```javascript
/* This is highlighted Javascript! */
window.onload = function() {
	var a = "hello, world!";
	var b = 5;
};
```

```c
/* Highlighted C */
#include<stdio.h>
typedef struct {
	int a;
} test;
```

```php
<?php
	# highlighted PHP
	function foo($a) {
		$a = 'hello';
		return $a;
	}
?>
```

```python
# highlighted python
class test:
	""" docstring """
	def myfunc():
		if True or 1 > 0:
			print "hello"
		else
			print test
```

```html
<span class="foo">
	<!-- try hovering over the entity! -->
	HTML &amp;
</span>
```

```css
/* This also highlights */
span[data-test="foo"] > .bar {
	color: red;
}
```

```sdlang
// dub.sdl can contain comments!
name "somepackage"
description "A little web service of mine."
authors "Peter Parker"
homepage "http://myproject.example.com"
license "GPL-2.0"
dependency "vibe-d" version="~>0.7.23"
configuration "metro-app" {
	platforms "windows"
	targetType "executable"
	versions "MetroApp"
	libs "d3d11"
}
configuration "desktop-app" {
	platforms "windows"
	targetType "executable"
	versions "DesktopApp"
	libs "d3d9"
}
configuration "glut-app" {
	// works on any platform
	targetType "executable"
	versions "GlutApp"
}
```
/* This is highlighted Javascript! */
window.onload = function() {
	var a = "hello, world!";
	var b = 5;
};
/* Highlighted C */
#include<stdio.h>
typedef struct {
	int a;
} test;
<?php
	# highlighted PHP
	function foo($a) {
		$a = 'hello';
		return $a;
	}
?>
# highlighted python
class test:
""" docstring """ def myfunc():
if True or 1 > 0:
print "hello"
else
print test
<span class="foo">
	<!-- try hovering over the entity! -->
	HTML &amp;
</span>
/* This also highlights */
span[data-test="foo"] > .bar {
	color: red;
}
1 // dub.sdl can contain comments!
2 name "somepackage"
3 description "A little web service of mine."
4 authors "Peter Parker"
5 homepage "http://myproject.example.com"
6 license "GPL-2.0"
7 dependency "vibe-d" version="~>0.7.23"
8 configuration "metro-app" {
9 	platforms "windows"
10 	targetType "executable"
11 	versions "MetroApp"
12 	libs "d3d11"
13 }
14 configuration "desktop-app" {
15 	platforms "windows"
16 	targetType "executable"
17 	versions "DesktopApp"
18 	libs "d3d9"
19 }
20 configuration "glut-app" {
21 	// works on any platform
22 	targetType "executable"
23 	versions "GlutApp"
24 }

Currently supported languages for highlighting include: C, C++, Javascript, PHP, Java, C#, CSS, HTML, XML, Python, Ruby, adrscript and D. Though, for D, you should use ddoc style --- delimiters to get the full-featured D highlighter instead of using the simpler one here. This simple highlighter aims for good enough to help visually on simple examples rather than being perfect on each target language.

Use the language name in all lower case when tagging the language, like php or c++.

If you ever want to document the syntax of a Markdown code block itself, I added a magic ```{ code }``` syntax. As long as the braces are nested, everything inside will be considered part of the literal code block, including other code blocks.

The generator MAY syntax highlight the language using span with class names, but might not (really depends on if I implement it). You may use the language as a target in CSS using the data-language attribute to customize the appearance.

Ddoc style - for D code

The ddoc style block only works with D code. It runs the sample through the D lexer, so it understands things like nested documentation comments and will properly skip them while syntax highlighting the output.

---
/**
	Ddoc style code blocks understand D deeply.

	---
	if(example.nested)
		stillWorks!();
	---
*/
void main() {}
---
/**
	Ddoc style code blocks understand D deeply.

	---
	if(example.nested)
		stillWorks!();
	---
*/
void main() {}

Ddoc style code samples are special in one way: you can highlight code inside it by using /* adrdox_highlight{ */ code here would be highlighted /* }adrdox_highlight */ comments in the sample. Note that it matches those strings exactly, meaning you must use /* */ comments and must have the same spacing. /* adrdox_highlight{ */ turns it on, /* }adrdox_highlight */ turns it off. Note that if you don't turn it off, you may cause invalid html to be generated (the implementation just opens and closes a span element right now).

---
// I will demo highlight below for the `main` function
/* adrdox_highlight{ */void main() {

}/* }adrdox_highlight */
// and now we are done.
---
// I will demo highlight below for the `main` function
void main() {

}
// and now we are done.

Console macro - for console output

The $(CONSOLE) macro is for copy/pasting text out of your console, such as showing command lines or program output. You MAY nest macros inside it for additional formatting, and thus, you should escape any $ followed by ( in the text.

$(CONSOLE
	$ dmd hello.d
	$ ./hello
	Hello, $(B world)!
)
$ dmd hello.d
$ ./hello
Hello, world!

Note that most special syntax works inside $(CONSOLE), but Ddoc-style code samples, delimited with ---, does not. This is because that breaks things more often than it is useful.

Documented unittests

I also implemented the feature from ddoc where unittests with a documentation comment are appended to the examples section of the previous documented declaration. They will appear in an Examples section (together with any others you manually write in Examples:), or inline in the documentation if you give them an $(ID some_unique_name) in the doc comment of the unittest, and write $(EMBED_UNITTEST some_unique_name) somewhere in your body text. Both the test and its associated comment will be moved to that location instead of being put in the examples section.

If you have a line that must be in the test to be useful, but should not appear in the documentation, you can simply comment it: // exclude from docs. But the line must end with that exact string.

/// The assert inside will not appear in the generated docs
unittest {
   int a;
   assert(a == 2); // exclude from docs
   writeln(a);
}

Cross-referencing

Many tasks of cross-referencing are done automatically. Inheritance and function signatures use semantic data from the D source to link themselves. URLs in the raw text, such as http://dpldocs.info/ are detected and hyperlinked automatically. Tables of contents are created, as needed, by scanning for headers.

However, in your text, you may also want to reference names and links that are not automatically detected.

Since this is such a common task, I dedicated a short, special syntax to it: square brackets. Write a name or URL inside brackets and it will linkify it, as specifically as it can from the index built from semantic D data. For example: [arsd.color] will yield arsd.color, a link to my color module.

When documenting code, it will first try to detect a URL. If so, it treats it as a link. Next, it will try to look up the D identifier in the current scope. If it finds it, it will link to the most local variable, following the import graph. If all else fails, it will just assume it is a relative filename and link that way.

If you want to load modules for name lookup, but not generate documentation for them, pass the file or the directory containing to adrdox with --load.

In most cases, putting a D name inside brackets should link as you expect.

You can also change the display name by putting a pipe after the link, followed by text: [arsd.color|my color module] gives my color module.

Local sections can be referenced with [#cross-referencing]: cross referencing.

Markdown-style [text](url) links are also supported. There must be no space between the ] and ( and it must all appear on the same line. My link here. Markdown-style links do not attempt name lookups like adrdox native [links].

User-defined attribues

If you want a UDA to document its uses, you can add the magic macro $(UDA_USES) to it somewhere. This will list links to each symbol possessing the uda.

/++
	This is used on:

	$(UDA_USES)
+/
enum MyUDA;

@MyUDA void foo() {}

Paragraph detection

The generator will automatically handle paragraph tags by looking for blank lines and other separators. Just write and trust it to do the right thing. (If it doesn't, email me a bug report, please.)

Images

You can post images with $(IMG source_url, alt text). The default CSS will put some reasonable size limits and margin on it.

The image will typically be hosted elsewhere, IMG simply takes a URL (though it can be a data url, you need to manage that yourself too).

FIXME: implement and document $(LEFT ), $(RIGHT ), and $(CENTERED ).

You may also use inline $(SVG ) or $(RAW_HTML). FIXME

Markdown-style ![alt text](url) images are also supported, iff there are no spaces between the symbols and all appear on the same line. d logo.

Note that if the parens are not there, it is normal![1] (code there: normal![1])

Headers

You can use ddoc-style macros for headers: $(H1 Name of header), $(H2 Subheader), and so on through $(H6). Linking will be added automatically by the generator.

Custom ddoc sections (see below) are translated into <h3> headers.

You can also use a markdown style ==== under a line to trigger a header. These will render as <h3> if at top level, and <h4> if under a custom ddoc section (FIXME: that details is not yet implemented). For this to work:

  • The header must be preceded by a blank line
  • The ==== must be directly below the header
  • The ==== must be followed by a blank line
  • There must be at least 4 = on the line, and no other text (excluding whitespace).

This is some text preceding the header.

This is the header
==================

This is a paragraph under that header.

This is some text preceding the header.

This is the header

This is a paragraph under that header.

Moreover, markdown style ## Header are also supported. The number of # characters indicate the header level (1-6). Similar restrictions apply:

  • The header must be preceded by and followed by a blank line
  • The # must be the first non-whitespace character on the line
  • There must be a space following the # characters.

# H1

## H2

### H3

#not a header, missing space

a # is not a header

Nor is the following a header
# because it is not preceded by a blank line

H1

H2

H3

#not a header, missing space

a # is not a header

Nor is the following a header # because it is not preceded by a blank line

Ddoc sections

Most the Ddoc sections are supported too, and should be used where appropriate to document your code. I also added one called diagnostics:, where you can list common compile errors seen with the function.

Examples: (or Example:) is special in that documented unit tests are appended here.

You may define custom ddoc sections as long as they are all one word and includes at least one underscore in the name. They will be translated to H3 headers, since they typically go under the Detailed Description H2-level header.

Be sure to correctly nest headers - put H3 under H2, and H4 under H3, etc. Failure to do so may break your table of contents.

	$(H2 A header)
		Some content
	$(H3 Another header)
		Some more content

$(H3 	A Ddoc Style Header)


		And some content

A header

Some content

Another header

Some more content

A Ddoc Style Header

And some content

Content blocks

There are a few content blocks to add boxes to your documentation: $(TIP), $(NOTE), $(WARNING), $(PITFALL), and $(SIDEBAR). Inside these, you may write any content.

Use these boxes to make certain content stand out so the reader pays attention to something special (or, in the case of SIDEBAR, get out of the way so the reader can skip it). The intended semantics are:

$(TIP) is a cool fact to help you make the most of the code.

$(NOTE) is something the reader should be aware of, but they can get it wrong without major consequence.

$(WARNING) is something they need to watch out for, such as potential crashes or memory leaks when using the function.

$(PITFALL) is something that users very commonly get wrong and you want them to see it to avoid making the same mistake yet again.

$(SIDEBAR) will be typically displayed outside the flow of the text. It should be used when you want to expand on some details, but it isn't something the user strictly needs to know.

Fancier Formatting

There are several magic macros that use domain-specific syntaxes for common formatting tasks, like lists and tables. The ddoc-style macro brackets the text, which is laid out in a particular way to make writing, reading, and editing the data most easy.

Blockquotes

Use the $(BLOCKQUOTE) macro to surround the quote. It will render as you expected.

$(BLOCKQUOTE
	This is a quote! You can write whatever you want in here.

	Including paragraphs, and other content. Unlike markdown, you
	do not need to write `>` or spaces or anything else before every
	line, instead you just wrap the whole thing in `$(BLOCKQUOTE)`.

	If it has unbalanced parenthesis, you can use `$(LPAREN)` or `$(RPAREN)`
	for them.
)
This is a quote! You can write whatever you want in here.

Including paragraphs, and other content. Unlike markdown, you do not need to write > or spaces or anything else before every line, instead you just wrap the whole thing in $(BLOCKQUOTE).

If it has unbalanced parenthesis, you can use $(LPAREN) or $(RPAREN) for them.

Lists

There are two types of list: $(LIST) and $(NUMBERED_LIST). Both work the same way. The only difference is $(LIST) generates a <ul> tag, while $(NUMBERED_LIST) generates a <ol> tag.

Inside the magic list macros, a * character at the beginning of a line will create a new list item.

Make sure the leading * does not line up with your comment marker, or the preprocessor may strip it thinking it is a comment in the style of:
/**
  * one of these
  */

Since the preprocessor runs before analyzing brackets, it won't know that the star was intentional.

I recommend indenting your list stars by at least 4 spaces or one tab for best results.

$(LIST
	* List item
	* Another list item
)

$(NUMBERED_LIST
	* One
	* Two
	* Three
)
  • List item
  • Another list item
  1. One
  2. Two
  3. Three

Text inside the list items is processed normally. You may nest lists, have paragraphs inside them, or anything else.

You can add a class name to the list element in the HTML by using the $(CLASS) magic macro before opening your first list item. Use this class, along with CSS, to apply custom style to the list and its items.

You may also use $(RAW_HTML) for full control of the output, or legacy Ddoc style $(UL $(LI ...)) macros to form lists as well.

Tables

I support two table syntaxes: list tables (by row and by column, inspired by reStructuredText) and compact tables, with optional ASCII art (inspired by Markdown).

Compact Tables

A compact table consists of an optional one-line caption, a one-line header row, and any number of one-line data rows.

Cells are separated with the | character. Empty cells at the beginning or end of the table are ignored, allowing you to draw an ASCII art border around the table if you like.

The first row is always considered the header row. Columns without header text are also considered header columns.

The minimal syntax to define a table is:

$(SMALL_TABLE
	Basic table caption (this line is optional)
	header 1|header 2
	data 1|data 2
	more data | more data
)
Basic table caption (this line is optional)
header 1header 2
data 1data 2
more datamore data
Since the ddoc-style macro bracketing the table must have balanced parenthesis, any unbalanced parenthesis character inside should be put inside a `code block`. You can also put pipe characters inside code blocks:
$(SMALL_TABLE
	h1|h2
	`d1|with pipe`|d2
)
h1h2
d1|with piped2

ASCII art inside the compact table is allowed, but not required. Any line that consists only of the characters +-=| is assumed to be decorative and ignored by the parser. Empty lines are also ignored. White space around your cells are also ignored.

The result is you can style it how you like. The following code will render the same way as the above table:

$(SMALL_TABLE
	Basic table caption (this line is optional)
	+-----------+-----------+
	| header 1  | header 2  |
	+===========+===========+
	| data 1    | data 2    |
	| more data | more data |
	+-----------+-----------+
)
Basic table caption (this line is optional)
header 1header 2
data 1data 2
more datamore data
Two-dimensional tabular data

If a table has an empty upper-left cell, it is assumed to have two axes. Cells under the column with the empty header are also rendered as headers.

Here is a two-dimensional table with and without the optional ascii art.

$(SMALL_TABLE

	XOR Truth Table
	+-----------+
	|   | 0 | 1 |
	+===|===|===+
	| 0 | F | T |
	| 1 | T | F |
	+-----------+
)

$(SMALL_TABLE
	Alternative XOR
	||0|1
	0|F|T
	1|T|F
)
XOR Truth Table
01
0FT
1TF
Alternative XOR
01
0FT
1TF

Notice that even without the ascii art, the outer pipe is necessary to indicate that an empty cell was intended in the upper left corner.

If you want to make a feature table, you can do it as a compact table with any entry for yes, and no data for no.
$(SMALL_TABLE
	Features
	|| x | y
	a| * |
	b|   | *
	c| * | *
)
Features
xy
a*
b*
c**

You can then style these with CSS rules like td:empty in lieu of adding a class to each element. The empty cell on the right did not require an extra | because all data rows are assumed to have equal number of cells as the header row.

Longer tables

I also support a list table format, inspired by restructuredText.

$(TABLE_ROWS
	Caption
	* + Header 1
	  + Header 2
	* - Data 1
	  - Data 2
	* - Data 1
	  - Data 2
)
Caption
Header 1Header 2
Data 1Data 2
Data 1Data 2

In this format, the text before any * is the caption. Then, a leading * indicates a new row, a leading + starts a new table header, and a leading - starts a new table cell. The cells can be as long as you like.

adrdox will also detect if you put a header on the left side of later rows, and format the table accordingly:

$(TABLE_ROWS
	Caption
	* + Header 1
	  + Header 2
	  + Header 3
	* + 2D Header
	  - Data 1.2
	  - Data 1.3
	* + Again
	  - Data 1.2
	  - Data 2.3
)
Caption
Header 1Header 2Header 3
2D HeaderData 1.2Data 1.3
AgainData 1.2Data 2.3

Formatting tables

To format tables, including aligning text inside a column, add a class name to the tag using the magic $(CLASS name) macro right inside the table backeting, then target that with CSS rules in your stylesheet.

$(RAW_HTML
	<style>
	.my-yellow-table {
		background-color: yellow;
	}
	</style>
)
$(TABLE_ROWS
	$(CLASS my-yellow-table)
	Caption
	* + Header 1
	  + Header 2
	* - Data 1
	  - Data 2
	* - Data 1
	  - Data 2
)

Caption
Header 1Header 2
Data 1Data 2
Data 1Data 2

More advanced tables

To avoid complicating the syntax in more common cases, I do not attempt to support everything possible. Notably, most cases of colspan and rowspan cannot be expressed in any of my syntaxes.

If you need something, and all else fails, you can always use the $(RAW_HTML) escape hatch and write the code yourself.

Mathematics

The doc generator can also render LaTeX formulas, if latex and dvipng is installed on your system.

$(MATH \int_{1}^{\pi} \cos(x) dx )

\int_{1}^{\pi} \cos(x) dx

Note that generating these images is kinda slow. You must balance parenthesis inside the macro, and all the output images will be rendered inline, packed in the html file.

If you can use a plain text or html character btw, you should. Don't break out MATH just for an $(INF) symbol, for example.

Ddoc Macro to HTML Tag reference

  • $(IMG source_url, alt text)
  • $(B bold text)
  • $(I italic text)
  • $(U underlined text)
  • $(SUPERSCRIPT superscript text)
  • $(SUB subscript text)

Adding ID and class attributes to HTML

You can add an ID or class attribute to an HTML tag by putting $(ID id_here) or $(CLASS class_here) inside a ddoc macro. It must be inside a $(ddoc_style) macro to be recognized.

Ddoc Sections

List of supported DDoc Sections

  • Examples: or Example: gives usage examples. Documented unittests, if present and not embedded (see documented unittests), will also appear here.
  • Bugs:
  • See_Also:
  • Returns:
  • Throws:
  • Deprecated:
  • Params: uses a special name = comment syntax, just like ddoc, where only param names detected are printed.
  • Macros: are read, but ignored.

Meta subsections

The following sections, if present, will be grouped under the Meta header:

  • Authors: or Author:
  • Date
  • License:
  • Source:
  • History:
  • Credits:
  • Standards:
  • Copyright:
  • Version:

Adrdox extension sections

  • Diagnostics: is a place to describe common errors you will see while trying to use the function, and explain how to fix them.
  • Link_References: does name=value. See footnotes.

Custom sections

If you start a line with some_section:, it will become a custom section in the document. It must have at least one underscore to be recognizes as a custom section.

Footnotes

adrdox supports footnotes[1] and popup notes[2], scoped to the declaration attached to the comment. The syntax is to simply write [n], such as [1], where you want it to be displayed, then later in the comment, write a Link_References: section at the end of your comment, like so:

Link_References:
	1 = https://en.wikipedia.org/wiki/Footnote
	2 = This note will popup inline.

Undefined footnote references output the plain text without modification, like [3]. Numeric footnotes can only be used locally, they must be used and defined inside the same comment.

Text references must always be contained to a single line in the current implementation.

If you need something more complex than a single link or line of text, write a section for your notes inside your comment and use the [n] Link_References to link to it:

/++
	This huge complex function needs a complex footnote[1].

	$(H2 Footnotes)

	$(DIV $(ID note-1)
		This can be arbitrarily complex.
	)

	Link_References:
		1 = [a_huge_complex_function#note-1]
+/
void a_huge_complex_function() {}

See that live here.

You can also do custom links, images, or popup text via the shortcut [reference] syntax. You can define them with a symbol name in the Link_References section:

Link_References:
	dlang = http://dlang.org/
	dlogo = $(IMG /d-logo.png, The D Logo)
	dmotto = Modern convenience. Modeling power. Native efficiency.

You can now reference those with [dlang], [dlogo], and [dmotto], which will render thusly: dlang, The D Logo, dmotto. Be aware that ONLY a single line of plain text, a single $(IMG), or a single link (url or convenience reference, see below) are allowed in the Link_References section.

Link references will override D name lookup. Be aware of name clashes that might break convenient access to in-scope symbol names.

Like with other convenience links, you can change the displayed text by using a pipe character, like [dlang|The D Website]. It will continue to link to the same place or pop up the same text. If the name references an image, the text after the pipe will locally change the alt text on the image tag.

Additionally, the pipe character can be used in the reference definition to change the default display text:

Link_References:
	input_range = [std.range.primitives.isInputRange|input range]

will always show "input range" when you write [input_range], but can still be overridden by local text after the pipe, like [input_range|an input range]. Those will render: input range and an input range.

Yes, you can define link references in terms of a D reference. It will look up the name using the normal scoping rules for the attached declaration.
If you use a reference in a global reference definition, it will look up the name in the scope at the *usage point*. This may change in the future.

Unrecognized refs are forwarded to regular lookups.

While numeric link references are strictly scoped to the declaration of the attached comment, text link references are inherited by child declarations. Thus, you can define shortcuts at module scope and use them throughout the module. You can even define one in a package and use it throughout the package, without explicitly importing the package.d inside the module. Link references, however, are not imported like normal D symbols. They follow a strict parent->child inheritance.

If you need a link reference to be used over and over across packages, you may also define global link references in a text file you pass to adrdox with the --link-references option. The format of this text file is as follows:

name = value
othername = other value

Yes, the same as the Link_References: section inside a comment, but with no surrounding decoration.

Be especially careful when defining global textual link macros, because they will override normal name lookups when doing [convenient] cross references across the entire current documentation build set.

You may want to give unique, yet convenient names to common concepts used throughout your library and define them as Link_References for easy use.

Side-by-side comparisons

You might want to show two things side by side to emphasize how the user's existing knowledge can be shared. You can do that with the $(SIDE_BY_SIDE $(COLUMN)) syntax:

$(SIDE_BY_SIDE
	$(COLUMN
		```php
		<?php
			$foo = $_POST["foo"];
		?>
		```
	)
	$(COLUMN
		---
		import arsd.cgi;
		string foo = cgi.post["foo"];
		---
	)
)
<?php
	$foo = $_POST["foo"];
?>
import arsd.cgi;
string foo = cgi.post["foo"];

Try to keep your columns as narrow as reasonable, so they can actually be read side-by-side!

Commenting stuff out in comments

The macro $(COMMENT ...) is removed from the generated document. You can use it to comment stuff out of your comment. Of course, you can also just use regular /* comments instead of /**.

Always Documenting Something

If you want something to always be documented, even if it is private, add $(ALWAYS_DOCUMENT) to its comment somewhere.

Documentable Constructs

adrdox allows documenting more language constructs than ddoc. It lets you document public imports, postblits, destructors, anonymous enums, and more. Try putting a doc comment on almost anything and see what happens!

Suggestion Box / Bug Report