整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

AsciiDoc 的相关整理

. AsciiDoc 简介

  • AsciiDoc 是一种文本文档格式(轻量级的标记语言),用于编写注释、文档、文章、书籍、电子书、幻灯片、网页、手册页和博客。
  • AsciiDoc 文件可以翻译成多种格式,包括 HTML、PDF、EPUB、手册页面等。
  • AsciiDoc 是高度可配置的,用户可以定制和扩展 AsciiDoc 源文件语法和后端输出标记(几乎可以是任何类型的 SGML/XML 标记)。
  • AsciiDoc 是免费软件,并根据 GNU 通用公共许可证版本 2(GPLV2)的条款进行许可。

1.1 语法

1.1.1 文档头

  • 可以包含文档头、作者、修订行、自定义属性等。
  • 头部可选但是必须在文档的顶部。
= My Document's Title
Doc Writer <doc.writer@asciidoctor.org>
v1.0, 2018-04-11
:toc:
:imagesdir: assets/images
:homepage: https://asciidoctor.org
My document provides...

1.1.2 标题

  • 需要靠左侧顶格。
  • 可以包含文档头、第 1 ~ 第 5 章节标题。
  • 当使用项目文档类型(默认值)时,只能有一个 0 级的节标题(即,文档标题),并且它必须位于文档头中。
  • 等号的数目与 HTML 输出中的标题级别相匹配。
  • 例如,(=)转换成为 <h2> 标签。
= 文档标题 (0级) =
== 段落标题 (1级) ==
=== 段落标题 (2级) ===
==== 段落标题 (3级) ====
===== 段落标题 (4级) =====

1.1.3 段落

  • 段落不需要任何特殊的标记,段落只需要是连续文本的一行或多行。
  • 开始新的段落需要用一个空行进行分隔。
  • 文档中的大部分内容是段落文本,因此 AsciiDoc 不需要任何特殊的标记或属性来指定段落内容。
Paragraphs don’t require any special markup in AsciiDoc. A paragraph is just one or more lines of consecutive text.
To begin a new paragraph, separate it by at least one blank line. Newlines within a paragraph are not displayed.

1.1.3.1 换行

  • 在 AsciiDoc 中,相邻或连续的文本行形成段落元素。若要在另一个元素(如节标题或表)之后开始新的段落,则插入空行,然后继续键入内容即可。
  • 因为 AsciiDoc 转换文档时,相邻的文本行会被合并为单个段落,这意味着可以包装段落文本或将每个句子或短语放在单独的行上,输出中是不会出现换行的。
  • 如果希望保留段落中的换行符,可以使用加号 (+) 后的空格或 hardbreaks 属性。这样会导致每一行之后增加可见的换行标记(例如 <BR>)。
Rubies are red, +
Topazes are blue.
[%hardbreaks]
Ruby is red.
Java is black.
  • 通过将 hardbreaks 属性添加到文档头部,可以在整个文档中保留换行符。
:hardbreaks:
......
Rubies are red,
Topazes are blue.

1.1.3.2 文字段落

  • 由至少一个空间偏移的段落成为文字段落,文字段落中的所有行必须是相邻的。
  • 文本段落显示为预格式化文本,文本以固定宽度字体显示,空格和换行符都会被保留下来。

1.1.3.3 提示段落

  • 主要是为了引起读者注意,用标签开头。
  • 标签必须大写,后面跟着冒号(:)。

标签说明 NOTE 注释,TIP 提示,WARNING 警告,IMPORTANT 重要,CAUTION 注意。

TIP: Pro tip...
IMPORTANT: Don't forget...
WARNING: Watch out for...
CAUTION: Ensure that...
  • 当想对复杂内容应用警告时,可以将标签设置为块上的样式属性。
  • 下例是在分隔块上的属性列表中设置标签,标签必须大写。
[IMPORTANT] 
.Feeding the Werewolves
==== 
While werewolves are hardy community members, keep in mind the following dietary concerns:
. They are allergic to cinnamon.
. More than two glasses of orange juice in 24 hours makes them howl in harmony with alarms and sirens.
. Celery makes them sad.
====
  • 可以使用 icons 参数制定图标的路径。
[icons="./images/icons/wink.png"]
NOTE: What lovely war.
  • 使用 caption 参数定义警告标题返回的文本信息(在警告图标设置为可用时 icons 参数必须设置为 icons=None)。
[icons=None, caption="特殊提示"]
NOTE: This is my special note.
1.1.3.3.1 图标
  • AsciiDoc 提供三种显示图标的策略。
  • 作为文本
  • 作为图像
  • 作为从图标字体中选择的字符。
  • 使用图标属性控制策略。默认行显示返回的文本。
  • 如果希望使用图像显示图标,可以在文档头中将图标属性设置为空值。如果正在转换为 DocBook,或者希望使用一种简单的方法使 HTML 可以脱机查看,则建议采用此策略。DocBook 工具链提供了警告和标注等图标的图像,这些图标可以用自己的自定义图标替换。如果使用内联图标宏,则需要为这些图标提供图像。
  • 也可以使用字体图标设置为 AsciiDoc 图标,若要使用此特性,需要将图标文件属性的值设置为文档标题中的字体。可以从 Awesome 中获得更多的字体图标。这种方式默认情况下需要在线访问。
= Document Title
:icons: font
......
NOTE: Asciidoctor supports font-based admonition icons, powered by Font Awesome!
  • HTML 格式输出。
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Asciidoctor supports font-based admonition icons, powered by Font Awesome!
</td>
</tr>
</table>
</div>
  • AsciiDoc 中添加了 Awesome 的字体超强样式表和字体文件的引用。
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/3.1.0/css/font-awesome.min.css">
1.1.3.3.2 Unicode 文本图标
  • 代替图像或基于字体的图标,可以通过使用一个小技巧使用 Unicode 文本来表示警告图标。
  • 如果在文档上没有设置图标属性,AsciiDoc 输出一个标识警告类型的文本标签。此标签的文本来自 AsciiDoc 属性。
  • 属性的名称是 <类型> 标题,其中 <类型> 是小写中的警告类型。例如,提示提示的属性是提示字幕。
  • 可以将一个 Unicode 字形赋值给这个属性,而不是单词。
:tip-caption: 
[TIP]
It's possible to use Unicode glyphs as admonition icons.
  • HTML 格式输出。
<td class="icon">
<div class="title"></div>
</td>
1.1.3.3.3 内联图标
  • 图标可以插入到段落内容的任意位置,内嵌宏。
icon:tags[] ruby, asciidoctor
  • HTML 格式输出。
<div class="paragraph">
<p><span class="icon"><i class="fa fa-tags"></i></span> ruby, asciidoctor</p>
</div>
  • 内联图标宏和角色语法。
icon:tags[role="blue"] ruby, asciidoctor
  • 图标大小
  • 默认为 1x
icon:heart[2x]
icon:heart[size=2x]
  • 图标旋转和翻转
icon:shield[rotate=90, flip=vertical]
  • 链接
icon:download[link="http://rubygems.org/downloads/asciidoctor-1.5.2.gem"]

1.1.3.4 引文段落

  • 将引文样式应用到任何段落,它将使用更大的字体大小。
  • 自动将引文段落进行样式化。
  • 可以采用 (.) 的方式设置引文角色和分配到段落上。
  • 当将文档转换为 HTML 并使用默认样式表查看时,前导的第一段将自动样式化为前导段。
[.lead]
This text will be styled as a lead paragraph (i.e., larger font).

1.1.4 块结构

  • 任何块都可以有一个标题,位于块的上方。块标题是从一个点开始的文本行。

1.1.4.1 文本块

  • 文字块定义为三种方式
  • 用一个或多个空格缩进段落的第一行。
  • 将文字属性应用于段落或区块。
  • 使用文字块定界符(…)。
 error: The requested operation returned error: 1954 Forbidden search for defensive operations manual
 absolutely fatal: operation initiation lost in the dodecahedron of doom
 would you like to die again? y/n
....
Lazarus: Where is the *defensive operations manual*?
Computer: Calculating ...
Can not locate object that you are not authorized to know exists.
Would you like to ask another question?
Lazarus: Did the werewolves tell you to say that?
Computer: Calculating ...
....

注意:在输出中,粗体文本格式没有应用于文本。

  • 当希望整个文本块是文本,并且不希望缩进时,可在元素的顶部设置文本属性。
[literal]
error: The requested operation returned error: 1954 Forbidden search for defensive operations manual
absolutely fatal: operation initiation lost in the dodecahedron of doom
would you like to die again? y/n

1.1.4.2 注释块

  • 不会输出到目标文件。
  • 行注释
  • 行注释可用于分割元素,如两个相邻列表。
// A single-line comment.
  • 块注释
////
CommentBlock
////
1.1.4.3 清单块(列表块)
  • 用于计算机的输出和文件列表、可用于程序代码。
  • 里面特殊字符不替换。
  • 列表块内容被转换为 <PRE> 文本。
  • 列表块中的内容只受特殊字符和标注替换的限制。
  • 列表块名称应用于内容的两种方式。
  • 在元素上设置列表属性。
  • 包含分隔符列表块中的内容。
  • 将列表块名称应用于元素,例如段落,通过在该元素上设置列表属性。
[listing]
This is an example of a paragraph styled with `listing`.
Notice that the monospace markup is preserved in the output.
  • 包含分隔的列表块由四个连字符(----)组成的行包围。
  • 列表块有利于显示原始源代码,尤其是与源代码和源代码突出显示器属性一起使用时。
.app.rb
[source,ruby]
----
require 'sinatra'
get '/hi' do
 "Hello World!"
end
  • 具有自定义替换语法的列表块。
:version: 1.5.6.1
[source,xml,subs="verbatim,attributes"]
----
<dependency>
 <groupId>org.asciidoctor</groupId>
 <artifactId>asciidoctor-java-integration</artifactId>
 <version>{version}</version>
</dependency>
----
  • 滚动支持
  • nowrap 会增加(css 样式 white-space:nowrap 和 word-wrap: normal)到 <PRE> 元素上。
[source%nowrap,java]
----
public class ApplicationConfigurationProvider extends HttpConfigurationProvider
{
 @Override
 public Configuration getConfiguration(ServletContext context)
 {
 return ConfigurationBuilder.begin()
 .addRule()
 .when(Direction.isInbound().and(Path.matches("/{path}")))
 .perform(Log.message(Level.INFO, "Client requested path: {path}"))
 .where("path").matches(".*");
 }
}
----
  • 全局强制不换行 ,可以设置 prewrap 属性。
:prewrap!:
  • 带标题的列表块
.Gemfile.lock
----
GEM
 remote: https://rubygems.org/
 specs:
 asciidoctor (1.5.6.1)
PLATFORMS
 ruby
DEPENDENCIES
 asciidoctor (~> 1.5.6.1)
----
  • 带标注的代码块
[source,ruby]
----
require 'sinatra' // <1>
get '/hi' do // <2>
 "Hello World!" // <3>
end
----
<1> Library import
<2> URL mapping
<3> HTTP response body
  • 带不可选择标注的代码块
----
line of code // <1>
line of code # <2>
line of code ;; <3>
----
<1> A callout behind a line comment for C-style languages.
<2> A callout behind a line comment for Ruby, Python, Perl, etc.
<3> A callout behind a line comment for Clojure.
  • 具有不可选标注的 XML 代码块
[source,xml]
----
<section>
 <title>Section Title</title> <!--1-->
</section>
----
<1> The section title is required.
  • 直接引入源文件的代码块
[source,ruby]
----
include::app.rb[]
----
  • 源文件相对源目录的代码块
:sourcedir: src/main/java
[source,java]
----
include::{sourcedir}/org/asciidoctor/Asciidoctor.java[]
----
  • 引入源文件一部分的代码块
[source,ruby,indent=0]
----
include::lib/document.rb[lines=5..10]
----
  • 无分隔符的代码块
[source,xml]
<meta name="viewport"
 content="width=device-width, initial-scale=1.0">
This is normal content.
  • 代码列表块启动语法高亮可以在文档头中设置。
  • 高亮属性有 coderay、highlightjs、prettify 和 pygments。
:source-highlighter: pygments

1.1.4.4 侧边栏块

  • 有边框显示。
.AsciiDoc history
****
AsciiDoc was first released in Nov 2002 by Stuart Rackham.
It was designed from the start to be a shorthand syntax
for producing professional documents like DocBook and LaTeX.
****

1.1.4.5 引用文本块

  • 文本块左上角显示一个双引号图片。
____
QuoteBlock
____
  • 负责引用块
[quote, Abraham Lincoln, Address delivered at the dedication of the Cemetery at Gettysburg]
____
Four score and seven years ago our fathers brought forth
on this continent a new nation...
____
[quote, Albert Einstein]
A person who never made a mistake never tried anything new.
____
A person who never made a mistake never tried anything new.
____
[quote, Charles Lutwidge Dodgson, 'Mathematician and author, also known as http://en.wikipedia.org/wiki/Lewis_Carroll[Lewis Carroll]']
____
If you don't know where you are going, any road will get you there.
____
  • 缩写块引用(只有 Asciidoctor 支持)
"I hold it that a little rebellion now and then is a good thing,
and as necessary in the political world as storms in the physical."
-- Thomas Jefferson, Papers of Thomas Jefferson: Volume 11
  • 空引用
[, James Baldwin]
""
Not everything that is faced can be changed.
But nothing can be changed until it is faced.
""

1.1.4.6 案例文本块

  • 可以使用 NOTE、TIP、IMPORTANT、WARNING、CAUTION 显示提示块。
====
ExampleBlock
====

1.1.4.7 混合使用

.Sample document
====
Here's a sample AsciiDoc document:
[listing]
....
= Title of Document
Doc Writer
:toc:
This guide provides...
....
The document header is useful, but not required.
====
[NOTE]
====
An admonition block may contain complex content.
.A list
- one
- two
- three
Another paragraph.
====

1.1.4.8 开放块

--
An open block can be an anonymous container,
or it can masquerade as any other block.
--
[source]
--
puts "I'm a source block!"
--

1.1.5 列表

1.1.5.1 有序列表

  • 通过在第一个列表之后插入一个空白行和一行注释,可以将两个相邻的列表分开。-
  • 约定使用(//)作为行注释向其他作者提供一个提示,即它是一个列表分隔符。
1. 阿拉伯数字标注的列表项目.
a. 小写字母标注的列表项目.
F. 大写字母标注的列表项目.
iii) 小写罗马数字标注的列表项目.
IX) 大写罗马数字标注的列表项目.

1.1.5.2 无序列表

- List item.
* List item.
** List item.
*** List item.
**** List item.
***** List item.

1.1.5.3 自定义列表

  • 字母或数字开始 1-4 个冒号或两个分号结束。
Operating Systems::
 Linux:::
 . Fedora
 * Desktop
 . Ubuntu
 * Desktop
 * Server
 BSD:::
 . FreeBSD
 . NetBSD
Cloud Providers::
 PaaS:::
 . OpenShift
 . CloudBees
 IaaS:::
 . Amazon EC2
 . Rackspace

1.1.5.4 问答列表

[qanda]
What is Asciidoctor?::
 An implementation of the AsciiDoc processor in Ruby.
What is the answer to the Ultimate Question?:: 42

1.1.5.5 复选框列表

* [*] checked
* [x] also checked
* [ ] not checked
* normal list item

1.1.5.6 单行标记

first term:: definition of first term
second term:: definition of second term

1.1.5.7 多行标记

first term::
definition of first term
second term::
definition of second term

1.1.5.8 专业术语列表

[glossary]
术语1::
 解释1.
术语2::
 解释2.

1.1.6 文本格式

1.1.6.1 粗体

*bold phrase* & **char**acter**s**

1.1.6.2 斜体

_italic phrase_ & __char__acter__s__

1.1.6.3 等宽字体

`monospace phrase` & ``char``acter``s``
  • 如果要在等宽字体中用到({name})这样的格式(需要直译),那么可以使用(+ 和 +)符号或者转义符(\)。
You can reference the value of a document attribute using the syntax `+{name}+`, where `name` is the attribute name.

1.1.6.4 混合使用

`*_monospace bold italic phrase_*` & ``**__char__**``acter``**__s__**``

1.1.6.5 标记字体(黄色背景)

Werewolves are allergic to #cassia cinnamon#.

1.1.6.6 字体缩小

Did the werewolves read the [.small]##small print##?

1.1.6.7 字体扩大

[.big]##O##nce upon an infinite loop.

1.1.6.8 删除线

We need [.line-through]#ten# make that twenty VMs.

1.1.6.9 下划线

Where did all the [.underline]#cores# run off to?

1.1.6.10 上标

^super^script phrase

1.1.6.11 下标

~sub~script phrase

1.1.6.12 智能引号

  • 如果不希望应用智能引号,可以使用 (\)进行转义。
"`double curved quotes`"
'`single curved quotes`'
Olaf's desk was a mess.
All of the werewolves`' desks were a mess.
Olaf had been with the company since the `'60s.
“double curved quotes”
‘single curved quotes’
Olaf’s desk was a mess.
All of the werewolves’ desks were a mess.
Olaf had been with the company since the ’60s.

1.1.6.13 文本替换

符号显示说明(C)©版权(TM)™商标(R)®注册商标…​...省略号->→右箭头<-←左箭头=>⇒右双箭头<=⇐左双箭头➊➊数字--—破折号(只能在两个字符之间使用)

  • 文本替换是指其字符的通用字符集 / Unicode 代码,使用格式。
  • https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references 可查询通用字符集。
hhhh;

1.1.7 其他标签

1.1.7.1 文件包含语句

  • 如果不在相邻的文件包含语句之间插入空白行以保持内容分离,务必在源文档中添加空白行,以避免意外的结果,如吞并部分标题等。
= Reference Documentation
Lead Developer
This is documentation for project X.
include::basics.adoc[]
include::installation.adoc[]
include::example.adoc[]
  • 包含 URL 文件
include::https://raw.githubusercontent.com/asciidoctor/asciidoctor/master/README.adoc[]

1.1.7.2 水平线

'''

1.1.7.3 分页符

<<<

1.1.7.4 超链接

  • 外部链接
https://asciidoctor.org - automatic!
https://asciidoctor.org[Asciidoctor]
https://github.com/asciidoctor[Asciidoctor @ *GitHub*]
  • 具有空格和特殊字符
link:++https://example.org/?q=[a b]++[URL with special characters]
link:https://example.org/?q=%5Ba%20b%5D[URL with special characters]
  • Windows 路径
link:\\server\share\whitepaper.pdf[Whitepaper]
  • 相对路径
link:index.html[Docs]
  • 电子邮件和 IRC
devel@discuss.arquillian.org
mailto:devel@discuss.arquillian.org[Discuss Arquillian]
mailto:devel-join@discuss.arquillian.org[Subscribe, Subscribe me, I want to join!]
irc://irc.freenode.org/#fedora

1.1.7.5 锚点

锚点:[[A88]]
链接:<<A88,chapter titles>>

1.1.7.6 图片

  • 块图像
image::sunset.jpg[]
image::sunset.jpg[Sunset]
.A mountain sunset
[#img-sunset]
[caption="Figure 1: ",link=https://www.flickr.com/photos/javh/5448336655]
image::sunset.jpg[Sunset,300,200]
image::https://asciidoctor.org/images/octocat.jpg[GitHub mascot]
  • 内联图
Click image:icons/play.png[Play, title="Play"] to get the party started.
Click image:icons/pause.png[title="Pause"] when you need a break.
  • 具有定位角色的内联图
image:sunset.jpg[Sunset,150,150,role="right"] What a beautiful sunset!

1.1.7.7 视频

  • 块视频
video::video_file.mp4[]
video::video_file.mp4[width=640, start=60, end=140, options=autoplay]

1.1.7.8 源码

  • 内联方式(等宽字体)
Reference code like `types` or `methods` inline.
  • 内联方式(直译方法)
Output literal monospace text such as `+{backtick}+` by
enclosing the text in pluses, then again in backticks.

1.1.7.9 文档目录(ToC)

= AsciiDoc Writer's Guide
Doc Writer <doc.writer@asciidoctor.org>
v1.0, 2013-08-01
:toc: right

1.1.7.10 参考文献

_The Pragmatic Programmer_ <<pp>> should be required reading for all developers.
To learn all about design patterns, refer to the book by the "`Gang of Four`" <<gof>>.
[bibliography]
== References
- [[[pp]]] Andy Hunt & Dave Thomas. The Pragmatic Programmer:
 From Journeyman to Master. Addison-Wesley. 1999.
- [[[gof,2]]] Erich Gamma, Richard Helm, Ralph Johnson & John Vlissides. Design Patterns:
 Elements of Reusable Object-Oriented Software. Addison-Wesley. 1994.

1.1.7.11 脚注

A statement.footnote:[Clarification about this statement.]
A bold statement!footnoteref:[disclaimer,Opinions are my own.]
Another bold statement.footnoteref:[disclaimer]

1.1.8 表格

  • 除非指定了 cols 属性,否则列的数量等于块分隔符之间的第一行(非空)上的单元格分隔符字符的数量。
  • 当空白行跟随第一个非空行时,第一行中的单元格将升迁到表标题。
.Table Title
|===
|Name of Column 1 |Name of Column 2 |Name of Column 3 
|Cell in column 1, row 1
|Cell in column 2, row 1
|Cell in column 3, row 1
|Cell in column 1, row 2
|Cell in column 2, row 2
|Cell in column 3, row 2
|===
  • cols 属性中的(*)是重复运算符,意味着在列的其余部分重复列规范。
  • 当头中的单元格没有在一行上定义时,必须使用 cols 属性设置表中的列数,使用 %header 选项(或 .=header 属性)将第一行提升到表头。
[%header,cols=2*] 
|===
|Name of Column 1
|Name of Column 2
|Cell in column 1, row 1
|Cell in column 2, row 1
|Cell in column 1, row 2
|Cell in column 2, row 2
|===
  • 下例中指定该表有三列,并设置它们的相对宽度。
[cols="1,1,2", options="header"] 
.Applications
|===
|Name
|Category
|Description
|Firefox
|Browser
|Mozilla Firefox is an open-source web browser.
It's designed for standards compliance,
performance, portability.
|Arquillian
|Testing
|An innovative and highly extensible testing platform.
Empowers developers to easily create real, automated tests.
|===
  • 包含其他标签的表
[cols="2,2,5a"]
|===
|Firefox
|Browser
|Mozilla Firefox is an open-source web browser.
It's designed for:
* standards compliance
* performance
* portability
http://getfirefox.com[Get Firefox]!
|===
  • CSV 格式的表
[%header,format=csv]
|===
Artist,Track,Genre
Baauer,Harlem Shake,Hip Hop
The Lumineers,Ho Hey,Folk Rock
|===
  • CSV 格式速记表(只有 Asciidoctor 支持)
,===
Artist,Track,Genre
Baauer,Harlem Shake,Hip Hop
,===
  • 引入 CSV 文件表
|===
include::customers.csv[]
|===
  • DSV 数据使用速记表
:===
Artist:Track:Genre
Robyn:Indestructable:Dance
:===
  • 带格式化、对齐和合并单元的表
[cols="e,m,^,>s", width="25%"]
|===
|1 >s|2 |3 |4
^|5 2.2+^.^|6 .3+<.>m|7
^|8
|9 2+>|10
|===

1.1.9 属性

  • 定义和使用
:url-home: https://asciidoctor.org
:link-docs: https://asciidoctor.org/docs[documentation]
:summary: Asciidoctor is a mature, plain-text document format for \
 writing notes, articles, documentation, books, and more. \
 It's also a text processor & toolchain for translating \
 documents into various output formats (i.e., backends), \
 including HTML, DocBook, PDF and ePub.
:checkedbox: pass:normal[{startsb}✔{endsb}]
Check out {url-home}[Asciidoctor]!
{summary}
Be sure to read the {link-docs} too!
{checkedbox} That's done!
  • 计数器属性
[caption=""]
.Parts{counter2:index:0}
|===
|Part Id |Description
|PX-{counter:index}
|Description of PX-{index}
|PX-{counter:index}
|Description of PX-{index}
|===

1.1.10 直译方式

  • 转移符直译
\*Stars* is not rendered as bold text.
The asterisks around the word are preserved.
\{author} is not resolved to the author name.
The curly brackets around the word are preserved.
`A\--Z` connects A to Z in monospace using two dashes.
The dashes are not replaced by an em dash.
\[[Word]] is not interpreted as an anchor.
The double brackets around the word are preserved.
[\[[Word]]] is not interpreted as a bibliography anchor.
The triple brackets around the word are preserved.
In these cases, the backslash character is automatically removed.
  • (+)号直译
`+Text inside {plus} characters+` is not formatted.
However, special characters like +<+ and +>+ are still escaped.
  • pass 宏直译
pass:[<u>underline me</u>] is also underlined.
  • 三(+)直译
+++<u>underline me</u>+++ is underlined.

1.2 兼容 Markdown

  • 兼容 Markdown 标题
# Document Title (Level 0)
## Section Level 1
### Section Level 2
#### Section Level 3
##### Section Level 4
###### Section Level 5
  • 兼容 Markdown 代码块
```ruby
require 'sinatra'
get '/hi' do
 "Hello World!"
end
\``` \\ 去除第一个 \ 符号
  • 兼容 Markdown 引用块
> I hold it that a little rebellion now and then is a good thing,
> and as necessary in the political world as storms in the physical.
> -- Thomas Jefferson, Papers of Thomas Jefferson: Volume 11
  • 兼容 Markdown 引用块和块内容
> > What's new?
>
> I've got Markdown in my AsciiDoc!
>
> > Like what?
>
> * Blockquotes
> * Headings
> * Fenced code blocks
>
> > Is there more?
>
> Yep. AsciiDoc and Markdown share a lot of common syntax already.
  • 兼容 Markdown 水平线
---
- - -
***
* * *

参考资料

https://asciidoctor.org/docs/

近经常被问 https://t.itmuch.com/doc.html 文档页是怎么制作的,考虑到步骤略复杂,写篇手记总结下吧。

TIPS

https://t.itmuch.com/doc.html 是个人在慕课网视频《 面向未来微服务:Spring Cloud Alibaba从入门到进阶[1] 》的实战项目配套文档。

效果

总体步骤

•整合Swagger,生成Swagger描述端点 /v2/api-docs

•使用 swagger2markup-maven-plugin ,将 /v2/api-docs 生成ASCIIDOC文件;

•使用 asciidoctor-maven-plugin ,将ASCIIDOC文件转换成HTML;

•部署

整合Swagger

TIPS

Swagger的使用非常简单,本文不展开探讨了,各位看官自行百度一下用法吧。

常用注解:

•@Api

•@ApiOperation

•@ApiModel

•@ApiModelProperty

1 加依赖

<!-- swagger -->
<!-- 之所以要排除,是因为如果不排除会报NumberFormatException的警告。 -->
<!-- 参考:https://github.com/springfox/springfox/issues/2265-->
<dependency>
 <groupId>io.springfox</groupId>
 <artifactId>springfox-swagger2</artifactId>
 <version>2.9.2</version>
 <exclusions>
 <exclusion>
 <groupId>io.swagger</groupId>
 <artifactId>swagger-annotations</artifactId>
 </exclusion>
 <exclusion>
 <groupId>io.swagger</groupId>
 <artifactId>swagger-models</artifactId>
 </exclusion>
 </exclusions>
</dependency>
<dependency>
 <groupId>io.springfox</groupId>
 <artifactId>springfox-swagger-ui</artifactId>
 <version>2.9.2</version>
</dependency>
<dependency>
 <groupId>io.swagger</groupId>
 <artifactId>swagger-annotations</artifactId>
 <version>1.5.21</version>
</dependency>
<dependency>
 <groupId>io.swagger</groupId>
 <artifactId>swagger-models</artifactId>
 <version>1.5.21</version>
</dependency>

2 配置Swagger(按照自己的需要配置,下面的配置代码仅供参考)

/**
 * @author itmuch.com
 */
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
 /**
 * swagger 信息
 *
 * @return 页面信息
 */
 private ApiInfo apiInfo() {
 return new ApiInfoBuilder()
 .title("ITMuch API")
 .description("ITMuch API")
 .termsOfServiceUrl("")
 .version("1.0.0")
 .contact(new Contact("", "", "")).build();
 }
 @Bean
 public Docket customImplementation() {
 return new Docket(DocumentationType.SWAGGER_2)
 .select()
 .apis(RequestHandlerSelectors.basePackage("com.itmuch"))
 .paths(PathSelectors.any())
 .build()
 .apiInfo(this.apiInfo());
 //.globalOperationParameters(parameters);
 }
}

3 为接口Swagger注解

@RestController
@RequestMapping("/notices")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Api(tags = "公告相关接口", description = "公告相关接口")
public class NoticeController {
 /**
 * 查询最新的一条公告
 *
 * @return 公告列表
 */
 @GetMapping("/newest")
 @ApiOperation(value = "查询最新的一条公告", notes = "用于:公告")
 public Notice findNewest() {
 return new Notice();
 }
}
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@ApiModel("公告")
public class Notice {
 /**
 * ID
 */
 @ApiModelProperty("id")
 private Integer id;
 /**
 * 公告内容
 */
 @ApiModelProperty("公告内容")
 private String content;
 ...
}

这样,应用启动完成后,就会有一个/v2/api-docs 端点,描述了你的API的信息。

生成ASCIIDOC

在pom.xml中添加如下内容:

<build>
 <plugins>
 <plugin>
 <groupId>io.github.swagger2markup</groupId>
 <artifactId>swagger2markup-maven-plugin</artifactId>
 <version>1.3.1</version>
 <configuration>
 <!-- api-docs访问url -->
 <swaggerInput>http://localhost:8080/v2/api-docs</swaggerInput>
 <!-- 生成为单个文档,输出路径 -->
 <outputFile>src/docs/asciidoc/generated/all</outputFile>
 <config>
 <!-- ascii格式文档 -->
 <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
 <swagger2markup.pathsGroupedBy>TAGS</swagger2markup.pathsGroupedBy>
 </config>
 </configuration>
 </plugin>
 ...

swagger2markup-maven-plugin 插件的作用是读取 http://localhost:8080/v2/api-docs 的信息,生成ASCIIDOC文档。当然你也可以生成其他格式,比如Markdown等等。

这款插件还有很多使用姿势,详见 https://github.com/Swagger2Markup/swagger2markup-maven-plugin[2]

生成HTML

下面,只需要将ASCIIDOC转换成html就OK了,在pom.xml中添加如下内容:

<build>
 <plugins>
 <plugin>
 <groupId>org.asciidoctor</groupId>
 <artifactId>asciidoctor-maven-plugin</artifactId>
 <version>1.5.6</version>
 <configuration>
 <!-- asciidoc文档输入路径 -->
 <sourceDirectory>src/docs/asciidoc/generated</sourceDirectory>
 <!-- html文档输出路径 -->
 <outputDirectory>src/docs/asciidoc/html</outputDirectory>
 <backend>html</backend>
 <sourceHighlighter>coderay</sourceHighlighter>
 <!-- html文档格式参数 -->
 <attributes>
 <doctype>book</doctype>
 <toc>left</toc>
 <toclevels>3</toclevels>
 <numbered></numbered>
 <hardbreaks></hardbreaks>
 <sectlinks></sectlinks>
 <sectanchors></sectanchors>
 </attributes>
 </configuration>
 </plugin>

asciidoctor-maven-plugin 插件同样也有很多姿势,详见:https://github.com/asciidoctor/asciidoctor-maven-plugin[3]

生成的文件在 src/docs/asciidoc/html (看你插件上面的配置哈),然后你就可以弄个NGINX部署了。

干货分享

最近将个人学习笔记整理成册,使用PDF分享。关注我,回复如下代码,即可获得百度盘地址,无套路领取!

•001:《Java并发与高并发解决方案》学习笔记;

•002:《深入JVM内核——原理、诊断与优化》学习笔记;

•003:《Java面试宝典》

•004:《Docker开源书》

•005:《Kubernetes开源书》

•006:《DDD速成(领域驱动设计速成)》


References

[1] 面向未来微服务:Spring Cloud Alibaba从入门到进阶: https://coding.imooc.com/class/358.html

[2]: https://github.com/Swagger2Markup/swagger2markup-maven-plugin

[3]: https://github.com/asciidoctor/asciidoctor-maven-plugin

相信很多后端开发在项目中都会碰到要写 api 文档,不管是给前端、移动端等提供更好的对接,还是以后为了以后交接方便,都会要求写 api 文档。

而手写 api 文档的话有诸多痛点:

  • 文档更新的时候,需要再次发送给对接人
  • 接口太多,手写文档很难管理
  • 接口返回的结果不明确
  • 不能直接在线测试接口,通常需要使用工具,如 postman 等

Swagger 就很好地解决了这个问题。

Swagger 简介

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。

Swagger 使用

1.相关依赖

<!--swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

2.Swagger 配置类

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket buildDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(buildApiInf()) //将api的元信息设置为包含在json resourcelisting响应中
        //.host("127.0.0.1:8080") //设置ip和端口,或者域名
        .select()  //启动用于api选择的生成器
        //.apis(RequestHandlerSelectors.any())
        .apis(RequestHandlerSelectors.basePackage("cn.zwqh.springboot.controller"))//指定controller路径
        .paths(PathSelectors.any()).build();
    }

    private ApiInfo buildApiInf() {

        Contact contact=new Contact("朝雾轻寒","https://www.zwqh.top/","zwqh@clover1314.com");
        return new ApiInfoBuilder()
        .title("Swagger Demo Restful API Docs")//文档标题
        .description("Swagger 示例 Restful Api 文档")//文档描述
        .contact(contact)//联系人
        .version("1.0")//版本号
        //.license("")//更新此API的许可证信息
        //.licenseUrl("")//更新此API的许可证Url
        //.termsOfServiceUrl("")//更新服务条款URL
        .build();

    }
}

3.Spring MVC 相关配置

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    /**
     * 静态资源配置(默认)
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");// 静态资源路径
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        super.addResourceHandlers(registry);
    }

}

如果不添加此静态资源配置会报错,找不到相关路径

4.Model 中使用 Swagger 注解

@ApiModel(value = "UserEntity", description = "用户对象")
public class UserEntity implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 5237730257103305078L;
    @ApiModelProperty(value ="用户id",name="id",dataType="Long",required = false,example = "1",hidden = false )
    private Long id;
    @ApiModelProperty(value ="用户名",name="userName",dataType="String",required = false,example = "关羽" )
    private String userName;
    @ApiModelProperty(value ="用户性别",name="userSex",dataType="String",required = false,example = "男" )
    private String userSex;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

}

5. Controller 中使用 Swagger 注解


@RestController
@RequestMapping("/api")
@Api(tags = { "接口分组1", "接口分组2" })
public class ApiController {

    @Autowired
    private UserDao userDao;

    @GetMapping("/getAllUser")
    @ApiOperation(value = "获取所有用户", notes = "", httpMethod = "GET", tags = "接口分组3")
    public List<UserEntity> getAll() {
        return userDao.getAll();
    }

    @GetMapping("/getUserById")
    @ApiOperation(value = "根据id获取用户", notes = "id必传", httpMethod = "GET")
    @ApiImplicitParam(name = "id", value = "用户id",example = "1", required = true, dataType = "long", paramType = "query")
    public UserEntity getOne(Long id) {
        return userDao.getOne(id);
    }

    @PostMapping("/getUserByNameAndSex")
    @ApiOperation(value = "根据name和sex获取用户", notes = "", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userName", value = "用户名", example = "关羽", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "userSex", value = "用户性别", example = "男", required = true, dataType = "string", paramType = "query") })
    public UserEntity getUserByNameAndSex(String userName, String userSex) {
        return userDao.getUserByNameAndSex(userName, userSex);
    }

    @PostMapping("/insertUser")
    @ApiOperation(value = "新增用户", notes = "传json,数据放body", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "body", value = "用户对象json", example = "{userName:'朝雾轻寒',userSex:'男'}", required = true) })
    public String insertUser(@RequestBody String body) {
        System.out.println(body);
        UserEntity user = JSON.parseObject(body, UserEntity.class);
        userDao.insertUser(user);
        return "{code:0,msg:'success'}";
    }

    @PostMapping("/updateUser")
    @ApiOperation(value = "修改用户", notes = "传json,数据放body", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "body", value = "用户对象json", example = "{id:23,userName:'朝雾轻寒',userSex:'女'}", required = true) })
    public String updateUser(@RequestBody String body) {
        System.out.println(body);
        UserEntity user = JSON.parseObject(body, UserEntity.class);
        userDao.updateUser(user);
        return "{code:0,msg:'success'}";
    }

    @PostMapping("/deleteUser")
    @ApiOperation(value = "删除用户", notes = "id必传", httpMethod = "POST")
    public String deleteUser(@ApiParam(name = "id", value = "用户id", required = true) Long id) {
        userDao.deleteUser(id);
        return "{code:0,msg:'success'}";
    }
}

5.测试

访问 http://127.0.0.1:8080/swagger-ui.html 进行接口在线测试

Swagger 常用注解

1.@Api

用于类,表示表示这个类是swagger的资源。属性如下:

  • tags 表示说明,tags如果有多个值,会生成多个列表
  • value 表示说明,可以使用tags替代

2.@ApiOperation

用于方法,表示一个http请求的操作。属性如下:

  • value 用于方法描述
  • notes 用于提示内容
  • tags 用于API文档控制的标记列表,视情况而用,可以进行独立分组

3.@ApiParam

用于方法、参数、字段说明;表示对参数的添加元数据。

  • name 参数名
  • value 参数说明
  • required 是否必填

4.@ApiModel

用于类,表示对类进行说明,用于参数用实体类接受。

  • value 对象名
  • description 描述

5.@ApiModelProperty

用于方法、字段,表示对model属性的说明或者数据操作更改。

  • value 字段说明
  • name 重写属性名
  • dataType 重写属性数据类型
  • required 是否必填
  • example 举例说明
  • hidden 隐藏

6.@ApiIgnore

用于类、方法、方法参数,表示这个方法或者类被忽略,不在swagger-ui.html上显示。

7.@ApiImplicitParam

用于方法,表示单独的请求参数。

  • name 参数名
  • value 参数说明
  • dataType 数据类型
  • paramType 参数类型
  • example 举例说明

8.@ApiImplicitParams

用于方法,包含多个 @ApiImplicitParam。

9.@ApiResponses @ApiResponse

用于类或者方法,描述操作的可能响应。

  • code 响应的HTTP状态代码
  • message 响应附带的可读消息

10.@ResponseHeader

用于方法,响应头设置。

  • name 响应头名称
  • description 头描述
  • response 默认响应类 void
  • responseContainer 参考ApiOperation中配置

Swagger 导出离线 api 文档

1.导出 AsciiDocs、Markdown、Confluence 格式文档

添加依赖

<!-- swagger2markup 相关依赖 -->
        <dependency>
            <groupId>io.github.swagger2markup</groupId>
            <artifactId>swagger2markup</artifactId>
            <version>1.3.3</version>
        </dependency>

转换工具类

public class SwaggerUtils {

    private static final String url = "http://127.0.0.1:8080/v2/api-docs";
    /**
     * 生成AsciiDocs格式文档
     * @throws MalformedURLException
     */
    public static void generateAsciiDocs() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.ASCIIDOC)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema().build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/asciidoc/generated"));
    }
    /**
     * 生成AsciiDocs格式文档,并汇总成一个文件
     * @throws MalformedURLException
     */
    public static void generateAsciiDocsToFile() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.ASCIIDOC)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFile(Paths.get("./docs/asciidoc/generated/all"));
    }

    /**
     * 生成Markdown格式文档
     * @throws MalformedURLException
     */
    public static void generateMarkdownDocs() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.MARKDOWN)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/markdown/generated"));
    }
    /**
     * 生成Markdown格式文档,并汇总成一个文件
     * @throws MalformedURLException
     */
    public static void generateMarkdownDocsToFile() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.MARKDOWN)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFile(Paths.get("./docs/markdown/generated/all"));
    }

    /**
     * 生成Confluence格式文档
     * @throws MalformedURLException
     */
    public static void generateConfluenceDocs() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.CONFLUENCE_MARKUP)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/confluence/generated"));
    }

    /**
     * 生成Confluence格式文档,并汇总成一个文件
     * @throws MalformedURLException
     */
    public static void generateConfluenceDocsToFile() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.CONFLUENCE_MARKUP)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFile(Paths.get("./docs/confluence/generated/all"));
    }

}

使用测试 Controller

@RestController
@RequestMapping("/export")
@ApiIgnore
public class ExportController {

    @RequestMapping("/ascii")
    public String exportAscii() throws MalformedURLException{
        SwaggerUtils.generateAsciiDocs();
        return "success";
    }

    @RequestMapping("/asciiToFile")
    public String asciiToFile() throws MalformedURLException{
        SwaggerUtils.generateAsciiDocsToFile();
        return "success";
    }

    @RequestMapping("/markdown")
    public String exportMarkdown() throws MalformedURLException{
        SwaggerUtils.generateMarkdownDocs();
        return "success";
    }

    @RequestMapping("/markdownToFile")
    public String exportMarkdownToFile() throws MalformedURLException{
        SwaggerUtils.generateMarkdownDocsToFile();
        return "success";
    }

    @RequestMapping("/confluence")
    public String confluence() throws MalformedURLException{
        SwaggerUtils.generateConfluenceDocs();
        return "success";
    }

    @RequestMapping("/confluenceToFile")
    public String confluenceToFile() throws MalformedURLException{
        SwaggerUtils.generateConfluenceDocsToFile();
        return "success";
    }
}

2.导出 html、pdf、xml 格式

添加依赖

<!--离线文档 -->
        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
        <!--springfox-staticdocs 生成静态文档 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-staticdocs</artifactId>
            <version>2.6.1</version>
        </dependency>
<build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
                <plugin>
                    <groupId>io.github.swagger2markup</groupId>
                    <artifactId>swagger2markup-maven-plugin</artifactId>
                    <version>1.3.1</version>
                    <configuration>
                        <swaggerInput>http://127.0.0.1:8080/v2/api-docs</swaggerInput>
                        <outputDir>./docs/asciidoc/generated</outputDir>
                        <config>
                            <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
                        </config>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.asciidoctor</groupId>
                    <artifactId>asciidoctor-maven-plugin</artifactId>
                    <version>1.5.3</version>
                    <!-- <version>2.0.0-RC.1</version> -->
                    <!-- Include Asciidoctor PDF for pdf generation -->
                    <dependencies>
                        <dependency>
                            <groupId>org.asciidoctor</groupId>
                            <artifactId>asciidoctorj-pdf</artifactId>
                            <version>1.5.0-alpha.10.1</version>
                        </dependency>
                        <dependency>
                            <groupId>org.jruby</groupId>
                            <artifactId>jruby-complete</artifactId>
                            <version>1.7.21</version>
                        </dependency>
                    </dependencies>
                    <configuration>
                        <sourceDirectory>./docs/asciidoc/generated</sourceDirectory>
                        <outputDirectory>./docs/asciidoc/html</outputDirectory> 
                        <backend>html</backend>
                        <!-- <outputDirectory>./docs/asciidoc/pdf</outputDirectory> 
                        <backend>pdf</backend> -->
                        <headerFooter>true</headerFooter> 
                        <doctype>book</doctype> 
                        <sourceHighlighter>coderay</sourceHighlighter>
                        <attributes>
                            <!-- 菜单栏在左边 -->
                            <toc>left</toc>
                            <!-- 多标题排列 -->
                            <toclevels>3</toclevels>
                            <!-- 自动打数字序号 -->
                            <sectnums>true</sectnums>
                        </attributes>
                    </configuration>                    
                </plugin>
            </plugins>
        </pluginManagement>

    </build>

可以修改此处 html 和 pdf,通过 mvn asciidoctor:process-asciidoc 可以导出相应格式文件

<outputDirectory>./docs/asciidoc/html</outputDirectory> 
                        <backend>html</backend>

执行 mvn asciidoctor:process-asciidoc 后再执行 mvn generate-resources,可在 targt/generated-docs 目录下生成 xml 格式文件