Skip to content

Commit

Permalink
#280: Ignore requirement in Markdown code blocks (#433)
Browse files Browse the repository at this point in the history
* #280: Inside Markdown code blocks requirements are now ignored (see https://github.github.com/gfm/#fenced-code-blocks for specification).
  • Loading branch information
redcatbear authored Jan 6, 2025
1 parent 159a20e commit 6a25536
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 2 deletions.
1 change: 1 addition & 0 deletions doc/changes/changes.md
Original file line number Diff line number Diff 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 number Diff line number Diff 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 number Diff line number Diff 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 number Diff line number Diff 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 Down Expand 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 Down Expand 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 number Diff line number Diff 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 number Diff line number Diff 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 Down Expand 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()));
}
}

0 comments on commit 6a25536

Please sign in to comment.