mirror of
https://gitee.com/dcren/initializr.git
synced 2025-04-05 17:38:06 +08:00
Project documentation infrastructure
This commit adds support for an `HelpDocument` that can be generated alongside the project. Such document can hold an arbitrary number of sections with pre-defined sections such as "Getting Started" and "Next Steps". A default contributor retrieves the links for requested dependencies and add them to the document. Closes gh-353 Co-authored-by: Madhura Bhave <mbhave@pivotal.io>
This commit is contained in:
parent
2746a3a6e7
commit
924a73310a
@ -19,6 +19,11 @@
|
||||
<artifactId>initializr-metadata</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.samskivert</groupId>
|
||||
<artifactId>jmustache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.spring.initializr</groupId>
|
||||
<artifactId>initializr-generator</artifactId>
|
||||
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import io.spring.initializr.generator.io.text.BulletedSection;
|
||||
import io.spring.initializr.generator.io.text.Section;
|
||||
|
||||
/**
|
||||
* Section that provides links and other important references to get started.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public final class GettingStartedSection extends PreDefinedSection {
|
||||
|
||||
private final BulletedSection<Link> referenceDocs;
|
||||
|
||||
private final BulletedSection<Link> guides;
|
||||
|
||||
private final BulletedSection<Link> additionalLinks;
|
||||
|
||||
GettingStartedSection(MustacheTemplateRenderer templateRenderer) {
|
||||
super("Getting Started");
|
||||
this.referenceDocs = new BulletedSection<>(templateRenderer,
|
||||
"documentation/reference-documentation");
|
||||
this.guides = new BulletedSection<>(templateRenderer, "documentation/guides");
|
||||
this.additionalLinks = new BulletedSection<>(templateRenderer,
|
||||
"documentation/additional-links");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return referenceDocs().isEmpty() && guides().isEmpty()
|
||||
&& additionalLinks().isEmpty() && super.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Section> resolveSubSections(List<Section> sections) {
|
||||
List<Section> allSections = new ArrayList<>();
|
||||
allSections.add(this.referenceDocs);
|
||||
allSections.add(this.guides);
|
||||
allSections.add(this.additionalLinks);
|
||||
allSections.addAll(sections);
|
||||
return allSections;
|
||||
}
|
||||
|
||||
public GettingStartedSection addReferenceDocLink(String href, String description) {
|
||||
this.referenceDocs.addItem(new Link(href, description));
|
||||
return this;
|
||||
}
|
||||
|
||||
public BulletedSection<Link> referenceDocs() {
|
||||
return this.referenceDocs;
|
||||
}
|
||||
|
||||
public GettingStartedSection addGuideLink(String href, String description) {
|
||||
this.guides.addItem(new Link(href, description));
|
||||
return this;
|
||||
}
|
||||
|
||||
public BulletedSection<Link> guides() {
|
||||
return this.guides;
|
||||
}
|
||||
|
||||
public GettingStartedSection addAdditionalLink(String href, String description) {
|
||||
this.additionalLinks.addItem(new Link(href, description));
|
||||
return this;
|
||||
}
|
||||
|
||||
public BulletedSection<Link> additionalLinks() {
|
||||
return this.additionalLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal representation of a link.
|
||||
*/
|
||||
public static class Link {
|
||||
|
||||
private final String href;
|
||||
|
||||
private final String description;
|
||||
|
||||
Link(String href, String description) {
|
||||
this.href = href;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getHref() {
|
||||
return this.href;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import io.spring.initializr.generator.io.text.MustacheSection;
|
||||
import io.spring.initializr.generator.io.text.Section;
|
||||
|
||||
/**
|
||||
* Project's help document intended to give additional references to the users. Contains a
|
||||
* getting started section, additional sections and a next steps section.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class HelpDocument {
|
||||
|
||||
private final MustacheTemplateRenderer templateRenderer;
|
||||
|
||||
private final GettingStartedSection gettingStarted;
|
||||
|
||||
private final PreDefinedSection nextSteps;
|
||||
|
||||
private final LinkedList<Section> sections = new LinkedList<>();
|
||||
|
||||
public HelpDocument(MustacheTemplateRenderer templateRenderer) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.gettingStarted = new GettingStartedSection(templateRenderer);
|
||||
this.nextSteps = new PreDefinedSection("Next Steps");
|
||||
}
|
||||
|
||||
public GettingStartedSection gettingStarted() {
|
||||
return this.gettingStarted;
|
||||
}
|
||||
|
||||
public PreDefinedSection nextSteps() {
|
||||
return this.nextSteps;
|
||||
}
|
||||
|
||||
public HelpDocument addSection(Section section) {
|
||||
this.sections.add(section);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section rendered by the specified mustache template and model.
|
||||
* @param templateName the name of the mustache template to render
|
||||
* @param model the model that should be used for the rendering
|
||||
* @return this document
|
||||
*/
|
||||
public HelpDocument addSection(String templateName, Map<String, Object> model) {
|
||||
return addSection(
|
||||
new MustacheSection(this.templateRenderer, templateName, model));
|
||||
}
|
||||
|
||||
public List<Section> getSections() {
|
||||
return Collections.unmodifiableList(this.sections);
|
||||
}
|
||||
|
||||
public void write(PrintWriter writer) throws IOException {
|
||||
LinkedList<Section> allSections = new LinkedList<>(this.sections);
|
||||
allSections.addFirst(this.gettingStarted);
|
||||
allSections.addLast(this.nextSteps);
|
||||
for (Section section : allSections) {
|
||||
section.write(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return gettingStarted().isEmpty() && this.sections.isEmpty()
|
||||
&& nextSteps().isEmpty();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Callback for customizing a project's {@link HelpDocument}. Invoked with an
|
||||
* {@link Ordered order} of {@code 0} by default, considering overriding
|
||||
* {@link #getOrder()} to customize this behaviour.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface HelpDocumentCustomizer extends Ordered {
|
||||
|
||||
void customize(HelpDocument document);
|
||||
|
||||
@Override
|
||||
default int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import io.spring.initializr.generator.project.contributor.ProjectContributor;
|
||||
|
||||
/**
|
||||
* {@link ProjectContributor} for the project's {@code HELP.md} file.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class HelpDocumentProjectContributor implements ProjectContributor {
|
||||
|
||||
private final HelpDocument helpDocument;
|
||||
|
||||
public HelpDocumentProjectContributor(HelpDocument helpDocument) {
|
||||
this.helpDocument = helpDocument;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contribute(Path projectRoot) throws IOException {
|
||||
if (this.helpDocument.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Path file = Files.createFile(projectRoot.resolve("HELP.md"));
|
||||
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(file))) {
|
||||
this.helpDocument.write(writer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import io.spring.initializr.generator.project.ProjectGenerationConfiguration;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Configuration for contributions specific to the help documentation of a project.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ProjectGenerationConfiguration
|
||||
@Import(HelpDocumentProjectGenerationDefaultContributorsConfiguration.class)
|
||||
public class HelpDocumentProjectGenerationConfiguration {
|
||||
|
||||
@Bean
|
||||
public HelpDocumentProjectContributor helpDocumentProjectContributor(
|
||||
MustacheTemplateRenderer templateRenderer,
|
||||
ObjectProvider<HelpDocumentCustomizer> helpDocumentCustomizers) {
|
||||
HelpDocument helpDocument = new HelpDocument(templateRenderer);
|
||||
helpDocumentCustomizers.orderedStream()
|
||||
.forEach((customizer) -> customizer.customize(helpDocument));
|
||||
return new HelpDocumentProjectContributor(helpDocument);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import io.spring.initializr.generator.project.ResolvedProjectDescription;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Default {@link HelpDocument} contributors.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Configuration
|
||||
public class HelpDocumentProjectGenerationDefaultContributorsConfiguration {
|
||||
|
||||
@Bean
|
||||
public RequestedDependenciesHelpDocumentCustomizer dependenciesHelpDocumentCustomizer(
|
||||
ResolvedProjectDescription description, InitializrMetadata metadata) {
|
||||
return new RequestedDependenciesHelpDocumentCustomizer(description, metadata);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.io.text.Section;
|
||||
|
||||
/**
|
||||
* Section that is pre-defined and always present in the document. You can only add
|
||||
* additional sections to pre-defined sections.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class PreDefinedSection implements Section {
|
||||
|
||||
private final String title;
|
||||
|
||||
private final List<Section> subSections = new ArrayList<>();
|
||||
|
||||
public PreDefinedSection(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public PreDefinedSection addSection(Section section) {
|
||||
this.subSections.add(section);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PrintWriter writer) throws IOException {
|
||||
if (!isEmpty()) {
|
||||
writer.println("# " + this.title);
|
||||
writer.println("");
|
||||
for (Section section : resolveSubSections(this.subSections)) {
|
||||
section.write(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.subSections.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the sections to render based on the current registered sections.
|
||||
* @param sections the registered sections
|
||||
* @return the sections to render
|
||||
*/
|
||||
protected List<Section> resolveSubSections(List<Section> sections) {
|
||||
return sections;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import io.spring.initializr.generator.project.ResolvedProjectDescription;
|
||||
import io.spring.initializr.metadata.Dependency;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* A {@link HelpDocumentCustomizer} that register links for selected dependencies.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class RequestedDependenciesHelpDocumentCustomizer
|
||||
implements HelpDocumentCustomizer {
|
||||
|
||||
private final ResolvedProjectDescription projectDescription;
|
||||
|
||||
private final InitializrMetadata metadata;
|
||||
|
||||
public RequestedDependenciesHelpDocumentCustomizer(
|
||||
ResolvedProjectDescription projectDescription, InitializrMetadata metadata) {
|
||||
this.projectDescription = projectDescription;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(HelpDocument document) {
|
||||
this.projectDescription.getRequestedDependencies().forEach((id, dependency) -> {
|
||||
Dependency dependencyMetadata = this.metadata.getDependencies().get(id);
|
||||
if (dependencyMetadata != null) {
|
||||
handleDependency(document, dependencyMetadata);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
private void handleDependency(HelpDocument document, Dependency dependency) {
|
||||
GettingStartedSection gettingStartedSection = document.gettingStarted();
|
||||
dependency.getLinks().forEach((link) -> {
|
||||
if (link.getDescription() != null && link.getRel() != null) {
|
||||
if ("reference".equals(link.getRel())) {
|
||||
gettingStartedSection.addReferenceDocLink(link.getHref(),
|
||||
link.getDescription());
|
||||
}
|
||||
else if ("guide".equals(link.getRel())) {
|
||||
gettingStartedSection.addGuideLink(link.getHref(),
|
||||
link.getDescription());
|
||||
}
|
||||
else {
|
||||
gettingStartedSection.addAdditionalLink(link.getHref(),
|
||||
link.getDescription());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Documentation contributors. Generate a {@code HELP.md} at the root of the project with
|
||||
* additional information based on requested dependencies.
|
||||
*/
|
||||
package io.spring.initializr.generator.spring.documentation;
|
@ -7,4 +7,5 @@ io.spring.initializr.generator.spring.code.groovy.GroovyProjectGenerationConfigu
|
||||
io.spring.initializr.generator.spring.code.java.JavaProjectGenerationConfiguration,\
|
||||
io.spring.initializr.generator.spring.code.kotlin.KotlinProjectGenerationConfiguration,\
|
||||
io.spring.initializr.generator.spring.configuration.ApplicationConfigurationProjectGenerationConfiguration,\
|
||||
io.spring.initializr.generator.spring.documentation.HelpDocumentProjectGenerationConfiguration,\
|
||||
io.spring.initializr.generator.spring.scm.git.GitProjectGenerationConfiguration
|
@ -0,0 +1,6 @@
|
||||
### Additional Links
|
||||
These additional references should also help you:
|
||||
|
||||
{{#items}}
|
||||
* [{{description}}]({{href}})
|
||||
{{/items}}
|
@ -0,0 +1,6 @@
|
||||
### Guides
|
||||
The following guides illustrates how to use certain features concretely:
|
||||
|
||||
{{#items}}
|
||||
* [{{description}}]({{href}})
|
||||
{{/items}}
|
@ -0,0 +1,6 @@
|
||||
### Reference Documentation
|
||||
For further reference, please consider the following sections:
|
||||
|
||||
{{#items}}
|
||||
* [{{description}}]({{href}})
|
||||
{{/items}}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link GettingStartedSection}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class GettingStartedSectionTests {
|
||||
|
||||
private final MustacheTemplateRenderer renderer = new MustacheTemplateRenderer("");
|
||||
|
||||
@Test
|
||||
void gettingStartedEmpty() {
|
||||
GettingStartedSection gettingStarted = newGettingStartedSection();
|
||||
assertThat(gettingStarted.isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void gettingStartedWithGuideLinkIsNotEmpty() {
|
||||
GettingStartedSection gettingStarted = newGettingStartedSection();
|
||||
gettingStarted.addGuideLink("https://example.com", "Test");
|
||||
assertThat(gettingStarted.isEmpty()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void gettingStartedWithReferenceDocLinkIsNotEmpty() {
|
||||
GettingStartedSection gettingStarted = newGettingStartedSection();
|
||||
gettingStarted.addReferenceDocLink("https://example.com", "Test");
|
||||
assertThat(gettingStarted.isEmpty()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void gettingStartedWithAdditionalLinkIsNotEmpty() {
|
||||
GettingStartedSection gettingStarted = newGettingStartedSection();
|
||||
gettingStarted.addAdditionalLink("https://example.com", "Test");
|
||||
assertThat(gettingStarted.isEmpty()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void gettingStartedWithSubSectionIsNotEmpty() {
|
||||
GettingStartedSection gettingStarted = newGettingStartedSection();
|
||||
gettingStarted.addSection((writer) -> writer.println("test"));
|
||||
assertThat(gettingStarted.isEmpty()).isFalse();
|
||||
}
|
||||
|
||||
private GettingStartedSection newGettingStartedSection() {
|
||||
return new GettingStartedSection(this.renderer);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link HelpDocumentProjectContributor}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class HelpDocumentProjectContributorTests {
|
||||
|
||||
private Path directory;
|
||||
|
||||
private MustacheTemplateRenderer templateRenderer;
|
||||
|
||||
@BeforeEach
|
||||
void setup(@TempDir Path directory) {
|
||||
this.directory = directory;
|
||||
this.templateRenderer = new MustacheTemplateRenderer("classpath:/templates");
|
||||
}
|
||||
|
||||
@Test
|
||||
void helpDocumentEmptyDoesNotCreateFile() throws IOException {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
assertThat(document.isEmpty()).isTrue();
|
||||
Path projectDir = Files.createTempDirectory(this.directory, "project-");
|
||||
new HelpDocumentProjectContributor(document).contribute(projectDir);
|
||||
Path helpDocument = projectDir.resolve("HELP.md");
|
||||
assertThat(helpDocument).doesNotExist();
|
||||
}
|
||||
|
||||
@Test
|
||||
void helpDocumentWithLinksToGuide() throws IOException {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
document.gettingStarted().addGuideLink("https://test.example.com", "test")
|
||||
.addGuideLink("https://test2.example.com", "test2");
|
||||
List<String> lines = generateDocument(document);
|
||||
assertThat(lines).containsExactly("# Getting Started", "", "### Guides",
|
||||
"The following guides illustrates how to use certain features concretely:",
|
||||
"", "* [test](https://test.example.com)",
|
||||
"* [test2](https://test2.example.com)", "");
|
||||
}
|
||||
|
||||
@Test
|
||||
void helpDocumentWithLinksToReferenceDoc() throws IOException {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
document.gettingStarted().addReferenceDocLink("https://test.example.com", "doc")
|
||||
.addReferenceDocLink("https://test2.example.com", "doc2");
|
||||
List<String> lines = generateDocument(document);
|
||||
assertThat(lines).containsExactly("# Getting Started", "",
|
||||
"### Reference Documentation",
|
||||
"For further reference, please consider the following sections:", "",
|
||||
"* [doc](https://test.example.com)",
|
||||
"* [doc2](https://test2.example.com)", "");
|
||||
}
|
||||
|
||||
@Test
|
||||
void helpDocumentWithLinksToOtherLinks() throws IOException {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
document.gettingStarted().addAdditionalLink("https://test.example.com",
|
||||
"Something");
|
||||
List<String> lines = generateDocument(document);
|
||||
assertThat(lines).containsExactly("# Getting Started", "", "### Additional Links",
|
||||
"These additional references should also help you:", "",
|
||||
"* [Something](https://test.example.com)", "");
|
||||
}
|
||||
|
||||
@Test
|
||||
void helpDocumentWithSimpleSection() throws IOException {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
document.addSection((writer) -> writer
|
||||
.println(String.format("# My test section%n%n * Test")));
|
||||
List<String> lines = generateDocument(document);
|
||||
assertThat(lines).containsExactly("# My test section", "", " * Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void helpDocumentWithLinksAndSimpleSection() throws IOException {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
document.gettingStarted().addGuideLink("https://test.example.com", "test")
|
||||
.addSection((writer) -> writer
|
||||
.println(String.format("# My test section%n%n * Test")));
|
||||
List<String> lines = generateDocument(document);
|
||||
assertThat(lines).containsExactly("# Getting Started", "", "### Guides",
|
||||
"The following guides illustrates how to use certain features concretely:",
|
||||
"", "* [test](https://test.example.com)", "", "# My test section", "",
|
||||
" * Test");
|
||||
}
|
||||
|
||||
private List<String> generateDocument(HelpDocument document) throws IOException {
|
||||
Path projectDir = Files.createTempDirectory(this.directory, "project-");
|
||||
new HelpDocumentProjectContributor(document).contribute(projectDir);
|
||||
Path helpDocument = projectDir.resolve("HELP.md");
|
||||
assertThat(helpDocument).isRegularFile();
|
||||
return Files.readAllLines(helpDocument);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
import io.spring.initializr.generator.spring.test.InitializrMetadataTestBuilder;
|
||||
import io.spring.initializr.generator.test.project.ProjectAssetTester;
|
||||
import io.spring.initializr.metadata.Dependency;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import io.spring.initializr.metadata.Link;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link HelpDocumentProjectGenerationConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class HelpDocumentProjectGenerationConfigurationTests {
|
||||
|
||||
private ProjectAssetTester projectTester;
|
||||
|
||||
private InitializrMetadataTestBuilder metadataBuilder = InitializrMetadataTestBuilder
|
||||
.withDefaults();
|
||||
|
||||
@BeforeEach
|
||||
void setup(@TempDir Path directory) {
|
||||
this.projectTester = new ProjectAssetTester()
|
||||
.withConfiguration(HelpDocumentProjectGenerationConfiguration.class)
|
||||
.withBean(MustacheTemplateRenderer.class,
|
||||
() -> new MustacheTemplateRenderer("classpath:/templates"))
|
||||
.withBean(InitializrMetadata.class, () -> this.metadataBuilder.build())
|
||||
.withDirectory(directory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void helpDocumentIsNotContributedWithoutLinks() {
|
||||
assertThat(this.projectTester.generate(new ProjectDescription())
|
||||
.getRelativePathsOfProjectFiles()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void helpDocumentIsContributedWithLinks() {
|
||||
Dependency dependency = Dependency.withId("example", "com.example", "example");
|
||||
dependency.getLinks().add(
|
||||
Link.create("guide", "https://example.com/how-to", "How-to example"));
|
||||
dependency.getLinks().add(Link.create("reference", "https://example.com/doc",
|
||||
"Reference doc example"));
|
||||
this.metadataBuilder.addDependencyGroup("test", dependency);
|
||||
ProjectDescription description = new ProjectDescription();
|
||||
description.addDependency("example", null);
|
||||
assertThat(
|
||||
this.projectTester.generate(description).getRelativePathsOfProjectFiles())
|
||||
.containsOnly("HELP.md");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
/**
|
||||
* Tests for {@link HelpDocument}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class HelpDocumentTests {
|
||||
|
||||
private final MustacheTemplateRenderer templateRenderer = new MustacheTemplateRenderer(
|
||||
"classpath:/templates");
|
||||
|
||||
@Test
|
||||
void renderEmptyDocumentDoesNotCallWriter() throws IOException {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
PrintWriter out = mock(PrintWriter.class);
|
||||
document.write(out);
|
||||
verifyZeroInteractions(out);
|
||||
}
|
||||
|
||||
@Test
|
||||
void renderSingleSection() {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
document.addSection((writer) -> writer.println("# Test"));
|
||||
String out = write(document);
|
||||
assertThat(out).contains("# Test", "");
|
||||
}
|
||||
|
||||
@Test
|
||||
void renderLinks() {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
document.gettingStarted().addReferenceDocLink("https://example.com/doc", "Doc");
|
||||
document.gettingStarted().addGuideLink("https://example.com/guide-1", "Guide 1");
|
||||
document.gettingStarted().addGuideLink("https://example.com/guide-2", "Guide 2");
|
||||
String out = write(document);
|
||||
assertThat(out).contains("# Getting Started", "", "### Reference Documentation",
|
||||
"For further reference, please consider the following sections:", "",
|
||||
"* [Doc](https://example.com/doc)", "", "### Guides",
|
||||
"The following guides illustrates how to use certain features concretely:",
|
||||
"", "* [Guide 1](https://example.com/guide-1)",
|
||||
"* [Guide 2](https://example.com/guide-2)", "");
|
||||
}
|
||||
|
||||
@Test
|
||||
void renderOnlyAdditionalLink() {
|
||||
HelpDocument document = new HelpDocument(this.templateRenderer);
|
||||
document.gettingStarted().addAdditionalLink("https://example.com/app",
|
||||
"Test App");
|
||||
String out = write(document);
|
||||
assertThat(out).contains("# Getting Started", "", "### Additional Links",
|
||||
"These additional references should also help you:", "",
|
||||
"* [Test App](https://example.com/app)", "");
|
||||
}
|
||||
|
||||
private String write(HelpDocument document) {
|
||||
try {
|
||||
StringWriter out = new StringWriter();
|
||||
document.write(new PrintWriter(out));
|
||||
return out.toString();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.spring.documentation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
import io.spring.initializr.generator.project.ResolvedProjectDescription;
|
||||
import io.spring.initializr.generator.spring.test.InitializrMetadataTestBuilder;
|
||||
import io.spring.initializr.metadata.Dependency;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import io.spring.initializr.metadata.Link;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link RequestedDependenciesHelpDocumentCustomizer}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class RequestedDependenciesHelpDocumentCustomizerTests {
|
||||
|
||||
private final InitializrMetadataTestBuilder metadataBuilder = InitializrMetadataTestBuilder
|
||||
.withDefaults();
|
||||
|
||||
@Test
|
||||
void dependencyLinkWithNoDescriptionIsIgnored() {
|
||||
Dependency dependency = Dependency.withId("example", "com.example", "example");
|
||||
dependency.getLinks().add(Link.create("guide", "https://example.com/how-to"));
|
||||
this.metadataBuilder.addDependencyGroup("test", dependency);
|
||||
HelpDocument document = customizeHelp("example");
|
||||
assertThat(document.gettingStarted().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void dependencyWithReferenceDocLink() {
|
||||
Dependency dependency = Dependency.withId("example", "com.example", "example");
|
||||
dependency.getLinks().add(Link.create("reference", "https://example.com/doc",
|
||||
"Reference doc example"));
|
||||
this.metadataBuilder.addDependencyGroup("test", dependency);
|
||||
HelpDocument document = customizeHelp("example");
|
||||
assertThat(document.gettingStarted().isEmpty()).isFalse();
|
||||
List<GettingStartedSection.Link> links = document.gettingStarted().referenceDocs()
|
||||
.getItems();
|
||||
assertThat(links).hasSize(1);
|
||||
assertLink(links.get(0), "https://example.com/doc", "Reference doc example");
|
||||
}
|
||||
|
||||
@Test
|
||||
void dependencyWithGuideLink() {
|
||||
Dependency dependency = Dependency.withId("example", "com.example", "example");
|
||||
dependency.getLinks().add(
|
||||
Link.create("guide", "https://example.com/how-to", "How-to example"));
|
||||
this.metadataBuilder.addDependencyGroup("test", dependency);
|
||||
HelpDocument document = customizeHelp("example");
|
||||
assertThat(document.gettingStarted().isEmpty()).isFalse();
|
||||
List<GettingStartedSection.Link> links = document.gettingStarted().guides()
|
||||
.getItems();
|
||||
assertThat(links).hasSize(1);
|
||||
assertLink(links.get(0), "https://example.com/how-to", "How-to example");
|
||||
}
|
||||
|
||||
@Test
|
||||
void dependencyWithAdditionalLink() {
|
||||
Dependency dependency = Dependency.withId("example", "com.example", "example");
|
||||
dependency.getLinks()
|
||||
.add(Link.create("something", "https://example.com/test", "Test App"));
|
||||
this.metadataBuilder.addDependencyGroup("test", dependency);
|
||||
HelpDocument document = customizeHelp("example");
|
||||
assertThat(document.gettingStarted().isEmpty()).isFalse();
|
||||
List<GettingStartedSection.Link> links = document.gettingStarted()
|
||||
.additionalLinks().getItems();
|
||||
assertThat(links).hasSize(1);
|
||||
assertLink(links.get(0), "https://example.com/test", "Test App");
|
||||
}
|
||||
|
||||
private void assertLink(GettingStartedSection.Link link, String href,
|
||||
String description) {
|
||||
assertThat(link.getHref()).isEqualTo(href);
|
||||
assertThat(link.getDescription()).isEqualTo(description);
|
||||
}
|
||||
|
||||
private HelpDocument customizeHelp(String... requestedDependencies) {
|
||||
ProjectDescription description = new ProjectDescription();
|
||||
for (String requestedDependency : requestedDependencies) {
|
||||
description.addDependency(requestedDependency, null);
|
||||
}
|
||||
InitializrMetadata metadata = this.metadataBuilder.build();
|
||||
HelpDocument document = new HelpDocument(
|
||||
new MustacheTemplateRenderer("classpath:/templates"));
|
||||
new RequestedDependenciesHelpDocumentCustomizer(
|
||||
new ResolvedProjectDescription(description), metadata)
|
||||
.customize(document);
|
||||
return document;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.io.text;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.spring.initializr.generator.io.template.TemplateRenderer;
|
||||
|
||||
/**
|
||||
* {@link Section} for list of items using a {@link TemplateRenderer}.
|
||||
*
|
||||
* @param <T> the type of the item in the bullets
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class BulletedSection<T> implements Section {
|
||||
|
||||
private final TemplateRenderer templateRenderer;
|
||||
|
||||
private final String templateName;
|
||||
|
||||
private final String itemName;
|
||||
|
||||
private List<T> items = new ArrayList<>();
|
||||
|
||||
public BulletedSection(TemplateRenderer templateRenderer, String templateName) {
|
||||
this(templateRenderer, templateName, "items");
|
||||
}
|
||||
|
||||
public BulletedSection(TemplateRenderer templateRenderer, String templateName,
|
||||
String itemName) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.templateName = templateName;
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
public BulletedSection addItem(T item) {
|
||||
this.items.add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.items.isEmpty();
|
||||
}
|
||||
|
||||
public List<T> getItems() {
|
||||
return Collections.unmodifiableList(this.items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PrintWriter writer) throws IOException {
|
||||
if (!isEmpty()) {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
model.put(this.itemName, this.items);
|
||||
writer.println(this.templateRenderer.render(this.templateName, model));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.io.text;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Map;
|
||||
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
|
||||
/**
|
||||
* {@link Section} that uses a {@link MustacheTemplateRenderer}. Renders the content with
|
||||
* a newline at the end.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class MustacheSection implements Section {
|
||||
|
||||
private final MustacheTemplateRenderer templateRenderer;
|
||||
|
||||
private final String templateName;
|
||||
|
||||
private final Map<String, Object> model;
|
||||
|
||||
public MustacheSection(MustacheTemplateRenderer templateRenderer, String templateName,
|
||||
Map<String, Object> model) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.templateName = templateName;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PrintWriter writer) throws IOException {
|
||||
writer.println(this.templateRenderer.render(this.templateName,
|
||||
resolveModel(this.model)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the {@code model} prior to render the section.
|
||||
* @param model the current model
|
||||
* @return the model to use to render this section (never null)
|
||||
*/
|
||||
protected Map<String, Object> resolveModel(Map<String, Object> model) {
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.io.text;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import io.spring.initializr.generator.io.template.TemplateRenderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
/**
|
||||
* Tests for {@link BulletedSection}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class BulletedSectionTests {
|
||||
|
||||
@Mock
|
||||
private TemplateRenderer renderer;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<Map<String, Object>> modelCaptor;
|
||||
|
||||
@Test
|
||||
void bulletedSectionEmpty() {
|
||||
assertThat(new BulletedSection<String>(this.renderer, "test").isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void bulletedSectionEmptyDoesNotInvokeRender() throws IOException {
|
||||
BulletedSection<String> section = new BulletedSection<>(this.renderer, "test");
|
||||
PrintWriter writer = mock(PrintWriter.class);
|
||||
section.write(writer);
|
||||
verifyNoMoreInteractions(writer, this.renderer);
|
||||
}
|
||||
|
||||
@Test
|
||||
void bulletedSectionWithItem() {
|
||||
BulletedSection<String> section = new BulletedSection<>(this.renderer, "test");
|
||||
section.addItem("test");
|
||||
assertThat(section.isEmpty()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void bulletedSectionWithDefaultItemName() throws IOException {
|
||||
given(this.renderer.render(eq("template"), any())).willReturn("output");
|
||||
BulletedSection<String> section = new BulletedSection<>(this.renderer,
|
||||
"template");
|
||||
section.addItem("test");
|
||||
section.write(new PrintWriter(new StringWriter()));
|
||||
verify(this.renderer).render(eq("template"), this.modelCaptor.capture());
|
||||
Map<String, Object> model = this.modelCaptor.getValue();
|
||||
assertThat(model).containsOnly(entry("items", Collections.singletonList("test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void bulletedSectionWithCustomItemName() throws IOException {
|
||||
given(this.renderer.render(eq("template"), any())).willReturn("output");
|
||||
BulletedSection<String> section = new BulletedSection<>(this.renderer, "template",
|
||||
"elements");
|
||||
section.addItem("test");
|
||||
section.write(new PrintWriter(new StringWriter()));
|
||||
verify(this.renderer).render(eq("template"), this.modelCaptor.capture());
|
||||
Map<String, Object> model = this.modelCaptor.getValue();
|
||||
assertThat(model)
|
||||
.containsOnly(entry("elements", Collections.singletonList("test")));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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 io.spring.initializr.generator.io.text;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import com.samskivert.mustache.MustacheException;
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link MustacheSection}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class MustacheSectionTests {
|
||||
|
||||
private final MustacheTemplateRenderer renderer = new MustacheTemplateRenderer(
|
||||
"classpath:/templates/mustache");
|
||||
|
||||
@Test
|
||||
void renderSection() throws IOException {
|
||||
MustacheSection section = new MustacheSection(this.renderer, "test",
|
||||
Collections.singletonMap("key", "hello"));
|
||||
StringWriter writer = new StringWriter();
|
||||
section.write(new PrintWriter(writer));
|
||||
assertThat(writer.toString()).isEqualTo(String.format("hello%n"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void renderSectionWithMissingKey() {
|
||||
MustacheSection section = new MustacheSection(this.renderer, "test",
|
||||
Collections.singletonMap("another", "hello"));
|
||||
assertThatThrownBy(() -> section.write(new PrintWriter(new StringWriter())))
|
||||
.isInstanceOf(MustacheException.class).hasMessageContaining("key");
|
||||
}
|
||||
|
||||
@Test
|
||||
void renderSectionWithCustomModelResolution() throws IOException {
|
||||
MustacheSection section = new MustacheSection(this.renderer, "test",
|
||||
Collections.emptyMap()) {
|
||||
@Override
|
||||
protected Map<String, Object> resolveModel(Map<String, Object> model) {
|
||||
return Collections.singletonMap("key", "custom");
|
||||
}
|
||||
};
|
||||
StringWriter writer = new StringWriter();
|
||||
section.write(new PrintWriter(writer));
|
||||
assertThat(writer.toString()).isEqualTo(String.format("custom%n"));
|
||||
}
|
||||
|
||||
}
|
@ -17,13 +17,14 @@
|
||||
package io.spring.initializr.generator.test.project;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.io.SimpleIndentStrategy;
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import io.spring.initializr.generator.project.DefaultProjectAssetGenerator;
|
||||
import io.spring.initializr.generator.project.ProjectAssetGenerator;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
@ -49,8 +50,12 @@ public class ProjectGeneratorTester
|
||||
}
|
||||
|
||||
private static Map<Class<?>, Supplier<?>> defaultBeans() {
|
||||
return Collections.singletonMap(IndentingWriterFactory.class,
|
||||
Map<Class<?>, Supplier<?>> beans = new HashMap<>();
|
||||
beans.put(IndentingWriterFactory.class,
|
||||
() -> IndentingWriterFactory.create(new SimpleIndentStrategy(" ")));
|
||||
beans.put(MustacheTemplateRenderer.class,
|
||||
() -> new MustacheTemplateRenderer("classpath:/templates"));
|
||||
return beans;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,8 +89,8 @@ public class InitializrAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TemplateRenderer templateRenderer(Environment environment,
|
||||
@ConditionalOnMissingBean(TemplateRenderer.class)
|
||||
public MustacheTemplateRenderer templateRenderer(Environment environment,
|
||||
ObjectProvider<CacheManager> cacheManager) {
|
||||
return new MustacheTemplateRenderer("classpath:/templates",
|
||||
determineCache(environment, cacheManager.getIfAvailable()));
|
||||
|
@ -24,6 +24,7 @@ import java.util.Map;
|
||||
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.io.SimpleIndentStrategy;
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
import io.spring.initializr.generator.project.ProjectDirectoryFactory;
|
||||
import io.spring.initializr.generator.spring.test.InitializrMetadataTestBuilder;
|
||||
import io.spring.initializr.generator.spring.test.ProjectAssert;
|
||||
@ -206,6 +207,11 @@ public class ProjectGenerationInvokerTests {
|
||||
return IndentingWriterFactory.create(new SimpleIndentStrategy("\t"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MustacheTemplateRenderer templateRenderer() {
|
||||
return new MustacheTemplateRenderer("classpath:/templates");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProjectDirectoryFactory projectDirectoryFactory() {
|
||||
return (description) -> Files.createTempDirectory("project-");
|
||||
|
Loading…
Reference in New Issue
Block a user