diff --git a/src/Elastic.Markdown/Myst/InlineParsers/DiagnosticLinkInlineParser.cs b/src/Elastic.Markdown/Myst/InlineParsers/DiagnosticLinkInlineParser.cs index 0f2f1b614..f38bab684 100644 --- a/src/Elastic.Markdown/Myst/InlineParsers/DiagnosticLinkInlineParser.cs +++ b/src/Elastic.Markdown/Myst/InlineParsers/DiagnosticLinkInlineParser.cs @@ -184,6 +184,12 @@ private static void ProcessCrossLink(LinkInline link, InlineProcessor processor, uri, out var resolvedUri) ) link.Url = resolvedUri.ToString(); + + // Emit error for empty link text in crosslinks + if (link.FirstChild == null) + { + processor.EmitError(link, $"Crosslink '{url}' has empty link text. Please provide explicit link text."); + } } private static void ProcessInternalLink(LinkInline link, InlineProcessor processor, ParserContext context) diff --git a/tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs b/tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs index a7644bf99..142f453f5 100644 --- a/tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs +++ b/tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs @@ -164,6 +164,62 @@ public void EmitsCrossLink() } } +public class CrossLinkEmptyTextTest(ITestOutputHelper output) : LinkTestBase(output, + """ + + Go to [](kibana://index.md) + """ +) +{ + [Fact] + public void GeneratesHtml() => + // language=html - empty crosslinks now emit an error + Html.Should().Contain( + """
""" + ); + + [Fact] + public void HasError() => + Collector.Diagnostics.Should().Contain(d => + d.Severity == Severity.Error && + d.Message.Contains("empty link text")); + + [Fact] + public void EmitsCrossLink() + { + Collector.CrossLinks.Should().HaveCount(1); + Collector.CrossLinks.Should().Contain("kibana://index.md"); + } +} + +public class CrossLinkEmptyTextNoTitleTest(ITestOutputHelper output) : LinkTestBase(output, + """ + + Go to [](kibana://get-started/index.md) + """ +) +{ + [Fact] + public void GeneratesHtml() => + // language=html - empty crosslinks emit an error + Html.Should().Contain( + """""" + ); + + [Fact] + public void HasError() => + Collector.Diagnostics.Should().Contain(d => + d.Severity == Severity.Error && + d.Message.Contains("empty link text")); + + [Fact] + public void EmitsCrossLink() + { + Collector.CrossLinks.Should().HaveCount(1); + Collector.CrossLinks.Should().Contain("kibana://get-started/index.md"); + } +} + public class LinkWithUnresolvedInterpolationError(ITestOutputHelper output) : LinkTestBase(output, """ [global search field]({{this-variable-does-not-exist}}/introduction.html#kibana-navigation-search) diff --git a/tests/authoring/Framework/TestCrossLinkResolver.fs b/tests/authoring/Framework/TestCrossLinkResolver.fs index 6657de9d1..a8357699e 100644 --- a/tests/authoring/Framework/TestCrossLinkResolver.fs +++ b/tests/authoring/Framework/TestCrossLinkResolver.fs @@ -90,3 +90,4 @@ type TestCrossLinkResolver (config: ConfigurationFile) = CrossLinkResolver.TryResolve(errorEmitter, crossLinks, uriResolver, crossLinkUri, &resolvedUri) +