diff --git a/livingdoc-examples/microservice/src/main/livingdoc/gherkin_template.erb b/livingdoc-examples/microservice/src/main/livingdoc/gherkin_template.erb deleted file mode 100644 index 5d9f1d5d..00000000 --- a/livingdoc-examples/microservice/src/main/livingdoc/gherkin_template.erb +++ /dev/null @@ -1,117 +0,0 @@ -=== Feature <%= feature['name'] %> - -<% if feature.key?('description') %> - <%= feature['description'] %> -<% end %> - -<% if feature.key?('background') %>==== <%= feature['background']['name'] %> - <% if feature['background'].key?('description') %> - <%= feature['background']['description'] %> - <% end %> - <% if feature['background'].key?('steps') %> - [.step-list] - <% feature['background']['steps'].each do |step| %> - *<%= step['keyword'].strip %>* <%= step['name'] %> - <% if step.key?('doc_string') %> - + - .... - <%= step['doc_string']['value'] %> - .... - <% end %> - <% if step.key?('rows') %> - + - <% if step['rows'].first && step['rows'].first.key?('cols') %> - [<%= step['rows'].first['cols'] %>] - <% end %> - |==== - <% step['rows'].each_with_index do |row, index| %> - <% row['cells'].each_with_index do |cell, i| %> - <% - if row.key?('cell-styles') && row['cell-styles'].length > i %><%= row['cell-styles'][i] %> - <% end %>| <%= cell %> - <% end %> - <% end %>|==== - <% end %> - - <% end %> - <% end %> - - <% if feature['background'].key?('examples') - example = feature['background']['examples'] %> - - ===== <%= example['keyword'].strip %> <%= example['name'] %> - - <% if example['rows'].first && example['rows'].first.key?('cols') %> - [<%= example['rows'].first['cols'] %>] - <% end %> - |==== - <% example['rows'].each_with_index do |row, index| %> - <% row['cells'].each_with_index do |cell, i| %> - <% - if row.key?('cell-styles') && row['cell-styles'].length > i %><%= row['cell-styles'][i] %> - <% end %>| <%= cell %> - <% end %> - <% if index == 0 %> - <% end %> - <% end %>|==== - <% end %> -<% end %> - -<% if feature.key?('scenarios') %> - <% feature['scenarios'].each do |scenario| %>==== <%= scenario['name'] %> - <% if scenario.key?('description') %> - <%= scenario['description'] %> - <% end %> - <% if scenario.key?('steps') %> - [.step-list] - <% scenario['steps'].each do |step| %> - *<%= step['keyword'].strip %>* <%= step['name'] %> - <% if step.key?('doc_string') %> - + - .... - <%= step['doc_string']['value'] %> - .... - <% end %> - <% if step.key?('rows') %> - + - <% if step['rows'].first && step['rows'].first.key?('cols') %> - [<%= step['rows'].first['cols'] %>] - <% end %> - |==== - <% step['rows'].each_with_index do |row, index| %> - <% row['cells'].each_with_index do |cell, i| %> - <% - if row.key?('cell-styles') && row['cell-styles'].length > i %><%= row['cell-styles'][i] %> - <% end %>| <%= cell %> - <% end %> - <% end %>|==== - <% end %> - - <% end %> - <% end %> - - <% if scenario.key?('examples') - example = scenario['examples'] - %> - - ===== <%= example['keyword'].strip %> <%= example['name'] %> - - <% if example['rows'].first && example['rows'].first.key?('cols') %> - [<%= example['rows'].first['cols'] %>] - <% end %> - |==== - <% example['rows'].each_with_index do |row, index| %> - <% row['cells'].each_with_index do |cell, i| %> - <% - if row.key?('cell-styles') && row['cell-styles'].length > i %><%= row['cell-styles'][i] %> - <% end %>| <%= cell %> - <% end %> - <% if index == 0 %> - <% end %> - <% end %>|==== - - <% end %> - - <% end %> -<% end %> - diff --git a/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/GherkinMojo.java b/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/GherkinMojo.java index c618aef9..68c9f012 100644 --- a/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/GherkinMojo.java +++ b/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/GherkinMojo.java @@ -23,7 +23,7 @@ package ch.ifocusit.livingdoc.plugin; import ch.ifocusit.livingdoc.plugin.baseMojo.AbstractDocsGeneratorMojo; -import ch.ifocusit.livingdoc.plugin.gherkin.GherkinToAsciidocTransformer; +import ch.ifocusit.livingdoc.plugin.gherkin.StandaloneGherkinProcessor; import com.github.domgold.doctools.asciidoctor.gherkin.MapFormatter; import io.github.robwin.markup.builder.asciidoc.AsciiDocBuilder; import org.apache.commons.io.FileUtils; @@ -34,6 +34,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -82,10 +83,16 @@ public class GherkinMojo extends AbstractDocsGeneratorMojo { private boolean gerkinSeparateFeature; /** - * Flag to indicate if generated asciidoc file must use the gherkin plugin + * Flag to indicate if generated asciidoc file must use the asciidoc gherkin macro (like include macro) */ - @Parameter(property = "livingdoc.gherkin.gherkinAsciidocPlugin", defaultValue = "true") - private boolean gherkinAsciidocPlugin; + @Parameter(property = "livingdoc.gherkin.gherkinAsciidocMacro", defaultValue = "false") + private boolean gherkinAsciidocMacro; + + /** + * Replace gherkin processor default template. Must be used with gherkinAsciidocPlugin option to false + */ + @Parameter(property = "livingdoc.gherkin.gherkinAsciidocTemplate") + private File gherkinAsciidocTemplate; protected boolean somethingWasGenerated = false; @@ -123,11 +130,14 @@ public void executeMojo() { throw new IllegalStateException("Error reading " + path, e); } } - if (gherkinAsciidocPlugin) { + if (gherkinAsciidocMacro) { getDocBuilder(pageCount.get()).textLine(String.format("gherkin::%s[%s]", path, gherkinOptions)); } else { try { - getDocBuilder(pageCount.get()).textLine(new GherkinToAsciidocTransformer().transform(readFileToString(FileUtils.getFile(path), defaultCharset()))); + getDocBuilder(pageCount.get()).textLine(StandaloneGherkinProcessor.builder() + .gherkinTemplate(gherkinAsciidocTemplate) + .build() + .process(readFileToString(FileUtils.getFile(path), defaultCharset()))); } catch (IOException e) { throw new IllegalStateException("Error reading " + path, e); } @@ -166,6 +176,7 @@ private Stream readFeatures() { .filter(path -> Files.exists(Paths.get(path))) .flatMap(path -> { try { + //noinspection resource return Files.walk(Paths.get(path)).filter(p -> p.toString().endsWith(".feature")); } catch (IOException e) { throw new IllegalStateException(String.format("Error browsing %s", path), e); diff --git a/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/gherkin/GherkinToAsciidocTransformer.java b/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/gherkin/GherkinToAsciidocTransformer.java deleted file mode 100644 index dfa63a85..00000000 --- a/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/gherkin/GherkinToAsciidocTransformer.java +++ /dev/null @@ -1,83 +0,0 @@ -package ch.ifocusit.livingdoc.plugin.gherkin; - -import com.github.domgold.doctools.asciidoctor.gherkin.MapFormatter; -import org.apache.commons.lang3.StringUtils; - -import java.util.List; -import java.util.Map; - -import static ch.ifocusit.livingdoc.plugin.utils.AsciidocUtil.NEWLINE; - -@SuppressWarnings("unchecked") -public class GherkinToAsciidocTransformer { - - private final StringBuilder builder = new StringBuilder(); - - public String transform(String fileContent) { - return format(MapFormatter.parse(fileContent)); - } - - private String format(Map parsed) { - builder.append("=== ").append(parsed.get("name")).append(NEWLINE).append(NEWLINE); - manageDescription(parsed); - if (parsed.containsKey("background")) { - Map background = (Map) parsed.get("background"); - manageScenario(background); - } - if (parsed.containsKey("scenarios")) { - List> scenarios = (List>) parsed.get("scenarios"); - for (Map scenario : scenarios) { - manageScenario(scenario); - } - } - return builder.toString(); - } - - private void manageDescription(Map container) { - String description = (String) container.get("description"); - if (StringUtils.isNotBlank(description)) { - builder.append(description).append(NEWLINE); - } - builder.append(NEWLINE); - } - - private void manageScenario(Map scenario) { - builder.append("==== ").append(scenario.get("name")).append(NEWLINE); - manageDescription(scenario); - manageSteps(scenario); - manageTable(scenario); - } - - private void manageSteps(Map container) { - if (container.containsKey("steps")) { - List> steps = (List>) container.get("steps"); - for (Map step : steps) { - String keyword = (String) step.get("keyword"); - builder.append("* *").append(keyword.trim()).append("* ").append(step.get("name")).append(NEWLINE); - if (step.containsKey("doc_string")) { - Map doc_string = (Map) step.get("doc_string"); - builder.append("+").append(NEWLINE).append("....").append(NEWLINE).append(doc_string.get("value")).append("....").append(NEWLINE); - } - builder.append(NEWLINE); - manageTable(step); - } - } - } - - private void manageTable(Map container) { - if (container.containsKey("examples")) { - Map examples = (Map) container.get("examples"); - builder.append("===== ").append(examples.get("keyword")).append(NEWLINE); - List> rows = (List>) examples.get("rows"); - builder.append("|====").append(NEWLINE); - for (Map row : rows) { - List cells = (List) row.get("cells"); - for (Object cell : cells) { - builder.append("| ").append(cell); - } - builder.append(NEWLINE); - } - builder.append("|====").append(NEWLINE).append(NEWLINE); - } - } -} diff --git a/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/gherkin/StandaloneGherkinProcessor.java b/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/gherkin/StandaloneGherkinProcessor.java new file mode 100644 index 00000000..3ebb3055 --- /dev/null +++ b/livingdoc-maven-plugin/src/main/java/ch/ifocusit/livingdoc/plugin/gherkin/StandaloneGherkinProcessor.java @@ -0,0 +1,27 @@ +package ch.ifocusit.livingdoc.plugin.gherkin; + +import com.github.domgold.doctools.asciidoctor.gherkin.MapFormatter; +import lombok.Builder; +import lombok.SneakyThrows; +import org.apache.commons.io.IOUtils; +import org.jruby.embed.ScriptingContainer; + +import java.io.File; +import java.nio.charset.Charset; +import java.util.Objects; + +@Builder +public class StandaloneGherkinProcessor { + + private File gherkinTemplate; + + @SneakyThrows + public String process(String fileContent) { + ScriptingContainer container = new ScriptingContainer(); + container.put("feature_file_content", fileContent); + container.put("template_content", gherkinTemplate != null ? IOUtils.toString(gherkinTemplate.toURI(), Charset.defaultCharset()) : MapFormatter.getDefaultTemplate()); + String scriptPath = "/standaloneGherkinProcessor.rb"; + String script = IOUtils.toString(Objects.requireNonNull(getClass().getResourceAsStream(scriptPath)), Charset.defaultCharset()); + return (String) container.runScriptlet(script); + } +} diff --git a/livingdoc-maven-plugin/src/main/resources/plantuml_macro.mustache b/livingdoc-maven-plugin/src/main/resources/plantuml_macro.mustache deleted file mode 100644 index 3162271c..00000000 --- a/livingdoc-maven-plugin/src/main/resources/plantuml_macro.mustache +++ /dev/null @@ -1,8 +0,0 @@ - - INLINE - - - - INLINE - title = {{fileName}} - diff --git a/livingdoc-maven-plugin/src/main/resources/standaloneGherkinProcessor.rb b/livingdoc-maven-plugin/src/main/resources/standaloneGherkinProcessor.rb new file mode 100644 index 00000000..6b4505d6 --- /dev/null +++ b/livingdoc-maven-plugin/src/main/resources/standaloneGherkinProcessor.rb @@ -0,0 +1,54 @@ +require 'erb' + +def preprocess_feature feature + if feature.key?('background') + preprocess_scenario feature['background'] + end + if feature.key?('scenarios') + feature['scenarios'].each do |scenario| + preprocess_scenario scenario + end + end +end + +def preprocess_scenario scenario + if scenario.key?('steps') + preprocess_steplist scenario['steps'] + end + if scenario.key?('examples') + preprocess_table_comments scenario['examples']['rows'] + end +end + +def preprocess_steplist steplist + steplist.each do |step| + if step.key?('rows') + preprocess_table_comments step['rows'] + end + end +end + +def preprocess_table_comments rows + if rows.length > 0 && rows.first.key?('comments') && rows.first['comments'].length > 0 && rows.first['comments'].first['value'].match(/^#cols=/) + cols = rows.first['comments'].first['value'][1..-1] + rows.first['comments'].java_send :remove, [Java::int], 0 + rows.first["cols"] = cols + end + rows.each do |row| + if row.key?('comments') && row['comments'].length > 0 && row['comments'].first['value'].match(/^#cells=/) + cells = row['comments'].first['value'][7..-1].split(/,/) + row['cell-styles'] = cells + row['comments'].java_send :remove, [Java::int], 0 + end + end +end + +# parse feature and make the result available to the template via binding as 'feature' hash. +feature = com.github.domgold.doctools.asciidoctor.gherkin.MapFormatter.parse(feature_file_content) + +preprocess_feature(feature) + +erb_template = ERB.new(template_content) +rendered_template_output = erb_template.result(binding()) + +rendered_template_output diff --git a/livingdoc-maven-plugin/src/main/resources/templates/gherkin_template.erb b/livingdoc-maven-plugin/src/main/resources/templates/gherkin_template.erb deleted file mode 100644 index 1970c158..00000000 --- a/livingdoc-maven-plugin/src/main/resources/templates/gherkin_template.erb +++ /dev/null @@ -1,87 +0,0 @@ - -[[feature-<%=feature['name']%>]] - -=== <%= feature['name'] %> - -<%if feature.key?('description') %> - <%= feature['description'] %> -<% end %> - -<%if feature.key?('background') %>==== <%= feature['background']['name'] %> - <%if feature['background'].key?('description') %> - <%= feature['background']['description'] %> - <% end %><%if feature['background'].key?('steps') %> - [.step-list]<% feature['background']['steps'].each do |step| %> - * *<%= step['keyword'].strip %>* <%= step['name'] %><%if step.key?('doc_string') %> - + - .... - <%= step['doc_string']['value'] %> - .... - <% end %><%if step.key?('rows') %> - +<% if step['rows'].first && step['rows'].first.key?('cols') %> - [<%= step['rows'].first['cols'] %>]<% end %> - |==== - <% step['rows'].each_with_index do |row, index| %><% row['cells'].each_with_index do |cell, i| %><% - if row.key?('cell-styles') && row['cell-styles'].length > i %><%= row['cell-styles'][i] %><% end %>| <%= cell %> <% end %> - <% end %>|==== - <% end %> - - <% end %> - <% end %> - - <%if feature['background'].key?('examples') - example = feature['background']['examples'] %> - - ===== <%= example['keyword'].strip %> <%= example['name'] %> - - <% if example['rows'].first && example['rows'].first.key?('cols') %> - [<%= example['rows'].first['cols'] %>]<% end %> - |==== - <% example['rows'].each_with_index do |row, index| %><% row['cells'].each_with_index do |cell, i| %><% - if row.key?('cell-styles') && row['cell-styles'].length > i %><%= row['cell-styles'][i] %><% end %>| <%= cell %> <% end %> - <% if index == 0 %> - <% end %><% end %>|==== - <% end %> -<% end %> - -<%if feature.key?('scenarios') %><% feature['scenarios'].each do |scenario| %>==== <%= scenario['name'] %> - <%if scenario.key?('description') %> - <%= scenario['description'] %> - <% end %><%if scenario.key?('steps') %> - [.step-list]<% scenario['steps'].each do |step| %> - * *<%= step['keyword'].strip %>* <%= step['name'] %><%if step.key?('doc_string') %> - + - .... - <%= step['doc_string']['value'] %> - .... - <% end %><%if step.key?('rows') %> - +<% if step['rows'].first && step['rows'].first.key?('cols') %> - [<%= step['rows'].first['cols'] %>]<% end %> - |==== - <% step['rows'].each_with_index do |row, index| %><% row['cells'].each_with_index do |cell, i| %><% - if row.key?('cell-styles') && row['cell-styles'].length > i %><%= row['cell-styles'][i] %><% end %>| <%= cell %> <% end %> - <% end %>|==== - <% end %> - - <% end %> - <% end %> - - <%if scenario.key?('examples') - example = scenario['examples'] - %> - - ===== <%= example['keyword'].strip %> <%= example['name'] %> - - <% if example['rows'].first && example['rows'].first.key?('cols') %> - [<%= example['rows'].first['cols'] %>]<% end %> - |==== - <% example['rows'].each_with_index do |row, index| %><% row['cells'].each_with_index do |cell, i| %><% - if row.key?('cell-styles') && row['cell-styles'].length > i %><%= row['cell-styles'][i] %><% end %>| <%= cell %> <% end %> - <% if index == 0 %> - <% end %><% end %>|==== - - <% end %> - - <% end %> -<% end %> - diff --git a/livingdoc-maven-plugin/src/test/java/ch/ifocusit/livingdoc/plugin/gherkin/GherkinToAsciidocTransformerTest.java b/livingdoc-maven-plugin/src/test/java/ch/ifocusit/livingdoc/plugin/gherkin/StandaloneGherkinProcessorTest.java similarity index 77% rename from livingdoc-maven-plugin/src/test/java/ch/ifocusit/livingdoc/plugin/gherkin/GherkinToAsciidocTransformerTest.java rename to livingdoc-maven-plugin/src/test/java/ch/ifocusit/livingdoc/plugin/gherkin/StandaloneGherkinProcessorTest.java index c3e69f5c..ab9ae1bd 100644 --- a/livingdoc-maven-plugin/src/test/java/ch/ifocusit/livingdoc/plugin/gherkin/GherkinToAsciidocTransformerTest.java +++ b/livingdoc-maven-plugin/src/test/java/ch/ifocusit/livingdoc/plugin/gherkin/StandaloneGherkinProcessorTest.java @@ -9,7 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class GherkinToAsciidocTransformerTest { +class StandaloneGherkinProcessorTest { @Test void transform() throws Exception { @@ -17,9 +17,9 @@ void transform() throws Exception { String fileContent = FileUtils.readFileToString(new File(Objects.requireNonNull(this.getClass().getResource("/simple.feature")).toURI()), Charset.defaultCharset()); String expected = FileUtils.readFileToString(new File(Objects.requireNonNull(this.getClass().getResource("/simple.adoc")).toURI()), Charset.defaultCharset()); // when - String adoc = new GherkinToAsciidocTransformer().transform(fileContent); + String adoc = StandaloneGherkinProcessor.builder().build().process(fileContent); // then - assertThat(adoc).isEqualTo(expected); + assertThat(adoc).isEqualToIgnoringWhitespace(expected); } @Test @@ -28,8 +28,8 @@ void transformComplex() throws Exception { String fileContent = FileUtils.readFileToString(new File(Objects.requireNonNull(this.getClass().getResource("/complex.feature")).toURI()), Charset.defaultCharset()); String expected = FileUtils.readFileToString(new File(Objects.requireNonNull(this.getClass().getResource("/complex.adoc")).toURI()), Charset.defaultCharset()); // when - String adoc = new GherkinToAsciidocTransformer().transform(fileContent); + String adoc = StandaloneGherkinProcessor.builder().build().process(fileContent); // then - assertThat(adoc).isEqualTo(expected); + assertThat(adoc).isEqualToIgnoringWhitespace(expected); } -} \ No newline at end of file +} diff --git a/livingdoc-maven-plugin/src/test/resources/complex.adoc b/livingdoc-maven-plugin/src/test/resources/complex.adoc index 7f2cb964..67e9f880 100644 --- a/livingdoc-maven-plugin/src/test/resources/complex.adoc +++ b/livingdoc-maven-plugin/src/test/resources/complex.adoc @@ -1,4 +1,6 @@ -=== A complex feature + +=== A full feature that doesn't limit + This is the feature description. @@ -15,8 +17,6 @@ String test = "Hello, Asciidoctor."; WARNING: admonition. -include::included_doc.adoc[] - .A table with title |==== | A | B @@ -24,42 +24,101 @@ include::included_doc.adoc[] | 1 | 2 |==== + ==== Background + + +[.step-list] * *Given* a complex background step with table with header ++ +[cols=".<2,.^5,^.>3",options="header"] +|==== +h| Header Cell 1 h| Header Cell 2 h| Header Cell 3 +| Cell 1 Row 1 m| Cell 2 Row 1 monospace | Cell 3 Row 1 +| Cell 1 Row 2 with *bold* | Cell 2 Row 2 | Cell 3 Row 2 +|==== + + + + + + + ==== 1st scenario title + The scenario description comes here. [NOTE] ==== -You can add nice comments -==== +You can add nice description, with https://github.com/jboz/living-documentation[links] - dash list in scenario description - the second list item +==== +[.step-list] * *Given* a simple step + * *When* I have a step with a *table* ++ +|==== +| a | b +| c | d +|==== + + * *And* I render the asciidoctor content to html + * *Then* the parameters should NOT get processed. ++ +|==== +| img +| **.png +|==== + + * *And* the file "**.png" everything is fine. + + + + + ===== Examples + + +[cols="2,2,^4"] |==== -| parameter_name| parameter_value| 3rd colonne double width -| _actorWidth_| 25| A -| actorHeight| 30| B +| parameter_name | parameter_value | 3rd colonne double width + +| _actorWidth_ | 25 | A +| actorHeight | 30 | B |==== + + ==== 2nd scenario title + + +[.step-list] * *Given* a short scenario + * *Then* it's really short. + + + + + + + + diff --git a/livingdoc-maven-plugin/src/test/resources/complex.feature b/livingdoc-maven-plugin/src/test/resources/complex.feature index f6c8da19..3a832974 100644 --- a/livingdoc-maven-plugin/src/test/resources/complex.feature +++ b/livingdoc-maven-plugin/src/test/resources/complex.feature @@ -1,5 +1,5 @@ # language: en -Feature: A complex feature +Feature: A full feature that doesn't limit This is the feature description. In the feature's description, you can use asciidoctor markup as it pleases you. @@ -15,8 +15,6 @@ Feature: A complex feature WARNING: admonition. - include::included_doc.adoc[] - .A table with title |==== | A | B @@ -39,11 +37,11 @@ Feature: A complex feature [NOTE] ==== - You can add nice comments - ==== + You can add nice description, with https://github.com/jboz/living-documentation[links] - dash list in scenario description - the second list item + ==== Given a simple step When I have a step with a *table* @@ -63,4 +61,4 @@ Feature: A complex feature Scenario: 2nd scenario title Given a short scenario - Then it's really short. \ No newline at end of file + Then it's really short. diff --git a/livingdoc-maven-plugin/src/test/resources/simple.adoc b/livingdoc-maven-plugin/src/test/resources/simple.adoc index cac365fe..1c696ca6 100644 --- a/livingdoc-maven-plugin/src/test/resources/simple.adoc +++ b/livingdoc-maven-plugin/src/test/resources/simple.adoc @@ -1,33 +1,72 @@ + === A simple feature + This is the feature description. + ==== Background + + +[.step-list] * *Given* a simple background step. + + + + + + ==== Apple + + +[.step-list] * *Given* two apples + * *When* I eat one apple + * *Then* there is one apple left. + + + + + ==== Second scenario title + Will add 5 to any number +[.step-list] * *Given* a number + * *When* I add it to 5 + * *Then* the result is + + + + + ===== Examples + + |==== -| operand| result -| 0| 5 -| 1| 6 -| 5| 10 +| operand | result + +| 0 | 5 +| 1 | 6 +| 5 | 10 |==== + + + + +