Skip to content
This repository has been archived by the owner on Apr 19, 2022. It is now read-only.

Commit

Permalink
improved the slug that was chosen for a file
Browse files Browse the repository at this point in the history
  • Loading branch information
aarondandy committed Dec 22, 2014
1 parent b39a6d3 commit 3dc9f32
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 23 deletions.
69 changes: 51 additions & 18 deletions src/DuckyDocs.SiteBuilder/StaticApiPageGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,63 @@ namespace DuckyDocs.SiteBuilder
{
public class StaticApiPageGenerator
{
public static string CreateSlugName(string cRef)
public static string CreateSlugName(CRefIdentifier cRef)
{
var slug = cRef;
if (slug.Length >= 2 && Char.IsLetter(slug[0]) && slug[1] == ':')
{
var prefixLeffter = slug[0];
slug = String.Concat(slug.Substring(2), '-', prefixLeffter);
var fullCRefText = cRef.ToString();
var slugBuilder = new StringBuilder(fullCRefText);

if (cRef.HasTargetType) {
slugBuilder.Remove(0, cRef.TargetType.Length+1);
}

var slugChars = slug.ToCharArray();
for (int i = 0; i < slugChars.Length; ++i)
{
var c = slugChars[i];
if (c == '#' || c == ':')
{
slugChars[i] = '-';
bool requiresHash = false;
for (int i = 0; i < slugBuilder.Length; ++i) {
var c = slugBuilder[i];

if (c == '#' || c == ':' || c == '@' || c == '`' || c == '~') {
// remove
requiresHash = true;
var nextIndex = i + 1;
if (c == '`' && nextIndex < slugBuilder.Length && Char.IsNumber(slugBuilder[nextIndex])) {
slugBuilder.Remove(i, 2);
i -= 2;
}
else {
slugBuilder.Remove(i, 1);
i--;
}
continue;
}
else if (c == '@' || c == '`')
{
slugChars[i] = '!';
else if (c == '(' || c == '{') {
requiresHash = true;
slugBuilder.Remove(i, slugBuilder.Length - i);
break;
}
}

return new string(slugChars);
if (requiresHash) {
var hash = CalculteSlugHash(fullCRefText); // NOTE: always hash the full cRef
slugBuilder.Append('-');
slugBuilder.Append(hash.ToString("X"));
}
else if(cRef.HasTargetType) {
slugBuilder.Append('-');
slugBuilder.Append(cRef.TargetType);
}

return slugBuilder.ToString();
}

private static uint CalculteSlugHash(string text) {
Contract.Requires(text != null);
var hash = (ulong)3074457345618258791;
foreach (var c in text) {
unchecked {
hash += (ulong)c;
hash *= (ulong)3074457345618258799;
}
}
return unchecked((uint)(hash >> 32) ^ (uint)hash);
}

public DirectoryInfo TemplateDirectory { get; set; }
Expand Down Expand Up @@ -251,7 +284,7 @@ private FileInfo CreateFilePath(CodeDocSimpleMember model)
{
Contract.Requires(model != null);
Contract.Ensures(Contract.Result<FileInfo>() != null);
var fileName = CreateSlugName(model.CRefText) + ".html";
var fileName = CreateSlugName(model.CRef) + ".html";
return new FileInfo(Path.Combine(OutputDirectory.FullName, fileName));
}

Expand Down
11 changes: 6 additions & 5 deletions tests/DuckyDocs.SiteBuilder.Tests/CodeDocHtmlGenerationFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ public static void doc_page_link_to_others()
@"@using DuckyDocs.CodeDoc
@using DuckyDocs.SiteBuilder
<html><h1>@Model.ShortName</h1>@foreach(var field in Model.Fields.Cast<CodeDocField>()){
<div><a href=""@(StaticApiPageGenerator.CreateSlugName(field.CRefText)).html"">@field.ShortName</a></div>
<div><a href=""@(StaticApiPageGenerator.CreateSlugName(field.CRef)).html"">@field.ShortName</a></div>
}</html>");
var apiPageGen = new StaticApiPageGenerator
{
Expand Down Expand Up @@ -331,15 +331,15 @@ public static void dump_entire_repository()
@"@using DuckyDocs.CodeDoc
@using DuckyDocs.SiteBuilder
<html><h1>@Model.ShortName</h1>@foreach(var field in (Model.Fields ?? Enumerable.Empty<ICodeDocMember>()).Cast<CodeDocField>()){
<div><a href=""@(StaticApiPageGenerator.CreateSlugName(field.CRefText)).html"">@field.ShortName</a></div>
<div><a href=""@(StaticApiPageGenerator.CreateSlugName(field.CRef)).html"">@field.ShortName</a></div>
}</html>");
File.WriteAllText(
Path.Combine(templateDirectory.FullName, "_namespace.cshtml"),
@"@using DuckyDocs.CodeDoc
@using DuckyDocs.SiteBuilder
<html><h1>@Model.ShortName</h1>@foreach(var typeCRef in Model.TypeCRefs){
var typeModel = ViewBag.GetTargetPreviewModel(typeCRef);
<div><a href=""@(StaticApiPageGenerator.CreateSlugName(typeModel.CRefText)).html"">@typeModel.ShortName</a></div>
<div><a href=""@(StaticApiPageGenerator.CreateSlugName(typeModel.CRef)).html"">@typeModel.ShortName</a></div>
}</html>");
foreach (var fileName in new[] {
"_delegate.cshtml",
Expand Down Expand Up @@ -367,12 +367,13 @@ @using DuckyDocs.SiteBuilder
resultShortNames.Should().Contain("-N.html");
resultShortNames.Should().Contain("Test.Annotations-N.html");
resultShortNames.Should().Contain("TestLibrary1.Class1.Inner-T.html");
resultShortNames.Should().Contain("TestLibrary1.Class1.TrySomeOutRefStuff(System.Int32!,System.Int32!)-M.html");
resultShortNames.Should().Contain("TestLibrary1.Generic1!2.AMix!!1(!0,!!0)-M.html");
resultShortNames.Should().Contain("TestLibrary1.PublicExposedTestClass.ProtectedEvent-E.html");
resultShortNames.Should().Contain("TestLibrary1.ClassWithContracts.Stuff-P.html");
resultShortNames.Should().Contain("TestLibrary1.Class1.MyFunc-T.html");

resultShortNames.Any(x => x.StartsWith("TestLibrary1.Class1.TrySomeOutRefStuff-")).Should().BeTrue();
resultShortNames.Any(x => x.StartsWith("TestLibrary1.Generic1.AMix-")).Should().BeTrue();

resultShortNames.Should().NotContain("System.Attribute.GetHashCode-M.html");
resultShortNames.Should().NotContain("System.Object.ToString-M.html");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<Compile Include="DirectoryLifetimeManager.cs" />
<Compile Include="MarkdownFileConversionFacts.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SlugGenerationFacts.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\DuckyDocs.CodeDoc\DuckyDocs.CodeDoc.csproj">
Expand Down
45 changes: 45 additions & 0 deletions tests/DuckyDocs.SiteBuilder.Tests/SlugGenerationFacts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DuckyDocs.CRef;
using FluentAssertions;
using Xunit;

namespace DuckyDocs.SiteBuilder.Tests
{
public static class SlugGenerationFacts
{

[Fact]
public static void overload_slugs_differ() {
var cRefA = new CRefIdentifier("M:TestLibrary1.Class1.Inherits.VirtualInstanceMethod(System.Int32)");
var cRefB = new CRefIdentifier("M:TestLibrary1.Class1.Inherits.VirtualInstanceMethod(System.String)");

var slugA = StaticApiPageGenerator.CreateSlugName(cRefA);
var slugB = StaticApiPageGenerator.CreateSlugName(cRefB);

slugA.Should().NotBe(slugB);
}

[Fact]
public static void append_target_type_as_suffix() {
var cRef = new CRefIdentifier("F:Class1.FieldA");

var slug = StaticApiPageGenerator.CreateSlugName(cRef);

slug.Should().Be("Class1.FieldA-F");
}

[Fact]
public static void remove_generic_name_parts() {
var cRef = new CRefIdentifier("M:TestLibrary1.Generic1`2.AMix`1(``1,`0)");

var slug = StaticApiPageGenerator.CreateSlugName(cRef);

slug.Should().StartWith("TestLibrary1.Generic1.AMix-");
}

}
}

0 comments on commit 3dc9f32

Please sign in to comment.