diff --git a/heylogs-api/pom.xml b/heylogs-api/pom.xml
index ed80ca1..5badb80 100644
--- a/heylogs-api/pom.xml
+++ b/heylogs-api/pom.xml
@@ -65,17 +65,6 @@
-
- org.semver4j
- semver4j
- 5.3.0
-
-
- org.jetbrains
- annotations
-
-
-
com.github.nbbrd.java-io-util
java-io-base
@@ -102,4 +91,25 @@
test
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+ tests/**
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/heylogs-api/src/test/java/internal/heylogs/ChangelogNodesTest.java b/heylogs-api/src/test/java/internal/heylogs/ChangelogNodesTest.java
index 4c10aba..ea5e683 100644
--- a/heylogs-api/src/test/java/internal/heylogs/ChangelogNodesTest.java
+++ b/heylogs-api/src/test/java/internal/heylogs/ChangelogNodesTest.java
@@ -8,8 +8,8 @@
import java.util.List;
import java.util.Map;
-import static _test.Sample.asHeading;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.asHeading;
+import static tests.heylogs.api.Sample.using;
import static internal.heylogs.ChangelogNodes.*;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/heylogs-api/src/test/java/internal/heylogs/ExtendedRulesTest.java b/heylogs-api/src/test/java/internal/heylogs/ExtendedRulesTest.java
index e99c17d..0b79c04 100644
--- a/heylogs-api/src/test/java/internal/heylogs/ExtendedRulesTest.java
+++ b/heylogs-api/src/test/java/internal/heylogs/ExtendedRulesTest.java
@@ -1,6 +1,6 @@
package internal.heylogs;
-import _test.Sample;
+import tests.heylogs.api.Sample;
import com.vladsch.flexmark.ast.LinkNodeBase;
import com.vladsch.flexmark.util.ast.Node;
import nbbrd.heylogs.Nodes;
@@ -12,7 +12,7 @@
import java.util.Objects;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.using;
import static internal.heylogs.ExtendedRules.NO_RULE_ISSUE;
import static internal.heylogs.ExtendedRules.validateConsistentSeparator;
import static nbbrd.heylogs.Nodes.of;
diff --git a/heylogs-api/src/test/java/internal/heylogs/GuidingPrinciplesTest.java b/heylogs-api/src/test/java/internal/heylogs/GuidingPrinciplesTest.java
index 69e08c5..5b7de9f 100644
--- a/heylogs-api/src/test/java/internal/heylogs/GuidingPrinciplesTest.java
+++ b/heylogs-api/src/test/java/internal/heylogs/GuidingPrinciplesTest.java
@@ -9,7 +9,7 @@
import java.util.Objects;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.using;
import static internal.heylogs.GuidingPrinciples.validateForHumans;
import static internal.heylogs.GuidingPrinciples.validateLatestVersionFirst;
import static nbbrd.heylogs.Nodes.of;
diff --git a/heylogs-api/src/test/java/internal/heylogs/JsonFormatTest.java b/heylogs-api/src/test/java/internal/heylogs/JsonFormatTest.java
index e28d629..7199b5d 100644
--- a/heylogs-api/src/test/java/internal/heylogs/JsonFormatTest.java
+++ b/heylogs-api/src/test/java/internal/heylogs/JsonFormatTest.java
@@ -4,7 +4,7 @@
import nbbrd.heylogs.spi.FormatLoader;
import org.junit.jupiter.api.Test;
-import static _test.Sample.*;
+import static tests.heylogs.api.Sample.*;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
diff --git a/heylogs-api/src/test/java/internal/heylogs/StylishFormatTest.java b/heylogs-api/src/test/java/internal/heylogs/StylishFormatTest.java
index 2f6f252..d7187e4 100644
--- a/heylogs-api/src/test/java/internal/heylogs/StylishFormatTest.java
+++ b/heylogs-api/src/test/java/internal/heylogs/StylishFormatTest.java
@@ -5,7 +5,7 @@
import nbbrd.heylogs.spi.FormatType;
import org.junit.jupiter.api.Test;
-import static _test.Sample.*;
+import static tests.heylogs.api.Sample.*;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
diff --git a/heylogs-api/src/test/java/internal/heylogs/github/GitHubRulesTest.java b/heylogs-api/src/test/java/internal/heylogs/github/GitHubRulesTest.java
index 7c5e256..36001be 100644
--- a/heylogs-api/src/test/java/internal/heylogs/github/GitHubRulesTest.java
+++ b/heylogs-api/src/test/java/internal/heylogs/github/GitHubRulesTest.java
@@ -1,6 +1,6 @@
package internal.heylogs.github;
-import _test.Sample;
+import tests.heylogs.api.Sample;
import com.vladsch.flexmark.ast.Link;
import com.vladsch.flexmark.util.ast.Node;
import nbbrd.heylogs.Nodes;
@@ -11,7 +11,7 @@
import java.util.Objects;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.using;
import static internal.heylogs.github.GitHubRules.*;
import static java.util.stream.Collectors.toList;
import static nbbrd.heylogs.Nodes.of;
diff --git a/heylogs-api/src/test/java/internal/heylogs/semver/SemVerTest.java b/heylogs-api/src/test/java/internal/heylogs/semver/SemVerTest.java
deleted file mode 100644
index af8239e..0000000
--- a/heylogs-api/src/test/java/internal/heylogs/semver/SemVerTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package internal.heylogs.semver;
-
-import nbbrd.heylogs.spi.VersioningLoader;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class SemVerTest {
-
- @Test
- void getVersioningId() {
- assertThat(new SemVer().getVersioningId())
- .matches(VersioningLoader.ID_PATTERN);
- }
-
- @Test
- void getVersioningName() {
- assertThat(new SemVer().getVersioningName())
- .isNotBlank();
- }
-
- @Test
- void isValidVersion() {
- SemVer x = new SemVer();
- assertThat(x.isValidVersion("1.1.0")).isTrue();
- assertThat(x.isValidVersion(".1.0")).isFalse();
- }
-}
\ No newline at end of file
diff --git a/heylogs-api/src/test/java/nbbrd/heylogs/ChangelogTest.java b/heylogs-api/src/test/java/nbbrd/heylogs/ChangelogTest.java
index edd41f3..675f902 100644
--- a/heylogs-api/src/test/java/nbbrd/heylogs/ChangelogTest.java
+++ b/heylogs-api/src/test/java/nbbrd/heylogs/ChangelogTest.java
@@ -1,12 +1,12 @@
package nbbrd.heylogs;
-import _test.Sample;
+import tests.heylogs.api.Sample;
import com.vladsch.flexmark.ast.Heading;
import org.junit.jupiter.api.Test;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.using;
import static nbbrd.heylogs.Changelog.parse;
-import static _test.Sample.asHeading;
+import static tests.heylogs.api.Sample.asHeading;
import static org.assertj.core.api.Assertions.*;
public class ChangelogTest {
diff --git a/heylogs-api/src/test/java/nbbrd/heylogs/HeylogsTest.java b/heylogs-api/src/test/java/nbbrd/heylogs/HeylogsTest.java
index 0bbf3cb..7ce8e74 100644
--- a/heylogs-api/src/test/java/nbbrd/heylogs/HeylogsTest.java
+++ b/heylogs-api/src/test/java/nbbrd/heylogs/HeylogsTest.java
@@ -1,11 +1,14 @@
package nbbrd.heylogs;
-import _test.Sample;
+import tests.heylogs.api.Sample;
import com.vladsch.flexmark.util.ast.Document;
+import com.vladsch.flexmark.util.ast.Node;
import internal.heylogs.StylishFormat;
-import internal.heylogs.semver.SemVerRule;
+import lombok.NonNull;
import nbbrd.heylogs.spi.Rule;
import nbbrd.heylogs.spi.RuleIssue;
+import nbbrd.heylogs.spi.RuleSeverity;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.jupiter.api.Test;
import java.io.IOException;
@@ -13,7 +16,7 @@
import java.util.List;
import java.util.function.Function;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.using;
import static internal.heylogs.URLExtractor.urlOf;
import static java.util.Collections.singletonList;
import static nbbrd.heylogs.Filter.builder;
@@ -36,11 +39,11 @@ public void testFactories() {
.map(Rule::getRuleId)
.doesNotContain("semver");
- assertThat(Heylogs.ofServiceLoader().toBuilder().rule(new SemVerRule()).build())
+ assertThat(Heylogs.ofServiceLoader().toBuilder().rule(new MockedRule()).build())
.extracting(Heylogs::getRules, list(Rule.class))
.hasSizeGreaterThan(1)
.map(Rule::getRuleId)
- .contains("semver");
+ .contains("mocked");
}
@Test
@@ -156,7 +159,7 @@ public void testScanContent() {
.valid(true)
.releaseCount(13)
.timeRange(TimeRange.of(LocalDate.of(2014, 5, 31), LocalDate.of(2019, 2, 15)))
- .compatibility("Semantic Versioning")
+// .compatibility("Semantic Versioning")
.unreleasedChanges(2)
.forgeName("GitHub")
.forgeURL(urlOf("https://github.com/olivierlacan/keep-a-changelog"))
@@ -250,4 +253,37 @@ private static String releaseChangesToString(Heylogs heylogs, Document doc, Vers
heylogs.releaseChanges(doc, version, "v");
return Sample.FORMATTER.render(doc);
}
+
+ private static final class MockedRule implements Rule {
+
+ @Override
+ public @NonNull String getRuleId() {
+ return "mocked";
+ }
+
+ @Override
+ public @NonNull String getRuleName() {
+ return "";
+ }
+
+ @Override
+ public @NonNull String getRuleCategory() {
+ return "";
+ }
+
+ @Override
+ public boolean isRuleAvailable() {
+ return false;
+ }
+
+ @Override
+ public @NonNull RuleSeverity getRuleSeverity() {
+ return RuleSeverity.OFF;
+ }
+
+ @Override
+ public @Nullable RuleIssue getRuleIssueOrNull(@NonNull Node node) {
+ return null;
+ }
+ }
}
diff --git a/heylogs-api/src/test/java/nbbrd/heylogs/NodesTest.java b/heylogs-api/src/test/java/nbbrd/heylogs/NodesTest.java
index 694b77b..0820c69 100644
--- a/heylogs-api/src/test/java/nbbrd/heylogs/NodesTest.java
+++ b/heylogs-api/src/test/java/nbbrd/heylogs/NodesTest.java
@@ -4,7 +4,7 @@
import internal.heylogs.ChangelogNodes;
import org.junit.jupiter.api.Test;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.using;
import static org.assertj.core.api.Assertions.assertThat;
class NodesTest {
diff --git a/heylogs-api/src/test/java/nbbrd/heylogs/TypeOfChangeTest.java b/heylogs-api/src/test/java/nbbrd/heylogs/TypeOfChangeTest.java
index ebd732c..0ff8f53 100644
--- a/heylogs-api/src/test/java/nbbrd/heylogs/TypeOfChangeTest.java
+++ b/heylogs-api/src/test/java/nbbrd/heylogs/TypeOfChangeTest.java
@@ -1,11 +1,11 @@
package nbbrd.heylogs;
-import _test.Sample;
+import tests.heylogs.api.Sample;
import com.vladsch.flexmark.ast.Heading;
import org.junit.jupiter.api.Test;
-import static _test.Sample.asHeading;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.asHeading;
+import static tests.heylogs.api.Sample.using;
import static nbbrd.heylogs.TypeOfChange.parse;
import static org.assertj.core.api.Assertions.*;
diff --git a/heylogs-api/src/test/java/nbbrd/heylogs/VersionTest.java b/heylogs-api/src/test/java/nbbrd/heylogs/VersionTest.java
index 8a4282e..d9f2a55 100644
--- a/heylogs-api/src/test/java/nbbrd/heylogs/VersionTest.java
+++ b/heylogs-api/src/test/java/nbbrd/heylogs/VersionTest.java
@@ -1,13 +1,13 @@
package nbbrd.heylogs;
-import _test.Sample;
+import tests.heylogs.api.Sample;
import com.vladsch.flexmark.ast.Heading;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
-import static _test.Sample.asHeading;
-import static _test.Sample.using;
+import static tests.heylogs.api.Sample.asHeading;
+import static tests.heylogs.api.Sample.using;
import static nbbrd.heylogs.Version.*;
import static org.assertj.core.api.Assertions.*;
diff --git a/heylogs-api/src/test/java/_test/Sample.java b/heylogs-api/src/test/java/tests/heylogs/api/Sample.java
similarity index 99%
rename from heylogs-api/src/test/java/_test/Sample.java
rename to heylogs-api/src/test/java/tests/heylogs/api/Sample.java
index 8ef758d..e623310 100644
--- a/heylogs-api/src/test/java/_test/Sample.java
+++ b/heylogs-api/src/test/java/tests/heylogs/api/Sample.java
@@ -1,4 +1,4 @@
-package _test;
+package tests.heylogs.api;
import com.vladsch.flexmark.ast.Heading;
import com.vladsch.flexmark.formatter.Formatter;
diff --git a/heylogs-api/src/test/java/tests/heylogs/spi/RuleAssert.java b/heylogs-api/src/test/java/tests/heylogs/spi/RuleAssert.java
new file mode 100644
index 0000000..817f6c6
--- /dev/null
+++ b/heylogs-api/src/test/java/tests/heylogs/spi/RuleAssert.java
@@ -0,0 +1,37 @@
+package tests.heylogs.spi;
+
+import lombok.NonNull;
+import nbbrd.heylogs.spi.Rule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNullPointerException;
+
+public final class RuleAssert {
+
+ private RuleAssert() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
+ @SuppressWarnings("DataFlowIssue")
+ public static void assertRuleCompliance(@NonNull Rule x) {
+ assertThat(x.getRuleId())
+ .matches(nbbrd.heylogs.spi.RuleLoader.ID_PATTERN);
+
+ assertThat(x.getRuleName())
+ .isNotEmpty()
+ .isNotNull();
+
+ assertThat(x.getRuleCategory())
+ .isNotEmpty()
+ .isNotNull();
+
+ assertThat(x.getRuleSeverity())
+ .isNotNull();
+
+ assertThatNullPointerException()
+ .isThrownBy(() -> x.getRuleIssueOrNull(null));
+
+ assertThat(x.getClass())
+ .isFinal();
+ }
+}
diff --git a/heylogs-api/src/test/java/tests/heylogs/spi/VersioningAssert.java b/heylogs-api/src/test/java/tests/heylogs/spi/VersioningAssert.java
new file mode 100644
index 0000000..b97f166
--- /dev/null
+++ b/heylogs-api/src/test/java/tests/heylogs/spi/VersioningAssert.java
@@ -0,0 +1,30 @@
+package tests.heylogs.spi;
+
+import lombok.NonNull;
+import nbbrd.heylogs.spi.Versioning;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNullPointerException;
+
+public final class VersioningAssert {
+
+ private VersioningAssert() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
+ @SuppressWarnings("DataFlowIssue")
+ public static void assertVersioningCompliance(@NonNull Versioning x) {
+ assertThat(x.getVersioningId())
+ .matches(nbbrd.heylogs.spi.VersioningLoader.ID_PATTERN);
+
+ assertThat(x.getVersioningName())
+ .isNotEmpty()
+ .isNotNull();
+
+ assertThatNullPointerException()
+ .isThrownBy(() -> x.isValidVersion(null));
+
+ assertThat(x.getClass())
+ .isFinal();
+ }
+}
diff --git a/heylogs-bom/pom.xml b/heylogs-bom/pom.xml
index 9c076b8..ced5425 100644
--- a/heylogs-bom/pom.xml
+++ b/heylogs-bom/pom.xml
@@ -24,11 +24,23 @@
${project.groupId}
${project.version}
+
+ heylogs-api
+ ${project.groupId}
+ ${project.version}
+ tests
+ test-jar
+
heylogs-cli
${project.groupId}
${project.version}
+
+ heylogs-ext-semver
+ ${project.groupId}
+ ${project.version}
+
heylogs-maven-plugin
${project.groupId}
diff --git a/heylogs-cli/pom.xml b/heylogs-cli/pom.xml
index e1d2972..4557c9d 100644
--- a/heylogs-cli/pom.xml
+++ b/heylogs-cli/pom.xml
@@ -46,6 +46,11 @@
${project.groupId}
${project.version}
+
+ heylogs-ext-semver
+ ${project.groupId}
+ ${project.version}
+
info.picocli
picocli
diff --git a/heylogs-cli/src/main/java/internal/heylogs/cli/HeylogsOptions.java b/heylogs-cli/src/main/java/internal/heylogs/cli/HeylogsOptions.java
index 019e4a4..78e12f5 100644
--- a/heylogs-cli/src/main/java/internal/heylogs/cli/HeylogsOptions.java
+++ b/heylogs-cli/src/main/java/internal/heylogs/cli/HeylogsOptions.java
@@ -1,7 +1,7 @@
package internal.heylogs.cli;
-import internal.heylogs.semver.SemVerRule;
import nbbrd.heylogs.Heylogs;
+import nbbrd.heylogs.ext.semver.SemVerRule;
import picocli.CommandLine;
@lombok.Getter
diff --git a/heylogs-ext-semver/pom.xml b/heylogs-ext-semver/pom.xml
new file mode 100644
index 0000000..9d66342
--- /dev/null
+++ b/heylogs-ext-semver/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+
+
+ com.github.nbbrd.heylogs
+ heylogs-parent
+ 0.8.2-SNAPSHOT
+
+
+ heylogs-ext-semver
+ jar
+
+
+
+
+ org.checkerframework
+ checker-qual
+ provided
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+ com.github.nbbrd.java-design-util
+ java-design-processor
+ provided
+
+
+ com.github.nbbrd.java-service-util
+ java-service-processor
+ provided
+
+
+
+
+ heylogs-api
+ ${project.groupId}
+ ${project.version}
+
+
+ org.semver4j
+ semver4j
+ 5.3.0
+
+
+ org.jetbrains
+ annotations
+
+
+
+
+
+
+ heylogs-api
+ ${project.groupId}
+ ${project.version}
+ tests
+ test-jar
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+
\ No newline at end of file
diff --git a/heylogs-api/src/main/java/internal/heylogs/semver/SemVer.java b/heylogs-ext-semver/src/main/java/nbbrd/heylogs/ext/semver/SemVer.java
similarity index 94%
rename from heylogs-api/src/main/java/internal/heylogs/semver/SemVer.java
rename to heylogs-ext-semver/src/main/java/nbbrd/heylogs/ext/semver/SemVer.java
index 1eb2947..1a4d719 100644
--- a/heylogs-api/src/main/java/internal/heylogs/semver/SemVer.java
+++ b/heylogs-ext-semver/src/main/java/nbbrd/heylogs/ext/semver/SemVer.java
@@ -1,4 +1,4 @@
-package internal.heylogs.semver;
+package nbbrd.heylogs.ext.semver;
import lombok.NonNull;
import nbbrd.design.DirectImpl;
diff --git a/heylogs-api/src/main/java/internal/heylogs/semver/SemVerRule.java b/heylogs-ext-semver/src/main/java/nbbrd/heylogs/ext/semver/SemVerRule.java
similarity index 98%
rename from heylogs-api/src/main/java/internal/heylogs/semver/SemVerRule.java
rename to heylogs-ext-semver/src/main/java/nbbrd/heylogs/ext/semver/SemVerRule.java
index 6190ef4..3411678 100644
--- a/heylogs-api/src/main/java/internal/heylogs/semver/SemVerRule.java
+++ b/heylogs-ext-semver/src/main/java/nbbrd/heylogs/ext/semver/SemVerRule.java
@@ -1,4 +1,4 @@
-package internal.heylogs.semver;
+package nbbrd.heylogs.ext.semver;
import com.vladsch.flexmark.ast.Heading;
import com.vladsch.flexmark.util.ast.Node;
diff --git a/heylogs-api/src/test/java/internal/heylogs/semver/SemVerRuleTest.java b/heylogs-ext-semver/src/test/java/nbbrd/heylogs/ext/semver/SemVerRuleTest.java
similarity index 85%
rename from heylogs-api/src/test/java/internal/heylogs/semver/SemVerRuleTest.java
rename to heylogs-ext-semver/src/test/java/nbbrd/heylogs/ext/semver/SemVerRuleTest.java
index 1809a66..5cff839 100644
--- a/heylogs-api/src/test/java/internal/heylogs/semver/SemVerRuleTest.java
+++ b/heylogs-ext-semver/src/test/java/nbbrd/heylogs/ext/semver/SemVerRuleTest.java
@@ -1,23 +1,22 @@
-package internal.heylogs.semver;
+package nbbrd.heylogs.ext.semver;
import com.vladsch.flexmark.ast.Heading;
import com.vladsch.flexmark.util.ast.Node;
import nbbrd.heylogs.spi.RuleIssue;
-import nbbrd.heylogs.spi.RuleLoader;
import org.junit.jupiter.api.Test;
import java.util.Objects;
-import static _test.Sample.using;
import static nbbrd.heylogs.Nodes.of;
import static org.assertj.core.api.Assertions.assertThat;
+import static tests.heylogs.api.Sample.using;
+import static tests.heylogs.spi.RuleAssert.assertRuleCompliance;
public class SemVerRuleTest {
@Test
- public void testIdPattern() {
- assertThat(new SemVerRule().getRuleId())
- .matches(RuleLoader.ID_PATTERN);
+ public void testCompliance() {
+ assertRuleCompliance(new SemVerRule());
}
@Test
diff --git a/heylogs-ext-semver/src/test/java/nbbrd/heylogs/ext/semver/SemVerTest.java b/heylogs-ext-semver/src/test/java/nbbrd/heylogs/ext/semver/SemVerTest.java
new file mode 100644
index 0000000..423fb5d
--- /dev/null
+++ b/heylogs-ext-semver/src/test/java/nbbrd/heylogs/ext/semver/SemVerTest.java
@@ -0,0 +1,21 @@
+package nbbrd.heylogs.ext.semver;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static tests.heylogs.spi.VersioningAssert.assertVersioningCompliance;
+
+class SemVerTest {
+
+ @Test
+ public void testCompliance() {
+ assertVersioningCompliance(new SemVer());
+ }
+
+ @Test
+ void isValidVersion() {
+ SemVer x = new SemVer();
+ assertThat(x.isValidVersion("1.1.0")).isTrue();
+ assertThat(x.isValidVersion(".1.0")).isFalse();
+ }
+}
\ No newline at end of file
diff --git a/heylogs-ext-semver/src/test/resources/Empty.md b/heylogs-ext-semver/src/test/resources/Empty.md
new file mode 100644
index 0000000..e69de29
diff --git a/heylogs-ext-semver/src/test/resources/InvalidSemver.md b/heylogs-ext-semver/src/test/resources/InvalidSemver.md
new file mode 100644
index 0000000..886858b
--- /dev/null
+++ b/heylogs-ext-semver/src/test/resources/InvalidSemver.md
@@ -0,0 +1,7 @@
+# Changelog
+
+## [1.1.0] - 2019-02-15
+## [.1.0] - 2019-02-15
+
+[1.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...v1.1.0
+[.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...v1.1.0
diff --git a/heylogs-ext-semver/src/test/resources/Main.md b/heylogs-ext-semver/src/test/resources/Main.md
new file mode 100644
index 0000000..145e79f
--- /dev/null
+++ b/heylogs-ext-semver/src/test/resources/Main.md
@@ -0,0 +1,206 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+### Added
+
+- Added Dutch translation
+
+### Fixed
+
+- Fixed foldouts in Dutch translation
+
+## [1.1.0] - 2019-02-15
+
+### Added
+
+- Danish translation from [@frederikspang](https://github.com/frederikspang).
+- Georgian translation from [@tatocaster](https://github.com/tatocaster).
+- Changelog inconsistency section in Bad Practices
+
+### Changed
+
+- Fixed typos in Italian translation from [@lorenzo-arena](https://github.com/lorenzo-arena).
+- Fixed typos in Indonesian translation from [@ekojs](https://github.com/ekojs).
+
+## [1.0.0] - 2017-06-20
+
+### Added
+
+- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
+- Version navigation.
+- Links to latest released version in previous versions.
+- "Why keep a changelog?" section.
+- "Who needs a changelog?" section.
+- "How do I make a changelog?" section.
+- "Frequently Asked Questions" section.
+- New "Guiding Principles" sub-section to "How do I make a changelog?".
+- Simplified and Traditional Chinese translations from [@tianshuo](https://github.com/tianshuo).
+- German translation from [@mpbzh](https://github.com/mpbzh) & [@Art4](https://github.com/Art4).
+- Italian translation from [@azkidenz](https://github.com/azkidenz).
+- Swedish translation from [@magol](https://github.com/magol).
+- Turkish translation from [@emreerkan](https://github.com/emreerkan).
+- French translation from [@zapashcanon](https://github.com/zapashcanon).
+- Brazilian Portuguese translation from [@Webysther](https://github.com/Webysther).
+- Polish translation from [@amielucha](https://github.com/amielucha) & [@m-aciek](https://github.com/m-aciek).
+- Russian translation from [@aishek](https://github.com/aishek).
+- Czech translation from [@h4vry](https://github.com/h4vry).
+- Slovak translation from [@jkostolansky](https://github.com/jkostolansky).
+- Korean translation from [@pierceh89](https://github.com/pierceh89).
+- Croatian translation from [@porx](https://github.com/porx).
+- Persian translation from [@Hameds](https://github.com/Hameds).
+- Ukrainian translation from [@osadchyi-s](https://github.com/osadchyi-s).
+
+### Changed
+
+- Start using "changelog" over "change log" since it's the common usage.
+- Start versioning based on the current English version at 0.3.0 to help
+ translation authors keep things up-to-date.
+- Rewrite "What makes unicorns cry?" section.
+- Rewrite "Ignoring Deprecations" sub-section to clarify the ideal
+ scenario.
+- Improve "Commit log diffs" sub-section to further argument against
+ them.
+- Merge "Why can’t people just use a git log diff?" with "Commit log
+ diffs"
+- Fix typos in Simplified Chinese and Traditional Chinese translations.
+- Fix typos in Brazilian Portuguese translation.
+- Fix typos in Turkish translation.
+- Fix typos in Czech translation.
+- Fix typos in Swedish translation.
+- Improve phrasing in French translation.
+- Fix phrasing and spelling in German translation.
+
+### Removed
+
+- Section about "changelog" vs "CHANGELOG".
+
+## [0.3.0] - 2015-12-03
+
+### Added
+
+- RU translation from [@aishek](https://github.com/aishek).
+- pt-BR translation from [@tallesl](https://github.com/tallesl).
+- es-ES translation from [@ZeliosAriex](https://github.com/ZeliosAriex).
+
+## [0.2.0] - 2015-10-06
+
+### Changed
+
+- Remove exclusionary mentions of "open source" since this project can
+ benefit both "open" and "closed" source projects equally.
+
+## [0.1.0] - 2015-10-06
+
+### Added
+
+- Answer "Should you ever rewrite a change log?".
+
+### Changed
+
+- Improve argument against commit logs.
+- Start following [SemVer](https://semver.org) properly.
+
+## [0.0.8] - 2015-02-17
+
+### Changed
+
+- Update year to match in every README example.
+- Reluctantly stop making fun of Brits only, since most of the world
+ writes dates in a strange way.
+
+### Fixed
+
+- Fix typos in recent README changes.
+- Update outdated unreleased diff link.
+
+## [0.0.7] - 2015-02-16
+
+### Added
+
+- Link, and make it obvious that date format is ISO 8601.
+
+### Changed
+
+- Clarified the section on "Is there a standard change log format?".
+
+### Fixed
+
+- Fix Markdown links to tag comparison URL with footnote-style links.
+
+## [0.0.6] - 2014-12-12
+
+### Added
+
+- README section on "yanked" releases.
+
+## [0.0.5] - 2014-08-09
+
+### Added
+
+- Markdown links to version tags on release headings.
+- Unreleased section to gather unreleased changes and encourage note
+ keeping prior to releases.
+
+## [0.0.4] - 2014-08-09
+
+### Added
+
+- Better explanation of the difference between the file ("CHANGELOG")
+ and its function "the change log".
+
+### Changed
+
+- Refer to a "change log" instead of a "CHANGELOG" throughout the site
+ to differentiate between the file and the purpose of the file — the
+ logging of changes.
+
+### Removed
+
+- Remove empty sections from CHANGELOG, they occupy too much space and
+ create too much noise in the file. People will have to assume that the
+ missing sections were intentionally left out because they contained no
+ notable changes.
+
+## [0.0.3] - 2014-08-09
+
+### Added
+
+- "Why should I care?" section mentioning The Changelog podcast.
+
+## [0.0.2] - 2014-07-10
+
+### Added
+
+- Explanation of the recommended reverse chronological release ordering.
+
+## [0.0.1] - 2014-05-31
+
+### Added
+
+- This CHANGELOG file to hopefully serve as an evolving example of a
+ standardized open source project CHANGELOG.
+- CNAME file to enable GitHub Pages custom domain
+- README now contains answers to common questions about CHANGELOGs
+- Good examples and basic guidelines, including proper date formatting.
+- Counter-examples: "What makes unicorns cry?"
+
+[unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.1.0...HEAD
+[1.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...v1.1.0
+[1.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0
+[0.3.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.2.0...v0.3.0
+[0.2.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.1.0...v0.2.0
+[0.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.8...v0.1.0
+[0.0.8]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.7...v0.0.8
+[0.0.7]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.6...v0.0.7
+[0.0.6]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.5...v0.0.6
+[0.0.5]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.4...v0.0.5
+[0.0.4]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.3...v0.0.4
+[0.0.3]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.2...v0.0.3
+[0.0.2]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.1...v0.0.2
+[0.0.1]: https://github.com/olivierlacan/keep-a-changelog/releases/tag/v0.0.1
\ No newline at end of file
diff --git a/heylogs-maven-plugin/pom.xml b/heylogs-maven-plugin/pom.xml
index 727bafa..e8ee2f1 100644
--- a/heylogs-maven-plugin/pom.xml
+++ b/heylogs-maven-plugin/pom.xml
@@ -59,6 +59,11 @@
${project.groupId}
${project.version}
+
+ heylogs-ext-semver
+ ${project.groupId}
+ ${project.version}
+
com.github.nbbrd.java-console-properties
java-console-properties
diff --git a/heylogs-maven-plugin/src/main/java/nbbrd/heylogs/maven/plugin/CheckMojo.java b/heylogs-maven-plugin/src/main/java/nbbrd/heylogs/maven/plugin/CheckMojo.java
index 717b669..7ce1f88 100644
--- a/heylogs-maven-plugin/src/main/java/nbbrd/heylogs/maven/plugin/CheckMojo.java
+++ b/heylogs-maven-plugin/src/main/java/nbbrd/heylogs/maven/plugin/CheckMojo.java
@@ -1,9 +1,9 @@
package nbbrd.heylogs.maven.plugin;
import internal.heylogs.StylishFormat;
-import internal.heylogs.semver.SemVer;
import nbbrd.heylogs.Check;
import nbbrd.heylogs.Heylogs;
+import nbbrd.heylogs.ext.semver.SemVer;
import nbbrd.heylogs.spi.Versioning;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
diff --git a/heylogs-maven-plugin/src/main/java/nbbrd/heylogs/maven/plugin/HeylogsMojo.java b/heylogs-maven-plugin/src/main/java/nbbrd/heylogs/maven/plugin/HeylogsMojo.java
index 0cce37e..1ea666e 100644
--- a/heylogs-maven-plugin/src/main/java/nbbrd/heylogs/maven/plugin/HeylogsMojo.java
+++ b/heylogs-maven-plugin/src/main/java/nbbrd/heylogs/maven/plugin/HeylogsMojo.java
@@ -3,9 +3,9 @@
import com.vladsch.flexmark.formatter.Formatter;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Document;
-import internal.heylogs.semver.SemVerRule;
import nbbrd.design.MightBePromoted;
import nbbrd.heylogs.Heylogs;
+import nbbrd.heylogs.ext.semver.SemVerRule;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
diff --git a/pom.xml b/pom.xml
index 577f3fd..42ca725 100644
--- a/pom.xml
+++ b/pom.xml
@@ -243,6 +243,7 @@
heylogs-cli
heylogs-maven-plugin
heylogs-bom
+ heylogs-ext-semver