asciidoc-parser 0.19.0

Parser for AsciiDoc format
Documentation
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
75
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
use crate::tests::prelude::*;

track_file!("ref/asciidoc-lang/docs/modules/macros/pages/links.adoc");

non_normative!(
    r#"
= Links
:url-url-def: https://en.wikipedia.org/wiki/URL

AsciiDoc offers a variety of ways of creating links (aka hyperlinks) to other addressable resources.
The pages in this section document how to add and customize links in AsciiDoc.

== URLs and links

The [.term]*target* of a link is a {url-url-def}[Uniform Resource Locator^] (URL), otherwise known as a web address.
The text the reader clicks to navigate to that target is referred to as the [.term]*link text*.

NOTE: You may sometimes see the term URI used in place of a URL.
Although the URI is more technically correct in some cases, URL is the accepted term.

The URL is the web address of a unique resource.
A URL can either be absolute or relative.
An absolute URL consists of a scheme, an authority (i.e., domain name), a path with an optional file extension, and metadata in the form of a query string and fragment (e.g., `\https://example.org/asciidoc/links.html?source=home`).
You may recognize an absolute URL as what you type in the location bar of a web browser, such as the one for this page.
A relative URL is the portion of an absolute URL that starts after either the root path or a subpath (e.g., `guides/getting-started.html`).

Since an absolute URL has a distinct, recognizable syntax, an AsciiDoc processor will detect URLs (unless escaped) and automatically convert them to links wherever the macros substitution step is applied.
This also works for bare email addresses.
You can learn more about this behavior in xref:autolinks.adoc[].
To make a link to a relative URL, you must be specify it explicitly as the target of a xref:link-macro.adoc[link macro].

== Link-related macros

Instead of showing the bare URL or email address as the link text, you may want to customize that text.
Or perhaps you want to apply attributes to the link, such as a role.
To do so, you'd use either the xref:url-macro.adoc[URL macro] or, if you're linking to xref:complex-urls.adoc[a complex URL], the more decisive xref:link-macro.adoc[link macro].
(You can also use the xref:link-macro.adoc[link macro] to make a link to an addressable resource using a relative URL or a URL that is not otherwise recognized as an absolute URL).

When linking to an email address, you can use the specialized xref:mailto-macro.adoc[mailto macro] to enhance the link with prepopulated subject and body text.

"#
);

mod encode_reserved_characters {
    use crate::tests::prelude::*;

    non_normative!(
        r#"
== Encode reserved characters

If the URL contains reserved characters, such as double quote (`"`), space, or an unconstrained AsciiDoc formatting mark, you'll need to encode these characters using URI encoding.
For example, a double quote is encoded as `%22`.
An underscore is encoded as `%5F`.
If you do not encode these characters, the URL may be mangled or cause the processor to fail.

"#
    );

    #[test]
    fn example() {
        verifies!(
            r#"
Let's assume we are creating a URL that contains a query string parameter named `q` that contains reserved characters:

....
https://example.org?q=label:"Requires docs"
....

To encode a URL, open the development tools in your browser and pass the URL to the `encodeURI` function:

[,js]
----
encodeURI('http://example.org?q=label:"Requires docs"')
----

Here's the encoded URL that we'd use in the AsciiDoc document:

....
https://example.org?q=label:%22Requires%20docs%22
....

Depending on the capabilities of the web application, the space character can be encoded as `+` instead of `%20`.

"#
        );

        let doc = Parser::default().parse("https://example.org?q=label:%22Requires%20docs%22");

        assert_eq!(
            doc,
            Document {
                header: Header {
                    title_source: None,
                    title: None,
                    attributes: &[],
                    author_line: None,
                    revision_line: None,
                    comments: &[],
                    source: Span {
                        data: "",
                        line: 1,
                        col: 1,
                        offset: 0,
                    },
                },
                blocks: &[Block::Simple(SimpleBlock {
                    content: Content {
                        original: Span {
                            data: "https://example.org?q=label:%22Requires%20docs%22",
                            line: 1,
                            col: 1,
                            offset: 0,
                        },
                        rendered: "<a href=\"https://example.org?q=label:%22Requires%20docs%22\" class=\"bare\">https://example.org?q=label:%22Requires%20docs%22</a>",
                    },
                    source: Span {
                        data: "https://example.org?q=label:%22Requires%20docs%22",
                        line: 1,
                        col: 1,
                        offset: 0,
                    },
                    style: SimpleBlockStyle::Paragraph,
                    title_source: None,
                    title: None,
                    caption: None,
                    number: None,
                    anchor: None,
                    anchor_reftext: None,
                    attrlist: None,
                },),],
                source: Span {
                    data: "https://example.org?q=label:%22Requires%20docs%22",
                    line: 1,
                    col: 1,
                    offset: 0,
                },
                warnings: &[],
                source_map: SourceMap(&[]),
                catalog: Catalog::default(),
            }
        );
    }
}

mod hide_uri_scheme {
    use crate::tests::prelude::*;

    non_normative!(
        r#"
[#hide-uri-scheme]
== Hide the URL scheme

If the link text is a bare URL (aka URI), whether that link was created automatically or using a link-related macro, you can configure the AsciiDoc processor to hide the scheme (e.g., _https://_).
Hiding the scheme can make the URL more readable--perhaps even recognizable--to a person less familiar with technical nomenclature.

"#
    );

    #[test]
    fn example() {
        verifies!(
            r#"
To configure the AsciiDoc processor to display the linked URL without the scheme part, set the `hide-uri-scheme` attribute in the header of the AsciiDoc document.

[source]
----
= Document Title
:hide-uri-scheme: <.>

https://asciidoctor.org
----
<.> Note the use of `uri` instead of `url` in the attribute name.

When the `hide-uri-scheme` attribute is set, the above URL will be displayed to the reader as follows:

====
https://asciidoctor.org[asciidoctor.org]
====

Note the absence of _https://_ in the URL.
The prefix will still be present in the link target.

"#
        );

        let doc = Parser::default()
            .parse("= Document Title\n:hide-uri-scheme:\n\nhttps://asciidoctor.org");

        assert_eq!(
            doc,
            Document {
                header: Header {
                    title_source: Some(Span {
                        data: "Document Title",
                        line: 1,
                        col: 3,
                        offset: 2,
                    },),
                    title: Some("Document Title",),
                    attributes: &[Attribute {
                        name: Span {
                            data: "hide-uri-scheme",
                            line: 2,
                            col: 2,
                            offset: 18,
                        },
                        value_source: None,
                        value: InterpretedValue::Set,
                        source: Span {
                            data: ":hide-uri-scheme:",
                            line: 2,
                            col: 1,
                            offset: 17,
                        },
                    },],
                    author_line: None,
                    revision_line: None,
                    comments: &[],
                    source: Span {
                        data: "= Document Title\n:hide-uri-scheme:",
                        line: 1,
                        col: 1,
                        offset: 0,
                    },
                },
                blocks: &[Block::Simple(SimpleBlock {
                    content: Content {
                        original: Span {
                            data: "https://asciidoctor.org",
                            line: 4,
                            col: 1,
                            offset: 36,
                        },
                        rendered: r#"<a href="https://asciidoctor.org" class="bare">asciidoctor.org</a>"#,
                        // Expected output verified by running Asciidoc locally.
                    },
                    source: Span {
                        data: "https://asciidoctor.org",
                        line: 4,
                        col: 1,
                        offset: 36,
                    },
                    style: SimpleBlockStyle::Paragraph,
                    title_source: None,
                    title: None,
                    caption: None,
                    number: None,
                    anchor: None,
                    anchor_reftext: None,
                    attrlist: None,
                },),],
                source: Span {
                    data: "= Document Title\n:hide-uri-scheme:\n\nhttps://asciidoctor.org",
                    line: 1,
                    col: 1,
                    offset: 0,
                },
                warnings: &[],
                source_map: SourceMap(&[]),
                catalog: Catalog::default(),
            }
        );
    }
}

non_normative!(
    r#"
////
= URLs and Links

A Uniform Resource Link (URL) represents the location of a resource on the web.
Typical URLs contain a scheme, domain name, file name, and extension.

#move image#
//image::url.png[]

// tag::basic[]
AsciiDoc recognizes the following common schemes without the help of any markup.

[#schemes]
* http
* https
* ftp
* irc
* mailto
* \email@email.com

You can think of these schemas as implicit macro names (with the exception of a bare email address).
Since the URL in the example below begins with a protocol (in this case _https_ followed by a colon), the AsciiDoc processor will automatically turn it into a hyperlink.
We call this a URL macro.

[source]
----
include::example$url.adoc[tag=base-co]
----
<.> The trailing period will not get caught up in the link.

To prevent automatic linking of an URL, prepend it with a backslash (`\`).

[source]
----
Once launched, the site will be available at \https://example.org.
----

== Link text

To attach a URL to text, enclose the text in square brackets at the end of the URL, thus making it a URL macro.

[source]
----
include::example$url.adoc[tag=irc]
----
// end::basic[]

Additionally, you can format the link text.

[source]
----
include::example$url.adoc[tag=text]
----

.Rendered URLs
====
include::example$url.adoc[tag=base]
====

You may also want to append empty square brackets to force the URL to be parsed when it would not normally be recognized, such as if it's enclosed in double quotes:

[source]
----
Type "https://asciidoctor.org[]" into the location bar of your browser.
----

== The link macro

// tag::link[]
When a URL does not start with one of the <<schemes,common schemes>>, or the URL is not surrounded by word boundaries, you must use the `link` macro.
The `link` macro is a stronger version of a URI macro, which you can think of like an unconstrained macro.
The URL is preceded by `link:` and followed by square brackets.
The square brackets may include optional link text.
The URL is used for the text of the link if link text is not specified.
Attributes inside the square brackets are parsed automatically if an equal sign is found after a comma (e.g., `[link text,window=_blank]`).

.Anatomy of a link macro
[source]
----
link:url[optional link text, optional target attribute, optional role attribute]
----

Let's consider a case where we need to use the link macro (instead of just a URI macro) to expand a link when it's not adjacent to a word boundary (i.e., unconstrained).

[source]
----
include::example$url.adoc[tag=unconstrained]
----

====
include::example$url.adoc[tag=unconstrained]
====

If we didn't use the `link:` prefix in this case, the URL macro would not be detected by the parser.
// end::link[]

[#complex-urls]
.Troubleshooting Complex URLs
****
A URL may not display correctly when it contains characters such as underscores (`+_+`) or carets (`+^`).
include::partial$ts-url-format.adoc[tag=sb]
****

Next, we'll add a target and role to a link macro.

// tag::attr[]
[#link-macro-attributes]
=== Link macro attributes

AsciiDoc didn't used to recognize attributes in the link macro by default.
This is no longer the case.
The AsciiDoc processor automatically parses attributes in the link macro, but only under certain contains (introduced in Asciidoctor 1.5.7).
If the AsciiDoc processor detects an equal sign after the first comma, it must parse the attributes in the link macro.
For example, when attribute parsing is enabled, you can specify the name of the target window using the `window` attribute.

[source]
----
include::example$url.adoc[tag=linkattrs-h]
----

====
include::example$url.adoc[tag=linkattrs]
====

Since `_blank` is the most common window name, we've introduced shorthand for it.
Just end the link text with a caret (`+^+`):

[source]
----
include::example$url.adoc[tag=linkattrs-s]
----

CAUTION: If you use the caret syntax more than once in a single paragraph, you may need to escape the first occurrence with a backslash.

You can also add a role (i.e., CSS class) to the link using an attribute declaration (which implicitly enables attribute parsing).

[source]
----
include::example$url.adoc[tag=css]
----

====
include::example$url.adoc[tag=css]
====

TIP: Links with attributes (including the subject and body segments on mailto links) weren't always supported in AsciiDoc.
Now that they are, you must surround the link text in double quotes if it contains a comma.
// end::attr[]
////
"#
);