Skip to content
Merged
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
21 changes: 0 additions & 21 deletions src/Butil/Bit.Butil.Build/ButilConsumerScan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,6 @@

namespace Bit.Butil.Build;

/// <summary>How an untrimmed publish works out which Bit.Butil types the app it is publishing uses.</summary>
public enum ButilScanMode
{
/// <summary>Do not scan. The default: without ILLink there is then no signal but an explicit list.</summary>
None,

/// <summary>
/// Match Bit.Butil type names against the names in each assembly's <c>#Strings</c> heap. Needs no table
/// parsing at all, and over-includes whenever an app has a type of its own by the same name - which,
/// with names like <c>Window</c>, <c>Console</c> and <c>Storage</c> in the library, is often.
/// </summary>
TypeNames,

/// <summary>
/// Match each assembly's <c>TypeRef</c> rows, which name the namespace as well, so only real references
/// to <c>Bit.Butil</c> types count. Costs no more at publish than <see cref="TypeNames"/> and is the mode
/// to use.
/// </summary>
TypeReferences,
}

/// <summary>
/// Reads a publish's own assemblies to find the Bit.Butil types the app references, and turns those into the
/// set of JavaScript modules it can reach.
Expand Down
27 changes: 27 additions & 0 deletions src/Butil/Bit.Butil.Build/ButilScanMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Bit.Butil.Build;

/// <summary>How an untrimmed publish works out which Bit.Butil types the app it is publishing uses.</summary>
public enum ButilScanMode
{
/// <summary>Do not scan. The default: without ILLink there is then no signal but an explicit list.</summary>
None,

/// <summary>
/// Match Bit.Butil type names against the names in each assembly's <c>#Strings</c> heap. Needs no table
/// parsing at all, and over-includes whenever an app has a type of its own by the same name - which,
/// with names like <c>Window</c>, <c>Console</c> and <c>Storage</c> in the library, is often.
/// </summary>
TypeNames,

/// <summary>
/// Match each assembly's <c>TypeRef</c> rows, which name the namespace as well, so only real references
/// to <c>Bit.Butil</c> types count. Costs no more at publish than <see cref="TypeNames"/> and is the mode
/// to use.
/// </summary>
TypeReferences,
}
8 changes: 0 additions & 8 deletions src/Butil/Bit.Butil.Build/ButilScriptBundler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,3 @@ public static void WriteBundle(string chunksDirectory, IEnumerable<string> modul
}
}
}

/// <summary>Module names in dependency-first order, and each module's direct dependencies.</summary>
public sealed class ButilScriptManifest(IReadOnlyList<string> order, IReadOnlyDictionary<string, string[]> dependencies)
{
public IReadOnlyList<string> Order { get; } = order;

public IReadOnlyDictionary<string, string[]> Dependencies { get; } = dependencies;
}
15 changes: 15 additions & 0 deletions src/Butil/Bit.Butil.Build/ButilScriptManifest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Bit.Butil.Build;

/// <summary>Module names in dependency-first order, and each module's direct dependencies.</summary>
public sealed class ButilScriptManifest(IReadOnlyList<string> order, IReadOnlyDictionary<string, string[]> dependencies)
{
public IReadOnlyList<string> Order { get; } = order;

public IReadOnlyDictionary<string, string[]> Dependencies { get; } = dependencies;
}
15 changes: 15 additions & 0 deletions src/Butil/Bit.Butil.Build/MetadataHeap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.IO;
using System.Text;

namespace Bit.Butil.Build;

/// <summary>The file offset and size of one metadata stream. A stream the image does not have is empty.</summary>
public readonly struct MetadataHeap(int offset, int size)
{
public int Offset { get; } = offset;

public int Size { get; } = size;

public bool IsEmpty => Size == 0;
}
46 changes: 0 additions & 46 deletions src/Butil/Bit.Butil.Build/MetadataTables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,49 +338,3 @@ private MetadataToken ReadCodedIndex(int position, int tagBits, params int[] tab
: new MetadataToken(tables[tag], (int)(raw >> tagBits));
}
}

/// <summary>A type's namespace and name, as the metadata spells them.</summary>
public readonly struct TypeName(string @namespace, string name) : IEquatable<TypeName>
{
public string Namespace { get; } = @namespace ?? string.Empty;

public string Name { get; } = name ?? string.Empty;

public string FullName => Namespace.Length == 0 ? Name : Namespace + "." + Name;

public bool Equals(TypeName other)
=> string.Equals(Namespace, other.Namespace, StringComparison.Ordinal) && string.Equals(Name, other.Name, StringComparison.Ordinal);

public override bool Equals(object? obj) => obj is TypeName other && Equals(other);

public override int GetHashCode() => (Namespace.GetHashCode() * 397) ^ Name.GetHashCode();

public override string ToString() => FullName;
}

/// <summary>A metadata table and a one-based row in it. Row 0 means "nothing".</summary>
public readonly struct MetadataToken(int table, int row)
{
public int Table { get; } = table;

public int Row { get; } = row;

public bool IsNil => Row == 0;
}

/// <summary>One <c>TypeDef</c> row, in the terms the module map needs.</summary>
public readonly struct TypeDefinition(int row, TypeName name, MetadataToken extends, int fieldListStart, int methodListStart)
{
public int Row { get; } = row;

public TypeName Name { get; } = name;

/// <summary>The base type. Nil for <c>System.Object</c> and for interfaces.</summary>
public MetadataToken Extends { get; } = extends;

/// <summary>The one-based <c>Field</c> row this type's fields start at.</summary>
public int FieldListStart { get; } = fieldListStart;

/// <summary>The one-based <c>MethodDef</c> row this type's methods start at.</summary>
public int MethodListStart { get; } = methodListStart;
}
13 changes: 13 additions & 0 deletions src/Butil/Bit.Butil.Build/MetadataToken.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;

namespace Bit.Butil.Build;

/// <summary>A metadata table and a one-based row in it. Row 0 means "nothing".</summary>
public readonly struct MetadataToken(int table, int row)
{
public int Table { get; } = table;

public int Row { get; } = row;

public bool IsNil => Row == 0;
}
10 changes: 0 additions & 10 deletions src/Butil/Bit.Butil.Build/PeImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,3 @@ public int ReadInt32(int position)
public BadImageFormatException Invalid(string reason)
=> new($"'{Path}' could not be read as a managed assembly: {reason}.");
}

/// <summary>The file offset and size of one metadata stream. A stream the image does not have is empty.</summary>
public readonly struct MetadataHeap(int offset, int size)
{
public int Offset { get; } = offset;

public int Size { get; } = size;

public bool IsEmpty => Size == 0;
}
20 changes: 20 additions & 0 deletions src/Butil/Bit.Butil.Build/TypeDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Bit.Butil.Build;

/// <summary>One <c>TypeDef</c> row, in the terms the module map needs.</summary>
public readonly struct TypeDefinition(int row, TypeName name, MetadataToken extends, int fieldListStart, int methodListStart)
{
public int Row { get; } = row;

public TypeName Name { get; } = name;

/// <summary>The base type. Nil for <c>System.Object</c> and for interfaces.</summary>
public MetadataToken Extends { get; } = extends;

/// <summary>The one-based <c>Field</c> row this type's fields start at.</summary>
public int FieldListStart { get; } = fieldListStart;

/// <summary>The one-based <c>MethodDef</c> row this type's methods start at.</summary>
public int MethodListStart { get; } = methodListStart;
}
22 changes: 22 additions & 0 deletions src/Butil/Bit.Butil.Build/TypeName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace Bit.Butil.Build;

/// <summary>A type's namespace and name, as the metadata spells them.</summary>
public readonly struct TypeName(string @namespace, string name) : IEquatable<TypeName>
{
public string Namespace { get; } = @namespace ?? string.Empty;

public string Name { get; } = name ?? string.Empty;

public string FullName => Namespace.Length == 0 ? Name : Namespace + "." + Name;

public bool Equals(TypeName other)
=> string.Equals(Namespace, other.Namespace, StringComparison.Ordinal) && string.Equals(Name, other.Name, StringComparison.Ordinal);

public override bool Equals(object? obj) => obj is TypeName other && Equals(other);

public override int GetHashCode() => (Namespace.GetHashCode() * 397) ^ Name.GetHashCode();

public override string ToString() => FullName;
}
25 changes: 25 additions & 0 deletions src/Butil/Bit.Butil.Demo/Client/Docs/ApiNeeds.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Components;
using Bit.Butil.Demo.Client.Pages;

namespace Bit.Butil.Demo.Client.Docs;

/// <summary>
/// The preconditions an API imposes on the calling page, beyond simply being implemented.
/// </summary>
[Flags]
public enum ApiNeeds
{
None = 0,

/// <summary>Only available over HTTPS or on localhost.</summary>
SecureContext = 1,

/// <summary>The browser prompts the user, and the call fails if permission is denied.</summary>
Permission = 2,

/// <summary>Must be called from a user-gesture handler such as a click.</summary>
UserGesture = 4,

/// <summary>Behind an experimental or origin-trial flag in at least one shipping engine.</summary>
Experimental = 8,
}
30 changes: 30 additions & 0 deletions src/Butil/Bit.Butil.Demo/Client/Docs/ApiSupport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Components;
using Bit.Butil.Demo.Client.Pages;

namespace Bit.Butil.Demo.Client.Docs;

/// <summary>
/// How widely the underlying browser API is implemented. This is about the web platform, not about
/// Butil: every wrapper on this site works everywhere Blazor does, but it can only expose what the
/// browser underneath it implements.
/// </summary>
public enum ApiSupport
{
/// <summary>Not a browser API at all - a guide page.</summary>
Guide,

/// <summary>Implemented by every current engine.</summary>
Broad,

/// <summary>Implemented everywhere, but with members or behaviour that differ between engines.</summary>
Partial,

/// <summary>Chromium only (Chrome, Edge, Opera and friends).</summary>
Chromium,

/// <summary>Chromium on desktop only.</summary>
ChromiumDesktop,

/// <summary>Chromium on Android only.</summary>
ChromiumMobile,
}
12 changes: 12 additions & 0 deletions src/Butil/Bit.Butil.Demo/Client/Docs/DocGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Components;
using Bit.Butil.Demo.Client.Pages;

namespace Bit.Butil.Demo.Client.Docs;

/// <param name="Icon">
/// The key of the mark that stands for this area of the platform, resolved by Shared/Icon.razor.
/// It is declared per group rather than per page on purpose: sixty-six glyphs in one list is
/// decoration a reader has to look past to find a name, while ten of them are landmarks that say
/// which part of the browser they are now in.
/// </param>
public record DocGroup(string Title, string Icon, DocLink[] Links);
23 changes: 23 additions & 0 deletions src/Butil/Bit.Butil.Demo/Client/Docs/DocLink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Components;
using Bit.Butil.Demo.Client.Pages;

namespace Bit.Butil.Demo.Client.Docs;

/// <param name="PageType">
/// The component routed at <paramref name="Url"/>. Naming it here is what lets the MCP server
/// (Server/Controllers/McpController.cs) render a page's documentation on demand, so an agent reads
/// the same text a human does instead of a second copy that could go stale.
/// </param>
/// <param name="Services">
/// The Bit.Butil public types the page documents, when they are not simply the title without its
/// spaces. Only the pages whose title is not a type name ("Local &amp; Session Storage") or whose
/// API is a set of extension methods ("Element", "Animation") need to state them.
/// </param>
public record DocLink(
string Title,
string Url,
string Summary,
Type PageType,
ApiSupport Support = ApiSupport.Broad,
ApiNeeds Needs = ApiNeeds.None,
string[]? Services = null);
74 changes: 0 additions & 74 deletions src/Butil/Bit.Butil.Demo/Client/Docs/DocsNav.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,6 @@

namespace Bit.Butil.Demo.Client.Docs;

/// <summary>
/// How widely the underlying browser API is implemented. This is about the web platform, not about
/// Butil: every wrapper on this site works everywhere Blazor does, but it can only expose what the
/// browser underneath it implements.
/// </summary>
public enum ApiSupport
{
/// <summary>Not a browser API at all - a guide page.</summary>
Guide,

/// <summary>Implemented by every current engine.</summary>
Broad,

/// <summary>Implemented everywhere, but with members or behaviour that differ between engines.</summary>
Partial,

/// <summary>Chromium only (Chrome, Edge, Opera and friends).</summary>
Chromium,

/// <summary>Chromium on desktop only.</summary>
ChromiumDesktop,

/// <summary>Chromium on Android only.</summary>
ChromiumMobile,
}

/// <summary>
/// The preconditions an API imposes on the calling page, beyond simply being implemented.
/// </summary>
[Flags]
public enum ApiNeeds
{
None = 0,

/// <summary>Only available over HTTPS or on localhost.</summary>
SecureContext = 1,

/// <summary>The browser prompts the user, and the call fails if permission is denied.</summary>
Permission = 2,

/// <summary>Must be called from a user-gesture handler such as a click.</summary>
UserGesture = 4,

/// <summary>Behind an experimental or origin-trial flag in at least one shipping engine.</summary>
Experimental = 8,
}

/// <param name="PageType">
/// The component routed at <paramref name="Url"/>. Naming it here is what lets the MCP server
/// (Server/Controllers/McpController.cs) render a page's documentation on demand, so an agent reads
/// the same text a human does instead of a second copy that could go stale.
/// </param>
/// <param name="Services">
/// The Bit.Butil public types the page documents, when they are not simply the title without its
/// spaces. Only the pages whose title is not a type name ("Local &amp; Session Storage") or whose
/// API is a set of extension methods ("Element", "Animation") need to state them.
/// </param>
public record DocLink(
string Title,
string Url,
string Summary,
Type PageType,
ApiSupport Support = ApiSupport.Broad,
ApiNeeds Needs = ApiNeeds.None,
string[]? Services = null);

/// <param name="Icon">
/// The key of the mark that stands for this area of the platform, resolved by Shared/Icon.razor.
/// It is declared per group rather than per page on purpose: sixty-six glyphs in one list is
/// decoration a reader has to look past to find a name, while ten of them are landmarks that say
/// which part of the browser they are now in.
/// </param>
public record DocGroup(string Title, string Icon, DocLink[] Links);

/// <summary>
/// The single source of truth for the site taxonomy: the sidebar, the home page feature grid,
/// the browser-support matrix and the prev/next pager are all rendered from this list.
Expand Down
Loading
Loading