Merge pull request #136 from chenqi146/dev

feat: add group and tag
This commit is contained in:
shalousun 2021-08-18 23:09:04 +08:00 committed by GitHub
commit 76be2eb854
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 991 additions and 118 deletions

View File

@ -31,6 +31,7 @@ import com.power.doc.template.SpringBootDocBuildTemplate;
import com.thoughtworks.qdox.JavaProjectBuilder; import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static com.power.doc.constants.DocGlobalConstants.*; import static com.power.doc.constants.DocGlobalConstants.*;
@ -71,6 +72,7 @@ public class AdocDocBuilder {
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder); List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
if (config.isAllInOne()) { if (config.isAllInOne()) {
String docName = builderTemplate.allInOneDocName(config,INDEX_DOC,".doc"); String docName = builderTemplate.allInOneDocName(config,INDEX_DOC,".doc");
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_ADOC_TPL, docName); builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_ADOC_TPL, docName);
} else { } else {
builderTemplate.buildApiDoc(apiDocList, config, API_DOC_ADOC_TPL, API_EXTENSION); builderTemplate.buildApiDoc(apiDocList, config, API_DOC_ADOC_TPL, API_EXTENSION);

View File

@ -31,6 +31,7 @@ import com.power.doc.template.SpringBootDocBuildTemplate;
import com.thoughtworks.qdox.JavaProjectBuilder; import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static com.power.doc.constants.DocGlobalConstants.*; import static com.power.doc.constants.DocGlobalConstants.*;
@ -70,6 +71,7 @@ public class ApiDocBuilder {
if (config.isAllInOne()) { if (config.isAllInOne()) {
String version = config.isCoverOld() ? "" : "-V" + DateTimeUtil.long2Str(System.currentTimeMillis(), DATE_FORMAT); String version = config.isCoverOld() ? "" : "-V" + DateTimeUtil.long2Str(System.currentTimeMillis(), DATE_FORMAT);
String docName = builderTemplate.allInOneDocName(config,"AllInOne" + version + ".md",".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); builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_MD_TPL, docName);
} else { } else {
builderTemplate.buildApiDoc(apiDocList, config, API_DOC_MD_TPL, API_EXTENSION); builderTemplate.buildApiDoc(apiDocList, config, API_DOC_MD_TPL, API_EXTENSION);

View File

@ -169,6 +169,7 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
apiDoc1.setList(new ArrayList<>(0)); apiDoc1.setList(new ArrayList<>(0));
apiDoc1.setLink("error_code_list"); apiDoc1.setLink("error_code_list");
apiDoc1.setAlias("error"); apiDoc1.setAlias("error");
apiDoc1.setGroup(apiDoc1.getDesc());
apiDocs.add(apiDoc1); apiDocs.add(apiDoc1);
} }
// set dict list // set dict list
@ -178,6 +179,7 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
apiDoc1.setLink("dict_list"); apiDoc1.setLink("dict_list");
apiDoc1.setAlias("dict"); apiDoc1.setAlias("dict");
apiDoc1.setDesc(titleMap.get(TemplateVariable.DICT_LIST_TITLE.getVariable())); apiDoc1.setDesc(titleMap.get(TemplateVariable.DICT_LIST_TITLE.getVariable()));
apiDoc1.setGroup(apiDoc1.getDesc());
List<ApiMethodDoc> methodDocs = new ArrayList<>(); List<ApiMethodDoc> methodDocs = new ArrayList<>();
for (ApiDocDict apiDocDict : apiDocDictList) { for (ApiDocDict apiDocDict : apiDocDictList) {
ApiMethodDoc methodDoc = new ApiMethodDoc(); ApiMethodDoc methodDoc = new ApiMethodDoc();

View File

@ -27,13 +27,14 @@ import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig; import com.power.doc.model.ApiConfig;
import com.power.doc.model.ApiDoc; import com.power.doc.model.ApiDoc;
import com.power.doc.template.IDocBuildTemplate; import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.template.SpringBootDocBuildTemplate;
import com.power.doc.utils.BeetlTemplateUtil; import com.power.doc.utils.BeetlTemplateUtil;
import com.thoughtworks.qdox.JavaProjectBuilder; import com.thoughtworks.qdox.JavaProjectBuilder;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.beetl.core.Template; import org.beetl.core.Template;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import static com.power.doc.constants.DocGlobalConstants.*; import static com.power.doc.constants.DocGlobalConstants.*;
@ -74,6 +75,7 @@ public class HtmlApiDocBuilder {
Template indexCssTemplate = BeetlTemplateUtil.getByName(ALL_IN_ONE_CSS); 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);
if (config.isAllInOne()) { if (config.isAllInOne()) {
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
if (config.isCreateDebugPage()) { if (config.isCreateDebugPage()) {
INDEX_HTML = DEBUG_PAGE_ALL_TPL; INDEX_HTML = DEBUG_PAGE_ALL_TPL;
if (StringUtils.isNotEmpty(config.getAllInOneDocFileName())) { if (StringUtils.isNotEmpty(config.getAllInOneDocFileName())) {

View File

@ -80,6 +80,7 @@ public class TornaBuilder {
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder); ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework()); IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder); List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
buildTorna(apiDocList, config, javaProjectBuilder); buildTorna(apiDocList, config, javaProjectBuilder);
} }
@ -91,23 +92,34 @@ public class TornaBuilder {
* @param builder JavaProjectBuilder * @param builder JavaProjectBuilder
*/ */
public static void buildTorna(List<ApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) { public static void buildTorna(List<ApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) {
TornaApi tornaApi = new TornaApi(); TornaApi tornaApi = new TornaApi();
tornaApi.setAuthor(StringUtil.isEmpty(apiConfig.getAuthor()) ? System.getProperty("user.name") : apiConfig.getAuthor()); tornaApi.setAuthor(StringUtil.isEmpty(apiConfig.getAuthor()) ? System.getProperty("user.name") : apiConfig.getAuthor());
Apis api; Apis api;
List<Apis> apisList = new ArrayList<>(); List<Apis> groupApiList = new ArrayList<>();
//Convert ApiDoc to Apis //Convert ApiDoc to Apis
for (ApiDoc a : apiDocs) { 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 = new Apis();
api.setName(StringUtils.isBlank(a.getDesc()) ? a.getName() : a.getDesc()); api.setName(StringUtils.isBlank(groupApi.getDesc()) ? groupApi.getName() : groupApi.getDesc());
api.setItems(buildApis(a.getList(), TornaUtil.setDebugEnv(apiConfig, tornaApi))); api.setAuthor(tornaApi.getAuthor());
api.setOrderIndex(groupApi.getOrder());
api.setIsFolder(TornaConstants.YES); api.setIsFolder(TornaConstants.YES);
api.setAuthor(a.getAuthor()); api.setItems(apisList);
api.setOrderIndex(a.getOrder()); groupApiList.add(api);
apisList.add(api);
} }
tornaApi.setCommonErrorCodes(buildErrorCode(apiConfig)); tornaApi.setCommonErrorCodes(buildErrorCode(apiConfig));
tornaApi.setApis(apisList); tornaApi.setApis(groupApiList);
tornaApi.setIsReplace(apiConfig.isReplace() ? 1 : 0);
//Build push document information //Build push document information
Map<String, String> requestJson = TornaConstants.buildParams(PUSH, new Gson().toJson(tornaApi), apiConfig); Map<String, String> requestJson = TornaConstants.buildParams(PUSH, new Gson().toJson(tornaApi), apiConfig);
//Push dictionary information //Push dictionary information

View File

@ -119,4 +119,9 @@ public interface DocTags {
* response tag @since 2.2.0 * response tag @since 2.2.0
*/ */
String API_RESPONSE = "response"; String API_RESPONSE = "response";
/**
* custom @tag
*/
String TAG = "tag";
} }

View File

@ -26,8 +26,10 @@ import com.power.common.util.CollectionUtil;
import com.power.doc.constants.DocLanguage; import com.power.doc.constants.DocLanguage;
import com.power.doc.model.rpc.RpcApiDependency; import com.power.doc.model.rpc.RpcApiDependency;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
/** /**
* Description: * Description:
@ -351,12 +353,16 @@ public class ApiConfig {
*/ */
private String framework; private String framework;
private List<ApiGroup> groups;
/** /**
* replace old document while push to torna * replace old document while push to torna
* @since 2.2.4 * @since 2.2.4
*/ */
private boolean replace; private boolean replace;
public String getPathPrefix() { public String getPathPrefix() {
return pathPrefix; return pathPrefix;
} }
@ -450,6 +456,20 @@ public class ApiConfig {
this.requestHeaders.forEach(header -> header.setDesc(header.getDesc() + "(Global)")); 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() { public List<ApiReqParam> getRequestParams() {
return requestParams; return requestParams;
} }

View File

@ -25,6 +25,7 @@ package com.power.doc.model;
import com.power.common.util.StringUtil; import com.power.common.util.StringUtil;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -35,7 +36,7 @@ public class ApiDoc implements Comparable<ApiDoc> {
* *
* @since 1.7+ * @since 1.7+
*/ */
public int order; public Integer order;
/** /**
* controller name * controller name
@ -49,6 +50,26 @@ public class ApiDoc implements Comparable<ApiDoc> {
*/ */
private String alias; 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 * List of method doc
*/ */
@ -66,6 +87,16 @@ public class ApiDoc implements Comparable<ApiDoc> {
private String author; private String author;
/**
* if this is group, then is true
*/
private boolean isFolder;
/**
* children
*/
private List<ApiDoc> childrenApiDocs = new ArrayList<>();
public String getAuthor() { public String getAuthor() {
return author; return author;
} }
@ -98,11 +129,11 @@ public class ApiDoc implements Comparable<ApiDoc> {
this.desc = desc; this.desc = desc;
} }
public int getOrder() { public Integer getOrder() {
return order; return order;
} }
public void setOrder(int order) { public void setOrder(Integer order) {
this.order = order; this.order = order;
} }
@ -114,6 +145,14 @@ public class ApiDoc implements Comparable<ApiDoc> {
this.alias = alias; this.alias = alias;
} }
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public String getLink() { public String getLink() {
if (StringUtil.isNotEmpty(link)) { if (StringUtil.isNotEmpty(link)) {
return link; return link;
@ -125,6 +164,38 @@ public class ApiDoc implements Comparable<ApiDoc> {
this.link = link; 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 @Override
public int compareTo(ApiDoc o) { public int compareTo(ApiDoc o) {
if (Objects.nonNull(o.getDesc())) { if (Objects.nonNull(o.getDesc())) {
@ -133,6 +204,31 @@ public class ApiDoc implements Comparable<ApiDoc> {
return name.compareTo(o.getName()); 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 @Override
public String toString() { public String toString() {

View File

@ -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;
}
}

View File

@ -33,7 +33,7 @@ import java.util.Map;
/** /**
* java api method info model. * java api method info model.
*/ */
public class ApiMethodDoc implements Serializable { public class ApiMethodDoc implements Serializable, Cloneable {
private static final long serialVersionUID = 7211922919532562867L; private static final long serialVersionUID = 7211922919532562867L;
@ -202,6 +202,11 @@ public class ApiMethodDoc implements Serializable {
*/ */
private boolean listParam = false; private boolean listParam = false;
/**
* tags
*/
private String[] tags;
public Integer getIsRequestArray() { public Integer getIsRequestArray() {
return isRequestArray; return isRequestArray;
} }
@ -462,6 +467,15 @@ public class ApiMethodDoc implements Serializable {
this.page = page; this.page = page;
} }
public String[] getTags() {
return tags;
}
public ApiMethodDoc setTags(String[] tags) {
this.tags = tags;
return this;
}
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder("{"); final StringBuilder sb = new StringBuilder("{");
@ -510,4 +524,13 @@ public class ApiMethodDoc implements Serializable {
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@Override
public ApiMethodDoc clone() {
try {
return (ApiMethodDoc) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("clone apiMethodDoc is error", e);
}
}
} }

View File

@ -35,6 +35,8 @@ import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaType; import com.thoughtworks.qdox.model.JavaType;
import java.util.*; 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.DocGlobalConstants.NO_COMMENTS_FOUND;
import static com.power.doc.constants.DocTags.IGNORE_RESPONSE_BODY_ADVICE; import static com.power.doc.constants.DocTags.IGNORE_RESPONSE_BODY_ADVICE;
@ -82,7 +84,14 @@ public interface IDocBuildTemplate<T> {
apiDoc.setName(controllerName); apiDoc.setName(controllerName);
apiDoc.setAuthor(classAuthor); apiDoc.setAuthor(classAuthor);
apiDoc.setAlias(controllerName); apiDoc.setAlias(controllerName);
apiDoc.setFolder(true);
apiDoc.setPackageName(cls.getPackage().getName());
//apiDoc.setAuthor(); //apiDoc.setAuthor();
// handle class tags
List<DocletTag> classTags = cls.getTagsByName(DocTags.TAG);
apiDoc.setTags(classTags.stream().map(DocletTag::getValue).toArray(String[]::new));
if (isUseMD5) { if (isUseMD5) {
String name = DocUtil.generateId(apiDoc.getName()); String name = DocUtil.generateId(apiDoc.getName());
apiDoc.setAlias(name); apiDoc.setAlias(name);
@ -94,6 +103,54 @@ public interface IDocBuildTemplate<T> {
} }
/**
* handle group api docs
*
* @author cqmike
* @param apiDocList
* @param apiConfig
*/
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());
groups.forEach(group -> {
ApiDoc groupApiDoc = ApiDoc.buildGroupApiDoc(group.getName());
groupApiDoc.setOrder(order.getAndIncrement());
finalApiDocs.add(groupApiDoc);
apiDocList.forEach(doc -> {
if (!DocUtil.isMatch(group.getApis(), doc.getPackageName())) {
defaultGroup.getChildrenApiDocs().add(doc);
doc.setOrder(defaultGroup.getChildrenApiDocs().size());
return;
}
groupApiDoc.getChildrenApiDocs().add(doc);
doc.setOrder(groupApiDoc.getChildrenApiDocs().size());
doc.setGroup(group.getName());
if (StringUtil.isEmpty(group.getPaths())) {
return;
}
List<ApiMethodDoc> methodDocs = doc.getList().stream()
.filter(l -> DocPathUtil.matches(l.getPath(), group.getPaths(), null))
.collect(Collectors.toList());
doc.setList(methodDocs);
});
});
return finalApiDocs;
}
default List<ApiParam> buildReturnApiParams(DocJavaMethod docJavaMethod, ProjectDocConfigBuilder projectBuilder) { default List<ApiParam> buildReturnApiParams(DocJavaMethod docJavaMethod, ProjectDocConfigBuilder projectBuilder) {
JavaMethod method = docJavaMethod.getJavaMethod(); JavaMethod method = docJavaMethod.getJavaMethod();
if (method.getReturns().isVoid() && Objects.isNull(projectBuilder.getApiConfig().getResponseBodyAdvice())) { if (method.getReturns().isVoid() && Objects.isNull(projectBuilder.getApiConfig().getResponseBodyAdvice())) {

View File

@ -37,6 +37,7 @@ import com.power.doc.model.request.RequestMapping;
import com.power.doc.utils.*; import com.power.doc.utils.*;
import com.thoughtworks.qdox.model.*; import com.thoughtworks.qdox.model.*;
import com.thoughtworks.qdox.model.expression.AnnotationValue; import com.thoughtworks.qdox.model.expression.AnnotationValue;
import org.apache.commons.lang3.ArrayUtils;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -88,6 +89,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
List<ApiMethodDoc> apiMethodDocs = buildControllerMethod(cls, apiConfig, projectBuilder); List<ApiMethodDoc> apiMethodDocs = buildControllerMethod(cls, apiConfig, projectBuilder);
this.handleApiDoc(cls, apiDocList, apiMethodDocs, order, apiConfig.isMd5EncryptedHtmlName()); this.handleApiDoc(cls, apiDocList, apiMethodDocs, order, apiConfig.isMd5EncryptedHtmlName());
} }
// handle TagsApiDoc
apiDocList = handleTagsApiDoc(apiDocList);
// sort // sort
if (apiConfig.isSortByTitle()) { if (apiConfig.isSortByTitle()) {
Collections.sort(apiDocList); Collections.sort(apiDocList);
@ -100,6 +104,72 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
return apiDocList; return apiDocList;
} }
/**
* handle tags to api doc
* copy the same tag
*
* @author cqmike
* @param apiDocList
*/
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 @Override
public ApiDoc getSingleApiData(ProjectDocConfigBuilder projectBuilder, String apiClassName) { public ApiDoc getSingleApiData(ProjectDocConfigBuilder projectBuilder, String apiClassName) {
return null; return null;
@ -179,6 +249,11 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
} else { } else {
apiMethodDoc.setGroup(group); apiMethodDoc.setGroup(group);
} }
// handle tags
List<DocletTag> tags = method.getTagsByName(DocTags.TAG);
apiMethodDoc.setTags(tags.stream().map(DocletTag::getValue).toArray(String[]::new));
methodOrder++; methodOrder++;
apiMethodDoc.setName(method.getName()); apiMethodDoc.setName(method.getName());
apiMethodDoc.setOrder(methodOrder); apiMethodDoc.setOrder(methodOrder);
@ -225,7 +300,6 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
apiMethodDoc.setQueryParams(apiMethodReqParam.getQueryParams()); apiMethodDoc.setQueryParams(apiMethodReqParam.getQueryParams());
apiMethodDoc.setRequestParams(apiMethodReqParam.getRequestParams()); apiMethodDoc.setRequestParams(apiMethodReqParam.getRequestParams());
} }
List<ApiReqParam> allApiReqHeaders; List<ApiReqParam> allApiReqHeaders;
if (this.configApiReqParams != null) { if (this.configApiReqParams != null) {
@ -235,38 +309,26 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
final List<ApiReqParam> headerParamList = reqParamMap.getOrDefault(ApiReqParamInTypeEnum.HEADER.getValue(), Collections.emptyList()); final List<ApiReqParam> headerParamList = reqParamMap.getOrDefault(ApiReqParamInTypeEnum.HEADER.getValue(), Collections.emptyList());
allApiReqHeaders = Stream.of(apiReqHeaders, headerParamList).filter(Objects::nonNull) allApiReqHeaders = Stream.of(apiReqHeaders, headerParamList).filter(Objects::nonNull)
.flatMap(Collection::stream).distinct().collect(Collectors.toList()); .flatMap(Collection::stream).distinct().collect(Collectors.toList());
// query param handle
// final List<ApiReqParam> queryParamList = reqParamMap.getOrDefault(ApiReqParamInTypeEnum.QUERY.getValue(), Collections.emptyList());
// AtomicInteger querySize = apiMethodDoc.getQueryParams() == null ? new AtomicInteger(1)
// : new AtomicInteger(apiMethodDoc.getQueryParams().size() + 1);
// final List<ApiParam> defaultQueryList = queryParamList.stream()
// .map(param -> ApiReqParam.convertToApiParam(param).setQueryParam(true).setId(querySize.getAndIncrement()))
// .collect(Collectors.toList());
//
// apiMethodDoc.setQueryParams(Stream.of(apiMethodDoc.getQueryParams(), defaultQueryList).filter(Objects::nonNull)
// .flatMap(Collection::stream).distinct().collect(Collectors.toList()));
//
// // path param handle
// final List<ApiReqParam> pathParamList = reqParamMap.getOrDefault(ApiReqParamInTypeEnum.PATH.getValue(), Collections.emptyList());
// AtomicInteger pathSize = apiMethodDoc.getPathParams() == null ? new AtomicInteger(1)
// : new AtomicInteger(apiMethodDoc.getPathParams().size() + 1);
// final List<ApiParam> defaultPathList = pathParamList.stream()
// .map(param -> ApiReqParam.convertToApiParam(param).setPathParam(true).setId(pathSize.getAndIncrement()))
// .collect(Collectors.toList());
//
// apiMethodDoc.setPathParams(Stream.of(apiMethodDoc.getPathParams(), defaultPathList).filter(Objects::nonNull)
// .flatMap(Collection::stream).distinct().collect(Collectors.toList()));
} else { } else {
allApiReqHeaders = apiReqHeaders.stream().filter(param -> filterPath(requestMapping, param)).collect(Collectors.toList()); allApiReqHeaders = apiReqHeaders.stream().filter(param -> filterPath(requestMapping, param)).collect(Collectors.toList());
} }
// allApiReqParams.removeIf(apiReqHeader -> filterPath(requestMapping, apiReqHeader));
//reduce create in template //reduce create in template
apiMethodDoc.setHeaders(this.createDocRenderHeaders(allApiReqHeaders, apiConfig.isAdoc())); apiMethodDoc.setHeaders(this.createDocRenderHeaders(allApiReqHeaders, apiConfig.isAdoc()));
apiMethodDoc.setRequestHeaders(allApiReqHeaders); 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 // build request json
ApiRequestExample requestExample = buildReqJson(docJavaMethod, apiMethodDoc, requestMapping.getMethodType(), ApiRequestExample requestExample = buildReqJson(docJavaMethod, apiMethodDoc, requestMapping.getMethodType(),
projectBuilder); projectBuilder);
@ -315,12 +377,10 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
Map<String, String> pathParamsMap = new LinkedHashMap<>(); Map<String, String> pathParamsMap = new LinkedHashMap<>();
Map<String, String> queryParamsMap = new LinkedHashMap<>(); Map<String, String> queryParamsMap = new LinkedHashMap<>();
Stream.of(apiMethodDoc.getPathParams()).filter(Objects::nonNull) apiMethodDoc.getPathParams().stream().filter(Objects::nonNull).filter(ApiParam::isConfigParam)
.flatMap(pl -> pl.stream().filter(ApiParam::isConfigParam))
.forEach(param -> pathParamsMap.put(param.getField(), param.getValue())); .forEach(param -> pathParamsMap.put(param.getField(), param.getValue()));
Stream.of(apiMethodDoc.getQueryParams()).filter(Objects::nonNull) apiMethodDoc.getQueryParams().stream().filter(Objects::nonNull).filter(ApiParam::isConfigParam)
.flatMap(pl -> pl.stream().filter(ApiParam::isConfigParam))
.forEach(param -> queryParamsMap.put(param.getField(), param.getValue())); .forEach(param -> queryParamsMap.put(param.getField(), param.getValue()));
List<JavaAnnotation> methodAnnotations = method.getAnnotations(); List<JavaAnnotation> methodAnnotations = method.getAnnotations();
@ -407,6 +467,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
String[] globGicName = DocClassUtil.getSimpleGicName(gicTypeName); String[] globGicName = DocClassUtil.getSimpleGicName(gicTypeName);
String comment = this.paramCommentResolve(paramsComments.get(paramName)); String comment = this.paramCommentResolve(paramsComments.get(paramName));
String mockValue = createMockValue(paramsComments, paramName, typeName, simpleTypeName); String mockValue = createMockValue(paramsComments, paramName, typeName, simpleTypeName);
if (queryParamsMap.containsKey(paramName)) {
mockValue = queryParamsMap.get(paramName);
}
if (requestFieldToUnderline) { if (requestFieldToUnderline) {
paramName = StringUtil.camelToUnderline(paramName); paramName = StringUtil.camelToUnderline(paramName);
} }
@ -466,6 +529,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE); Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE);
mockValue = StringUtil.removeQuotes(String.valueOf(value)); mockValue = StringUtil.removeQuotes(String.valueOf(value));
} }
if (pathParamsMap.containsKey(paramName)) {
mockValue = pathParamsMap.get(paramName);
}
pathParamsMap.put(paramName, mockValue); pathParamsMap.put(paramName, mockValue);
paramAdded = true; paramAdded = true;
} }
@ -896,9 +962,15 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
for (ApiParam param : paramList) { for (ApiParam param : paramList) {
param.setValue(StringUtil.removeDoubleQuotes(param.getValue())); param.setValue(StringUtil.removeDoubleQuotes(param.getValue()));
if (param.isPathParam()) { if (param.isPathParam()) {
if (pathReqParamMap.containsKey(param.getField())) {
param.setConfigParam(true).setValue(pathReqParamMap.get(param.getField()).getValue());
}
param.setId(pathParams.size() + 1); param.setId(pathParams.size() + 1);
pathParams.add(param); pathParams.add(param);
} else if (param.isQueryParam() || requestBodyCounter < 1) { } 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); param.setId(queryParams.size() + 1);
queryParams.add(param); queryParams.add(param);
} else { } else {

View File

@ -45,7 +45,7 @@ import java.util.stream.Collectors;
*/ */
public class DocUtil { 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 faker = new Faker(new Locale("smart-doc_language"));
private static Faker enFaker = new Faker(new Locale("en-US")); private static Faker enFaker = new Faker(new Locale("en-US"));
@ -287,6 +287,27 @@ public class DocUtil {
return builder.toString(); return builder.toString();
} }
/**
* // /detail/{id:[a-zA-Z0-9]{3}}/{name:[a-zA-Z0-9]{3}}
* 去除正则表达式
* @param str
* @return
*/
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 * handle spring mvc method
* *

View File

@ -17,26 +17,30 @@ for(revisionLog in revisionLogList){
<% <%
for(api in apiDocList){ for(apiGroup in apiDocList){
%> %>
== ${api.desc} == ${apiGroup.group}
<%
for(api in apiGroup.childrenApiDocs){
%>
=== ${api.desc}
<% <%
for(doc in api.list){ for(doc in api.list){
%> %>
<%if(doc.deprecated){%> <%if(doc.deprecated){%>
=== [line-through]#${doc.desc}# ==== [line-through]#${doc.desc}#
<%}else{%> <%}else{%>
=== ${doc.desc} ==== ${doc.desc}
<%}%> <%}%>
*URL:* ${doc.url} *URL:* `${doc.url}`
*Type:* ${doc.type} *Type:* `${doc.type}`
<%if(isNotEmpty(doc.author)){%> <%if(isNotEmpty(doc.author)){%>
*Author:* ${doc.author} *Author:* ${doc.author}
<%}%> <%}%>
*Content-Type:* ${doc.contentType} *Content-Type:* `${doc.contentType}`
<%if(isNotEmpty(doc.headers)){%> <%if(isNotEmpty(doc.headers)){%>
*Request-headers:* *Request-headers:*
@ -122,6 +126,7 @@ ${doc.responseUsage}
---- ----
<%}%> <%}%>
<% } %>
<% } %> <% } %>
<% } %> <% } %>
<%if(isNotEmpty(errorCodeList)){%> <%if(isNotEmpty(errorCodeList)){%>

View File

@ -14,7 +14,11 @@ ${revisionLog.version}|${revisionLog.revisionTime}|${revisionLog.status}|${revis
<% <%
for(api in apiDocList){ for(apiGroup in apiDocList){
%>
# ${apiGroup.group}
<%
for(api in apiGroup.childrenApiDocs){
%> %>
## ${api.desc} ## ${api.desc}
<% <%
@ -106,6 +110,7 @@ ${doc.responseUsage}
``` ```
<%}%> <%}%>
<% } %>
<% } %> <% } %>
<% } %> <% } %>
<%if(isNotEmpty(errorCodeList)){%> <%if(isNotEmpty(errorCodeList)){%>

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,12 @@
let api = []; let api = [];
<%for(api in apiDocList){%> <%for(apiGroup in apiDocList) {%>
api.push({ api.push({
name: '${apiGroup.group}',
order: '${apiGroup.order}',
list: []
})
<%for(api in apiGroup.childrenApiDocs) {%>
api[${apiGroupLP.dataIndex}].list.push({
alias: '${api.alias}', alias: '${api.alias}',
order: '${api.order}', order: '${api.order}',
link: '${removeLineBreaks(api.link)}', link: '${removeLineBreaks(api.link)}',
@ -8,12 +14,13 @@ api.push({
list: [] list: []
}) })
<%for(doc in api.list) {%> <%for(doc in api.list) {%>
api[${apiLP.dataIndex}].list.push({ api[${apiGroupLP.dataIndex}].list[${apiLP.dataIndex}].list.push({
order: '${doc.order}', order: '${doc.order}',
desc: '${removeLineBreaks(doc.desc)}', desc: '${removeLineBreaks(doc.desc)}',
}); });
<%}%> <%}%>
<%}%> <%}%>
<%}%>
document.onkeydown = keyDownSearch; document.onkeydown = keyDownSearch;
function keyDownSearch(e) { function keyDownSearch(e) {
const theEvent = e; const theEvent = e;
@ -21,38 +28,52 @@ function keyDownSearch(e) {
if (code == 13) { if (code == 13) {
const search = document.getElementById('search'); const search = document.getElementById('search');
const searchValue = search.value; const searchValue = search.value;
let searchArr = []; let searchGroup = [];
for (let i = 0; i < api.length; i++) { for (let i = 0; i < api.length; i++) {
let apiData = api[i];
const desc = apiData.desc; let apiGroup = api[i];
if (desc.indexOf(searchValue) > -1) {
searchArr.push({ let searchArr = [];
order: apiData.order, for (let i = 0; i < apiGroup.list.length; i++) {
desc: apiData.desc, let apiData = apiGroup.list[i];
link: apiData.link, const desc = apiData.desc;
list: apiData.list if (desc.indexOf(searchValue) > -1) {
}); searchArr.push({
} else {
let methodList = apiData.list || [];
let methodListTemp = [];
for (let j = 0; j < methodList.length; j++) {
const methodData = methodList[j];
const methodDesc = methodData.desc;
if (methodDesc.indexOf(searchValue) > -1) {
methodListTemp.push(methodData);
break;
}
}
if (methodListTemp.length > 0) {
const data = {
order: apiData.order, order: apiData.order,
desc: apiData.desc, desc: apiData.desc,
link: apiData.link, link: apiData.link,
list: methodListTemp list: apiData.list
}; });
searchArr.push(data); } else {
let methodList = apiData.list || [];
let methodListTemp = [];
for (let j = 0; j < methodList.length; j++) {
const methodData = methodList[j];
const methodDesc = methodData.desc;
if (methodDesc.indexOf(searchValue) > -1) {
methodListTemp.push(methodData);
break;
}
}
if (methodListTemp.length > 0) {
const data = {
order: apiData.order,
desc: apiData.desc,
link: apiData.link,
list: methodListTemp
};
searchArr.push(data);
}
} }
} }
if (searchArr.length === 0) {
continue;
}
searchGroup.push({
name: apiGroup.name,
order: apiGroup.order,
list: searchArr
});
} }
let html; let html;
if (searchValue == '') { if (searchValue == '') {
@ -63,7 +84,7 @@ function keyDownSearch(e) {
} else { } else {
const liClass = "open"; const liClass = "open";
const display = "display: block"; const display = "display: block";
html = buildAccordion(searchArr,liClass,display); html = buildAccordion(searchGroup,liClass,display);
document.getElementById('accordion').innerHTML = html; document.getElementById('accordion').innerHTML = html;
} }
const Accordion = function (el, multiple) { const Accordion = function (el, multiple) {
@ -85,18 +106,29 @@ function keyDownSearch(e) {
} }
} }
function buildAccordion(apiData, liClass, display) { function buildAccordion(apiGroups, liClass, display) {
let html = ""; let html = "";
let doc; let doc;
if (apiData.length > 0) { if (apiGroups.length > 0) {
for (let j = 0; j < apiData.length; j++) { for (let i = 0; i < apiGroups.length; i++) {
let apiGroup = apiGroups[i];
html += '<li class="'+liClass+'">'; html += '<li class="'+liClass+'">';
html += '<a class="dd" href="#_' + apiData[j].link + '">' + apiData[j].order + '.&nbsp;' + apiData[j].desc + '</a>'; html += '<a class="dd" href="#_' + apiGroup.name + '">' + apiGroup.order + '.&nbsp;' + apiGroup.name + '</a>';
html += '<ul class="sectlevel2" style="'+display+'">'; html += '<ul class="sectlevel1">';
doc = apiData[j].list;
for (let m = 0; m < doc.length; m++) { let apiData = apiGroup.list;
html += '<li><a href="#_' + apiData[j].order + '_' + doc[m].order + '_' + doc[m].desc + '">' + apiData[j].order + '.' + doc[m].order + '.&nbsp;' + doc[m].desc + '</a> </li>'; for (let j = 0; j < apiData.length; j++) {
html += '<li class="'+liClass+'">';
html += '<a class="dd" href="#_' + apiData[j].link + '">' + apiData[j].order + '.&nbsp;' + apiData[j].desc + '</a>';
html += '<ul class="sectlevel2" style="'+display+'">';
doc = apiData[j].list;
for (let m = 0; m < doc.length; m++) {
html += '<li><a href="#_' + apiData[j].order + '_' + doc[m].order + '_' + doc[m].desc + '">' + apiData[j].order + '.' + doc[m].order + '.&nbsp;' + doc[m].desc + '</a> </li>';
}
html += '</ul>';
html += '</li>';
} }
html += '</ul>'; html += '</ul>';
html += '</li>'; html += '</li>';
} }

View File

@ -102,7 +102,7 @@ public class ApiDocTest {
//OpenApiBuilder.buildOpenApi(config); //OpenApiBuilder.buildOpenApi(config);
HtmlApiDocBuilder.buildApiDoc(config); HtmlApiDocBuilder.buildApiDoc(config);
//RpcTornaBuilder.buildApiDoc(config); //RpcTornaBuilder.buildApiDoc(config);
TornaBuilder.buildApiDoc(config); // TornaBuilder.buildApiDoc(config);
// RpcHtmlBuilder.buildApiDoc(config); // RpcHtmlBuilder.buildApiDoc(config);
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();
DateTimeUtil.printRunTime(end, start); DateTimeUtil.printRunTime(end, start);