include.adoc 6.78 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
= Includes
// Include Directive Syntax and Processing
// Include Directive Concepts and Syntax

You can include content from another file into the current AsciiDoc document using the include directive.
The included content can be AsciiDoc or it can be any other text format.
Where that content is included in the document determines how it will be processed.

== What is an include directive?

An [.term]*include directive* imports content from an external file into the content of the current document.
When the current document is processed, the include directive syntax is replaced by the contents of the include file.
Think of the include directive like a file expander.
The include directive is a <<include-processing,preprocessor directive>>, so it has no awareness of the surrounding context.

== When is an include directive useful?

The include directive is useful when you want to:

* Partition a large document into smaller files for better organization and to make restructuring simpler.
//** always separate consecutive include directives by a blank line unless your intent is for the included lines to run together
* Insert source code from the external files where the code is maintained.
* Populate tables with output, such as CSV data, from other programs.
* Create document variants by combining the include directive with xref:conditionals.adoc[conditional preprocessor directives].
* Reuse content snippets and boilerplate content, such as term definitions, disclaimers, etc., multiple times within the same document.

[#include-syntax]
== Include directive syntax

An include directive must be placed on a line by itself with the following syntax:

[source,subs=+quotes]
----
\include::path[leveloffset=__offset__,lines=__ranges__,tag(s)=__name(s)__,indent=__depth__,opts=optional]
----

The leveloffset, lines, tag(s), indent, and opts attributes are optional, making the simplest case look like:

[source]
----
\include::content.adoc[]
----

[#include-processing]
== Include processing

Although the include directive looks like a block macro, *it's not a macro and therefore isn't processed like one*.
It's a preprocessor directive; it's important to understand the distinction.

include::partial$preprocessor.adoc[]
The include directive is a preprocessor directive that always adds lines.

The best way to think of the include directive is to imagine that it is being replaced by the lines from the include file (i.e., the imported lines).
Only after the lines from the target of the include directive are added to the current document does the parser read and interpret those lines.

IMPORTANT: The include directive is disabled when Asciidoctor is run in secure mode.
In secure mode, the include directive is converted to a link in the output document.
See xref:asciidoctor::safe-modes.adoc[] to learn more.

== Escaping an include directive

If you don't want the include directive to be processed, you must escape it using a backslash.

----
\include::just-an-example.ext[]
----

Escaping the directive is necessary _even if it appears in a verbatim block_ since it's not aware of the surrounding document structure.

[#include-resolution]
== Include file resolution

The path used in an include directive can be relative or absolute.

Dan Allen's avatar
Dan Allen committed
75
If the path is relative, the processor resolves the path using the following rules:
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

* If the include directive is used in the main (top-level) document, relative paths are resolved relative to the base directory.
(The base directory defaults to the directory of the main document and can be overridden from the CLI or API).
* If the include directive is used in a file that has itself been included, the path is resolved relative to the including (i.e., current) file.

//TODO show examples to contrast a relative vs an absolute include

These defaults make it easy to reason about how the path to the include file is resolved.

If the processor cannot locate the file (perhaps because you mistyped the path), you'll still be able to convert the document.
However, you'll get the following warning message during conversion:

 asciidoctor: WARNING: my-document.adoc: line 3: include file not found: /.../content.adoc

The following message will also be inserted into the output:

 Unresolved directive in my-document.adoc - include::content.adoc[]

To fix the problem, edit the file path and run the converter again.
If you don't want Asciidoctor to trigger a warning, and instead drop the include that cannot be found, add the `opts=optional` attribute to the include directive.

If you store your AsciiDoc files in nested folders at different levels, relative file paths can quickly become awkward and inflexible.
A common pattern to help here is to define the paths in attributes defined in the header, then prefix all include paths with a reference to one of these attributes:

[source]
------
:includedir: _includes
:sourcedir: ../src/main/java

\include::{includedir}/fragment1.adoc[]

[source,java]
----
\include::{sourcedir}/org/asciidoctor/Asciidoctor.java[]
----
------

Keep in mind that no matter how Asciidoctor resolves the path to the file, access to that file is limited by the safe mode setting under which Asciidoctor is run.
If a path violates the security restrictions, it may be truncated.

[#include-nonasciidoc]
== AsciiDoc vs non-AsciiDoc files

The include directive performs a simple file merge, so it works with any text file.
// NOTE this point about normalization should probably be moved to an earlier section
The content of all included content is normalized.
This means that the encoding is forced to UTF-8 (or converted from UTF-16 to UTF-8 if the file contains a BOM) and trailing whitespace and endlines are removed from each line and replaced with a Unix line feed.
This normalization is important to how Asciidoctor works.

If the file is recognized as an AsciiDoc file (i.e., it has one of the following extensions: `.asciidoc`, `.adoc`, `.ad`, `.asc`, or `.txt`), Asciidoctor runs the preprocessor on the lines, looking for and interpreting the following directives:

* includes
* preprocessor conditionals (e.g., `ifdef`)
//* front matter (if enabled)

This allows includes to be nested, and provides lot of flexibility in constructing radically different documents with a single master document and a few command line attributes.

Including non-AsciiDoc files is normally done to merge output from other programs or populate table data:

[source]
----
.2016 Sales Results
,===
\include::sales/2016/results.csv[]
,===
----

In this case, the include directive does not do any processing of AsciiDoc directives.
The content is inserted as is (after being normalized).

////
CAUTION: You *can* put AsciiDoc content in a non-AsciiDoc file.
Its content will still be processed as AsciiDoc, but any include statements will be ignored, and therefore cause errors later in processing.
It is likely to cause confusion, so best avoided.
////