Skip to content

Commit

Permalink
feat: basic API page output for .NET (#9309)
Browse files Browse the repository at this point in the history
  • Loading branch information
yufeih authored Oct 20, 2023
1 parent 2fccdbd commit c6f6dc1
Show file tree
Hide file tree
Showing 201 changed files with 3,599 additions and 1,270 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ dotnet_diagnostic.IDE0110.severity = suggestion # IDE0110: Remove unnecessary di
dotnet_diagnostic.IDE0240.severity = suggestion # IDE0240: Nullable directive is redundant
dotnet_diagnostic.IDE0241.severity = suggestion # IDE0241: Nullable directive is unnecessary

dotnet_diagnostic.CS8509.severity = suggestion # The switch expression does not handle all possible values of its input type

csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion # IDE0058: Remove unnecessary expression value
csharp_style_unused_value_assignment_preference = discard_variable:suggestion # IDE0059: Remove unnecessary value assignment
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">true</ContinuousIntegrationBuild>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(ContinuousIntegrationBuild)' == 'true' ">$(TargetFrameworks);net8.0</TargetFrameworks>
<LangVersion>Latest</LangVersion>
<LangVersion>Preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
Expand Down
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.7.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="OneOf" Version="3.0.263" />
<PackageVersion Include="OneOf.SourceGenerator" Version="3.0.263" />
<PackageVersion Include="PdfPig" Version="0.1.8" />
<PackageVersion Include="Spectre.Console.Cli" Version="0.47.0" />
<PackageVersion Include="Stubble.Core" Version="1.10.8" />
Expand Down
23 changes: 23 additions & 0 deletions samples/seed/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,35 @@
"enumSortOrder": "declaringOrder",
"outputFormat": "markdown",
"output": "obj/md"
},
{
"src": [
{
"files": [
"assembly/bin/**/*.dll",
"project/**/*.csproj",
"solution/**/*.sln",
"csharp/**/*.cs",
"vb/**/*.vb"
],
"exclude": [
"project/Project.Core/**"
],
"src": "dotnet"
}
],
"namespaceLayout": "nested",
"enumSortOrder": "declaringOrder",
"outputFormat": "apiPage",
"output": "obj/apipage"
}
],
"build": {
"content": [
{ "files": [ "**/*.yml" ], "src": "obj/api", "dest": "api" },
{ "files": [ "**/*.yml" ], "src": "obj/apipage", "dest": "apipage" },
{ "files": [ "**" ], "src": "obj/md", "dest": "md" },
{ "files": [ "**" ], "src": "obj/apipage", "dest": "apipage" },
{ "files": [ "articles/**/*.{md,yml}", "*.md", "toc.yml", "restapi/**", "md/**", "md2/**" ] }
],
"resource": [
Expand Down
2 changes: 2 additions & 0 deletions samples/seed/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
href: obj/api/
- name: .NET API (markdown)
href: obj/md/
- name: .NET API (apipage)
href: obj/apipage/
- name: REST API
href: restapi/
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

/**
* This file is used to generate the API page JSON schema. To generate the schema:
* 1. run `npx typescript-json-schema ApiPage.schema.d.ts ApiPage --required --strictNullChecks --out ApiPage.schema.json`
* 2. manually mark properties as markdown
*/

/** Define the markdown content type */
type markdown = string;

/** Represents an inline composed of text or links */
type Inline = string | (string | { text: string; url?: string })[];
type Span = string | { text: string; url?: string };
type Inline = Span | Span[];

/** Represents a markdown block */
type Markdown = {
Expand Down Expand Up @@ -44,7 +39,7 @@ type Api = (
/** API source URL */
src?: string;

/** Opaque metadata about the API as HTML data-* attributes */
/** Opaque metadata about the API as HTML data-{key} attributes */
metadata?: { [key: string]: string };
};

Expand All @@ -71,31 +66,33 @@ type Code = {
/** Code text */
code: string;

/** Code [langauge identifier](https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers) */
/** Code [language identifier](https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers) */
languageId?: string;
};

/** Represents a set of parameters */
type Params = {
parameters: {
/** Parameter name */
name?: string;
type Param = {
/** Parameter name */
name?: string;

/** Parameter type */
type?: Inline;

/** Parameter type */
type?: Inline;
/** Parameter default value */
default?: string;

/** Parameter default value */
default?: string;
/** Parameter description in markdown format */
description?: markdown;

/** Parameter description in markdown format */
description?: markdown;
/** Is this parameter deprecated, or the deprecation reason */
deprecated?: boolean | string;

/** Is this parameter deprecated, or the deprecation reason */
deprecated?: boolean | string;
/** Is this parameter optional? */
optional?: boolean;
}

/** Is this parameter optional? */
optional?: boolean;
}[];
/** Represents a set of parameters */
type Params = {
parameters: Param[];
};

/** Represents block level elements */
Expand All @@ -114,7 +111,7 @@ type ApiPage = {
/** Page title */
title: string;

/** Opaque metadata about the page as HTML <meta> tags */
/** Opaque metadata about the page as HTML \<meta> tags */
metadata?: { [key: string]: string | string[] };

/** Default code [language identifier](https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers) */
Expand Down
162 changes: 162 additions & 0 deletions src/Docfx.Build/ApiPage/ApiPage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if NET7_0_OR_GREATER

using System.Text.Json;
using System.Text.Json.Serialization;
using OneOf;

#nullable enable

namespace Docfx.Build.ApiPage;

struct LinkSpan
{
public required string text { get; init; }
public string? url { get; init; }
}

[GenerateOneOf]
partial class Span : OneOfBase<string, LinkSpan> { }

[GenerateOneOf]
partial class Inline : OneOfBase<Span, Span[]> { }

struct Markdown
{
public required string markdown { get; init; }
}

struct H1
{
public required string h1 { get; init; }
public string? id { get; init; }
}

struct H2
{
public required string h2 { get; init; }
public string? id { get; init; }
}

struct H3
{
public required string h3 { get; init; }
public string? id { get; init; }
}

struct H4
{
public required string h4 { get; init; }
public string? id { get; init; }
}

struct H5
{
public required string h5 { get; init; }
public string? id { get; init; }
}

struct H6
{
public required string h6 { get; init; }
public string? id { get; init; }
}

[GenerateOneOf]
partial class Heading : OneOfBase<H1, H2, H3, H4, H5, H6> { }

abstract class ApiBase
{
public string? id { get; init; }
public OneOf<bool, string>? deprecated { get; init; }
public string? src { get; init; }
public Dictionary<string, string>? metadata { get; init; }
}

class Api1 : ApiBase
{
public required string api1 { get; init; }
}

class Api2 : ApiBase
{
public required string api2 { get; init; }
}

class Api3 : ApiBase
{
public required string api3 { get; init; }
}

class Api4 : ApiBase
{
public required string api4 { get; init; }
}


[GenerateOneOf]
partial class Api : OneOfBase<Api1, Api2, Api3, Api4> { }

record struct Fact(string name, Inline value);

struct Facts
{
public required Fact[] facts { get; init; }
}

struct List
{
public required Inline[] list { get; init; }
}

struct Inheritance
{
public required Inline[] inheritance { get; init; }
}

struct Code
{
public required string code { get; init; }
public string? languageId { get; init; }
}

class Parameter
{
public string? name { get; init; }
public Inline? type { get; init; }
public string? @default { get; init; }
public string? description { get; init; }
public OneOf<bool, string>? deprecated { get; init; }
public bool? optional { get; init; }
}

struct Parameters
{
public required Parameter[] parameters { get; init; }
}

[GenerateOneOf]
partial class Block : OneOfBase<Heading, Api, Markdown, Facts, Parameters, List, Inheritance, Code> { }

record ApiPage
{
public static JsonSerializerOptions JsonSerializerOptions { get; } = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull | JsonIgnoreCondition.WhenWritingDefault,
};

static ApiPage()
{
JsonSerializerOptions.Converters.Add(new OneOfJsonConverterFactory());
}

public required string title { get; init; }
public required Block[] body { get; init; }

public string? languageId { get; init; }
public Dictionary<string, OneOf<string, string[]>>? metadata { get; init; }
}

#endif
Loading

0 comments on commit c6f6dc1

Please sign in to comment.