Skip to content
Closed
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 docs/source/docset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,4 @@ toc:
- file: index.md
- file: req.md
- folder: nested
- file: external-links.md
9 changes: 9 additions & 0 deletions docs/source/testing/external-links.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: "External Links"
---

[inline external link](kibana://path/to/file.md)

[reference external link][1]

[1]: kibana://path/to/another/file.md
17 changes: 11 additions & 6 deletions src/Elastic.Markdown/IO/LinkReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,24 @@ public record LinkReference
[JsonPropertyName("url_path_prefix")]
public required string? UrlPathPrefix { get; init; }

[JsonPropertyName("links")]
public required string[] Links { get; init; } = [];
[JsonPropertyName("internal_links")]
public required string[] InternalLinks { get; init; } = [];

[JsonPropertyName("external_links")]
public required string[] ExternalLinks { get; init; } = [];

public static LinkReference Create(DocumentationSet set)
{
var links = set.FlatMappedFiles.Values
.OfType<MarkdownFile>()
.Select(m => m.RelativePath).ToArray();
var markdownFiles = set.FlatMappedFiles.Values.OfType<MarkdownFile>().ToArray();
var internalLinks = markdownFiles.Select(m => m.RelativePath).ToArray();
var externalLinks = markdownFiles.SelectMany(m => m.Links).ToHashSet().ToArray();
return new LinkReference
{
UrlPathPrefix = set.Context.UrlPathPrefix,
Origin = set.Context.Git,
Links = links
InternalLinks = internalLinks,
ExternalLinks = externalLinks
};
}

}
15 changes: 15 additions & 0 deletions src/Elastic.Markdown/IO/MarkdownFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Markdig;
using Markdig.Extensions.Yaml;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
using Slugify;

namespace Elastic.Markdown.IO;
Expand Down Expand Up @@ -42,6 +43,7 @@ public string? NavigationTitle
get => !string.IsNullOrEmpty(_navigationTitle) ? _navigationTitle : Title;
private set => _navigationTitle = value;
}
public IReadOnlySet<string> Links { get; private set; } = new HashSet<string>();

//indexed by slug
private readonly Dictionary<string, PageTocItem> _tableOfContent = new();
Expand All @@ -56,6 +58,8 @@ public string? NavigationTitle

private bool _instructionsParsed;

public static readonly HashSet<string> ExcludedExternalLinkSchemes = ["http", "https", "mailto", "tel", "file"];

public MarkdownFile[] YieldParents()
{
var parents = new List<MarkdownFile>();
Expand All @@ -82,11 +86,22 @@ public async Task<MarkdownDocument> ParseFullAsync(Cancel ctx)
await MinimalParse(ctx);

var document = await MarkdownParser.ParseAsync(SourceFile, YamlFrontMatter, ctx);
ReadLinks(document);
if (Title == RelativePath)
Collector.EmitWarning(SourceFile.FullName, "Missing yaml front-matter block defining a title or a level 1 header");
return document;
}

private void ReadLinks(MarkdownDocument document)
{
var links = document.Descendants<LinkInline>()
.Select(l => l.Url)
.Where(l => !string.IsNullOrEmpty(l) && !l.StartsWith('/'))
.Where(url => Uri.TryCreate(url, UriKind.Absolute, out var uri) && !ExcludedExternalLinkSchemes.Contains(uri.Scheme));

Links = new HashSet<string>(links!);
}

private void ReadDocumentInstructions(MarkdownDocument document)
{
if (document.FirstOrDefault() is YamlFrontMatterBlock yaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
return match;

var url = link.Url;
var uri = Uri.TryCreate(url, UriKind.Absolute, out var u) ? u : null;
var line = link.Line + 1;
var column = link.Column;
var length = url?.Length ?? 1;
Expand All @@ -58,7 +59,12 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
return match;
}

if (Uri.TryCreate(url, UriKind.Absolute, out var uri) && uri.Scheme.StartsWith("http"))
if (uri != null && !MarkdownFile.ExcludedExternalLinkSchemes.Contains(uri.Scheme))
{
return match;
}

if (uri != null && uri.Scheme.StartsWith("http"))
{
var baseDomain = uri.Host == "localhost" ? "localhost" : string.Join('.', uri.Host.Split('.')[^2..]);
if (!context.Configuration.ExternalLinkHosts.Contains(baseDomain))
Expand Down Expand Up @@ -128,8 +134,5 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
link.Url += $"#{anchor}";

return match;



}
}
Loading