Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add built-in integration for community documentation #937

Merged
merged 12 commits into from
Aug 10, 2022
22 changes: 9 additions & 13 deletions Bonsai.Configuration/ConfigurationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,29 +80,25 @@ public static IDictionary<string, PackageReference> GetPackageReferenceMap(this
return packageMap;
}

public static IEnumerable<PackageReference> GetAssemblyPackageReferences(
public static PackageReference GetAssemblyPackageReference(
this PackageConfiguration configuration,
IEnumerable<string> assemblyNames,
string assemblyName,
IDictionary<string, PackageReference> packageMap)
{
var dependencies = new List<PackageReference>();
foreach (var assemblyName in assemblyNames)
var assemblyLocation = GetAssemblyLocation(configuration, assemblyName);
if (assemblyLocation != null)
{
var assemblyLocation = GetAssemblyLocation(configuration, assemblyName);
if (assemblyLocation != null)
var pathElements = assemblyLocation.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
if (pathElements.Length > 1 && pathElements[0] == RepositoryPath)
{
var pathElements = assemblyLocation.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
if (pathElements.Length > 1 && pathElements[0] == RepositoryPath)
if (packageMap.TryGetValue(pathElements[1], out PackageReference package))
{
if (packageMap.TryGetValue(pathElements[1], out PackageReference package))
{
dependencies.Add(package);
}
return package;
}
}
}

return dependencies;
return null;
}

public static void SetAssemblyResolve(PackageConfiguration configuration)
Expand Down
4 changes: 3 additions & 1 deletion Bonsai.Configuration/ScriptExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ public void AddAssemblyReferences(IEnumerable<string> assemblyReferences)
var projectReferences = root.Descendants(PackageReferenceElement).ToArray();
var lastReference = projectReferences.LastOrDefault();

var packageReferences = packageConfiguration.GetAssemblyPackageReferences(assemblyReferences, packageMap);
var packageReferences = assemblyReferences
.Select(assemblyName => packageConfiguration.GetAssemblyPackageReference(assemblyName, packageMap))
.Where(package => package != null);
foreach (var reference in packageReferences)
{
var includeAttribute = new XAttribute(PackageIncludeAttribute, reference.Id);
Expand Down
1 change: 1 addition & 0 deletions Bonsai.Editor/Bonsai.Editor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ItemGroup>
<PackageReference Include="Rx-PlatformServices" Version="2.2.5" />
<PackageReference Include="SvgNet" Version="2.2.2" />
<PackageReference Include="YamlDotNet" Version="11.2.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Bonsai.Design\Bonsai.Design.csproj" />
Expand Down
98 changes: 98 additions & 0 deletions Bonsai.Editor/DocumentationHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Cache;
using System.Threading.Tasks;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace Bonsai.Editor
{
static class DocumentationHelper
{
public static async Task<Uri> GetDocumentationAsync(this IDocumentationProvider provider, string assemblyName, string uid)
{
var baseUrl = provider.GetDocumentationUrl(assemblyName);
if (string.IsNullOrEmpty(baseUrl))
{
throw new ArgumentException($"No documentation found for the specified module.", nameof(assemblyName));
}

return await GetDocumentationAsync(baseUrl, uid);
}

static async Task<Uri> GetDocumentationAsync(string baseUrl, string uid)
{
var lookup = await GetXRefMapAsync(baseUrl.TrimEnd('/'), "/docs", string.Empty);
return new Uri(lookup[uid]);
}

static async Task<Dictionary<string, string>> GetXRefMapAsync(string baseUrl, params string[] hrefs)
{
if (hrefs == null || hrefs.Length == 0)
{
throw new ArgumentException("No downstream URLs have been specified.", nameof(hrefs));
}

WebException lastException = default;
for (int i = 0; i < hrefs.Length; i++)
{
try { return await GetXRefMapAsync($"{baseUrl}{hrefs[i]}"); }
catch (WebException ex) when (ex.Response is HttpWebResponse httpResponse &&
httpResponse.StatusCode is HttpStatusCode.NotFound)
{
lastException = ex;
continue;
}
}

throw lastException;
}

static async Task<Dictionary<string, string>> GetXRefMapAsync(string baseUrl)
{
const int ReadWriteTimeout = 10000;
var requestUrl = $"{baseUrl}/xrefmap.yml";
var request = WebRequest.CreateHttp(requestUrl);
request.ReadWriteTimeout = ReadWriteTimeout;
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate);
using var response = await request.GetResponseAsync();
var stream = response.GetResponseStream();
using var reader = new StreamReader(stream);
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build();
var xrefmap = deserializer.Deserialize<XRefMap>(reader);
return xrefmap.References.ToDictionary(
reference => reference.Uid,
reference => $"{baseUrl}/{reference.Href}");
}

class XRefMap
{
public bool? Sorted { get; set; }

public List<XRefSpec> References { get; set; }
}

class XRefSpec
{
public string Uid { get; set; }

public string Name { get; set; }

public string Href { get; set; }

public string CommentId { get; set; }

public string FullName { get; set; }

public string NameWithType { get; set; }

public bool? IsSpec { get; set; }
}
}
}
13 changes: 9 additions & 4 deletions Bonsai.Editor/EditorDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ namespace Bonsai.Editor
{
static class EditorDialog
{
public static void OpenUri(string url)
public static void OpenUrl(Uri url)
{
OpenUrl(url.AbsoluteUri);
}

public static void OpenUrl(string url)
{
var validUrl = Uri.TryCreate(url, UriKind.Absolute, out Uri result) &&
(result.Scheme == Uri.UriSchemeFile || result.Scheme == Uri.UriSchemeHttp || result.Scheme == Uri.UriSchemeHttps);
Expand Down Expand Up @@ -34,17 +39,17 @@ public static void OpenUri(string url)

public static void ShowDocs()
{
OpenUri("http://bonsai-rx.org/docs/editor/");
OpenUrl("https://bonsai-rx.org/docs/articles/editor");
}

public static void ShowForum()
{
OpenUri("https://github.com/bonsai-rx/bonsai/discussions");
OpenUrl("https://github.com/bonsai-rx/bonsai/discussions");
}

public static void ShowReportBug()
{
OpenUri("https://github.com/bonsai-rx/bonsai/issues");
OpenUrl("https://github.com/bonsai-rx/bonsai/issues");
}

public static void ShowAboutBox()
Expand Down
32 changes: 23 additions & 9 deletions Bonsai.Editor/EditorForm.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading