Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changes/changes.md
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
# Changes

* [4.2.0](changes_4.2.0.md)
* [4.1.0](changes_4.1.0.md)
* [4.0.2](changes_4.0.2.md)
* [4.0.1](changes_4.0.1.md)
Expand Down
11 changes: 11 additions & 0 deletions doc/changes/changes_4.2.0.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
# OpenFastTrace 4.2.0, released ???

Code name: Markdown code blocks

## Summary

In this release we changed the behavior of the Markdown importer, so that if we are inside a code block, no OFT specification items are found. This is a corner case, but we think that this behavior is what users would expect (#480).

## Features

* #480: Ignore specification items inside Markdown code blocks
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ public enum LineParserState
TITLE,
/** Found tags */
TAGS,
/** Code block */
CODE_BLOCK,
/** Reached the end of the file */
EOF
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -42,6 +42,7 @@ protected Transition[] configureTransitions()
transition(START , SPEC_ITEM , MdPattern.ID , this::beginItem ),
transition(START , TITLE , SECTION_TITLE , this::rememberTitle ),
transition(START , START , MdPattern.FORWARD , this::forward ),
transition(START , CODE_BLOCK , MdPattern.CODE_BEGIN , () -> {} ),
transition(START , START , MdPattern.EVERYTHING , () -> {} ),

transition(TITLE , SPEC_ITEM , MdPattern.ID , this::beginItem ),
Expand DownExpand Up@@ -99,7 +100,6 @@ protected Transition[] configureTransitions()
transition(COMMENT , TAGS , MdPattern.TAGS , () -> {} ),
transition(COMMENT , COMMENT , MdPattern.EVERYTHING , this::appendComment ),


// [impl->dsn~md.covers-list~1]
transition(COVERS , SPEC_ITEM , MdPattern.ID , this::beginItem ),
transition(COVERS , TITLE , SECTION_TITLE , () -> {endItem(); rememberTitle();}),
Expand DownExpand Up@@ -156,7 +156,9 @@ protected Transition[] configureTransitions()
transition(TAGS , COVERS , MdPattern.COVERS , () -> {} ),
transition(TAGS , TAGS , MdPattern.TAGS , () -> {} ),
transition(TAGS , TAGS , MdPattern.TAGS_INT , this::addTag ),
transition(TAGS , START , MdPattern.FORWARD , () -> {endItem(); forward();} )
transition(TAGS , START , MdPattern.FORWARD , () -> {endItem(); forward();} ),

transition(CODE_BLOCK , START , MdPattern.CODE_END , () -> {} )
};
// @formatter:on
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,6 +15,8 @@ enum MdPattern
// [impl->dsn~md.artifact-forwarding-notation~1]

// @formatter:off
CODE_BEGIN(" *[`~]{3,30}\\w*\\s*"),
CODE_END(" *[`~]{3,30}\\s*"),
COMMENT("Comment:\\s*"),
COVERS("Covers:\\s*"),
COVERS_REF(PatternConstants.REFERENCE_AFTER_BULLET),
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
package org.itsallcode.openfasttrace.importer.markdown;

import static org.hamcrest.Matchers.emptyIterable;
import static org.itsallcode.matcher.auto.AutoMatcher.contains;
import static org.itsallcode.openfasttrace.testutil.core.ItemBuilderFactory.item;

Expand All@@ -8,6 +9,7 @@
import org.itsallcode.openfasttrace.testutil.importer.lightweightmarkup.AbstractLightWeightMarkupImporterTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;

class TestMarkdownMarkupImporter extends AbstractLightWeightMarkupImporterTest
Expand DownExpand Up@@ -138,4 +140,79 @@ void testLessThenThreeUnderliningCharactersAreNotDetectedAsTitleUnderlines()
.location("z", 3)
.build()));
}

@ParameterizedTest
@CsvSource(
{
"```,```",
"``` ,``` ",
"``` ,```",
"````, ````",
" ```, ```",
" ```, ```",
" ```, ```",
"```java, ```",
"```java , ``` ",
"~~~, ~~~",
"~~~java, ~~~",
" ~~~~java, ~~~~ "
})
void testWhenInsideMarkdownCodeBlockThenNoSpecificationItemMustBeDetected(final String startMarker,
final String endMarker)
{
assertImport("file_with_code_block.md", """
%s
This is a code block, the following requirement must be ignored.

req~example~1
%s
""".formatted(startMarker, endMarker),
emptyIterable());
}

@ParameterizedTest
@CsvSource(
{
"`,`",
"``,``",
" ``', ``",
"`` ,`` ",
"``java,``",
"~~,~~",
})
void testWhenNotInsideMarkdownCodeBlockThenSpecificationItemMustBeDetected(final String startMarker,
final String endMarker)
{
assertImport("file_without_code_block.md", """
%s
This is not a code block, the following requirement must be detected.

req~example~1
%s
""".formatted(startMarker, endMarker),
contains(item()
.id(SpecificationItemId.parseId("req~example~1"))
.location("file_without_code_block.md", 4)
.description(endMarker) // End marker looks like part of the description in this case.
.build()));
}

@Test
void testWhenCodeBlockIsInsideCommentSectionThenItIsImportedAsPartOfComment()
{
assertImport("file_with_code_block_in_comment.md", """
req~comment_with_code_block~1
Comment:

```
This is a code block inside a comment.
```
""",
contains(item()
.id(SpecificationItemId.createId("req", "comment_with_code_block", 1))
.comment("```" + System.lineSeparator()+ "This is a code block inside a comment."
+ System.lineSeparator() + "```")
.location("file_with_code_block_in_comment.md", 1)
.build()));
}
}