Compare commits
222 Commits
Author | SHA1 | Date |
---|---|---|
shalousun | 4e899a831a | |
shalousun | 228cffc6ea | |
cqmike | 802acd31b4 | |
cqmike | a4abc7866f | |
cqmike | 751b26b6cc | |
shalousun | 1ab06ff4d8 | |
shalousun | 1c61a3d52e | |
shalousun | 94b4a92523 | |
cqmike | 88add1c32e | |
shalousun | ae1738e9b8 | |
shalousun | a2c3b98b87 | |
shalousun | d996715bcd | |
shalousun | d82ed6744e | |
shalousun | d4691dcbf4 | |
shalousun | c54eab1076 | |
shalousun | 91b6b87244 | |
shalousun | d9a630658d | |
xingzi | 8d1dace67e | |
shalousun | 38026fc3c8 | |
durian530 | 47c8a51400 | |
shalousun | bb3739b4de | |
shalousun | 95b7c3b9d8 | |
shalousun | 7b24b37c0a | |
shalousun | a2bd0a041b | |
shalousun | 849cdcc1c6 | |
shalousun | 6be5a6c747 | |
shalousun | 66d7ccc8ee | |
shalousun | 302f9b7da7 | |
shalousun | 6f1e358c47 | |
shalousun | 3daa8333ad | |
shalousun | d803e4e881 | |
shalousun | e4e3846512 | |
shalousun | b791298384 | |
shalousun | fd0a80c784 | |
shalousun | 6778a4f6ad | |
shalousun | 17168b93de | |
shalousun | 196db481bd | |
shalousun | e4b7b9e181 | |
shalousun | 83b3b327ce | |
shalousun | ca1048c869 | |
shalousun | 627bd476a3 | |
shalousun | 19506d33f0 | |
shalousun | c123d83c69 | |
xingzi | f7a460754c | |
xingzi | d1bdf37d26 | |
xingzi | 4bac204e50 | |
xingzi | b9d108fd4b | |
shalousun | d073d143b6 | |
xingzi | 63a02559ea | |
xingzi | b2b5a21775 | |
shalousun | d65938c63e | |
shalousun | 6d993ed2a4 | |
shalousun | 6e3def2f7e | |
tangcent | a4deb5d901 | |
shalousun | 0c558c3a27 | |
shalousun | 96f46feeca | |
shalousun | 4643950d2c | |
shalousun | 77370faeb2 | |
shalousun | 92e6f9c4d5 | |
shalousun | fe7c6fc62d | |
shalousun | 93ff84cdfc | |
shalousun | ee45b87df2 | |
Forget | e2608debe4 | |
shalousun | 835e25c613 | |
shalousun | 1af03b725a | |
shalousun | 445ac56958 | |
shalousun | 20a6b14e5d | |
shalousun | f26abd5ad2 | |
shalousun | 79abbcd876 | |
shalousun | 7f16381e7c | |
shalousun | 1198e25e4c | |
xzli15 | 210b748e99 | |
shalousun | e64cfdcbda | |
shalousun | 2eedb8fa4b | |
shalousun | 08d085de96 | |
xzli15 | b8094d0ad4 | |
yao.hq | fe3765f1cb | |
shalousun | 04a253b3d1 | |
chenqi | 40d99634df | |
shalousun | 47e132bc2d | |
shalousun | 390b94b70b | |
shalousun | ea3d13a9b5 | |
cqmike | e8f52eefa0 | |
cqmike | 932d9a6aaf | |
shalousun | a433860946 | |
shalousun | c6db6a8f4d | |
shalousun | b59a6007d5 | |
shalousun | d1deef32f4 | |
xzli15 | 686ad49e32 | |
xzli15 | d896d18770 | |
shalousun | 115486f30e | |
shalousun | 5359af7dbc | |
shalousun | 68d04dadf3 | |
xzli15 | 5c7166d046 | |
xzli15 | 9b449ab7e0 | |
shalousun | 86ade55b84 | |
chenqi | 1b7661c6db | |
chenqi | df53344b3f | |
chenqi | be9d40ecf0 | |
shalousun | 599ec18890 | |
shalousun | 76be2eb854 | |
shalousun | cf6452c5d1 | |
shalousun | a50b3a01cf | |
chenqi | 1330e887c8 | |
xzli15 | 31fbc38394 | |
shalousun | bfb9fe054a | |
shalousun | 8c030e1418 | |
chenqi | 388c178662 | |
xingzi | d024ea9ac5 | |
chenqi | 44397612c4 | |
chenqi | 77f315ca9c | |
shalousun | af46ba63d8 | |
chenqi | 70171b7bb7 | |
shalousun | c783e3d1ed | |
shalousun | c563680c8a | |
shalousun | 27d77cd0a0 | |
shalousun | 9d04d2552b | |
shalousun | 65616c797a | |
shalousun | 58c45db77c | |
Daisy | 0eb6f620ea | |
song_my | 7c8cf1f96c | |
chenqi | 86f4e43ba9 | |
shalousun | 273170f7db | |
shalousun | 1347e13940 | |
shalousun | 31cd6112ed | |
Forget | 11c775a2b0 | |
Forget | 30999e0489 | |
shalousun | 97a0c5ef05 | |
shalousun | 1b5b3a84b9 | |
chenqi | 3dee302e76 | |
chenqi | 47d6a96509 | |
shalousun | d6d23f37e9 | |
shalousun | 6f3c4e2f06 | |
shalousun | 0874de6e6c | |
shalousun | 364a8204d8 | |
shalousun | f9359ac14d | |
shalousun | bba038ef00 | |
shalousun | 980b1d4170 | |
shalousun | 05019d9782 | |
shalousun | ce9ba20063 | |
shalousun | 91d1637dca | |
shalousun | dda70ab3a2 | |
shalousun | fcd9594aca | |
shalousun | 2f152f4f27 | |
shalousun | 7d05b3e956 | |
shalousun | 69724ace31 | |
shalousun | 49b67e35b1 | |
shalousun | 16e50651a0 | |
Daisy | 10cdc1e0d7 | |
shalousun | fb215cc74b | |
shalousun | 64d1dc8529 | |
shalousun | 4cc4c8e00a | |
shalousun | 79e1b1d176 | |
shalousun | f72021d48b | |
shalousun | 7aa678c5da | |
shalousun | 3756a97e24 | |
shalousun | 72e1dd7bd0 | |
shalousun | 01a45f9fa0 | |
shalousun | d9bdf58d95 | |
shalousun | 21cbef4b82 | |
shalousun | 6d8182dd08 | |
shalousun | c52ffb8dd7 | |
taogang | d7a5faa6eb | |
Daisy | ae77ba4106 | |
Daisy | 158fbf1d16 | |
shalousun | 561c552c94 | |
shalousun | f925694fb3 | |
shalousun | 8e9c91e101 | |
shalousun | b7a42bcb8d | |
xingzi | 129b603eff | |
shalousun | 7415c19c90 | |
shalousun | 8e2b86b39d | |
shalousun | b1afdea45e | |
shalousun | 5c79eeb4e2 | |
shalousun | 4c45a17f65 | |
shalousun | 5f67a3d727 | |
shalousun | 69e6859cfc | |
shalousun | c59d58134a | |
shalousun | 9b9451e41f | |
shalousun | 777eab2fcd | |
shalousun | b50f84f142 | |
songhaozhi | 489cd11a22 | |
shalousun | 7019620c01 | |
shalousun | 01cd6f18d3 | |
shalousun | ee230dcd62 | |
songhaozhi | 3ba32a65f2 | |
songhaozhi | 84c9af7a1f | |
shalousun | 3f63bf3310 | |
shalousun | 219f16c5f5 | |
songhaozhi | 021c5253cd | |
songhaozhi | 7064028106 | |
shalousun | 86fc20031c | |
shalousun | 4290104f5c | |
shalousun | 5a147bac10 | |
shalousun | 83c492bce1 | |
shalousun | 63107fd075 | |
shalousun | 118fd81080 | |
shalousun | 4972dfb4fb | |
shalousun | c815f12d06 | |
Forget | ed273cebf4 | |
shalousun | 3c5330e8f3 | |
shalousun | 5f0e156890 | |
xingzi | 8932f145c8 | |
xingzi | 764584d479 | |
shalousun | 18c28ed965 | |
shalousun | 357a3e2be8 | |
shalousun | 8850c08c70 | |
shalousun | 761edaf434 | |
shalousun | 0a9f6223b1 | |
xingzi | e4c1863a66 | |
shalousun | 2eb97081d2 | |
shalousun | d837bfd77f | |
Forget | 37bcd3ff7c | |
shalousun | c9441c6469 | |
shalousun | 05f1432cc3 | |
shalousun | e67e46427e | |
shalousun | 5933e2ff17 | |
shalousun | 3597732de8 | |
Forget | 660eb38042 | |
shalousun | e4ba5ec4ae | |
shalousun | 9d957ef62e | |
shalousun | e6069fc911 |
|
@ -1,43 +1,37 @@
|
|||
---
|
||||
name: Bug report 🐞 about: Create a report to help us improve title: ''
|
||||
labels: bug assignees: ''
|
||||
name: Bug report 🐞
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## Your Environment(您的使用环境)
|
||||
|
||||
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||
|
||||
* smart-doc version:
|
||||
* plugin version (e.g. smart-doc-maven-plugin or smart-doc-gradle-plugin):
|
||||
* build tool version(maven or gradle):
|
||||
|
||||
## Expected Behavior(您期望的结果)
|
||||
|
||||
<!--- If you're describing a bug, tell us what should happen -->
|
||||
<!--- If you're suggesting a change/improvement, tell us how it should work -->
|
||||
|
||||
## Current Behavior(当前结果)
|
||||
|
||||
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
|
||||
|
||||
## Possible Solution(bug解决建议)
|
||||
|
||||
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
||||
<!--- or ideas how to implement the addition or change -->
|
||||
|
||||
## Steps to Reproduce (Bug产生步骤,请尽量提供用例代码)
|
||||
|
||||
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
|
||||
<!--- reproduce this bug. Include code to reproduce, if relevant -->
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
|
||||
## Context(Bug影响描述)
|
||||
|
||||
<!--- How has this issue affected you? What are you trying to accomplish? -->
|
||||
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
---
|
||||
name: Feature Request 💡 about: Suggest a new idea for the project. labels: enhancement
|
||||
name: Feature Request 💡
|
||||
about: Suggest a new idea for the project.
|
||||
labels: enhancement
|
||||
---
|
||||
|
||||
## Summary(关于这个pr的描述)
|
||||
|
|
166
CHANGELOG.md
166
CHANGELOG.md
|
@ -1,8 +1,140 @@
|
|||
## smart-doc版本
|
||||
|
||||
#### 版本号:2.3.2
|
||||
- 更新日期: 2021-11-21
|
||||
- 更新内容:
|
||||
1. 修复debug调试页搜索后目录锚点错误。
|
||||
2. 修复生成openapi时List<String>等基本类型数组入参时类型转换错误。
|
||||
3. 优化泛型类型显示,当泛型类型的实参类型是基本类型时直接显示为基本类型。
|
||||
4. 新增对@RequestAttribute参数的忽略。
|
||||
5. 修复@RequstBody使用基本类型时的请求参数示例错误
|
||||
|
||||
#### 版本号:2.3.1
|
||||
- 更新日期: 2021-11-13
|
||||
- 更新内容:
|
||||
1. 修复debug调试不支持请求头设置中文值的bug。
|
||||
2. 修复response自定义tag设置返回未格式化换行问题。
|
||||
3. 修复枚举类型字段指定mock不生效的问题。
|
||||
4. 新增对@SessionAttribute参数做忽略。
|
||||
5. 支持controller实现接口,并使用default方法。
|
||||
|
||||
#### 版本号:2.3.0
|
||||
- 更新日期: 2021-11-07
|
||||
- 更新内容:
|
||||
1. 修复创建html文档丢失search.js文件问题。
|
||||
2. 修复packageFilters配置多个包时只有第一个生效的问题。
|
||||
3. 修复debug调试页面的curl指令错误。
|
||||
4. 修复设置了下载文件接口加download标记后,数据并未生效的bug。
|
||||
5. 优化一些部分常见字段的随机值生成。
|
||||
#### 版本号:2.2.9
|
||||
- 更新日期: 2021-10-31
|
||||
- 更新内容:
|
||||
1. 修复生成openapi文件上传错误问题。
|
||||
2. 修复文件上传接口推送到torna参数被放置到query参数列表的问题。
|
||||
3. 修改List<T>类型参数推送到torna错误的问题
|
||||
4. 优化outPath配置,只使用torna推送时可以不再要求配置outPath项。
|
||||
|
||||
#### 版本号:2.2.8
|
||||
- 更新日期: 2021-10-07
|
||||
- 更新内容:
|
||||
1. 修复html文档无接口注释时锚点跳转错误的问题。
|
||||
2. 修复导出postman时服务端口配置成变量报错的问题。
|
||||
|
||||
#### 版本号:2.2.7
|
||||
- 更新日期: 2021-09-12
|
||||
- 更新内容:
|
||||
1. 修复dubbo文档css连接错误。
|
||||
2. 修复分组后组归错误。
|
||||
3. 修复路径常量相似度时替换错误的bug。
|
||||
4. JSR303分组优化,标记Null的分组字段将不再显示在文档中 。
|
||||
#### 版本号:2.2.6
|
||||
- 更新日期: 2021-09-05
|
||||
- 更新内容:
|
||||
1. 修复html文档静态资源链接错误。
|
||||
2. 不配置分组时不显示分组。
|
||||
3. 修复分组后目录item搜索错误。
|
||||
4. 优化maven插件提示 。
|
||||
#### 版本号:2.2.5
|
||||
- 更新日期: 2021-08-08
|
||||
- 更新内容:
|
||||
1. 支持在html文档中不显示参数列表。
|
||||
2. html文档使用的资源全部改成本地引用。
|
||||
3. 修复Boolean类型字段命名为is前缀时,is前缀被去除的bug。
|
||||
4. 修复配置了字典码列表后枚举字段注释显示错误#139 。
|
||||
5. 修复分析过程中出现的数组越界异常 。
|
||||
6. 新增接口分组支持。
|
||||
#### 版本号:2.2.4
|
||||
|
||||
- 更新日期: 2021-08-08
|
||||
- 更新内容:
|
||||
1. 修复字典码推送torna错误 #https://gitee.com/smart-doc-team/smart-doc/issues/I43JQR。
|
||||
2. 新增jsr303 @size和@length支持。
|
||||
3. 修改html的模板样式错误。
|
||||
4. 修复postman错误#I41G2E 。
|
||||
5. 新增isReplace配置 。
|
||||
6. 修复当存在多个jsr注解时,部分注解失效问题。
|
||||
#### 版本号:2.2.3
|
||||
|
||||
- 更新日期: 2021-07-18
|
||||
- 更新内容:
|
||||
1. 增加pathPrefix配置项用于配置上下文,引入该配置项后serverUrl仅用于配置服务器地址。
|
||||
2. 支持请求头常量设置解析。
|
||||
3. 支持使用JsonIgnoreProperties和JSONType注解去忽略多字段。
|
||||
4. 修改部分文档设置allInOneDocFileName无效的问题,#131 。
|
||||
5. 修复dubbo rpc文档模板格式错误 #https://gitee.com/smart-doc-team/smart-doc/issues/I40ZGE .
|
||||
6. 支持配置添加拦截器中设置全局请求参数,#https://github.com/smart-doc-group/smart-doc/issues/132 .
|
||||
7. 修复部分类型mock未推送到torna的问题。
|
||||
|
||||
#### 版本号:2.2.2
|
||||
|
||||
- 更新日期: 2021-07-04
|
||||
- 更新内容:
|
||||
1. 修复url中遇到正则表达解析错误问题.
|
||||
2. 修复生成的json样例部分格式化后错误的bug,gitee #I3XSE5。
|
||||
3. 增强对文档中html特殊字符的处理,防止html渲染后显示错误,gitee #I3XO31。
|
||||
4. 请求头设置增强,支持配置urlPatterns和excludePathPatterns两个属性去匹配对应的接口。
|
||||
5. 优化了maven插件的提示,优化后可以将加载了那些目录模块代码路径打印。
|
||||
6. 提供了其它框架扩展文档解析的能力。
|
||||
7. 修复doc模板错误,gitee #I3Y640。
|
||||
8. 修复字典模板错误,#119。
|
||||
9. 添加忽略HttpServlet对象。
|
||||
10. 支持内置替换Jpa Pageable分页对象,去除不必要的请求参数替换配置。
|
||||
11. packageFilters增强,可使用正则进行匹配,gitee #I3YKZ4 。
|
||||
12. 修复dubbo rpc文档推送到torna数据错误。
|
||||
13. 修复customResponseFields和customRequestFields设置时不同类同名字段覆盖bug,gitee #I3Y6AL。
|
||||
14. 修复高版本gradle中使用implements添加依赖时,gradle插件无法加载依赖导致返回空json的bug。
|
||||
#### 版本号:2.2.1
|
||||
|
||||
- 更新日期: 2021-06-20
|
||||
- 更新内容:
|
||||
1. 移除代码中System.out.print打印.
|
||||
|
||||
#### 版本号:2.2.0
|
||||
|
||||
- 更新日期: 2021-06-20
|
||||
- 更新内容:
|
||||
1. 修复参数多行注释时,注释提取错误,gitee #I3TYYP.
|
||||
2. 修复部分代码可能出现的空指针问题。
|
||||
3. 添加@response tag。支持自己设置response example
|
||||
4. 修复推送到torna请求或返回为数组时,示例显示错误
|
||||
5. Character类型解析支持。
|
||||
6. 修复使用Quartz中JobDataMap类型解析错误。
|
||||
7. 移除YapiBuilder。smart-doc不在支持其他第三方接口系统,请使用torna.
|
||||
#### 版本号:2.1.9
|
||||
|
||||
- 更新日期: 2021-05-29
|
||||
- 更新内容:
|
||||
1. 修复inlineEnum为false时枚举展示在参数中的问题。
|
||||
2. 返回Spring文件下载对象支持自动识别为文件下载,减少手动标记@download tag。
|
||||
3. smart-doc使用的css cdn更换,默认使用国内cdn,提升国内的加载速度,切换英文环境使用google的cdn.
|
||||
4. 添加多层泛型嵌套的解析支持。gitee #I3T6UV .
|
||||
5. 修复父类是泛型时父类中LocalDateTime类型字段生成json样例错误。
|
||||
6. 添加将接口排序order推送到torna中。
|
||||
7. 修复类上的@ignore tag不生效bug.
|
||||
8. 优化字典码推送,空字典码不会像torna发起推送请求。
|
||||
#### 版本号:2.1.8
|
||||
|
||||
- 更新日期: 2020-05-17
|
||||
- 更新日期: 2021-05-22
|
||||
- 更新内容:
|
||||
1. 修复推送接口到torna丢失部分mock值的问题。
|
||||
2. 修复在参数注释中配置类替换时将非类名解析成类名的bug 。
|
||||
|
@ -11,17 +143,17 @@
|
|||
5. 修复maven插件torna-rest和torna-rpc两个task未加编译前缀的问题。
|
||||
6. 修复生成json用例中数组类型json错误的问题。
|
||||
7. 修复customRequestFields中设置字段value在用例中不生效的bug。
|
||||
|
||||
8. 添加@JsonProperty支持,支持JsonProperty.Access控制字段。
|
||||
#### 版本号:2.1.7
|
||||
|
||||
- 更新日期: 2020-05-12
|
||||
- 更新日期: 2021-05-12
|
||||
- 更新内容:
|
||||
1. 添加推送接口作者信息到torna数据错误的bug。
|
||||
2. 修复空参数curl命令多余?号问题,github 。
|
||||
|
||||
#### 版本号:2.1.6
|
||||
|
||||
- 更新日期: 2020-05-10
|
||||
- 更新日期: 2021-05-10
|
||||
- 更新内容:
|
||||
1. 修复不允许List中放文件上传对象错误的bug。
|
||||
2. 添加推送接口作者信息到torna,通过配置author设置推送人,不配置默认为计算机用户名。
|
||||
|
@ -29,14 +161,14 @@
|
|||
|
||||
#### 版本号:2.1.5
|
||||
|
||||
- 更新日期: 2020-05-05
|
||||
- 更新日期: 2021-05-05
|
||||
- 更新内容:
|
||||
1. 修复requestBodyAdvice请求样例丢之。
|
||||
2. 添加dubbo文档到torna的推送。
|
||||
|
||||
#### 版本号:2.1.4
|
||||
|
||||
- 更新日期: 2020-04-24
|
||||
- 更新日期: 2021-04-24
|
||||
- 更新内容:
|
||||
1. 修复Controller继承时,父类的Mapping未继承的问题。
|
||||
2. 修复配置responseBodyAdvice后,controller中void方法返回显示错误。
|
||||
|
@ -48,7 +180,7 @@
|
|||
|
||||
#### 版本号:2.1.3
|
||||
|
||||
- 更新日期: 2020-04-11
|
||||
- 更新日期: 2021-04-11
|
||||
- 更新内容:
|
||||
1. 增强对文件上传的支持。
|
||||
2. 增加customRequestFields配置项,#97。
|
||||
|
@ -58,21 +190,21 @@
|
|||
|
||||
#### 版本号:2.1.2
|
||||
|
||||
- 更新日期: 2020-03-29
|
||||
- 更新日期: 2021-03-29
|
||||
- 更新内容:
|
||||
1. 修复Map嵌套在某些结构体中栈溢出问题,gitee #I3CCLY。
|
||||
2. 修复Torna数据推送问题。
|
||||
|
||||
#### 版本号:2.1.1
|
||||
|
||||
- 更新日期: 2020-03-24
|
||||
- 更新日期: 2021-03-24
|
||||
- 更新内容:
|
||||
1. 修复Map嵌套在某些结构体中栈溢出问题,gitee #I3CCLY。
|
||||
2. 修复Torna数据推送问题。
|
||||
|
||||
#### 版本号:2.1.0
|
||||
|
||||
- 更新日期: 2020-03-21
|
||||
- 更新日期: 2021-03-21
|
||||
- 更新内容:
|
||||
1. 导出的postman的url资源下添加缺失的protocol。
|
||||
2. 增加@ignoreParams自定义tag来过滤掉不想显示在文档中参数。
|
||||
|
@ -82,7 +214,7 @@
|
|||
|
||||
#### 版本号:2.0.9
|
||||
|
||||
- 更新日期: 2020-03-12
|
||||
- 更新日期: 2021-03-12
|
||||
- 更新内容:
|
||||
1. 支持UUID和ZonedDateTime字段类型,#89。
|
||||
2. 对map参数增加开关来兼容旧项目,还是不建议使用map参数。
|
||||
|
@ -90,7 +222,7 @@
|
|||
|
||||
#### 版本号:2.0.8
|
||||
|
||||
- 更新日期: 2020-02-26
|
||||
- 更新日期: 2021-02-26
|
||||
- 更新内容:
|
||||
1. 修复文件上传的参数丢失的注释。
|
||||
2. 修复2.0.7新增忽略接口方法后解析父类字段缺失注释bug。
|
||||
|
@ -98,7 +230,7 @@
|
|||
|
||||
#### 版本号:2.0.7
|
||||
|
||||
- 更新日期: 2020-01-30
|
||||
- 更新日期: 2021-01-30
|
||||
- 更新内容:
|
||||
1. 修复postman的url中不附加的context-path的问题。
|
||||
2. 修复带正则的path路径参数解析出现截取越界的问题。
|
||||
|
@ -108,21 +240,21 @@
|
|||
|
||||
#### 版本号:2.0.6
|
||||
|
||||
- 更新日期: 2020-01-15
|
||||
- 更新日期: 2021-01-15
|
||||
- 更新内容:
|
||||
1. 修复带正则的path路径参数在postman中用例问题。
|
||||
2. 增强对祖传不良代码的分析兼容。
|
||||
|
||||
#### 版本号:2.0.5
|
||||
|
||||
- 更新日期: 2020-01-09
|
||||
- 更新日期: 2021-01-09
|
||||
- 更新内容:
|
||||
1. 修复集合类无泛型参数作为入参出参时的数组越界。
|
||||
2. 修复新开tab访问的url拼接问题。
|
||||
|
||||
#### 版本号:2.0.3-2.0.4
|
||||
|
||||
- 更新日期: 2020-01-01
|
||||
- 更新日期: 2021-01-01
|
||||
- 更新内容:
|
||||
1. 修改页面的错误列表标题显示。
|
||||
2. 修改debug页面curl header语法错误。
|
||||
|
@ -131,7 +263,7 @@
|
|||
|
||||
#### 版本号:2.0.2
|
||||
|
||||
- 更新日期: 2020-02-27
|
||||
- 更新日期: 2020-12-27
|
||||
- 更新内容:
|
||||
1. 修改创建openapi时的空指针异常。
|
||||
2. 修改debug页面时未使用mock值的问题。
|
||||
|
|
266
README.md
266
README.md
|
@ -5,7 +5,7 @@
|
|||
![number of issues closed](https://img.shields.io/github/issues-closed-raw/shalousun/smart-doc)
|
||||
![closed pull requests](https://img.shields.io/github/issues-pr-closed/shalousun/smart-doc)
|
||||
![java version](https://img.shields.io/badge/JAVA-1.8+-green.svg)
|
||||
[![chinese](https://img.shields.io/badge/chinese-中文文档-brightgreen)](https://github.com/shalousun/smart-doc/blob/master/README_CN.md)
|
||||
[![chinese](https://img.shields.io/badge/chinese-中文文档-brightgreen)](https://smart-doc-group.github.io/#/zh-cn/)
|
||||
|
||||
## Introduce
|
||||
|
||||
|
@ -14,6 +14,7 @@ based on interface source code analysis to generate interface documents, and zer
|
|||
write Javadoc comments when developing, smart-doc can help you generate Markdown or HTML5 document. smart-doc does not
|
||||
need to inject annotations into the code like Swagger.
|
||||
|
||||
[quick start](https://smart-doc-group.github.io/#/)
|
||||
## Features
|
||||
|
||||
- Zero annotation, zero learning cost, only need to write standard JAVA document comments.
|
||||
|
@ -36,252 +37,7 @@ smart-doc + [Torna](http://torna.cn) form an industry-leading document generatio
|
|||
smart-doc to complete Java source code analysis and extract annotations to generate API documents without intrusion, and
|
||||
automatically push the documents to the Torna enterprise-level interface document management platform.
|
||||
|
||||
![smart-doc+torna](https://raw.githubusercontent.com/shalousun/smart-doc/master/images/smart-doc-torna.png)
|
||||
|
||||
## Getting Started
|
||||
|
||||
[Smart-doc Samples](https://github.com/shalousun/smart-doc-demo.git)。
|
||||
|
||||
```
|
||||
# git clone https://github.com/shalousun/smart-doc-demo.git
|
||||
```
|
||||
|
||||
This example already provides a static html document generated in advance. You can start the Spring Boot project and
|
||||
then go directly to `http://localhost:8080/doc/api.html` to view the interface documentation generated by smart-doc. Of
|
||||
course, you can also browse `http://localhost:8080/doc/api.html`, which looks a html like generated
|
||||
by `asciidoctor-maven-plugin` plugin.
|
||||
|
||||
### Add Maven Plugin
|
||||
|
||||
Add [smart-doc-maven-plugin](https://github.com/smart-doc-group/smart-doc-maven-plugin) in your pom.xml.
|
||||
|
||||
```
|
||||
<plugin>
|
||||
<groupId>com.github.shalousun</groupId>
|
||||
<artifactId>smart-doc-maven-plugin</artifactId>
|
||||
<version>[latest]</version>
|
||||
<configuration>
|
||||
<!--Specify the configuration file used to generate the document-->
|
||||
<configFile>./src/main/resources/smart-doc.json</configFile>
|
||||
<!--smart-doc implements automatic analysis of the dependency tree to load the source code of third-party dependencies. If some framework dependency libraries are not loaded, an error is reported, then use excludes to exclude-->
|
||||
<excludes>
|
||||
<!--The format is: groupId: artifactId; refer to the following-->
|
||||
<exclude>com.google.guava:guava</exclude>
|
||||
</excludes>
|
||||
<!--Since version 1.0.8, the plugin provides includes support-->
|
||||
<!--smart-doc can automatically analyze the dependency tree to load all dependent source code. In principle, it will affect the efficiency of document construction, so you can use includes to let the plugin load the components you configure.-->
|
||||
<includes>
|
||||
<!--The format is: groupId: artifactId; refer to the following-->
|
||||
<include>com.alibaba:fastjson</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<!--Comment out phase if you don't need to start smart-doc when compiling-->
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<!--smart-doc provides html, openapi, markdown, adoc and other goals-->
|
||||
<goal>html</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Create a JSON configuration file in your project. The smart-doc-maven-plugin plugin will use this configuration
|
||||
information. For example, create `/src/main/resources/smart-doc.json` in the project. The configuration contents are as
|
||||
follows.
|
||||
|
||||
**Minimize configuration:**
|
||||
|
||||
```
|
||||
{
|
||||
"allInOne": true, // whether to merge documents into one file, generally recommended as true
|
||||
"isStrict": false,//If the strict mode is set to true, Smart-doc forces that the public method in each interface in the code has a comment.
|
||||
"outPath": "src/main/resources/static/doc" //Set the api document output path.
|
||||
}
|
||||
```
|
||||
|
||||
Only the above three simple configuration items can make smart-doc-maven-plugin work. In fact, only the outPath
|
||||
configuration item is necessary.
|
||||
|
||||
**Detailed configuration content:**
|
||||
|
||||
When you need to use smart-doc to generate more API document information, you can add detailed configuration content.
|
||||
|
||||
```
|
||||
{
|
||||
"serverUrl": "http://127.0.0.1", // Set the server address, not required
|
||||
"isStrict": false, // whether to enable strict mode
|
||||
"allInOne": true, // whether to merge documents into one file, generally recommended as true
|
||||
"outPath": "D: // md2", // Specify the output path of the document
|
||||
"coverOld": true, // Whether to overwrite old files, mainly used for mardown file overwrite
|
||||
"style":"xt256", //set highlight
|
||||
"createDebugPage": true,//Create a page that can be used to test your APIs like swagger
|
||||
"language":"ENGLISH",//support ENGLISH and CHINESE
|
||||
"packageFilters": "", // controller package filtering, multiple package names separated by commas
|
||||
"md5EncryptedHtmlName": false, // only used if each controller generates an html file
|
||||
"projectName": "smart-doc", // Configure your own project name
|
||||
"skipTransientField": true, // Not currently implemented
|
||||
"requestFieldToUnderline":true, //convert request field to underline
|
||||
"responseFieldToUnderline":true,//convert response field to underline
|
||||
"sortByTitle":false,//Sort by interface title, the default value is false
|
||||
"showAuthor":true,// display author,default is true
|
||||
"inlineEnum":true,// Set to true to display enumeration details in the parameter table
|
||||
"recursionLimit":7,// Set the number of recursive executions to avoid stack overflow, the default is 7
|
||||
"allInOneDocFileName":"index.html",//Customize the output document name
|
||||
"requestExample":"true",//Whether to display the request example in the document, the default value is true.
|
||||
"responseExample":"true",//Whether to display the response example in the document, the default is true.
|
||||
"displayActualType":false,//display actual type of generic,
|
||||
"urlSuffix":".do",//Support the url suffix of the old SpringMVC project,@since 2.1.0
|
||||
"appKey": "xxx",// torna appKey, @since 2.0.9
|
||||
"appToken": "xxx", //torna appToken,@since 2.0.9
|
||||
"secret": "xx",//torna secret,@since 2.0.9
|
||||
"openUrl": "torna server/api/",//torna server url,@since 2.0.9
|
||||
"tornaDebug":false,"// show log while set true
|
||||
"ignoreRequestParams":[ //The request parameter object will be discarded when generating the document.@since 1.9.2
|
||||
"org.springframework.ui.ModelMap"
|
||||
],
|
||||
"dataDictionaries": [{// Configure the data dictionary, no need to set
|
||||
"title": "Order Status", // The name of the data dictionary
|
||||
"enumClassName": "com.power.doc.enums.OrderEnum", // Data dictionary enumeration class name
|
||||
"codeField": "code", // The field name corresponding to the data dictionary dictionary code
|
||||
"descField": "desc" // Data dictionary object description information dictionary
|
||||
}],
|
||||
"errorCodeDictionaries": [{// error code list, no need to set
|
||||
"title": "title",
|
||||
"enumClassName": "com.power.doc.enums.ErrorCodeEnum", // Error code enumeration class
|
||||
"codeField": "code", // Code field name of the error code
|
||||
"descField": "desc" // Field name corresponding to the error code description
|
||||
}],
|
||||
"revisionLogs": [{// Set document change records, no need to set
|
||||
"version": "1.0", // Document version number
|
||||
"revisionTime": "2020-12-31 10:30", //revision time
|
||||
"author": "author", // Document change author
|
||||
"status": "update", // Change operation status, generally: create, update, etc.
|
||||
"remarks": "desc" // Change description
|
||||
}],
|
||||
"customResponseFields": [{// Customly add fields and comments. If api-doc encounters a field with the same name later, directly add a comment to the corresponding field. It is not necessary.
|
||||
"name": "code", // Override the response code field
|
||||
"desc": "Response code", // Override field comment of response code
|
||||
"value": "00000" // Set the value of the response code
|
||||
}],
|
||||
"customRequestFields": [{//@since 2.1.3
|
||||
"name":"code", //Override the request code field
|
||||
"desc":"request code", //Override field comment of response code
|
||||
"ownerClassName":"com.xxx.constant.entity.Result",
|
||||
"value":"200", // Set the value of the response code
|
||||
"required":true,
|
||||
"ignore":false
|
||||
}],
|
||||
"apiObjectReplacements": [{ // Supports replacing specified objects with custom objects to complete document rendering
|
||||
"className": "org.springframework.data.domain.Pageable",
|
||||
"replacementClassName": "com.power.doc.model.PageRequestDto" //Use custom PageRequestDto instead of JPA Pageable for document rendering.
|
||||
}],
|
||||
"rpcApiDependencies":[{ // Your Apache Dubbo api interface module dependency description.
|
||||
"artifactId":"SpringBoot2-Dubbo-Api",
|
||||
"groupId":"com.demo",
|
||||
"version":"1.0.0"
|
||||
}],
|
||||
"apiConstants": [{//Configure your own constant class, smart-doc automatically replaces with a specific value when parsing to a constant
|
||||
"constantsClassName": "com.power.doc.constants.RequestParamConstant"
|
||||
}],
|
||||
"responseBodyAdvice":{ //Support ResponseBodyAdvice
|
||||
"className":"com.power.common.model.CommonResult" // Standard POJO for Response
|
||||
},
|
||||
"requestBodyAdvice":{ //Support ResponseBodyAdvice
|
||||
"className":"com.power.common.model.CommonResult" // Standard POJO for Request
|
||||
},
|
||||
"rpcConsumerConfig": "src/main/resources/consumer-example.conf",//dubbo consumer config example
|
||||
"requestHeaders": [{// Set global request headers, no need to set
|
||||
"name": "token",
|
||||
"type": "string",
|
||||
"desc": "desc",
|
||||
"required": false,
|
||||
"since": "-"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** This JSON configuration can be converted into JSON using smart-doc's ApiConfig Object. So the project
|
||||
configuration can also refer to the introduction of smart-doc.
|
||||
|
||||
### Generated document
|
||||
|
||||
#### Run Plugin with MAVEN command
|
||||
|
||||
```
|
||||
// Generate html
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:html
|
||||
// Generate markdown
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:markdown
|
||||
// Generate adoc
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:adoc
|
||||
// Generate postman collection
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:postman
|
||||
// Generate document and send to Torna
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:torna-rest
|
||||
|
||||
// Apache Dubbo RPC
|
||||
// Generate html
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-html
|
||||
// Generate markdown
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-markdown
|
||||
// Generate adoc
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-adoc
|
||||
// Push dubbo rpc document to Torna
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:torna-rpc
|
||||
```
|
||||
|
||||
**Note:** Under the window system, if you use the maven command line to perform document generation, non-English
|
||||
characters may be garbled, so you need to specify `-Dfile.encoding = UTF-8` during execution.
|
||||
|
||||
View maven's coding
|
||||
|
||||
```
|
||||
# mvn -version
|
||||
Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T19:57:37+08:00)
|
||||
Maven home: D:\ProgramFiles\maven\bin\..
|
||||
Java version: 1.8.0_191, vendor: Oracle Corporation
|
||||
Java home: D:\ProgramFiles\Java\jdk1.8.0_191\jre
|
||||
Default locale: zh_CN, platform encoding: GBK
|
||||
OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos"
|
||||
```
|
||||
|
||||
#### Run Plugin in IDEA
|
||||
|
||||
On Use IntelliJ IDE, if you have added smart-doc-maven-plugin to the project, you can directly find the plugin smart-doc
|
||||
plugin and click to generate API documentation.
|
||||
|
||||
![smart-doc-maven-plugin](https://raw.githubusercontent.com/shalousun/smart-doc-maven-plugin/master/images/idea.png)
|
||||
|
||||
### Use Gradle Plugin
|
||||
|
||||
If you use gradle to build the project, you can refer to the documentation of the gradle plugin to integrate,
|
||||
[smart-doc-gradle-plugin](https://github.com/smart-doc-group/smart-doc-gradle-plugin/blob/master/README.md)
|
||||
|
||||
### Generated document example
|
||||
|
||||
#### Interface header rendering
|
||||
|
||||
![header](https://images.gitee.com/uploads/images/2019/1231/223538_be45f8a9_144669.png "header.png")
|
||||
|
||||
#### Request parameter example rendering
|
||||
|
||||
![request-params](https://images.gitee.com/uploads/images/2019/1231/223710_88933f55_144669.png "request.png")
|
||||
|
||||
#### Response parameter example renderings
|
||||
|
||||
![response-fields](https://images.gitee.com/uploads/images/2019/1231/223817_32bea6dc_144669.png "response.png")
|
||||
|
||||
## Integration through unit tests
|
||||
|
||||
You can generate documentation by adding smart-doc dependencies directly to your project and then writing unit tests to
|
||||
start smart-doc. we still recommend that you use the smart-doc-maven-plugin plugin.
|
||||
|
||||
[Use smart-doc by junit test](https://github.com/smart-doc-group/smart-doc/wiki/Use-smart-doc-by-junit-test)
|
||||
![smart-doc+torna](https://raw.githubusercontent.com/shalousun/smart-doc/master/images/smart-doc-torna-en.png)
|
||||
|
||||
## Building
|
||||
|
||||
|
@ -295,28 +51,30 @@ mvn clean install -Dmaven.test.skip=true
|
|||
|
||||
- Jakarta RS-API 2.x
|
||||
|
||||
## Other reference
|
||||
|
||||
- [Smart-doc manual](https://github.com/shalousun/smart-doc/wiki)
|
||||
|
||||
## Who is using
|
||||
|
||||
These are only part of the companies using smart-doc, for reference only. If you are using smart-doc,
|
||||
please [add your company here](https://github.com/shalousun/smart-doc/issues/12) to tell us your scenario to make
|
||||
please [add your company here](https://github.com/smart-doc-group/smart-doc/issues/12) to tell us your scenario to make
|
||||
smart-doc better.
|
||||
|
||||
![IFLYTEK](https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/iflytek.png)
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/oneplus.png" title="OnePlus" width="83px" height="83px"/>
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/xiaomi.png" title="Xiaomi" width="170px" height="83px"/>
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/yuanmengjiankang.png" title="yuanmengjiankang" width="260px" height="83px"/>
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/neusoft.png" title="东软集团" width="170px" height="83px"/>
|
||||
<img src="https://www.hand-china.com/static/img/hand-logo.svg" title="上海汉得信息技术股份有限公司" width="260px" height="83px"/>
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/shunfeng.png" title="顺丰" width="83px" height="83px"/>
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/zhongkezhilian.png" title="zhongkezhilian" width="272px" height="83px"/>
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/yuanmengjiankang.png" title="yuanmengjiankang" width="260px" height="83px"/>
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/puqie_gaitubao_100x100.jpg" title="puqie" width="83px" height="83px"/>
|
||||
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/tianbo-tech.png" title="tianbo tech" width="127px" height="70px"/>
|
||||
|
||||
## Acknowledgements
|
||||
Thanks to [JetBrains SoftWare](https://www.jetbrains.com) for providing free Open Source license for this open source project.
|
||||
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/jetbrains-variant-3.png" width="260px" height="220px"/>
|
||||
## License
|
||||
|
||||
Smart-doc is under the Apache 2.0 license. See the [LICENSE](https://github.com/shalousun/smart-doc/blob/master/LICENSE)
|
||||
Smart-doc is under the Apache 2.0 license. See the [LICENSE](https://github.com/smart-doc-group/smart-doc/blob/master/LICENSE)
|
||||
file for details.
|
||||
|
||||
## Contact
|
||||
|
|
260
README_CN.md
260
README_CN.md
|
@ -14,8 +14,8 @@ Collection2.0+、OpenAPI 3.0+的文档。
|
|||
$\color{red}{你给我的star,胜过所有读过的诗—smart-doc}$
|
||||
|
||||
> 无论你是很有经验的大佬、还是刚入行的萌新。遇到使用疑惑时,我们希望你能仔细阅读smart-doc官方码云的wiki文档。我们将smart-doc及其插件的 每一个配置项和可能在日常中遇到的问题都整理到了文档中。仔细阅读文档就是对开源项目最大的支持。
|
||||
[wiki文档](https://gitee.com/smart-doc-team/smart-doc/wikis/HOME?sort_id=3127893)
|
||||
|
||||
查看[快速开始](https://smart-doc-group.github.io/#/zh-cn/) 了解详情
|
||||
## Features
|
||||
|
||||
- 零注解、零学习成本、只需要写标准JAVA注释。
|
||||
|
@ -43,234 +43,6 @@ smart-doc + [Torna](http://torna.cn) 组成行业领先的文档生成和管理
|
|||
|
||||
> Torna是由smart-doc官方独家推动联合研发的企业级文档管理系统,因此smart-doc官方不会对接其它任何的外部文档管理系统,例如像showdoc、yapi 之类的对接请自定内部处理,也不要再给我们提其他文档系统对接的PR。我们核心是把smart-doc+Torna的这套方案打造好。
|
||||
|
||||
## Getting Started
|
||||
|
||||
smart-doc使用和测试可参考[smart-doc demo](https://gitee.com/devin-alan/api-doc-test.git)。
|
||||
|
||||
```
|
||||
# git clone https://gitee.com/devin-alan/api-doc-test.git
|
||||
```
|
||||
|
||||
你可以启动这个Spring Boot的项目,然后访问`http://localhost:8080/doc/api.html`来浏览smart-doc生成的接口文档。
|
||||
|
||||
### Add Maven Plugin
|
||||
|
||||
smart-doc官方目前已经开发完成[Maven插件](https://gitee.com/smart-doc-team/smart-doc-maven-plugin)
|
||||
和[Gradle插件](https://gitee.com/smart-doc-team/smart-doc-gradle-plugin),
|
||||
你可以根据自己的构建工具来选择使用Maven插件或者是Gradle插件。
|
||||
|
||||
#### Add Plugin
|
||||
|
||||
```
|
||||
<plugin>
|
||||
<groupId>com.github.shalousun</groupId>
|
||||
<artifactId>smart-doc-maven-plugin</artifactId>
|
||||
<version>[最新版本]</version>
|
||||
<configuration>
|
||||
<!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
|
||||
<configFile>./src/main/resources/smart-doc.json</configFile>
|
||||
<!--指定项目名称-->
|
||||
<projectName>测试</projectName>
|
||||
<!--smart-doc实现自动分析依赖树加载第三方依赖的源码,如果一些框架依赖库加载不到导致报错,这时请使用excludes排除掉-->
|
||||
<excludes>
|
||||
<!--格式为:groupId:artifactId;参考如下-->
|
||||
<exclude>com.alibaba:fastjson</exclude>
|
||||
</excludes>
|
||||
<!--自1.0.8版本开始,插件提供includes支持-->
|
||||
<!--smart-doc能自动分析依赖树加载所有依赖源码,原则上会影响文档构建效率,因此你可以使用includes来让插件加载你配置的组件-->
|
||||
<includes>
|
||||
<!--格式为:groupId:artifactId;参考如下-->
|
||||
<include>com.alibaba:fastjson</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<!--如果不需要在执行编译时启动smart-doc,则将phase注释掉-->
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<!--smart-doc提供了html、openapi、markdown等goal,可按需配置-->
|
||||
<goal>html</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
|
||||
在项目中添加创建一个`smart-doc.json`配置文件,插件读取这个配置来生成项目的文档, 这个配置内容实际上就是以前采用单元测试编写的`ApiConfig`转成json后的结果,因此关于配置项说明可以参考原来单元测试的配置。
|
||||
|
||||
**最小配置单元:**
|
||||
|
||||
```
|
||||
{
|
||||
"outPath": "D://md2" //指定文档的输出路径,相对路径时请用./开头,eg:./src/main/resources/static/doc
|
||||
}
|
||||
```
|
||||
|
||||
> 如果你想把html文档也打包到应用中一起访问,则建议你配置路径为:src/main/resources/static/doc
|
||||
|
||||
仅仅需要上面一行配置就能启动smart-doc-maven-plugin插件,根据自己项目情况更多详细的配置参考下面。
|
||||
**详细配置说明**
|
||||
|
||||
```
|
||||
{
|
||||
"serverUrl": "http://127.0.0.1", //服务器地址,非必须。导出postman建议设置成http://{{server}}方便直接在postman直接设置环境变量
|
||||
"isStrict": false, //是否开启严格模式
|
||||
"allInOne": true, //是否将文档合并到一个文件中,一般推荐为true
|
||||
"outPath": "D://md2", //指定文档的输出路径
|
||||
"coverOld": true, //是否覆盖旧的文件,主要用于mardown文件覆盖
|
||||
"createDebugPage": true,//@since 2.0.0 smart-doc支持创建可以测试的html页面,仅在AllInOne模式中起作用。
|
||||
"packageFilters": "",//controller包过滤,多个包用英文逗号隔开
|
||||
"md5EncryptedHtmlName": false,//只有每个controller生成一个html文件是才使用
|
||||
"style":"xt256", //基于highlight.js的代码高设置,可选值很多可查看码云wiki,喜欢配色统一简洁的同学可以不设置
|
||||
"projectName": "smart-doc",//配置自己的项目名称
|
||||
"skipTransientField": true,//目前未实现
|
||||
"sortByTitle":false,//接口标题排序,默认为false,@since 1.8.7版本开始
|
||||
"showAuthor":true,//是否显示接口作者名称,默认是true,不想显示可关闭
|
||||
"requestFieldToUnderline":true,//自动将驼峰入参字段在文档中转为下划线格式,//@since 1.8.7版本开始
|
||||
"responseFieldToUnderline":true,//自动将驼峰入参字段在文档中转为下划线格式,//@since 1.8.7版本开始
|
||||
"inlineEnum":true,//设置为true会将枚举详情展示到参数表中,默认关闭,//@since 1.8.8版本开始
|
||||
"recursionLimit":7,//设置允许递归执行的次数用于避免一些对象解析卡主,默认是7,正常为3次以内,//@since 1.8.8版本开始
|
||||
"allInOneDocFileName":"index.html",//自定义设置输出文档名称, @since 1.9.0
|
||||
"requestExample":"true",//是否将请求示例展示在文档中,默认true,@since 1.9.0
|
||||
"responseExample":"true",//是否将响应示例展示在文档中,默认为true,@since 1.9.0
|
||||
"urlSuffix":".do",//支持SpringMVC旧项目的url后缀,@since 2.1.0
|
||||
"displayActualType":false,//配置true会在注释栏自动显示泛型的真实类型短类名,@since 1.9.6
|
||||
"appKey": "20201216788835306945118208",// torna平台对接appKey,, @since 2.0.9
|
||||
"appToken": "c16931fa6590483fb7a4e85340fcbfef", //torna平台appToken,@since 2.0.9
|
||||
"secret": "W.ZyGMOB9Q0UqujVxnfi@.I#V&tUUYZR",//torna平台secret,@since 2.0.9
|
||||
"openUrl": "http://localhost:7700/api",//torna平台地址,填写自己的私有化部署地址@since 2.0.9
|
||||
"debugEnvName":"测试环境", //torna环境名称
|
||||
"debugEnvUrl":"http://127.0.0.1",//推送torna配置接口服务地址
|
||||
"tornaDebug":false,//启用会推送日志
|
||||
"ignoreRequestParams":[ //忽略请求参数对象,把不想生成文档的参数对象屏蔽掉,@since 1.9.2
|
||||
"org.springframework.ui.ModelMap"
|
||||
],
|
||||
"dataDictionaries": [{ //配置数据字典,没有需求可以不设置
|
||||
"title": "http状态码字典", //数据字典的名称
|
||||
"enumClassName": "com.power.common.enums.HttpCodeEnum", //数据字典枚举类名称
|
||||
"codeField": "code",//数据字典字典码对应的字段名称
|
||||
"descField": "message"//数据字典对象的描述信息字典
|
||||
}],
|
||||
"errorCodeDictionaries": [{ //错误码列表,没有需求可以不设置
|
||||
"title": "title",
|
||||
"enumClassName": "com.power.common.enums.HttpCodeEnum", //错误码枚举类
|
||||
"codeField": "code",//错误码的code码字段名称
|
||||
"descField": "message"//错误码的描述信息对应的字段名
|
||||
}],
|
||||
"revisionLogs": [{ //文档变更记录
|
||||
"version": "1.0", //文档版本号
|
||||
"revisionTime": "2020-12-31 10:30", //文档修订时间
|
||||
"status": "update", //变更操作状态,一般为:创建、更新等
|
||||
"author": "author", //文档变更作者
|
||||
"remarks": "desc" //变更描述
|
||||
}
|
||||
],
|
||||
"customResponseFields": [{ //自定义添加字段和注释,api-doc后期遇到同名字段则直接给相应字段加注释,非必须
|
||||
"name": "code",//覆盖响应码字段
|
||||
"desc": "响应代码",//覆盖响应码的字段注释
|
||||
"ownerClassName": "org.springframework.data.domain.Pageable", //指定你要添加注释的类名
|
||||
"value": "00000"//设置响应码的值
|
||||
}],
|
||||
"customRequestFields": [{ //自定义请求体的注释,@since 2.1.3
|
||||
"name":"code", //属性名
|
||||
"desc":"状态码", //描述
|
||||
"ownerClassName":"com.xxx.constant.entity.Result", //属性对应的类全路径
|
||||
"value":"200", //默认值或者mock值
|
||||
"required":true, //是否必填
|
||||
"ignore":false //是否忽略
|
||||
}],
|
||||
"requestHeaders": [{ //设置请求头,没有需求可以不设置
|
||||
"name": "token",//请求头名称
|
||||
"type": "string",//请求头类型
|
||||
"desc": "desc",//请求头描述信息
|
||||
"value":"token请求头的值",//不设置默认null
|
||||
"required": false,//是否必须
|
||||
"since": "-"//什么版本添加的改请求头
|
||||
}],
|
||||
"rpcApiDependencies":[{ // 项目开放的dubbo api接口模块依赖,配置后输出到文档方便使用者集成
|
||||
"artifactId":"SpringBoot2-Dubbo-Api",
|
||||
"groupId":"com.demo",
|
||||
"version":"1.0.0"
|
||||
}],
|
||||
"rpcConsumerConfig": "src/main/resources/consumer-example.conf",//文档中添加dubbo consumer集成配置,用于方便集成方可以快速集成
|
||||
"apiObjectReplacements": [{ // 自smart-doc 1.8.5开始你可以使用自定义类覆盖其他类做文档渲染,非必须
|
||||
"className": "org.springframework.data.domain.Pageable",
|
||||
"replacementClassName": "com.power.doc.model.PageRequestDto" //自定义的PageRequestDto替换Pageable做文档渲染
|
||||
}],
|
||||
"apiConstants": [{//从1.8.9开始配置自己的常量类,smart-doc在解析到常量时自动替换为具体的值
|
||||
"constantsClassName": "com.power.doc.constants.RequestParamConstant"
|
||||
}],
|
||||
"responseBodyAdvice":{ //自smart-doc 1.9.8起,ResponseBodyAdvice统一返回设置,可用ignoreResponseBodyAdvice tag来忽略
|
||||
"className":"com.power.common.model.CommonResult" //通用响应体
|
||||
},
|
||||
"requestBodyAdvice":{ ////自smart-doc 2.1.4 起,支持设置RequestBodyAdvice统一请求包装类
|
||||
"className":"com.power.common.model.CommonResult"
|
||||
},
|
||||
"sourceCodePaths": [{ //设置代码路径, 插件已经能够自动下载发布的源码包,没必要配置
|
||||
"path": "src/main/java",
|
||||
"desc": "测试"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
上面的JSON配置实例中只有"outPath"是必填项。
|
||||
|
||||
**注意:** 对于老用户完全可以通过`Fastjson`或者是`Gson`库将`ApiConfig`转化成JSON配置。
|
||||
|
||||
#### Use Maven Command
|
||||
|
||||
添加好插件和配置文件后可以直接运行Maven命令生成文档。
|
||||
|
||||
```
|
||||
//生成html
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:html
|
||||
//生成markdown
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:markdown
|
||||
//生成adoc
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:adoc
|
||||
//生成postman json数据
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:postman
|
||||
// 生成 Open Api 3.0+,Since smart-doc-maven-plugin 1.1.5
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:openapi
|
||||
// 生成文档推送到Torna平台
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:torna-rest
|
||||
|
||||
// Apache Dubbo RPC文档
|
||||
// Generate html
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-html
|
||||
// Generate markdown
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-markdown
|
||||
// Generate adoc
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-adoc
|
||||
|
||||
// 生成dubbo接口文档推送到torna
|
||||
mvn -Dfile.encoding=UTF-8 smart-doc:torna-rpc
|
||||
```
|
||||
|
||||
**注意:** 尤其在window系统下,如果实际使用Maven命令行执行文档生成,可能会出现乱码,因此需要在执行时指定`-Dfile.encoding=UTF-8`。
|
||||
|
||||
#### Use in IDEA
|
||||
|
||||
![idea中smart-doc-maven插件使用](https://gitee.com/smart-doc-team/smart-doc-maven-plugin/raw/master/images/idea.png "maven_plugin_tasks.png")
|
||||
|
||||
### Use gradle plugin
|
||||
|
||||
如果你使用Gradle来构建项目,你可以参考Gradle插件的使用文档来集成,
|
||||
[smart-doc-gradle-plugin](https://gitee.com/smart-doc-team/smart-doc-gradle-plugin/blob/master/README_CN.md)
|
||||
|
||||
### Use Junit Test
|
||||
|
||||
从smart-doc 1.7.9开始,官方提供了Maven插件,使用smart-doc的Maven插件后不再需要创建单元测试。
|
||||
[单元测试生成文档](https://gitee.com/smart-doc-team/smart-doc/wikis/单元测试集成smart-doc?sort_id=1990284)
|
||||
|
||||
> 单元测试集成存在很多绝限性: <br/>1. 对于多模块项目源码注释很麻烦,也不符合正常开发团队的开发协作。<br/>2. 不方便与CI工具集成
|
||||
|
||||
### Generated document example
|
||||
|
||||
[点击查看文档生成文档效果图](https://gitee.com/smart-doc-team/smart-doc/wikis/文档效果图?sort_id=1652819)
|
||||
|
||||
## Building
|
||||
|
||||
如果你需要自己构建smart-doc,那可以使用下面命令,构建需要依赖Java 1.8。
|
||||
|
@ -283,11 +55,6 @@ mvn clean install -Dmaven.test.skip=true
|
|||
|
||||
- Jakarta RS-API 2.x
|
||||
|
||||
## Other reference
|
||||
|
||||
- [smart-doc功能使用介绍](https://my.oschina.net/u/1760791/blog/2250962)
|
||||
- [smart-doc官方wiki](https://gitee.com/smart-doc-team/smart-doc/wikis/Home?sort_id=1652800)
|
||||
|
||||
## License
|
||||
|
||||
smart-doc is under the Apache 2.0 license. See
|
||||
|
@ -302,18 +69,33 @@ the [LICENSE](https://gitee.com/smart-doc-team/smart-doc/blob/master/LICENSE) fi
|
|||
![IFLYTEK](https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/iflytek.png)
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/oneplus.png" title="一加" width="83px" height="83px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/xiaomi.png" title="小米" width="170px" height="83px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/yuanmengjiankang.png" title="远盟健康" width="260px" height="83px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/zhongkezhilian.png" title="中科智链" width="272px" height="83px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/neusoft.png" title="东软集团" width="180px" height="83px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/zhongkezhilian.png" title="中科智链" width="272px" height="83px"/>
|
||||
<img src="https://www.hand-china.com/static/img/hand-logo.svg" title="上海汉得信息技术股份有限公司" width="260px" height="83px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/shunfeng.png" title="顺丰" width="83px" height="83px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/yuanmengjiankang.png" title="远盟健康" width="260px" height="83px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/puqie_gaitubao_100x100.jpg" title="普切信息科技" width="83px" height="83px"/>
|
||||
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/tianbo-tech.png" title="杭州天铂云科" width="127px" height="70px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/tianbo-tech.png" title="杭州天铂云科" width="135px" height="83px"/>
|
||||
|
||||
|
||||
## Award situation
|
||||
|
||||
- 2020 年度 OSC 中国开源项目评选”活动中获得「最积极运营项目」
|
||||
|
||||
## Acknowledgements
|
||||
感谢[JetBrains SoftWare](https://www.jetbrains.com) 为本开源项目提供的免费Open Source license。
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/jetbrains-variant-3.png" width="260px" height="220px"/>
|
||||
## Contact
|
||||
|
||||
愿意参与构建smart-doc或者是需要交流问题可以加入qq群:
|
||||
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/smart-doc-qq.png" title="qq群" width="200px" height="200px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/smart-doc-qq.png" title="qq群" width="200px" height="210px"/>
|
||||
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/smart-doc-qq2.jpeg" title="qq群2" width="200px" height="210px"/>
|
||||
|
||||
> 1群已满,有问题请加2群。
|
||||
|
||||
|
||||
## Donate
|
||||
如果您觉得我们的开源软件对你有所帮助,请扫下方二维码打赏我们一杯咖啡
|
||||
|
||||
<img src="https://images.gitee.com/uploads/images/2020/0831/225756_9aecdd4d_144669.png" width="200px" height="210px"/>
|
||||
|
|
150
doc/List.md
150
doc/List.md
|
@ -1,150 +0,0 @@
|
|||
关于list结构的返回json数据测试
|
||||
|
||||
# List<String>结构
|
||||
|
||||
api-doc对于List中返回基础数据类型都是支持的
|
||||
|
||||
```
|
||||
/**
|
||||
* List<String>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "listString")
|
||||
public List<String> testList() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
api-doc生成的响应数据
|
||||
|
||||
```
|
||||
[ "ivvqah","isrz5x"]
|
||||
```
|
||||
|
||||
# List<Map<String,String>>结构
|
||||
|
||||
```
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public List<Map<String,String>> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
api-doc生成的响应数据
|
||||
|
||||
```
|
||||
[{
|
||||
"mapKey1": "o9mibj",
|
||||
"mapKey2": "3dnnrn"
|
||||
}]
|
||||
```
|
||||
|
||||
# List<Map<String,T>>结构
|
||||
|
||||
```
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public List<Map<String,Student>> testMap() {
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
相应数据省略
|
||||
|
||||
# 测试List<T>结构
|
||||
|
||||
```
|
||||
/**
|
||||
* 测试List<T>结构
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public List<Teacher> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
# List<T<M,N>>结构
|
||||
|
||||
```
|
||||
/**
|
||||
* 测试List<T<M,N>>结构
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public List<Teacher<User,User>> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
# List<Map<M,N<P,k>>>超复杂结构
|
||||
|
||||
```
|
||||
/**
|
||||
* 测试List<Map<M,N<P,k>>>超复杂结构
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public List<Map<String,Teacher<User,User>>> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
api-doc自动返回的数据
|
||||
|
||||
```
|
||||
[{
|
||||
"mapKey": {
|
||||
"data": {
|
||||
"userName": "lxh2yi",
|
||||
"userAddress": "6jfp3h",
|
||||
"userAge": 741
|
||||
},
|
||||
"data1": {
|
||||
"userName": "1wp54g",
|
||||
"userAddress": "8ul6m4",
|
||||
"userAge": 550
|
||||
},
|
||||
"age": 10
|
||||
}
|
||||
}]
|
||||
```
|
||||
|
||||
# List<T<List<M>,List<M>,List<M>>>超复杂结构
|
||||
|
||||
```
|
||||
/**
|
||||
* List<T<List<M>,List<M>,List<M>>>
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "listString")
|
||||
public List<Teacher<List<User>,List<User>,List<User>>> testListString(){
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
# 其他复杂结构
|
||||
|
||||
```
|
||||
/**
|
||||
* List<T<List<M>,List<M>,List<M>>>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "listString")
|
||||
public List<Teacher<Teacher<User,User,User>,User,User>> testListString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@GetMapping(value = "listString")
|
||||
public List<Teacher<Teacher<User,User,User>,Teacher<User,User,User>,Teacher<User,User,User>>> testListString() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
**注意:** api-doc为了传入的复杂泛型结构数据,做了许多情况的测试,目前基本能兼容系统开发中95%以上的List返回接口, 也提供了一些能够处理的很复杂的泛型结构,但是这种复杂的泛型结构在开发中是不被推荐的。
|
171
doc/Map.md
171
doc/Map.md
|
@ -1,171 +0,0 @@
|
|||
Api-doc对于api中map结构数据的json化处理多组测试用例,对于map返回的json结构, 目前基本仅仅支持,String类型的key。
|
||||
|
||||
**基础数据类型:** json支持的基本java数据类型(不包含byte,包含String)
|
||||
|
||||
# map使用基础数据类型
|
||||
|
||||
```
|
||||
/**
|
||||
* 测试map使用基础数据类型
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public Map<String,Integer> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
api-doc 生成的json:
|
||||
|
||||
```
|
||||
{
|
||||
"mapKey1": 721,
|
||||
"mapKey2": 280
|
||||
}
|
||||
```
|
||||
|
||||
# map使用Object
|
||||
|
||||
因为api-doc使用的是无侵入静态分析生成api文档,因此对于直接使用Object做map value的接口,api-doc无法准确的生成json。
|
||||
所以api-doc返回是会在默认json中加一段警告,使用者需要自己去修改返回数据,或者是使用显示的类型数据结构。
|
||||
|
||||
```
|
||||
/**
|
||||
* 测试map使用基础数据类型
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public Map<String,Object> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
api-doc 生成的json:
|
||||
|
||||
```
|
||||
{
|
||||
"mapKey": {
|
||||
"waring": "You may use java.util.Object for Map value;Api-doc can't be handle."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# map中属于自己定义的简单数据结构
|
||||
|
||||
User对象的属性仅仅是基本数据类型
|
||||
|
||||
```
|
||||
/**
|
||||
* 测试map使用自定义数据结构
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public Map<String,User> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
api-doc 生成的json:
|
||||
|
||||
```
|
||||
{
|
||||
"mapKey": {
|
||||
"userName": "7t2ccy",
|
||||
"userAddress": "3ipy7g",
|
||||
"userAge": 280
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# map中属于自己定义的复杂数据结构
|
||||
|
||||
Student对象的属性有基本类型又有User类型和Map类型的属性。
|
||||
|
||||
```
|
||||
/**
|
||||
* 测试map使用自定义数据结构
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public Map<String,Student> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
api-doc 生成的json:
|
||||
|
||||
```
|
||||
{
|
||||
"mapKey": {
|
||||
"stuName": "9cwzml",
|
||||
"stuAge": 792,
|
||||
"stuAddress": "rdfmtx",
|
||||
"user": {
|
||||
"userName": "fjglql",
|
||||
"userAddress": "yy6vkf",
|
||||
"userAge": 398
|
||||
},
|
||||
"userMap": {
|
||||
"mapKey": {
|
||||
"userName": "paw90w",
|
||||
"userAddress": "mnmz42",
|
||||
"userAge": 937
|
||||
}
|
||||
},
|
||||
"user1": {
|
||||
"userName": "rr3v6g",
|
||||
"userAddress": "rbeorq",
|
||||
"userAge": 399
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Map<M,N<P,k>>复杂结构
|
||||
|
||||
```
|
||||
{
|
||||
"mapKey":{
|
||||
"data":{
|
||||
"userName":"tumrit",
|
||||
"userAddress":"v8fvdi",
|
||||
"userAge":465
|
||||
},
|
||||
"data1":{
|
||||
"userName":"f7wbwk",
|
||||
"userAddress":"brdh8j",
|
||||
"userAge":345
|
||||
},
|
||||
"age":194
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Map<String,T<List<M>,N>超复杂结构
|
||||
|
||||
```
|
||||
/**
|
||||
* Map<String,T<List<M>,N>超复杂结构
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/map/Primitive")
|
||||
public Map<String,Teacher<List<User>,User>> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
# Map其他复杂结构
|
||||
|
||||
对于map的key采用多泛型的情况,目前api-doc也是支持的。
|
||||
|
||||
```
|
||||
/**
|
||||
* Map<String,T<List<M>,N>超复杂结构
|
||||
* @return
|
||||
*/
|
||||
public Map<String,Teacher<Map<String,User>,Map<String,User>,Map<String,User>>> testMap() {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
**注意:** api-doc为了传入的复杂泛型结构数据,做了许多情况的测试,目前基本能兼容系统开发中95%以上的Map返回接口, 也提供了一些能够处理的很复杂的泛型结构,但是这种复杂的泛型结构在开发中是不被推荐的。
|
31
doc/error.md
31
doc/error.md
|
@ -1,31 +0,0 @@
|
|||
api-doc对Spring mvc或者SpringBoot应用的Controller接口返回做了一些强制规约,一旦在代码中使用 这些被api-doc不推荐的接口返回类型,api-doc将会直接报错。
|
||||
|
||||
# 违反规约的实例
|
||||
|
||||
## 直接返回Object
|
||||
|
||||
```
|
||||
/**
|
||||
* 返回object
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/test/Object")
|
||||
public Object getMe(){
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
报错提示:Please do not return java.lang.Object directly in api interface.
|
||||
|
||||
## 将非String对象作为Map的key,然后将map作为接口中返回
|
||||
|
||||
```
|
||||
/**
|
||||
* 测试object的作为map的key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/test/map")
|
||||
public Map<Object,Object> objectMap(){
|
||||
return null;
|
||||
}
|
||||
```
|
|
@ -1,74 +0,0 @@
|
|||
{
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Pet": {
|
||||
"type": "object",
|
||||
"discriminator": {
|
||||
"propertyName": "petType"
|
||||
},
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"petType": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"petType"
|
||||
]
|
||||
},
|
||||
"Cat": {
|
||||
"description": "A representation of a cat. Note that `Cat` will be used as the discriminator value.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"huntingSkill": {
|
||||
"type": "string",
|
||||
"description": "The measured skill for hunting",
|
||||
"default": "lazy",
|
||||
"enum": [
|
||||
"clueless",
|
||||
"lazy",
|
||||
"adventurous",
|
||||
"aggressive"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"huntingSkill"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"Dog": {
|
||||
"description": "A representation of a dog. Note that `Dog` will be used as the discriminator value.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"packSize": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "the size of the pack the dog is from",
|
||||
"default": 0,
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"packSize"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
130
doc/temp.md
130
doc/temp.md
|
@ -1,130 +0,0 @@
|
|||
```java
|
||||
/**
|
||||
* Get fields
|
||||
*
|
||||
* @param cls1 The JavaClass object
|
||||
* @param counter Recursive counter
|
||||
* @param addedFields added fields,Field deduplication
|
||||
* @return list of JavaField
|
||||
*/
|
||||
public static List<DocJavaField> getFields(JavaClass cls1,int counter,HashMap<String, DocJavaField> addedFields){
|
||||
List<DocJavaField> fieldList=new ArrayList<>();
|
||||
if(null==cls1){
|
||||
return fieldList;
|
||||
}else if("Object".equals(cls1.getSimpleName())||"Timestamp".equals(cls1.getSimpleName())||
|
||||
"Date".equals(cls1.getSimpleName())||"Locale".equals(cls1.getSimpleName())
|
||||
||"ClassLoader".equals(cls1.getSimpleName())||JavaClassValidateUtil.isMap(cls1.getFullyQualifiedName())
|
||||
||cls1.isEnum()||"Serializable".equals(cls1.getSimpleName())){
|
||||
return fieldList;
|
||||
}else{
|
||||
String className=cls1.getFullyQualifiedName();
|
||||
if(cls1.isInterface()&&
|
||||
!JavaClassValidateUtil.isCollection(className)&&
|
||||
!JavaClassValidateUtil.isMap(className)){
|
||||
List<JavaMethod> methods=cls1.getMethods();
|
||||
for(JavaMethod javaMethod:methods){
|
||||
String methodName=javaMethod.getName();
|
||||
int paramSize=javaMethod.getParameters().size();
|
||||
boolean enable=false;
|
||||
if(methodName.startsWith("get")&&!"get".equals(methodName)&¶mSize==0){
|
||||
methodName=StringUtil.firstToLowerCase(methodName.substring(3));
|
||||
enable=true;
|
||||
}else if(methodName.startsWith("is")&&!"is".equals(methodName)&¶mSize==0){
|
||||
methodName=StringUtil.firstToLowerCase(methodName.substring(2));
|
||||
enable=true;
|
||||
}
|
||||
if(!enable||addedFields.containsKey(methodName)){
|
||||
continue;
|
||||
}
|
||||
String comment=javaMethod.getComment();
|
||||
JavaField javaField=new DefaultJavaField(javaMethod.getReturns(),methodName);
|
||||
DocJavaField docJavaField=DocJavaField.builder()
|
||||
.setJavaField(javaField)
|
||||
.setComment(comment)
|
||||
.setDocletTags(javaMethod.getTags())
|
||||
.setAnnotations(javaMethod.getAnnotations())
|
||||
.setFullyQualifiedName(javaField.getType().getFullyQualifiedName())
|
||||
.setGenericCanonicalName(javaField.getType().getGenericCanonicalName());
|
||||
addedFields.put(methodName,docJavaField);
|
||||
}
|
||||
}
|
||||
// ignore enum parent class
|
||||
if(!cls1.isEnum()){
|
||||
JavaClass parentClass=cls1.getSuperJavaClass();
|
||||
getFields(parentClass,counter,addedFields);
|
||||
List<JavaType> implClasses=cls1.getImplements();
|
||||
for(JavaType type:implClasses){
|
||||
JavaClass javaClass=(JavaClass)type;
|
||||
getFields(javaClass,counter,addedFields);
|
||||
}
|
||||
}
|
||||
Map<String, JavaType> actualJavaTypes=getActualTypesMap(cls1);
|
||||
List<JavaMethod> javaMethods=cls1.getMethods();
|
||||
for(JavaMethod method:javaMethods){
|
||||
String methodName=method.getName();
|
||||
int paramSize=method.getParameters().size();
|
||||
if(methodName.startsWith("get")&&!"get".equals(methodName)&¶mSize==0){
|
||||
methodName=StringUtil.firstToLowerCase(methodName.substring(3));
|
||||
}else if(methodName.startsWith("is")&&!"is".equals(methodName)&¶mSize==0){
|
||||
methodName=StringUtil.firstToLowerCase(methodName.substring(2));
|
||||
}
|
||||
if(addedFields.containsKey(methodName)){
|
||||
String comment=method.getComment();
|
||||
DocJavaField docJavaField=addedFields.get(methodName);
|
||||
docJavaField.setAnnotations(method.getAnnotations());
|
||||
docJavaField.setComment(comment);
|
||||
addedFields.put(methodName,docJavaField);
|
||||
}
|
||||
}
|
||||
for(JavaField javaField:cls1.getFields()){
|
||||
String fieldName=javaField.getName();
|
||||
DocJavaField docJavaField=DocJavaField.builder();
|
||||
boolean typeChecked=false;
|
||||
String gicName=javaField.getType().getGenericCanonicalName();
|
||||
String subTypeName=javaField.getType().getFullyQualifiedName();
|
||||
String actualType=null;
|
||||
if(JavaClassValidateUtil.isCollection(subTypeName)&&
|
||||
!JavaClassValidateUtil.isCollection(gicName)){
|
||||
String[]gNameArr=DocClassUtil.getSimpleGicName(gicName);
|
||||
actualType=JavaClassUtil.getClassSimpleName(gNameArr[0]);
|
||||
docJavaField.setArray(true);
|
||||
typeChecked=true;
|
||||
}
|
||||
if(JavaClassValidateUtil.isPrimitive(subTypeName)&&!typeChecked){
|
||||
docJavaField.setPrimitive(true);
|
||||
typeChecked=true;
|
||||
}
|
||||
if(JavaClassValidateUtil.isFile(subTypeName)&&!typeChecked){
|
||||
docJavaField.setFile(true);
|
||||
typeChecked=true;
|
||||
}
|
||||
if(javaField.getType().isEnum()&&!typeChecked){
|
||||
docJavaField.setEnum(true);
|
||||
}
|
||||
for(Map.Entry<String, JavaType> entry:actualJavaTypes.entrySet()){
|
||||
String key=entry.getKey();
|
||||
JavaType value=entry.getValue();
|
||||
if(gicName.contains(key)){
|
||||
subTypeName=subTypeName.replaceAll(key,value.getFullyQualifiedName());
|
||||
gicName=gicName.replaceAll(key,value.getGenericCanonicalName());
|
||||
actualType=value.getFullyQualifiedName();
|
||||
}
|
||||
}
|
||||
docJavaField.setComment(javaField.getComment())
|
||||
.setJavaField(javaField).setFullyQualifiedName(subTypeName)
|
||||
.setGenericCanonicalName(gicName).setActualJavaType(actualType)
|
||||
.setAnnotations(javaField.getAnnotations());
|
||||
if(addedFields.containsKey(fieldName)){
|
||||
addedFields.put(fieldName,docJavaField);
|
||||
continue;
|
||||
}
|
||||
addedFields.put(fieldName,docJavaField);
|
||||
}
|
||||
List<DocJavaField> parentFieldList=addedFields.values().stream()
|
||||
.filter(v->Objects.nonNull(v)).collect(Collectors.toList());
|
||||
fieldList.addAll(parentFieldList);
|
||||
}
|
||||
return fieldList;
|
||||
}
|
||||
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 178 KiB |
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
20
pom.xml
20
pom.xml
|
@ -5,7 +5,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>smart-doc</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>2.1.7</version>
|
||||
<version>2.3.2</version>
|
||||
|
||||
<name>smart-doc</name>
|
||||
<url>https://github.com/smart-doc-group/smart-doc.git</url>
|
||||
|
@ -34,19 +34,19 @@
|
|||
</developers>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<flexmark.version>0.62.2</flexmark.version>
|
||||
<junit.jupiter.version>5.8.1</junit.jupiter.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ibeetl</groupId>
|
||||
<artifactId>beetl</artifactId>
|
||||
<version>3.3.1.RELEASE</version>
|
||||
<version>3.8.1.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.qdox</groupId>
|
||||
|
@ -67,17 +67,17 @@
|
|||
<dependency>
|
||||
<groupId>com.github.shalousun</groupId>
|
||||
<artifactId>common-util</artifactId>
|
||||
<version>2.0.6</version>
|
||||
<version>2.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.6</version>
|
||||
<version>2.8.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.30</version>
|
||||
<version>1.7.32</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
@ -132,7 +132,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
*/
|
||||
package com.power.doc.builder;
|
||||
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.ApiDoc;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.SpringBootDocBuildTemplate;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -61,14 +61,16 @@ public class AdocDocBuilder {
|
|||
*/
|
||||
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config,false);
|
||||
config.setParamsDataToTree(false);
|
||||
config.setAdoc(true);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
IDocBuildTemplate docBuildTemplate = new SpringBootDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
if (config.isAllInOne()) {
|
||||
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_ADOC_TPL, INDEX_DOC);
|
||||
String docName = builderTemplate.allInOneDocName(config,INDEX_DOC,".adoc");
|
||||
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
|
||||
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_ADOC_TPL, docName);
|
||||
} else {
|
||||
builderTemplate.buildApiDoc(apiDocList, config, API_DOC_ADOC_TPL, API_EXTENSION);
|
||||
builderTemplate.buildErrorCodeDoc(config, ERROR_CODE_LIST_ADOC_TPL, ERROR_CODE_LIST_ADOC);
|
||||
|
@ -86,7 +88,7 @@ public class AdocDocBuilder {
|
|||
config.setAdoc(false);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, new JavaProjectBuilder());
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config,false);
|
||||
builderTemplate.buildSingleApi(configBuilder, controllerName, API_DOC_ADOC_TPL, API_EXTENSION);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public class ApiDataBuilder {
|
|||
* @return List of ApiDoc
|
||||
*/
|
||||
public static ApiAllData getApiData(ApiConfig config) {
|
||||
return getApiData(config, false);
|
||||
return getApiData(config, Boolean.FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,7 +49,7 @@ public class ApiDataBuilder {
|
|||
* @return List of ApiDoc
|
||||
*/
|
||||
public static ApiAllData getApiDataTree(ApiConfig config) {
|
||||
return getApiData(config, true);
|
||||
return getApiData(config, Boolean.TRUE);
|
||||
}
|
||||
|
||||
private static ApiAllData getApiData(ApiConfig config, boolean toTree) {
|
||||
|
@ -57,7 +57,7 @@ public class ApiDataBuilder {
|
|||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInitForGetApiData(config);
|
||||
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
|
||||
builderTemplate.getApiData(config, javaProjectBuilder);
|
||||
return builderTemplate.getApiData(config, javaProjectBuilder);
|
||||
ApiAllData apiAllData = builderTemplate.getApiData(config, javaProjectBuilder);
|
||||
return apiAllData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
package com.power.doc.builder;
|
||||
|
||||
import com.power.common.util.DateTimeUtil;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.ApiDoc;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.SpringBootDocBuildTemplate;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -60,15 +60,17 @@ public class ApiDocBuilder {
|
|||
*/
|
||||
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config,false);
|
||||
config.setAdoc(false);
|
||||
config.setParamsDataToTree(false);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
IDocBuildTemplate docBuildTemplate = new SpringBootDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
if (config.isAllInOne()) {
|
||||
String version = config.isCoverOld() ? "" : "-V" + DateTimeUtil.long2Str(System.currentTimeMillis(), DATE_FORMAT);
|
||||
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_MD_TPL, "AllInOne" + version + ".md");
|
||||
String docName = builderTemplate.allInOneDocName(config,"AllInOne" + version + ".md",".md");
|
||||
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
|
||||
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_MD_TPL, docName);
|
||||
} else {
|
||||
builderTemplate.buildApiDoc(apiDocList, config, API_DOC_MD_TPL, API_EXTENSION);
|
||||
builderTemplate.buildErrorCodeDoc(config, ERROR_CODE_LIST_MD_TPL, ERROR_CODE_LIST_MD);
|
||||
|
@ -87,7 +89,7 @@ public class ApiDocBuilder {
|
|||
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config,false);
|
||||
builderTemplate.buildSingleApi(configBuilder, controllerName, API_DOC_MD_TPL, API_EXTENSION);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,20 +22,29 @@
|
|||
*/
|
||||
package com.power.doc.builder;
|
||||
|
||||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.DateTimeUtil;
|
||||
import com.power.common.util.EnumUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.constants.DocGlobalConstants;
|
||||
import com.power.doc.constants.DocLanguage;
|
||||
import com.power.doc.constants.FrameworkEnum;
|
||||
import com.power.doc.constants.TemplateVariable;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.ApiErrorCode;
|
||||
import com.power.doc.model.ApiErrorCodeDictionary;
|
||||
import com.power.doc.model.RevisionLog;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.beetl.core.Resource;
|
||||
import org.beetl.core.Template;
|
||||
import org.beetl.core.resource.ClasspathResourceLoader;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.power.doc.constants.DocGlobalConstants.CSS_CDN;
|
||||
import static com.power.doc.constants.DocGlobalConstants.CSS_CDN_CH;
|
||||
|
||||
/**
|
||||
* @author yu 2020/5/16.
|
||||
|
@ -48,10 +57,11 @@ public class BaseDocBuilderTemplate {
|
|||
* check condition and init
|
||||
*
|
||||
* @param config Api config
|
||||
* @param checkOutPath check out path
|
||||
*/
|
||||
public void checkAndInit(ApiConfig config) {
|
||||
public void checkAndInit(ApiConfig config,boolean checkOutPath) {
|
||||
this.checkAndInitForGetApiData(config);
|
||||
if (StringUtil.isEmpty(config.getOutPath())) {
|
||||
if (StringUtil.isEmpty(config.getOutPath())&&!checkOutPath) {
|
||||
throw new RuntimeException("doc output path can't be null or empty");
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +93,10 @@ public class BaseDocBuilderTemplate {
|
|||
.setStatus("auto")
|
||||
);
|
||||
}
|
||||
if (StringUtil.isEmpty(config.getFramework())) {
|
||||
config.setFramework(FrameworkEnum.SPRING.getFramework());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Map<String, String> setDirectoryLanguageVariable(ApiConfig config, Template mapper) {
|
||||
|
@ -107,4 +121,47 @@ public class BaseDocBuilderTemplate {
|
|||
}
|
||||
return titleMap;
|
||||
}
|
||||
|
||||
public void setCssCDN(ApiConfig config, Template template) {
|
||||
if (DocLanguage.CHINESE.equals(config.getLanguage())) {
|
||||
template.binding(TemplateVariable.CSS_CND.getVariable(), CSS_CDN_CH);
|
||||
} else {
|
||||
template.binding(TemplateVariable.CSS_CND.getVariable(), CSS_CDN);
|
||||
}
|
||||
}
|
||||
|
||||
public String allInOneDocName(ApiConfig apiConfig, String fileName, String suffix) {
|
||||
String allInOneName = apiConfig.getAllInOneDocFileName();
|
||||
if (StringUtils.isNotEmpty(apiConfig.getAllInOneDocFileName())) {
|
||||
if (allInOneName.endsWith(suffix)) {
|
||||
return allInOneName;
|
||||
} else {
|
||||
return allInOneName + suffix;
|
||||
}
|
||||
} else if (StringUtil.isNotEmpty(fileName) && fileName.endsWith(suffix)) {
|
||||
return fileName;
|
||||
} else {
|
||||
return fileName + suffix;
|
||||
}
|
||||
}
|
||||
public static void copyJarFile(String source, String target) {
|
||||
ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader("/template/");
|
||||
Resource resource = resourceLoader.getResource(source);
|
||||
try (FileWriter fileWriter = new FileWriter(target, false);
|
||||
Reader reader = resource.openReader()) {
|
||||
char[] c = new char[1024 * 1024];
|
||||
int temp;
|
||||
int len = 0;
|
||||
while ((temp = reader.read()) != -1) {
|
||||
c[len] = (char) temp;
|
||||
len++;
|
||||
}
|
||||
reader.close();
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
bufferedWriter.write(c, 0, len);
|
||||
bufferedWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,16 +22,18 @@
|
|||
*/
|
||||
package com.power.doc.builder;
|
||||
|
||||
import com.power.common.util.*;
|
||||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.DateTimeUtil;
|
||||
import com.power.common.util.FileUtil;
|
||||
import com.power.doc.constants.DocLanguage;
|
||||
import com.power.doc.constants.HighlightStyle;
|
||||
import com.power.doc.constants.TemplateVariable;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.*;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.SpringBootDocBuildTemplate;
|
||||
import com.power.doc.utils.BeetlTemplateUtil;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
import com.thoughtworks.qdox.model.JavaClass;
|
||||
import org.beetl.core.Template;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -39,8 +41,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.power.doc.constants.DocGlobalConstants.FILE_SEPARATOR;
|
||||
import static com.power.doc.constants.DocGlobalConstants.SEARCH_JS_OUT;
|
||||
import static com.power.doc.constants.DocGlobalConstants.*;
|
||||
|
||||
/**
|
||||
* @author yu 2019/9/26.
|
||||
|
@ -123,6 +124,7 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
Template tpl = BeetlTemplateUtil.getByName(template);
|
||||
String style = config.getStyle();
|
||||
tpl.binding(TemplateVariable.STYLE.getVariable(), style);
|
||||
tpl.binding(TemplateVariable.HIGH_LIGHT_CSS_LINK.getVariable(), config.getHighlightStyleLink());
|
||||
tpl.binding(TemplateVariable.BACKGROUND.getVariable(), HighlightStyle.getBackgroundColor(style));
|
||||
tpl.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocList);
|
||||
tpl.binding(TemplateVariable.ERROR_CODE_LIST.getVariable(), errorCodeList);
|
||||
|
@ -133,6 +135,9 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
tpl.binding(TemplateVariable.PROJECT_NAME.getVariable(), config.getProjectName());
|
||||
tpl.binding(TemplateVariable.REQUEST_EXAMPLE.getVariable(), config.isRequestExample());
|
||||
tpl.binding(TemplateVariable.RESPONSE_EXAMPLE.getVariable(), config.isResponseExample());
|
||||
tpl.binding(TemplateVariable.DISPLAY_REQUEST_PARAMS.getVariable(), config.isRequestParamsTable());
|
||||
tpl.binding(TemplateVariable.DISPLAY_RESPONSE_PARAMS.getVariable(), config.isResponseParamsTable());
|
||||
setCssCDN(config, tpl);
|
||||
if (CollectionUtil.isEmpty(errorCodeList)) {
|
||||
tpl.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 1);
|
||||
} else {
|
||||
|
@ -158,33 +163,48 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
apiDoc1.setOrder(apiDocs.size() + 1);
|
||||
apiDocs.add(apiDoc1);
|
||||
}
|
||||
|
||||
boolean isOnlyDefaultGroup = apiDocList.size() == 1;
|
||||
|
||||
Map<String, String> titleMap = setDirectoryLanguageVariable(config, tpl);
|
||||
// set error code
|
||||
if (CollectionUtil.isNotEmpty(errorCodeList)) {
|
||||
ApiDoc apiDoc1 = new ApiDoc();
|
||||
apiDoc1.setOrder(apiDocs.size() + 1);
|
||||
apiDoc1.setOrder((isOnlyDefaultGroup ? apiDocs.get(0).getChildrenApiDocs().size() : apiDocs.size()) + 1);
|
||||
apiDoc1.setDesc(titleMap.get(TemplateVariable.ERROR_LIST_TITLE.getVariable()));
|
||||
apiDoc1.setList(new ArrayList<>(0));
|
||||
apiDoc1.setLink("error_code_list");
|
||||
apiDoc1.setAlias("error");
|
||||
apiDocs.add(apiDoc1);
|
||||
apiDoc1.setGroup(apiDoc1.getDesc());
|
||||
if (isOnlyDefaultGroup) {
|
||||
apiDocs.get(0).getChildrenApiDocs().add(apiDoc1);
|
||||
} else {
|
||||
apiDocs.add(apiDoc1);
|
||||
}
|
||||
}
|
||||
// set dict list
|
||||
List<ApiDocDict> apiDocDictList = DocUtil.buildDictionary(config, javaProjectBuilder);
|
||||
ApiDoc apiDoc1 = new ApiDoc();
|
||||
apiDoc1.setOrder(apiDocs.size() + 1);
|
||||
apiDoc1.setLink("dict_list");
|
||||
apiDoc1.setAlias("dict");
|
||||
apiDoc1.setDesc(titleMap.get(TemplateVariable.DICT_LIST_TITLE.getVariable()));
|
||||
List<ApiMethodDoc> methodDocs = new ArrayList<>();
|
||||
for (ApiDocDict apiDocDict : apiDocDictList) {
|
||||
ApiMethodDoc methodDoc = new ApiMethodDoc();
|
||||
methodDoc.setOrder(apiDocDict.getOrder());
|
||||
methodDoc.setDesc(apiDocDict.getTitle());
|
||||
methodDocs.add(methodDoc);
|
||||
if (CollectionUtil.isNotEmpty(apiDocDictList)) {
|
||||
ApiDoc apiDoc1 = new ApiDoc();
|
||||
apiDoc1.setOrder((isOnlyDefaultGroup ? apiDocs.get(0).getChildrenApiDocs().size() : apiDocs.size()) + 1);
|
||||
apiDoc1.setLink("dict_list");
|
||||
apiDoc1.setAlias("dict");
|
||||
apiDoc1.setDesc(titleMap.get(TemplateVariable.DICT_LIST_TITLE.getVariable()));
|
||||
apiDoc1.setGroup(apiDoc1.getDesc());
|
||||
List<ApiMethodDoc> methodDocs = new ArrayList<>();
|
||||
for (ApiDocDict apiDocDict : apiDocDictList) {
|
||||
ApiMethodDoc methodDoc = new ApiMethodDoc();
|
||||
methodDoc.setOrder(apiDocDict.getOrder());
|
||||
methodDoc.setDesc(apiDocDict.getTitle());
|
||||
methodDocs.add(methodDoc);
|
||||
}
|
||||
apiDoc1.setList(methodDocs);
|
||||
if (isOnlyDefaultGroup) {
|
||||
apiDocs.get(0).getChildrenApiDocs().add(apiDoc1);
|
||||
} else {
|
||||
apiDocs.add(apiDoc1);
|
||||
}
|
||||
}
|
||||
apiDoc1.setList(methodDocs);
|
||||
apiDocs.add(apiDoc1);
|
||||
tpl.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocs);
|
||||
FileUtil.nioWriteFile(tpl.render(), config.getOutPath() + FILE_SEPARATOR + SEARCH_JS_OUT);
|
||||
}
|
||||
|
@ -200,10 +220,11 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
public void buildErrorCodeDoc(ApiConfig config, String template, String outPutFileName) {
|
||||
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
|
||||
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
|
||||
Template mapper = BeetlTemplateUtil.getByName(template);
|
||||
mapper.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
|
||||
mapper.binding(TemplateVariable.LIST.getVariable(), errorCodeList);
|
||||
FileUtil.nioWriteFile(mapper.render(), config.getOutPath() + FILE_SEPARATOR + outPutFileName);
|
||||
Template tpl = BeetlTemplateUtil.getByName(template);
|
||||
setCssCDN(config, tpl);
|
||||
tpl.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
|
||||
tpl.binding(TemplateVariable.LIST.getVariable(), errorCodeList);
|
||||
FileUtil.nioWriteFile(tpl.render(), config.getOutPath() + FILE_SEPARATOR + outPutFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -223,12 +244,15 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
Template errorTemplate = BeetlTemplateUtil.getByName(template);
|
||||
errorTemplate.binding(TemplateVariable.PROJECT_NAME.getVariable(), config.getProjectName());
|
||||
String style = config.getStyle();
|
||||
errorTemplate.binding(TemplateVariable.HIGH_LIGHT_CSS_LINK.getVariable(), config.getHighlightStyleLink());
|
||||
errorTemplate.binding(TemplateVariable.STYLE.getVariable(), style);
|
||||
if (CollectionUtil.isEmpty(errorCodeList)) {
|
||||
errorTemplate.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 1);
|
||||
} else {
|
||||
errorTemplate.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 2);
|
||||
}
|
||||
// set css cdn
|
||||
setCssCDN(config, errorTemplate);
|
||||
List<ApiDocDict> apiDocDictList = DocUtil.buildDictionary(config, javaProjectBuilder);
|
||||
errorTemplate.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
|
||||
errorTemplate.binding(TemplateVariable.VERSION.getVariable(), now);
|
||||
|
@ -259,13 +283,22 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
|
||||
mapper.binding(TemplateVariable.PROJECT_NAME.getVariable(), config.getProjectName());
|
||||
String style = config.getStyle();
|
||||
mapper.binding(TemplateVariable.HIGH_LIGHT_CSS_LINK.getVariable(), config.getHighlightStyleLink());
|
||||
mapper.binding(TemplateVariable.STYLE.getVariable(), style);
|
||||
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
|
||||
if (CollectionUtil.isEmpty(errorCodeList)) {
|
||||
mapper.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 1);
|
||||
// set css cdn
|
||||
setCssCDN(config, mapper);
|
||||
if (DocLanguage.CHINESE.equals(config.getLanguage())) {
|
||||
mapper.binding(TemplateVariable.CSS_CND.getVariable(), CSS_CDN_CH);
|
||||
} else {
|
||||
mapper.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 2);
|
||||
mapper.binding(TemplateVariable.CSS_CND.getVariable(), CSS_CDN);
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(errorCodeList)) {
|
||||
mapper.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 2);
|
||||
} else {
|
||||
mapper.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 1);
|
||||
}
|
||||
|
||||
mapper.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
|
||||
mapper.binding(TemplateVariable.VERSION.getVariable(), now);
|
||||
mapper.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocList);
|
||||
|
@ -289,6 +322,8 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
List<ApiDocDict> directoryList = DocUtil.buildDictionary(config, javaProjectBuilder);
|
||||
Template mapper = BeetlTemplateUtil.getByName(template);
|
||||
setDirectoryLanguageVariable(config, mapper);
|
||||
// set css cdn
|
||||
setCssCDN(config, mapper);
|
||||
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
|
||||
mapper.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
|
||||
mapper.binding(TemplateVariable.DICT_LIST.getVariable(), directoryList);
|
||||
|
@ -307,7 +342,7 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
public void buildSingleApi(ProjectDocConfigBuilder projectBuilder, String controllerName, String template, String fileExtension) {
|
||||
ApiConfig config = projectBuilder.getApiConfig();
|
||||
FileUtil.mkdirs(config.getOutPath());
|
||||
IDocBuildTemplate<ApiDoc> docBuildTemplate = new SpringBootDocBuildTemplate();
|
||||
IDocBuildTemplate<ApiDoc> docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
ApiDoc doc = docBuildTemplate.getSingleApiData(projectBuilder, controllerName);
|
||||
Template mapper = BeetlTemplateUtil.getByName(template);
|
||||
mapper.binding(TemplateVariable.DESC.getVariable(), doc.getDesc());
|
||||
|
@ -321,7 +356,8 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
this.checkAndInitForGetApiData(config);
|
||||
config.setMd5EncryptedHtmlName(true);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
IDocBuildTemplate docBuildTemplate = new SpringBootDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
return docBuildTemplate.getApiData(configBuilder);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
package com.power.doc.builder;
|
||||
|
||||
import com.power.common.util.FileUtil;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.ApiDoc;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.SpringBootDocBuildTemplate;
|
||||
import com.power.doc.utils.BeetlTemplateUtil;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -65,14 +65,19 @@ public class HtmlApiDocBuilder {
|
|||
*/
|
||||
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config,false);
|
||||
config.setParamsDataToTree(false);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
IDocBuildTemplate docBuildTemplate = new SpringBootDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
Template indexCssTemplate = BeetlTemplateUtil.getByName(ALL_IN_ONE_CSS);
|
||||
FileUtil.nioWriteFile(indexCssTemplate.render(), config.getOutPath() + FILE_SEPARATOR + ALL_IN_ONE_CSS);
|
||||
FileUtil.nioWriteFile(indexCssTemplate.render(), config.getOutPath() + FILE_SEPARATOR + ALL_IN_ONE_CSS_OUT);
|
||||
builderTemplate.copyJarFile("js/" + HIGH_LIGHT_JS, config.getOutPath() + FILE_SEPARATOR + HIGH_LIGHT_JS);
|
||||
builderTemplate.copyJarFile("css/" + FONT_STYLE, config.getOutPath() + FILE_SEPARATOR + FONT_STYLE);
|
||||
builderTemplate.copyJarFile("js/" + JQUERY, config.getOutPath() + FILE_SEPARATOR + JQUERY);
|
||||
builderTemplate.copyJarFile("css/" + HIGH_LIGHT_STYLE, config.getOutPath() + FILE_SEPARATOR + HIGH_LIGHT_STYLE);
|
||||
if (config.isAllInOne()) {
|
||||
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
|
||||
if (config.isCreateDebugPage()) {
|
||||
INDEX_HTML = DEBUG_PAGE_ALL_TPL;
|
||||
if (StringUtils.isNotEmpty(config.getAllInOneDocFileName())) {
|
||||
|
|
|
@ -22,16 +22,16 @@
|
|||
*/
|
||||
package com.power.doc.builder;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.FileUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.constants.DocGlobalConstants;
|
||||
import com.power.doc.constants.Methods;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.*;
|
||||
import com.power.doc.template.SpringBootDocBuildTemplate;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.power.doc.utils.JsonUtil;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -41,7 +41,6 @@ import java.util.*;
|
|||
*/
|
||||
public class OpenApiBuilder {
|
||||
|
||||
//过滤url中的特殊字符
|
||||
private static final String PATH_REGEX = "[/{};\\t+]";
|
||||
|
||||
/**
|
||||
|
@ -52,7 +51,7 @@ public class OpenApiBuilder {
|
|||
|
||||
public static void buildOpenApi(ApiConfig config) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config, false);
|
||||
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
openApiCreate(config, configBuilder);
|
||||
|
@ -66,7 +65,7 @@ public class OpenApiBuilder {
|
|||
*/
|
||||
public static void buildOpenApi(ApiConfig config, JavaProjectBuilder projectBuilder) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config, false);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, projectBuilder);
|
||||
openApiCreate(config, configBuilder);
|
||||
}
|
||||
|
@ -79,7 +78,7 @@ public class OpenApiBuilder {
|
|||
*/
|
||||
private static void openApiCreate(ApiConfig config, ProjectDocConfigBuilder configBuilder) {
|
||||
config.setParamsDataToTree(true);
|
||||
SpringBootDocBuildTemplate docBuildTemplate = new SpringBootDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
Map<String, Object> json = new HashMap<>(8);
|
||||
json.put("openapi", "3.0.3");
|
||||
|
@ -90,15 +89,14 @@ public class OpenApiBuilder {
|
|||
|
||||
String filePath = config.getOutPath();
|
||||
filePath = filePath + DocGlobalConstants.OPEN_API_JSON;
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
String data = gson.toJson(json);
|
||||
String data = JsonUtil.toPrettyJson(json);
|
||||
FileUtil.nioWriteFile(data, filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* info 信息
|
||||
* Build openapi info
|
||||
*
|
||||
* @param apiConfig 文档配置信息
|
||||
* @param apiConfig ApiConfig
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildInfo(ApiConfig apiConfig) {
|
||||
|
@ -109,9 +107,9 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* server 信息
|
||||
* Build Servers
|
||||
*
|
||||
* @param config 文档配置信息
|
||||
* @param config ApiConfig
|
||||
* @return
|
||||
*/
|
||||
private static List<Map<String, Object>> buildServers(ApiConfig config) {
|
||||
|
@ -123,9 +121,9 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 构建path数据 url请求
|
||||
* Build openapi paths
|
||||
*
|
||||
* @param apiDocList api列表
|
||||
* @param apiDocList List of api
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildPaths(List<ApiDoc> apiDocList) {
|
||||
|
@ -135,7 +133,7 @@ public class OpenApiBuilder {
|
|||
List<ApiMethodDoc> apiMethodDocs = a.getList();
|
||||
apiMethodDocs.forEach(
|
||||
method -> {
|
||||
//设置paths的请求url 将双斜杠替换成单斜杠
|
||||
//replace '//' to '/'
|
||||
String url = method.getPath().replace("//", "/");
|
||||
Map<String, Object> request = buildPathUrls(method, a);
|
||||
//pathMap.put(method.getPath().replace("//", "/"), buildPathUrls(method, a));
|
||||
|
@ -153,10 +151,10 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* paths 设置url请求方式
|
||||
* Build path urls
|
||||
*
|
||||
* @param apiMethodDoc 方法参数
|
||||
* @param apiDoc 类参数
|
||||
* @param apiMethodDoc Method
|
||||
* @param apiDoc ApiDoc
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildPathUrls(ApiMethodDoc apiMethodDoc, ApiDoc apiDoc) {
|
||||
|
@ -190,9 +188,9 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 请求体构建 只针对post请求 并且请求体不为null
|
||||
* Build request body
|
||||
*
|
||||
* @param apiMethodDoc 方法参数
|
||||
* @param apiMethodDoc ApiMethodDoc
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildRequestBody(ApiMethodDoc apiMethodDoc) {
|
||||
|
@ -200,7 +198,7 @@ public class OpenApiBuilder {
|
|||
boolean isPost = (apiMethodDoc.getType().equals(Methods.POST.getValue())
|
||||
|| apiMethodDoc.getType().equals(Methods.PUT.getValue()) ||
|
||||
apiMethodDoc.getType().equals(Methods.PATCH.getValue()));
|
||||
//如果是post请求 且包含请求体
|
||||
//add content of post method
|
||||
if (isPost) {
|
||||
requestBody.put("content", buildContent(apiMethodDoc, false));
|
||||
return requestBody;
|
||||
|
@ -242,19 +240,17 @@ public class OpenApiBuilder {
|
|||
if (!isRep && apiMethodDoc.getContentType().equals(DocGlobalConstants.MULTIPART_TYPE)) {
|
||||
// formdata
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
if (apiMethodDoc.isListParam()) {
|
||||
map.put("type", DocGlobalConstants.ARRAY);
|
||||
} else {
|
||||
map.put("type", "object");
|
||||
}
|
||||
map.put("type", "object");
|
||||
Map<String, Object> properties = new LinkedHashMap<>();
|
||||
Map<String, Object> detail;
|
||||
for (ApiParam apiParam : apiMethodDoc.getQueryParams()) {
|
||||
detail = new HashMap<>();
|
||||
detail.put("type", apiParam.getType());
|
||||
detail.put("description", apiParam.getDesc());
|
||||
|
||||
detail.put("example", DocUtil.handleJsonStr(apiParam.getValue()));
|
||||
if ("file".equals(apiParam.getType())) {
|
||||
detail.remove("example");
|
||||
if (apiParam.isHasItems()) {
|
||||
detail.put("type", "array");
|
||||
Map<String, Object> items = new HashMap<>();
|
||||
|
@ -263,6 +259,7 @@ public class OpenApiBuilder {
|
|||
detail.put("items", items);
|
||||
} else {
|
||||
detail.put("format", "binary");
|
||||
detail.put("type", "string");
|
||||
}
|
||||
}
|
||||
properties.put(apiParam.getField(), detail);
|
||||
|
@ -379,7 +376,7 @@ public class OpenApiBuilder {
|
|||
}
|
||||
//如果包含请求头
|
||||
if (!CollectionUtil.isEmpty(apiMethodDoc.getRequestHeaders())) {
|
||||
for (ApiReqHeader header : apiMethodDoc.getRequestHeaders()) {
|
||||
for (ApiReqParam header : apiMethodDoc.getRequestHeaders()) {
|
||||
parameters = new HashMap<>(20);
|
||||
parameters.put("name", header.getName());
|
||||
parameters.put("description", header.getDesc());
|
||||
|
@ -419,6 +416,9 @@ public class OpenApiBuilder {
|
|||
schema.put("format", "binary");
|
||||
} else if ("enum".equals(apiParam.getType())) {
|
||||
schema.put("enum", apiParam.getEnumValues());
|
||||
}else if("array".equals(apiParam.getType())) {
|
||||
schema.put("type","array");
|
||||
schema.put("items",new HashMap<>());
|
||||
}
|
||||
} else {
|
||||
schema.put("format", "int16".equals(apiParam.getType()) ? "int32" : apiParam.getType());
|
||||
|
@ -432,7 +432,7 @@ public class OpenApiBuilder {
|
|||
* @param header 参数信息
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildParametersSchema(ApiReqHeader header) {
|
||||
private static Map<String, Object> buildParametersSchema(ApiReqParam header) {
|
||||
Map<String, Object> schema = new HashMap<>(10);
|
||||
String openApiType = DocUtil.javaTypeToOpenApiTypeConvert(header.getType());
|
||||
schema.put("type", openApiType);
|
||||
|
@ -441,9 +441,9 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 构建返回信息
|
||||
* build response
|
||||
*
|
||||
* @param apiMethodDoc 方法参数
|
||||
* @param apiMethodDoc ApiMethodDoc
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildResponses(ApiMethodDoc apiMethodDoc) {
|
||||
|
@ -453,9 +453,9 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 构建返回信息实体
|
||||
* response body
|
||||
*
|
||||
* @param apiMethodDoc 方法参数
|
||||
* @param apiMethodDoc ApiMethodDoc
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildResponsesBody(ApiMethodDoc apiMethodDoc) {
|
||||
|
@ -466,9 +466,9 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 构建component
|
||||
* component schema
|
||||
*
|
||||
* @param apiDocs 请求列表
|
||||
* @param apiDocs List of ApiDoc
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildComponentsSchema(List<ApiDoc> apiDocs) {
|
||||
|
@ -501,9 +501,9 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* component schema properties 信息
|
||||
* component schema properties
|
||||
*
|
||||
* @param apiParam 参数列表
|
||||
* @param apiParam list of ApiParam
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildProperties(List<ApiParam> apiParam) {
|
||||
|
@ -539,9 +539,9 @@ public class OpenApiBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* component schema properties 实体信息构建
|
||||
* component schema properties data
|
||||
*
|
||||
* @param apiParam 参数基本信息
|
||||
* @param apiParam ApiParam
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, Object> buildPropertiesData(ApiParam apiParam) {
|
||||
|
|
|
@ -22,12 +22,11 @@
|
|||
*/
|
||||
package com.power.doc.builder;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.FileUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.constants.DocGlobalConstants;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.*;
|
||||
import com.power.doc.model.postman.InfoBean;
|
||||
import com.power.doc.model.postman.ItemBean;
|
||||
|
@ -38,13 +37,12 @@ import com.power.doc.model.postman.request.RequestBean;
|
|||
import com.power.doc.model.postman.request.body.BodyBean;
|
||||
import com.power.doc.model.postman.request.header.HeaderBean;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.SpringBootDocBuildTemplate;
|
||||
import com.power.doc.utils.PathUtil;
|
||||
import com.power.doc.utils.DocPathUtil;
|
||||
import com.power.doc.utils.JsonUtil;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -57,13 +55,13 @@ public class PostmanJsonBuilder {
|
|||
private static final String MSG = "Interface name is not set.";
|
||||
|
||||
/**
|
||||
* 构建postman json
|
||||
* build postman json
|
||||
*
|
||||
* @param config 配置文件
|
||||
* @param config Smart-doc ApiConfig
|
||||
*/
|
||||
public static void buildPostmanCollection(ApiConfig config) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config,false);
|
||||
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
postManCreate(config, configBuilder);
|
||||
|
@ -77,17 +75,17 @@ public class PostmanJsonBuilder {
|
|||
*/
|
||||
public static void buildPostmanCollection(ApiConfig config, JavaProjectBuilder projectBuilder) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config,false);
|
||||
config.setParamsDataToTree(false);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, projectBuilder);
|
||||
postManCreate(config, configBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 第一层的Item
|
||||
* Build the first layer of Postman Item
|
||||
*
|
||||
* @param apiDoc
|
||||
* @return
|
||||
* @param apiDoc Documentation for each Controller
|
||||
* @return First layer of Postman Item
|
||||
*/
|
||||
private static ItemBean buildItemBean(ApiDoc apiDoc) {
|
||||
ItemBean itemBean = new ItemBean();
|
||||
|
@ -105,10 +103,10 @@ public class PostmanJsonBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 构建第二层的item
|
||||
* Build the second layer of Postman item
|
||||
*
|
||||
* @param apiMethodDoc
|
||||
* @return
|
||||
* @param apiMethodDoc Documentation for each method
|
||||
* @return The second layer of Postman item
|
||||
*/
|
||||
private static ItemBean buildItem(ApiMethodDoc apiMethodDoc) {
|
||||
ItemBean item = new ItemBean();
|
||||
|
@ -130,37 +128,19 @@ public class PostmanJsonBuilder {
|
|||
}
|
||||
|
||||
private static UrlBean buildUrlBean(ApiMethodDoc apiMethodDoc) {
|
||||
UrlBean urlBean = new UrlBean();
|
||||
UrlBean urlBean = new UrlBean(apiMethodDoc.getServerUrl());
|
||||
String url = Optional.ofNullable(apiMethodDoc.getRequestExample().getUrl()).orElse(apiMethodDoc.getUrl());
|
||||
urlBean.setRaw(PathUtil.toPostmanPath(url));
|
||||
try {
|
||||
URL javaUrl = new java.net.URL(apiMethodDoc.getServerUrl());
|
||||
if (javaUrl.getPort() == -1) {
|
||||
urlBean.setPort(null);
|
||||
} else {
|
||||
urlBean.setPort(String.valueOf(javaUrl.getPort()));
|
||||
}
|
||||
// set protocol
|
||||
String protocol = javaUrl.getProtocol();
|
||||
if (StringUtil.isNotEmpty(protocol)) {
|
||||
urlBean.setProtocol(protocol);
|
||||
}
|
||||
|
||||
List<String> hosts = new ArrayList<>();
|
||||
hosts.add(javaUrl.getHost());
|
||||
urlBean.setHost(hosts);
|
||||
|
||||
List<String> paths = new ArrayList<>();
|
||||
paths.add(javaUrl.getPath());
|
||||
urlBean.setPath(paths);
|
||||
} catch (MalformedURLException e) {
|
||||
}
|
||||
String shortUrl = PathUtil.toPostmanPath(apiMethodDoc.getPath());
|
||||
urlBean.setRaw(DocPathUtil.toPostmanPath(url));
|
||||
String shortUrl = DocPathUtil.toPostmanPath(apiMethodDoc.getPath());
|
||||
String[] paths = shortUrl.split("/");
|
||||
List<String> pathList = new ArrayList<>();
|
||||
if (CollectionUtil.isNotEmpty(urlBean.getPath()) && shortUrl.indexOf(urlBean.getPath().get(0)) < 0) {
|
||||
pathList.add(urlBean.getPath().get(0).replaceAll("/", ""));
|
||||
String serverPath = CollectionUtil.isNotEmpty(urlBean.getPath()) ? urlBean.getPath().get(0) : "";
|
||||
// Add server path
|
||||
if (CollectionUtil.isNotEmpty(urlBean.getPath()) && !shortUrl.contains(serverPath)) {
|
||||
String[] serverPaths = serverPath.split("/");
|
||||
pathList.addAll(Arrays.asList(serverPaths));
|
||||
}
|
||||
// Add mapping path
|
||||
for (String str : paths) {
|
||||
if (StringUtil.isNotEmpty(str)) {
|
||||
pathList.add(str);
|
||||
|
@ -193,21 +173,20 @@ public class PostmanJsonBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 构造请求体
|
||||
* Build payload
|
||||
*
|
||||
* @param apiMethodDoc
|
||||
* @return
|
||||
* @return Body payload
|
||||
*/
|
||||
private static BodyBean buildBodyBean(ApiMethodDoc apiMethodDoc) {
|
||||
BodyBean bodyBean;
|
||||
if (apiMethodDoc.getContentType().contains(DocGlobalConstants.JSON_CONTENT_TYPE)) {
|
||||
bodyBean = new BodyBean(false);
|
||||
bodyBean = new BodyBean(Boolean.FALSE);// Json request
|
||||
bodyBean.setMode(DocGlobalConstants.POSTMAN_MODE_RAW);
|
||||
if (apiMethodDoc.getRequestExample() != null) {
|
||||
bodyBean.setRaw(apiMethodDoc.getRequestExample().getJsonBody());
|
||||
}
|
||||
} else {
|
||||
bodyBean = new BodyBean(true);
|
||||
bodyBean = new BodyBean(Boolean.TRUE); //Formdata
|
||||
bodyBean.setMode(DocGlobalConstants.POSTMAN_MODE_FORMDATA);
|
||||
bodyBean.setFormdata(apiMethodDoc.getRequestExample().getFormDataList());
|
||||
}
|
||||
|
@ -216,15 +195,13 @@ public class PostmanJsonBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 构造请求头
|
||||
* Build header
|
||||
*
|
||||
* @param apiMethodDoc
|
||||
* @return
|
||||
* @return List of header
|
||||
*/
|
||||
private static List<HeaderBean> buildHeaderBeanList(ApiMethodDoc apiMethodDoc) {
|
||||
List<HeaderBean> headerBeans = new ArrayList<>();
|
||||
|
||||
List<ApiReqHeader> headers = apiMethodDoc.getRequestHeaders();
|
||||
List<ApiReqParam> headers = apiMethodDoc.getRequestHeaders();
|
||||
headers.forEach(
|
||||
apiReqHeader -> {
|
||||
HeaderBean headerBean = new HeaderBean();
|
||||
|
@ -241,7 +218,7 @@ public class PostmanJsonBuilder {
|
|||
}
|
||||
|
||||
private static void postManCreate(ApiConfig config, ProjectDocConfigBuilder configBuilder) {
|
||||
IDocBuildTemplate docBuildTemplate = new SpringBootDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
RequestItem requestItem = new RequestItem();
|
||||
requestItem.setInfo(new InfoBean(config.getProjectName()));
|
||||
|
@ -255,8 +232,7 @@ public class PostmanJsonBuilder {
|
|||
requestItem.setItem(itemBeans);
|
||||
String filePath = config.getOutPath();
|
||||
filePath = filePath + DocGlobalConstants.POSTMAN_JSON;
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
String data = gson.toJson(requestItem);
|
||||
String data = JsonUtil.toPrettyJson(requestItem);
|
||||
FileUtil.nioWriteFile(data, filePath);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ public class ProjectDocConfigBuilder {
|
|||
private void initCustomResponseFieldsMap(ApiConfig config) {
|
||||
if (CollectionUtil.isNotEmpty(config.getCustomResponseFields())) {
|
||||
for (CustomField field : config.getCustomResponseFields()) {
|
||||
customRespFieldMap.put(field.getName(), field);
|
||||
customRespFieldMap.put(field.getOwnerClassName() + "." + field.getName(), field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ public class ProjectDocConfigBuilder {
|
|||
private void initCustomRequestFieldsMap(ApiConfig config) {
|
||||
if (CollectionUtil.isNotEmpty(config.getCustomRequestFields())) {
|
||||
for (CustomField field : config.getCustomRequestFields()) {
|
||||
customReqFieldMap.put(field.getName(), field);
|
||||
customReqFieldMap.put(field.getOwnerClassName() + "." + field.getName(), field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,32 +193,41 @@ public class ProjectDocConfigBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置高亮样式
|
||||
*/
|
||||
private void setHighlightStyle() {
|
||||
String style = apiConfig.getStyle();
|
||||
if (DocGlobalConstants.HIGH_LIGHT_DEFAULT_STYLE.equals(style)) {
|
||||
// use local css file
|
||||
apiConfig.setHighlightStyleLink(DocGlobalConstants.HIGH_LIGHT_CSS_DEFAULT);
|
||||
return;
|
||||
}
|
||||
if (HighlightStyle.containsStyle(style)) {
|
||||
apiConfig.setHighlightStyleLink(String.format(DocGlobalConstants.HIGH_LIGHT_CSS_URL_FORMAT, style));
|
||||
return;
|
||||
}
|
||||
Random random = new Random();
|
||||
if ("randomLight".equals(style)) {
|
||||
if (DocGlobalConstants.HIGH_LIGHT_CSS_RANDOM_LIGHT.equals(style)) {
|
||||
// Eliminate styles that do not match the template
|
||||
style = HighlightStyle.randomLight(random);
|
||||
if (HighlightStyle.containsStyle(style)) {
|
||||
apiConfig.setStyle(style);
|
||||
apiConfig.setHighlightStyleLink(String.format(DocGlobalConstants.HIGH_LIGHT_CSS_URL_FORMAT, style));
|
||||
} else {
|
||||
apiConfig.setStyle("null");
|
||||
apiConfig.setStyle(null);
|
||||
}
|
||||
} else if ("randomDark".equals(style)) {
|
||||
apiConfig.setStyle(HighlightStyle.randomDark(random));
|
||||
} else if (DocGlobalConstants.HIGH_LIGHT_CSS_RANDOM_DARK.equals(style)) {
|
||||
style = HighlightStyle.randomDark(random);
|
||||
if (DocGlobalConstants.HIGH_LIGHT_DEFAULT_STYLE.equals(style)) {
|
||||
apiConfig.setHighlightStyleLink(DocGlobalConstants.HIGH_LIGHT_CSS_DEFAULT);
|
||||
} else {
|
||||
apiConfig.setHighlightStyleLink(String.format(DocGlobalConstants.HIGH_LIGHT_CSS_URL_FORMAT, style));
|
||||
}
|
||||
apiConfig.setStyle(style);
|
||||
} else {
|
||||
// Eliminate styles that do not match the template
|
||||
apiConfig.setStyle("null");
|
||||
apiConfig.setStyle(null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public JavaProjectBuilder getJavaProjectBuilder() {
|
||||
return javaProjectBuilder;
|
||||
}
|
||||
|
|
|
@ -23,15 +23,17 @@
|
|||
package com.power.doc.builder;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.OkHttp3Util;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.constants.TornaConstants;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.ApiDoc;
|
||||
import com.power.doc.model.torna.Apis;
|
||||
import com.power.doc.model.torna.TornaApi;
|
||||
import com.power.doc.model.torna.TornaDic;
|
||||
import com.power.doc.template.SpringBootDocBuildTemplate;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.power.doc.utils.TornaUtil;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
@ -73,9 +75,11 @@ public class TornaBuilder {
|
|||
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
|
||||
config.setParamsDataToTree(true);
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
builderTemplate.checkAndInit(config,true);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
List<ApiDoc> apiDocList = new SpringBootDocBuildTemplate().getApiData(configBuilder);
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
|
||||
buildTorna(apiDocList, config, javaProjectBuilder);
|
||||
}
|
||||
|
||||
|
@ -84,37 +88,56 @@ public class TornaBuilder {
|
|||
*
|
||||
* @param apiDocs apiData
|
||||
* @param apiConfig ApiConfig
|
||||
* @param builder JavaProjectBuilder
|
||||
* @param builder JavaProjectBuilder
|
||||
*/
|
||||
public static void buildTorna(List<ApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) {
|
||||
TornaApi tornaApi = new TornaApi();
|
||||
tornaApi.setAuthor(StringUtil.isEmpty(apiConfig.getAuthor()) ? System.getProperty("user.name") : apiConfig.getAuthor());
|
||||
tornaApi.setIsReplace((apiConfig.getReplace() == null || apiConfig.getReplace()) ? 1 : 0);
|
||||
Apis api;
|
||||
List<Apis> apisList = new ArrayList<>();
|
||||
//添加接口数据
|
||||
for (ApiDoc a : apiDocs) {
|
||||
List<Apis> groupApiList = new ArrayList<>();
|
||||
//Convert ApiDoc to Apis
|
||||
for (ApiDoc groupApi : apiDocs) {
|
||||
List<Apis> apisList = new ArrayList<>();
|
||||
List<ApiDoc> childrenApiDocs = groupApi.getChildrenApiDocs();
|
||||
for (ApiDoc a : childrenApiDocs) {
|
||||
api = new Apis();
|
||||
api.setName(StringUtils.isBlank(a.getDesc()) ? a.getName() : a.getDesc());
|
||||
api.setItems(buildApis(a.getList(), TornaUtil.setDebugEnv(apiConfig, tornaApi)));
|
||||
api.setIsFolder(TornaConstants.YES);
|
||||
api.setAuthor(a.getAuthor());
|
||||
api.setOrderIndex(a.getOrder());
|
||||
apisList.add(api);
|
||||
}
|
||||
api = new Apis();
|
||||
api.setName(StringUtils.isBlank(a.getDesc()) ? a.getName() : a.getDesc());
|
||||
api.setItems(buildApis(a.getList(), TornaUtil.setDebugEnv(apiConfig, tornaApi)));
|
||||
api.setName(StringUtils.isBlank(groupApi.getDesc()) ? groupApi.getName() : groupApi.getDesc());
|
||||
api.setAuthor(tornaApi.getAuthor());
|
||||
api.setOrderIndex(groupApi.getOrder());
|
||||
api.setIsFolder(TornaConstants.YES);
|
||||
api.setAuthor(a.getAuthor());
|
||||
apisList.add(api);
|
||||
api.setItems(apisList);
|
||||
groupApiList.add(api);
|
||||
|
||||
}
|
||||
tornaApi.setCommonErrorCodes(buildErrorCode(apiConfig));
|
||||
tornaApi.setApis(apisList);
|
||||
//推送文档信息
|
||||
// delete default group when only default group
|
||||
tornaApi.setApis(groupApiList.size() == 1 ? groupApiList.get(0).getItems() : groupApiList);
|
||||
//Build push document information
|
||||
Map<String, String> requestJson = TornaConstants.buildParams(PUSH, new Gson().toJson(tornaApi), apiConfig);
|
||||
//推送字典信息
|
||||
//Push dictionary information
|
||||
Map<String, Object> dicMap = new HashMap<>(2);
|
||||
List<TornaDic> docDicts = TornaUtil.buildTornaDic(DocUtil.buildDictionary(apiConfig, builder));
|
||||
dicMap.put("enums", docDicts);
|
||||
Map<String, String> dicRequestJson = TornaConstants.buildParams(ENUM_PUSH, new Gson().toJson(dicMap), apiConfig);
|
||||
//获取返回结果
|
||||
if (CollectionUtil.isNotEmpty(docDicts)) {
|
||||
dicMap.put("enums", docDicts);
|
||||
Map<String, String> dicRequestJson = TornaConstants.buildParams(ENUM_PUSH, new Gson().toJson(dicMap), apiConfig);
|
||||
String dicResponseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(dicRequestJson));
|
||||
TornaUtil.printDebugInfo(apiConfig, dicResponseMsg, dicRequestJson, ENUM_PUSH);
|
||||
}
|
||||
//Get the response result
|
||||
String responseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(requestJson));
|
||||
String dicResponseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(dicRequestJson));
|
||||
//开启调试时打印请求信息
|
||||
|
||||
//Print the log of pushing documents to Torna
|
||||
TornaUtil.printDebugInfo(apiConfig, responseMsg, requestJson, PUSH);
|
||||
TornaUtil.printDebugInfo(apiConfig, dicResponseMsg, dicRequestJson, ENUM_PUSH);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,264 +0,0 @@
|
|||
/*
|
||||
* smart-doc https://github.com/shalousun/smart-doc
|
||||
*
|
||||
* Copyright (C) 2018-2021 smart-doc
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.power.doc.builder;
|
||||
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.power.common.util.FileUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.constants.DocGlobalConstants;
|
||||
import com.power.doc.constants.TemplateVariable;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.ApiDoc;
|
||||
import com.power.doc.model.ApiParam;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.SpringBootDocBuildTemplate;
|
||||
import com.power.doc.utils.BeetlTemplateUtil;
|
||||
import com.power.doc.utils.Iterables;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
import org.beetl.core.Template;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.power.doc.constants.DocGlobalConstants.YAPI_RESULT_TPL;
|
||||
|
||||
|
||||
/**
|
||||
* generate yapi's yapi json
|
||||
*
|
||||
* @author dai19470 2020/08/20.
|
||||
*/
|
||||
public class YapiJsonBuilder {
|
||||
|
||||
|
||||
/**
|
||||
* 构建yapi json
|
||||
*
|
||||
* @param config 配置文件
|
||||
*/
|
||||
public static void buildYapiCollection(ApiConfig config) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
yapiJsonCreate(config, configBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for smart-doc maven plugin and gradle plugin.
|
||||
*
|
||||
* @param config ApiConfig Object
|
||||
* @param projectBuilder QDOX avaProjectBuilder
|
||||
*/
|
||||
public static void buildYapiCollection(ApiConfig config, JavaProjectBuilder projectBuilder) {
|
||||
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, projectBuilder);
|
||||
yapiJsonCreate(config, configBuilder);
|
||||
}
|
||||
|
||||
|
||||
private static Set<String> getUrl(String url, String patter) {
|
||||
Pattern pattern = Pattern.compile(patter);
|
||||
Matcher matcher = pattern.matcher(url);
|
||||
Set<String> result = new HashSet<>();
|
||||
while (matcher.find()) {
|
||||
result.add(matcher.group());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void yapiJsonCreate(ApiConfig config, ProjectDocConfigBuilder configBuilder) {
|
||||
config.setParamsDataToTree(true);
|
||||
IDocBuildTemplate docBuildTemplate = new SpringBootDocBuildTemplate();
|
||||
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
List<Map<String, Object>> requestItem = new ArrayList<>();
|
||||
|
||||
Iterables.forEach(apiDocList, (index, apiDoc) -> {
|
||||
Map<String, Object> module = new HashMap<>();
|
||||
module.put("index", index);
|
||||
module.put("name", apiDoc.getDesc());
|
||||
module.put("parent_id", -1);
|
||||
module.put("desc", apiDoc.getDesc());
|
||||
module.put("add_time", System.currentTimeMillis() / 1000);
|
||||
module.put("up_time", System.currentTimeMillis() / 1000);
|
||||
|
||||
List<Map<String, Object>> methods = new ArrayList();
|
||||
|
||||
Iterables.forEach(apiDoc.getList(), (idx, apiMethodDoc) -> {
|
||||
Map<String, Object> method = new HashMap<>();
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("path", apiMethodDoc.getPath());
|
||||
map.put("params", new Object[]{});
|
||||
method.put("query_path", map);
|
||||
// method.put("owners",new String[]{apiMethodDoc.getAuthor()});
|
||||
method.put("owners", new String[]{});
|
||||
method.put("edit_uid", 0);
|
||||
method.put("status", "done");
|
||||
method.put("type", "static");
|
||||
method.put("req_body_is_json_schema", true);
|
||||
method.put("res_body_is_json_schema", true);
|
||||
method.put("api_opened", false);
|
||||
method.put("index", idx);
|
||||
method.put("tag", new Object[]{});
|
||||
method.put("method", apiMethodDoc.getType());
|
||||
method.put("title", apiMethodDoc.getDesc());
|
||||
method.put("desc", apiMethodDoc.getDetail());
|
||||
method.put("name", apiMethodDoc.getName());
|
||||
method.put("path", apiMethodDoc.getPath().replace("//", "/"));
|
||||
method.put("req_body_form", Arrays.asList());
|
||||
|
||||
|
||||
List<Map<String, Object>> req_params = new ArrayList();
|
||||
Set<String> req_param = getUrl(apiMethodDoc.getPath(), "(?<=\\{)(.+?)(?=\\})");
|
||||
Iterables.forEach(req_param, (j, param) -> {
|
||||
ApiParam temp = apiMethodDoc.getRequestParams().stream().filter(apiParam -> apiParam.getField().equals(param)).findFirst().orElse(null);
|
||||
if (temp != null) {
|
||||
Map<String, Object> h = new HashMap<>();
|
||||
h.put("example", "");
|
||||
h.put("name", temp.getField());
|
||||
h.put("type", temp.getType());
|
||||
h.put("desc", temp.getDesc());
|
||||
req_params.add(j, h);
|
||||
}
|
||||
});
|
||||
method.put("req_params", req_params);
|
||||
|
||||
method.put("res_body_type", "json");
|
||||
List<Map<String, Object>> querys = new ArrayList();
|
||||
Iterables.forEach(apiMethodDoc.getRequestParams(), (j, res) -> {
|
||||
Map<String, Object> h = new HashMap<>();
|
||||
h.put("required", res.isRequired() ? "1" : "0");
|
||||
h.put("desc", res.getDesc());
|
||||
h.put("name", res.getField());
|
||||
h.put("example", "");
|
||||
h.put("type", res.getType());
|
||||
querys.add(j, h);
|
||||
});
|
||||
method.put("req_query", querys);
|
||||
|
||||
List<Map<String, Object>> headers = new ArrayList();
|
||||
Iterables.forEach(apiMethodDoc.getRequestHeaders(), (j, res) -> {
|
||||
Map<String, Object> h = new HashMap<>();
|
||||
h.put("required", res.isRequired() ? "1" : "0");
|
||||
h.put("value", res.getValue());
|
||||
h.put("name", res.getName());
|
||||
h.put("desc", res.getDesc());
|
||||
headers.add(j, h);
|
||||
});
|
||||
|
||||
method.put("req_headers", headers);
|
||||
|
||||
Template apiTemplate = BeetlTemplateUtil.getByName(YAPI_RESULT_TPL);
|
||||
|
||||
apiTemplate.binding(TemplateVariable.RESPONSE_LIST.getVariable(), generateJson(apiMethodDoc.getResponseParams()));
|
||||
String json = apiTemplate.render();
|
||||
method.put("res_body", json);
|
||||
|
||||
if (StringUtil.isNotEmpty(apiMethodDoc.getResponseUsage())) {
|
||||
method.put("desc", "<pre><code>\n" + apiMethodDoc.getResponseUsage() + "\n</code></pre>\n");
|
||||
}
|
||||
|
||||
methods.add(idx, method);
|
||||
});
|
||||
module.put("list", methods);
|
||||
|
||||
requestItem.add(module);
|
||||
});
|
||||
|
||||
String filePath = config.getOutPath();
|
||||
filePath = filePath + DocGlobalConstants.YAPI_JSON;
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
String data = gson.toJson(requestItem);
|
||||
FileUtil.nioWriteFile(data, filePath);
|
||||
}
|
||||
|
||||
private static String generateJson(List<ApiParam> responseParams) {
|
||||
StringBuffer re = new StringBuffer("\"type\":\"object\",\n\"properties\":{\n");
|
||||
HashSet<String> required = new HashSet<>();
|
||||
responseParams.stream().forEach(apiParam -> {
|
||||
re.append(getTypeAndPropertiesJson(apiParam));
|
||||
if (apiParam.isRequired()) {
|
||||
required.add(apiParam.getField());
|
||||
}
|
||||
});
|
||||
Gson gs = new Gson();
|
||||
re.append("\"required\":\"" + gs.toJson(required.toArray()) + "\"");
|
||||
re.append("\t}");
|
||||
return re.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字段类型转换为yapi的字段类型
|
||||
*
|
||||
* @param type java type
|
||||
* @return String
|
||||
*/
|
||||
private static String changeType(String type) {
|
||||
switch (type) {
|
||||
case "boolean":
|
||||
return "boolean";
|
||||
case "int32":
|
||||
return "integer";
|
||||
case "int64":
|
||||
return "number";
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个参数拼接字符串
|
||||
*
|
||||
* @param param ApiParam
|
||||
* @return String
|
||||
*/
|
||||
private static String getTypeAndPropertiesJson(ApiParam param) {
|
||||
StringBuffer resultJson = new StringBuffer();
|
||||
|
||||
resultJson.append("\"" + param.getField() + "\":{");
|
||||
resultJson.append("\"type\":\"" + changeType(param.getType()) + "\", ");
|
||||
|
||||
if (param.getChildren() != null && param.getChildren().size() > 0) {
|
||||
if (param.getType().equals("object")) {
|
||||
resultJson.append(" \"properties\":{");
|
||||
param.getChildren().forEach(child -> {
|
||||
resultJson.append(getTypeAndPropertiesJson(child));
|
||||
});
|
||||
} else if (param.getType().equals("array")) {
|
||||
resultJson.append(" \"items\":{");
|
||||
resultJson.append("\"type\":\"object\",\n\"properties\":{\n");
|
||||
param.getChildren().forEach(child -> {
|
||||
resultJson.append(getTypeAndPropertiesJson(child));
|
||||
});
|
||||
resultJson.append("\t},");
|
||||
}
|
||||
resultJson.append("},");
|
||||
}
|
||||
resultJson.append("},");
|
||||
return resultJson.toString();
|
||||
}
|
||||
}
|
|
@ -23,9 +23,11 @@
|
|||
package com.power.doc.builder.rpc;
|
||||
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.FrameworkEnum;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.rpc.RpcApiDoc;
|
||||
import com.power.doc.template.RpcDocBuildTemplate;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -58,15 +60,17 @@ public class RpcAdocBuilder {
|
|||
* @param javaProjectBuilder ProjectDocConfigBuilder
|
||||
*/
|
||||
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
|
||||
config.setFramework(FrameworkEnum.DUBBO.getFramework());
|
||||
config.setAdoc(true);
|
||||
config.setShowJavaType(true);
|
||||
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
RpcDocBuildTemplate docBuildTemplate = new RpcDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<RpcApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
if (config.isAllInOne()) {
|
||||
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, RPC_ALL_IN_ONE_ADOC_TPL, INDEX_DOC);
|
||||
String docName = builderTemplate.allInOneDocName(config, INDEX_DOC, ".adoc");
|
||||
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, RPC_ALL_IN_ONE_ADOC_TPL, docName);
|
||||
} else {
|
||||
builderTemplate.buildApiDoc(apiDocList, config, RPC_API_DOC_ADOC_TPL, API_EXTENSION);
|
||||
builderTemplate.buildErrorCodeDoc(config, ERROR_CODE_LIST_ADOC_TPL, ERROR_CODE_LIST_ADOC);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
*/
|
||||
package com.power.doc.builder.rpc;
|
||||
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.constants.FrameworkEnum;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.rpc.RpcApiAllData;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
@ -39,6 +41,9 @@ public class RpcApiDataBuilder {
|
|||
*/
|
||||
public static RpcApiAllData getApiData(ApiConfig config) {
|
||||
config.setShowJavaType(true);
|
||||
if (StringUtil.isEmpty(config.getFramework())) {
|
||||
config.setFramework(FrameworkEnum.DUBBO.getFramework());
|
||||
}
|
||||
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
|
||||
builderTemplate.checkAndInitForGetApiData(config);
|
||||
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
|
||||
|
|
|
@ -25,15 +25,17 @@ package com.power.doc.builder.rpc;
|
|||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.DateTimeUtil;
|
||||
import com.power.common.util.FileUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.builder.BaseDocBuilderTemplate;
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.FrameworkEnum;
|
||||
import com.power.doc.constants.TemplateVariable;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.ApiErrorCode;
|
||||
import com.power.doc.model.rpc.RpcApiAllData;
|
||||
import com.power.doc.model.rpc.RpcApiDoc;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.RpcDocBuildTemplate;
|
||||
import com.power.doc.utils.BeetlTemplateUtil;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
@ -56,7 +58,10 @@ public class RpcDocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
private static long now = System.currentTimeMillis();
|
||||
|
||||
public void checkAndInit(ApiConfig config) {
|
||||
super.checkAndInit(config);
|
||||
if (StringUtil.isEmpty(config.getFramework())) {
|
||||
config.setFramework(FrameworkEnum.DUBBO.getFramework());
|
||||
}
|
||||
super.checkAndInit(config,false);
|
||||
config.setOutPath(config.getOutPath() + FILE_SEPARATOR + RPC_OUT_DIR);
|
||||
}
|
||||
|
||||
|
@ -112,6 +117,7 @@ public class RpcDocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
tpl.binding(TemplateVariable.PROJECT_NAME.getVariable(), config.getProjectName());
|
||||
tpl.binding(TemplateVariable.RPC_CONSUMER_CONFIG.getVariable(), rpcConfigConfigContent);
|
||||
setDirectoryLanguageVariable(config, tpl);
|
||||
setCssCDN(config, tpl);
|
||||
FileUtil.nioWriteFile(tpl.render(), outPath + FILE_SEPARATOR + outPutFileName);
|
||||
}
|
||||
|
||||
|
@ -188,7 +194,7 @@ public class RpcDocBuilderTemplate extends BaseDocBuilderTemplate {
|
|||
this.checkAndInitForGetApiData(config);
|
||||
config.setMd5EncryptedHtmlName(true);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
IDocBuildTemplate docBuildTemplate = new RpcDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
return docBuildTemplate.getApiData(configBuilder);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,11 @@ package com.power.doc.builder.rpc;
|
|||
|
||||
import com.power.common.util.FileUtil;
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.FrameworkEnum;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.rpc.RpcApiDoc;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.RpcDocBuildTemplate;
|
||||
import com.power.doc.utils.BeetlTemplateUtil;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
@ -68,10 +71,12 @@ public class RpcHtmlBuilder {
|
|||
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
RpcDocBuildTemplate docBuildTemplate = new RpcDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<RpcApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
Template indexCssTemplate = BeetlTemplateUtil.getByName(ALL_IN_ONE_CSS);
|
||||
FileUtil.nioWriteFile(indexCssTemplate.render(), config.getOutPath() + FILE_SEPARATOR + ALL_IN_ONE_CSS);
|
||||
FileUtil.nioWriteFile(indexCssTemplate.render(), config.getOutPath() + FILE_SEPARATOR + ALL_IN_ONE_CSS_OUT);
|
||||
builderTemplate.copyJarFile("css/" + FONT_STYLE, config.getOutPath() + FILE_SEPARATOR + FONT_STYLE);
|
||||
builderTemplate.copyJarFile("js/" + JQUERY, config.getOutPath() + FILE_SEPARATOR + JQUERY);
|
||||
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, RPC_ALL_IN_ONE_HTML_TPL, INDEX_HTML);
|
||||
builderTemplate.buildSearchJs(apiDocList, config, RPC_ALL_IN_ONE_SEARCH_TPL, SEARCH_JS);
|
||||
}
|
||||
|
|
|
@ -24,10 +24,10 @@ package com.power.doc.builder.rpc;
|
|||
|
||||
import com.power.common.util.DateTimeUtil;
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.rpc.RpcApiDoc;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.RpcDocBuildTemplate;
|
||||
import com.thoughtworks.qdox.JavaProjectBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -54,23 +54,24 @@ public class RpcMarkdownBuilder {
|
|||
/**
|
||||
* Only for smart-doc maven plugin and gradle plugin.
|
||||
*
|
||||
* @param config ApiConfig
|
||||
* @param apiConfig ApiConfig
|
||||
* @param javaProjectBuilder ProjectDocConfigBuilder
|
||||
*/
|
||||
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
|
||||
config.setAdoc(false);
|
||||
config.setShowJavaType(true);
|
||||
public static void buildApiDoc(ApiConfig apiConfig, JavaProjectBuilder javaProjectBuilder) {
|
||||
apiConfig.setAdoc(false);
|
||||
apiConfig.setShowJavaType(true);
|
||||
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
IDocBuildTemplate docBuildTemplate = new RpcDocBuildTemplate();
|
||||
builderTemplate.checkAndInit(apiConfig);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(apiConfig, javaProjectBuilder);
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(apiConfig.getFramework());
|
||||
List<RpcApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
if (config.isAllInOne()) {
|
||||
String version = config.isCoverOld() ? "" : "-V" + DateTimeUtil.long2Str(System.currentTimeMillis(), DATE_FORMAT);
|
||||
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, RPC_ALL_IN_ONE_MD_TPL, "rpc-all" + version + ".md");
|
||||
if (apiConfig.isAllInOne()) {
|
||||
String version = apiConfig.isCoverOld() ? "" : "-V" + DateTimeUtil.long2Str(System.currentTimeMillis(), DATE_FORMAT);
|
||||
String docName = builderTemplate.allInOneDocName(apiConfig, "rpc-all" + version, ".md");
|
||||
builderTemplate.buildAllInOne(apiDocList, apiConfig, javaProjectBuilder, RPC_ALL_IN_ONE_MD_TPL, docName);
|
||||
} else {
|
||||
builderTemplate.buildApiDoc(apiDocList, config, RPC_API_DOC_MD_TPL, API_EXTENSION);
|
||||
builderTemplate.buildErrorCodeDoc(config, ERROR_CODE_LIST_MD_TPL, ERROR_CODE_LIST_MD);
|
||||
builderTemplate.buildApiDoc(apiDocList, apiConfig, RPC_API_DOC_MD_TPL, API_EXTENSION);
|
||||
builderTemplate.buildErrorCodeDoc(apiConfig, ERROR_CODE_LIST_MD_TPL, ERROR_CODE_LIST_MD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,16 +23,19 @@
|
|||
package com.power.doc.builder.rpc;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.OkHttp3Util;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.TornaConstants;
|
||||
import com.power.doc.factory.BuildTemplateFactory;
|
||||
import com.power.doc.model.ApiConfig;
|
||||
import com.power.doc.model.rpc.RpcApiDoc;
|
||||
import com.power.doc.model.torna.Apis;
|
||||
import com.power.doc.model.torna.DubboInfo;
|
||||
import com.power.doc.model.torna.TornaApi;
|
||||
import com.power.doc.model.torna.TornaDic;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
import com.power.doc.template.RpcDocBuildTemplate;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.power.doc.utils.TornaUtil;
|
||||
|
@ -76,14 +79,15 @@ public class RpcTornaBuilder {
|
|||
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
|
||||
builderTemplate.checkAndInit(config);
|
||||
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
|
||||
RpcDocBuildTemplate docBuildTemplate = new RpcDocBuildTemplate();
|
||||
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
|
||||
List<RpcApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
|
||||
buildTorna(apiDocList, config,javaProjectBuilder);
|
||||
buildTorna(apiDocList, config, javaProjectBuilder);
|
||||
}
|
||||
|
||||
public static void buildTorna(List<RpcApiDoc> apiDocs, ApiConfig apiConfig,JavaProjectBuilder builder) {
|
||||
public static void buildTorna(List<RpcApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) {
|
||||
TornaApi tornaApi = new TornaApi();
|
||||
tornaApi.setAuthor(StringUtil.isEmpty(apiConfig.getAuthor()) ? System.getProperty("user.name") : apiConfig.getAuthor());
|
||||
tornaApi.setIsReplace((apiConfig.getReplace() == null || apiConfig.getReplace()) ? 1 : 0);
|
||||
Apis api;
|
||||
List<Apis> apisList = new ArrayList<>();
|
||||
//添加接口数据
|
||||
|
@ -100,23 +104,28 @@ public class RpcTornaBuilder {
|
|||
.setVersion(a.getVersion())
|
||||
.setDependency(TornaUtil.buildDependencies(apiConfig.getRpcApiDependencies()))
|
||||
.setInterfaceName(a.getName()));
|
||||
api.setOrderIndex(a.getOrder());
|
||||
apisList.add(api);
|
||||
}
|
||||
tornaApi.setCommonErrorCodes(buildErrorCode(apiConfig));
|
||||
tornaApi.setApis(apisList);
|
||||
//推送文档信息
|
||||
//Build push document information
|
||||
Map<String, String> requestJson = TornaConstants.buildParams(PUSH, new Gson().toJson(tornaApi), apiConfig);
|
||||
|
||||
//推送字典信息
|
||||
Map<String,Object> dicMap = new HashMap<>(2);
|
||||
List<TornaDic> docDicts =TornaUtil.buildTornaDic(DocUtil.buildDictionary(apiConfig,builder));
|
||||
dicMap.put("enums",docDicts);
|
||||
//Push dictionary information
|
||||
Map<String, Object> dicMap = new HashMap<>(2);
|
||||
List<TornaDic> docDicts = TornaUtil.buildTornaDic(DocUtil.buildDictionary(apiConfig, builder));
|
||||
|
||||
if (CollectionUtil.isNotEmpty(docDicts)) {
|
||||
dicMap.put("enums", docDicts);
|
||||
Map<String, String> dicRequestJson = TornaConstants.buildParams(ENUM_PUSH, new Gson().toJson(dicMap), apiConfig);
|
||||
String dicResponseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(dicRequestJson));
|
||||
TornaUtil.printDebugInfo(apiConfig, dicResponseMsg, dicRequestJson, ENUM_PUSH);
|
||||
}
|
||||
Map<String, String> dicRequestJson = TornaConstants.buildParams(ENUM_PUSH, new Gson().toJson(dicMap), apiConfig);
|
||||
//获取返回结果
|
||||
//Get the response result
|
||||
String responseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(requestJson));
|
||||
String dicResponseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(dicRequestJson));
|
||||
//开启调试时打印请求信息
|
||||
TornaUtil.printDebugInfo(apiConfig, responseMsg, requestJson,PUSH);
|
||||
TornaUtil.printDebugInfo(apiConfig, dicResponseMsg, dicRequestJson,ENUM_PUSH);
|
||||
//Print the log of pushing documents to Torna
|
||||
TornaUtil.printDebugInfo(apiConfig, responseMsg, requestJson, PUSH);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package com.power.doc.constants;
|
||||
|
||||
/**
|
||||
* @author chen qi 2021-07-15 10:55
|
||||
**/
|
||||
public enum ApiReqParamInTypeEnum {
|
||||
|
||||
/**
|
||||
* header param
|
||||
*/
|
||||
HEADER("header"),
|
||||
|
||||
/**
|
||||
* query param
|
||||
*/
|
||||
QUERY("query"),
|
||||
|
||||
/**
|
||||
* path param
|
||||
*/
|
||||
PATH("path");
|
||||
|
||||
private final String value;
|
||||
|
||||
ApiReqParamInTypeEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -39,6 +39,11 @@ public interface DocAnnotationConstants {
|
|||
|
||||
String SHORT_JSON_IGNORE = "JsonIgnore";
|
||||
|
||||
/**
|
||||
* jackson JsonIgnoreProperties annotation
|
||||
*/
|
||||
String SHORT_JSON_IGNORE_PROPERTIES = "JsonIgnoreProperties";
|
||||
|
||||
String SHORT_JSON_PROPERTY = "JsonProperty";
|
||||
|
||||
String SHORT_JSON_FIELD = "JSONField";
|
||||
|
@ -66,4 +71,20 @@ public interface DocAnnotationConstants {
|
|||
String JSON_CREATOR = "JsonCreator";
|
||||
|
||||
String MAX = "max";
|
||||
|
||||
String SIZE = "size";
|
||||
|
||||
String LENGTH = "length";
|
||||
|
||||
String JSON_PROPERTY = "JsonProperty";
|
||||
|
||||
/**
|
||||
* Fastjson JSONType annotation
|
||||
*/
|
||||
String SHORT_JSON_TYPE = "JSONType";
|
||||
|
||||
/**
|
||||
* Fastjson JSONType annotation ignores prop
|
||||
*/
|
||||
String IGNORE_PROP = "ignores";
|
||||
}
|
||||
|
|
|
@ -91,7 +91,17 @@ public interface DocGlobalConstants {
|
|||
|
||||
String SINGLE_DICT_HTML_TPL = "html/dict.html";
|
||||
|
||||
String ALL_IN_ONE_CSS = "AllInOne.css";
|
||||
String ALL_IN_ONE_CSS = "css/AllInOne.css";
|
||||
|
||||
String ALL_IN_ONE_CSS_OUT = "AllInOne.css";
|
||||
|
||||
String FONT_STYLE = "font.css";
|
||||
|
||||
String HIGH_LIGHT_JS = "highlight.min.js";
|
||||
|
||||
String JQUERY = "jquery.min.js";
|
||||
|
||||
String HIGH_LIGHT_STYLE = "xt256.min.css";
|
||||
|
||||
String RPC_OUT_DIR = "rpc";
|
||||
|
||||
|
@ -137,10 +147,16 @@ public interface DocGlobalConstants {
|
|||
|
||||
String MODE_AND_VIEW_FULLY = "org.springframework.web.servlet.ModelAndView";
|
||||
|
||||
String FEIGN_CLIENT_FULLY = "org.springframework.cloud.netflix.feign.FeignClient";
|
||||
|
||||
String FEIGN_CLIENT = "FeignClient";
|
||||
|
||||
String MULTIPART_FILE_FULLY = "org.springframework.web.multipart.MultipartFile";
|
||||
|
||||
String JAVA_OBJECT_FULLY = "java.lang.Object";
|
||||
|
||||
String JAVA_BOOLEAN = "java.lang.Boolean";
|
||||
|
||||
String JAVA_STRING_FULLY = "java.lang.String";
|
||||
|
||||
String JAVA_MAP_FULLY = "java.util.Map";
|
||||
|
@ -202,4 +218,59 @@ public interface DocGlobalConstants {
|
|||
String DUBBO_SWAGGER = "org.apache.dubbo.rpc.protocol.rest.integration.swagger.DubboSwaggerApiListingResource";
|
||||
|
||||
String ARRAY = "array";
|
||||
|
||||
String OBJECT = "object";
|
||||
|
||||
String JSON_PROPERTY_READ_WRITE = "JsonProperty.Access.READ_WRITE";
|
||||
|
||||
String JSON_PROPERTY_READ_ONLY = "JsonProperty.Access.READ_ONLY";
|
||||
|
||||
String JSON_PROPERTY_WRITE_ONLY = "JsonProperty.Access.WRITE_ONLY";
|
||||
|
||||
String CSS_CDN_CH = "https://fonts.googleapis.cnpmjs.org";
|
||||
|
||||
String CSS_CDN = "https://fonts.googleapis.com";
|
||||
|
||||
String PATH_DELIMITER = "/";
|
||||
|
||||
|
||||
/**
|
||||
* JAX-RS@PATH
|
||||
*/
|
||||
String JAX_PATH_FULLY = "javax.ws.rs.Path";
|
||||
/**
|
||||
* JAX-RS@Produces
|
||||
*/
|
||||
String JAX_PRODUCES_FULLY = "javax.ws.rs.Produces";
|
||||
/**
|
||||
* JAX-RS@Produces
|
||||
*/
|
||||
String JAX_CONSUMES_FULLY = "javax.ws.rs.Consumes";
|
||||
/**
|
||||
* JAX-RS@GET
|
||||
*/
|
||||
String JAX_GET_FULLY = "javax.ws.rs.GET";
|
||||
/**
|
||||
* JAX-RS@POST
|
||||
*/
|
||||
String JAX_POST_FULLY = "javax.ws.rs.POST";
|
||||
/**
|
||||
* JAX-RS@PUT
|
||||
*/
|
||||
String JAX_PUT_FULLY = "javax.ws.rs.PUT";
|
||||
/**
|
||||
* JAX-RS@DELETE
|
||||
*/
|
||||
String JAXB_DELETE_FULLY = "javax.ws.rs.DELETE";
|
||||
|
||||
String HIGH_LIGHT_CSS_URL_FORMAT = "https://cdn.bootcdn.net/ajax/libs/highlight.js/10.3.2/styles/%s.min.css";
|
||||
|
||||
String HIGH_LIGHT_DEFAULT_STYLE = "xt256";
|
||||
|
||||
String HIGH_LIGHT_CSS_DEFAULT = "xt256.min.css";
|
||||
|
||||
String HIGH_LIGHT_CSS_RANDOM_LIGHT = "randomLight";
|
||||
|
||||
String HIGH_LIGHT_CSS_RANDOM_DARK = "randomDark";
|
||||
|
||||
}
|
||||
|
|
|
@ -114,4 +114,19 @@ public interface DocTags {
|
|||
String IGNORE_RESPONSE_BODY_ADVICE = "ignoreResponseBodyAdvice";
|
||||
|
||||
String IGNORE_REQUEST_BODY_ADVICE = "ignoreRequestBodyAdvice";
|
||||
|
||||
/**
|
||||
* response tag @since 2.2.0
|
||||
*/
|
||||
String API_RESPONSE = "response";
|
||||
|
||||
/**
|
||||
* custom @tag
|
||||
*/
|
||||
String TAG = "tag";
|
||||
|
||||
/**
|
||||
* custom @dubboRest tag
|
||||
*/
|
||||
String DUBBO_REST = "dubboRest";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* smart-doc https://github.com/shalousun/smart-doc
|
||||
*
|
||||
* Copyright (C) 2018-2021 smart-doc
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.power.doc.constants;
|
||||
|
||||
import com.power.common.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Smart-doc Supported Framework
|
||||
*
|
||||
* @author yu 2021/6/27.
|
||||
*/
|
||||
public enum FrameworkEnum {
|
||||
|
||||
/**
|
||||
* Apache Dubbo
|
||||
*/
|
||||
DUBBO("dubbo", "com.power.doc.template.RpcDocBuildTemplate"),
|
||||
|
||||
/**
|
||||
* Spring Framework
|
||||
*/
|
||||
SPRING("spring", "com.power.doc.template.SpringBootDocBuildTemplate"),
|
||||
|
||||
/**
|
||||
* JAX-RS
|
||||
*/
|
||||
JAX_RS("JAX-RS", "com.power.doc.template.JaxrsDocBuildTemplate");
|
||||
|
||||
/**
|
||||
* Framework name
|
||||
*/
|
||||
private String framework;
|
||||
|
||||
/**
|
||||
* Framework IDocBuildTemplate implement
|
||||
*/
|
||||
private String className;
|
||||
|
||||
|
||||
FrameworkEnum(String framework, String className) {
|
||||
this.framework = framework;
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public static String getClassNameByFramework(String framework) {
|
||||
String className = "";
|
||||
if (StringUtil.isEmpty(framework)) {
|
||||
return className;
|
||||
}
|
||||
for (FrameworkEnum e : FrameworkEnum.values()) {
|
||||
if (e.framework.equalsIgnoreCase(framework)) {
|
||||
className = e.className;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
|
||||
public String getFramework() {
|
||||
return framework;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
}
|
|
@ -229,7 +229,7 @@ public class HighlightStyle {
|
|||
|
||||
|
||||
/**
|
||||
* 随机一个 light style
|
||||
* Randomly select a light style
|
||||
*
|
||||
* @param random Random
|
||||
* @return String of random
|
||||
|
@ -239,7 +239,7 @@ public class HighlightStyle {
|
|||
}
|
||||
|
||||
/**
|
||||
* 随机一个 dark style
|
||||
* Randomly select a dark style
|
||||
*
|
||||
* @param random Random
|
||||
* @return String of random
|
||||
|
@ -249,7 +249,7 @@ public class HighlightStyle {
|
|||
}
|
||||
|
||||
/**
|
||||
* 随机一个 style
|
||||
* Randomly select a style
|
||||
*
|
||||
* @param random Random
|
||||
* @return String of random
|
||||
|
@ -271,10 +271,9 @@ public class HighlightStyle {
|
|||
}
|
||||
|
||||
/**
|
||||
* |
|
||||
* 高亮样式是否存在
|
||||
* Does the highlight style exist?
|
||||
*
|
||||
* @param style 高亮样式
|
||||
* @param style Highlight style
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean containsStyle(String style) {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package com.power.doc.constants;
|
||||
|
||||
/**
|
||||
* JAX-RS Annotations
|
||||
*
|
||||
* @author Zxq
|
||||
*/
|
||||
public interface JAXRSAnnotations {
|
||||
/**
|
||||
* JAX-RS@PATH
|
||||
*/
|
||||
String JAX_PATH = "Path";
|
||||
/**
|
||||
* JAX-RS@Produces
|
||||
*/
|
||||
String JAX_PRODUCES = "Produces";
|
||||
/**
|
||||
* JAX-RS@HeaderParam
|
||||
*/
|
||||
String JAX_HEADER_PARAM = "HeaderParam";
|
||||
/**
|
||||
* JAX-RS@PathParam
|
||||
*/
|
||||
String JAX_PATH_PARAM = "PathParam";
|
||||
/**
|
||||
* JAX-RS@QueryParam
|
||||
*/
|
||||
String JAX_QUERY_PARAM = "QueryParam";
|
||||
/**
|
||||
* JAX-RS@FormParam
|
||||
*/
|
||||
String JAX_FORM_PARAM = "FormParam";
|
||||
/**
|
||||
* JAX-RS@Consumes
|
||||
*/
|
||||
String JAX_CONSUMES = "Consumes";
|
||||
|
||||
/**
|
||||
* JAX-RS@GET
|
||||
*/
|
||||
String GET = "GET";
|
||||
/**
|
||||
* JAX-RS@POST
|
||||
*/
|
||||
String POST = "POST";
|
||||
/**
|
||||
* JAX-RS@PUT
|
||||
*/
|
||||
String PUT = "PUT";
|
||||
/**
|
||||
* JAX-RS@DELETE
|
||||
*/
|
||||
String DELETE = "DELETE";
|
||||
}
|
|
@ -50,4 +50,8 @@ public interface SpringMvcAnnotations {
|
|||
String REST_CONTROLLER = "RestController";
|
||||
|
||||
String PATH_VARIABLE = "PathVariable";
|
||||
|
||||
String SESSION_ATTRIBUTE = "SessionAttribute";
|
||||
|
||||
String REQUEST_ATTRIBUTE="RequestAttribute";
|
||||
}
|
||||
|
|
|
@ -51,10 +51,14 @@ public enum TemplateVariable {
|
|||
RPC_CONSUMER_CONFIG("consumerConfigExample"),
|
||||
REQUEST_EXAMPLE("isRequestExample"),
|
||||
RESPONSE_EXAMPLE("isResponseExample"),
|
||||
DISPLAY_REQUEST_PARAMS("displayRequestParams"),
|
||||
DISPLAY_RESPONSE_PARAMS("displayResponseParams"),
|
||||
RESPONSE_LIST("respList"),
|
||||
ORDER("order"),
|
||||
INDEX_ALIAS("alias"),
|
||||
DIRECTORY_TREE("directoryTree");
|
||||
DIRECTORY_TREE("directoryTree"),
|
||||
HIGH_LIGHT_CSS_LINK("highlightCssLink"),
|
||||
CSS_CND("css_cdn");
|
||||
|
||||
private String variable;
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ public class TornaConstants {
|
|||
if (StringUtils.isNotBlank(data)) {
|
||||
data = URLEncoder.encode(data, "utf-8");
|
||||
}
|
||||
// 公共参数
|
||||
// Public request parameters for pushing documents to Torna
|
||||
param.put("name", name);
|
||||
param.put("app_key", config.getAppKey());
|
||||
param.put("data", data);
|
||||
|
@ -112,23 +112,16 @@ public class TornaConstants {
|
|||
}
|
||||
|
||||
/**
|
||||
* 生成md5,全部大写
|
||||
* Generate md5 and convert to uppercase
|
||||
*
|
||||
* @param message 消息
|
||||
* @param message message
|
||||
* @return String
|
||||
*/
|
||||
public static String md5(String message) {
|
||||
try {
|
||||
// 1 创建一个提供信息摘要算法的对象,初始化为md5算法对象
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
|
||||
// 2 将消息变成byte数组
|
||||
byte[] input = message.getBytes();
|
||||
|
||||
// 3 计算后获得字节数组,这就是那128位了
|
||||
byte[] buff = md.digest(input);
|
||||
|
||||
// 4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串
|
||||
return byte2hex(buff);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -136,8 +129,7 @@ public class TornaConstants {
|
|||
}
|
||||
|
||||
/**
|
||||
* 二进制转十六进制字符串
|
||||
*
|
||||
* Convert byte array to hex
|
||||
* @param bytes byte array
|
||||
* @return String
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* smart-doc https://github.com/shalousun/smart-doc
|
||||
*
|
||||
* Copyright (C) 2018-2021 smart-doc
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.power.doc.factory;
|
||||
|
||||
import com.power.doc.constants.FrameworkEnum;
|
||||
import com.power.doc.template.IDocBuildTemplate;
|
||||
|
||||
/**
|
||||
* @author yu 2021/6/27.
|
||||
*/
|
||||
public class BuildTemplateFactory {
|
||||
|
||||
/**
|
||||
* Get Doc build template
|
||||
*
|
||||
* @param framework framework name
|
||||
* @param <T> API doc type
|
||||
* @return Implements of IDocBuildTemplate
|
||||
*/
|
||||
public static <T> IDocBuildTemplate<T> getDocBuildTemplate(String framework) {
|
||||
String className = FrameworkEnum.getClassNameByFramework(framework);
|
||||
try {
|
||||
return (IDocBuildTemplate) Class.forName(className).newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("The class=>" + className + " is not found , smart-doc currently supported framework name can only be set in [dubbo, spring].");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* smart-doc https://github.com/shalousun/smart-doc
|
||||
*
|
||||
* Copyright (C) 2018-2021 smart-doc
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.power.doc.function;
|
||||
|
||||
import org.beetl.core.Context;
|
||||
import org.beetl.core.Function;
|
||||
|
||||
/**
|
||||
* @author yu 2021/6/26.
|
||||
*/
|
||||
public class HtmlEscape implements Function {
|
||||
|
||||
@Override
|
||||
public String call(Object[] paras, Context ctx) {
|
||||
String str = String.valueOf(paras[0]).replaceAll("&", "&")
|
||||
.replaceAll("\"",""");
|
||||
return str;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.power.doc.function;
|
||||
|
||||
import org.beetl.core.Context;
|
||||
import org.beetl.core.Function;
|
||||
|
||||
/**
|
||||
* @author yu 2021/7/24.
|
||||
*/
|
||||
public class RemoveLineBreaks implements Function {
|
||||
|
||||
@Override
|
||||
public String call(Object[] paras, Context ctx) {
|
||||
String str = String.valueOf(paras[0])
|
||||
.replaceAll("\n", " ")
|
||||
.replaceAll("\r"," ");
|
||||
return str;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* smart-doc https://github.com/shalousun/smart-doc
|
||||
*
|
||||
* Copyright (C) 2018-2021 smart-doc
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.power.doc.handler;
|
||||
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.JAXRSAnnotations;
|
||||
import com.power.doc.model.ApiReqParam;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.thoughtworks.qdox.model.JavaAnnotation;
|
||||
import com.thoughtworks.qdox.model.JavaMethod;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Zxq
|
||||
*/
|
||||
public class JaxrsHeaderHandler {
|
||||
|
||||
/**
|
||||
* Handle JAX RS Header
|
||||
* @param method method
|
||||
* @param projectBuilder ProjectDocConfigBuilder
|
||||
* @return list of ApiReqParam
|
||||
*/
|
||||
public List<ApiReqParam> handle(JavaMethod method, ProjectDocConfigBuilder projectBuilder) {
|
||||
List<JavaAnnotation> annotations = method.getAnnotations();
|
||||
List<ApiReqParam> ApiReqParams = new ArrayList<>();
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
// hit target head annotation
|
||||
if (JAXRSAnnotations.JAX_HEADER_PARAM.equals(annotation.getType().getName())) {
|
||||
ApiReqParam ApiReqParam = new ApiReqParam();
|
||||
// Obtain header value
|
||||
ApiReqParam.setValue(DocUtil.getRequestHeaderValue(annotation).replaceAll("\"", ""));
|
||||
ApiReqParam.setName(DocUtil.getRequestHeaderValue(annotation).replaceAll("\"", ""));
|
||||
ApiReqParam.setType("string");
|
||||
ApiReqParam.setDesc("desc");
|
||||
ApiReqParams.add(ApiReqParam);
|
||||
}
|
||||
}
|
||||
return ApiReqParams;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* smart-doc https://github.com/shalousun/smart-doc
|
||||
*
|
||||
* Copyright (C) 2018-2021 smart-doc
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.power.doc.handler;
|
||||
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.common.util.UrlUtil;
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.*;
|
||||
import com.power.doc.model.request.JaxrsPathMapping;
|
||||
import com.power.doc.utils.DocUrlUtil;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.thoughtworks.qdox.model.JavaAnnotation;
|
||||
import com.thoughtworks.qdox.model.JavaMethod;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.power.doc.constants.DocTags.DEPRECATED;
|
||||
import static com.power.doc.constants.DocTags.IGNORE;
|
||||
|
||||
/**
|
||||
* dubbo Rest 注解处理器
|
||||
*
|
||||
* @author Zxq
|
||||
*/
|
||||
public class JaxrsPathHandler {
|
||||
/**
|
||||
* ANNOTATION_NAMES
|
||||
*/
|
||||
private static final Set<String> ANNOTATION_NAMES = Collections.unmodifiableSet(new HashSet<>(
|
||||
Arrays.asList(JAXRSAnnotations.DELETE,
|
||||
DocGlobalConstants.JAXB_DELETE_FULLY,
|
||||
JAXRSAnnotations.PUT, DocGlobalConstants.JAX_PUT_FULLY,
|
||||
JAXRSAnnotations.GET, DocGlobalConstants.JAX_GET_FULLY,
|
||||
JAXRSAnnotations.POST, DocGlobalConstants.JAX_POST_FULLY
|
||||
)));
|
||||
|
||||
Map<String, String> constantsMap;
|
||||
|
||||
public JaxrsPathMapping handle(ProjectDocConfigBuilder projectBuilder, String baseUrl, JavaMethod method) {
|
||||
|
||||
List<JavaAnnotation> annotations = method.getAnnotations();
|
||||
this.constantsMap = projectBuilder.getConstantsMap();
|
||||
String url;
|
||||
String methodType = null;
|
||||
String shortUrl = null;
|
||||
String mediaType = null;
|
||||
String serverUrl = projectBuilder.getServerUrl();
|
||||
String contextPath = projectBuilder.getApiConfig().getPathPrefix();
|
||||
boolean deprecated = false;
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
String annotationName = annotation.getType().getName();
|
||||
if (JAXRSAnnotations.JAX_PRODUCES.equals(annotationName)) {
|
||||
mediaType = DocUtil.getRequestHeaderValue(annotation);
|
||||
}
|
||||
// Deprecated annotation on method
|
||||
if (DocAnnotationConstants.DEPRECATED.equals(annotationName)) {
|
||||
deprecated = true;
|
||||
}
|
||||
if (JAXRSAnnotations.JAX_PATH.equals(annotationName) ||
|
||||
JAXRSAnnotations.JAX_PATH_PARAM.equals(annotationName) ||
|
||||
DocGlobalConstants.JAX_PATH_FULLY
|
||||
.equals(annotationName)) {
|
||||
shortUrl = DocUtil.handleMappingValue(annotation);
|
||||
}
|
||||
if (ANNOTATION_NAMES.contains(annotationName)) {
|
||||
methodType = annotationName;
|
||||
}
|
||||
}
|
||||
// @deprecated tag on method
|
||||
if (Objects.nonNull(method.getTagByName(DEPRECATED))) {
|
||||
deprecated = true;
|
||||
}
|
||||
JaxrsPathMapping jaxrsPathMapping = getJaxbPathMapping(projectBuilder, baseUrl, method, shortUrl, serverUrl, contextPath);
|
||||
if (jaxrsPathMapping != null) {
|
||||
return jaxrsPathMapping.setDeprecated(deprecated)
|
||||
.setMethodType(methodType)
|
||||
.setMediaType(mediaType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private JaxrsPathMapping getJaxbPathMapping(ProjectDocConfigBuilder projectBuilder,
|
||||
String baseUrl, JavaMethod method,
|
||||
String shortUrl,
|
||||
String serverUrl,
|
||||
String contextPath) {
|
||||
String url;
|
||||
if (Objects.nonNull(shortUrl)) {
|
||||
if (Objects.nonNull(method.getTagByName(IGNORE))) {
|
||||
return null;
|
||||
}
|
||||
shortUrl = StringUtil.removeQuotes(shortUrl);
|
||||
List<String> urls = DocUtil.split(shortUrl);
|
||||
url = String.join(DocGlobalConstants.PATH_DELIMITER, serverUrl, contextPath, baseUrl, shortUrl);
|
||||
shortUrl = String.join(DocGlobalConstants.PATH_DELIMITER, DocGlobalConstants.PATH_DELIMITER, contextPath, baseUrl, shortUrl);
|
||||
if (urls.size() > 1) {
|
||||
url = DocUrlUtil.getMvcUrls(serverUrl, contextPath + "/" + baseUrl, urls);
|
||||
shortUrl = DocUrlUtil.getMvcUrls(DocGlobalConstants.EMPTY, contextPath + "/" + baseUrl, urls);
|
||||
}
|
||||
for (Map.Entry<String, String> entry : constantsMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if (url.contains(key)) {
|
||||
url = url.replace(key, value).replace("+", "");
|
||||
}
|
||||
if (shortUrl.contains(key)) {
|
||||
shortUrl = shortUrl.replace(key, value).replace("+", "");
|
||||
}
|
||||
}
|
||||
String urlSuffix = projectBuilder.getApiConfig().getUrlSuffix();
|
||||
url = UrlUtil.simplifyUrl(url);
|
||||
shortUrl = UrlUtil.simplifyUrl(shortUrl);
|
||||
if (StringUtil.isNotEmpty(urlSuffix)) {
|
||||
url += urlSuffix;
|
||||
shortUrl += urlSuffix;
|
||||
}
|
||||
return JaxrsPathMapping.builder()
|
||||
.setUrl(StringUtil.trim(url))
|
||||
.setShortUrl(StringUtil.trim(shortUrl));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,10 +23,11 @@
|
|||
package com.power.doc.handler;
|
||||
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.DocAnnotationConstants;
|
||||
import com.power.doc.constants.DocTags;
|
||||
import com.power.doc.constants.SpringMvcAnnotations;
|
||||
import com.power.doc.model.ApiReqHeader;
|
||||
import com.power.doc.model.ApiReqParam;
|
||||
import com.power.doc.utils.DocClassUtil;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.thoughtworks.qdox.model.JavaAnnotation;
|
||||
|
@ -45,11 +46,13 @@ public class SpringMVCRequestHeaderHandler {
|
|||
/**
|
||||
* handle Spring MVC Request Header
|
||||
*
|
||||
* @param method JavaMethod
|
||||
* @param method JavaMethod
|
||||
* @param projectBuilder projectBuilder
|
||||
* @return list of ApiReqHeader
|
||||
*/
|
||||
public List<ApiReqHeader> handle(JavaMethod method) {
|
||||
List<ApiReqHeader> mappingHeaders = new ArrayList<>();
|
||||
public List<ApiReqParam> handle(JavaMethod method, ProjectDocConfigBuilder projectBuilder) {
|
||||
Map<String, String> constantsMap = projectBuilder.getConstantsMap();
|
||||
List<ApiReqParam> mappingHeaders = new ArrayList<>();
|
||||
List<JavaAnnotation> annotations = method.getAnnotations();
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
String annotationName = annotation.getType().getValue();
|
||||
|
@ -71,20 +74,31 @@ public class SpringMVCRequestHeaderHandler {
|
|||
processMappingHeaders(header, mappingHeaders);
|
||||
}
|
||||
}
|
||||
List<ApiReqHeader> reqHeaders = new ArrayList<>();
|
||||
List<ApiReqParam> reqHeaders = new ArrayList<>();
|
||||
for (JavaParameter javaParameter : method.getParameters()) {
|
||||
List<JavaAnnotation> javaAnnotations = javaParameter.getAnnotations();
|
||||
String className = method.getDeclaringClass().getCanonicalName();
|
||||
Map<String, String> paramMap = DocUtil.getParamsComments(method, DocTags.PARAM, className);
|
||||
String paramName = javaParameter.getName();
|
||||
ApiReqHeader apiReqHeader;
|
||||
ApiReqParam apiReqHeader;
|
||||
for (JavaAnnotation annotation : javaAnnotations) {
|
||||
String annotationName = annotation.getType().getValue();
|
||||
if (SpringMvcAnnotations.REQUEST_HERDER.equals(annotationName)) {
|
||||
apiReqHeader = new ApiReqHeader();
|
||||
apiReqHeader = new ApiReqParam();
|
||||
Map<String, Object> requestHeaderMap = annotation.getNamedParameterMap();
|
||||
if (requestHeaderMap.get(DocAnnotationConstants.VALUE_PROP) != null) {
|
||||
apiReqHeader.setName(StringUtil.removeQuotes((String) requestHeaderMap.get(DocAnnotationConstants.VALUE_PROP)));
|
||||
String attribute = DocUtil.handleRequestHeaderValue(annotation);
|
||||
String constValue = ((String) requestHeaderMap.get(DocAnnotationConstants.VALUE_PROP)).replaceAll("\"", "");
|
||||
if (StringUtil.isEmpty(attribute)) {
|
||||
apiReqHeader.setName(constValue);
|
||||
} else {
|
||||
Object value = constantsMap.get(attribute);
|
||||
if (value == null) {
|
||||
apiReqHeader.setName(constValue);
|
||||
} else {
|
||||
apiReqHeader.setName((String) value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
apiReqHeader.setName(paramName);
|
||||
}
|
||||
|
@ -100,7 +114,8 @@ public class SpringMVCRequestHeaderHandler {
|
|||
}
|
||||
apiReqHeader.setDesc(desc.toString());
|
||||
if (requestHeaderMap.get(DocAnnotationConstants.REQUIRED_PROP) != null) {
|
||||
apiReqHeader.setRequired(!Boolean.FALSE.toString().equals(requestHeaderMap.get(DocAnnotationConstants.REQUIRED_PROP)));
|
||||
apiReqHeader.setRequired(!Boolean.FALSE.toString()
|
||||
.equals(requestHeaderMap.get(DocAnnotationConstants.REQUIRED_PROP)));
|
||||
} else {
|
||||
apiReqHeader.setRequired(true);
|
||||
}
|
||||
|
@ -111,8 +126,10 @@ public class SpringMVCRequestHeaderHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
List<ApiReqHeader> allApiReqHeaders = Stream.of(mappingHeaders, reqHeaders)
|
||||
.flatMap(Collection::stream).distinct().collect(Collectors.toList());
|
||||
List<ApiReqParam> allApiReqHeaders = Stream.of(mappingHeaders, reqHeaders)
|
||||
.flatMap(Collection::stream)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
return allApiReqHeaders;
|
||||
}
|
||||
|
||||
|
@ -130,11 +147,15 @@ public class SpringMVCRequestHeaderHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void processMappingHeaders(String header, List<ApiReqHeader> mappingHeaders) {
|
||||
public void processMappingHeaders(String header, List<ApiReqParam> mappingHeaders) {
|
||||
if (header.contains("!=")) {
|
||||
String headerName = header.substring(0, header.indexOf("!"));
|
||||
ApiReqHeader apiReqHeader = ApiReqHeader.builder().setName(headerName)
|
||||
.setRequired(true).setValue(null).setDesc("header condition").setType("string");
|
||||
ApiReqParam apiReqHeader = ApiReqParam.builder()
|
||||
.setName(headerName)
|
||||
.setRequired(true)
|
||||
.setValue(null)
|
||||
.setDesc("header condition")
|
||||
.setType("string");
|
||||
mappingHeaders.add(apiReqHeader);
|
||||
} else {
|
||||
String headerName;
|
||||
|
@ -146,8 +167,12 @@ public class SpringMVCRequestHeaderHandler {
|
|||
} else {
|
||||
headerName = header;
|
||||
}
|
||||
ApiReqHeader apiReqHeader = ApiReqHeader.builder().setName(headerName)
|
||||
.setRequired(true).setValue(headerValue).setDesc("header condition").setType("string");
|
||||
ApiReqParam apiReqHeader = ApiReqParam.builder()
|
||||
.setName(headerName)
|
||||
.setRequired(true)
|
||||
.setValue(headerValue)
|
||||
.setDesc("header condition")
|
||||
.setType("string");
|
||||
mappingHeaders.add(apiReqHeader);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import com.power.doc.utils.DocUtil;
|
|||
import com.thoughtworks.qdox.model.JavaAnnotation;
|
||||
import com.thoughtworks.qdox.model.JavaMethod;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -64,6 +63,7 @@ public class SpringMVCRequestMappingHandler {
|
|||
String shortUrl = null;
|
||||
String mediaType = null;
|
||||
String serverUrl = projectBuilder.getServerUrl();
|
||||
String contextPath = projectBuilder.getApiConfig().getPathPrefix();
|
||||
boolean deprecated = false;
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
String annotationName = annotation.getType().getName();
|
||||
|
@ -108,37 +108,45 @@ public class SpringMVCRequestMappingHandler {
|
|||
return null;
|
||||
}
|
||||
shortUrl = StringUtil.removeQuotes(shortUrl);
|
||||
String[] urls = shortUrl.split(",");
|
||||
if (urls.length > 1) {
|
||||
url = DocUrlUtil.getMvcUrls(serverUrl, controllerBaseUrl, Arrays.asList(urls));
|
||||
shortUrl = DocUrlUtil.getMvcUrls("", controllerBaseUrl, Arrays.asList(urls));
|
||||
List<String> urls = DocUtil.split(shortUrl);
|
||||
if (urls.size() > 1) {
|
||||
url = DocUrlUtil.getMvcUrls(serverUrl, contextPath + "/" + controllerBaseUrl, urls);
|
||||
shortUrl = DocUrlUtil.getMvcUrls(DocGlobalConstants.EMPTY, contextPath + "/" + controllerBaseUrl, urls);
|
||||
} else {
|
||||
url = serverUrl + "/" + controllerBaseUrl + "/" + shortUrl;
|
||||
shortUrl = "/" + controllerBaseUrl + "/" + shortUrl;
|
||||
url = String.join(DocGlobalConstants.PATH_DELIMITER, serverUrl, contextPath, controllerBaseUrl, shortUrl);
|
||||
shortUrl = String.join(DocGlobalConstants.PATH_DELIMITER, DocGlobalConstants.PATH_DELIMITER, contextPath, controllerBaseUrl, shortUrl);
|
||||
}
|
||||
for (Map.Entry<String, String> entry : constantsMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if (url.contains(key)) {
|
||||
url = url.replace(key, value);
|
||||
url = url.replace("+", "");
|
||||
}
|
||||
if (shortUrl.contains(key)) {
|
||||
shortUrl = shortUrl.replace(key, value);
|
||||
shortUrl = shortUrl.replace("+", "");
|
||||
}
|
||||
url = delConstantsUrl(url, key, value);
|
||||
shortUrl = delConstantsUrl(shortUrl, key, value);
|
||||
}
|
||||
String urlSuffix = projectBuilder.getApiConfig().getUrlSuffix();
|
||||
if (StringUtil.isNotEmpty(urlSuffix)) {
|
||||
url = UrlUtil.simplifyUrl(url) + urlSuffix;
|
||||
shortUrl = UrlUtil.simplifyUrl(shortUrl) + urlSuffix;
|
||||
url = UrlUtil.simplifyUrl(StringUtil.trim(url)) + urlSuffix;
|
||||
shortUrl = UrlUtil.simplifyUrl(StringUtil.trim(shortUrl)) + urlSuffix;
|
||||
} else {
|
||||
url = UrlUtil.simplifyUrl(url);
|
||||
shortUrl = UrlUtil.simplifyUrl(shortUrl);
|
||||
url = UrlUtil.simplifyUrl(StringUtil.trim(url));
|
||||
shortUrl = UrlUtil.simplifyUrl(StringUtil.trim(shortUrl));
|
||||
}
|
||||
return RequestMapping.builder().setMediaType(mediaType).setMethodType(methodType)
|
||||
.setUrl(StringUtil.trim(url)).setShortUrl(StringUtil.trim(shortUrl)).setDeprecated(deprecated);
|
||||
.setUrl(url).setShortUrl(shortUrl).setDeprecated(deprecated);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String delConstantsUrl(String url, String replaceKey, String replaceValue) {
|
||||
url = StringUtil.trim(url);
|
||||
url = url.replace("+", "");
|
||||
url = UrlUtil.simplifyUrl(url);
|
||||
String[] pathWords = url.split("/");
|
||||
for (String word : pathWords) {
|
||||
if (word.equals(replaceKey)) {
|
||||
url = url.replace(replaceKey, replaceValue);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,9 @@ public class FormDataBuildHelper {
|
|||
if (JavaClassValidateUtil.isArray(gicName)) {
|
||||
gicName = gicName.substring(0, gicName.indexOf("["));
|
||||
}
|
||||
if (JavaClassValidateUtil.isPrimitive(gicName)) {
|
||||
pre = pre.substring(0, pre.lastIndexOf("."));
|
||||
}
|
||||
formDataList.addAll(getFormData(gicName, registryClasses, counter, builder, pre + "[]"));
|
||||
}
|
||||
int n = 0;
|
||||
|
@ -101,7 +104,7 @@ public class FormDataBuildHelper {
|
|||
String fieldName = field.getName();
|
||||
String subTypeName = docField.getFullyQualifiedName();
|
||||
String fieldGicName = docField.getGenericCanonicalName();
|
||||
JavaClass javaClass = builder.getJavaProjectBuilder().getClassByName(subTypeName);
|
||||
JavaClass javaClass = field.getType();
|
||||
if (field.isStatic() || "this$0".equals(fieldName) ||
|
||||
JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) {
|
||||
continue;
|
||||
|
@ -152,6 +155,9 @@ public class FormDataBuildHelper {
|
|||
formDataList.add(formData);
|
||||
} else if (javaClass.isEnum()) {
|
||||
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE);
|
||||
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
|
||||
value = tagsMap.get(DocTags.MOCK);
|
||||
}
|
||||
FormData formData = new FormData();
|
||||
formData.setKey(pre + fieldName);
|
||||
formData.setType("text");
|
||||
|
|
|
@ -22,18 +22,21 @@
|
|||
*/
|
||||
package com.power.doc.helper;
|
||||
|
||||
import com.power.common.util.JsonFormatUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.DocAnnotationConstants;
|
||||
import com.power.doc.constants.DocGlobalConstants;
|
||||
import com.power.doc.constants.DocTags;
|
||||
import com.power.doc.constants.ValidatorAnnotations;
|
||||
import com.power.doc.model.*;
|
||||
import com.power.doc.utils.*;
|
||||
import com.thoughtworks.qdox.model.*;
|
||||
import com.thoughtworks.qdox.model.expression.AnnotationValue;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.power.doc.constants.DocGlobalConstants.JSON_PROPERTY_READ_ONLY;
|
||||
import static com.power.doc.constants.DocGlobalConstants.JSON_PROPERTY_WRITE_ONLY;
|
||||
import static com.power.doc.constants.DocTags.IGNORE_RESPONSE_BODY_ADVICE;
|
||||
|
||||
|
||||
|
@ -51,21 +54,45 @@ public class JsonBuildHelper {
|
|||
*/
|
||||
public static String buildReturnJson(DocJavaMethod docJavaMethod, ProjectDocConfigBuilder builder) {
|
||||
JavaMethod method = docJavaMethod.getJavaMethod();
|
||||
if (method.getReturns().isVoid() && Objects.isNull(builder.getApiConfig().getResponseBodyAdvice())) {
|
||||
return "Doesn't return a value.";
|
||||
String responseBodyAdvice = null;
|
||||
if (Objects.nonNull(builder.getApiConfig().getResponseBodyAdvice())) {
|
||||
responseBodyAdvice = builder.getApiConfig().getResponseBodyAdvice().getClassName();
|
||||
}
|
||||
if (method.getReturns().isVoid() && Objects.isNull(responseBodyAdvice)) {
|
||||
return "Return void.";
|
||||
}
|
||||
DocletTag downloadTag = method.getTagByName(DocTags.DOWNLOAD);
|
||||
if (Objects.nonNull(downloadTag)) {
|
||||
return "File download.";
|
||||
}
|
||||
if (method.getReturns().isEnum() && Objects.isNull(responseBodyAdvice)) {
|
||||
return StringUtil.removeQuotes(String.valueOf(JavaClassUtil.getEnumValue(method.getReturns(), Boolean.FALSE)));
|
||||
}
|
||||
if (method.getReturns().isPrimitive() && Objects.isNull(responseBodyAdvice)) {
|
||||
String typeName = method.getReturnType().getCanonicalName();
|
||||
return StringUtil.removeQuotes(DocUtil.jsonValueByType(typeName));
|
||||
}
|
||||
if (DocGlobalConstants.JAVA_STRING_FULLY.equals(method.getReturnType().getGenericCanonicalName())
|
||||
&& Objects.isNull(responseBodyAdvice)) {
|
||||
return "string";
|
||||
}
|
||||
String returnTypeGenericCanonicalName = method.getReturnType().getGenericCanonicalName();
|
||||
if (Objects.nonNull(builder.getApiConfig().getResponseBodyAdvice())
|
||||
if (Objects.nonNull(responseBodyAdvice)
|
||||
&& Objects.isNull(method.getTagByName(IGNORE_RESPONSE_BODY_ADVICE))) {
|
||||
String responseBodyAdvice = builder.getApiConfig().getResponseBodyAdvice().getClassName();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(responseBodyAdvice)
|
||||
.append("<")
|
||||
.append(returnTypeGenericCanonicalName).append(">");
|
||||
returnTypeGenericCanonicalName = sb.toString();
|
||||
if (!returnTypeGenericCanonicalName.startsWith(responseBodyAdvice)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(responseBodyAdvice)
|
||||
.append("<")
|
||||
.append(returnTypeGenericCanonicalName).append(">");
|
||||
returnTypeGenericCanonicalName = sb.toString();
|
||||
}
|
||||
}
|
||||
ApiReturn apiReturn = DocClassUtil.processReturnType(returnTypeGenericCanonicalName);
|
||||
String typeName = apiReturn.getSimpleName();
|
||||
if (JavaClassValidateUtil.isFileDownloadResource(typeName)) {
|
||||
docJavaMethod.setDownload(true);
|
||||
return "File download.";
|
||||
}
|
||||
Map<String, JavaType> actualTypesMap = docJavaMethod.getActualTypesMap();
|
||||
String returnType = apiReturn.getGenericCanonicalName();
|
||||
if (Objects.nonNull(actualTypesMap)) {
|
||||
|
@ -80,7 +107,10 @@ public class JsonBuildHelper {
|
|||
}
|
||||
return StringUtil.removeQuotes(DocUtil.jsonValueByType(typeName));
|
||||
}
|
||||
return JsonFormatUtil.formatJson(buildJson(typeName, returnType, Boolean.TRUE, 0, new HashMap<>(), builder));
|
||||
|
||||
|
||||
return JsonUtil.toPrettyFormat(buildJson(typeName, returnType, Boolean.TRUE, 0,
|
||||
new HashMap<>(), new ArrayList<>(0), builder));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,13 +119,13 @@ public class JsonBuildHelper {
|
|||
* @param isResp Response flag
|
||||
* @param counter Recursive counter
|
||||
* @param registryClasses class container
|
||||
* @param groupClasses valid group class
|
||||
* @param builder project config builder
|
||||
* @return String
|
||||
*/
|
||||
public static String buildJson(String typeName, String genericCanonicalName,
|
||||
boolean isResp, int counter, Map<String, String> registryClasses, ProjectDocConfigBuilder builder) {
|
||||
boolean isResp, int counter, Map<String, String> registryClasses, List<String> groupClasses, ProjectDocConfigBuilder builder) {
|
||||
|
||||
//存储泛型所对应的实体类
|
||||
Map<String, String> genericMap = new HashMap<>(10);
|
||||
JavaClass javaClass = builder.getJavaProjectBuilder().getClassByName(typeName);
|
||||
ApiConfig apiConfig = builder.getApiConfig();
|
||||
|
@ -118,16 +148,21 @@ public class JsonBuildHelper {
|
|||
return StringUtil.removeQuotes(DocUtil.jsonValueByType(typeName));
|
||||
}
|
||||
if (javaClass.isEnum()) {
|
||||
return String.valueOf(JavaClassUtil.getEnumValue(javaClass, Boolean.FALSE));
|
||||
return StringUtil.removeQuotes(String.valueOf(JavaClassUtil.getEnumValue(javaClass, Boolean.FALSE)));
|
||||
}
|
||||
boolean skipTransientField = apiConfig.isSkipTransientField();
|
||||
StringBuilder data0 = new StringBuilder();
|
||||
JavaClass cls = builder.getClassByName(typeName);
|
||||
|
||||
|
||||
data0.append("{");
|
||||
String[] globGicName = DocClassUtil.getSimpleGicName(genericCanonicalName);
|
||||
//添加泛型对应关系
|
||||
if (Objects.isNull(globGicName) || globGicName.length < 1) {
|
||||
// obtain generics from parent class
|
||||
JavaClass superJavaClass = cls != null ? cls.getSuperJavaClass() : null;
|
||||
if (Objects.nonNull(superJavaClass) && !"Object".equals(superJavaClass.getSimpleName())) {
|
||||
globGicName = DocClassUtil.getSimpleGicName(superJavaClass.getGenericFullyQualifiedName());
|
||||
}
|
||||
}
|
||||
JavaClassUtil.genericParamMap(genericMap, cls, globGicName);
|
||||
StringBuilder data = new StringBuilder();
|
||||
if (JavaClassValidateUtil.isCollection(typeName) || JavaClassValidateUtil.isArray(typeName)) {
|
||||
|
@ -146,12 +181,12 @@ public class JsonBuildHelper {
|
|||
data.append(DocUtil.jsonValueByType(gName));
|
||||
} else if (gName.contains("<")) {
|
||||
String simple = DocClassUtil.getSimpleName(gName);
|
||||
String json = buildJson(simple, gName, isResp, nextLevel, registryClasses, builder);
|
||||
String json = buildJson(simple, gName, isResp, nextLevel, registryClasses, groupClasses, builder);
|
||||
data.append(json);
|
||||
} else if (JavaClassValidateUtil.isCollection(gName)) {
|
||||
data.append("\"any object\"");
|
||||
} else {
|
||||
String json = buildJson(gName, gName, isResp, nextLevel, registryClasses, builder);
|
||||
String json = buildJson(gName, gName, isResp, nextLevel, registryClasses, groupClasses, builder);
|
||||
data.append(json);
|
||||
}
|
||||
data.append("]");
|
||||
|
@ -168,40 +203,41 @@ public class JsonBuildHelper {
|
|||
}
|
||||
String gicName = gNameTemp.substring(gNameTemp.indexOf(",") + 1, gNameTemp.lastIndexOf(">"));
|
||||
if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(gicName)) {
|
||||
data.append("{").append("\"mapKey\":").append("{\"waring\":\"You may use java.util.Object for Map value; smart-doc can't be handle.\"}").append("}");
|
||||
data.append("{").append("\"mapKey\":").append("{\"waring\":\"You may use java.util.Object for Map value; smart-doc can't be handle.\"}")
|
||||
.append("}");
|
||||
} else if (JavaClassValidateUtil.isPrimitive(gicName)) {
|
||||
data.append("{").append("\"mapKey1\":").append(DocUtil.jsonValueByType(gicName)).append(",");
|
||||
data.append("\"mapKey2\":").append(DocUtil.jsonValueByType(gicName)).append("}");
|
||||
} else if (gicName.contains("<")) {
|
||||
String simple = DocClassUtil.getSimpleName(gicName);
|
||||
String json = buildJson(simple, gicName, isResp, nextLevel, registryClasses, builder);
|
||||
String json = buildJson(simple, gicName, isResp, nextLevel, registryClasses, groupClasses, builder);
|
||||
data.append("{").append("\"mapKey\":").append(json).append("}");
|
||||
} else {
|
||||
data.append("{").append("\"mapKey\":").append(buildJson(gicName, gNameTemp, isResp, counter + 1, registryClasses, builder)).append("}");
|
||||
data.append("{").append("\"mapKey\":").append(buildJson(gicName, gNameTemp, isResp, counter + 1, registryClasses, groupClasses, builder)).append("}");
|
||||
}
|
||||
return data.toString();
|
||||
} else if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(typeName)) {
|
||||
data.append("{\"object\":\" any object\"},");
|
||||
// throw new RuntimeException("Please do not return java.lang.Object directly in api interface.");
|
||||
} else if (JavaClassValidateUtil.isReactor(typeName)) {
|
||||
data.append(buildJson(globGicName[0], typeName, isResp, nextLevel, registryClasses, builder));
|
||||
data.append(buildJson(globGicName[0], typeName, isResp, nextLevel, registryClasses, groupClasses, builder));
|
||||
return data.toString();
|
||||
} else {
|
||||
boolean requestFieldToUnderline = builder.getApiConfig().isRequestFieldToUnderline();
|
||||
boolean responseFieldToUnderline = builder.getApiConfig().isResponseFieldToUnderline();
|
||||
List<DocJavaField> fields = JavaClassUtil.getFields(cls, 0, new LinkedHashMap<>());
|
||||
Map<String, String> ignoreFields = JavaClassUtil.getClassJsonIgnoreFields(cls);
|
||||
out:
|
||||
for (DocJavaField docField : fields) {
|
||||
JavaField field = docField.getJavaField();
|
||||
String subTypeName = docField.getFullyQualifiedName();
|
||||
String fieldName = field.getName();
|
||||
if (field.isStatic() || "this$0".equals(fieldName) ||
|
||||
JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) {
|
||||
continue;
|
||||
}
|
||||
if (field.isTransient() && skipTransientField) {
|
||||
continue;
|
||||
}
|
||||
String fieldName = docField.getFieldName();
|
||||
if (ignoreFields.containsKey(fieldName)) {
|
||||
continue;
|
||||
}
|
||||
String subTypeName = docField.getFullyQualifiedName();
|
||||
if ((responseFieldToUnderline && isResp) || (requestFieldToUnderline && !isResp)) {
|
||||
fieldName = StringUtil.camelToUnderline(fieldName);
|
||||
}
|
||||
|
@ -214,6 +250,25 @@ public class JsonBuildHelper {
|
|||
List<JavaAnnotation> annotations = docField.getAnnotations();
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
String annotationName = annotation.getType().getValue();
|
||||
if (ValidatorAnnotations.NULL.equals(annotationName) && !isResp) {
|
||||
List<String> groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation);
|
||||
for (String groupClass : groupClassList) {
|
||||
if (groupClasses.contains(groupClass)) {
|
||||
continue out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DocAnnotationConstants.JSON_PROPERTY.equalsIgnoreCase(annotationName)) {
|
||||
AnnotationValue value = annotation.getProperty("access");
|
||||
if (Objects.nonNull(value)) {
|
||||
if (JSON_PROPERTY_READ_ONLY.equals(value.getParameterValue()) && !isResp) {
|
||||
continue out;
|
||||
}
|
||||
if (JSON_PROPERTY_WRITE_ONLY.equals(value.getParameterValue()) && isResp) {
|
||||
continue out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DocAnnotationConstants.SHORT_JSON_IGNORE.equals(annotationName)) {
|
||||
continue out;
|
||||
} else if (DocAnnotationConstants.SHORT_JSON_FIELD.equals(annotationName)) {
|
||||
|
@ -232,12 +287,13 @@ public class JsonBuildHelper {
|
|||
}
|
||||
String typeSimpleName = field.getType().getSimpleName();
|
||||
String fieldGicName = docField.getGenericCanonicalName();
|
||||
CustomField customResponseField = builder.getCustomRespFieldMap().get(fieldName);
|
||||
CustomField customRequestField = builder.getCustomReqFieldMap().get(fieldName);
|
||||
if (customRequestField != null && typeName.equals(customRequestField.getOwnerClassName()) && (customRequestField.isIgnore()) && !isResp) {
|
||||
CustomField customResponseField = builder.getCustomRespFieldMap().get(typeName + "." + fieldName);
|
||||
CustomField customRequestField = builder.getCustomReqFieldMap().get(typeName + "." + fieldName);
|
||||
|
||||
if (customRequestField != null && JavaClassUtil.isTargetChildClass(typeName, customRequestField.getOwnerClassName()) && (customRequestField.isIgnore()) && !isResp) {
|
||||
continue;
|
||||
}
|
||||
if (customResponseField != null && typeName.equals(customResponseField.getOwnerClassName()) && (customResponseField.isIgnore()) && isResp) {
|
||||
if (customResponseField != null && JavaClassUtil.isTargetChildClass(typeName, customResponseField.getOwnerClassName()) && (customResponseField.isIgnore()) && isResp) {
|
||||
continue;
|
||||
}
|
||||
data0.append("\"").append(fieldName).append("\":");
|
||||
|
@ -256,10 +312,10 @@ public class JsonBuildHelper {
|
|||
if (StringUtil.isEmpty(fieldValue)) {
|
||||
fieldValue = DocUtil.getValByTypeAndFieldName(typeSimpleName, field.getName());
|
||||
}
|
||||
if (null != customRequestField && !isResp && customRequestField.getOwnerClassName().equals(typeName)) {
|
||||
if (Objects.nonNull(customRequestField) && !isResp && typeName.equals(customRequestField.getOwnerClassName())) {
|
||||
JavaFieldUtil.buildCustomField(data0, typeSimpleName, customRequestField);
|
||||
}
|
||||
if (null != customResponseField && isResp && customResponseField.getOwnerClassName().equals(typeName)) {
|
||||
if (Objects.nonNull(customResponseField) && isResp && typeName.equals(customResponseField.getOwnerClassName())) {
|
||||
JavaFieldUtil.buildCustomField(data0, typeSimpleName, customResponseField);
|
||||
}
|
||||
if (data0.length() == data0Length) {
|
||||
|
@ -293,7 +349,8 @@ public class JsonBuildHelper {
|
|||
data0.append("[").append(DocUtil.jsonValueByType(gicName1)).append("]").append(",");
|
||||
} else {
|
||||
if (!typeName.equals(gicName1)) {
|
||||
data0.append("[").append(buildJson(DocClassUtil.getSimpleName(gicName1), gicName1, isResp, nextLevel, registryClasses, builder)).append("]").append(",");
|
||||
data0.append("[").append(buildJson(DocClassUtil.getSimpleName(gicName1), gicName1, isResp, nextLevel, registryClasses, groupClasses, builder))
|
||||
.append("]").append(",");
|
||||
} else {
|
||||
data0.append("[{\"$ref\":\"..\"}]").append(",");
|
||||
}
|
||||
|
@ -310,7 +367,7 @@ public class JsonBuildHelper {
|
|||
data0.append("[").append(value).append("],");
|
||||
continue out;
|
||||
}
|
||||
data0.append("[").append(buildJson(gicName, fieldGicName, isResp, nextLevel, registryClasses, builder)).append("]").append(",");
|
||||
data0.append("[").append(buildJson(gicName, fieldGicName, isResp, nextLevel, registryClasses, groupClasses, builder)).append("]").append(",");
|
||||
} else {
|
||||
data0.append("[{\"$ref\":\"..\"}]").append(",");
|
||||
}
|
||||
|
@ -326,18 +383,27 @@ public class JsonBuildHelper {
|
|||
}
|
||||
String gicName = fieldGicName.substring(fieldGicName.indexOf(",") + 1, fieldGicName.indexOf(">"));
|
||||
if (gicName.length() == 1) {
|
||||
String gicName1 = genericMap.get(gicName) == null ? globGicName[0] : genericMap.get(gicName);
|
||||
String gicName1 = "";
|
||||
if (Objects.nonNull(genericMap.get(gicName))) {
|
||||
gicName1 = genericMap.get(gicName);
|
||||
} else {
|
||||
if (globGicName.length > 0) {
|
||||
gicName1 = globGicName[0];
|
||||
}
|
||||
}
|
||||
if (DocGlobalConstants.JAVA_STRING_FULLY.equals(gicName1)) {
|
||||
data0.append("{").append("\"mapKey\":").append(DocUtil.jsonValueByType(gicName1)).append("},");
|
||||
} else {
|
||||
if (!typeName.equals(gicName1)) {
|
||||
data0.append("{").append("\"mapKey\":").append(buildJson(DocClassUtil.getSimpleName(gicName1), gicName1, isResp, nextLevel, registryClasses, builder)).append("},");
|
||||
data0.append("{").append("\"mapKey\":")
|
||||
.append(buildJson(DocClassUtil.getSimpleName(gicName1), gicName1, isResp, nextLevel, registryClasses, groupClasses, builder)).append("},");
|
||||
} else {
|
||||
data0.append("{\"mapKey\":{}},");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data0.append("{").append("\"mapKey\":").append(buildJson(gicName, fieldGicName, isResp, nextLevel, registryClasses, builder)).append("},");
|
||||
data0.append("{").append("\"mapKey\":").append(buildJson(gicName, fieldGicName, isResp, nextLevel, registryClasses, groupClasses, builder))
|
||||
.append("},");
|
||||
}
|
||||
} else if (subTypeName.length() == 1) {
|
||||
if (!typeName.equals(genericCanonicalName)) {
|
||||
|
@ -346,10 +412,10 @@ public class JsonBuildHelper {
|
|||
data0.append(DocUtil.jsonValueByType(gicName)).append(",");
|
||||
} else {
|
||||
String simple = DocClassUtil.getSimpleName(gicName);
|
||||
data0.append(buildJson(simple, gicName, isResp, nextLevel, registryClasses, builder)).append(",");
|
||||
data0.append(buildJson(simple, gicName, isResp, nextLevel, registryClasses, groupClasses, builder)).append(",");
|
||||
}
|
||||
} else {
|
||||
data0.append("{\"waring\":\"You may have used non-display generics.\"},");
|
||||
data0.append("{},");
|
||||
}
|
||||
} else if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) {
|
||||
if (StringUtil.isNotEmpty(field.getComment())) {
|
||||
|
@ -359,26 +425,32 @@ public class JsonBuildHelper {
|
|||
String gicName = genericMap.get(subTypeName) == null ? globGicName[0] : genericMap.get(subTypeName);
|
||||
if (!typeName.equals(genericCanonicalName)) {
|
||||
if (JavaClassValidateUtil.isPrimitive(gicName)) {
|
||||
data0.append("\"").append(buildJson(gicName, genericCanonicalName, isResp, nextLevel, registryClasses, builder)).append("\",");
|
||||
data0.append("\"").append(buildJson(gicName, genericCanonicalName, isResp, nextLevel, registryClasses, groupClasses, builder)).append("\",");
|
||||
} else {
|
||||
String simpleName = DocClassUtil.getSimpleName(gicName);
|
||||
data0.append(buildJson(simpleName, gicName, isResp, nextLevel, registryClasses, builder)).append(",");
|
||||
data0.append(buildJson(simpleName, gicName, isResp, nextLevel, registryClasses, groupClasses, builder)).append(",");
|
||||
}
|
||||
} else {
|
||||
data0.append("{\"waring\":\"You may have used non-display generics.\"},");
|
||||
data0.append("{},");
|
||||
}
|
||||
} else {
|
||||
data0.append("{\"waring\":\"You may have used non-display generics.\"},");
|
||||
data0.append("{},");
|
||||
}
|
||||
} else if (typeName.equals(subTypeName)) {
|
||||
data0.append("{\"$ref\":\"...\"}").append(",");
|
||||
} else {
|
||||
javaClass = builder.getJavaProjectBuilder().getClassByName(subTypeName);
|
||||
if (!isResp && javaClass.isEnum()) {
|
||||
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.FALSE);
|
||||
data0.append(value).append(",");
|
||||
javaClass = field.getType();
|
||||
if (javaClass.isEnum()) {
|
||||
// Override old value
|
||||
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
|
||||
data0.append(tagsMap.get(DocTags.MOCK)).append(",");
|
||||
} else {
|
||||
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.FALSE);
|
||||
data0.append(value).append(",");
|
||||
}
|
||||
} else {
|
||||
data0.append(buildJson(subTypeName, fieldGicName, isResp, nextLevel, registryClasses, builder)).append(",");
|
||||
fieldGicName = DocUtil.formatFieldTypeGicName(genericMap, globGicName, fieldGicName);
|
||||
data0.append(buildJson(subTypeName, fieldGicName, isResp, nextLevel, registryClasses, groupClasses, builder)).append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -390,6 +462,4 @@ public class JsonBuildHelper {
|
|||
data0.append("}");
|
||||
return data0.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import com.thoughtworks.qdox.model.JavaAnnotation;
|
|||
import com.thoughtworks.qdox.model.JavaClass;
|
||||
import com.thoughtworks.qdox.model.JavaField;
|
||||
import com.thoughtworks.qdox.model.JavaMethod;
|
||||
import com.thoughtworks.qdox.model.expression.AnnotationValue;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -54,8 +55,7 @@ public class ParamsBuildHelper {
|
|||
public static List<ApiParam> buildParams(String className, String pre, int level, String isRequired, boolean isResp,
|
||||
Map<String, String> registryClasses, ProjectDocConfigBuilder projectBuilder,
|
||||
List<String> groupClasses, int pid, boolean jsonRequest) {
|
||||
String maxLength = null;
|
||||
//存储泛型所对应的实体类
|
||||
|
||||
Map<String, String> genericMap = new HashMap<>(10);
|
||||
|
||||
if (StringUtil.isEmpty(className)) {
|
||||
|
@ -82,7 +82,14 @@ public class ParamsBuildHelper {
|
|||
String simpleName = DocClassUtil.getSimpleName(className);
|
||||
String[] globGicName = DocClassUtil.getSimpleGicName(className);
|
||||
JavaClass cls = projectBuilder.getClassByName(simpleName);
|
||||
//如果存在泛型 则将泛型与类名的对应关系存起来
|
||||
if (Objects.isNull(globGicName) || globGicName.length < 1) {
|
||||
// obtain generics from parent class
|
||||
JavaClass superJavaClass = cls != null ? cls.getSuperJavaClass() : null;
|
||||
if (superJavaClass != null && !"Object".equals(superJavaClass.getSimpleName())) {
|
||||
globGicName = DocClassUtil.getSimpleGicName(superJavaClass.getGenericFullyQualifiedName());
|
||||
}
|
||||
}
|
||||
|
||||
JavaClassUtil.genericParamMap(genericMap, cls, globGicName);
|
||||
List<DocJavaField> fields = JavaClassUtil.getFields(cls, 0, new LinkedHashMap<>());
|
||||
if (JavaClassValidateUtil.isPrimitive(simpleName)) {
|
||||
|
@ -103,7 +110,7 @@ public class ParamsBuildHelper {
|
|||
registryClasses, projectBuilder, groupClasses, pid, jsonRequest));
|
||||
}
|
||||
} else if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(className)) {
|
||||
ApiParam param = ApiParam.of().setField(pre + "any object").setType("object").setPid(pid);
|
||||
ApiParam param = ApiParam.of().setId(pid + 1).setField(pre + "any object").setType("object").setPid(pid);
|
||||
if (StringUtil.isEmpty(isRequired)) {
|
||||
param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
} else {
|
||||
|
@ -111,22 +118,25 @@ public class ParamsBuildHelper {
|
|||
}
|
||||
paramList.add(param);
|
||||
} else if (JavaClassValidateUtil.isReactor(simpleName)) {
|
||||
paramList.addAll(buildParams(globGicName[0], pre, nextLevel, isRequired, isResp,
|
||||
registryClasses, projectBuilder, groupClasses, pid, jsonRequest));
|
||||
if (globGicName.length > 0) {
|
||||
paramList.addAll(buildParams(globGicName[0], pre, nextLevel, isRequired, isResp,
|
||||
registryClasses, projectBuilder, groupClasses, pid, jsonRequest));
|
||||
}
|
||||
} else {
|
||||
Map<String, String> ignoreFields = JavaClassUtil.getClassJsonIgnoreFields(cls);
|
||||
out:
|
||||
for (DocJavaField docField : fields) {
|
||||
String maxLength = null;
|
||||
JavaField field = docField.getJavaField();
|
||||
String fieldName = field.getName();
|
||||
String subTypeName = docField.getFullyQualifiedName();
|
||||
if (field.isStatic() || "this$0".equals(fieldName) ||
|
||||
JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) {
|
||||
continue;
|
||||
}
|
||||
if (field.isTransient() && skipTransientField) {
|
||||
continue;
|
||||
}
|
||||
String fieldName = docField.getFieldName();
|
||||
if (ignoreFields.containsKey(fieldName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String subTypeName = docField.getFullyQualifiedName();
|
||||
if ((responseFieldToUnderline && isResp) || (requestFieldToUnderline && !isResp)) {
|
||||
fieldName = StringUtil.camelToUnderline(fieldName);
|
||||
}
|
||||
|
@ -150,12 +160,12 @@ public class ParamsBuildHelper {
|
|||
}
|
||||
boolean strRequired = false;
|
||||
int annotationCounter = 0;
|
||||
CustomField customResponseField = responseFieldMap.get(fieldName);
|
||||
CustomField customResponseField = responseFieldMap.get(simpleName + "." + fieldName);
|
||||
if (customResponseField != null && JavaClassUtil.isTargetChildClass(simpleName, customResponseField.getOwnerClassName())
|
||||
&& (customResponseField.isIgnore()) && isResp) {
|
||||
continue;
|
||||
}
|
||||
CustomField customRequestField = projectBuilder.getCustomReqFieldMap().get(fieldName);
|
||||
CustomField customRequestField = projectBuilder.getCustomReqFieldMap().get(simpleName + "." + fieldName);
|
||||
if (customRequestField != null && JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName())
|
||||
&& (customRequestField.isIgnore()) && !isResp) {
|
||||
continue;
|
||||
|
@ -163,8 +173,30 @@ public class ParamsBuildHelper {
|
|||
an:
|
||||
for (JavaAnnotation annotation : javaAnnotations) {
|
||||
String simpleAnnotationName = annotation.getType().getValue();
|
||||
if ("max".equalsIgnoreCase(simpleAnnotationName)) {
|
||||
maxLength = annotation.getProperty(DocAnnotationConstants.VALUE_PROP).toString();
|
||||
AnnotationValue annotationValue = null;
|
||||
if (DocAnnotationConstants.MAX.equalsIgnoreCase(simpleAnnotationName)) {
|
||||
annotationValue = annotation.getProperty(DocAnnotationConstants.VALUE_PROP);
|
||||
}
|
||||
if (DocAnnotationConstants.SIZE.equalsIgnoreCase(simpleAnnotationName)) {
|
||||
annotationValue = annotation.getProperty(DocAnnotationConstants.MAX);
|
||||
}
|
||||
if (DocAnnotationConstants.LENGTH.equalsIgnoreCase(simpleAnnotationName)) {
|
||||
annotationValue = annotation.getProperty(DocAnnotationConstants.MAX);
|
||||
}
|
||||
if (!Objects.isNull(annotationValue)) {
|
||||
maxLength = annotationValue.toString();
|
||||
}
|
||||
|
||||
if (DocAnnotationConstants.JSON_PROPERTY.equalsIgnoreCase(simpleAnnotationName)) {
|
||||
AnnotationValue value = annotation.getProperty("access");
|
||||
if (Objects.nonNull(value)) {
|
||||
if (JSON_PROPERTY_READ_ONLY.equals(value.getParameterValue()) && !isResp) {
|
||||
continue out;
|
||||
}
|
||||
if (JSON_PROPERTY_WRITE_ONLY.equals(value.getParameterValue()) && isResp) {
|
||||
continue out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DocAnnotationConstants.SHORT_JSON_IGNORE.equals(simpleAnnotationName)) {
|
||||
continue out;
|
||||
|
@ -185,7 +217,7 @@ public class ParamsBuildHelper {
|
|||
for (String javaClass : groupClassList) {
|
||||
if (groupClasses.contains(javaClass)) {
|
||||
strRequired = false;
|
||||
break an;
|
||||
continue out;
|
||||
}
|
||||
}
|
||||
} else if (JavaClassValidateUtil.isJSR303Required(simpleAnnotationName) && !isResp) {
|
||||
|
@ -276,25 +308,6 @@ public class ParamsBuildHelper {
|
|||
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND, since, strRequired);
|
||||
}
|
||||
} else {
|
||||
ApiParam param = ApiParam.of().setField(pre + fieldName).setPid(pid).setMaxLength(maxLength);
|
||||
JavaClass javaClass = projectBuilder.getJavaProjectBuilder().getClassByName(subTypeName);
|
||||
if (javaClass.isEnum()) {
|
||||
comment = comment + handleEnumComment(javaClass, projectBuilder);
|
||||
param.setType(DocGlobalConstants.ENUM);
|
||||
}
|
||||
if (JavaClassValidateUtil.isCollection(subTypeName)) {
|
||||
String gNameTemp = fieldGicName;
|
||||
// like Student<T>, Student class has a field List<T> lists.
|
||||
if (globGicName.length > 0 && JAVA_LIST_FULLY.equals(gNameTemp)) {
|
||||
gNameTemp = gNameTemp + "<T>";
|
||||
}
|
||||
String[] gNameArr = DocClassUtil.getSimpleGicName(gNameTemp);
|
||||
if (gNameArr.length > 0) {
|
||||
String gName = DocClassUtil.getSimpleGicName(gNameTemp)[0];
|
||||
JavaClass javaClass1 = projectBuilder.getJavaProjectBuilder().getClassByName(gName);
|
||||
comment = comment + handleEnumComment(javaClass1, projectBuilder);
|
||||
}
|
||||
}
|
||||
String appendComment = "";
|
||||
if (displayActualType) {
|
||||
if (globGicName.length > 0) {
|
||||
|
@ -307,84 +320,112 @@ public class ParamsBuildHelper {
|
|||
appendComment = " (ActualType: " + JavaClassUtil.getClassSimpleName(docField.getActualJavaType()) + ")";
|
||||
}
|
||||
}
|
||||
//如果已经设置返回类型 不需要再次设置
|
||||
if (param.getType() == null) {
|
||||
String processedType;
|
||||
if (typeSimpleName.length() == 1) {
|
||||
processedType = DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
|
||||
} else {
|
||||
processedType = isShowJavaType ? typeSimpleName : DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
|
||||
}
|
||||
param.setType(processedType);
|
||||
}
|
||||
if (!isResp && javaClass.isEnum()) {
|
||||
List<JavaMethod> methods = javaClass.getMethods();
|
||||
int index = 0;
|
||||
|
||||
enumOut:
|
||||
for (JavaMethod method : methods) {
|
||||
List<JavaAnnotation> javaAnnotationList = method.getAnnotations();
|
||||
for (JavaAnnotation annotation : javaAnnotationList) {
|
||||
if (annotation.getType().getValue().contains("JsonValue")) {
|
||||
break enumOut;
|
||||
}
|
||||
}
|
||||
if (CollectionUtil.isEmpty(javaAnnotations) && index < 1) {
|
||||
break enumOut;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
Object value = JavaClassUtil.getEnumValue(javaClass, !jsonRequest);
|
||||
param.setValue(String.valueOf(value));
|
||||
param.setEnumValues(JavaClassUtil.getEnumValues(javaClass));
|
||||
param.setType(DocGlobalConstants.ENUM);
|
||||
}
|
||||
if (StringUtil.isNotEmpty(comment)) {
|
||||
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
|
||||
} else {
|
||||
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
|
||||
}
|
||||
StringBuilder preBuilder = new StringBuilder();
|
||||
for (int j = 0; j < level; j++) {
|
||||
preBuilder.append(DocGlobalConstants.FIELD_SPACE);
|
||||
}
|
||||
preBuilder.append("└─");
|
||||
int fieldPid = paramList.size() + pid;
|
||||
if (JavaClassValidateUtil.isMap(subTypeName)) {
|
||||
String gNameTemp = fieldGicName;
|
||||
String valType = DocClassUtil.getMapKeyValueType(gNameTemp).length == 0 ? gNameTemp : DocClassUtil.getMapKeyValueType(gNameTemp)[1];
|
||||
if (JavaClassValidateUtil.isMap(gNameTemp) || JAVA_OBJECT_FULLY.equals(valType)) {
|
||||
ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object")
|
||||
.setId(fieldPid + 1).setPid(fieldPid)
|
||||
.setMaxLength(maxLength)
|
||||
.setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
paramList.add(param1);
|
||||
continue;
|
||||
}
|
||||
if (!JavaClassValidateUtil.isPrimitive(valType)) {
|
||||
if (valType.length() == 1) {
|
||||
String gicName = genericMap.get(valType);
|
||||
if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
|
||||
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
|
||||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
}
|
||||
} else {
|
||||
paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired,
|
||||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
int fieldPid;
|
||||
ApiParam param = ApiParam.of().setField(pre + fieldName).setPid(pid).setMaxLength(maxLength);
|
||||
|
||||
String processedType;
|
||||
if (typeSimpleName.length() == 1) {
|
||||
String gicName = JAVA_OBJECT_FULLY;
|
||||
if (Objects.nonNull(genericMap.get(typeSimpleName))) {
|
||||
gicName = genericMap.get(subTypeName);
|
||||
} else {
|
||||
if (globGicName.length > 0) {
|
||||
gicName = globGicName[0];
|
||||
}
|
||||
}
|
||||
} else if (JavaClassValidateUtil.isCollection(subTypeName)) {
|
||||
String gNameTemp = fieldGicName;
|
||||
if (globGicName.length > 0 && JAVA_LIST_FULLY.equals(gNameTemp)) {
|
||||
gNameTemp = gNameTemp + "<T>";
|
||||
if (JavaClassValidateUtil.isPrimitive(gicName)) {
|
||||
processedType = DocClassUtil.processTypeNameForParams(gicName);
|
||||
} else {
|
||||
processedType = DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
|
||||
}
|
||||
String[] gNameArr = DocClassUtil.getSimpleGicName(gNameTemp);
|
||||
} else {
|
||||
processedType = isShowJavaType ? typeSimpleName : DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
|
||||
}
|
||||
param.setType(processedType);
|
||||
JavaClass javaClass = field.getType();
|
||||
if (javaClass.isEnum()) {
|
||||
comment = comment + handleEnumComment(javaClass, projectBuilder);
|
||||
param.setType(DocGlobalConstants.ENUM);
|
||||
if (!isResp) {
|
||||
List<JavaMethod> methods = javaClass.getMethods();
|
||||
int index = 0;
|
||||
enumOut:
|
||||
for (JavaMethod method : methods) {
|
||||
List<JavaAnnotation> javaAnnotationList = method.getAnnotations();
|
||||
for (JavaAnnotation annotation : javaAnnotationList) {
|
||||
if (annotation.getType().getValue().contains("JsonValue")) {
|
||||
break enumOut;
|
||||
}
|
||||
}
|
||||
if (CollectionUtil.isEmpty(javaAnnotations) && index < 1) {
|
||||
break enumOut;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
Object value = JavaClassUtil.getEnumValue(javaClass, !jsonRequest);
|
||||
param.setValue(String.valueOf(value));
|
||||
param.setEnumValues(JavaClassUtil.getEnumValues(javaClass));
|
||||
}
|
||||
// Override old value
|
||||
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
|
||||
param.setValue(tagsMap.get(DocTags.MOCK));
|
||||
}
|
||||
if (StringUtil.isNotEmpty(comment)) {
|
||||
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
|
||||
} else {
|
||||
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
|
||||
}
|
||||
|
||||
} else if (JavaClassValidateUtil.isCollection(subTypeName) || JavaClassValidateUtil.isArray(subTypeName)) {
|
||||
param.setType("array");
|
||||
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
|
||||
param.setValue(fieldValue);
|
||||
}
|
||||
|
||||
if (globGicName.length > 0 && "java.util.List".equals(fieldGicName)) {
|
||||
fieldGicName = fieldGicName + "<T>";
|
||||
}
|
||||
if (JavaClassValidateUtil.isArray(subTypeName)) {
|
||||
fieldGicName = fieldGicName.substring(0, fieldGicName.lastIndexOf("["));
|
||||
fieldGicName = "java.util.List<" + fieldGicName + ">";
|
||||
}
|
||||
String[] gNameArr = DocClassUtil.getSimpleGicName(fieldGicName);
|
||||
if (gNameArr.length == 0) {
|
||||
continue out;
|
||||
}
|
||||
String gName = DocClassUtil.getSimpleGicName(gNameTemp)[0];
|
||||
|
||||
if (!JavaClassValidateUtil.isPrimitive(gName)) {
|
||||
if (gNameArr.length > 0) {
|
||||
String gName = DocClassUtil.getSimpleGicName(fieldGicName)[0];
|
||||
JavaClass javaClass1 = projectBuilder.getJavaProjectBuilder().getClassByName(gName);
|
||||
comment = comment + handleEnumComment(javaClass1, projectBuilder);
|
||||
}
|
||||
String gName = gNameArr[0];
|
||||
if (JavaClassValidateUtil.isPrimitive(gName)) {
|
||||
String builder = DocUtil.jsonValueByType(gName) +
|
||||
"," +
|
||||
DocUtil.jsonValueByType(gName);
|
||||
if (StringUtil.isEmpty(fieldValue)) {
|
||||
param.setValue(DocUtil.handleJsonStr(builder));
|
||||
} else {
|
||||
param.setValue(fieldValue);
|
||||
}
|
||||
if (StringUtil.isNotEmpty(comment)) {
|
||||
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
|
||||
} else {
|
||||
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
|
||||
}
|
||||
} else {
|
||||
if (StringUtil.isNotEmpty(comment)) {
|
||||
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
|
||||
} else {
|
||||
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
|
||||
}
|
||||
fieldPid = paramList.size() + pid;
|
||||
if (!simpleName.equals(gName) && !gName.equals(simpleName)) {
|
||||
JavaClass arraySubClass = projectBuilder.getJavaProjectBuilder().getClassByName(gName);
|
||||
if (arraySubClass.isEnum()) {
|
||||
|
@ -408,19 +449,49 @@ public class ParamsBuildHelper {
|
|||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (JavaClassValidateUtil.isMap(subTypeName)) {
|
||||
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
|
||||
param.setType("map");
|
||||
param.setValue(fieldValue);
|
||||
}
|
||||
|
||||
if (StringUtil.isNotEmpty(comment)) {
|
||||
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
|
||||
} else {
|
||||
String builder = "[" +
|
||||
DocUtil.jsonValueByType(gName) +
|
||||
"," +
|
||||
DocUtil.jsonValueByType(gName) +
|
||||
"]";
|
||||
if (StringUtil.isEmpty(fieldValue)) {
|
||||
param.setValue(DocUtil.handleJsonStr(builder));
|
||||
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
|
||||
}
|
||||
fieldPid = paramList.size() + pid;
|
||||
String gNameTemp = fieldGicName;
|
||||
String valType = DocClassUtil.getMapKeyValueType(gNameTemp).length == 0 ? gNameTemp : DocClassUtil.getMapKeyValueType(gNameTemp)[1];
|
||||
if (JavaClassValidateUtil.isMap(gNameTemp) || JAVA_OBJECT_FULLY.equals(valType)) {
|
||||
ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object")
|
||||
.setId(fieldPid + 1).setPid(fieldPid)
|
||||
.setMaxLength(maxLength)
|
||||
.setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
paramList.add(param1);
|
||||
continue;
|
||||
}
|
||||
if (!JavaClassValidateUtil.isPrimitive(valType)) {
|
||||
if (valType.length() == 1) {
|
||||
String gicName = genericMap.get(valType);
|
||||
if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
|
||||
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
|
||||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
}
|
||||
} else {
|
||||
param.setValue(fieldValue);
|
||||
paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired,
|
||||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
}
|
||||
}
|
||||
} else if (subTypeName.length() == 1 || DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) {
|
||||
if (StringUtil.isNotEmpty(comment)) {
|
||||
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
|
||||
} else {
|
||||
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
|
||||
}
|
||||
fieldPid = paramList.size() + pid;
|
||||
// handle java generic or object
|
||||
if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName) && StringUtil.isNotEmpty(field.getComment())) {
|
||||
ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object")
|
||||
|
@ -461,21 +532,19 @@ public class ParamsBuildHelper {
|
|||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
}
|
||||
}
|
||||
} else if (JavaClassValidateUtil.isArray(subTypeName)) {
|
||||
fieldGicName = fieldGicName.substring(0, fieldGicName.indexOf("["));
|
||||
if (className.equals(fieldGicName)) {
|
||||
//do nothing
|
||||
} else if (!JavaClassValidateUtil.isPrimitive(fieldGicName)) {
|
||||
paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired,
|
||||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
}
|
||||
} else if (simpleName.equals(subTypeName)) {
|
||||
//do nothing
|
||||
} else {
|
||||
if (!javaClass.isEnum()) {
|
||||
paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired,
|
||||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
if (StringUtil.isNotEmpty(comment)) {
|
||||
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
|
||||
} else {
|
||||
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
|
||||
}
|
||||
fieldGicName = DocUtil.formatFieldTypeGicName(genericMap, globGicName, fieldGicName);
|
||||
fieldPid = paramList.size() + pid;
|
||||
paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired,
|
||||
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
|
||||
|
||||
}
|
||||
}
|
||||
}//end field
|
||||
|
@ -527,7 +596,6 @@ public class ParamsBuildHelper {
|
|||
}
|
||||
} else {
|
||||
enumComments = DocUtil.replaceNewLineToHtmlBr(enumComments);
|
||||
comment = comment + "<br/>" + JavaClassUtil.getEnumParams(javaClass) + "<br/>";
|
||||
if (StringUtil.isNotEmpty(enumComments)) {
|
||||
comment = comment + "(See: " + enumComments + ")";
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.power.common.util.CollectionUtil;
|
|||
import com.power.doc.constants.DocLanguage;
|
||||
import com.power.doc.model.rpc.RpcApiDependency;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -43,6 +44,11 @@ public class ApiConfig {
|
|||
*/
|
||||
private String serverUrl;
|
||||
|
||||
/**
|
||||
* Path Prefix, eg: Servlet ContextPath
|
||||
*/
|
||||
private String pathPrefix = "";
|
||||
|
||||
/**
|
||||
* Set comments check mode
|
||||
*/
|
||||
|
@ -67,7 +73,13 @@ public class ApiConfig {
|
|||
/**
|
||||
* list of Request headers
|
||||
*/
|
||||
private List<ApiReqHeader> requestHeaders;
|
||||
private List<ApiReqParam> requestHeaders;
|
||||
|
||||
/**
|
||||
* @since 2.2.2
|
||||
* list of Request params
|
||||
*/
|
||||
private List<ApiReqParam> requestParams;
|
||||
|
||||
/**
|
||||
* @since 1.7.5
|
||||
|
@ -151,6 +163,7 @@ public class ApiConfig {
|
|||
* project group
|
||||
*/
|
||||
private String group;
|
||||
|
||||
/**
|
||||
* @since 1.7.5
|
||||
* project name
|
||||
|
@ -277,6 +290,8 @@ public class ApiConfig {
|
|||
|
||||
private String style;
|
||||
|
||||
private String highlightStyleLink;
|
||||
|
||||
/**
|
||||
* create debug page
|
||||
*/
|
||||
|
@ -300,38 +315,75 @@ public class ApiConfig {
|
|||
* Torna appKey
|
||||
*/
|
||||
private String appKey;
|
||||
|
||||
/**
|
||||
* Torna Secret
|
||||
*/
|
||||
private String secret;
|
||||
|
||||
/**
|
||||
* Torna appToken
|
||||
*/
|
||||
private String appToken;
|
||||
|
||||
/**
|
||||
* Torna openUrl
|
||||
*/
|
||||
private String openUrl;
|
||||
|
||||
/**
|
||||
* 调试环境名称
|
||||
* Debugging environment name
|
||||
*/
|
||||
private String debugEnvName;
|
||||
|
||||
/**
|
||||
* 调试环境请求路径
|
||||
* Url of the debugging environment
|
||||
*/
|
||||
private String debugEnvUrl;
|
||||
|
||||
/**
|
||||
* torna调试开关
|
||||
* Show log when pushing document to torna
|
||||
*/
|
||||
private boolean tornaDebug = true;
|
||||
|
||||
/**
|
||||
* 推送人
|
||||
* The operator who pushes the document to Torna
|
||||
*/
|
||||
private String author;
|
||||
|
||||
/**
|
||||
* smart-doc supported framework, if not set default is spring,
|
||||
*/
|
||||
private String framework;
|
||||
|
||||
|
||||
private List<ApiGroup> groups;
|
||||
|
||||
/**
|
||||
* replace old document while push to torna
|
||||
* @since 2.2.4
|
||||
*/
|
||||
private Boolean replace;
|
||||
|
||||
/**
|
||||
* @since 2.2.5
|
||||
*/
|
||||
private boolean requestParamsTable = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* @since 2.2.5
|
||||
*/
|
||||
private boolean responseParamsTable = Boolean.TRUE;
|
||||
|
||||
|
||||
public String getPathPrefix() {
|
||||
return pathPrefix;
|
||||
}
|
||||
|
||||
public void setPathPrefix(String pathPrefix) {
|
||||
this.pathPrefix = pathPrefix;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
@ -404,18 +456,46 @@ public class ApiConfig {
|
|||
this.outPath = outPath;
|
||||
}
|
||||
|
||||
public List<ApiReqHeader> getRequestHeaders() {
|
||||
public List<ApiReqParam> getRequestHeaders() {
|
||||
return requestHeaders;
|
||||
}
|
||||
|
||||
public void setRequestHeaders(List<ApiReqHeader> requestHeaders) {
|
||||
public void setRequestHeaders(List<ApiReqParam> requestHeaders) {
|
||||
this.requestHeaders = requestHeaders;
|
||||
}
|
||||
|
||||
public void setRequestHeaders(ApiReqHeader... requestHeaders) {
|
||||
public void setRequestHeaders(ApiReqParam... requestHeaders) {
|
||||
this.requestHeaders = CollectionUtil.asList(requestHeaders);
|
||||
this.requestHeaders.stream().map(header -> header.setDesc(header.getDesc() + "(Global)"))
|
||||
.collect(Collectors.toList());
|
||||
this.requestHeaders.forEach(header -> header.setDesc(header.getDesc() + "(Global)"));
|
||||
}
|
||||
|
||||
public List<ApiGroup> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public ApiConfig setGroups(List<ApiGroup> groups) {
|
||||
this.groups = groups;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApiConfig setGroups(ApiGroup... groups) {
|
||||
this.groups = CollectionUtil.asList(groups);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public List<ApiReqParam> getRequestParams() {
|
||||
return requestParams;
|
||||
}
|
||||
|
||||
public ApiConfig setRequestParams(List<ApiReqParam> requestParams) {
|
||||
this.requestParams = requestParams;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setRequestParams(ApiReqParam... requestParams) {
|
||||
this.requestParams = CollectionUtil.asList(requestParams);
|
||||
this.requestParams.forEach(param -> param.setDesc(param.getDesc() + "(Global)"));
|
||||
}
|
||||
|
||||
public List<CustomField> getCustomResponseFields() {
|
||||
|
@ -520,7 +600,7 @@ public class ApiConfig {
|
|||
}
|
||||
return this.dataDictionaries.stream().filter((apiDataDictionary ->
|
||||
enumClassName.equalsIgnoreCase(apiDataDictionary.getEnumClassName())))
|
||||
.findFirst().orElse(new ApiDataDictionary());
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public List<ApiErrorCodeDictionary> getErrorCodeDictionaries() {
|
||||
|
@ -792,106 +872,43 @@ public class ApiConfig {
|
|||
this.customRequestFields = CollectionUtil.asList(customRequestFields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("{");
|
||||
sb.append("\"serverUrl\":\"")
|
||||
.append(serverUrl).append('\"');
|
||||
sb.append(",\"isStrict\":")
|
||||
.append(isStrict);
|
||||
sb.append(",\"allInOne\":")
|
||||
.append(allInOne);
|
||||
sb.append(",\"outPath\":\"")
|
||||
.append(outPath).append('\"');
|
||||
sb.append(",\"sourceCodePaths\":")
|
||||
.append(sourceCodePaths);
|
||||
sb.append(",\"requestHeaders\":")
|
||||
.append(requestHeaders);
|
||||
sb.append(",\"coverOld\":")
|
||||
.append(coverOld);
|
||||
sb.append(",\"customResponseFields\":")
|
||||
.append(customResponseFields);
|
||||
sb.append(",\"errorCodes\":")
|
||||
.append(errorCodes);
|
||||
sb.append(",\"packageFilters\":\"")
|
||||
.append(packageFilters).append('\"');
|
||||
sb.append(",\"revisionLogs\":")
|
||||
.append(revisionLogs);
|
||||
sb.append(",\"md5EncryptedHtmlName\":")
|
||||
.append(md5EncryptedHtmlName);
|
||||
sb.append(",\"language\":")
|
||||
.append(language);
|
||||
sb.append(",\"adoc\":")
|
||||
.append(adoc);
|
||||
sb.append(",\"dataDictionaries\":")
|
||||
.append(dataDictionaries);
|
||||
sb.append(",\"errorCodeDictionaries\":")
|
||||
.append(errorCodeDictionaries);
|
||||
sb.append(",\"apiObjectReplacements\":")
|
||||
.append(apiObjectReplacements);
|
||||
sb.append(",\"rpcApiDependencies\":")
|
||||
.append(rpcApiDependencies);
|
||||
sb.append(",\"apiConstants\":")
|
||||
.append(apiConstants);
|
||||
sb.append(",\"group\":\"")
|
||||
.append(group).append('\"');
|
||||
sb.append(",\"projectName\":\"")
|
||||
.append(projectName).append('\"');
|
||||
sb.append(",\"projectCName\":\"")
|
||||
.append(projectCName).append('\"');
|
||||
sb.append(",\"skipTransientField\":")
|
||||
.append(skipTransientField);
|
||||
sb.append(",\"showAuthor\":")
|
||||
.append(showAuthor);
|
||||
sb.append(",\"requestFieldToUnderline\":")
|
||||
.append(requestFieldToUnderline);
|
||||
sb.append(",\"responseFieldToUnderline\":")
|
||||
.append(responseFieldToUnderline);
|
||||
sb.append(",\"sortByTitle\":")
|
||||
.append(sortByTitle);
|
||||
sb.append(",\"showJavaType\":")
|
||||
.append(showJavaType);
|
||||
sb.append(",\"inlineEnum\":")
|
||||
.append(inlineEnum);
|
||||
sb.append(",\"rpcConsumerConfig\":\"")
|
||||
.append(rpcConsumerConfig).append('\"');
|
||||
sb.append(",\"recursionLimit\":")
|
||||
.append(recursionLimit);
|
||||
sb.append(",\"requestExample\":")
|
||||
.append(requestExample);
|
||||
sb.append(",\"responseExample\":")
|
||||
.append(responseExample);
|
||||
sb.append(",\"allInOneDocFileName\":\"")
|
||||
.append(allInOneDocFileName).append('\"');
|
||||
sb.append(",\"paramsDataToTree\":")
|
||||
.append(paramsDataToTree);
|
||||
sb.append(",\"ignoreRequestParams\":")
|
||||
.append(ignoreRequestParams);
|
||||
sb.append(",\"displayActualType\":")
|
||||
.append(displayActualType);
|
||||
sb.append(",\"responseBodyAdvice\":")
|
||||
.append(responseBodyAdvice);
|
||||
sb.append(",\"style\":\"")
|
||||
.append(style).append('\"');
|
||||
sb.append(",\"createDebugPage\":")
|
||||
.append(createDebugPage);
|
||||
sb.append(",\"urlSuffix\":\"")
|
||||
.append(urlSuffix).append('\"');
|
||||
sb.append(",\"appKey\":\"")
|
||||
.append(appKey).append('\"');
|
||||
sb.append(",\"secret\":\"")
|
||||
.append(secret).append('\"');
|
||||
sb.append(",\"appToken\":\"")
|
||||
.append(appToken).append('\"');
|
||||
sb.append(",\"openUrl\":\"")
|
||||
.append(openUrl).append('\"');
|
||||
sb.append(",\"debugEnvName\":\"")
|
||||
.append(debugEnvName).append('\"');
|
||||
sb.append(",\"debugEnvUrl\":\"")
|
||||
.append(debugEnvUrl).append('\"');
|
||||
sb.append(",\"tornaDebug\":")
|
||||
.append(tornaDebug);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
public String getFramework() {
|
||||
return framework;
|
||||
}
|
||||
|
||||
public void setFramework(String framework) {
|
||||
this.framework = framework;
|
||||
}
|
||||
|
||||
public Boolean getReplace() {
|
||||
return replace;
|
||||
}
|
||||
|
||||
public void setReplace(Boolean replace) {
|
||||
this.replace = replace;
|
||||
}
|
||||
|
||||
public boolean isRequestParamsTable() {
|
||||
return requestParamsTable;
|
||||
}
|
||||
|
||||
public void setRequestParamsTable(boolean requestParamsTable) {
|
||||
this.requestParamsTable = requestParamsTable;
|
||||
}
|
||||
|
||||
public boolean isResponseParamsTable() {
|
||||
return responseParamsTable;
|
||||
}
|
||||
|
||||
public void setResponseParamsTable(boolean responseParamsTable) {
|
||||
this.responseParamsTable = responseParamsTable;
|
||||
}
|
||||
|
||||
public String getHighlightStyleLink() {
|
||||
return highlightStyleLink;
|
||||
}
|
||||
|
||||
public void setHighlightStyleLink(String highlightStyleLink) {
|
||||
this.highlightStyleLink = highlightStyleLink;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ package com.power.doc.model;
|
|||
|
||||
import com.power.common.util.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -35,7 +36,7 @@ public class ApiDoc implements Comparable<ApiDoc> {
|
|||
*
|
||||
* @since 1.7+
|
||||
*/
|
||||
public int order;
|
||||
public Integer order;
|
||||
|
||||
/**
|
||||
* controller name
|
||||
|
@ -49,6 +50,26 @@ public class ApiDoc implements Comparable<ApiDoc> {
|
|||
*/
|
||||
private String alias;
|
||||
|
||||
/**
|
||||
* tags
|
||||
*
|
||||
* @author cqmike
|
||||
*/
|
||||
private String[] tags;
|
||||
|
||||
/**
|
||||
* group
|
||||
*
|
||||
* @author cqmike
|
||||
*/
|
||||
private String group;
|
||||
|
||||
/**
|
||||
* class in package name
|
||||
*
|
||||
*/
|
||||
private String packageName;
|
||||
|
||||
/**
|
||||
* List of method doc
|
||||
*/
|
||||
|
@ -66,6 +87,16 @@ public class ApiDoc implements Comparable<ApiDoc> {
|
|||
|
||||
private String author;
|
||||
|
||||
/**
|
||||
* if this is group, then is true
|
||||
*/
|
||||
private boolean isFolder;
|
||||
|
||||
/**
|
||||
* children
|
||||
*/
|
||||
private List<ApiDoc> childrenApiDocs = new ArrayList<>();
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
@ -98,11 +129,11 @@ public class ApiDoc implements Comparable<ApiDoc> {
|
|||
this.desc = desc;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
public Integer getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
public void setOrder(Integer order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
|
@ -114,6 +145,14 @@ public class ApiDoc implements Comparable<ApiDoc> {
|
|||
this.alias = alias;
|
||||
}
|
||||
|
||||
public String[] getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(String[] tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public String getLink() {
|
||||
if (StringUtil.isNotEmpty(link)) {
|
||||
return link;
|
||||
|
@ -125,6 +164,38 @@ public class ApiDoc implements Comparable<ApiDoc> {
|
|||
this.link = link;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public boolean isFolder() {
|
||||
return isFolder;
|
||||
}
|
||||
|
||||
public void setFolder(boolean folder) {
|
||||
isFolder = folder;
|
||||
}
|
||||
|
||||
public List<ApiDoc> getChildrenApiDocs() {
|
||||
return childrenApiDocs;
|
||||
}
|
||||
|
||||
public void setChildrenApiDocs(List<ApiDoc> childrenApiDocs) {
|
||||
this.childrenApiDocs = childrenApiDocs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ApiDoc o) {
|
||||
if (Objects.nonNull(o.getDesc())) {
|
||||
|
@ -133,6 +204,31 @@ public class ApiDoc implements Comparable<ApiDoc> {
|
|||
return name.compareTo(o.getName());
|
||||
}
|
||||
|
||||
public static ApiDoc buildTagApiDoc(ApiDoc source, String tag, ApiMethodDoc methodDoc) {
|
||||
ApiDoc apiDoc = new ApiDoc();
|
||||
apiDoc.setAlias(source.getAlias());
|
||||
apiDoc.setLink(source.getLink());
|
||||
apiDoc.setDesc(tag);
|
||||
apiDoc.setAuthor(source.getAuthor());
|
||||
apiDoc.setPackageName(source.getPackageName());
|
||||
apiDoc.setName(tag);
|
||||
apiDoc.setList(new ArrayList<>());
|
||||
ApiMethodDoc clone = methodDoc.clone();
|
||||
clone.setOrder(apiDoc.getList().size() + 1);
|
||||
apiDoc.getList().add(clone);
|
||||
return apiDoc;
|
||||
}
|
||||
|
||||
|
||||
public static ApiDoc buildGroupApiDoc(String group) {
|
||||
ApiDoc apiDoc = new ApiDoc();
|
||||
apiDoc.setFolder(true);
|
||||
apiDoc.setGroup(group);
|
||||
apiDoc.setName(group);
|
||||
apiDoc.setDesc(group);
|
||||
apiDoc.setChildrenApiDocs(new ArrayList<>());
|
||||
return apiDoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package com.power.doc.model;
|
||||
|
||||
/**
|
||||
* api group
|
||||
*
|
||||
* @author cqmike
|
||||
* @version 1.0.0
|
||||
* @since 2021年07月31日 16:39:00
|
||||
*/
|
||||
public class ApiGroup {
|
||||
|
||||
/**
|
||||
* group name
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* package name
|
||||
* support patten
|
||||
*/
|
||||
private String apis;
|
||||
|
||||
/**
|
||||
* url path
|
||||
* support patten
|
||||
*/
|
||||
private String paths;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ApiGroup setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getApis() {
|
||||
return apis;
|
||||
}
|
||||
|
||||
public ApiGroup setApis(String apis) {
|
||||
this.apis = apis;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPaths() {
|
||||
return paths;
|
||||
}
|
||||
|
||||
public ApiGroup setPaths(String paths) {
|
||||
this.paths = paths;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ import java.util.Map;
|
|||
/**
|
||||
* java api method info model.
|
||||
*/
|
||||
public class ApiMethodDoc implements Serializable {
|
||||
public class ApiMethodDoc implements Serializable, Cloneable {
|
||||
|
||||
|
||||
private static final long serialVersionUID = 7211922919532562867L;
|
||||
|
@ -109,7 +109,7 @@ public class ApiMethodDoc implements Serializable {
|
|||
/**
|
||||
* http request headers
|
||||
*/
|
||||
private List<ApiReqHeader> requestHeaders;
|
||||
private List<ApiReqParam> requestHeaders;
|
||||
|
||||
/**
|
||||
* path params
|
||||
|
@ -181,12 +181,64 @@ public class ApiMethodDoc implements Serializable {
|
|||
* mark page
|
||||
*/
|
||||
private String page = "";
|
||||
|
||||
/**
|
||||
* torna request is array
|
||||
*/
|
||||
private Integer isRequestArray;
|
||||
/**
|
||||
* torna request is array-type
|
||||
*/
|
||||
private String requestArrayType;
|
||||
/**
|
||||
* torna response is array
|
||||
*/
|
||||
private Integer isResponseArray;
|
||||
/**
|
||||
* torna request is array
|
||||
*/
|
||||
private String responseArrayType;
|
||||
/**
|
||||
* 是否为List数据 openApi
|
||||
*/
|
||||
private boolean listParam = false;
|
||||
|
||||
/**
|
||||
* tags
|
||||
*/
|
||||
private String[] tags;
|
||||
|
||||
public Integer getIsRequestArray() {
|
||||
return isRequestArray;
|
||||
}
|
||||
|
||||
public void setIsRequestArray(Integer isRequestArray) {
|
||||
this.isRequestArray = isRequestArray;
|
||||
}
|
||||
|
||||
public String getRequestArrayType() {
|
||||
return requestArrayType;
|
||||
}
|
||||
|
||||
public void setRequestArrayType(String requestArrayType) {
|
||||
this.requestArrayType = requestArrayType;
|
||||
}
|
||||
|
||||
public Integer getIsResponseArray() {
|
||||
return isResponseArray;
|
||||
}
|
||||
|
||||
public void setIsResponseArray(Integer isResponseArray) {
|
||||
this.isResponseArray = isResponseArray;
|
||||
}
|
||||
|
||||
public String getResponseArrayType() {
|
||||
return responseArrayType;
|
||||
}
|
||||
|
||||
public void setResponseArrayType(String responseArrayType) {
|
||||
this.responseArrayType = responseArrayType;
|
||||
}
|
||||
|
||||
public boolean isListParam() {
|
||||
return listParam;
|
||||
}
|
||||
|
@ -291,11 +343,11 @@ public class ApiMethodDoc implements Serializable {
|
|||
this.responseParams = responseParams;
|
||||
}
|
||||
|
||||
public List<ApiReqHeader> getRequestHeaders() {
|
||||
public List<ApiReqParam> getRequestHeaders() {
|
||||
return requestHeaders;
|
||||
}
|
||||
|
||||
public void setRequestHeaders(List<ApiReqHeader> requestHeaders) {
|
||||
public void setRequestHeaders(List<ApiReqParam> requestHeaders) {
|
||||
this.requestHeaders = requestHeaders;
|
||||
}
|
||||
|
||||
|
@ -415,6 +467,15 @@ public class ApiMethodDoc implements Serializable {
|
|||
this.page = page;
|
||||
}
|
||||
|
||||
public String[] getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public ApiMethodDoc setTags(String[] tags) {
|
||||
this.tags = tags;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("{");
|
||||
|
@ -463,4 +524,13 @@ public class ApiMethodDoc implements Serializable {
|
|||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiMethodDoc clone() {
|
||||
try {
|
||||
return (ApiMethodDoc) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException("clone apiMethodDoc is error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,6 +104,12 @@ public class ApiParam {
|
|||
*/
|
||||
private String maxLength;
|
||||
|
||||
/**
|
||||
* is config.json config param
|
||||
* default false
|
||||
*/
|
||||
private boolean configParam;
|
||||
|
||||
public static ApiParam of() {
|
||||
return new ApiParam();
|
||||
}
|
||||
|
@ -243,6 +249,15 @@ public class ApiParam {
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean isConfigParam() {
|
||||
return configParam;
|
||||
}
|
||||
|
||||
public ApiParam setConfigParam(boolean configParam) {
|
||||
this.configParam = configParam;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("{");
|
||||
|
|
|
@ -22,36 +22,48 @@
|
|||
*/
|
||||
package com.power.doc.model;
|
||||
|
||||
import com.power.doc.constants.ApiReqParamInTypeEnum;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* http request header info model
|
||||
* http request param info model
|
||||
*
|
||||
* @author yu 2018/06/18.
|
||||
* @author chenqi 2021/07/15
|
||||
*/
|
||||
public class ApiReqHeader {
|
||||
public class ApiReqParam {
|
||||
|
||||
/**
|
||||
* Request header name
|
||||
* Request param name
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Request header type
|
||||
* Request param type
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* request header defaultValue
|
||||
* request param defaultValue
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* Request header description
|
||||
* Request param description
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
/**
|
||||
* where is param location
|
||||
* default header
|
||||
*
|
||||
* @see ApiReqParamInTypeEnum value
|
||||
*/
|
||||
private String paramIn;
|
||||
|
||||
/**
|
||||
* required flag
|
||||
*
|
||||
|
@ -66,20 +78,27 @@ public class ApiReqHeader {
|
|||
*/
|
||||
private String since = "-";
|
||||
|
||||
@Deprecated
|
||||
public static ApiReqHeader header() {
|
||||
return new ApiReqHeader();
|
||||
}
|
||||
/**
|
||||
* @since 2.2.2
|
||||
* Regular expression match request param
|
||||
*/
|
||||
private String pathPatterns;
|
||||
|
||||
public static ApiReqHeader builder() {
|
||||
return new ApiReqHeader();
|
||||
/**
|
||||
* @since 2.2.2
|
||||
* Regular expression ignore request param
|
||||
*/
|
||||
private String excludePathPatterns;
|
||||
|
||||
public static ApiReqParam builder() {
|
||||
return new ApiReqParam();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ApiReqHeader setName(String name) {
|
||||
public ApiReqParam setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
@ -88,7 +107,7 @@ public class ApiReqHeader {
|
|||
return type;
|
||||
}
|
||||
|
||||
public ApiReqHeader setType(String type) {
|
||||
public ApiReqParam setType(String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
@ -97,7 +116,7 @@ public class ApiReqHeader {
|
|||
return desc;
|
||||
}
|
||||
|
||||
public ApiReqHeader setDesc(String desc) {
|
||||
public ApiReqParam setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
return this;
|
||||
}
|
||||
|
@ -106,7 +125,7 @@ public class ApiReqHeader {
|
|||
return required;
|
||||
}
|
||||
|
||||
public ApiReqHeader setRequired(boolean required) {
|
||||
public ApiReqParam setRequired(boolean required) {
|
||||
this.required = required;
|
||||
return this;
|
||||
}
|
||||
|
@ -115,7 +134,7 @@ public class ApiReqHeader {
|
|||
return since;
|
||||
}
|
||||
|
||||
public ApiReqHeader setSince(String since) {
|
||||
public ApiReqParam setSince(String since) {
|
||||
this.since = since;
|
||||
return this;
|
||||
}
|
||||
|
@ -124,16 +143,46 @@ public class ApiReqHeader {
|
|||
return value;
|
||||
}
|
||||
|
||||
public ApiReqHeader setValue(String value) {
|
||||
public ApiReqParam setValue(String value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPathPatterns() {
|
||||
return pathPatterns;
|
||||
}
|
||||
|
||||
public ApiReqParam setPathPatterns(String pathPatterns) {
|
||||
this.pathPatterns = pathPatterns;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getExcludePathPatterns() {
|
||||
return excludePathPatterns;
|
||||
}
|
||||
|
||||
public ApiReqParam setExcludePathPatterns(String excludePathPatterns) {
|
||||
this.excludePathPatterns = excludePathPatterns;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getParamIn() {
|
||||
if (StringUtils.isEmpty(paramIn)) {
|
||||
return ApiReqParamInTypeEnum.HEADER.getValue();
|
||||
}
|
||||
return paramIn;
|
||||
}
|
||||
|
||||
public ApiReqParam setParamIn(String paramIn) {
|
||||
this.paramIn = paramIn;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ApiReqHeader that = (ApiReqHeader) o;
|
||||
ApiReqParam that = (ApiReqParam) o;
|
||||
return Objects.equals(name, that.name);
|
||||
}
|
||||
|
||||
|
@ -153,11 +202,23 @@ public class ApiReqHeader {
|
|||
.append(value).append('\"');
|
||||
sb.append(",\"desc\":\"")
|
||||
.append(desc).append('\"');
|
||||
sb.append(",\"paramIn\":")
|
||||
.append(paramIn);
|
||||
sb.append(",\"required\":")
|
||||
.append(required);
|
||||
sb.append(",\"since\":\"")
|
||||
.append(since).append('\"');
|
||||
sb.append(",\"pathPatterns\":\"")
|
||||
.append(pathPatterns).append('\"');
|
||||
sb.append(",\"excludePathPatterns\":\"")
|
||||
.append(excludePathPatterns).append('\"');
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static ApiParam convertToApiParam(ApiReqParam param) {
|
||||
return ApiParam.of().setField(param.getName()).setValue(param.getValue())
|
||||
.setRequired(param.isRequired()).setDesc(param.getDesc()).setConfigParam(true)
|
||||
.setVersion("-").setType(param.getType());
|
||||
}
|
||||
}
|
|
@ -69,6 +69,11 @@ public class DocJavaField {
|
|||
*/
|
||||
private String actualJavaType;
|
||||
|
||||
/**
|
||||
* field name
|
||||
*/
|
||||
private String fieldName;
|
||||
|
||||
private boolean array;
|
||||
|
||||
private boolean primitive;
|
||||
|
@ -199,4 +204,13 @@ public class DocJavaField {
|
|||
public void setEnum(boolean anEnum) {
|
||||
isEnum = anEnum;
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
public DocJavaField setFieldName(String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ public class DocJavaMethod {
|
|||
|
||||
private Map<String, JavaType> actualTypesMap;
|
||||
|
||||
private boolean download;
|
||||
|
||||
public static DocJavaMethod builder() {
|
||||
return new DocJavaMethod();
|
||||
}
|
||||
|
@ -80,4 +82,13 @@ public class DocJavaMethod {
|
|||
this.requestSchema = requestSchema;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isDownload() {
|
||||
return download;
|
||||
}
|
||||
|
||||
public DocJavaMethod setDownload(boolean download) {
|
||||
this.download = download;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* smart-doc https://github.com/shalousun/smart-doc
|
||||
*
|
||||
* Copyright (C) 2018-2021 smart-doc
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.power.doc.model.framework;
|
||||
|
||||
public class PageableAsQueryParam {
|
||||
|
||||
/**
|
||||
* Page you want to retrieve (0..N)
|
||||
*/
|
||||
private Integer page;
|
||||
|
||||
/**
|
||||
* Number of records per page
|
||||
*/
|
||||
private Integer size;
|
||||
|
||||
/**
|
||||
* Sorting criteria in the format: property(,asc|desc),Default sort order is ascending.
|
||||
* Multiple sort criteria are supported.
|
||||
*/
|
||||
private String sort;
|
||||
|
||||
public Integer getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(Integer page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public Integer getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Integer size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
public void setSort(String sort) {
|
||||
this.sort = sort;
|
||||
}
|
||||
}
|
|
@ -22,11 +22,17 @@
|
|||
*/
|
||||
package com.power.doc.model.postman;
|
||||
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.model.postman.request.ParamBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* post
|
||||
*
|
||||
* @author yu 2020/11/28.
|
||||
*/
|
||||
public class UrlBean {
|
||||
|
@ -45,6 +51,42 @@ public class UrlBean {
|
|||
|
||||
private List<ParamBean> variable;
|
||||
|
||||
public UrlBean() {
|
||||
|
||||
}
|
||||
|
||||
public UrlBean(String serverUrl) {
|
||||
if (StringUtil.isEmpty(serverUrl)) {
|
||||
return;
|
||||
}
|
||||
Pattern pattern = Pattern.compile("(https?://)([^:^/]*)(:[a-zA-Z-z0-9|^{{\\}}$]*)?(.*)?");
|
||||
Matcher matcher = pattern.matcher(serverUrl);
|
||||
if (matcher.find()) {
|
||||
String protocol = matcher.group(1);
|
||||
protocol = protocol.substring(0, protocol.indexOf(":"));
|
||||
|
||||
String domain = matcher.group(2);
|
||||
List<String> hosts = new ArrayList<>();
|
||||
hosts.add(domain);
|
||||
// port
|
||||
String port = matcher.group(3);
|
||||
if (StringUtil.isNotEmpty(port)) {
|
||||
port = port.replace(":", "");
|
||||
}
|
||||
|
||||
String uri = matcher.group(4);
|
||||
List<String> paths = new ArrayList<>();
|
||||
paths.add(uri);
|
||||
|
||||
this.protocol = protocol;
|
||||
this.host = hosts;
|
||||
this.port = port;
|
||||
this.path = paths;
|
||||
} else {
|
||||
throw new RuntimeException("ServerUrl must contain http or https protocol.");
|
||||
}
|
||||
}
|
||||
|
||||
public String getRaw() {
|
||||
return raw;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*/
|
||||
package com.power.doc.model.request;
|
||||
|
||||
import com.power.doc.model.ApiReqHeader;
|
||||
import com.power.doc.model.ApiReqParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -33,7 +33,7 @@ public class CurlRequest {
|
|||
|
||||
private String type;
|
||||
|
||||
private List<ApiReqHeader> reqHeaders;
|
||||
private List<ApiReqParam> reqHeaders;
|
||||
|
||||
private String url;
|
||||
|
||||
|
@ -54,11 +54,11 @@ public class CurlRequest {
|
|||
return this;
|
||||
}
|
||||
|
||||
public List<ApiReqHeader> getReqHeaders() {
|
||||
public List<ApiReqParam> getReqHeaders() {
|
||||
return reqHeaders;
|
||||
}
|
||||
|
||||
public CurlRequest setReqHeaders(List<ApiReqHeader> reqHeaders) {
|
||||
public CurlRequest setReqHeaders(List<ApiReqParam> reqHeaders) {
|
||||
this.reqHeaders = reqHeaders;
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package com.power.doc.model.request;
|
||||
|
||||
/**
|
||||
* @author yu 2021/8/28.
|
||||
*/
|
||||
public class JaxrsPathMapping extends RequestMapping {
|
||||
|
||||
/**
|
||||
* url
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* path
|
||||
*/
|
||||
private String shortUrl;
|
||||
/**
|
||||
* methodType
|
||||
*/
|
||||
private String methodType;
|
||||
/**
|
||||
* media type
|
||||
*/
|
||||
private String mediaType;
|
||||
|
||||
/**
|
||||
* method deprecated
|
||||
*/
|
||||
private boolean deprecated;
|
||||
|
||||
public static JaxrsPathMapping builder() {
|
||||
return new JaxrsPathMapping();
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public JaxrsPathMapping setUrl(String url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getShortUrl() {
|
||||
return shortUrl;
|
||||
}
|
||||
|
||||
public JaxrsPathMapping setShortUrl(String shortUrl) {
|
||||
this.shortUrl = shortUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMethodType() {
|
||||
return methodType;
|
||||
}
|
||||
|
||||
public JaxrsPathMapping setMethodType(String methodType) {
|
||||
this.methodType = methodType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMediaType() {
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
public JaxrsPathMapping setMediaType(String mediaType) {
|
||||
this.mediaType = mediaType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isDeprecated() {
|
||||
return deprecated;
|
||||
}
|
||||
|
||||
public JaxrsPathMapping setDeprecated(boolean deprecated) {
|
||||
this.deprecated = deprecated;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -35,7 +35,14 @@ public class RequestMapping {
|
|||
* path
|
||||
*/
|
||||
private String shortUrl;
|
||||
/**
|
||||
* method type
|
||||
*/
|
||||
private String methodType;
|
||||
|
||||
/**
|
||||
* media type
|
||||
*/
|
||||
private String mediaType;
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,7 @@ public class Apis {
|
|||
private String parentId;
|
||||
private String isShow;
|
||||
private String author;
|
||||
private Integer orderIndex;
|
||||
private DubboInfo dubboInfo;
|
||||
private List<HttpParam> headerParams;
|
||||
private List<HttpParam> pathParams;
|
||||
|
@ -45,6 +46,50 @@ public class Apis {
|
|||
private List<HttpParam> responseParams;
|
||||
private String errorCodeParams;
|
||||
private List<Apis> items;
|
||||
private Integer isRequestArray;
|
||||
private String requestArrayType;
|
||||
private Integer isResponseArray;
|
||||
private String responseArrayType;
|
||||
|
||||
public Integer getIsRequestArray() {
|
||||
return isRequestArray;
|
||||
}
|
||||
|
||||
public void setIsRequestArray(Integer isRequestArray) {
|
||||
this.isRequestArray = isRequestArray;
|
||||
}
|
||||
|
||||
public String getRequestArrayType() {
|
||||
return requestArrayType;
|
||||
}
|
||||
|
||||
public void setRequestArrayType(String requestArrayType) {
|
||||
this.requestArrayType = requestArrayType;
|
||||
}
|
||||
|
||||
public Integer getIsResponseArray() {
|
||||
return isResponseArray;
|
||||
}
|
||||
|
||||
public void setIsResponseArray(Integer isResponseArray) {
|
||||
this.isResponseArray = isResponseArray;
|
||||
}
|
||||
|
||||
public String getResponseArrayType() {
|
||||
return responseArrayType;
|
||||
}
|
||||
|
||||
public void setResponseArrayType(String responseArrayType) {
|
||||
this.responseArrayType = responseArrayType;
|
||||
}
|
||||
|
||||
public Integer getOrderIndex() {
|
||||
return orderIndex;
|
||||
}
|
||||
|
||||
public void setOrderIndex(Integer orderIndex) {
|
||||
this.orderIndex = orderIndex;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
|
|
|
@ -25,25 +25,14 @@ package com.power.doc.model.torna;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: xingzi 2021/2/25 12:13
|
||||
* @author xingzi 2021/2/25 12:13
|
||||
**/
|
||||
public class EnumInfo {
|
||||
/**
|
||||
* "enumInfo": {
|
||||
* "name": "支付枚举",
|
||||
* "description": "支付状态",
|
||||
* "items": [
|
||||
* {
|
||||
* "name": "WAIT_PAY",
|
||||
* "type": "string",
|
||||
* "value": "0",
|
||||
* "description": "未支付"
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private List<Item> items;
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -42,6 +42,18 @@ public class TornaApi {
|
|||
List<Apis> apis;
|
||||
String author;
|
||||
List<CommonErrorCode> commonErrorCodes;
|
||||
/**
|
||||
* 是否替换文档,1:替换,0:不替换(追加)。缺省:1
|
||||
*/
|
||||
Integer isReplace;
|
||||
|
||||
public Integer getIsReplace() {
|
||||
return isReplace;
|
||||
}
|
||||
|
||||
public void setIsReplace(Integer isReplace) {
|
||||
this.isReplace = isReplace;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
|
|
|
@ -29,9 +29,9 @@ import java.net.URLDecoder;
|
|||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* torna请求日志信息
|
||||
* Print the log of pushing documents to Torna
|
||||
*
|
||||
* @author: xingzi 2021/3/20 22:11
|
||||
* @author xingzi 2021/3/20 22:11
|
||||
**/
|
||||
public class TornaRequestInfo {
|
||||
private String code;
|
||||
|
@ -92,18 +92,16 @@ public class TornaRequestInfo {
|
|||
public String buildInfo() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("---------------------------START---------------------------\n")
|
||||
.append("接口名: ")
|
||||
.append("API: ")
|
||||
.append(category)
|
||||
.append("\n")
|
||||
.append("请求数据: \n")
|
||||
.append("Request: \n")
|
||||
.append(TornaConstants.GSON.toJson(requestInfo))
|
||||
.append("\n")
|
||||
.append("返回结果: \n")
|
||||
.append("Response: \n")
|
||||
.append(TornaConstants.GSON.fromJson(responseInfo, HashMap.class))
|
||||
.append("\n")
|
||||
.append("---------------------------END---------------------------\n");
|
||||
|
||||
|
||||
try {
|
||||
return URLDecoder.decode(sb.toString(), "utf-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
|
|
|
@ -35,6 +35,8 @@ import com.thoughtworks.qdox.model.JavaMethod;
|
|||
import com.thoughtworks.qdox.model.JavaType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.power.doc.constants.DocGlobalConstants.NO_COMMENTS_FOUND;
|
||||
import static com.power.doc.constants.DocTags.IGNORE_RESPONSE_BODY_ADVICE;
|
||||
|
@ -44,12 +46,12 @@ import static com.power.doc.constants.DocTags.IGNORE_RESPONSE_BODY_ADVICE;
|
|||
*/
|
||||
public interface IDocBuildTemplate<T> {
|
||||
|
||||
default String createDocRenderHeaders(List<ApiReqHeader> headers, boolean isAdoc) {
|
||||
default String createDocRenderHeaders(List<ApiReqParam> headers, boolean isAdoc) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (CollectionUtil.isEmpty(headers)) {
|
||||
headers = new ArrayList<>(0);
|
||||
}
|
||||
for (ApiReqHeader header : headers) {
|
||||
for (ApiReqParam header : headers) {
|
||||
if (isAdoc) {
|
||||
builder.append("|");
|
||||
}
|
||||
|
@ -82,7 +84,14 @@ public interface IDocBuildTemplate<T> {
|
|||
apiDoc.setName(controllerName);
|
||||
apiDoc.setAuthor(classAuthor);
|
||||
apiDoc.setAlias(controllerName);
|
||||
apiDoc.setFolder(true);
|
||||
apiDoc.setPackageName(cls.getPackage().getName());
|
||||
//apiDoc.setAuthor();
|
||||
|
||||
// handle class tags
|
||||
List<DocletTag> classTags = cls.getTagsByName(DocTags.TAG);
|
||||
apiDoc.setTags(classTags.stream().map(DocletTag::getValue).toArray(String[]::new));
|
||||
|
||||
if (isUseMD5) {
|
||||
String name = DocUtil.generateId(apiDoc.getName());
|
||||
apiDoc.setAlias(name);
|
||||
|
@ -94,19 +103,85 @@ public interface IDocBuildTemplate<T> {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* handle group api docs
|
||||
*
|
||||
* @param apiDocList list of apiDocList
|
||||
* @param apiConfig ApiConfig apiConfig
|
||||
* @author cqmike
|
||||
* @return List of ApiDoc
|
||||
*/
|
||||
default List<ApiDoc> handleApiGroup(List<ApiDoc> apiDocList, ApiConfig apiConfig) {
|
||||
if (CollectionUtil.isEmpty(apiDocList) || apiConfig == null) {
|
||||
return apiDocList;
|
||||
}
|
||||
List<ApiGroup> groups = apiConfig.getGroups();
|
||||
ApiDoc defaultGroup = ApiDoc.buildGroupApiDoc("default");
|
||||
List<ApiDoc> finalApiDocs = new ArrayList<>();
|
||||
finalApiDocs.add(defaultGroup);
|
||||
AtomicInteger order = new AtomicInteger(1);
|
||||
defaultGroup.setOrder(order.getAndIncrement());
|
||||
if (CollectionUtil.isEmpty(groups)) {
|
||||
defaultGroup.getChildrenApiDocs().addAll(apiDocList);
|
||||
return finalApiDocs;
|
||||
}
|
||||
Map<String, String> hasInsert = new HashMap<>();
|
||||
for (ApiGroup group : groups) {
|
||||
ApiDoc groupApiDoc = ApiDoc.buildGroupApiDoc(group.getName());
|
||||
groupApiDoc.setOrder(order.getAndIncrement());
|
||||
finalApiDocs.add(groupApiDoc);
|
||||
for (ApiDoc doc : apiDocList) {
|
||||
if (hasInsert.containsKey(doc.getAlias())) {
|
||||
continue;
|
||||
}
|
||||
if (!DocUtil.isMatch(group.getApis(), doc.getPackageName())) {
|
||||
continue;
|
||||
}
|
||||
hasInsert.put(doc.getAlias(), null);
|
||||
groupApiDoc.getChildrenApiDocs().add(doc);
|
||||
doc.setOrder(groupApiDoc.getChildrenApiDocs().size());
|
||||
doc.setGroup(group.getName());
|
||||
if (StringUtil.isEmpty(group.getPaths())) {
|
||||
continue;
|
||||
}
|
||||
List<ApiMethodDoc> methodDocs = doc.getList().stream()
|
||||
.filter(l -> DocPathUtil.matches(l.getPath(), group.getPaths(), null))
|
||||
.collect(Collectors.toList());
|
||||
doc.setList(methodDocs);
|
||||
}
|
||||
}
|
||||
// Ungrouped join the default group
|
||||
for (ApiDoc doc : apiDocList) {
|
||||
String key = doc.getAlias();
|
||||
if (!hasInsert.containsKey(key)) {
|
||||
defaultGroup.getChildrenApiDocs().add(doc);
|
||||
doc.setOrder(defaultGroup.getChildrenApiDocs().size());
|
||||
hasInsert.put(doc.getAlias(), null);
|
||||
}
|
||||
}
|
||||
return finalApiDocs;
|
||||
}
|
||||
|
||||
|
||||
default List<ApiParam> buildReturnApiParams(DocJavaMethod docJavaMethod, ProjectDocConfigBuilder projectBuilder) {
|
||||
JavaMethod method = docJavaMethod.getJavaMethod();
|
||||
if (method.getReturns().isVoid() && Objects.isNull(projectBuilder.getApiConfig().getResponseBodyAdvice())) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
DocletTag downloadTag = method.getTagByName(DocTags.DOWNLOAD);
|
||||
if (Objects.nonNull(downloadTag)) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
String returnTypeGenericCanonicalName = method.getReturnType().getGenericCanonicalName();
|
||||
if (Objects.nonNull(projectBuilder.getApiConfig().getResponseBodyAdvice())
|
||||
&& Objects.isNull(method.getTagByName(IGNORE_RESPONSE_BODY_ADVICE))) {
|
||||
String responseBodyAdvice = projectBuilder.getApiConfig().getResponseBodyAdvice().getClassName();
|
||||
returnTypeGenericCanonicalName = new StringBuffer()
|
||||
.append(responseBodyAdvice)
|
||||
.append("<")
|
||||
.append(returnTypeGenericCanonicalName).append(">").toString();
|
||||
if (!returnTypeGenericCanonicalName.startsWith(responseBodyAdvice)) {
|
||||
returnTypeGenericCanonicalName = new StringBuffer()
|
||||
.append(responseBodyAdvice)
|
||||
.append("<")
|
||||
.append(returnTypeGenericCanonicalName).append(">").toString();
|
||||
}
|
||||
}
|
||||
Map<String, JavaType> actualTypesMap = docJavaMethod.getActualTypesMap();
|
||||
ApiReturn apiReturn = DocClassUtil.processReturnType(returnTypeGenericCanonicalName);
|
||||
|
|
|
@ -0,0 +1,898 @@
|
|||
package com.power.doc.template;
|
||||
|
||||
import com.power.common.util.*;
|
||||
import com.power.doc.builder.ProjectDocConfigBuilder;
|
||||
import com.power.doc.constants.*;
|
||||
import com.power.doc.handler.JaxrsHeaderHandler;
|
||||
import com.power.doc.handler.JaxrsPathHandler;
|
||||
import com.power.doc.helper.FormDataBuildHelper;
|
||||
import com.power.doc.helper.JsonBuildHelper;
|
||||
import com.power.doc.helper.ParamsBuildHelper;
|
||||
import com.power.doc.model.*;
|
||||
import com.power.doc.model.request.ApiRequestExample;
|
||||
import com.power.doc.model.request.CurlRequest;
|
||||
import com.power.doc.model.request.JaxrsPathMapping;
|
||||
import com.power.doc.utils.*;
|
||||
import com.thoughtworks.qdox.model.*;
|
||||
import com.thoughtworks.qdox.model.expression.AnnotationValue;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.power.doc.constants.DocGlobalConstants.*;
|
||||
import static com.power.doc.constants.DocTags.IGNORE;
|
||||
import static com.power.doc.constants.DocTags.IGNORE_REQUEST_BODY_ADVICE;
|
||||
|
||||
/**
|
||||
* Build documents for JAX RS
|
||||
*
|
||||
* @author Zxq
|
||||
* @since 2021/7/15
|
||||
*/
|
||||
public class JaxrsDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
||||
|
||||
private static Logger log = Logger.getLogger(SpringBootDocBuildTemplate.class.getName());
|
||||
/**
|
||||
* api index
|
||||
*/
|
||||
private final AtomicInteger atomicInteger = new AtomicInteger(1);
|
||||
/**
|
||||
* headers
|
||||
*/
|
||||
private List<ApiReqParam> headers;
|
||||
|
||||
@Override
|
||||
public List<ApiDoc> getApiData(ProjectDocConfigBuilder projectBuilder) {
|
||||
ApiConfig apiConfig = projectBuilder.getApiConfig();
|
||||
this.headers = apiConfig.getRequestHeaders();
|
||||
List<ApiDoc> apiDocList = new ArrayList<>();
|
||||
int order = 0;
|
||||
Collection<JavaClass> classes = projectBuilder.getJavaProjectBuilder().getClasses();
|
||||
boolean setCustomOrder = false;
|
||||
// exclude class is ignore
|
||||
for (JavaClass cls : classes) {
|
||||
if (StringUtil.isNotEmpty(apiConfig.getPackageFilters())) {
|
||||
// from smart config
|
||||
if (!DocUtil.isMatch(apiConfig.getPackageFilters(), cls.getCanonicalName())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// from tag
|
||||
DocletTag ignoreTag = cls.getTagByName(DocTags.IGNORE);
|
||||
if (!checkController(cls) || Objects.nonNull(ignoreTag)) {
|
||||
continue;
|
||||
}
|
||||
String strOrder = JavaClassUtil.getClassTagsValue(cls, DocTags.ORDER, Boolean.TRUE);
|
||||
order++;
|
||||
if (ValidateUtil.isNonnegativeInteger(strOrder)) {
|
||||
setCustomOrder = true;
|
||||
order = Integer.parseInt(strOrder);
|
||||
}
|
||||
List<ApiMethodDoc> apiMethodDocs = buildControllerMethod(cls, apiConfig, projectBuilder);
|
||||
this.handleApiDoc(cls, apiDocList, apiMethodDocs, order, apiConfig.isMd5EncryptedHtmlName());
|
||||
}
|
||||
// sort
|
||||
if (apiConfig.isSortByTitle()) {
|
||||
Collections.sort(apiDocList);
|
||||
} else if (setCustomOrder) {
|
||||
// while set custom oder
|
||||
return apiDocList.stream()
|
||||
.sorted(Comparator.comparing(ApiDoc::getOrder))
|
||||
.peek(p -> p.setOrder(atomicInteger.getAndAdd(1))).collect(Collectors.toList());
|
||||
}
|
||||
return apiDocList;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiDoc getSingleApiData(ProjectDocConfigBuilder projectBuilder, String apiClassName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreReturnObject(String typeName, List<String> ignoreParams) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze resource method
|
||||
*
|
||||
* @param cls cls
|
||||
* @param apiConfig apiConfig
|
||||
* @param projectBuilder projectBuilder
|
||||
* @return List<ApiMethodDoc>
|
||||
*/
|
||||
private List<ApiMethodDoc> buildControllerMethod(final JavaClass cls, ApiConfig apiConfig,
|
||||
ProjectDocConfigBuilder projectBuilder) {
|
||||
String clazName = cls.getCanonicalName();
|
||||
boolean paramsDataToTree = projectBuilder.getApiConfig().isParamsDataToTree();
|
||||
String group = JavaClassUtil.getClassTagsValue(cls, DocTags.GROUP, Boolean.TRUE);
|
||||
String classAuthor = JavaClassUtil.getClassTagsValue(cls, DocTags.AUTHOR, Boolean.TRUE);
|
||||
List<JavaAnnotation> classAnnotations = this.getAnnotations(cls);
|
||||
String baseUrl = "";
|
||||
for (JavaAnnotation annotation : classAnnotations) {
|
||||
String annotationName = annotation.getType().getValue();
|
||||
if (JAXRSAnnotations.JAX_PATH.equals(annotationName) ||
|
||||
DocGlobalConstants.JAX_PATH_FULLY.equals(annotationName)) {
|
||||
baseUrl = StringUtil.removeQuotes(DocUtil.getRequestHeaderValue(annotation));
|
||||
}
|
||||
}
|
||||
|
||||
List<JavaMethod> methods = cls.getMethods();
|
||||
List<DocJavaMethod> docJavaMethods = new ArrayList<>(methods.size());
|
||||
// filter private method
|
||||
for (JavaMethod method : methods) {
|
||||
if (method.isPrivate()) {
|
||||
continue;
|
||||
}
|
||||
docJavaMethods.add(DocJavaMethod.builder().setJavaMethod(method));
|
||||
}
|
||||
JavaClass parentClass = cls.getSuperJavaClass();
|
||||
if (Objects.nonNull(parentClass) && !"Object".equals(parentClass.getSimpleName())) {
|
||||
Map<String, JavaType> actualTypesMap = JavaClassUtil.getActualTypesMap(parentClass);
|
||||
List<JavaMethod> parentMethodList = parentClass.getMethods();
|
||||
for (JavaMethod method : parentMethodList) {
|
||||
docJavaMethods.add(DocJavaMethod.builder().setJavaMethod(method).setActualTypesMap(actualTypesMap));
|
||||
}
|
||||
}
|
||||
List<ApiMethodDoc> methodDocList = new ArrayList<>(methods.size());
|
||||
int methodOrder = 0;
|
||||
for (DocJavaMethod docJavaMethod : docJavaMethods) {
|
||||
JavaMethod method = docJavaMethod.getJavaMethod();
|
||||
if (checkCondition(method)) continue;
|
||||
// new api doc
|
||||
//handle request mapping
|
||||
JaxrsPathMapping jaxPathMapping = new JaxrsPathHandler()
|
||||
.handle(projectBuilder, baseUrl, method);
|
||||
if (Objects.isNull(jaxPathMapping)) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtil.isEmpty(method.getComment()) && apiConfig.isStrict()) {
|
||||
throw new RuntimeException("Unable to find comment for method " + method.getName() + " in " + cls.getCanonicalName());
|
||||
}
|
||||
ApiMethodDoc apiMethodDoc = new ApiMethodDoc();
|
||||
DocletTag downloadTag = method.getTagByName(DocTags.DOWNLOAD);
|
||||
if (Objects.nonNull(downloadTag)) {
|
||||
apiMethodDoc.setDownload(true);
|
||||
}
|
||||
DocletTag pageTag = method.getTagByName(DocTags.PAGE);
|
||||
if (Objects.nonNull(pageTag)) {
|
||||
String pageUrl = projectBuilder.getServerUrl() + "/" + pageTag.getValue();
|
||||
apiMethodDoc.setPage(UrlUtil.simplifyUrl(pageUrl));
|
||||
}
|
||||
DocletTag docletTag = method.getTagByName(DocTags.GROUP);
|
||||
apiMethodDoc.setGroup(group);
|
||||
if (Objects.nonNull(docletTag)) {
|
||||
apiMethodDoc.setGroup(docletTag.getValue());
|
||||
}
|
||||
methodOrder++;
|
||||
apiMethodDoc.setName(method.getName());
|
||||
apiMethodDoc.setOrder(methodOrder);
|
||||
String comment = DocUtil.getEscapeAndCleanComment(method.getComment());
|
||||
apiMethodDoc.setDesc(comment);
|
||||
String methodUid = DocUtil.generateId(clazName + method.getName());
|
||||
apiMethodDoc.setMethodId(methodUid);
|
||||
String apiNoteValue = DocUtil.getNormalTagComments(method, DocTags.API_NOTE, cls.getName());
|
||||
if (StringUtil.isEmpty(apiNoteValue)) {
|
||||
apiNoteValue = method.getComment();
|
||||
}
|
||||
Map<String, String> authorMap = DocUtil.getParamsComments(method, DocTags.AUTHOR, cls.getName());
|
||||
String authorValue = String.join(", ", new ArrayList<>(authorMap.keySet()));
|
||||
if (apiConfig.isShowAuthor() && StringUtil.isNotEmpty(authorValue)) {
|
||||
apiMethodDoc.setAuthor(JsonUtil.toPrettyFormat(authorValue));
|
||||
}
|
||||
if (apiConfig.isShowAuthor() && StringUtil.isEmpty(authorValue)) {
|
||||
apiMethodDoc.setAuthor(classAuthor);
|
||||
}
|
||||
apiMethodDoc.setDetail(apiNoteValue);
|
||||
List<ApiReqParam> ApiReqParams = new JaxrsHeaderHandler().handle(method, projectBuilder);
|
||||
apiMethodDoc.setType(jaxPathMapping.getMethodType());
|
||||
apiMethodDoc.setUrl(jaxPathMapping.getUrl());
|
||||
apiMethodDoc.setServerUrl(projectBuilder.getServerUrl());
|
||||
apiMethodDoc.setPath(jaxPathMapping.getShortUrl());
|
||||
apiMethodDoc.setDeprecated(jaxPathMapping.isDeprecated());
|
||||
List<JavaParameter> javaParameters = method.getParameters();
|
||||
|
||||
setTornaArrayTags(javaParameters, apiMethodDoc, docJavaMethod.getJavaMethod().getReturns());
|
||||
// apiMethodDoc.setIsRequestArray();
|
||||
ApiMethodReqParam apiMethodReqParam = requestParams(docJavaMethod, projectBuilder);
|
||||
// build request params
|
||||
if (paramsDataToTree) {
|
||||
apiMethodDoc.setPathParams(ApiParamTreeUtil.apiParamToTree(apiMethodReqParam.getPathParams()));
|
||||
apiMethodDoc.setQueryParams(ApiParamTreeUtil.apiParamToTree(apiMethodReqParam.getQueryParams()));
|
||||
apiMethodDoc.setRequestParams(ApiParamTreeUtil.apiParamToTree(apiMethodReqParam.getRequestParams()));
|
||||
} else {
|
||||
apiMethodDoc.setPathParams(apiMethodReqParam.getPathParams());
|
||||
apiMethodDoc.setQueryParams(apiMethodReqParam.getQueryParams());
|
||||
apiMethodDoc.setRequestParams(apiMethodReqParam.getRequestParams());
|
||||
}
|
||||
|
||||
List<ApiReqParam> allApiReqParams;
|
||||
allApiReqParams = ApiReqParams;
|
||||
if (this.headers != null) {
|
||||
allApiReqParams = Stream.of(this.headers, ApiReqParams)
|
||||
.flatMap(Collection::stream).distinct().collect(Collectors.toList());
|
||||
}
|
||||
allApiReqParams.removeIf(ApiReqParam -> {
|
||||
if (StringUtil.isEmpty(ApiReqParam.getPathPatterns())
|
||||
&& StringUtil.isEmpty(ApiReqParam.getExcludePathPatterns())) {
|
||||
return false;
|
||||
} else {
|
||||
boolean flag = DocPathUtil.matches(jaxPathMapping.getShortUrl(), ApiReqParam.getPathPatterns()
|
||||
, ApiReqParam.getExcludePathPatterns());
|
||||
return !flag;
|
||||
}
|
||||
});
|
||||
//reduce create in template
|
||||
apiMethodDoc.setHeaders(this.createDocRenderHeaders(allApiReqParams, apiConfig.isAdoc()));
|
||||
apiMethodDoc.setRequestHeaders(allApiReqParams);
|
||||
|
||||
// build request json
|
||||
ApiRequestExample requestExample = buildReqJson(docJavaMethod, apiMethodDoc, jaxPathMapping.getMethodType(),
|
||||
projectBuilder);
|
||||
String requestJson = requestExample.getExampleBody();
|
||||
// set request example detail
|
||||
apiMethodDoc.setRequestExample(requestExample);
|
||||
apiMethodDoc.setRequestUsage(requestJson == null ? requestExample.getUrl() : requestJson);
|
||||
// build response usage
|
||||
String responseValue = DocUtil.getNormalTagComments(method, DocTags.API_RESPONSE, cls.getName());
|
||||
if (StringUtil.isNotEmpty(responseValue)) {
|
||||
apiMethodDoc.setResponseUsage(responseValue);
|
||||
} else {
|
||||
apiMethodDoc.setResponseUsage(JsonBuildHelper.buildReturnJson(docJavaMethod, projectBuilder));
|
||||
}
|
||||
// auto mark file download
|
||||
if (Objects.isNull(docletTag)) {
|
||||
apiMethodDoc.setDownload(docJavaMethod.isDownload());
|
||||
}
|
||||
// build response params
|
||||
List<ApiParam> responseParams = buildReturnApiParams(docJavaMethod, projectBuilder);
|
||||
if (paramsDataToTree) {
|
||||
responseParams = ApiParamTreeUtil.apiParamToTree(responseParams);
|
||||
}
|
||||
apiMethodDoc.setReturnSchema(docJavaMethod.getReturnSchema());
|
||||
apiMethodDoc.setRequestSchema(docJavaMethod.getRequestSchema());
|
||||
apiMethodDoc.setResponseParams(responseParams);
|
||||
methodDocList.add(apiMethodDoc);
|
||||
}
|
||||
return methodDocList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param method method
|
||||
* @return boolean
|
||||
*/
|
||||
private boolean checkCondition(JavaMethod method) {
|
||||
return method.isPrivate() || Objects.nonNull(method.getTagByName(IGNORE));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getAnnotations
|
||||
*
|
||||
* @param cls java-class
|
||||
* @return All javaAnnotation
|
||||
*/
|
||||
private List<JavaAnnotation> getAnnotations(JavaClass cls) {
|
||||
List<JavaAnnotation> annotationsList = new ArrayList<>(cls.getAnnotations());
|
||||
boolean flag = annotationsList.stream().anyMatch(item -> {
|
||||
String annotationName = item.getType().getValue();
|
||||
return JAXRSAnnotations.JAX_PATH.equals(annotationName) ||
|
||||
JAX_PATH_FULLY.equals(annotationName);
|
||||
});
|
||||
// child override parent set
|
||||
if (flag) {
|
||||
return annotationsList;
|
||||
}
|
||||
JavaClass superJavaClass = cls.getSuperJavaClass();
|
||||
if (Objects.nonNull(superJavaClass) && !"Object".equals(superJavaClass.getSimpleName())) {
|
||||
annotationsList.addAll(getAnnotations(superJavaClass));
|
||||
}
|
||||
return annotationsList;
|
||||
}
|
||||
|
||||
/**
|
||||
* build request params
|
||||
*
|
||||
* @param docJavaMethod docJavaMethod
|
||||
* @param builder builder
|
||||
* @return ApiMethodReqParam
|
||||
*/
|
||||
private ApiMethodReqParam requestParams(final DocJavaMethod docJavaMethod, ProjectDocConfigBuilder builder) {
|
||||
JavaMethod javaMethod = docJavaMethod.getJavaMethod();
|
||||
boolean isStrict = builder.getApiConfig().isStrict();
|
||||
String className = javaMethod.getDeclaringClass().getCanonicalName();
|
||||
Map<String, String> replacementMap = builder.getReplaceClassMap();
|
||||
Map<String, String> paramTagMap = DocUtil.getParamsComments(javaMethod, DocTags.PARAM, className);
|
||||
Map<String, String> paramsComments = DocUtil.getParamsComments(javaMethod, DocTags.PARAM, null);
|
||||
List<ApiParam> paramList = new ArrayList<>();
|
||||
List<JavaParameter> parameterList = javaMethod.getParameters();
|
||||
if (parameterList.size() < 1) {
|
||||
return ApiMethodReqParam.builder()
|
||||
.setPathParams(new ArrayList<>(0))
|
||||
.setQueryParams(paramList)
|
||||
.setRequestParams(new ArrayList<>(0));
|
||||
}
|
||||
Map<String, String> constantsMap = builder.getConstantsMap();
|
||||
boolean requestFieldToUnderline = builder.getApiConfig().isRequestFieldToUnderline();
|
||||
Set<String> ignoreSets = ignoreParamsSets(javaMethod);
|
||||
Map<String, JavaType> actualTypesMap = docJavaMethod.getActualTypesMap();
|
||||
out:
|
||||
for (JavaParameter parameter : parameterList) {
|
||||
String paramName = parameter.getName();
|
||||
if (ignoreSets.contains(paramName)) {
|
||||
continue;
|
||||
}
|
||||
JavaType javaType = parameter.getType();
|
||||
if (Objects.nonNull(actualTypesMap) && Objects.nonNull(actualTypesMap.get(javaType.getCanonicalName()))) {
|
||||
javaType = actualTypesMap.get(javaType.getCanonicalName());
|
||||
}
|
||||
String typeName = javaType.getGenericCanonicalName();
|
||||
String simpleName = javaType.getValue().toLowerCase();
|
||||
String fullTypeName = javaType.getFullyQualifiedName();
|
||||
String simpleTypeName = javaType.getValue();
|
||||
String commentClass = paramTagMap.get(paramName);
|
||||
String rewriteClassName = getRewriteClassName(replacementMap, fullTypeName, commentClass);
|
||||
// rewrite class
|
||||
if (DocUtil.isClassName(rewriteClassName)) {
|
||||
typeName = rewriteClassName;
|
||||
fullTypeName = DocClassUtil.getSimpleName(rewriteClassName);
|
||||
}
|
||||
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, builder.getApiConfig().getIgnoreRequestParams())) {
|
||||
continue;
|
||||
}
|
||||
fullTypeName = DocClassUtil.rewriteRequestParam(fullTypeName);
|
||||
typeName = DocClassUtil.rewriteRequestParam(typeName);
|
||||
if (!paramTagMap.containsKey(paramName) && JavaClassValidateUtil.isPrimitive(fullTypeName) && isStrict) {
|
||||
throw new RuntimeException("ERROR: Unable to find javadoc @QueryParam for actual param \""
|
||||
+ paramName + "\" in method " + javaMethod.getName() + " from " + className);
|
||||
}
|
||||
String comment = this.paramCommentResolve(paramTagMap.get(paramName));
|
||||
if (requestFieldToUnderline) {
|
||||
paramName = StringUtil.camelToUnderline(paramName);
|
||||
}
|
||||
//file upload
|
||||
if (JavaClassValidateUtil.isFile(typeName)) {
|
||||
ApiParam param = ApiParam.of().setField(paramName).setType("file")
|
||||
.setId(paramList.size() + 1).setQueryParam(true)
|
||||
.setRequired(true).setVersion(DocGlobalConstants.DEFAULT_VERSION)
|
||||
.setDesc(comment);
|
||||
if (typeName.contains("[]") || typeName.endsWith(">")) {
|
||||
comment = comment + "(array of file)";
|
||||
param.setDesc(comment);
|
||||
param.setHasItems(true);
|
||||
}
|
||||
paramList.add(param);
|
||||
continue;
|
||||
}
|
||||
String mockValue = createMockValue(paramsComments, paramName, typeName, simpleTypeName);
|
||||
JavaClass javaClass = builder.getJavaProjectBuilder().getClassByName(fullTypeName);
|
||||
List<JavaAnnotation> annotations = parameter.getAnnotations();
|
||||
List<String> groupClasses = JavaClassUtil.getParamGroupJavaClass(annotations);
|
||||
String strRequired = "false";
|
||||
boolean isPathVariable = false;
|
||||
boolean isRequestBody = false;
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
String annotationName = annotation.getType().getValue();
|
||||
if (JAXRSAnnotations.JAX_HEADER_PARAM.equals(annotationName)) {
|
||||
continue out;
|
||||
}
|
||||
// path param
|
||||
if (JAXRSAnnotations.JAX_PATH_PARAM.equals(annotationName) ) {
|
||||
isPathVariable = true;
|
||||
paramName = getParamName(paramName, annotation);
|
||||
for (Map.Entry<String, String> entry : constantsMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if (paramName.contains(key)) {
|
||||
paramName = paramName.replace(key, value);
|
||||
}
|
||||
// replace mockValue
|
||||
if (mockValue.contains(key)) {
|
||||
mockValue = mockValue.replace(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean required = false;
|
||||
boolean queryParam = !isPathVariable;
|
||||
if (JavaClassValidateUtil.isCollection(fullTypeName) || JavaClassValidateUtil.isArray(fullTypeName)) {
|
||||
if (JavaClassValidateUtil.isCollection(typeName)) {
|
||||
typeName = typeName + "<T>";
|
||||
}
|
||||
String[] gicNameArr = DocClassUtil.getSimpleGicName(typeName);
|
||||
String gicName = gicNameArr[0];
|
||||
if (JavaClassValidateUtil.isArray(gicName)) {
|
||||
gicName = gicName.substring(0, gicName.indexOf("["));
|
||||
}
|
||||
JavaClass gicJavaClass = builder.getJavaProjectBuilder().getClassByName(gicName);
|
||||
if (gicJavaClass.isEnum()) {
|
||||
Object value = JavaClassUtil.getEnumValue(gicJavaClass, Boolean.TRUE);
|
||||
ApiParam param = ApiParam.of().setField(paramName).setDesc(comment + ",[array of enum]")
|
||||
.setRequired(required)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
.setId(paramList.size() + 1)
|
||||
.setType("array").setValue(String.valueOf(value));
|
||||
paramList.add(param);
|
||||
} else if (JavaClassValidateUtil.isPrimitive(gicName)) {
|
||||
String shortSimple = DocClassUtil.processTypeNameForParams(gicName);
|
||||
ApiParam param = ApiParam.of()
|
||||
.setField(paramName)
|
||||
.setDesc(comment + ",[array of " + shortSimple + "]")
|
||||
.setRequired(required)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
.setId(paramList.size() + 1)
|
||||
.setType("array")
|
||||
.setValue(DocUtil.getValByTypeAndFieldName(gicName, paramName));
|
||||
paramList.add(param);
|
||||
} else {
|
||||
throw new RuntimeException("Dubbo Rest can't support binding Collection on method "
|
||||
+ javaMethod.getName() + ",Check it in " + javaMethod.getDeclaringClass()
|
||||
.getCanonicalName());
|
||||
}
|
||||
} else if (JavaClassValidateUtil.isPrimitive(fullTypeName)) {
|
||||
ApiParam param = ApiParam.of()
|
||||
.setField(paramName)
|
||||
.setType(DocClassUtil.processTypeNameForParams(simpleName))
|
||||
.setId(paramList.size() + 1)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
.setValue(mockValue)
|
||||
.setDesc(comment)
|
||||
.setRequired(required)
|
||||
.setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
paramList.add(param);
|
||||
} else if (JavaClassValidateUtil.isMap(fullTypeName)) {
|
||||
log.warning("When using smart-doc, it is not recommended to use Map to receive parameters, Check it in "
|
||||
+ javaMethod.getDeclaringClass().getCanonicalName() + "#" + javaMethod.getName());
|
||||
if (JavaClassValidateUtil.isMap(typeName)) {
|
||||
ApiParam apiParam = ApiParam.of()
|
||||
.setField(paramName)
|
||||
.setType("map")
|
||||
.setId(paramList.size() + 1)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
.setDesc(comment)
|
||||
.setRequired(required)
|
||||
.setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
paramList.add(apiParam);
|
||||
continue;
|
||||
}
|
||||
String[] gicNameArr = DocClassUtil.getSimpleGicName(typeName);
|
||||
if (JavaClassValidateUtil.isPrimitive(gicNameArr[1])) {
|
||||
ApiParam apiParam = ApiParam.of()
|
||||
.setField(paramName)
|
||||
.setType("map")
|
||||
.setId(paramList.size() + 1)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
.setDesc(comment)
|
||||
.setRequired(required)
|
||||
.setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
paramList.add(apiParam);
|
||||
} else {
|
||||
paramList.addAll(ParamsBuildHelper.buildParams(gicNameArr[1], DocGlobalConstants.EMPTY, 0,
|
||||
"true", Boolean.FALSE, new HashMap<>(),
|
||||
builder, groupClasses, 0, Boolean.FALSE));
|
||||
}
|
||||
|
||||
}
|
||||
// param is enum
|
||||
else if (javaClass.isEnum()) {
|
||||
String o = JavaClassUtil.getEnumParams(javaClass);
|
||||
Object value = JavaClassUtil.getEnumValue(javaClass, true);
|
||||
ApiParam param = ApiParam.of().setField(paramName)
|
||||
.setId(paramList.size() + 1)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
.setValue(String.valueOf(value))
|
||||
.setType("enum").setDesc(StringUtil.removeQuotes(o))
|
||||
.setRequired(required)
|
||||
.setVersion(DocGlobalConstants.DEFAULT_VERSION)
|
||||
.setEnumValues(JavaClassUtil.getEnumValues(javaClass));
|
||||
paramList.add(param);
|
||||
} else {
|
||||
paramList.addAll(ParamsBuildHelper.buildParams(typeName, DocGlobalConstants.EMPTY, 0,
|
||||
"true", Boolean.FALSE, new HashMap<>(), builder, groupClasses, 0, Boolean.FALSE));
|
||||
}
|
||||
}
|
||||
List<ApiParam> pathParams = new ArrayList<>();
|
||||
List<ApiParam> queryParams = new ArrayList<>();
|
||||
List<ApiParam> bodyParams = new ArrayList<>();
|
||||
for (ApiParam param : paramList) {
|
||||
param.setValue(StringUtil.removeDoubleQuotes(param.getValue()));
|
||||
if (param.isPathParam()) {
|
||||
param.setId(pathParams.size() + 1);
|
||||
pathParams.add(param);
|
||||
} else {
|
||||
param.setId(queryParams.size() + 1);
|
||||
queryParams.add(param);
|
||||
}
|
||||
}
|
||||
return ApiMethodReqParam.builder()
|
||||
.setRequestParams(bodyParams)
|
||||
.setPathParams(pathParams)
|
||||
.setQueryParams(queryParams);
|
||||
}
|
||||
|
||||
private String getParamName(String paramName, JavaAnnotation annotation) {
|
||||
AnnotationValue annotationValue = annotation.getProperty(DocAnnotationConstants.VALUE_PROP);
|
||||
if (Objects.nonNull(annotationValue)) {
|
||||
paramName = StringUtil.removeQuotes(annotationValue.toString());
|
||||
}
|
||||
AnnotationValue annotationOfName = annotation.getProperty(DocAnnotationConstants.NAME_PROP);
|
||||
if (Objects.nonNull(annotationOfName)) {
|
||||
paramName = StringUtil.removeQuotes(annotationOfName.toString());
|
||||
}
|
||||
return paramName;
|
||||
}
|
||||
|
||||
private String createMockValue(Map<String, String> paramsComments, String paramName, String typeName, String simpleTypeName) {
|
||||
String mockValue = "";
|
||||
if (JavaClassValidateUtil.isPrimitive(typeName)) {
|
||||
mockValue = paramsComments.get(paramName);
|
||||
if (Objects.nonNull(mockValue) && mockValue.contains("|")) {
|
||||
mockValue = mockValue.substring(mockValue.lastIndexOf("|") + 1);
|
||||
} else {
|
||||
mockValue = "";
|
||||
}
|
||||
if (StringUtil.isEmpty(mockValue)) {
|
||||
mockValue = DocUtil.getValByTypeAndFieldName(simpleTypeName, paramName, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
return mockValue;
|
||||
}
|
||||
|
||||
private static void setTornaArrayTags(List<JavaParameter> javaParameters, ApiMethodDoc apiMethodDoc, JavaClass returnClass) {
|
||||
|
||||
apiMethodDoc.setIsResponseArray(0);
|
||||
apiMethodDoc.setIsRequestArray(0);
|
||||
//response tags
|
||||
if (JavaClassValidateUtil.isCollection(returnClass.getFullyQualifiedName()) ||
|
||||
JavaClassValidateUtil.isArray(returnClass.getFullyQualifiedName())) {
|
||||
apiMethodDoc.setIsResponseArray(1);
|
||||
String gicType;
|
||||
String simpleGicType;
|
||||
String typeName = returnClass.getGenericFullyQualifiedName();
|
||||
gicType = getType(typeName);
|
||||
simpleGicType = gicType.substring(gicType.lastIndexOf(".") + 1).toLowerCase();
|
||||
apiMethodDoc.setResponseArrayType(JavaClassValidateUtil.isPrimitive(gicType) ? simpleGicType : OBJECT);
|
||||
}
|
||||
//request tags
|
||||
if (CollectionUtil.isNotEmpty(javaParameters)) {
|
||||
for (JavaParameter parameter : javaParameters) {
|
||||
String gicType;
|
||||
String simpleGicType;
|
||||
String typeName = parameter.getType().getGenericFullyQualifiedName();
|
||||
String name = parameter.getType().getFullyQualifiedName();
|
||||
gicType = getType(typeName);
|
||||
simpleGicType = gicType.substring(gicType.lastIndexOf(".") + 1).toLowerCase();
|
||||
// is array
|
||||
if (JavaClassValidateUtil.isCollection(name) || JavaClassValidateUtil.isArray(name)) {
|
||||
boolean hasRequestBody = false;
|
||||
//param has @RequestBody ?
|
||||
List<JavaAnnotation> annotations = parameter.getAnnotations();
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
if (REQUEST_BODY_FULLY.equals(annotation.getType().getName())) {
|
||||
hasRequestBody = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//formData - multiple data
|
||||
if (!hasRequestBody && javaParameters.size() > 1) {
|
||||
return;
|
||||
} else {
|
||||
apiMethodDoc.setIsRequestArray(1);
|
||||
if (JavaClassValidateUtil.isPrimitive(gicType)) {
|
||||
apiMethodDoc.setRequestArrayType(simpleGicType);
|
||||
} else {
|
||||
apiMethodDoc.setRequestArrayType(OBJECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ApiRequestExample buildReqJson(DocJavaMethod javaMethod, ApiMethodDoc apiMethodDoc, String methodType,
|
||||
ProjectDocConfigBuilder configBuilder) {
|
||||
JavaMethod method = javaMethod.getJavaMethod();
|
||||
Map<String, String> pathParamsMap = new LinkedHashMap<>();
|
||||
List<JavaAnnotation> methodAnnotations = method.getAnnotations();
|
||||
List<JavaParameter> parameterList = method.getParameters();
|
||||
List<ApiReqParam> reqHeaderList = apiMethodDoc.getRequestHeaders();
|
||||
if (parameterList.size() < 1) {
|
||||
CurlRequest curlRequest = CurlRequest.builder()
|
||||
.setContentType(apiMethodDoc.getContentType())
|
||||
.setType(methodType)
|
||||
.setReqHeaders(reqHeaderList)
|
||||
.setUrl(apiMethodDoc.getUrl());
|
||||
String format = CurlUtil.toCurl(curlRequest);
|
||||
return ApiRequestExample.builder().setUrl(apiMethodDoc.getUrl()).setExampleBody(format);
|
||||
}
|
||||
Set<String> ignoreSets = ignoreParamsSets(method);
|
||||
Map<String, JavaType> actualTypesMap = javaMethod.getActualTypesMap();
|
||||
Map<String, String> constantsMap = configBuilder.getConstantsMap();
|
||||
boolean requestFieldToUnderline = configBuilder.getApiConfig().isRequestFieldToUnderline();
|
||||
Map<String, String> replacementMap = configBuilder.getReplaceClassMap();
|
||||
Map<String, String> paramsComments = DocUtil.getParamsComments(method, DocTags.PARAM, null);
|
||||
List<FormData> formDataList = new ArrayList<>();
|
||||
ApiRequestExample requestExample = ApiRequestExample.builder();
|
||||
for (JavaParameter parameter : parameterList) {
|
||||
JavaType javaType = parameter.getType();
|
||||
if (Objects.nonNull(actualTypesMap) && Objects.nonNull(actualTypesMap.get(javaType.getCanonicalName()))) {
|
||||
javaType = actualTypesMap.get(javaType.getCanonicalName());
|
||||
}
|
||||
String paramName = parameter.getName();
|
||||
if (ignoreSets.contains(paramName)) {
|
||||
continue;
|
||||
}
|
||||
String typeName = javaType.getFullyQualifiedName();
|
||||
String gicTypeName = javaType.getGenericCanonicalName();
|
||||
|
||||
String commentClass = paramsComments.get(paramName);
|
||||
//ignore request params
|
||||
if (Objects.nonNull(commentClass) && commentClass.contains(IGNORE)) {
|
||||
continue;
|
||||
}
|
||||
String rewriteClassName = this.getRewriteClassName(replacementMap, typeName, commentClass);
|
||||
// rewrite class
|
||||
if (DocUtil.isClassName(rewriteClassName)) {
|
||||
gicTypeName = rewriteClassName;
|
||||
typeName = DocClassUtil.getSimpleName(rewriteClassName);
|
||||
}
|
||||
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, configBuilder.getApiConfig()
|
||||
.getIgnoreRequestParams())) {
|
||||
continue;
|
||||
}
|
||||
String simpleTypeName = javaType.getValue();
|
||||
typeName = DocClassUtil.rewriteRequestParam(typeName);
|
||||
gicTypeName = DocClassUtil.rewriteRequestParam(gicTypeName);
|
||||
//if params is collection
|
||||
if (JavaClassValidateUtil.isCollection(typeName)) {
|
||||
apiMethodDoc.setListParam(true);
|
||||
}
|
||||
JavaClass javaClass = configBuilder.getJavaProjectBuilder().getClassByName(typeName);
|
||||
String[] globGicName = DocClassUtil.getSimpleGicName(gicTypeName);
|
||||
String comment = this.paramCommentResolve(paramsComments.get(paramName));
|
||||
String mockValue = createMockValue(paramsComments, paramName, typeName, simpleTypeName);
|
||||
if (requestFieldToUnderline) {
|
||||
paramName = StringUtil.camelToUnderline(paramName);
|
||||
}
|
||||
List<JavaAnnotation> annotations = parameter.getAnnotations();
|
||||
List<String> groupClasses = JavaClassUtil.getParamGroupJavaClass(annotations);
|
||||
boolean paramAdded = false;
|
||||
for (JavaAnnotation annotation : methodAnnotations) {
|
||||
String annotationName = annotation.getType().getValue();
|
||||
if (JAXRSAnnotations.JAX_CONSUMES.equals(annotationName) || paramAdded) {
|
||||
AnnotationValue avalue = annotation.getProperty(DocAnnotationConstants.VALUE_PROP);
|
||||
if (avalue != null && avalue.toString().contains("json") || avalue.toString().contains("JSON")) {
|
||||
paramName = getParamName(paramName, annotation);
|
||||
for (Map.Entry<String, String> entry : constantsMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
// replace param
|
||||
if (paramName.contains(key)) {
|
||||
paramName = paramName.replace(key, value);
|
||||
}
|
||||
// replace mockValue
|
||||
if (mockValue.contains(key)) {
|
||||
mockValue = mockValue.replace(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
apiMethodDoc.setContentType(JSON_CONTENT_TYPE);
|
||||
if (Objects.nonNull(configBuilder.getApiConfig().getRequestBodyAdvice())
|
||||
&& Objects.isNull(method.getTagByName(IGNORE_REQUEST_BODY_ADVICE))) {
|
||||
String requestBodyAdvice = configBuilder.getApiConfig()
|
||||
.getRequestBodyAdvice()
|
||||
.getClassName();
|
||||
typeName = configBuilder.getApiConfig().getRequestBodyAdvice().getClassName();
|
||||
gicTypeName = requestBodyAdvice + "<" + gicTypeName + ">";
|
||||
}
|
||||
|
||||
if (JavaClassValidateUtil.isPrimitive(simpleTypeName)) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("{\"")
|
||||
.append(paramName)
|
||||
.append("\":")
|
||||
.append(DocUtil.handleJsonStr(mockValue))
|
||||
.append("}");
|
||||
requestExample.setJsonBody(JsonUtil.toPrettyFormat(builder.toString())).setJson(true);
|
||||
} else {
|
||||
String json = JsonBuildHelper.buildJson(typeName, gicTypeName, Boolean.FALSE, 0, new HashMap<>(),groupClasses, configBuilder);
|
||||
requestExample.setJsonBody(JsonUtil.toPrettyFormat(json)).setJson(true);
|
||||
}
|
||||
paramAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (JAXRSAnnotations.JAX_PATH_PARAM.equals(annotationName)) {
|
||||
if (javaClass.isEnum()) {
|
||||
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE);
|
||||
mockValue = StringUtil.removeQuotes(String.valueOf(value));
|
||||
}
|
||||
pathParamsMap.put(paramName, mockValue);
|
||||
paramAdded = true;
|
||||
}
|
||||
if (paramAdded) {
|
||||
continue;
|
||||
}
|
||||
//file upload
|
||||
if (JavaClassValidateUtil.isFile(gicTypeName)) {
|
||||
apiMethodDoc.setContentType(FILE_CONTENT_TYPE);
|
||||
FormData formData = new FormData();
|
||||
formData.setKey(paramName);
|
||||
formData.setType("file");
|
||||
formData.setDescription(comment);
|
||||
formData.setValue(mockValue);
|
||||
formDataList.add(formData);
|
||||
} else if (JavaClassValidateUtil.isPrimitive(typeName)) {
|
||||
FormData formData = new FormData();
|
||||
formData.setKey(paramName);
|
||||
formData.setDescription(comment);
|
||||
formData.setType("text");
|
||||
formData.setValue(mockValue);
|
||||
formDataList.add(formData);
|
||||
} else if (JavaClassValidateUtil.isArray(typeName) || JavaClassValidateUtil.isCollection(typeName)) {
|
||||
String gicName = globGicName[0];
|
||||
if (JavaClassValidateUtil.isArray(gicName)) {
|
||||
gicName = gicName.substring(0, gicName.indexOf("["));
|
||||
}
|
||||
if (!JavaClassValidateUtil.isPrimitive(gicName)
|
||||
&& !configBuilder.getJavaProjectBuilder().getClassByName(gicName).isEnum()) {
|
||||
throw new RuntimeException("Dubbo rest can't support binding Collection on method "
|
||||
+ method.getName() + "Check it in " + method.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
FormData formData = new FormData();
|
||||
formData.setKey(paramName);
|
||||
if (!paramName.contains("[]")) {
|
||||
formData.setKey(paramName + "[]");
|
||||
}
|
||||
formData.setDescription(comment);
|
||||
formData.setType("text");
|
||||
formData.setValue(RandomUtil.randomValueByType(gicName));
|
||||
formDataList.add(formData);
|
||||
} else if (javaClass.isEnum()) {
|
||||
// do nothing
|
||||
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE);
|
||||
String strVal = StringUtil.removeQuotes(String.valueOf(value));
|
||||
FormData formData = new FormData();
|
||||
formData.setKey(paramName);
|
||||
formData.setType("text");
|
||||
formData.setDescription(comment);
|
||||
formData.setValue(strVal);
|
||||
formDataList.add(formData);
|
||||
} else {
|
||||
formDataList.addAll(FormDataBuildHelper.getFormData(gicTypeName, new HashMap<>(), 0, configBuilder, DocGlobalConstants.EMPTY));
|
||||
}
|
||||
}
|
||||
}
|
||||
requestExample.setFormDataList(formDataList);
|
||||
String[] paths = apiMethodDoc.getPath().split(";");
|
||||
String path = paths[0];
|
||||
String body;
|
||||
String exampleBody;
|
||||
String url;
|
||||
if (Methods.POST.getValue()
|
||||
.equals(methodType) || Methods.PUT.getValue()
|
||||
.equals(methodType)) {
|
||||
//for post put
|
||||
path = DocUtil.formatAndRemove(path, pathParamsMap);
|
||||
body = UrlUtil.urlJoin(DocGlobalConstants.EMPTY, DocUtil.formDataToMap(formDataList))
|
||||
.replace("?", DocGlobalConstants.EMPTY);
|
||||
body = StringUtil.removeQuotes(body);
|
||||
url = apiMethodDoc.getServerUrl() + "/" + path;
|
||||
url = UrlUtil.simplifyUrl(url);
|
||||
|
||||
if (requestExample.isJson()) {
|
||||
if (StringUtil.isNotEmpty(body)) {
|
||||
url = url + "?" + body;
|
||||
}
|
||||
CurlRequest curlRequest = CurlRequest.builder()
|
||||
.setBody(requestExample.getJsonBody())
|
||||
.setContentType(apiMethodDoc.getContentType())
|
||||
.setType(methodType)
|
||||
.setReqHeaders(reqHeaderList)
|
||||
.setUrl(url);
|
||||
exampleBody = CurlUtil.toCurl(curlRequest);
|
||||
} else {
|
||||
CurlRequest curlRequest;
|
||||
if (StringUtil.isNotEmpty(body)) {
|
||||
curlRequest = CurlRequest.builder()
|
||||
.setBody(body)
|
||||
.setContentType(apiMethodDoc.getContentType())
|
||||
.setType(methodType)
|
||||
.setReqHeaders(reqHeaderList)
|
||||
.setUrl(url);
|
||||
} else {
|
||||
curlRequest = CurlRequest.builder()
|
||||
.setBody(requestExample.getJsonBody())
|
||||
.setContentType(apiMethodDoc.getContentType())
|
||||
.setType(methodType)
|
||||
.setReqHeaders(reqHeaderList)
|
||||
.setUrl(url);
|
||||
}
|
||||
exampleBody = CurlUtil.toCurl(curlRequest);
|
||||
}
|
||||
requestExample.setExampleBody(exampleBody).setUrl(url);
|
||||
} else {
|
||||
// for get delete
|
||||
pathParamsMap.putAll(DocUtil.formDataToMap(formDataList));
|
||||
path = DocUtil.formatAndRemove(path, pathParamsMap);
|
||||
url = UrlUtil.urlJoin(path, pathParamsMap);
|
||||
url = StringUtil.removeQuotes(url);
|
||||
url = apiMethodDoc.getServerUrl() + "/" + url;
|
||||
url = UrlUtil.simplifyUrl(url);
|
||||
CurlRequest curlRequest = CurlRequest.builder()
|
||||
.setBody(requestExample.getJsonBody())
|
||||
.setContentType(apiMethodDoc.getContentType())
|
||||
.setType(methodType)
|
||||
.setReqHeaders(reqHeaderList)
|
||||
.setUrl(url);
|
||||
exampleBody = CurlUtil.toCurl(curlRequest);
|
||||
requestExample.setExampleBody(exampleBody)
|
||||
.setJsonBody(DocGlobalConstants.EMPTY)
|
||||
.setUrl(url);
|
||||
}
|
||||
return requestExample;
|
||||
}
|
||||
|
||||
private String getRewriteClassName(Map<String, String> replacementMap, String fullTypeName, String commentClass) {
|
||||
String rewriteClassName;
|
||||
if (Objects.nonNull(commentClass) && !DocGlobalConstants.NO_COMMENTS_FOUND.equals(commentClass)) {
|
||||
String[] comments = commentClass.split("\\|");
|
||||
rewriteClassName = comments[comments.length - 1];
|
||||
if (DocUtil.isClassName(rewriteClassName)) {
|
||||
return rewriteClassName;
|
||||
}
|
||||
}
|
||||
return replacementMap.get(fullTypeName);
|
||||
}
|
||||
|
||||
private static String getType(String typeName) {
|
||||
String gicType;
|
||||
//get generic type
|
||||
if (typeName.contains("<")) {
|
||||
gicType = typeName.substring(typeName.indexOf("<") + 1, typeName.lastIndexOf(">"));
|
||||
} else {
|
||||
gicType = typeName;
|
||||
}
|
||||
if (gicType.contains("[")) {
|
||||
gicType = gicType.substring(0, gicType.indexOf("["));
|
||||
}
|
||||
return gicType;
|
||||
}
|
||||
|
||||
private boolean checkController(JavaClass cls) {
|
||||
if (cls.isAnnotation() || cls.isEnum()) {
|
||||
return false;
|
||||
}
|
||||
JavaClass superClass = cls.getSuperJavaClass();
|
||||
List<JavaAnnotation> classAnnotations = new ArrayList<>();
|
||||
if (Objects.nonNull(superClass)) {
|
||||
classAnnotations.addAll(superClass.getAnnotations());
|
||||
}
|
||||
classAnnotations.addAll(cls.getAnnotations());
|
||||
for (JavaAnnotation annotation : classAnnotations) {
|
||||
String name = annotation.getType().getValue();
|
||||
if (JAXRSAnnotations.JAX_PATH.equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// use custom doc tag to support Feign.
|
||||
List<DocletTag> docletTags = cls.getTags();
|
||||
for (DocletTag docletTag : docletTags) {
|
||||
String value = docletTag.getName();
|
||||
if (DocTags.DUBBO_REST.equals(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -35,10 +35,7 @@ import com.power.doc.model.ApiParam;
|
|||
import com.power.doc.model.DocJavaMethod;
|
||||
import com.power.doc.model.JavaMethodDoc;
|
||||
import com.power.doc.model.rpc.RpcApiDoc;
|
||||
import com.power.doc.utils.DocClassUtil;
|
||||
import com.power.doc.utils.DocUtil;
|
||||
import com.power.doc.utils.JavaClassUtil;
|
||||
import com.power.doc.utils.JavaClassValidateUtil;
|
||||
import com.power.doc.utils.*;
|
||||
import com.thoughtworks.qdox.model.*;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -70,7 +67,8 @@ public class RpcDocBuildTemplate implements IDocBuildTemplate<RpcApiDoc> {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (!checkDubboInterface(cls)) {
|
||||
DocletTag ignoreTag = cls.getTagByName(DocTags.IGNORE);
|
||||
if (!checkDubboInterface(cls)|| Objects.nonNull(ignoreTag)) {
|
||||
continue;
|
||||
}
|
||||
String strOrder = JavaClassUtil.getClassTagsValue(cls, DocTags.ORDER, Boolean.TRUE);
|
||||
|
@ -152,12 +150,20 @@ public class RpcDocBuildTemplate implements IDocBuildTemplate<RpcApiDoc> {
|
|||
continue;
|
||||
}
|
||||
apiMethodDoc.setDeprecated(deprecated);
|
||||
|
||||
|
||||
// build request params
|
||||
List<ApiParam> requestParams = requestParams(method, projectBuilder);
|
||||
apiMethodDoc.setRequestParams(requestParams);
|
||||
// build response params
|
||||
List<ApiParam> responseParams = buildReturnApiParams(DocJavaMethod.builder().setJavaMethod(method), projectBuilder);
|
||||
apiMethodDoc.setResponseParams(responseParams);
|
||||
|
||||
if (apiConfig.isParamsDataToTree()) {
|
||||
apiMethodDoc.setRequestParams(ApiParamTreeUtil.apiParamToTree(requestParams));
|
||||
apiMethodDoc.setResponseParams(ApiParamTreeUtil.apiParamToTree(responseParams));
|
||||
} else {
|
||||
apiMethodDoc.setRequestParams(requestParams);
|
||||
apiMethodDoc.setResponseParams(responseParams);
|
||||
}
|
||||
methodDocList.add(apiMethodDoc);
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import com.power.doc.model.request.RequestMapping;
|
|||
import com.power.doc.utils.*;
|
||||
import com.thoughtworks.qdox.model.*;
|
||||
import com.thoughtworks.qdox.model.expression.AnnotationValue;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -44,8 +45,7 @@ import java.util.logging.Logger;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.power.doc.constants.DocGlobalConstants.FILE_CONTENT_TYPE;
|
||||
import static com.power.doc.constants.DocGlobalConstants.JSON_CONTENT_TYPE;
|
||||
import static com.power.doc.constants.DocGlobalConstants.*;
|
||||
import static com.power.doc.constants.DocTags.IGNORE;
|
||||
import static com.power.doc.constants.DocTags.IGNORE_REQUEST_BODY_ADVICE;
|
||||
|
||||
|
@ -59,12 +59,13 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
* api index
|
||||
*/
|
||||
private final AtomicInteger atomicInteger = new AtomicInteger(1);
|
||||
private List<ApiReqHeader> headers;
|
||||
private List<ApiReqParam> configApiReqParams;
|
||||
|
||||
@Override
|
||||
public List<ApiDoc> getApiData(ProjectDocConfigBuilder projectBuilder) {
|
||||
ApiConfig apiConfig = projectBuilder.getApiConfig();
|
||||
this.headers = apiConfig.getRequestHeaders();
|
||||
this.configApiReqParams = Stream.of(apiConfig.getRequestHeaders(), apiConfig.getRequestParams()).filter(Objects::nonNull)
|
||||
.flatMap(Collection::stream).collect(Collectors.toList());
|
||||
List<ApiDoc> apiDocList = new ArrayList<>();
|
||||
int order = 0;
|
||||
Collection<JavaClass> classes = projectBuilder.getJavaProjectBuilder().getClasses();
|
||||
|
@ -75,8 +76,8 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
String ignoreTag = JavaClassUtil.getClassTagsValue(cls, DocTags.IGNORE, Boolean.FALSE);
|
||||
if (!checkController(cls) || StringUtil.isNotEmpty(ignoreTag)) {
|
||||
DocletTag ignoreTag = cls.getTagByName(DocTags.IGNORE);
|
||||
if (!checkController(cls) || Objects.nonNull(ignoreTag)) {
|
||||
continue;
|
||||
}
|
||||
String strOrder = JavaClassUtil.getClassTagsValue(cls, DocTags.ORDER, Boolean.TRUE);
|
||||
|
@ -88,6 +89,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
List<ApiMethodDoc> apiMethodDocs = buildControllerMethod(cls, apiConfig, projectBuilder);
|
||||
this.handleApiDoc(cls, apiDocList, apiMethodDocs, order, apiConfig.isMd5EncryptedHtmlName());
|
||||
}
|
||||
// handle TagsApiDoc
|
||||
apiDocList = handleTagsApiDoc(apiDocList);
|
||||
|
||||
// sort
|
||||
if (apiConfig.isSortByTitle()) {
|
||||
Collections.sort(apiDocList);
|
||||
|
@ -100,6 +104,70 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
return apiDocList;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle tags to api doc
|
||||
* copy the same tag
|
||||
*
|
||||
* @author cqmike
|
||||
*/
|
||||
private List<ApiDoc> handleTagsApiDoc(List<ApiDoc> apiDocList) {
|
||||
if (CollectionUtil.isEmpty(apiDocList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// all class tag copy
|
||||
Map<String, ApiDoc> copyMap = new HashMap<>();
|
||||
apiDocList.forEach(doc -> {
|
||||
String[] tags = doc.getTags();
|
||||
if (ArrayUtils.isEmpty(tags)) {
|
||||
tags = new String[]{doc.getName()};
|
||||
}
|
||||
|
||||
for (String tag : tags) {
|
||||
tag = StringUtil.trim(tag);
|
||||
copyMap.computeIfPresent(tag, (k, v) -> {
|
||||
List<ApiMethodDoc> list = CollectionUtil.isEmpty(v.getList()) ? new ArrayList<>() : v.getList();
|
||||
list.addAll(doc.getList());
|
||||
v.setList(list);
|
||||
return v;
|
||||
});
|
||||
copyMap.putIfAbsent(tag, doc);
|
||||
}
|
||||
});
|
||||
|
||||
// handle method tag
|
||||
Map<String, ApiDoc> allMap = new HashMap<>(copyMap);
|
||||
allMap.forEach((k, v) -> {
|
||||
List<ApiMethodDoc> methodDocList = v.getList();
|
||||
methodDocList.forEach(method -> {
|
||||
String[] tags = method.getTags();
|
||||
if (ArrayUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
for (String tag : tags) {
|
||||
tag = StringUtil.trim(tag);
|
||||
copyMap.computeIfPresent(tag, (k1, v2) -> {
|
||||
method.setOrder(v2.getList().size() + 1);
|
||||
v2.getList().add(method);
|
||||
return v2;
|
||||
});
|
||||
copyMap.putIfAbsent(tag, ApiDoc.buildTagApiDoc(v, tag, method));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
List<ApiDoc> apiDocs = new ArrayList<>(copyMap.values());
|
||||
int index = apiDocs.size() - 1;
|
||||
for (ApiDoc apiDoc : apiDocs) {
|
||||
if (apiDoc.getOrder() == null) {
|
||||
apiDoc.setOrder(index++);
|
||||
}
|
||||
}
|
||||
apiDocs.sort(Comparator.comparing(ApiDoc::getOrder));
|
||||
return apiDocs;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ApiDoc getSingleApiData(ProjectDocConfigBuilder projectBuilder, String apiClassName) {
|
||||
return null;
|
||||
|
@ -107,10 +175,7 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
|
||||
@Override
|
||||
public boolean ignoreReturnObject(String typeName, List<String> ignoreParams) {
|
||||
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, ignoreParams)) {
|
||||
return DocGlobalConstants.MODE_AND_VIEW_FULLY.equals(typeName);
|
||||
}
|
||||
return false;
|
||||
return JavaClassValidateUtil.isMvcIgnoreParams(typeName, ignoreParams);
|
||||
}
|
||||
|
||||
private List<ApiMethodDoc> buildControllerMethod(final JavaClass cls, ApiConfig apiConfig,
|
||||
|
@ -128,7 +193,12 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
DocGlobalConstants.REQUEST_MAPPING_FULLY.equals(annotationName)) {
|
||||
baseUrl = StringUtil.removeQuotes(DocUtil.getRequestMappingUrl(annotation));
|
||||
}
|
||||
//FeignClient path handle
|
||||
if (DocGlobalConstants.FEIGN_CLIENT.equals(annotationName) || DocGlobalConstants.FEIGN_CLIENT_FULLY.equals(annotationName)) {
|
||||
baseUrl = StringUtil.removeQuotes(DocUtil.getPathUrl(annotation, DocAnnotationConstants.PATH_PROP));
|
||||
}
|
||||
}
|
||||
|
||||
List<JavaMethod> methods = cls.getMethods();
|
||||
List<DocJavaMethod> docJavaMethods = new ArrayList<>(methods.size());
|
||||
for (JavaMethod method : methods) {
|
||||
|
@ -145,6 +215,16 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
docJavaMethods.add(DocJavaMethod.builder().setJavaMethod(method).setActualTypesMap(actualTypesMap));
|
||||
}
|
||||
}
|
||||
List<JavaType> implClasses = cls.getImplements();
|
||||
for (JavaType type : implClasses) {
|
||||
JavaClass javaClass = (JavaClass) type;
|
||||
Map<String, JavaType> actualTypesMap = JavaClassUtil.getActualTypesMap(javaClass);
|
||||
for (JavaMethod method : javaClass.getMethods()) {
|
||||
if (method.isDefault()) {
|
||||
docJavaMethods.add(DocJavaMethod.builder().setJavaMethod(method).setActualTypesMap(actualTypesMap));
|
||||
}
|
||||
}
|
||||
}
|
||||
List<ApiMethodDoc> methodDocList = new ArrayList<>(methods.size());
|
||||
int methodOrder = 0;
|
||||
for (DocJavaMethod docJavaMethod : docJavaMethods) {
|
||||
|
@ -177,6 +257,11 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
} else {
|
||||
apiMethodDoc.setGroup(group);
|
||||
}
|
||||
|
||||
// handle tags
|
||||
List<DocletTag> tags = method.getTagsByName(DocTags.TAG);
|
||||
apiMethodDoc.setTags(tags.stream().map(DocletTag::getValue).toArray(String[]::new));
|
||||
|
||||
methodOrder++;
|
||||
apiMethodDoc.setName(method.getName());
|
||||
apiMethodDoc.setOrder(methodOrder);
|
||||
|
@ -191,21 +276,28 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
Map<String, String> authorMap = DocUtil.getParamsComments(method, DocTags.AUTHOR, cls.getName());
|
||||
String authorValue = String.join(", ", new ArrayList<>(authorMap.keySet()));
|
||||
if (apiConfig.isShowAuthor() && StringUtil.isNotEmpty(authorValue)) {
|
||||
apiMethodDoc.setAuthor(authorValue);
|
||||
apiMethodDoc.setAuthor(JsonUtil.toPrettyFormat(authorValue));
|
||||
}
|
||||
if (apiConfig.isShowAuthor() && StringUtil.isEmpty(authorValue)) {
|
||||
apiMethodDoc.setAuthor(classAuthor);
|
||||
}
|
||||
apiMethodDoc.setDetail(apiNoteValue);
|
||||
//handle headers
|
||||
List<ApiReqHeader> apiReqHeaders = new SpringMVCRequestHeaderHandler().handle(method);
|
||||
List<ApiReqParam> apiReqHeaders = new SpringMVCRequestHeaderHandler().handle(method, projectBuilder);
|
||||
|
||||
apiMethodDoc.setType(requestMapping.getMethodType());
|
||||
apiMethodDoc.setUrl(requestMapping.getUrl());
|
||||
apiMethodDoc.setServerUrl(projectBuilder.getServerUrl());
|
||||
apiMethodDoc.setPath(requestMapping.getShortUrl());
|
||||
apiMethodDoc.setDeprecated(requestMapping.isDeprecated());
|
||||
ApiMethodReqParam apiMethodReqParam = requestParams(docJavaMethod, projectBuilder);
|
||||
List<JavaParameter> javaParameters = method.getParameters();
|
||||
|
||||
setTornaArrayTags(javaParameters, apiMethodDoc, docJavaMethod.getJavaMethod().getReturns());
|
||||
// apiMethodDoc.setIsRequestArray();
|
||||
final List<ApiReqParam> apiReqParamList = this.configApiReqParams.stream()
|
||||
.filter(param -> filterPath(requestMapping, param)).collect(Collectors.toList());
|
||||
|
||||
ApiMethodReqParam apiMethodReqParam = requestParams(docJavaMethod, projectBuilder, apiReqParamList);
|
||||
// build request params
|
||||
if (paramsDataToTree) {
|
||||
apiMethodDoc.setPathParams(ApiParamTreeUtil.apiParamToTree(apiMethodReqParam.getPathParams()));
|
||||
|
@ -217,17 +309,32 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
apiMethodDoc.setRequestParams(apiMethodReqParam.getRequestParams());
|
||||
}
|
||||
|
||||
List<ApiReqHeader> allApiReqHeaders;
|
||||
if (this.headers != null) {
|
||||
allApiReqHeaders = Stream.of(this.headers, apiReqHeaders)
|
||||
List<ApiReqParam> allApiReqHeaders;
|
||||
if (this.configApiReqParams != null) {
|
||||
final Map<String, List<ApiReqParam>> reqParamMap = apiReqParamList.stream().collect(Collectors.groupingBy(ApiReqParam::getParamIn));
|
||||
final List<ApiReqParam> headerParamList = reqParamMap.getOrDefault(ApiReqParamInTypeEnum.HEADER.getValue(), Collections.emptyList());
|
||||
allApiReqHeaders = Stream.of(apiReqHeaders, headerParamList).filter(Objects::nonNull)
|
||||
.flatMap(Collection::stream).distinct().collect(Collectors.toList());
|
||||
} else {
|
||||
allApiReqHeaders = apiReqHeaders;
|
||||
allApiReqHeaders = apiReqHeaders.stream().filter(param -> filterPath(requestMapping, param)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
//reduce create in template
|
||||
apiMethodDoc.setHeaders(this.createDocRenderHeaders(allApiReqHeaders, apiConfig.isAdoc()));
|
||||
apiMethodDoc.setRequestHeaders(allApiReqHeaders);
|
||||
|
||||
String path = apiMethodDoc.getPath().split(";")[0];
|
||||
String pathUrl = DocUtil.formatPathUrl(path);
|
||||
List<ApiParam> pathParams = apiMethodDoc.getPathParams();
|
||||
Iterator<ApiParam> pathIterator = pathParams.iterator();
|
||||
while (pathIterator.hasNext()) {
|
||||
ApiParam next = pathIterator.next();
|
||||
String pathKey = "{" + next.getField() + "}";
|
||||
if (!pathUrl.contains(pathKey)) {
|
||||
pathIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// build request json
|
||||
ApiRequestExample requestExample = buildReqJson(docJavaMethod, apiMethodDoc, requestMapping.getMethodType(),
|
||||
projectBuilder);
|
||||
|
@ -236,7 +343,13 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
apiMethodDoc.setRequestExample(requestExample);
|
||||
apiMethodDoc.setRequestUsage(requestJson == null ? requestExample.getUrl() : requestJson);
|
||||
// build response usage
|
||||
apiMethodDoc.setResponseUsage(JsonBuildHelper.buildReturnJson(docJavaMethod, projectBuilder));
|
||||
String responseValue = DocUtil.getNormalTagComments(method, DocTags.API_RESPONSE, cls.getName());
|
||||
if (StringUtil.isNotEmpty(responseValue)) {
|
||||
responseValue = responseValue.replaceAll("<br>", "");
|
||||
apiMethodDoc.setResponseUsage(JsonUtil.toPrettyFormat(responseValue));
|
||||
} else {
|
||||
apiMethodDoc.setResponseUsage(JsonBuildHelper.buildReturnJson(docJavaMethod, projectBuilder));
|
||||
}
|
||||
// build response params
|
||||
List<ApiParam> responseParams = buildReturnApiParams(docJavaMethod, projectBuilder);
|
||||
if (paramsDataToTree) {
|
||||
|
@ -250,10 +363,28 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
return methodDocList;
|
||||
}
|
||||
|
||||
private boolean filterPath(RequestMapping requestMapping, ApiReqParam apiReqHeader) {
|
||||
if (StringUtil.isEmpty(apiReqHeader.getPathPatterns())
|
||||
&& StringUtil.isEmpty(apiReqHeader.getExcludePathPatterns())) {
|
||||
return true;
|
||||
}
|
||||
return DocPathUtil.matches(requestMapping.getShortUrl(), apiReqHeader.getPathPatterns()
|
||||
, apiReqHeader.getExcludePathPatterns());
|
||||
|
||||
}
|
||||
|
||||
private ApiRequestExample buildReqJson(DocJavaMethod javaMethod, ApiMethodDoc apiMethodDoc, String methodType,
|
||||
ProjectDocConfigBuilder configBuilder) {
|
||||
JavaMethod method = javaMethod.getJavaMethod();
|
||||
Map<String, String> pathParamsMap = new LinkedHashMap<>();
|
||||
Map<String, String> queryParamsMap = new LinkedHashMap<>();
|
||||
|
||||
apiMethodDoc.getPathParams().stream().filter(Objects::nonNull).filter(ApiParam::isConfigParam)
|
||||
.forEach(param -> pathParamsMap.put(param.getField(), param.getValue()));
|
||||
|
||||
apiMethodDoc.getQueryParams().stream().filter(Objects::nonNull).filter(ApiParam::isConfigParam)
|
||||
.forEach(param -> queryParamsMap.put(param.getField(), param.getValue()));
|
||||
|
||||
List<JavaAnnotation> methodAnnotations = method.getAnnotations();
|
||||
for (JavaAnnotation annotation : methodAnnotations) {
|
||||
String annotationName = annotation.getType().getName();
|
||||
|
@ -264,23 +395,29 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
}
|
||||
String params = StringUtil.removeQuotes(paramsObjects.toString());
|
||||
if (!params.startsWith("[")) {
|
||||
mappingParamProcess(paramsObjects.toString(), pathParamsMap);
|
||||
mappingParamProcess(paramsObjects.toString(), queryParamsMap);
|
||||
continue;
|
||||
}
|
||||
List<String> headers = (LinkedList) paramsObjects;
|
||||
for (String str : headers) {
|
||||
mappingParamProcess(str, pathParamsMap);
|
||||
mappingParamProcess(str, queryParamsMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<JavaParameter> parameterList = method.getParameters();
|
||||
List<ApiReqHeader> reqHeaderList = apiMethodDoc.getRequestHeaders();
|
||||
List<ApiReqParam> reqHeaderList = apiMethodDoc.getRequestHeaders();
|
||||
if (parameterList.size() < 1) {
|
||||
String path = apiMethodDoc.getPath().split(";")[0];
|
||||
path = DocUtil.formatAndRemove(path, pathParamsMap);
|
||||
String url = UrlUtil.urlJoin(path, queryParamsMap);
|
||||
url = StringUtil.removeQuotes(url);
|
||||
url = apiMethodDoc.getServerUrl() + "/" + url;
|
||||
url = UrlUtil.simplifyUrl(url);
|
||||
CurlRequest curlRequest = CurlRequest.builder()
|
||||
.setContentType(apiMethodDoc.getContentType())
|
||||
.setType(methodType)
|
||||
.setReqHeaders(reqHeaderList)
|
||||
.setUrl(apiMethodDoc.getUrl());
|
||||
.setUrl(url);
|
||||
String format = CurlUtil.toCurl(curlRequest);
|
||||
return ApiRequestExample.builder().setUrl(apiMethodDoc.getUrl()).setExampleBody(format);
|
||||
}
|
||||
|
@ -317,7 +454,8 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
gicTypeName = rewriteClassName;
|
||||
typeName = DocClassUtil.getSimpleName(rewriteClassName);
|
||||
}
|
||||
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, configBuilder.getApiConfig().getIgnoreRequestParams())) {
|
||||
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, configBuilder.getApiConfig()
|
||||
.getIgnoreRequestParams())) {
|
||||
continue;
|
||||
}
|
||||
String simpleTypeName = javaType.getValue();
|
||||
|
@ -331,10 +469,14 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
String[] globGicName = DocClassUtil.getSimpleGicName(gicTypeName);
|
||||
String comment = this.paramCommentResolve(paramsComments.get(paramName));
|
||||
String mockValue = createMockValue(paramsComments, paramName, typeName, simpleTypeName);
|
||||
if (queryParamsMap.containsKey(paramName)) {
|
||||
mockValue = queryParamsMap.get(paramName);
|
||||
}
|
||||
if (requestFieldToUnderline) {
|
||||
paramName = StringUtil.camelToUnderline(paramName);
|
||||
}
|
||||
List<JavaAnnotation> annotations = parameter.getAnnotations();
|
||||
List<String> groupClasses = JavaClassUtil.getParamGroupJavaClass(annotations);
|
||||
boolean paramAdded = false;
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
String annotationName = annotation.getType().getValue();
|
||||
|
@ -342,9 +484,17 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
if (!springMvcRequestAnnotations.contains(fullName) || paramAdded) {
|
||||
continue;
|
||||
}
|
||||
if (SpringMvcAnnotations.SESSION_ATTRIBUTE.equals(annotationName)) {
|
||||
continue out;
|
||||
}
|
||||
if(SpringMvcAnnotations.REQUEST_ATTRIBUTE.equals(annotationName))
|
||||
{
|
||||
continue out;
|
||||
}
|
||||
if (SpringMvcAnnotations.REQUEST_HERDER.equals(annotationName)) {
|
||||
continue out;
|
||||
}
|
||||
|
||||
AnnotationValue annotationDefaultVal = annotation.getProperty(DocAnnotationConstants.DEFAULT_VALUE_PROP);
|
||||
if (null != annotationDefaultVal) {
|
||||
mockValue = StringUtil.removeQuotes(annotationDefaultVal.toString());
|
||||
|
@ -371,18 +521,11 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
gicTypeName = requestBodyAdvice + "<" + gicTypeName + ">";
|
||||
|
||||
}
|
||||
|
||||
if (JavaClassValidateUtil.isPrimitive(simpleTypeName)) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("{\"")
|
||||
.append(paramName)
|
||||
.append("\":")
|
||||
.append(DocUtil.handleJsonStr(mockValue))
|
||||
.append("}");
|
||||
requestExample.setJsonBody(JsonFormatUtil.formatJson(builder.toString())).setJson(true);
|
||||
requestExample.setJsonBody(mockValue).setJson(true);
|
||||
} else {
|
||||
String json = JsonBuildHelper.buildJson(typeName, gicTypeName, Boolean.FALSE, 0, new HashMap<>(), configBuilder);
|
||||
requestExample.setJsonBody(JsonFormatUtil.formatJson(json)).setJson(true);
|
||||
String json = JsonBuildHelper.buildJson(typeName, gicTypeName, Boolean.FALSE, 0, new HashMap<>(), groupClasses, configBuilder);
|
||||
requestExample.setJsonBody(JsonUtil.toPrettyFormat(json)).setJson(true);
|
||||
}
|
||||
paramAdded = true;
|
||||
} else if (SpringMvcAnnotations.PATH_VARIABLE.contains(annotationName)) {
|
||||
|
@ -390,6 +533,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE);
|
||||
mockValue = StringUtil.removeQuotes(String.valueOf(value));
|
||||
}
|
||||
if (pathParamsMap.containsKey(paramName)) {
|
||||
mockValue = pathParamsMap.get(paramName);
|
||||
}
|
||||
pathParamsMap.put(paramName, mockValue);
|
||||
paramAdded = true;
|
||||
}
|
||||
|
@ -452,12 +598,14 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
String body;
|
||||
String exampleBody;
|
||||
String url;
|
||||
final Map<String, String> formDataToMap = DocUtil.formDataToMap(formDataList);
|
||||
if (Methods.POST.getValue()
|
||||
.equals(methodType) || Methods.PUT.getValue()
|
||||
.equals(methodType)) {
|
||||
//for post put
|
||||
path = DocUtil.formatAndRemove(path, pathParamsMap);
|
||||
body = UrlUtil.urlJoin(DocGlobalConstants.EMPTY, DocUtil.formDataToMap(formDataList))
|
||||
formDataToMap.putAll(queryParamsMap);
|
||||
body = UrlUtil.urlJoin(DocGlobalConstants.EMPTY, formDataToMap)
|
||||
.replace("?", DocGlobalConstants.EMPTY);
|
||||
body = StringUtil.removeQuotes(body);
|
||||
url = apiMethodDoc.getServerUrl() + "/" + path;
|
||||
|
@ -496,9 +644,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
requestExample.setExampleBody(exampleBody).setUrl(url);
|
||||
} else {
|
||||
// for get delete
|
||||
pathParamsMap.putAll(DocUtil.formDataToMap(formDataList));
|
||||
queryParamsMap.putAll(formDataToMap);
|
||||
path = DocUtil.formatAndRemove(path, pathParamsMap);
|
||||
url = UrlUtil.urlJoin(path, pathParamsMap);
|
||||
url = UrlUtil.urlJoin(path, queryParamsMap);
|
||||
url = StringUtil.removeQuotes(url);
|
||||
url = apiMethodDoc.getServerUrl() + "/" + url;
|
||||
url = UrlUtil.simplifyUrl(url);
|
||||
|
@ -517,10 +665,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
}
|
||||
|
||||
|
||||
private ApiMethodReqParam requestParams(final DocJavaMethod docJavaMethod, ProjectDocConfigBuilder builder) {
|
||||
private ApiMethodReqParam requestParams(final DocJavaMethod docJavaMethod, ProjectDocConfigBuilder builder, List<ApiReqParam> configApiReqParams) {
|
||||
JavaMethod javaMethod = docJavaMethod.getJavaMethod();
|
||||
boolean isStrict = builder.getApiConfig().isStrict();
|
||||
Map<String, CustomField> responseFieldMap = new HashMap<>();
|
||||
String className = javaMethod.getDeclaringClass().getCanonicalName();
|
||||
Map<String, String> replacementMap = builder.getReplaceClassMap();
|
||||
Map<String, String> paramTagMap = DocUtil.getParamsComments(javaMethod, DocTags.PARAM, className);
|
||||
|
@ -546,10 +693,21 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
}
|
||||
}
|
||||
}
|
||||
final Map<String, Map<String, ApiReqParam>> collect = configApiReqParams.stream().collect(Collectors.groupingBy(ApiReqParam::getParamIn,
|
||||
Collectors.toMap(ApiReqParam::getName, m -> m, (k1, k2) -> k1)));
|
||||
final Map<String, ApiReqParam> pathReqParamMap = collect.getOrDefault(ApiReqParamInTypeEnum.PATH.getValue(), Collections.emptyMap());
|
||||
final Map<String, ApiReqParam> queryReqParamMap = collect.getOrDefault(ApiReqParamInTypeEnum.QUERY.getValue(), Collections.emptyMap());
|
||||
List<JavaParameter> parameterList = javaMethod.getParameters();
|
||||
if (parameterList.size() < 1) {
|
||||
AtomicInteger querySize = new AtomicInteger(paramList.size() + 1);
|
||||
paramList.addAll(queryReqParamMap.values().stream()
|
||||
.map(p -> ApiReqParam.convertToApiParam(p).setQueryParam(true).setId(querySize.getAndIncrement()))
|
||||
.collect(Collectors.toList()));
|
||||
AtomicInteger pathSize = new AtomicInteger(1);
|
||||
return ApiMethodReqParam.builder()
|
||||
.setPathParams(new ArrayList<>(0))
|
||||
.setPathParams(new ArrayList<>(pathReqParamMap.values().stream()
|
||||
.map(p -> ApiReqParam.convertToApiParam(p).setPathParam(true).setId(pathSize.getAndIncrement()))
|
||||
.collect(Collectors.toList())))
|
||||
.setQueryParams(paramList)
|
||||
.setRequestParams(new ArrayList<>(0));
|
||||
}
|
||||
|
@ -618,6 +776,13 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
boolean isRequestBody = false;
|
||||
for (JavaAnnotation annotation : annotations) {
|
||||
String annotationName = annotation.getType().getValue();
|
||||
if (SpringMvcAnnotations.SESSION_ATTRIBUTE.equals(annotationName)) {
|
||||
continue out;
|
||||
}
|
||||
if(SpringMvcAnnotations.REQUEST_ATTRIBUTE.equals(annotationName))
|
||||
{
|
||||
continue out;
|
||||
}
|
||||
if (SpringMvcAnnotations.REQUEST_HERDER.equals(annotationName)) {
|
||||
continue out;
|
||||
}
|
||||
|
@ -697,7 +862,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
}
|
||||
} else if (JavaClassValidateUtil.isPrimitive(gicName)) {
|
||||
String shortSimple = DocClassUtil.processTypeNameForParams(gicName);
|
||||
ApiParam param = ApiParam.of().setField(paramName).setDesc(comment + ",[array of " + shortSimple + "]")
|
||||
ApiParam param = ApiParam.of()
|
||||
.setField(paramName)
|
||||
.setDesc(comment + ",[array of " + shortSimple + "]")
|
||||
.setRequired(required)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
|
@ -717,16 +884,21 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
groupClasses, 0, Boolean.TRUE));
|
||||
} else {
|
||||
throw new RuntimeException("Spring MVC can't support binding Collection on method "
|
||||
+ javaMethod.getName() + ",Check it in " + javaMethod.getDeclaringClass().getCanonicalName());
|
||||
+ javaMethod.getName() + ",Check it in " + javaMethod.getDeclaringClass()
|
||||
.getCanonicalName());
|
||||
}
|
||||
}
|
||||
} else if (JavaClassValidateUtil.isPrimitive(fullTypeName)) {
|
||||
ApiParam param = ApiParam.of().setField(paramName)
|
||||
ApiParam param = ApiParam.of()
|
||||
.setField(paramName)
|
||||
.setType(DocClassUtil.processTypeNameForParams(simpleName))
|
||||
.setId(paramList.size() + 1)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam).setValue(mockValue)
|
||||
.setDesc(comment).setRequired(required).setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
.setQueryParam(queryParam)
|
||||
.setValue(mockValue)
|
||||
.setDesc(comment)
|
||||
.setRequired(required)
|
||||
.setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
paramList.add(param);
|
||||
if (requestBodyCounter > 0) {
|
||||
Map<String, Object> map = OpenApiSchemaUtil.primaryTypeSchema(simpleName);
|
||||
|
@ -737,11 +909,15 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
+ javaMethod.getDeclaringClass().getCanonicalName() + "#" + javaMethod.getName());
|
||||
//如果typeName 是 map 但没加泛型 java.util.HashMap
|
||||
if (JavaClassValidateUtil.isMap(typeName)) {
|
||||
ApiParam apiParam = ApiParam.of().setField(paramName).setType("map")
|
||||
ApiParam apiParam = ApiParam.of()
|
||||
.setField(paramName)
|
||||
.setType("map")
|
||||
.setId(paramList.size() + 1)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
.setDesc(comment).setRequired(required).setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
.setDesc(comment)
|
||||
.setRequired(required)
|
||||
.setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
paramList.add(apiParam);
|
||||
if (requestBodyCounter > 0) {
|
||||
Map<String, Object> map = OpenApiSchemaUtil.mapTypeSchema("object");
|
||||
|
@ -751,11 +927,15 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
}
|
||||
String[] gicNameArr = DocClassUtil.getSimpleGicName(typeName);
|
||||
if (JavaClassValidateUtil.isPrimitive(gicNameArr[1])) {
|
||||
ApiParam apiParam = ApiParam.of().setField(paramName).setType("map")
|
||||
ApiParam apiParam = ApiParam.of()
|
||||
.setField(paramName)
|
||||
.setType("map")
|
||||
.setId(paramList.size() + 1)
|
||||
.setPathParam(isPathVariable)
|
||||
.setQueryParam(queryParam)
|
||||
.setDesc(comment).setRequired(required).setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
.setDesc(comment)
|
||||
.setRequired(required)
|
||||
.setVersion(DocGlobalConstants.DEFAULT_VERSION);
|
||||
paramList.add(apiParam);
|
||||
if (requestBodyCounter > 0) {
|
||||
Map<String, Object> map = OpenApiSchemaUtil.mapTypeSchema(gicNameArr[1]);
|
||||
|
@ -791,11 +971,17 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
List<ApiParam> queryParams = new ArrayList<>();
|
||||
List<ApiParam> bodyParams = new ArrayList<>();
|
||||
for (ApiParam param : paramList) {
|
||||
param.setValue(StringUtil.removeQuotes(param.getValue()));
|
||||
param.setValue(StringUtil.removeDoubleQuotes(param.getValue()));
|
||||
if (param.isPathParam()) {
|
||||
if (pathReqParamMap.containsKey(param.getField())) {
|
||||
param.setConfigParam(true).setValue(pathReqParamMap.get(param.getField()).getValue());
|
||||
}
|
||||
param.setId(pathParams.size() + 1);
|
||||
pathParams.add(param);
|
||||
} else if (param.isQueryParam() || requestBodyCounter < 1) {
|
||||
if (queryReqParamMap.containsKey(param.getField())) {
|
||||
param.setConfigParam(true).setValue(queryReqParamMap.get(param.getField()).getValue());
|
||||
}
|
||||
param.setId(queryParams.size() + 1);
|
||||
queryParams.add(param);
|
||||
} else {
|
||||
|
@ -803,6 +989,27 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
bodyParams.add(param);
|
||||
}
|
||||
}
|
||||
|
||||
final Set<String> queryParamSet = queryParams.stream().map(ApiParam::getField).collect(Collectors.toSet());
|
||||
for (ApiReqParam value : queryReqParamMap.values()) {
|
||||
if (queryParamSet.contains(value.getName())) {
|
||||
continue;
|
||||
}
|
||||
final ApiParam apiParam = ApiReqParam.convertToApiParam(value)
|
||||
.setQueryParam(true).setId(queryParams.size());
|
||||
queryParams.add(apiParam);
|
||||
}
|
||||
|
||||
final Set<String> pathParamSet = pathParams.stream().map(ApiParam::getField).collect(Collectors.toSet());
|
||||
for (ApiReqParam value : pathReqParamMap.values()) {
|
||||
if (pathParamSet.contains(value.getName())) {
|
||||
continue;
|
||||
}
|
||||
final ApiParam apiParam = ApiReqParam.convertToApiParam(value)
|
||||
.setPathParam(true).setId(pathParams.size());
|
||||
pathParams.add(apiParam);
|
||||
}
|
||||
|
||||
ApiMethodReqParam apiMethodReqParam = ApiMethodReqParam.builder()
|
||||
.setRequestParams(bodyParams)
|
||||
.setPathParams(pathParams)
|
||||
|
@ -823,9 +1030,14 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
}
|
||||
|
||||
private boolean checkController(JavaClass cls) {
|
||||
if (cls.isAnnotation() || cls.isEnum()) {
|
||||
return false;
|
||||
}
|
||||
JavaClass superClass = cls.getSuperJavaClass();
|
||||
List<JavaAnnotation> classAnnotations = new ArrayList<>();
|
||||
classAnnotations.addAll(superClass.getAnnotations());
|
||||
if (Objects.nonNull(superClass)) {
|
||||
classAnnotations.addAll(superClass.getAnnotations());
|
||||
}
|
||||
classAnnotations.addAll(cls.getAnnotations());
|
||||
for (JavaAnnotation annotation : classAnnotations) {
|
||||
String name = annotation.getType().getValue();
|
||||
|
@ -928,9 +1140,61 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
|
|||
return annotationsList;
|
||||
}
|
||||
JavaClass superJavaClass = cls.getSuperJavaClass();
|
||||
if (!"Object".equals(superJavaClass.getSimpleName())) {
|
||||
if (Objects.nonNull(superJavaClass) && !"Object".equals(superJavaClass.getSimpleName())) {
|
||||
annotationsList.addAll(getAnnotations(superJavaClass));
|
||||
}
|
||||
return annotationsList;
|
||||
}
|
||||
|
||||
private static void setTornaArrayTags(List<JavaParameter> javaParameters, ApiMethodDoc apiMethodDoc, JavaClass returnClass) {
|
||||
|
||||
apiMethodDoc.setIsResponseArray(0);
|
||||
apiMethodDoc.setIsRequestArray(0);
|
||||
//response tags
|
||||
if (JavaClassValidateUtil.isCollection(returnClass.getFullyQualifiedName()) ||
|
||||
JavaClassValidateUtil.isArray(returnClass.getFullyQualifiedName())) {
|
||||
apiMethodDoc.setIsResponseArray(1);
|
||||
String gicType;
|
||||
String simpleGicType;
|
||||
String typeName = returnClass.getGenericFullyQualifiedName();
|
||||
gicType = getType(typeName);
|
||||
simpleGicType = gicType.substring(gicType.lastIndexOf(".") + 1).toLowerCase();
|
||||
apiMethodDoc.setResponseArrayType(JavaClassValidateUtil.isPrimitive(gicType) ? simpleGicType : OBJECT);
|
||||
}
|
||||
//request tags
|
||||
if (CollectionUtil.isNotEmpty(javaParameters)) {
|
||||
for (JavaParameter parameter : javaParameters) {
|
||||
String gicType;
|
||||
String simpleGicType;
|
||||
String typeName = parameter.getType().getGenericFullyQualifiedName();
|
||||
String name = parameter.getType().getFullyQualifiedName();
|
||||
gicType = getType(typeName);
|
||||
simpleGicType = gicType.substring(gicType.lastIndexOf(".") + 1).toLowerCase();
|
||||
// is array
|
||||
if (JavaClassValidateUtil.isCollection(name) || JavaClassValidateUtil.isArray(name)) {
|
||||
apiMethodDoc.setIsRequestArray(1);
|
||||
if (JavaClassValidateUtil.isPrimitive(gicType)) {
|
||||
apiMethodDoc.setRequestArrayType(simpleGicType);
|
||||
} else {
|
||||
apiMethodDoc.setRequestArrayType(OBJECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getType(String typeName) {
|
||||
String gicType;
|
||||
//get generic type
|
||||
if (typeName.contains("<")) {
|
||||
gicType = typeName.substring(typeName.indexOf("<") + 1, typeName.lastIndexOf(">"));
|
||||
} else {
|
||||
gicType = typeName;
|
||||
}
|
||||
if (gicType.contains("[")) {
|
||||
gicType = gicType.substring(0, gicType.indexOf("["));
|
||||
}
|
||||
return gicType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class ApiParamTreeUtil {
|
|||
}
|
||||
for (ApiParam apiParam : params) {
|
||||
// remove pre of field
|
||||
apiParam.setChildren(getChild(apiParam.getId(), apiParamList));
|
||||
apiParam.setChildren(getChild(apiParam.getId(), apiParamList,0));
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
@ -59,17 +59,22 @@ public class ApiParamTreeUtil {
|
|||
*
|
||||
* @param id param id
|
||||
* @param apiParamList List of ApiParam
|
||||
* @param counter invoked counter
|
||||
* @return List of ApiParam
|
||||
*/
|
||||
private static List<ApiParam> getChild(int id, List<ApiParam> apiParamList) {
|
||||
private static List<ApiParam> getChild(int id, List<ApiParam> apiParamList, int counter) {
|
||||
List<ApiParam> childList = new ArrayList<>();
|
||||
if (counter > 7) {
|
||||
return childList;
|
||||
}
|
||||
for (ApiParam param : apiParamList) {
|
||||
if (param.getPid() == id) {
|
||||
childList.add(param);
|
||||
}
|
||||
}
|
||||
counter++;
|
||||
for (ApiParam param : childList) {
|
||||
param.setChildren(getChild(param.getId(), apiParamList));
|
||||
param.setChildren(getChild(param.getId(), apiParamList, counter));
|
||||
}
|
||||
if (childList.size() == 0) {
|
||||
return new ArrayList<>(0);
|
||||
|
|
|
@ -25,7 +25,7 @@ package com.power.doc.utils;
|
|||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.constants.DocGlobalConstants;
|
||||
import com.power.doc.model.ApiReqHeader;
|
||||
import com.power.doc.model.ApiReqParam;
|
||||
import com.power.doc.model.request.CurlRequest;
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,7 @@ public class CurlUtil {
|
|||
sb.append(" 'Content-Type: ").append(request.getContentType()).append("'");
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(request.getReqHeaders())) {
|
||||
for (ApiReqHeader reqHeader : request.getReqHeaders()) {
|
||||
for (ApiReqParam reqHeader : request.getReqHeaders()) {
|
||||
sb.append(" -H");
|
||||
if (StringUtil.isEmpty(reqHeader.getValue())) {
|
||||
sb.append(" '" + reqHeader.getName() + "'");
|
||||
|
|
|
@ -188,6 +188,8 @@ public class DocClassUtil {
|
|||
case "zoneddatetime":
|
||||
case "java.time.zoneddatetime":
|
||||
case "java.time.ZonedDateTime":
|
||||
case "java.lang.Character":
|
||||
case "character":
|
||||
return "string";
|
||||
case "java.util.List":
|
||||
case "list":
|
||||
|
@ -255,7 +257,7 @@ public class DocClassUtil {
|
|||
public static String rewriteRequestParam(String typeName) {
|
||||
switch (typeName) {
|
||||
case "org.springframework.data.domain.Pageable":
|
||||
return "org.springframework.data.domain.PageRequest";
|
||||
return "com.power.doc.model.framework.PageableAsQueryParam";
|
||||
default:
|
||||
return typeName;
|
||||
}
|
||||
|
|
|
@ -22,12 +22,15 @@
|
|||
*/
|
||||
package com.power.doc.utils;
|
||||
|
||||
import com.power.common.util.PathUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PathUtil {
|
||||
public class DocPathUtil {
|
||||
|
||||
/**
|
||||
* Get the java class name
|
||||
|
@ -61,4 +64,24 @@ public class PathUtil {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine a match for the given lookup path.
|
||||
*
|
||||
* @param lookupPath the request path
|
||||
* @param includePatterns the path patterns to map (empty for matching to all paths)
|
||||
* @param excludePatterns the path patterns to exclude (empty for no specific excludes)
|
||||
* @return {@code true} if matched the request path
|
||||
*/
|
||||
public static boolean matches(String lookupPath, String includePatterns, String excludePatterns) {
|
||||
List<String> includePatternList = null;
|
||||
if (StringUtil.isNotEmpty(includePatterns)) {
|
||||
includePatternList = Arrays.asList(includePatterns.split(",", 0));
|
||||
}
|
||||
List<String> excludePatternList = null;
|
||||
if (StringUtil.isNotEmpty(excludePatterns)) {
|
||||
excludePatternList = Arrays.asList(excludePatterns.split(",", 0));
|
||||
}
|
||||
return PathUtil.matches(lookupPath,includePatternList,excludePatternList);
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ import org.apache.commons.codec.digest.DigestUtils;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -44,7 +45,7 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public class DocUtil {
|
||||
|
||||
private static Faker faker = new Faker(new Locale(System.getProperty(DocGlobalConstants.DOC_LANGUAGE)));
|
||||
private static Faker faker = new Faker(new Locale("en-US"));
|
||||
//private static Faker faker = new Faker(new Locale("smart-doc_language"));
|
||||
private static Faker enFaker = new Faker(new Locale("en-US"));
|
||||
|
||||
|
@ -54,7 +55,7 @@ public class DocUtil {
|
|||
|
||||
static {
|
||||
fieldValue.put("uuid-string", UUID.randomUUID().toString());
|
||||
fieldValue.put("uid", UUID.randomUUID().toString());
|
||||
fieldValue.put("traceid-string",UUID.randomUUID().toString());
|
||||
fieldValue.put("id-string", String.valueOf(RandomUtil.randomInt(1, 200)));
|
||||
fieldValue.put("nickname-string", enFaker.name().username());
|
||||
fieldValue.put("hostname-string", faker.internet().ipV4Address());
|
||||
|
@ -62,6 +63,8 @@ public class DocUtil {
|
|||
fieldValue.put("author-string", faker.book().author());
|
||||
fieldValue.put("url-string", faker.internet().url());
|
||||
fieldValue.put("username-string", faker.name().username());
|
||||
fieldValue.put("index-int","1");
|
||||
fieldValue.put("index-integer","1");
|
||||
fieldValue.put("page-int", "1");
|
||||
fieldValue.put("page-integer", "1");
|
||||
fieldValue.put("age-int", String.valueOf(RandomUtil.randomInt(0, 70)));
|
||||
|
@ -186,7 +189,7 @@ public class DocUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* 是否是合法的java类名称
|
||||
* valid java class name
|
||||
*
|
||||
* @param className class nem
|
||||
* @return boolean
|
||||
|
@ -227,11 +230,12 @@ public class DocUtil {
|
|||
}
|
||||
String[] patterns = packageFilters.split(",");
|
||||
for (String str : patterns) {
|
||||
String name = str;
|
||||
if (str.endsWith("*")) {
|
||||
name = str.substring(0, str.length() - 2);
|
||||
}
|
||||
if (controllerName.contains(name)) {
|
||||
if (str.contains("*")) {
|
||||
Pattern pattern = Pattern.compile(str);
|
||||
if (pattern.matcher(controllerName).matches()) {
|
||||
return true;
|
||||
}
|
||||
} else if (controllerName.startsWith(str)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -290,6 +294,28 @@ public class DocUtil {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* // /detail/{id:[a-zA-Z0-9]{3}}/{name:[a-zA-Z0-9]{3}}
|
||||
* remove pattern
|
||||
*
|
||||
* @param str path
|
||||
* @return String
|
||||
*/
|
||||
public static String formatPathUrl(String str) {
|
||||
if (!str.contains(":")) {
|
||||
return str;
|
||||
}
|
||||
String[] strArr = str.split("/");
|
||||
for (int i = 0; i < strArr.length; i++) {
|
||||
String pathParam = strArr[i];
|
||||
if (pathParam.contains(":")) {
|
||||
strArr[i] = pathParam.substring(0, pathParam.indexOf(":")) + "}";
|
||||
}
|
||||
}
|
||||
str = StringUtils.join(Arrays.asList(strArr), '/');
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle spring mvc method
|
||||
*
|
||||
|
@ -326,6 +352,37 @@ public class DocUtil {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Split url
|
||||
*
|
||||
* @param url URL to be divided
|
||||
* @return list of url
|
||||
*/
|
||||
public static List<String> split(String url) {
|
||||
char[] chars = url.toCharArray();
|
||||
List<String> result = new ArrayList<>();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Stack<Character> stack = new Stack<>();
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
char s = chars[i];
|
||||
if ('{' == s) {
|
||||
stack.push(s);
|
||||
}
|
||||
if ('}' == s) {
|
||||
stack.pop();
|
||||
}
|
||||
if (',' == s && stack.isEmpty()) {
|
||||
result.add(sb.toString());
|
||||
sb.delete(0, sb.length());
|
||||
continue;
|
||||
}
|
||||
sb.append(s);
|
||||
}
|
||||
result.add(sb.toString());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* obtain params comments
|
||||
*
|
||||
|
@ -341,18 +398,16 @@ public class DocUtil {
|
|||
String value = docletTag.getValue();
|
||||
if (StringUtil.isEmpty(value) && StringUtil.isNotEmpty(className)) {
|
||||
throw new RuntimeException("ERROR: #" + javaMethod.getName()
|
||||
+ "() - bad @" + tagName + " javadoc from " + javaMethod.getDeclaringClass().getCanonicalName() + ", must be add comment if you use it.");
|
||||
+ "() - bad @" + tagName + " javadoc from " + javaMethod.getDeclaringClass()
|
||||
.getCanonicalName() + ", must be add comment if you use it.");
|
||||
}
|
||||
String pName;
|
||||
String pValue;
|
||||
int idx = value.indexOf("\n");
|
||||
String pName = value;
|
||||
String pValue = DocGlobalConstants.NO_COMMENTS_FOUND;
|
||||
int idx = value.indexOf(" ");
|
||||
//existed \n
|
||||
if (idx > -1) {
|
||||
pName = value.substring(0, idx);
|
||||
pValue = value.substring(idx + 1);
|
||||
} else {
|
||||
pName = (value.contains(" ")) ? value.substring(0, value.indexOf(" ")) : value;
|
||||
pValue = value.contains(" ") ? value.substring(value.indexOf(' ') + 1) : DocGlobalConstants.NO_COMMENTS_FOUND;
|
||||
}
|
||||
paramTagMap.put(pName, pValue);
|
||||
}
|
||||
|
@ -476,6 +531,8 @@ public class DocUtil {
|
|||
case "BigDecimal":
|
||||
case "BigInteger":
|
||||
case "Byte":
|
||||
case "Character":
|
||||
case "character":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -525,14 +582,53 @@ public class DocUtil {
|
|||
* @return the url
|
||||
*/
|
||||
public static String getRequestMappingUrl(JavaAnnotation annotation) {
|
||||
Object url = annotation.getNamedParameter(DocAnnotationConstants.VALUE_PROP);
|
||||
return getPathUrl(annotation, DocAnnotationConstants.VALUE_PROP, DocAnnotationConstants.PATH_PROP);
|
||||
}
|
||||
|
||||
if (null != url) {
|
||||
return url.toString();
|
||||
} else {
|
||||
url = annotation.getNamedParameter(DocAnnotationConstants.PATH_PROP);
|
||||
return null == url ? StringUtil.EMPTY : url.toString();
|
||||
/**
|
||||
* Get mapping url from Annotation
|
||||
*
|
||||
* @param annotation JavaAnnotation
|
||||
* @param props annotation properties
|
||||
* @return the path
|
||||
*/
|
||||
public static String getPathUrl(JavaAnnotation annotation, String... props) {
|
||||
for (String prop : props) {
|
||||
Object url = annotation.getNamedParameter(prop);
|
||||
if (Objects.nonNull(url)) {
|
||||
return url.toString();
|
||||
}
|
||||
}
|
||||
return StringUtil.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle spring mvc RequestHeader value
|
||||
*
|
||||
* @param annotation JavaAnnotation
|
||||
* @return String
|
||||
*/
|
||||
public static String handleRequestHeaderValue(JavaAnnotation annotation) {
|
||||
String header = getRequestHeaderValue(annotation);
|
||||
if (StringUtil.isEmpty(header)) {
|
||||
return header;
|
||||
}
|
||||
return StringUtil.trimBlank(header);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain constant from @RequestHeader annotation
|
||||
*
|
||||
* @param annotation RequestMapping GetMapping PostMapping etc.
|
||||
* @return The constant value
|
||||
*/
|
||||
public static String getRequestHeaderValue(JavaAnnotation annotation) {
|
||||
Object constantValue = annotation.getNamedParameter(DocAnnotationConstants.VALUE_PROP);
|
||||
if (null != constantValue) {
|
||||
return constantValue.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static List<ApiErrorCode> errorCodeDictToList(ApiConfig config) {
|
||||
|
@ -609,4 +705,32 @@ public class DocUtil {
|
|||
return apiDocDictList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format field Type
|
||||
*
|
||||
* @param genericMap genericMap
|
||||
* @param globGicName globGicName array
|
||||
* @param fieldGicName fieldGicName
|
||||
* @return string
|
||||
*/
|
||||
public static String formatFieldTypeGicName(Map<String, String> genericMap, String[] globGicName, String fieldGicName) {
|
||||
String[] gNameArr = DocClassUtil.getSimpleGicName(fieldGicName);
|
||||
if (gNameArr.length > 0) {
|
||||
String gName = gNameArr[0];
|
||||
if (gName.length() == 1) {
|
||||
String gicName = "";
|
||||
if (Objects.nonNull(genericMap.get(gName))) {
|
||||
gicName = genericMap.get(gName);
|
||||
}
|
||||
if (globGicName.length > 0) {
|
||||
gicName = globGicName[0];
|
||||
}
|
||||
if (StringUtil.isNotEmpty(gicName)) {
|
||||
fieldGicName = fieldGicName.replace(gName, gicName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fieldGicName;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ package com.power.doc.utils;
|
|||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.constants.DocAnnotationConstants;
|
||||
import com.power.doc.constants.DocGlobalConstants;
|
||||
import com.power.doc.constants.DocValidatorAnnotationEnum;
|
||||
import com.power.doc.constants.ValidatorAnnotations;
|
||||
import com.power.doc.model.DocJavaField;
|
||||
|
@ -89,12 +90,15 @@ public class JavaClassUtil {
|
|||
String comment = javaMethod.getComment();
|
||||
JavaField javaField = new DefaultJavaField(javaMethod.getReturns(), methodName);
|
||||
DocJavaField docJavaField = DocJavaField.builder()
|
||||
.setFieldName(methodName)
|
||||
.setJavaField(javaField)
|
||||
.setComment(comment)
|
||||
.setDocletTags(javaMethod.getTags())
|
||||
.setAnnotations(javaMethod.getAnnotations())
|
||||
.setFullyQualifiedName(javaField.getType().getFullyQualifiedName())
|
||||
.setGenericCanonicalName(javaField.getType().getGenericCanonicalName());
|
||||
.setFullyQualifiedName(javaField.getType()
|
||||
.getFullyQualifiedName())
|
||||
.setGenericCanonicalName(javaField.getType()
|
||||
.getGenericCanonicalName());
|
||||
addedFields.put(methodName, docJavaField);
|
||||
}
|
||||
}
|
||||
|
@ -129,15 +133,26 @@ public class JavaClassUtil {
|
|||
DocJavaField docJavaField = addedFields.get(methodName);
|
||||
docJavaField.setAnnotations(method.getAnnotations());
|
||||
docJavaField.setComment(comment);
|
||||
docJavaField.setFieldName(methodName);
|
||||
addedFields.put(methodName, docJavaField);
|
||||
}
|
||||
}
|
||||
for (JavaField javaField : cls1.getFields()) {
|
||||
String fieldName = javaField.getName();
|
||||
String subTypeName = javaField.getType().getFullyQualifiedName();
|
||||
|
||||
if (javaField.isStatic() || "this$0".equals(fieldName) ||
|
||||
JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) {
|
||||
continue;
|
||||
}
|
||||
if (fieldName.startsWith("is") && ("boolean".equals(subTypeName))) {
|
||||
fieldName = StringUtil.firstToLowerCase(fieldName.substring(2));
|
||||
}
|
||||
|
||||
DocJavaField docJavaField = DocJavaField.builder();
|
||||
boolean typeChecked = false;
|
||||
String gicName = javaField.getType().getGenericCanonicalName();
|
||||
String subTypeName = javaField.getType().getFullyQualifiedName();
|
||||
|
||||
String actualType = null;
|
||||
if (JavaClassValidateUtil.isCollection(subTypeName) &&
|
||||
!JavaClassValidateUtil.isCollection(gicName)) {
|
||||
|
@ -160,7 +175,7 @@ public class JavaClassUtil {
|
|||
for (Map.Entry<String, JavaType> entry : actualJavaTypes.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
JavaType value = entry.getValue();
|
||||
if (gicName.contains(key)) {
|
||||
if (gicName.equals(key)) {
|
||||
subTypeName = subTypeName.replaceAll(key, value.getFullyQualifiedName());
|
||||
gicName = gicName.replaceAll(key, value.getGenericCanonicalName());
|
||||
actualType = value.getFullyQualifiedName();
|
||||
|
@ -169,15 +184,18 @@ public class JavaClassUtil {
|
|||
docJavaField.setComment(javaField.getComment())
|
||||
.setJavaField(javaField).setFullyQualifiedName(subTypeName)
|
||||
.setGenericCanonicalName(gicName).setActualJavaType(actualType)
|
||||
.setAnnotations(javaField.getAnnotations());
|
||||
.setAnnotations(javaField.getAnnotations())
|
||||
.setFieldName(fieldName);
|
||||
if (addedFields.containsKey(fieldName)) {
|
||||
addedFields.put(fieldName, docJavaField);
|
||||
continue;
|
||||
}
|
||||
addedFields.put(fieldName, docJavaField);
|
||||
}
|
||||
List<DocJavaField> parentFieldList = addedFields.values().stream()
|
||||
.filter(v -> Objects.nonNull(v)).collect(Collectors.toList());
|
||||
List<DocJavaField> parentFieldList = addedFields.values()
|
||||
.stream()
|
||||
.filter(v -> Objects.nonNull(v))
|
||||
.collect(Collectors.toList());
|
||||
fieldList.addAll(parentFieldList);
|
||||
}
|
||||
return fieldList;
|
||||
|
@ -442,15 +460,15 @@ public class JavaClassUtil {
|
|||
if (CollectionUtil.isEmpty(annotationValueList)) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < annotationValueList.size(); i++) {
|
||||
TypeRef annotationValue = (TypeRef) annotationValueList.get(i);
|
||||
DefaultJavaParameterizedType annotationValueType = (DefaultJavaParameterizedType) annotationValue.getType();
|
||||
for (AnnotationValue annotationValue : annotationValueList) {
|
||||
TypeRef typeRef = (TypeRef) annotationValue;
|
||||
DefaultJavaParameterizedType annotationValueType = (DefaultJavaParameterizedType) typeRef.getType();
|
||||
javaClassList.add(annotationValueType.getGenericCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
private static List<AnnotationValue> getAnnotationValues(List<String> validates, JavaAnnotation javaAnnotation) {
|
||||
List<AnnotationValue> annotationValueList = null;
|
||||
List<AnnotationValue> annotationValueList = new ArrayList<>();
|
||||
String simpleName = javaAnnotation.getType().getValue();
|
||||
if (simpleName.equalsIgnoreCase(ValidatorAnnotations.VALIDATED)) {
|
||||
if (Objects.nonNull(javaAnnotation.getProperty(DocAnnotationConstants.VALUE_PROP))) {
|
||||
|
@ -459,7 +477,6 @@ public class JavaClassUtil {
|
|||
annotationValueList = ((AnnotationValueList) v).getValueList();
|
||||
}
|
||||
if (v instanceof TypeRef) {
|
||||
annotationValueList = new ArrayList<>();
|
||||
annotationValueList.add(v);
|
||||
}
|
||||
}
|
||||
|
@ -470,7 +487,6 @@ public class JavaClassUtil {
|
|||
annotationValueList = ((AnnotationValueList) v).getValueList();
|
||||
}
|
||||
if (v instanceof TypeRef) {
|
||||
annotationValueList = new ArrayList<>();
|
||||
annotationValueList.add(v);
|
||||
}
|
||||
}
|
||||
|
@ -513,4 +529,40 @@ public class JavaClassUtil {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Map<String, String> getClassJsonIgnoreFields(JavaClass cls) {
|
||||
if (cls == null) return Collections.EMPTY_MAP;
|
||||
List<JavaAnnotation> classAnnotation = cls.getAnnotations();
|
||||
Map<String, String> ignoreFields = new HashMap<>();
|
||||
for (JavaAnnotation annotation : classAnnotation) {
|
||||
String simpleAnnotationName = annotation.getType().getValue();
|
||||
if (DocAnnotationConstants.SHORT_JSON_IGNORE_PROPERTIES.equalsIgnoreCase(simpleAnnotationName)) {
|
||||
return JavaClassUtil.getJsonIgnoresProp(annotation, DocAnnotationConstants.VALUE_PROP);
|
||||
}
|
||||
if (DocAnnotationConstants.SHORT_JSON_TYPE.equals(simpleAnnotationName)) {
|
||||
return JavaClassUtil.getJsonIgnoresProp(annotation, DocAnnotationConstants.IGNORE_PROP);
|
||||
}
|
||||
}
|
||||
return ignoreFields;
|
||||
}
|
||||
|
||||
public static Map<String, String> getJsonIgnoresProp(JavaAnnotation annotation, String propName) {
|
||||
Map<String, String> ignoreFields = new HashMap<>();
|
||||
Object ignoresObject = annotation.getNamedParameter(propName);
|
||||
if (Objects.isNull(ignoresObject)) {
|
||||
return ignoreFields;
|
||||
}
|
||||
if (ignoresObject instanceof String) {
|
||||
String prop = StringUtil.removeQuotes(ignoresObject.toString());
|
||||
ignoreFields.put(prop, null);
|
||||
return ignoreFields;
|
||||
}
|
||||
List<String> ignorePropList = (LinkedList) ignoresObject;
|
||||
for (String str : ignorePropList) {
|
||||
String prop = StringUtil.removeQuotes(str);
|
||||
ignoreFields.put(prop, null);
|
||||
}
|
||||
return ignoreFields;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ public class JavaClassValidateUtil {
|
|||
case "boolean":
|
||||
case "byte":
|
||||
case "uuid":
|
||||
case "character":
|
||||
case "java.sql.timestamp":
|
||||
case "java.util.date":
|
||||
case "java.time.localdatetime":
|
||||
|
@ -101,6 +102,7 @@ public class JavaClassValidateUtil {
|
|||
case "java.util.uuid":
|
||||
case "java.util.UUID":
|
||||
case "java.io.serializable":
|
||||
case "java.lang.character":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -213,6 +215,22 @@ public class JavaClassValidateUtil {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download
|
||||
* @param typeName return type name
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isFileDownloadResource(String typeName){
|
||||
switch (typeName) {
|
||||
case "org.springframework.core.io.Resource":
|
||||
case "org.springframework.core.io.InputStreamSource":
|
||||
case "org.springframework.core.io.ByteArrayResource":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ignore param of spring mvc
|
||||
*
|
||||
|
@ -228,14 +246,19 @@ public class JavaClassValidateUtil {
|
|||
case "org.springframework.ui.Model":
|
||||
case "org.springframework.ui.ModelMap":
|
||||
case "org.springframework.web.servlet.ModelAndView":
|
||||
case "org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap":
|
||||
case "org.springframework.validation.BindingResult":
|
||||
case "javax.servlet.http.HttpServletRequest":
|
||||
case "org.springframework.web.context.request.WebRequest":
|
||||
case "javax.servlet.http.HttpServlet":
|
||||
case "javax.servlet.http.HttpSession":
|
||||
case "javax.servlet.http.HttpServletResponse":
|
||||
case "org.springframework.web.context.request.WebRequest":
|
||||
case "org.springframework.web.reactive.function.server.ServerRequest":
|
||||
case "org.springframework.web.multipart.MultipartHttpServletRequest":
|
||||
case "org.springframework.http.HttpHeaders":
|
||||
case "org.springframework.core.io.Resource":
|
||||
case "org.springframework.core.io.InputStreamSource":
|
||||
case "org.springframework.core.io.ByteArrayResource":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* smart-doc https://github.com/shalousun/smart-doc
|
||||
*
|
||||
* Copyright (C) 2018-2021 smart-doc
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.power.doc.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* @author yu 2021/6/26.
|
||||
*/
|
||||
public class JsonUtil {
|
||||
|
||||
/**
|
||||
* Convert a JSON string to pretty print
|
||||
*
|
||||
* @param jsonString json string
|
||||
* @return Format json string
|
||||
*/
|
||||
public static String toPrettyFormat(String jsonString) {
|
||||
try {
|
||||
JsonElement jsonElement = JsonParser.parseString(jsonString);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||
String prettyJson = gson.toJson(jsonElement);
|
||||
return prettyJson;
|
||||
} catch (Exception e) {
|
||||
return jsonString;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSON to String and pretty print
|
||||
*
|
||||
* @param src Json
|
||||
* @return Format json string
|
||||
*/
|
||||
public static String toPrettyJson(Object src) {
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
String prettyJson = gson.toJson(src);
|
||||
return prettyJson;
|
||||
}
|
||||
}
|
|
@ -2,35 +2,30 @@ package com.power.doc.utils;
|
|||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.internal.$Gson$Types;
|
||||
import com.power.common.model.EnumDictionary;
|
||||
import com.power.common.util.CollectionUtil;
|
||||
import com.power.common.util.StringUtil;
|
||||
import com.power.doc.builder.BaseDocBuilderTemplate;
|
||||
import com.power.doc.constants.DocGlobalConstants;
|
||||
import com.power.doc.constants.TornaConstants;
|
||||
import com.power.doc.model.*;
|
||||
import com.power.doc.model.rpc.RpcApiDependency;
|
||||
import com.power.doc.model.torna.*;
|
||||
import okhttp3.internal.http2.ErrorCode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.power.doc.constants.TornaConstants.PUSH;
|
||||
|
||||
/**
|
||||
* @author xingzi 2021/4/28 16:15
|
||||
**/
|
||||
public class TornaUtil {
|
||||
|
||||
public static boolean setDebugEnv(ApiConfig apiConfig, TornaApi tornaApi) {
|
||||
//是否设置测试环境
|
||||
boolean hasDebugEnv = StringUtils.isNotBlank(apiConfig.getDebugEnvName())
|
||||
&&
|
||||
StringUtils.isNotBlank(apiConfig.getDebugEnvUrl());
|
||||
//设置测试环境
|
||||
//Set up the test environment
|
||||
List<DebugEnv> debugEnvs = new ArrayList<>();
|
||||
if (hasDebugEnv) {
|
||||
DebugEnv debugEnv = new DebugEnv();
|
||||
|
@ -42,9 +37,9 @@ public class TornaUtil {
|
|||
return hasDebugEnv;
|
||||
}
|
||||
|
||||
public static void printDebugInfo(ApiConfig apiConfig, String responseMsg, Map<String, String> requestJson,String category) {
|
||||
public static void printDebugInfo(ApiConfig apiConfig, String responseMsg, Map<String, String> requestJson, String category) {
|
||||
if (apiConfig.isTornaDebug()) {
|
||||
String sb = "配置信息列表: \n" +
|
||||
String sb = "Configuration information : \n" +
|
||||
"OpenUrl: " +
|
||||
apiConfig.getOpenUrl() +
|
||||
"\n" +
|
||||
|
@ -78,10 +73,10 @@ public class TornaUtil {
|
|||
* @return List of Api
|
||||
*/
|
||||
public static List<Apis> buildApis(List<ApiMethodDoc> apiMethodDocs, boolean hasDebugEnv) {
|
||||
//参数列表
|
||||
//Parameter list
|
||||
List<Apis> apis = new ArrayList<>();
|
||||
Apis methodApi;
|
||||
//遍历分类接口
|
||||
//Iterative classification interface
|
||||
for (ApiMethodDoc apiMethodDoc : apiMethodDocs) {
|
||||
methodApi = new Apis();
|
||||
methodApi.setIsFolder(TornaConstants.NO);
|
||||
|
@ -92,15 +87,24 @@ public class TornaUtil {
|
|||
methodApi.setDescription(apiMethodDoc.getDetail());
|
||||
methodApi.setIsShow(TornaConstants.YES);
|
||||
methodApi.setAuthor(apiMethodDoc.getAuthor());
|
||||
methodApi.setOrderIndex(apiMethodDoc.getOrder());
|
||||
|
||||
methodApi.setHeaderParams(buildHerder(apiMethodDoc.getRequestHeaders()));
|
||||
methodApi.setResponseParams(buildParams(apiMethodDoc.getResponseParams()));
|
||||
methodApi.setIsRequestArray(apiMethodDoc.getIsRequestArray());
|
||||
methodApi.setIsResponseArray(apiMethodDoc.getIsResponseArray());
|
||||
methodApi.setRequestArrayType(apiMethodDoc.getRequestArrayType());
|
||||
methodApi.setResponseArrayType(apiMethodDoc.getResponseArrayType());
|
||||
//Path
|
||||
if (CollectionUtil.isNotEmpty(apiMethodDoc.getPathParams())) {
|
||||
methodApi.setPathParams(buildParams(apiMethodDoc.getPathParams()));
|
||||
}
|
||||
//formData
|
||||
if (CollectionUtil.isNotEmpty(apiMethodDoc.getQueryParams())) {
|
||||
|
||||
if (CollectionUtil.isNotEmpty(apiMethodDoc.getQueryParams())
|
||||
&& DocGlobalConstants.MULTIPART_TYPE.equals(apiMethodDoc.getContentType())) {
|
||||
// file upload
|
||||
methodApi.setRequestParams(buildParams(apiMethodDoc.getQueryParams()));
|
||||
} else if (CollectionUtil.isNotEmpty(apiMethodDoc.getQueryParams())) {
|
||||
methodApi.setQueryParams(buildParams(apiMethodDoc.getQueryParams()));
|
||||
}
|
||||
//Json
|
||||
|
@ -119,10 +123,10 @@ public class TornaUtil {
|
|||
* @return List of Api
|
||||
*/
|
||||
public static List<Apis> buildDubboApis(List<JavaMethodDoc> apiMethodDocs) {
|
||||
//参数列表
|
||||
//Parameter list
|
||||
List<Apis> apis = new ArrayList<>();
|
||||
Apis methodApi;
|
||||
//遍历分类接口
|
||||
//Iterative classification interface
|
||||
for (JavaMethodDoc apiMethodDoc : apiMethodDocs) {
|
||||
methodApi = new Apis();
|
||||
methodApi.setIsFolder(TornaConstants.NO);
|
||||
|
@ -132,6 +136,7 @@ public class TornaUtil {
|
|||
methodApi.setAuthor(apiMethodDoc.getAuthor());
|
||||
methodApi.setUrl(apiMethodDoc.getMethodDefinition());
|
||||
methodApi.setResponseParams(buildParams(apiMethodDoc.getResponseParams()));
|
||||
methodApi.setOrderIndex(apiMethodDoc.getOrder());
|
||||
//Json
|
||||
if (CollectionUtil.isNotEmpty(apiMethodDoc.getRequestParams())) {
|
||||
methodApi.setRequestParams(buildParams(apiMethodDoc.getRequestParams()));
|
||||
|
@ -144,19 +149,13 @@ public class TornaUtil {
|
|||
/**
|
||||
* build request header
|
||||
*
|
||||
* @param apiReqHeaders 请求头参数列表
|
||||
* @param apiReqParams Request header parameter list
|
||||
* @return List of HttpParam
|
||||
*/
|
||||
public static List<HttpParam> buildHerder(List<ApiReqHeader> apiReqHeaders) {
|
||||
/**
|
||||
* name": "token",
|
||||
* "required": "1",
|
||||
* "example": "iphone12",
|
||||
* "description": "商品名称描述"
|
||||
*/
|
||||
public static List<HttpParam> buildHerder(List<ApiReqParam> apiReqParams) {
|
||||
HttpParam httpParam;
|
||||
List<HttpParam> headers = new ArrayList<>();
|
||||
for (ApiReqHeader header : apiReqHeaders) {
|
||||
for (ApiReqParam header : apiReqParams) {
|
||||
httpParam = new HttpParam();
|
||||
httpParam.setName(header.getName());
|
||||
httpParam.setRequired(header.isRequired() ? TornaConstants.YES : TornaConstants.NO);
|
||||
|
@ -170,30 +169,12 @@ public class TornaUtil {
|
|||
/**
|
||||
* build request response params
|
||||
*
|
||||
* @param apiParams 参数列表
|
||||
* @param apiParams Param list
|
||||
* @return List of HttpParam
|
||||
*/
|
||||
public static List<HttpParam> buildParams(List<ApiParam> apiParams) {
|
||||
HttpParam httpParam;
|
||||
List<HttpParam> bodies = new ArrayList<>();
|
||||
/**
|
||||
* "name": "goodsName",
|
||||
* "type": "string",
|
||||
* "required": "1",
|
||||
* "maxLength": "128",
|
||||
* "example": "iphone12",
|
||||
* "description": "商品名称描述",
|
||||
* "parentId": "",
|
||||
* "enumInfo": {
|
||||
* "name": "支付枚举",
|
||||
* "description": "支付状态",
|
||||
* "items": [
|
||||
* {
|
||||
* "name": "WAIT_PAY",
|
||||
* "type": "string",
|
||||
* "value": "0",
|
||||
* "description": "未支付"
|
||||
*/
|
||||
for (ApiParam apiParam : apiParams) {
|
||||
httpParam = new HttpParam();
|
||||
httpParam.setName(apiParam.getField());
|
||||
|
@ -239,11 +220,12 @@ public class TornaUtil {
|
|||
|
||||
public static List<TornaDic> buildTornaDic(List<ApiDocDict> apiDocDicts) {
|
||||
List<TornaDic> dics = new ArrayList<>();
|
||||
TornaDic tornaDic = new TornaDic();
|
||||
TornaDic tornaDic;
|
||||
if (CollectionUtil.isNotEmpty(apiDocDicts)) {
|
||||
for (ApiDocDict doc : apiDocDicts) {
|
||||
tornaDic = new TornaDic();
|
||||
tornaDic.setName(doc.getTitle())
|
||||
// .setDescription(doc.getTitle())
|
||||
// .setDescription(doc.getTitle())
|
||||
.setItems(buildTornaDicItems(doc.getDataDictList()));
|
||||
dics.add(tornaDic);
|
||||
}
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
DELIMITER_STATEMENT_START=<%
|
||||
DELIMITER_STATEMENT_END=%>
|
||||
FN.htmlEscape = com.power.doc.function.HtmlEscape
|
||||
FN.removeLineBreaks = com.power.doc.function.RemoveLineBreaks
|
||||
FNP.strUtil = org.beetl.ext.fn.StringUtil
|
|
@ -17,26 +17,33 @@ for(revisionLog in revisionLogList){
|
|||
|
||||
|
||||
<%
|
||||
for(api in apiDocList){
|
||||
for(apiGroup in apiDocList){
|
||||
%>
|
||||
== ${api.desc}
|
||||
<%
|
||||
if(apiGroupLP.size > 1) {%>
|
||||
==${apiGroup.group}
|
||||
<%} %>
|
||||
<%
|
||||
for(api in apiGroup.childrenApiDocs){
|
||||
%>
|
||||
=== ${api.desc}
|
||||
<%
|
||||
for(doc in api.list){
|
||||
%>
|
||||
<%if(doc.deprecated){%>
|
||||
=== [line-through]#${doc.desc}#
|
||||
==== [line-through]#${doc.desc}#
|
||||
<%}else{%>
|
||||
=== ${doc.desc}
|
||||
==== ${doc.desc}
|
||||
<%}%>
|
||||
*URL:* ${doc.url}
|
||||
*URL:* `${doc.url}`
|
||||
|
||||
*Type:* ${doc.type}
|
||||
*Type:* `${doc.type}`
|
||||
|
||||
<%if(isNotEmpty(doc.author)){%>
|
||||
*Author:* ${doc.author}
|
||||
<%}%>
|
||||
|
||||
*Content-Type:* ${doc.contentType}
|
||||
*Content-Type:* `${doc.contentType}`
|
||||
|
||||
<%if(isNotEmpty(doc.headers)){%>
|
||||
*Request-headers:*
|
||||
|
@ -122,6 +129,7 @@ ${doc.responseUsage}
|
|||
----
|
||||
<%}%>
|
||||
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<%if(isNotEmpty(errorCodeList)){%>
|
||||
|
|
|
@ -14,7 +14,14 @@ ${revisionLog.version}|${revisionLog.revisionTime}|${revisionLog.status}|${revis
|
|||
|
||||
|
||||
<%
|
||||
for(api in apiDocList){
|
||||
for(apiGroup in apiDocList){
|
||||
%>
|
||||
<%
|
||||
if(apiGroupLP.size > 1) {%>
|
||||
# ${apiGroup.group}
|
||||
<%}%>
|
||||
<%
|
||||
for(api in apiGroup.childrenApiDocs){
|
||||
%>
|
||||
## ${api.desc}
|
||||
<%
|
||||
|
@ -106,6 +113,7 @@ ${doc.responseUsage}
|
|||
```
|
||||
<%}%>
|
||||
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<%if(isNotEmpty(errorCodeList)){%>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -28,8 +28,9 @@ for(doc in list){
|
|||
|====================
|
||||
|Header | Type|Description|Required|Since
|
||||
${doc.headers}
|
||||
<%}%>
|
||||
|====================
|
||||
<%}%>
|
||||
|
||||
|
||||
<%if(isNotEmpty(doc.pathParams)){%>
|
||||
*Path-parameters:*
|
||||
|
|
|
@ -4,4 +4,10 @@ ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:
|
|||
.admonitionblock>table td.icon img{max-width:initial}.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}.exampleblock>.content>:first-child{margin-top:0}.exampleblock>.content>:last-child{margin-bottom:0}.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}.sidebarblock>:first-child{margin-top:0}.sidebarblock>:last-child{margin-bottom:0}.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}.listingblock pre.highlightjs{padding:0}.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}.listingblock pre.prettyprint{border-width:0}.listingblock>.content{position:relative}.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}.listingblock:hover code[data-lang]:before{display:block}.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:0}table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}table.pyhltable td.code{padding-left:.75em;padding-right:0}pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}pre.pygments .lineno{display:inline-block;margin-right:.25em}table.pyhltable .linenodiv{background:none!important;padding-right:0!important}.quoteblock{margin:0 1em 1.25em 1.5em;display:table}.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}.quoteblock blockquote{margin:0;padding:0;border:0}.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}.quoteblock .quoteblock blockquote:before{display:none}.verseblock{margin:0 1em 1.25em 1em}.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
||||
.verseblock pre strong{font-weight:400}.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}.quoteblock .attribution br,.verseblock .attribution br{display:none}.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}.quoteblock.abstract{margin:0 0 1.25em 0;display:block}.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}table.tableblock{max-width:100%;border-collapse:separate}table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0}table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0}table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}table.frame-all{border-width:1px}table.frame-sides{border-width:0 1px}table.frame-topbot{border-width:1px 0}th.halign-left,td.halign-left{text-align:left}th.halign-right,td.halign-right{text-align:right}th.halign-center,td.halign-center{text-align:center}th.valign-top,td.valign-top{vertical-align:top}th.valign-bottom,td.valign-bottom{vertical-align:bottom}th.valign-middle,td.valign-middle{vertical-align:middle}table thead th,table tfoot th{font-weight:bold}tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}p.tableblock>code:only-child{background:0;padding:0}p.tableblock{font-size:1em}td>div.verse{white-space:pre}ol{margin-left:1.75em}ul li ol{margin-left:1.5em}dl dd{margin-left:1.125em}dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}ul.unstyled,ol.unstyled{margin-left:0}ul.checklist{margin-left:.625em}ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}ul.inline>li>*{display:block}.unstyled dl dt{font-weight:400;font-style:normal}ol.arabic{list-style-type:decimal}ol.decimal{list-style-type:decimal-leading-zero}ol.loweralpha{list-style-type:lower-alpha}ol.upperalpha{list-style-type:upper-alpha}ol.lowerroman{list-style-type:lower-roman}ol.upperroman{list-style-type:upper-roman}ol.lowergreek{list-style-type:lower-greek}.hdlist>table,.colist>table{border:0;background:0}.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:0}td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}td.hdlist1{font-weight:bold;padding-bottom:1.25em}.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top}.colist>table tr>td:first-of-type img{max-width:initial}.colist>table tr>td:last-of-type{padding:.25em 0}.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}.imageblock.left,.imageblock[style*="float:left"]{margin:.25em .625em 1.25em 0}.imageblock.right,.imageblock[style*="float:right"]{margin:.25em 0 1.25em .625em}.imageblock>.title{margin-bottom:0}.imageblock.thumb,.imageblock.th{border-width:6px}.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}.image.left{margin-right:.625em}.image.right{margin-left:.625em}a.image{text-decoration:none;display:inline-block}a.image object{pointer-events:none}sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}sup.footnote a,sup.footnoteref a{text-decoration:none}
|
||||
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}#footnotes .footnote:last-of-type{margin-bottom:0}#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}.gist .file-data>table td.line-data{width:99%}div.unbreakable{page-break-inside:avoid}.big{font-size:larger}.small{font-size:smaller}.underline{text-decoration:underline}.overline{text-decoration:overline}.line-through{text-decoration:line-through}.aqua{color:#00bfbf}.aqua-background{background-color:#00fafa}.black{color:#000}.black-background{background-color:#000}.blue{color:#0000bf}.blue-background{background-color:#0000fa}.fuchsia{color:#bf00bf}.fuchsia-background{background-color:#fa00fa}.gray{color:#606060}.gray-background{background-color:#7d7d7d}.green{color:#006000}.green-background{background-color:#007d00}.lime{color:#00bf00}.lime-background{background-color:#00fa00}.maroon{color:#600000}.maroon-background{background-color:#7d0000}.navy{color:#000060}.navy-background{background-color:#00007d}.olive{color:#606000}.olive-background{background-color:#7d7d00}.purple{color:#600060}.purple-background{background-color:#7d007d}.red{color:#bf0000}.red-background{background-color:#fa0000}.silver{color:#909090}.silver-background{background-color:#bcbcbc}.teal{color:#006060}.teal-background{background-color:#007d7d}.white{color:#bfbfbf}.white-background{background-color:#fafafa}.yellow{color:#bfbf00}.yellow-background{background-color:#fafa00}span.icon>.fa{cursor:default}a span.icon>.fa{cursor:inherit}.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}.conum[data-value] *{color:#fff!important}.conum[data-value]+b{display:none}.conum[data-value]:after{content:attr(data-value)}pre .conum[data-value]{position:relative;top:-.125em}b.conum *{color:inherit!important}.conum:not([data-value]):empty{display:none}dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}h1,h2,p,td.content,span.alt{letter-spacing:-.01em}p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}p{margin-bottom:1.25rem}.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}.print-only{display:none!important}@media print{@page{margin:1.25cm .75cm}*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}a{color:inherit!important;text-decoration:underline!important}a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}abbr[title]:after{content:" (" attr(title) ")"}pre,blockquote,tr,img,object,svg{page-break-inside:avoid}thead{display:table-header-group}svg{max-width:100%}p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}#toc,.sidebarblock,.exampleblock>.content{background:none!important}#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}.sect1{padding-bottom:0!important}.sect1+.sect1{border:0!important}#header>h1:first-child{margin-top:1.25rem}
|
||||
body.book #header{text-align:center}body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}body.book #header .details{border:0!important;display:block;padding:0!important}body.book #header .details span:first-child{margin-left:0!important}body.book #header .details br{display:block}body.book #header .details br+span:before{content:none!important}body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}.listingblock code[data-lang]:before{display:block}#footer{background:none!important;padding:0 .9375em}#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}.hide-on-print{display:none!important}.print-only{display:block!important}.hide-for-print{display:none!important}.show-for-print{display:inherit!important}}#content .page-footer{height:100px;border-top:1px solid #ccc;overflow:hidden;padding:10px 0;font-size:14px;color:gray}#content .footer-modification{float:right}#content .footer-modification a{text-decoration:none}.sectlevel2{display:none}.submenu{background:#e7e7e6}.submenu li{border:0}.submenu a{color:#555}.checkbox{position:relative;height:30px}.checkbox input[type='checkbox']{position:absolute;left:0;top:0;width:20px;height:20px;opacity:0;border-radius:4px}.checkbox label{position:absolute;left:30px;top:0;height:20px;line-height:20px}.checkbox label:before{content:'';position:absolute;left:-30px;top:2px;width:20px;height:20px;border:1px solid #ddd;border-radius:4px;transition:all .3s ease;-webkit-transition:all .3s ease;-moz-transition:all .3s ease}.checkbox label:after{content:'';position:absolute;left:-22px;top:3px;width:6px;height:12px;border:0;border-right:1px solid #fff;border-bottom:1px solid #fff;border-radius:2px;transform:rotate(45deg);-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transition:all .3s ease;-webkit-transition:all .3s ease;-moz-transition:all .3s ease}.checkbox input[type='checkbox']:checked+label:before{background:#4cd764;border-color:#4cd764}.checkbox input[type='checkbox']:checked+label:after{background:#4cd764}.send-button{color:#fff;background-color:#5cb85c;display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px;outline-color:transparent}textarea{width:100%;background-color:#f7f7f8;border:1px solid #f7f7f8;border-radius:4px;font-size:1em;padding:1em;font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;outline-color:#dedede}input{border:0;background-color:transparent;outline-color:transparent;outline-style:dotted;max-width:100%}#book-search-input{padding:13px;background:0;transition:top .5s ease;border-bottom:1px solid rgba(0,0,0,.07);border-top:1px solid rgba(0,0,0,.07);margin-top:-1px}#book-search-input input,#book-search-input input:focus,#book-search-input input:hover{width:100%;background:0;border:1px solid transparent;box-shadow:none;outline:0;line-height:22px;padding:7px 7px;color:inherit}[contenteditable="plaintext-only"]:focus{border:0;outline:0}
|
||||
body.book #header{text-align:center}body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}body.book #header .details{border:0!important;display:block;padding:0!important}body.book #header .details span:first-child{margin-left:0!important}body.book #header .details br{display:block}body.book #header .details br+span:before{content:none!important}body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}.listingblock code[data-lang]:before{display:block}#footer{background:none!important;padding:0 .9375em}#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}.hide-on-print{display:none!important}.print-only{display:block!important}.hide-for-print{display:none!important}.show-for-print{display:inherit!important}}#content .page-footer{height:100px;border-top:1px solid #ccc;overflow:hidden;padding:10px 0;font-size:14px;color:gray}#content .footer-modification{float:right}#content .footer-modification a{text-decoration:none}.sectlevel2{display:none}.submenu{background:#e7e7e6}.submenu li{border:0}.submenu a{color:#555}.checkbox{position:relative;height:30px}.checkbox input[type='checkbox']{position:absolute;left:0;top:0;width:20px;height:20px;opacity:0;border-radius:4px}.checkbox label{position:absolute;left:30px;top:0;height:20px;line-height:20px}.checkbox label:before{content:'';position:absolute;left:-30px;top:2px;width:20px;height:20px;border:1px solid #ddd;border-radius:4px;transition:all .3s ease;-webkit-transition:all .3s ease;-moz-transition:all .3s ease}.checkbox label:after{content:'';position:absolute;left:-22px;top:3px;width:6px;height:12px;border:0;border-right:1px solid #fff;border-bottom:1px solid #fff;border-radius:2px;transform:rotate(45deg);-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transition:all .3s ease;-webkit-transition:all .3s ease;-moz-transition:all .3s ease}.checkbox input[type='checkbox']:checked+label:before{background:#4cd764;border-color:#4cd764}.checkbox input[type='checkbox']:checked+label:after{background:#4cd764}.send-button{color:#fff;background-color:#5cb85c;display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px;outline-color:transparent}textarea{width:100%;background-color:#f7f7f8;border:1px solid #f7f7f8;border-radius:4px;font-size:1em;padding:1em;font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;outline-color:#dedede}input{border:0;background-color:transparent;outline-color:transparent;outline-style:dotted;max-width:100%}#book-search-input{padding:13px;background:0;transition:top .5s ease;border-bottom:1px solid rgba(0,0,0,.07);border-top:1px solid rgba(0,0,0,.07);margin-top:-1px}#book-search-input input,#book-search-input input:focus,#book-search-input input:hover{width:100%;background:0;border:1px solid transparent;box-shadow:none;outline:0;line-height:22px;padding:7px 7px;color:inherit}[contenteditable="plaintext-only"]:focus{border:0;outline:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}script{display:none!important}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
|
||||
button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}html,body{font-size:100%}body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}a:hover{cursor:pointer}img,object,embed{max-width:100%;height:auto}object,embed{height:100%}img{-ms-interpolation-mode:bicubic}.left{float:left!important}.right{float:right!important}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}.text-justify{text-align:justify!important}.hide{display:none}img,object,svg{display:inline-block;vertical-align:middle}textarea{height:auto;min-height:50px}select{width:100%}.center{margin-left:auto;margin-right:auto}.spread{width:100%}p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}a{color:#364149;text-decoration:underline;line-height:inherit}a:hover,a:focus{color:#364149}a img{border:0}p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}p aside{font-size:.875em;line-height:1.35;font-style:italic}h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}h1{font-size:2.125em}h2{font-size:1.6875em}h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}h4,h5{font-size:1.125em}h6{font-size:1em}hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}em,i{font-style:italic;line-height:inherit}strong,b{font-weight:bold;line-height:inherit}small{font-size:60%;line-height:inherit}code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}ul,ol{margin-left:1.5em}ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}ul.square{list-style-type:square}ul.circle{list-style-type:circle}ul.disc{list-style-type:disc}ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}dl dt{margin-bottom:.3125em;font-weight:bold}dl dd{margin-bottom:1.25em}abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}abbr{text-transform:none}blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}blockquote cite:before{content:"\2014 \0020"}blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}h1{font-size:2.75em}h2{font-size:2.3125em}h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}h4{font-size:1.4375em}}table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}table thead,table tfoot{background:#f7f8f7;font-weight:bold}table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
||||
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}.clearfix:after,.float-group:after{clear:both}*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}*:not(pre)>code.nobreak{word-wrap:normal}*:not(pre)>code.nowrap{white-space:nowrap}pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}em em{font-style:normal}strong strong{font-weight:400}.keyseq{color:rgba(51,51,51,.8)}kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}.keyseq kbd:first-child{margin-left:0}.keyseq kbd:last-child{margin-right:0}.menuseq,.menuref{color:#000}.menuseq b:not(.caret),.menuref{font-weight:inherit}.menuseq{word-spacing:-.02em}.menuseq b.caret{font-size:1.25em;line-height:.8}.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}b.button:before{content:"[";padding:0 3px 0 2px}b.button:after{content:"]";padding:0 2px 0 3px}p a>code:hover{color:rgba(0,0,0,.9)}#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}#header:after,#content:after,#footnotes:after,#footer:after{clear:both}#content{margin-top:1.25em}#content:before{content:none}#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}#header .details span:first-child{margin-left:-.125em}#header .details span.email a{color:rgba(0,0,0,.85)}#header .details br{display:none}#header .details br+span:before{content:"\00a0\2013\00a0"}#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}#header .details br+span#revremark:before{content:"\00a0|\00a0"}#header #revnumber{text-transform:capitalize}#header #revnumber:after{content:"\00a0"}#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}#toc>ul{margin-left:.125em;padding-left:1.25em}#toc ul.sectlevel0>li>a{font-style:italic}#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}#toc li{line-height:1.3334;margin-top:.3334em;padding-bottom:4px;padding-top:4px}#toc a{text-decoration:none}#toc a:active{text-decoration:underline}#toctitle{color:#7a2518;font-size:1.2em}@media only screen and (min-width:768px){#toctitle{font-size:1.375em}body.toc2{padding-left:15em;padding-right:0}#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;#padding:1.25em 1em;height:100%;overflow:auto}#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
||||
#toc.toc2>ul{font-size:.9em;margin-bottom:0}#toc.toc2 ul ul{margin-left:0;padding-left:1em}#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}body.toc2.toc-right{padding-left:0;padding-right:15em}body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}#toc.toc2{width:20em}#toc.toc2 #toctitle{font-size:1.375em;border-bottom:1px solid rgba(0,0,0,.07);padding-top:20px;padding-bottom:15px}#toc.toc2 #toctitle span{padding-left:1.25em;padding-bottom:15px}#toc.toc2>ul{font-size:.95em}#toc.toc2 ul ul{padding-left:1.25em}body.toc2.toc-right{padding-left:0;padding-right:20em}}#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}#content #toc>:first-child{margin-top:0}#content #toc>:last-child{margin-bottom:0}#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}#footer-text{color:rgba(255,255,255,.8);line-height:1.44}.sect1{padding-bottom:.625em}@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}.sect1+.sect1{border-top:1px solid #efefed}#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}.admonitionblock>table{border-collapse:separate;border:0;background:0;width:100%}.admonitionblock>table td.icon{text-align:center;width:80px}.admonitionblock>table td.icon img{max-width:initial}.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}.exampleblock>.content>:first-child{margin-top:0}.exampleblock>.content>:last-child{margin-bottom:0}.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}.sidebarblock>:first-child{margin-top:0}.sidebarblock>:last-child{margin-bottom:0}.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
||||
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}.listingblock pre.highlightjs{padding:0}.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}.listingblock pre.prettyprint{border-width:0}.listingblock>.content{position:relative}.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}.listingblock:hover code[data-lang]:before{display:block}.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:0}table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}table.pyhltable td.code{padding-left:.75em;padding-right:0}pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}pre.pygments .lineno{display:inline-block;margin-right:.25em}table.pyhltable .linenodiv{background:none!important;padding-right:0!important}.quoteblock{margin:0 1em 1.25em 1.5em;display:table}.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}.quoteblock blockquote{margin:0;padding:0;border:0}.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}.quoteblock .quoteblock blockquote:before{display:none}.verseblock{margin:0 1em 1.25em 1em}.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}.verseblock pre strong{font-weight:400}.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}.quoteblock .attribution br,.verseblock .attribution br{display:none}.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}.quoteblock.abstract{margin:0 0 1.25em 0;display:block}.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}table.tableblock{max-width:100%;border-collapse:separate}table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0}table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0}table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
|
||||
table.frame-all{border-width:1px}table.frame-sides{border-width:0 1px}table.frame-topbot{border-width:1px 0}th.halign-left,td.halign-left{text-align:left}th.halign-right,td.halign-right{text-align:right}th.halign-center,td.halign-center{text-align:center}th.valign-top,td.valign-top{vertical-align:top}th.valign-bottom,td.valign-bottom{vertical-align:bottom}th.valign-middle,td.valign-middle{vertical-align:middle}table thead th,table tfoot th{font-weight:bold}tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}p.tableblock>code:only-child{background:0;padding:0}p.tableblock{font-size:1em}td>div.verse{white-space:pre}ol{margin-left:1.75em}ul li ol{margin-left:1.5em}dl dd{margin-left:1.125em}dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}ul.unstyled,ol.unstyled{margin-left:0}ul.checklist{margin-left:.625em}ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}ul.inline>li>*{display:block}.unstyled dl dt{font-weight:400;font-style:normal}ol.arabic{list-style-type:decimal}ol.decimal{list-style-type:decimal-leading-zero}ol.loweralpha{list-style-type:lower-alpha}ol.upperalpha{list-style-type:upper-alpha}ol.lowerroman{list-style-type:lower-roman}ol.upperroman{list-style-type:upper-roman}ol.lowergreek{list-style-type:lower-greek}.hdlist>table,.colist>table{border:0;background:0}.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:0}td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}td.hdlist1{font-weight:bold;padding-bottom:1.25em}.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top}.colist>table tr>td:first-of-type img{max-width:initial}.colist>table tr>td:last-of-type{padding:.25em 0}.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}.imageblock.left,.imageblock[style*="float:left"]{margin:.25em .625em 1.25em 0}.imageblock.right,.imageblock[style*="float:right"]{margin:.25em 0 1.25em .625em}.imageblock>.title{margin-bottom:0}.imageblock.thumb,.imageblock.th{border-width:6px}.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}.image.left{margin-right:.625em}.image.right{margin-left:.625em}a.image{text-decoration:none;display:inline-block}a.image object{pointer-events:none}sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}sup.footnote a,sup.footnoteref a{text-decoration:none}sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}#footnotes .footnote:last-of-type{margin-bottom:0}#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}.gist .file-data>table td.line-data{width:99%}div.unbreakable{page-break-inside:avoid}.big{font-size:larger}.small{font-size:smaller}.underline{text-decoration:underline}.overline{text-decoration:overline}.line-through{text-decoration:line-through}.aqua{color:#00bfbf}.aqua-background{background-color:#00fafa}.black{color:#000}.black-background{background-color:#000}.blue{color:#0000bf}.blue-background{background-color:#0000fa}.fuchsia{color:#bf00bf}.fuchsia-background{background-color:#fa00fa}.gray{color:#606060}.gray-background{background-color:#7d7d7d}.green{color:#006000}.green-background{background-color:#007d00}.lime{color:#00bf00}.lime-background{background-color:#00fa00}.maroon{color:#600000}.maroon-background{background-color:#7d0000}.navy{color:#000060}.navy-background{background-color:#00007d}.olive{color:#606000}.olive-background{background-color:#7d7d00}.purple{color:#600060}.purple-background{background-color:#7d007d}.red{color:#bf0000}
|
||||
.red-background{background-color:#fa0000}.silver{color:#909090}.silver-background{background-color:#bcbcbc}.teal{color:#006060}.teal-background{background-color:#007d7d}.white{color:#bfbfbf}.white-background{background-color:#fafafa}.yellow{color:#bfbf00}.yellow-background{background-color:#fafa00}span.icon>.fa{cursor:default}a span.icon>.fa{cursor:inherit}.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}.conum[data-value] *{color:#fff!important}.conum[data-value]+b{display:none}.conum[data-value]:after{content:attr(data-value)}pre .conum[data-value]{position:relative;top:-.125em}b.conum *{color:inherit!important}.conum:not([data-value]):empty{display:none}dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}h1,h2,p,td.content,span.alt{letter-spacing:-.01em}p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}p{margin-bottom:1.25rem}.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}.print-only{display:none!important}@media print{@page{margin:1.25cm .75cm}*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}a{color:inherit!important;text-decoration:underline!important}a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}abbr[title]:after{content:" (" attr(title) ")"}pre,blockquote,tr,img,object,svg{page-break-inside:avoid}thead{display:table-header-group}svg{max-width:100%}p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}#toc,.sidebarblock,.exampleblock>.content{background:none!important}#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}.sect1{padding-bottom:0!important}.sect1+.sect1{border:0!important}#header>h1:first-child{margin-top:1.25rem}body.book #header{text-align:center}body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}body.book #header .details{border:0!important;display:block;padding:0!important}body.book #header .details span:first-child{margin-left:0!important}body.book #header .details br{display:block}body.book #header .details br+span:before{content:none!important}body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}.listingblock code[data-lang]:before{display:block}#footer{background:none!important;padding:0 .9375em}#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}.hide-on-print{display:none!important}.print-only{display:block!important}.hide-for-print{display:none!important}.show-for-print{display:inherit!important}}#content .page-footer{height:100px;border-top:1px solid #ccc;overflow:hidden;padding:10px 0;font-size:14px;color:gray}#content .footer-modification{float:right}#content .footer-modification a{text-decoration:none}.sectlevel2{display:none}.submenu{background:#e7e7e6}.submenu li{border:0}.submenu a{color:#555}.copyright{text-align:right;padding-top:1.25em}#toTop{display:none;position:fixed;bottom:10px;right:0;width:44px;height:44px;border-radius:50%;background-color:#ced4ce;cursor:pointer;text-align:center}#upArrow{position:absolute;left:24%;right:0;bottom:19%;transition:.3s ease-in-out;display:block}#upText{position:absolute;left:0;right:0;bottom:0;font-size:16px;font-weight: 600;line-height:45px;display:none;transition:.3s ease-in-out;-webkit-box-align:center}
|
|
@ -0,0 +1,5 @@
|
|||
@font-face{font-family:'Droid Sans Mono';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/droidsansmono/v14/6NUO8FuJNQ2MbkrZ5-J8lKFrp7pRef2r.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Kaw1J5X9T9RW6j9bNfFImZzC7TMQ.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Kaw1J5X9T9RW6j9bNfFImbjC7TMQ.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Kaw1J5X9T9RW6j9bNfFImZjC7TMQ.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Kaw1J5X9T9RW6j9bNfFImaTC7TMQ.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Kaw1J5X9T9RW6j9bNfFImZTC7TMQ.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Kaw1J5X9T9RW6j9bNfFImZDC7TMQ.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Kaw1J5X9T9RW6j9bNfFImajC7.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Vaw1J5X9T9RW6j9bNfFIu0RWufuVMCoY.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Vaw1J5X9T9RW6j9bNfFIu0RWud-VMCoY.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Vaw1J5X9T9RW6j9bNfFIu0RWuf-VMCoY.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Vaw1J5X9T9RW6j9bNfFIu0RWucOVMCoY.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Vaw1J5X9T9RW6j9bNfFIu0RWufOVMCoY.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Vaw1J5X9T9RW6j9bNfFIu0RWufeVMCoY.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Noto Serif';font-style:italic;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Vaw1J5X9T9RW6j9bNfFIu0RWuc-VM.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Iaw1J5X9T9RW6j9bNfFoWaCi_.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
|
||||
@font-face{font-family:'Noto Serif';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Iaw1J5X9T9RW6j9bNfFMWaCi_.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Iaw1J5X9T9RW6j9bNfFsWaCi_.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Iaw1J5X9T9RW6j9bNfFQWaCi_.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Iaw1J5X9T9RW6j9bNfFgWaCi_.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Iaw1J5X9T9RW6j9bNfFkWaCi_.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Iaw1J5X9T9RW6j9bNfFcWaA.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Law1J5X9T9RW6j9bNdOwzfRqecf1I.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Law1J5X9T9RW6j9bNdOwzfROecf1I.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Law1J5X9T9RW6j9bNdOwzfRuecf1I.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Law1J5X9T9RW6j9bNdOwzfRSecf1I.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Law1J5X9T9RW6j9bNdOwzfRiecf1I.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Law1J5X9T9RW6j9bNdOwzfRmecf1I.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Noto Serif';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.cnpmjs.org/s/notoserif/v11/ga6Law1J5X9T9RW6j9bNdOwzfReecQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKWyV9hmIqOjjg.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKWyV9hvIqOjjg.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKWyV9hnIqOjjg.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKWyV9hoIqOjjg.woff2) format('woff2');unicode-range:U+0370-03FF}
|
||||
@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKWyV9hkIqOjjg.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKWyV9hlIqOjjg.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKWyV9hrIqM.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem6YaGs126MiZpBA-UFUK0Udc1UAw.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem6YaGs126MiZpBA-UFUK0ddc1UAw.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem6YaGs126MiZpBA-UFUK0Vdc1UAw.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem6YaGs126MiZpBA-UFUK0adc1UAw.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem6YaGs126MiZpBA-UFUK0Wdc1UAw.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem6YaGs126MiZpBA-UFUK0Xdc1UAw.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem6YaGs126MiZpBA-UFUK0Zdc0.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKXGUdhmIqOjjg.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKXGUdhvIqOjjg.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKXGUdhnIqOjjg.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKXGUdhoIqOjjg.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKXGUdhkIqOjjg.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKXGUdhlIqOjjg.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
||||
@font-face{font-family:'Open Sans';font-style:italic;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/memnYaGs126MiZpBA-UFUKXGUdhrIqM.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UN_r8OX-hpOqc.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UN_r8OVuhpOqc.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UN_r8OXuhpOqc.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UN_r8OUehpOqc.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UN_r8OXehpOqc.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UN_r8OXOhpOqc.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UN_r8OUuhp.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem8YaGs126MiZpBA-UFWJ0bbck.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem8YaGs126MiZpBA-UFUZ0bbck.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem8YaGs126MiZpBA-UFWZ0bbck.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem8YaGs126MiZpBA-UFVp0bbck.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem8YaGs126MiZpBA-UFWp0bbck.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem8YaGs126MiZpBA-UFW50bbck.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem8YaGs126MiZpBA-UFVZ0b.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UNirkOX-hpOqc.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
|
||||
@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UNirkOVuhpOqc.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UNirkOXuhpOqc.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UNirkOUehpOqc.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UNirkOXehpOqc.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UNirkOXOhpOqc.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:url(https://fonts.gstatic.cnpmjs.org/s/opensans/v23/mem5YaGs126MiZpBA-UNirkOUuhp.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
@ -0,0 +1 @@
|
|||
.hljs{display:block;overflow-x:auto;color:#eaeaea;background:#000;padding:.5em}.hljs-subst{color:#eaeaea}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-builtin-name,.hljs-type{color:#eaeaea}.hljs-params{color:#da0000}.hljs-literal,.hljs-name,.hljs-number{color:red;font-weight:bolder}.hljs-comment{color:#969896}.hljs-quote,.hljs-selector-id{color:#0ff}.hljs-template-variable,.hljs-title,.hljs-variable{color:#0ff;font-weight:700}.hljs-keyword,.hljs-selector-class,.hljs-symbol{color:#fff000}.hljs-bullet,.hljs-string{color:#0f0}.hljs-section,.hljs-tag{color:#000fff}.hljs-selector-tag{color:#000fff;font-weight:700}.hljs-attribute,.hljs-built_in,.hljs-link,.hljs-regexp{color:#f0f}.hljs-meta{color:#fff;font-weight:bolder}
|
File diff suppressed because one or more lines are too long
|
@ -9,15 +9,13 @@
|
|||
**Author:** ${author}
|
||||
|
||||
**Version:** ${version}
|
||||
<% for(doc in list){ %>
|
||||
<%
|
||||
for(doc in list){
|
||||
%>
|
||||
<%if(doc.deprecated){%>
|
||||
|
||||
## ~~${doc.desc}~~
|
||||
|
||||
<%}else{%>
|
||||
|
||||
## ${doc.desc}
|
||||
|
||||
<%}%>
|
||||
|
||||
**Definition:** ${doc.methodDefinition}
|
||||
|
@ -33,8 +31,9 @@
|
|||
|
||||
Parameter|Type|Description|Required|Since
|
||||
---|---|---|---|---
|
||||
|
||||
<% for(param in doc.requestParams){ %>
|
||||
<%
|
||||
for(param in doc.requestParams){
|
||||
%>
|
||||
${param.field}|${param.type}|${param.desc}|${param.required}|${param.version}
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
@ -44,8 +43,9 @@ ${param.field}|${param.type}|${param.desc}|${param.required}|${param.version}
|
|||
|
||||
Field | Type|Description|Since
|
||||
---|---|---|---
|
||||
|
||||
<% for(param in doc.responseParams){ %>
|
||||
<%
|
||||
for(param in doc.responseParams){
|
||||
%>
|
||||
${param.field}|${param.type}|${param.desc}|${param.version}
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
|
|
@ -1,31 +1,271 @@
|
|||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, initial-scale=1.0"><meta name="generator"content="smart-doc"><%if(isNotEmpty(projectName)){%><title>${projectName}</title><%}else{%><title>API Reference</title><%}%><link rel="stylesheet"href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"><link rel="stylesheet"href="AllInOne.css?v=${version}"/><script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script></head><body class="book toc2 toc-left"><div id="header"><%if(isNotEmpty(projectName)){%><h1>${projectName}</h1><%}%><div id="toc"class="toc2"><div id="book-search-input"><input id="search"type="text"placeholder="Type to search"></div><div id="toctitle"><span>API Reference</span></div><ul id="accordion"class="sectlevel1"><li><a href="#_add_dependency">1. Add dependency</a></li><%for(api in apiDocList){%><%if(apiLP.first){%><li class="open"><a class="dd"href="#_${api.link}">${api.order+1}. ${api.desc}</a><ul class="sectlevel2"style="display: block"><%for(doc in api.list){%><li><%if(doc.deprecated){%><a href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. <span class="line-through">${doc.desc}</span></a><%}else{%><a href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. ${doc.desc}</a><%}%></li><%}%></ul></li><%}else{%><li><a class="dd"href="#_${api.link}">${api.order+1}. ${api.desc}</a><ul class="sectlevel2"><%for(doc in api.list){%><li><%if(doc.deprecated){%><a href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. <span class="line-through">${doc.desc}</span></a><%}else{%><a href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. ${doc.desc}</a><%}%></li><%}%></ul></li><%}%><%}%><%if(isNotEmpty(errorCodeList)){%><li><a href="#_error_code_list">${apiDocList.~size+1}. ${errorListTitle}</a></li><%}%><%if(isNotEmpty(dictList)){%><li><a class="dd"href="#_dict_list">${dictListOrder}. ${dictListTitle}</a><ul class="sectlevel2"><%for(dict in dictList){%><li><a href="#_${dictListOrder}_${dict.order}_${dict.title}">${dictListOrder}.${dict.order}. ${dict.title}</a></li><%}%></ul></li><%}%></ul></div></div><div id="content"><%if(isNotEmpty(revisionLogList)){%><div id="preamble"><div class="sectionbody"><table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 20%;"><col style="width: 20%;"><col style="width: 20%;"><col style="width: 20%;"><col style="width: 20%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Version</th><th class="tableblock halign-left valign-top">Update Time</th><th class="tableblock halign-left valign-top">Status</th><th class="tableblock halign-left valign-top">Author</th><th class="tableblock halign-left valign-top">Description</th></tr></thead><tbody><%for(revisionLog in revisionLogList){%><tr><td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.version}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.revisionTime}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.status}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.author}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.remarks}</p></td></tr><%}%></tbody></table></div></div><%}%><%if(isNotEmpty(dependencyList)){%><div class="sect1"><h2 id="_add_dependency"><a class="anchor"href="#_add_dependency"></a><a class="link"href="#_add_dependency">1. Add dependency</a></h2><div class="sectionbody"><div class="listingblock"><div class="content">
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="smart-doc">
|
||||
<%if(isNotEmpty(projectName)){%><title>${projectName}</title><%}else{%><title>API Reference</title><%}%>
|
||||
<link rel="stylesheet" href="font.css?v=${version}">
|
||||
<link rel="stylesheet" href="AllInOne.css?v=${version}"/>
|
||||
<script src="jquery.min.js"></script>
|
||||
</head>
|
||||
<body class="book toc2 toc-left">
|
||||
<div id="header"> <%if(isNotEmpty(projectName)){%><h1>${projectName}</h1><%}%>
|
||||
<div id="toc" class="toc2">
|
||||
<div id="book-search-input"><input id="search" type="text" placeholder="Type to search"></div>
|
||||
<div id="toctitle"><span>API Reference</span></div>
|
||||
<ul id="accordion" class="sectlevel1">
|
||||
<li><a href="#_add_dependency">1. Add dependency</a></li>
|
||||
<%for(api in apiDocList){%><%if(apiLP.first){%>
|
||||
<li class="open"><a class="dd" href="#_${api.link}">${api.order+1}. ${api.desc}</a>
|
||||
<ul class="sectlevel2" style="display: block"><%for(doc in api.list){%>
|
||||
<li><%if(doc.deprecated){%><a href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. <span
|
||||
class="line-through">${htmlEscape(doc.desc)}</span></a><%}else{%><a
|
||||
href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. ${htmlEscape(doc.desc)}</a><%}%>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}else{%>
|
||||
<li><a class="dd" href="#_${api.link}">${api.order+1}. ${htmlEscape(api.desc)}</a>
|
||||
<ul class="sectlevel2"><%for(doc in api.list){%>
|
||||
<li><%if(doc.deprecated){%><a href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. <span
|
||||
class="line-through">${htmlEscape(doc.desc)}</span></a><%}else{%><a
|
||||
href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. ${htmlEscape(doc.desc)}</a><%}%>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}%><%}%><%if(isNotEmpty(errorCodeList)){%>
|
||||
<li><a href="#_error_code_list">${apiDocList.~size+1}. ${errorListTitle}</a></li>
|
||||
<%}%><%if(isNotEmpty(dictList)){%>
|
||||
<li><a class="dd" href="#_dict_list">${dictListOrder}. ${dictListTitle}</a>
|
||||
<ul class="sectlevel2"><%for(dict in dictList){%>
|
||||
<li><a href="#_${dictListOrder}_${dict.order}_${dict.title}">${dictListOrder}.${dict.order}. ${htmlEscape(dict.title)}</a>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content"> <%if(isNotEmpty(revisionLogList)){%>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<table class="tableblock frame-all grid-all spread">
|
||||
<colgroup>
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 20%;">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="tableblock halign-left valign-top">Version</th>
|
||||
<th class="tableblock halign-left valign-top">Update Time</th>
|
||||
<th class="tableblock halign-left valign-top">Status</th>
|
||||
<th class="tableblock halign-left valign-top">Author</th>
|
||||
<th class="tableblock halign-left valign-top">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><%for(revisionLog in revisionLogList){%>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.version}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.revisionTime}</p>
|
||||
</td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.status}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.author}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${revisionLog.remarks}</p></td>
|
||||
</tr>
|
||||
<%}%>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<%}%><%if(isNotEmpty(dependencyList)){%>
|
||||
<div class="sect1"><h2 id="_add_dependency"><a class="anchor" href="#_add_dependency"></a><a class="link"
|
||||
href="#_add_dependency">1. Add
|
||||
dependency</a></h2>
|
||||
<div class="sectionbody">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre><%for(dp in dependencyList){%><dependency>
|
||||
<groupId>${dp.groupId}</groupId>
|
||||
<artifactId>${dp.artifactId}</artifactId>
|
||||
<version>${dp.version}</version>
|
||||
<groupId>${dp.groupId}</groupId>
|
||||
<artifactId>${dp.artifactId}</artifactId>
|
||||
<version>${dp.version}</version>
|
||||
</dependency>
|
||||
<%}%>
|
||||
</pre>
|
||||
</div></div><%if(isNotEmpty(consumerConfigExample)){%><div class="paragraph"><p>Consumer config</p></div><div class="listingblock"><div class="content"><pre>${consumerConfigExample}</pre></div></div><%}%></div></div><%}%><%for(api in apiDocList){%><div class="sect1"><h2 id="_${api.desc}"><a class="anchor"href="#_${api.desc}"></a><a class="link"href="#_${api.desc}">${api.order+1}. ${api.desc}</a></h2><div class="sectionbody"><div class="paragraph"><p><strong>URI:</strong> ${api.uri}</p></div><div class="paragraph"><p><strong>Service:</strong> ${api.name}</p></div><div class="paragraph"><p><strong>Protocol:</strong> ${api.protocol}</p></div><div class="paragraph"><p><strong>Author:</strong> ${api.author}</p></div><div class="paragraph"><p><strong>Version:</strong> ${api.version}</p></div><%for(doc in api.list){%><div class="sect2"><h3 id="_${api.order+1}_${doc.order}_${doc.desc}"><a class="anchor"href="#_${api.order+1}_${doc.order}_${doc.desc}"></a><%if(doc.deprecated){%><a class="link"href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. <span class="line-through">${doc.desc}</span></a><%}else{%><a class="link"href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. ${doc.desc}</a><%}%></h3><div class="paragraph"><p><strong>Definition:</strong> ${doc.escapeMethodDefinition}</p></div><div class="paragraph"><p><strong>Description:</strong> ${doc.detail}</p></div><%if(isNotEmpty(doc.requestParams)){%><div class="paragraph"><p><strong>Invoke-parameters:</strong></p></div><table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 20%;"><col style="width: 20%;"><col style="width: 20%;"><col style="width: 20%;"><col style="width: 20%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Parameter</th><th class="tableblock halign-left valign-top">Type</th><th class="tableblock halign-left valign-top">Description</th><th class="tableblock halign-left valign-top">Required</th><th class="tableblock halign-left valign-top">Since</th></tr></thead><tbody><%for(param in doc.requestParams){%><tr><td class="tableblock halign-left valign-top"><p class="tableblock">${param.field}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${param.type}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${param.desc}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${param.required}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${param.version}</p></td></tr><%}%></tbody></table><%}%><%if(isNotEmpty(doc.responseParams)){%><div class="paragraph"><p><strong>Response-fields:</strong></p></div><table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 25%;"><col style="width: 25%;"><col style="width: 25%;"><col style="width: 25%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Field</th><th class="tableblock halign-left valign-top">Type</th><th class="tableblock halign-left valign-top">Description</th><th class="tableblock halign-left valign-top">Since</th></tr></thead><tbody><%for(param in doc.responseParams){%><tr><td class="tableblock halign-left valign-top"><p class="tableblock">${param.field}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${param.type}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${param.desc}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${param.version}</p></td></tr><%}%></tbody></table><%}%></div><%}%></div></div><%}%><%if(isNotEmpty(errorCodeList)){%><div class="sect1"><h2 id="_error_code_list"><a class="anchor"href="#_error_code_list"></a><a class="link"href="#_error_code_list">${apiDocList.~size+2}. ${errorListTitle}</a></h2><div class="sectionbody"><table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Error code</th><th class="tableblock halign-left valign-top">Description</th></tr></thead><tbody><%for(error in errorCodeList){%><tr><td class="tableblock halign-left valign-top"><p class="tableblock">${error.value}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${error.desc}</p></td></tr><%}%></tbody></table></div></div><%}%><footer class="page-footer"><span class="copyright">Generated by smart-doc at ${createTime}</span><span class="footer-modification">Suggestions,contact,support and error reporting on<a href="https://gitee.com/smart-doc-team/smart-doc"target="_blank"> Gitee</a> or<a href="https://github.com/shalousun/smart-doc"target="_blank"> Github</a></span></footer></div>
|
||||
</div>
|
||||
</div>
|
||||
<%if(isNotEmpty(consumerConfigExample)){%>
|
||||
<div class="paragraph"><p>Consumer config</p></div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre>${consumerConfigExample}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<%}%>
|
||||
</div>
|
||||
</div>
|
||||
<%}%><%for(api in apiDocList){%>
|
||||
<div class="sect1"><h2 id="_${api.desc}"><a class="anchor" href="#_${api.desc}"></a><a class="link"
|
||||
href="#_${api.desc}">${api.order+1}. ${htmlEscape(api.desc)}</a>
|
||||
</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph"><p><strong>URI:</strong> ${api.uri}</p></div>
|
||||
<div class="paragraph"><p><strong>Service:</strong> ${api.name}</p></div>
|
||||
<div class="paragraph"><p><strong>Protocol:</strong> ${api.protocol}</p></div>
|
||||
<div class="paragraph"><p><strong>Author:</strong> ${api.author}</p></div>
|
||||
<div class="paragraph"><p><strong>Version:</strong> ${api.version}</p></div>
|
||||
<%for(doc in api.list){%>
|
||||
<div class="sect2"><h3 id="_${api.order+1}_${doc.order}_${doc.desc}"><a class="anchor"
|
||||
href="#_${api.order+1}_${doc.order}_${doc.desc}"></a><%if(doc.deprecated){%><a
|
||||
class="link"
|
||||
href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. <span
|
||||
class="line-through">${htmlEscape(doc.desc)}</span></a><%}else{%><a class="link"
|
||||
href="#_${api.order+1}_${doc.order}_${doc.desc}">${api.order+1}.${doc.order}. ${htmlEscape(doc.desc)}</a><%}%>
|
||||
</h3>
|
||||
<div class="paragraph"><p><strong>Definition:</strong> ${doc.escapeMethodDefinition}</p></div>
|
||||
<div class="paragraph"><p><strong>Description:</strong> ${htmlEscape(doc.detail)}</p></div>
|
||||
<%if(isNotEmpty(doc.requestParams)){%>
|
||||
<div class="paragraph"><p><strong>Invoke-parameters:</strong></p></div>
|
||||
<table class="tableblock frame-all grid-all spread">
|
||||
<colgroup>
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 20%;">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="tableblock halign-left valign-top">Parameter</th>
|
||||
<th class="tableblock halign-left valign-top">Type</th>
|
||||
<th class="tableblock halign-left valign-top">Description</th>
|
||||
<th class="tableblock halign-left valign-top">Required</th>
|
||||
<th class="tableblock halign-left valign-top">Since</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><%for(param in doc.requestParams){%>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${param.field}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${param.type}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">
|
||||
${htmlEscape(param.desc)}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${param.required}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${param.version}</p></td>
|
||||
</tr>
|
||||
<%}%>
|
||||
</tbody>
|
||||
</table>
|
||||
<%}%><%if(isNotEmpty(doc.responseParams)){%>
|
||||
<div class="paragraph"><p><strong>Response-fields:</strong></p></div>
|
||||
<table class="tableblock frame-all grid-all spread">
|
||||
<colgroup>
|
||||
<col style="width: 25%;">
|
||||
<col style="width: 25%;">
|
||||
<col style="width: 25%;">
|
||||
<col style="width: 25%;">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="tableblock halign-left valign-top">Field</th>
|
||||
<th class="tableblock halign-left valign-top">Type</th>
|
||||
<th class="tableblock halign-left valign-top">Description</th>
|
||||
<th class="tableblock halign-left valign-top">Since</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><%for(param in doc.responseParams){%>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${param.field}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${param.type}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">
|
||||
${htmlEscape(param.desc)}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${param.version}</p></td>
|
||||
</tr>
|
||||
<%}%>
|
||||
</tbody>
|
||||
</table>
|
||||
<%}%>
|
||||
</div>
|
||||
<%}%>
|
||||
</div>
|
||||
</div>
|
||||
<%}%><%if(isNotEmpty(errorCodeList)){%>
|
||||
<div class="sect1"><h2 id="_error_code_list"><a class="anchor" href="#_error_code_list"></a><a class="link"
|
||||
href="#_error_code_list">${apiDocList.~size+2}. ${errorListTitle}</a>
|
||||
</h2>
|
||||
<div class="sectionbody">
|
||||
<table class="tableblock frame-all grid-all spread">
|
||||
<colgroup>
|
||||
<col style="width: 50%;">
|
||||
<col style="width: 50%;">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="tableblock halign-left valign-top">Error code</th>
|
||||
<th class="tableblock halign-left valign-top">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><%for(error in errorCodeList){%>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${error.value}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${htmlEscape(error.desc)}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<%}%>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<%}%>
|
||||
<footer class="page-footer"><span class="copyright">Generated by smart-doc at ${createTime}</span><span
|
||||
class="footer-modification">Suggestions,contact,support and error reporting on<ahref="https://gitee.com/smart-doc-team/smart-doc" target="_blank"> Gitee</a> or<ahref="https://github.com/smart-doc-group/smart-doc.git" target="_blank"> Github</a></span>
|
||||
</footer>
|
||||
<div href="javascript:void(0)" id="toTop"><img id="upArrow"
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABlUlEQVRIS+2UvUvDQBiH398Rly4udnARwUXs4qAIOigI4iL30dTZ2T9AcNPVvUsXF7uYttdScNDFRRAnB11cFFwKxcXBJTQnJ6lEbRI/CIiY9e6e5/e+9+ZAGX/ImE9/QKCU2jfGbGTQqq4xZgtSyisiKmQgIAAVCCFWAGxnIOhqrdd/xyUrpRZsP40xSwA6AI57vd5eq9W6T6s8tQIppSKi+gDQNREprfVNkiRRwDlfY4xZ+FAIuSOi8Qjw0nEc5XnebZwkViClXA2T5+xhY8xus9ncEUJMAziITN5FEARuXLsGCoQQywBs8uEovJ+Scz7FGDuMSM4cx3E9z+u8r+SDQEq5SEQ1IhoZBE+QnBKRq7V+iEreCDjn84wxCx9NgidITnK5nFutVh/7e14FSqnZIAhqAMY+A4+TADjyfb/Ubref7J4XQXhxNvnEV+AJlbTy+XypUqn4KBaLBZuciCa/A0+opN5oNFz7FpUBbP4EHicxxsyAcz7HGDvvz3nar5+2Ho5wOQwsU5+KNGDa+r8grUP0DBLjtRtNKEliAAAAAElFTkSuQmCC"><span
|
||||
id="upText">Top</span></div>
|
||||
</div>
|
||||
<script src="search.js?v=${version}"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
const Accordion = function (el, multiple) {
|
||||
this.el = el || {};
|
||||
this.multiple = multiple || false;
|
||||
const links = this.el.find('.dd');
|
||||
links.on('click', {el: this.el, multiple: this.multiple}, this.dropdown);
|
||||
const links = this.el.find(".dd");
|
||||
links.on("click", {el: this.el, multiple: this.multiple}, this.dropdown)
|
||||
};
|
||||
Accordion.prototype.dropdown = function (e) {
|
||||
const $el = e.data.el;
|
||||
$this = $(this), $next = $this.next();
|
||||
$next.slideToggle();
|
||||
$this.parent().toggleClass('open');
|
||||
$this.parent().toggleClass("open");
|
||||
if (!e.data.multiple) {
|
||||
$el.find('.submenu').not($next).slideUp("20").parent().removeClass('open');
|
||||
$el.find(".submenu").not($next).slideUp("20").parent().removeClass("open")
|
||||
}
|
||||
};
|
||||
new Accordion($('#accordion'), false);
|
||||
new Accordion($("#accordion"), false);
|
||||
$(window).scroll(function () {
|
||||
if ($(window).scrollTop() > 100) {
|
||||
$("#toTop").fadeIn(1500);
|
||||
$("#toTop").hover(function () {
|
||||
$("#upArrow").hide();
|
||||
$("#upText").show()
|
||||
}, function () {
|
||||
$("#upArrow").show();
|
||||
$("#upText").hide()
|
||||
})
|
||||
} else {
|
||||
$("#toTop").fadeOut(1500)
|
||||
}
|
||||
});
|
||||
$("#toTop").click(function () {
|
||||
$("body, html").animate({scrollTop: 0}, 1000);
|
||||
return false
|
||||
})
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
<%if(isNotEmpty(projectName)){%>
|
||||
|
||||
# ${projectName}
|
||||
|
||||
<%}%>
|
||||
|
||||
<%if(isNotEmpty(revisionLogList)){%>
|
||||
Version | Update Time | Status | Author | Description ---|---|---|---|---
|
||||
|
||||
Version|Update Time|Status|Author|Description
|
||||
---|---|---|---|---
|
||||
<% for(revisionLog in revisionLogList){ %>
|
||||
${revisionLog.version}|${revisionLog.revisionTime}|${revisionLog.status}|${revisionLog.author}|${revisionLog.remarks}
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
||||
<%if(isNotEmpty(dependencyList)){%>
|
||||
|
||||
## Add dependency
|
||||
|
||||
```
|
||||
|
@ -30,16 +29,15 @@ for(dependency in dependencyList){
|
|||
|
||||
<%if(isNotEmpty(consumerConfigExample)){%>
|
||||
Consumer config
|
||||
|
||||
```
|
||||
${consumerConfigExample}
|
||||
```
|
||||
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
||||
<% for(api in apiDocList){ %>
|
||||
|
||||
<%
|
||||
for(api in apiDocList){
|
||||
%>
|
||||
## ${api.desc}
|
||||
|
||||
**URI:** ${api.uri}
|
||||
|
@ -51,15 +49,13 @@ ${consumerConfigExample}
|
|||
**Author:** ${api.author}
|
||||
|
||||
**Version:** ${api.version}
|
||||
<% for(doc in api.list){ %>
|
||||
<%
|
||||
for(doc in api.list){
|
||||
%>
|
||||
<%if(doc.deprecated){%>
|
||||
|
||||
### ~~${doc.desc}~~
|
||||
|
||||
<%}else{%>
|
||||
|
||||
### ${doc.desc}
|
||||
|
||||
<%}%>
|
||||
|
||||
**Definition:** ${doc.methodDefinition}
|
||||
|
@ -75,8 +71,9 @@ ${consumerConfigExample}
|
|||
|
||||
Parameter|Type|Description|Required|Since
|
||||
---|---|---|---|---
|
||||
|
||||
<% for(param in doc.requestParams){ %>
|
||||
<%
|
||||
for(param in doc.requestParams){
|
||||
%>
|
||||
${param.field}|${param.type}|${param.desc}|${param.required}|${param.version}
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
@ -86,23 +83,25 @@ ${param.field}|${param.type}|${param.desc}|${param.required}|${param.version}
|
|||
|
||||
Field | Type|Description|Since
|
||||
---|---|---|---
|
||||
|
||||
<% for(param in doc.responseParams){ %>
|
||||
<%
|
||||
for(param in doc.responseParams){
|
||||
%>
|
||||
${param.field}|${param.type}|${param.desc}|${param.version}
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
||||
<%if(isNotEmpty(errorCodeList)){%>
|
||||
|
||||
|
||||
<%}%>
|
||||
<%}%>
|
||||
<%if(isNotEmpty(errorCodeList)){%>
|
||||
## ${errorListTitle}
|
||||
|
||||
Error code |Description
|
||||
---|---
|
||||
|
||||
<% for(error in errorCodeList){ %>
|
||||
<%
|
||||
for(error in errorCodeList){
|
||||
%>
|
||||
${error.value}|${error.desc}
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
||||
<%}%>
|
||||
<%}%>
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,101 @@
|
|||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, initial-scale=1.0"><meta name="generator"content="smart-doc"><title>SpringBoot2-Open-Api</title><link rel="stylesheet"href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"><link rel="stylesheet"href="AllInOne.css?v=1607962934038"/><link rel="stylesheet"href="https://cdn.bootcdn.net/ajax/libs/highlight.js/10.3.2/styles/xt256.min.css"><style>.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#000}.hljs{padding:0em}</style><script src="https://cdn.bootcdn.net/ajax/libs/highlight.js/10.3.2/highlight.min.js"></script><script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script></head><body class="book toc2 toc-left"><div id="header"><%if(isNotEmpty(projectName)){%><h1>${projectName}</h1><%}%><div id="toc"class="toc2"><div id="book-search-input"><input id="search"type="text"placeholder="Type to search"></div><div id="toctitle"><span>API Reference</span></div><ul id="accordion"class="sectlevel1"><%for(api in apiDocList){%><%if(apiLP.first){%><li><a class="dd"href="${alias}.html#header">${api.order}. ${api.desc}</a><ul class="sectlevel2"style="display: none"><%for(doc in api.list){%><li><%if(doc.deprecated){%><a href="${alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. <span class="line-through">${doc.desc}</span></a><%}else{%><a href="${alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. ${doc.desc}</a><%}%></li><%}%></ul></li><%}else{%><li><a class="dd"href="${api.alias}.html#header">${api.order}. ${api.desc}</a><ul class="sectlevel2"style="display: none"><%for(doc in api.list){%><li><%if(doc.deprecated){%><a href="${api.alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. <span class="line-through">${doc.desc}</span></a><%}else{%><a href="${api.alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. ${doc.desc}</a><%}%></li><%}%></ul></li><%}%><%}%><%if(isNotEmpty(errorCodeList)){%><li><a href="error.html#_error_code_list">${apiDocList.~size+1}. ${errorListTitle}</a></li><%}%><%if(isNotEmpty(dictList)){%><li class="open"><a class="dd"href="dict.html#_dict_list">${dictListOrder}. ${dictListTitle}</a><ul class="sectlevel2"style="display: block"><%for(dict in dictList){%><li><a href="dict.html#_${dictListOrder}_${dict.order}_${dict.title}">${dictListOrder}.${dict.order}. ${dict.title}</a></li><%}%></ul></li><%}%></ul></div></div><div id="content"><%if(isNotEmpty(dictList)){%><div class="sect1"><h2 id="_dict_list"><a class="anchor"href="#_dict_list"></a><a class="link"href="#_dict_list">${dictListOrder}. ${dictListTitle}</a></h2><div class="sectionbody"><%for(dict in dictList){%><div class="sect2"><h3 id="_${dictListOrder}_${dict.order}_${dict.title}"><a class="anchor"href="#_${dictListOrder}_${dict.order}_${dict.title}"></a><a class="link"href="#_${dictListOrder}_${dict.order}_${dict.title}">${dictListOrder}.${dict.order}. ${dict.title}</a></h3><table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 33%;"><col style="width: 33%;"><col style="width: 33%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Code</th><th class="tableblock halign-left valign-top">Type</th><th class="tableblock halign-left valign-top">Description</th></tr></thead><tbody><%for(dataDict in dict.dataDictList){%><tr><td class="tableblock halign-left valign-top"><p class="tableblock">${dataDict.value}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${dataDict.type}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${dataDict.desc}</p></td></tr><%}%></tbody></table></div><%}%></div></div><%}%><footer class="page-footer"><span class="copyright">Generated by smart-doc at ${createTime}</span><span class="footer-modification">Suggestions,contact,support and error reporting on<a href="https://gitee.com/smart-doc-team/smart-doc"target="_blank"> Gitee</a> or<a href="https://github.com/smart-doc-group/smart-doc.git"target="_blank"> Github</a></span></footer></div>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="smart-doc">
|
||||
<title>Dictionary</title>
|
||||
<link rel="stylesheet" href="font.css">
|
||||
<link rel="stylesheet" href="AllInOne.css?v=${version}"/>
|
||||
<%if(isNotEmpty(highlightCssLink)){%><link rel="stylesheet" href="${highlightCssLink}"><%}%>
|
||||
<style>.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint {
|
||||
background: ${background}
|
||||
}
|
||||
.hljs {
|
||||
padding: 0em
|
||||
}</style>
|
||||
<script src="highlight.min.js"></script>
|
||||
<script src="jquery.min.js"></script>
|
||||
</head>
|
||||
<body class="book toc2 toc-left">
|
||||
<div id="header"><%if(isNotEmpty(projectName)){%><h1>${projectName}</h1><%}%>
|
||||
<div id="toc" class="toc2">
|
||||
<div id="book-search-input"><input id="search" type="text" placeholder="Type to search"></div>
|
||||
<div id="toctitle"><span>API Reference</span></div>
|
||||
<ul id="accordion" class="sectlevel1"><%for(api in apiDocList){%><%if(apiLP.first){%>
|
||||
<li><a class="dd" href="${alias}.html#header">${api.order}. ${htmlEscape(api.desc)}</a>
|
||||
<ul class="sectlevel2" style="display: none"><%for(doc in api.list){%>
|
||||
<li><%if(doc.deprecated){%><a href="${alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. <span
|
||||
class="line-through">${htmlEscape(doc.desc)}</span></a><%}else{%><a
|
||||
href="${alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. ${htmlEscape(doc.desc)}</a><%}%>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}else{%>
|
||||
<li><a class="dd" href="${api.alias}.html#header">${api.order}. ${htmlEscape(api.desc)}</a>
|
||||
<ul class="sectlevel2" style="display: none"><%for(doc in api.list){%>
|
||||
<li><%if(doc.deprecated){%><a href="${api.alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. <span
|
||||
class="line-through">${htmlEscape(doc.desc)}</span></a><%}else{%><a
|
||||
href="${api.alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. ${htmlEscape(doc.desc)}</a><%}%>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}%><%}%><%if(isNotEmpty(errorCodeList)){%>
|
||||
<li><a href="error.html#_error_code_list">${apiDocList.~size+1}. ${errorListTitle}</a></li>
|
||||
<%}%><%if(isNotEmpty(dictList)){%>
|
||||
<li class="open"><a class="dd" href="dict.html#_dict_list">${dictListOrder}. ${dictListTitle}</a>
|
||||
<ul class="sectlevel2" style="display: block"><%for(dict in dictList){%>
|
||||
<li><a href="dict.html#_${dictListOrder}_${dict.order}_${dict.title}">${dictListOrder}.${dict.order}. ${dict.title}</a>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content"><%if(isNotEmpty(dictList)){%>
|
||||
<div class="sect1"><h2 id="_dict_list"><a class="anchor" href="#_dict_list"></a><a class="link" href="#_dict_list">${dictListOrder}. ${dictListTitle}</a>
|
||||
</h2>
|
||||
<div class="sectionbody"><%for(dict in dictList){%>
|
||||
<div class="sect2"><h3 id="_${dictListOrder}_${dict.order}_${dict.title}">
|
||||
<a class="anchor" href="#_${dictListOrder}_${dict.order}_${dict.title}"></a>
|
||||
<a class="link" href="#_${dictListOrder}_${dict.order}_${dict.title}">${dictListOrder}.${dict.order}. ${dict.title}</a>
|
||||
</h3>
|
||||
<table class="tableblock frame-all grid-all spread">
|
||||
<colgroup>
|
||||
<col style="width: 33%;">
|
||||
<col style="width: 33%;">
|
||||
<col style="width: 33%;">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="tableblock halign-left valign-top">Code</th>
|
||||
<th class="tableblock halign-left valign-top">Type</th>
|
||||
<th class="tableblock halign-left valign-top">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><%for(dataDict in dict.dataDictList){%>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${dataDict.value}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${dataDict.type}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${htmlEscape(dataDict.desc)}</p></td>
|
||||
</tr>
|
||||
<%}%>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<%}%>
|
||||
</div>
|
||||
</div>
|
||||
<%}%>
|
||||
<footer class="page-footer"><span class="copyright">Generated by smart-doc at ${createTime}</span><span
|
||||
class="footer-modification">Suggestions,contact,support and error reporting on<a
|
||||
href="https://gitee.com/smart-doc-team/smart-doc" target="_blank"> Gitee</a> or<a
|
||||
href="https://github.com/smart-doc-group/smart-doc.git" target="_blank"> Github</a></span></footer>
|
||||
</div>
|
||||
<script src="search.js?v=${version}"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
|
@ -18,7 +115,7 @@
|
|||
}
|
||||
};
|
||||
new Accordion($('#accordion'), false);
|
||||
hljs.initHighlightingOnLoad()
|
||||
hljs.highlightAll()
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -1,4 +1,104 @@
|
|||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, initial-scale=1.0"><meta name="generator"content="smart-doc"><title>SpringBoot2-Open-Api</title><link rel="stylesheet"href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"><link rel="stylesheet"href="AllInOne.css?v=1607962934038"/><link rel="stylesheet"href="https://cdn.bootcdn.net/ajax/libs/highlight.js/10.3.2/styles/xt256.min.css"><style>.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#000}.hljs{padding:0em}</style><script src="https://cdn.bootcdn.net/ajax/libs/highlight.js/10.3.2/highlight.min.js"></script><script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script></head><body class="book toc2 toc-left"><div id="header"><%if(isNotEmpty(projectName)){%><h1>${projectName}</h1><%}%><div id="toc"class="toc2"><div id="book-search-input"><input id="search"type="text"placeholder="Type to search"></div><div id="toctitle"><span>API Reference</span></div><ul id="accordion"class="sectlevel1"><%for(api in apiDocList){%><%if(apiLP.first){%><li><a class="dd"href="${alias}.html#header">${api.order}. ${api.desc}</a><ul class="sectlevel2"style="display: none"><%for(doc in api.list){%><li><%if(doc.deprecated){%><a href="${alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. <span class="line-through">${doc.desc}</span></a><%}else{%><a href="${alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. ${doc.desc}</a><%}%></li><%}%></ul></li><%}else{%><li><a class="dd"href="${api.alias}.html#header">${api.order}. ${api.desc}</a><ul class="sectlevel2"style="display: none"><%for(doc in api.list){%><li><%if(doc.deprecated){%><a href="${api.alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. <span class="line-through">${doc.desc}</span></a><%}else{%><a href="${api.alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. ${doc.desc}</a><%}%></li><%}%></ul></li><%}%><%}%><%if(isNotEmpty(errorCodeList)){%><li class="open"><a href="error.html#header">${apiDocList.~size+1}. ${errorListTitle}</a><ul class="sectlevel2"style="display: block"><li><a href="error.html#_${apiDocList.~size+1}_1_${errorListTitle}">${apiDocList.~size+1}.1. ${errorListTitle}</a></li></ul></li><%}%><%if(isNotEmpty(dictList)){%><li><a class="dd"href="dict.html#_dict_list">${dictListOrder}. ${dictListTitle}</a><ul class="sectlevel2"><%for(dict in dictList){%><li><a href="dict.html#_${dictListOrder}_${dict.order}_${dict.title}">${dictListOrder}.${dict.order}. ${dict.title}</a></li><%}%></ul></li><%}%></ul></div></div><div id="content"><%if(isNotEmpty(errorCodeList)){%><div class="sect1"><h2 id="_error_code_list"><a class="anchor"href="#_error_code_list"></a><a class="link"href="#_error_code_list">${apiDocList.~size+1}. ${errorListTitle}</a></h2><div class="sectionbody"><div class="sect2"><h3 id="_${apiDocList.~size+1}_1_${errorListTitle}"><a class="anchor"href="#_${apiDocList.~size+1}_1_${errorListTitle}"></a><a class="link"href="#_${apiDocList.~size+1}_1_${errorListTitle}">${apiDocList.~size+1}.1. ${errorListTitle}</a></h3><table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Error code</th><th class="tableblock halign-left valign-top">Description</th></tr></thead><tbody><%for(error in errorCodeList){%><tr><td class="tableblock halign-left valign-top"><p class="tableblock">${error.value}</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">${error.desc}</p></td></tr><%}%></tbody></table></div></div></div><%}%><footer class="page-footer"><span class="copyright">Generated by smart-doc at ${createTime}</span><span class="footer-modification">Suggestions,contact,support and error reporting on<a href="https://gitee.com/smart-doc-team/smart-doc"target="_blank"> Gitee</a> or<a href="https://github.com/smart-doc-group/smart-doc.git"target="_blank"> Github</a></span></footer></div>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="smart-doc">
|
||||
<title>Error Code</title>
|
||||
<link rel="stylesheet" href="font.css">
|
||||
<link rel="stylesheet" href="AllInOne.css?v=${version}"/>
|
||||
<%if(isNotEmpty(highlightCssLink)){%><link rel="stylesheet" href="${highlightCssLink}"><%}%>
|
||||
<style>.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint {
|
||||
background: ${background}
|
||||
}
|
||||
|
||||
.hljs {
|
||||
padding: 0em
|
||||
}</style>
|
||||
<script src="highlight.min.js"></script>
|
||||
<script src="jquery.min.js"></script>
|
||||
</head>
|
||||
<body class="book toc2 toc-left">
|
||||
<div id="header"><%if(isNotEmpty(projectName)){%><h1>${projectName}</h1><%}%>
|
||||
<div id="toc" class="toc2">
|
||||
<div id="book-search-input"><input id="search" type="text" placeholder="Type to search"></div>
|
||||
<div id="toctitle"><span>API Reference</span></div>
|
||||
<ul id="accordion" class="sectlevel1"><%for(api in apiDocList){%><%if(apiLP.first){%>
|
||||
<li><a class="dd" href="${alias}.html#header">${api.order}. ${htmlEscape(api.desc)}</a>
|
||||
<ul class="sectlevel2" style="display: none"><%for(doc in api.list){%>
|
||||
<li><%if(doc.deprecated){%><a href="${alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. <span
|
||||
class="line-through">${htmlEscape(doc.desc)}</span></a><%}else{%><a
|
||||
href="${alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. ${htmlEscape(doc.desc)}</a><%}%>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}else{%>
|
||||
<li><a class="dd" href="${api.alias}.html#header">${api.order}. ${htmlEscape(api.desc)}</a>
|
||||
<ul class="sectlevel2" style="display: none"><%for(doc in api.list){%>
|
||||
<li><%if(doc.deprecated){%><a href="${api.alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. <span
|
||||
class="line-through">${htmlEscape(doc.desc)}</span></a><%}else{%><a
|
||||
href="${api.alias}.html#_${api.order}_${doc.order}_${doc.desc}">${api.order}.${doc.order}. ${htmlEscape(doc.desc)}</a><%}%>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}%><%}%><%if(isNotEmpty(errorCodeList)){%>
|
||||
<li class="open"><a href="error.html#header">${apiDocList.~size+1}. ${errorListTitle}</a>
|
||||
<ul class="sectlevel2" style="display: block">
|
||||
<li><a href="error.html#_${apiDocList.~size+1}_1_${errorListTitle}">${apiDocList.~size+1}.1. ${errorListTitle}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<%}%><%if(isNotEmpty(dictList)){%>
|
||||
<li><a class="dd" href="dict.html#_dict_list">${dictListOrder}. ${dictListTitle}</a>
|
||||
<ul class="sectlevel2"><%for(dict in dictList){%>
|
||||
<li><a href="dict.html#_${dictListOrder}_${dict.order}_${dict.title}">${dictListOrder}.${dict.order}. ${dict.title}</a>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content"><%if(isNotEmpty(errorCodeList)){%>
|
||||
<div class="sect1"><h2 id="_error_code_list"><a class="anchor" href="#_error_code_list"></a><a class="link"
|
||||
href="#_error_code_list">${apiDocList.~size+1}. ${errorListTitle}</a>
|
||||
</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="sect2"><h3 id="_${apiDocList.~size+1}_1_${errorListTitle}"><a class="anchor"
|
||||
href="#_${apiDocList.~size+1}_1_${errorListTitle}"></a><a
|
||||
class="link" href="#_${apiDocList.~size+1}_1_${errorListTitle}">${apiDocList.~size+1}.1. ${errorListTitle}</a>
|
||||
</h3>
|
||||
<table class="tableblock frame-all grid-all spread">
|
||||
<colgroup>
|
||||
<col style="width: 50%;">
|
||||
<col style="width: 50%;">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="tableblock halign-left valign-top">Error code</th>
|
||||
<th class="tableblock halign-left valign-top">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><%for(error in errorCodeList){%>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${error.value}</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">${htmlEscape(error.desc)}</p></td>
|
||||
</tr>
|
||||
<%}%>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%}%>
|
||||
<footer class="page-footer"><span class="copyright">Generated by smart-doc at ${createTime}</span><span
|
||||
class="footer-modification">Suggestions,contact,support and error reporting on<a
|
||||
href="https://gitee.com/smart-doc-team/smart-doc" target="_blank"> Gitee</a> or<a
|
||||
href="https://github.com/smart-doc-group/smart-doc.git" target="_blank"> Github</a></span></footer>
|
||||
</div>
|
||||
<script src="search.js?v=${version}"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
|
@ -18,7 +118,7 @@
|
|||
}
|
||||
};
|
||||
new Accordion($('#accordion'), false);
|
||||
hljs.initHighlightingOnLoad()
|
||||
hljs.highlightAll()
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -15,7 +15,7 @@ $(function () {
|
|||
}
|
||||
};
|
||||
new Accordion($('#accordion'), false);
|
||||
hljs.initHighlightingOnLoad();
|
||||
hljs.highlightAll();
|
||||
});
|
||||
|
||||
$("[contenteditable=plaintext-only]").on('blur', function (e) {
|
||||
|
@ -182,7 +182,12 @@ function getInputData(element, returnFormDate) {
|
|||
formData.append(name, $(input)[0].files[0]);
|
||||
} else {
|
||||
const val = $(input).val();
|
||||
formData.append(name, val);
|
||||
if (isValidUrl(val)) {
|
||||
formData.append(name, encodeURI(val));
|
||||
} else {
|
||||
// support chinese
|
||||
formData.append(name, encodeURIComponent(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -277,10 +282,12 @@ function toCurl(request) {
|
|||
if (request.url.indexOf('https') == 0) {
|
||||
cmd.push("-k");
|
||||
}
|
||||
|
||||
// append Content-Type
|
||||
if (request.data && request.data.length > 0) {
|
||||
if (request.contentType) {
|
||||
cmd.push("-H");
|
||||
cmd.push("'Content-Type: application/json; charset=utf-8'");
|
||||
cmd.push("'Content-Type:");
|
||||
cmd.push(request.contentType+"'");
|
||||
}
|
||||
// append request headers
|
||||
let headerValue;
|
||||
|
@ -310,10 +317,39 @@ function toCurl(request) {
|
|||
}
|
||||
cmd.push(url);
|
||||
// append data
|
||||
if (request.data && request.data.length > 0) {
|
||||
|
||||
if (typeof request.data == 'object') {
|
||||
let index = 0;
|
||||
const bodyData = [];
|
||||
bodyData.push("\"")
|
||||
for (let key in request.data) {
|
||||
if (Object.prototype.hasOwnProperty.call(request.data, key)) {
|
||||
if (index===0){
|
||||
bodyData.push(key);
|
||||
bodyData.push("=");
|
||||
bodyData.push(request.data[key]);
|
||||
} else {
|
||||
bodyData.push("&")
|
||||
bodyData.push(key);
|
||||
bodyData.push("=");
|
||||
bodyData.push(request.data[key]);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
bodyData.push("\"");
|
||||
let bodyStr = ""
|
||||
bodyData.forEach(function (item) {
|
||||
bodyStr += item;
|
||||
});
|
||||
cmd.push("--data");
|
||||
cmd.push(bodyStr);
|
||||
} else if (request.data && request.data.length > 0) {
|
||||
// append json data
|
||||
cmd.push("--data");
|
||||
cmd.push("'" + request.data + "'");
|
||||
}
|
||||
|
||||
let curlCmd = "";
|
||||
cmd.forEach(function (item) {
|
||||
curlCmd += item + " ";
|
||||
|
@ -325,3 +361,13 @@ function toCurl(request) {
|
|||
function isEmpty(obj) {
|
||||
return obj === undefined || obj === null || new String(obj).trim() === '';
|
||||
}
|
||||
|
||||
function isValidUrl(_string) {
|
||||
let urlString;
|
||||
try {
|
||||
urlString = new URL(_string);
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
return urlString.protocol === "http:" || urlString.protocol === "https:" ;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue