diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 09cea5fb..9f20258e 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -35,6 +35,13 @@ jobs: cd wiki mdbook build + # mdBook has no per-page description and cannot build a page URL in its template, + # so descriptions declared as comments are lifted into + # here, along with og:url and canonical. + - name: Add Page Metadata + shell: pwsh + run: ./wiki/tools/Add-PageMetadata.ps1 -Book ./wiki/book -Require + # mdBook rewrites .md links to .html without verifying the target exists, so a # renamed or removed page builds cleanly and 404s in production. This also checks # that the legacy wiki redirect map still resolves. diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Grpc.ApiExplorer/Aot.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.Grpc.ApiExplorer/Aot.cs deleted file mode 100644 index 8d2e1cae..00000000 --- a/src/AspNetCore/WebApi/src/Asp.Versioning.Grpc.ApiExplorer/Aot.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. - -namespace Asp.Versioning; - -internal static class Aot -{ - internal const string TrimmingMessage = "The API Explorer does not currently support trimming or native AOT. https://aka.ms/aspnet/trimming"; -} \ No newline at end of file diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Asp.Versioning.OpenApi.csproj b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Asp.Versioning.OpenApi.csproj index 1866056a..af1bb6d2 100644 --- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Asp.Versioning.OpenApi.csproj +++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Asp.Versioning.OpenApi.csproj @@ -1,7 +1,7 @@  - 10.2.1 + 10.2.2 10.2.0.0 $(DefaultTargetFramework) Asp.Versioning.OpenApi diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/ReleaseNotes.txt b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/ReleaseNotes.txt index 2725eef9..114fecc8 100644 --- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/ReleaseNotes.txt +++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/ReleaseNotes.txt @@ -1 +1 @@ -Bump patched version due to transitive dependency \ No newline at end of file +Fixed XML Comment whitespace handling [Issue #1205](https://github.com/dotnet/aspnet-api-versioning/issues/1205) \ No newline at end of file diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Transformers/XmlComments.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Transformers/XmlComments.cs index c0ea3823..2996d93c 100644 --- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Transformers/XmlComments.cs +++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Transformers/XmlComments.cs @@ -24,7 +24,12 @@ public class XmlComments /// Initializes a new instance of the class. /// /// The file path of the XML comments to read. - protected XmlComments( string path ) => Xml = File.Exists( path ) ? XDocument.Load( path ) : new(); + /// The whitespace of the source file is preserved. A reader discards a text node that is only + /// whitespace by default, which is not insignificant here: it is the indentation the file is written with, + /// and it is the only way to know the margin that has to be removed before the text reads as Markdown. It is + /// also the space between two adjacent tags, which is the space between the words they wrap. + protected XmlComments( string path ) => + Xml = File.Exists( path ) ? XDocument.Load( path, LoadOptions.PreserveWhitespace ) : new(); /// /// Creates and returns new from the specified file. @@ -374,7 +379,12 @@ private static void ResolveParamRefTags( XElement element ) // containing element is rebuilt rather than each being replaced in turn, because the whitespace // between two of them is not a reliable separator: XLinq merges the text nodes around a replaced element. // - // This runs last, so every other tag has already been resolved to text and is the only element left. + // Only a starts a paragraph. Everything between two of them belongs to the same one, including a tag + // left in the tree because it has no Markdown of its own, such as or . Reading one of those as a + // block of its own would break the sentence around it into a paragraph per fragment. + // + // This runs last, so every other tag has already been resolved to text and is the only element left + // that carries structure. private static void ResolveParaTags( XElement element ) { foreach ( var parent in element.DescendantsAndSelf().ToArray() ) @@ -385,26 +395,41 @@ private static void ResolveParaTags( XElement element ) } var blocks = new List(); + var paragraph = new StringBuilder(); foreach ( var node in parent.Nodes() ) { - var text = node switch + if ( node is XElement para && para.Name == "para" ) { - XText content => TrimEachLine( content.Value ), - XElement para => TrimEachLine( para.Value ), - _ => string.Empty, - }; - - if ( text.Length > 0 ) + AddBlock( blocks, paragraph.ToString() ); + paragraph.Clear(); + AddBlock( blocks, para.Value ); + } + else if ( node is XText content ) { - blocks.Add( text ); + paragraph.Append( content.Value ); + } + else if ( node is XElement other ) + { + paragraph.Append( other.Value ); } } + AddBlock( blocks, paragraph.ToString() ); parent.ReplaceNodes( new XText( string.Join( "\n\n", blocks ) ) ); } } + private static void AddBlock( List blocks, string text ) + { + var block = TrimEachLine( text ); + + if ( block.Length > 0 ) + { + blocks.Add( block ); + } + } + private static void ResolveListTags( XElement element ) { foreach ( var list in element.Descendants( "list" ).ToArray() ) @@ -579,6 +604,11 @@ private static void ResolveInlineCode( XElement element ) // , , and are the html tags a documentation comment carries inline, and each has a direct markdown // equivalent. rewriting them keeps the meaning that reading the text of the enclosing element would drop. // the tags are visited from the inside out so that one nested in another is rewritten before it is absorbed. + // + // emphasis is delimited by an asterisk rather than an underscore. the two are interchangeable on their own, + // but an underscore only opens or closes emphasis at a word boundary, so it is literal text in the middle of + // a word and it does not pair with the asterisk of a nested the other way around; x and + // x then render differently despite meaning the same thing. private static void ResolveInlineTags( XElement element ) { foreach ( var inline in element.Descendants().Reverse().ToArray().Where( e => e.Parent is not null ) ) @@ -586,7 +616,7 @@ private static void ResolveInlineTags( XElement element ) var text = inline.Name.LocalName switch { "b" => Delimit( inline.Value, "**" ), - "i" => Delimit( inline.Value, "_" ), + "i" => Delimit( inline.Value, "*" ), "a" => LinkOf( inline ), _ => default, }; @@ -699,7 +729,10 @@ private static int MarginOf( string text ) var lines = text.Split( '\n' ); var margin = int.MaxValue; - for ( var i = 0; i < lines.Length; i++ ) + // the text of a member begins immediately after its opening tag rather than at the start of a line, so + // whatever precedes the first break carries none of the indentation the margin is measured from. counting + // it would report a margin of zero and leave the indentation on every line that does start one. + for ( var i = 1; i < lines.Length; i++ ) { var line = lines[i]; diff --git a/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Simulators/Documented.cs b/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Simulators/Documented.cs index a34c19da..b5b52d89 100644 --- a/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Simulators/Documented.cs +++ b/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Simulators/Documented.cs @@ -116,6 +116,34 @@ public class Documented /// public string Emphasis { get; set; } + /// + /// Gets or sets the sibling, which is underlined in place. + /// A note. + /// + public string Sibling { get; set; } + + /// + /// Gets or sets the adjacent. + /// + /// Remark of GetToDo + /// + /// + /// Remark of GetToDo + /// + /// + public string Adjacent { get; set; } + + /// + /// Gets or sets the intraword. + /// + /// Verylongword + /// + /// + /// Verylongword + /// + /// + public string Intraword { get; set; } + /// /// Gets or sets the reference, which is described by the /// specification. diff --git a/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Simulators/MinimalApi.cs b/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Simulators/MinimalApi.cs index 320e5a5c..ca8d95ff 100644 --- a/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Simulators/MinimalApi.cs +++ b/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Simulators/MinimalApi.cs @@ -36,6 +36,34 @@ public static class MinimalApi /// The detailed answer. public static int Detailed() => 42; + /// Mixed + /// + /// Text before code + /// + /// + /// var index = 5; + /// index++; + /// + /// + /// Text after code + /// + /// The mixed answer. + public static int Mixed() => 42; + + /// Outlined + /// + /// Text before list + /// + /// + /// First + /// Second + /// + /// + /// Text after list + /// + /// The outlined answer. + public static int Outlined() => 42; + /// /// Echo /// diff --git a/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Transformers/XmlCommentsStructureTest.cs b/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Transformers/XmlCommentsStructureTest.cs index 6d220f50..7261cd15 100644 --- a/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Transformers/XmlCommentsStructureTest.cs +++ b/src/AspNetCore/WebApi/test/Asp.Versioning.OpenApi.Tests/Transformers/XmlCommentsStructureTest.cs @@ -260,7 +260,7 @@ public void bold_and_italic_should_be_resolved_into_emphasis() var summary = comments.GetSummary( property ); // assert - summary.Should().Be( "Gets or sets the highlights, which are **important** and _subtle_." ); + summary.Should().Be( "Gets or sets the highlights, which are **important** and *subtle*." ); } [Fact] @@ -274,7 +274,62 @@ public void nested_emphasis_should_be_resolved_from_the_inside_out() var summary = comments.GetSummary( property ); // assert - summary.Should().Be( "Gets or sets the emphasis, which is **very _strongly_ worded**." ); + summary.Should().Be( "Gets or sets the emphasis, which is **very *strongly* worded**." ); + } + + [Fact] + public void nested_emphasis_should_be_resolved_the_same_way_in_either_order() + { + // arrange + var comments = XmlComments.FromFile( FilePath.XmlCommentFile ); + var property = typeof( Documented ).GetProperty( nameof( Documented.Intraword ) ); + + // act + var summary = comments.GetSummary( property ); + + // assert + summary.Should().Be( + "Gets or sets the intraword.\n" + + "\n" + + "Very***long***word\n" + + "\n" + + "Very***long***word" ); + } + + [Fact] + public void tag_beside_a_paragraph_should_not_start_one() + { + // arrange + var comments = XmlComments.FromFile( FilePath.XmlCommentFile ); + var property = typeof( Documented ).GetProperty( nameof( Documented.Sibling ) ); + + // act + var summary = comments.GetSummary( property ); + + // assert + summary.Should().Be( + "Gets or sets the sibling, which is underlined in place.\n" + + "\n" + + "A note." ); + } + + [Fact] + public void space_between_adjacent_inline_tags_should_be_retained() + { + // arrange + var comments = XmlComments.FromFile( FilePath.XmlCommentFile ); + var property = typeof( Documented ).GetProperty( nameof( Documented.Adjacent ) ); + + // act + var summary = comments.GetSummary( property ); + + // assert + summary.Should().Be( + "Gets or sets the adjacent.\n" + + "\n" + + "**Remark *of*** GetToDo\n" + + "\n" + + "**Remark** *of* GetToDo" ); } [Fact] @@ -373,6 +428,61 @@ public async Task paramref_should_be_resolved_in_the_document() description.GetValue().Should().Be( "The value of `id`." ); } + [Fact] + public void text_around_a_code_block_should_not_be_indented() + { + // arrange + var comments = XmlComments.FromFile( FilePath.XmlCommentFile ); + var method = typeof( MinimalApi ).GetMethod( nameof( MinimalApi.Mixed ) ); + + // act + var remarks = comments.GetRemarks( method ); + + // assert + remarks.Should().Be( + "Text before code\n" + + "\n\n" + + "```\n" + + "var index = 5;\n" + + "index++;\n" + + "```\n" + + "\n\n" + + "Text after code" ); + } + + [Fact] + public void text_around_a_list_should_not_be_indented() + { + // arrange + var comments = XmlComments.FromFile( FilePath.XmlCommentFile ); + var method = typeof( MinimalApi ).GetMethod( nameof( MinimalApi.Outlined ) ); + + // act + var remarks = comments.GetRemarks( method ); + + // assert + remarks.Should().Be( + "Text before list\n" + + "\n" + + "* First\n" + + "* Second\n" + + "\n" + + "Text after list" ); + } + + [Fact] + public async Task text_around_a_code_block_should_not_be_indented_in_the_document() + { + // arrange + var paths = await GeneratePathsAsync(); + + // act + var description = paths["/test/mixed"]["get"]["description"].GetValue(); + + // assert + description.Should().NotContain( "\n " ).And.StartWith( "Text before code" ); + } + [Fact] public async Task summary_and_value_should_describe_a_property() { @@ -421,6 +531,7 @@ private static async Task GenerateDocumentAsync() api.MapGet( "detailed", MinimalApi.Detailed ); api.MapGet( "documented", () => new Documented() ); api.MapGet( "echo/{id:int}", MinimalApi.Echo ); + api.MapGet( "mixed", MinimalApi.Mixed ); app.MapOpenApi().WithDocumentPerVersion(); var cancellationToken = TestContext.Current.CancellationToken; diff --git a/wiki/src/404.md b/wiki/src/404.md new file mode 100644 index 00000000..2355e2bf --- /dev/null +++ b/wiki/src/404.md @@ -0,0 +1,28 @@ +
+ + + +# Not Found + +Slithered through every page and API version. This page isn't in any of them. + +```http +HTTP/2 404 +api-supported-versions: 1.0 +content-type: application/problem+json +content-length: 163 + +{ + "type": "https://docs.api-versioning.org/problems#unsupported", + "title": "Not Found", + "status": 404, + "detail": "No page matched that URL in any API version.", + "code": "UnsupportedApiVersion" +} +``` + +It may have been renamed, sunset without a deprecation policy, or never shipped at all. +Try the [Introduction](index.html) or [Getting Started](getting-started.md), or press +s to search. + +
diff --git a/wiki/src/README.md b/wiki/src/README.md index 3c0450e4..908c0803 100644 --- a/wiki/src/README.md +++ b/wiki/src/README.md @@ -1,3 +1,5 @@ + + # Introduction Versioning is an important aspect of any mature web service. Microsoft has published REST API guidelines that require diff --git a/wiki/src/aspnet-core/config/conventions.md b/wiki/src/aspnet-core/config/conventions.md index c1e321f8..01630139 100644 --- a/wiki/src/aspnet-core/config/conventions.md +++ b/wiki/src/aspnet-core/config/conventions.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/config/conventions-pre.md}} ```c# diff --git a/wiki/src/aspnet-core/config/options.md b/wiki/src/aspnet-core/config/options.md index 7dacf469..65651263 100644 --- a/wiki/src/aspnet-core/config/options.md +++ b/wiki/src/aspnet-core/config/options.md @@ -1 +1,3 @@ + + {{#include ../../shared/config/options.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/config/overview.md b/wiki/src/aspnet-core/config/overview.md index dc0dd248..39f3e901 100644 --- a/wiki/src/aspnet-core/config/overview.md +++ b/wiki/src/aspnet-core/config/overview.md @@ -1,3 +1,5 @@ + + # Configuring Your Application Although different variations of ASP.NET have distinct application initialization methods, careful consideration was diff --git a/wiki/src/aspnet-core/config/reader.md b/wiki/src/aspnet-core/config/reader.md index 38d23c8e..9390a20c 100644 --- a/wiki/src/aspnet-core/config/reader.md +++ b/wiki/src/aspnet-core/config/reader.md @@ -1 +1,3 @@ + + {{#include ../../shared/config/reader.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/config/selector.md b/wiki/src/aspnet-core/config/selector.md index cfc5e1f2..f4b8c104 100644 --- a/wiki/src/aspnet-core/config/selector.md +++ b/wiki/src/aspnet-core/config/selector.md @@ -1 +1,3 @@ + + {{#include ../../shared/config/selector.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/docs/grpc-options.md b/wiki/src/aspnet-core/docs/grpc-options.md index 9458a63f..b210b2cd 100644 --- a/wiki/src/aspnet-core/docs/grpc-options.md +++ b/wiki/src/aspnet-core/docs/grpc-options.md @@ -1,3 +1,5 @@ + + # gRPC Options The API Explorer support for gRPC has a few options that allow you to customize the behavior. The options are minimal diff --git a/wiki/src/aspnet-core/docs/odata-options.md b/wiki/src/aspnet-core/docs/odata-options.md index ac65380b..8874ebbd 100644 --- a/wiki/src/aspnet-core/docs/odata-options.md +++ b/wiki/src/aspnet-core/docs/odata-options.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/docs/odata-options-pre.md}} {{#include ../../shared/docs/odata-options-post.md}} diff --git a/wiki/src/aspnet-core/docs/openapi-options.md b/wiki/src/aspnet-core/docs/openapi-options.md index 3e31cf51..f96c9672 100644 --- a/wiki/src/aspnet-core/docs/openapi-options.md +++ b/wiki/src/aspnet-core/docs/openapi-options.md @@ -1,3 +1,5 @@ + + # OpenAPI Options The OpenAPI options allows you to configure, customize, and extend the default behaviors when you add OpenAPI support. diff --git a/wiki/src/aspnet-core/docs/options.md b/wiki/src/aspnet-core/docs/options.md index f3e4b106..51613358 100644 --- a/wiki/src/aspnet-core/docs/options.md +++ b/wiki/src/aspnet-core/docs/options.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/docs/options-pre.md}} - [FormatGroupName](#format-group-name) diff --git a/wiki/src/aspnet-core/docs/overview.md b/wiki/src/aspnet-core/docs/overview.md index 745ff719..9dc112d8 100644 --- a/wiki/src/aspnet-core/docs/overview.md +++ b/wiki/src/aspnet-core/docs/overview.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/docs/overview-pre.md}} Any OpenAPI generator such as [Microsoft][openapi-ms], [Swashbuckle][openapi-swashbuckle], or [NSwag][openapi-nswag] diff --git a/wiki/src/aspnet-core/docs/scalar.md b/wiki/src/aspnet-core/docs/scalar.md index 5d2e3400..eb382f13 100644 --- a/wiki/src/aspnet-core/docs/scalar.md +++ b/wiki/src/aspnet-core/docs/scalar.md @@ -1,3 +1,5 @@ + + # Scalar Integration [Scalar](https://scalar.com/) has quickly become one of the more common, modern OpenAPI user interfaces and it easily diff --git a/wiki/src/aspnet-core/docs/swashbuckle.md b/wiki/src/aspnet-core/docs/swashbuckle.md index 71d4c537..cd2db5ee 100644 --- a/wiki/src/aspnet-core/docs/swashbuckle.md +++ b/wiki/src/aspnet-core/docs/swashbuckle.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/docs/swashbuckle-pre.md}} Remember to add the necessary references to one or both of the following: diff --git a/wiki/src/aspnet-core/errors.md b/wiki/src/aspnet-core/errors.md index 4efc78c6..68125247 100644 --- a/wiki/src/aspnet-core/errors.md +++ b/wiki/src/aspnet-core/errors.md @@ -1,3 +1,5 @@ + + {{#include ../shared/errors-pre.md}} ## Customization diff --git a/wiki/src/aspnet-core/examples.md b/wiki/src/aspnet-core/examples.md index c0ae40af..5d610268 100644 --- a/wiki/src/aspnet-core/examples.md +++ b/wiki/src/aspnet-core/examples.md @@ -1,3 +1,5 @@ + + # Examples Complete, runnable sample projects live in the [examples] folder of the repository. diff --git a/wiki/src/aspnet-core/ext/clients.md b/wiki/src/aspnet-core/ext/clients.md index 5960a704..68a111bc 100644 --- a/wiki/src/aspnet-core/ext/clients.md +++ b/wiki/src/aspnet-core/ext/clients.md @@ -1 +1,3 @@ + + {{#include ../../shared/ext/clients.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/ext/custom-attributes.md b/wiki/src/aspnet-core/ext/custom-attributes.md index c30a705a..ef39738b 100644 --- a/wiki/src/aspnet-core/ext/custom-attributes.md +++ b/wiki/src/aspnet-core/ext/custom-attributes.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/ext/custom-attributes-pre.md}} ``` diff --git a/wiki/src/aspnet-core/ext/custom-format.md b/wiki/src/aspnet-core/ext/custom-format.md index fee96ef7..4ab93ead 100644 --- a/wiki/src/aspnet-core/ext/custom-format.md +++ b/wiki/src/aspnet-core/ext/custom-format.md @@ -1 +1,3 @@ + + {{#include ../../shared/ext/custom-format.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/ext/third-party.md b/wiki/src/aspnet-core/ext/third-party.md index 04992b1c..fa03855f 100644 --- a/wiki/src/aspnet-core/ext/third-party.md +++ b/wiki/src/aspnet-core/ext/third-party.md @@ -1,3 +1,5 @@ + + # Third-Party The following are external, third-party extensions that showcase extensibility. diff --git a/wiki/src/aspnet-core/faq.md b/wiki/src/aspnet-core/faq.md index e008042c..ccfbb054 100644 --- a/wiki/src/aspnet-core/faq.md +++ b/wiki/src/aspnet-core/faq.md @@ -1 +1,3 @@ + + {{#include ../shared/faq.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/grpc/overview.md b/wiki/src/aspnet-core/grpc/overview.md index e04b9dff..90d8cafe 100644 --- a/wiki/src/aspnet-core/grpc/overview.md +++ b/wiki/src/aspnet-core/grpc/overview.md @@ -1,3 +1,5 @@ + + # API Versioning with gRPC Service API versioning using gRPC is nearly identical to the standard configuration with only a few modifications. When diff --git a/wiki/src/aspnet-core/grpc/request-parameters.md b/wiki/src/aspnet-core/grpc/request-parameters.md index 0b59b43f..2550cd70 100644 --- a/wiki/src/aspnet-core/grpc/request-parameters.md +++ b/wiki/src/aspnet-core/grpc/request-parameters.md @@ -1,3 +1,5 @@ + + # Request Parameters In most cases, adding API versioning to your gRPC services is orthogonal to how you define your service. gRPC sits atop diff --git a/wiki/src/aspnet-core/grpc/versioned-fields.md b/wiki/src/aspnet-core/grpc/versioned-fields.md index 52ce6fb6..1433b7fa 100644 --- a/wiki/src/aspnet-core/grpc/versioned-fields.md +++ b/wiki/src/aspnet-core/grpc/versioned-fields.md @@ -1,3 +1,5 @@ + + # Versioned Message Fields Protocol Buffer messages are designed to support backward compatibility. JSON schemas, on the other hand, can be strict diff --git a/wiki/src/aspnet-core/how-to/define-service-version.md b/wiki/src/aspnet-core/how-to/define-service-version.md index f0479fff..fe797d4d 100644 --- a/wiki/src/aspnet-core/how-to/define-service-version.md +++ b/wiki/src/aspnet-core/how-to/define-service-version.md @@ -1 +1,3 @@ + + {{#include ../../shared/how-to/define-service-version.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/how-to/deprecate-version.md b/wiki/src/aspnet-core/how-to/deprecate-version.md index af3cede0..6b96b3d8 100644 --- a/wiki/src/aspnet-core/how-to/deprecate-version.md +++ b/wiki/src/aspnet-core/how-to/deprecate-version.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/deprecate-version-pre.md}} This example demonstrates API versioning using all non-URL segment methods. diff --git a/wiki/src/aspnet-core/how-to/existing-services.md b/wiki/src/aspnet-core/how-to/existing-services.md index 5246d8fa..c933da53 100644 --- a/wiki/src/aspnet-core/how-to/existing-services.md +++ b/wiki/src/aspnet-core/how-to/existing-services.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/existing-services-pre.md}} ```c# diff --git a/wiki/src/aspnet-core/how-to/naming-conventions.md b/wiki/src/aspnet-core/how-to/naming-conventions.md index 8530f2dd..8ef24902 100644 --- a/wiki/src/aspnet-core/how-to/naming-conventions.md +++ b/wiki/src/aspnet-core/how-to/naming-conventions.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/naming-conventions-pre.md}} ```c# diff --git a/wiki/src/aspnet-core/how-to/overview.md b/wiki/src/aspnet-core/how-to/overview.md index 20e7c990..f5ed1d6d 100644 --- a/wiki/src/aspnet-core/how-to/overview.md +++ b/wiki/src/aspnet-core/how-to/overview.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/overview-pre.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/how-to/requested-version.md b/wiki/src/aspnet-core/how-to/requested-version.md index d8828930..18f1f3ee 100644 --- a/wiki/src/aspnet-core/how-to/requested-version.md +++ b/wiki/src/aspnet-core/how-to/requested-version.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/requested-version-pre.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/how-to/version-advertisement.md b/wiki/src/aspnet-core/how-to/version-advertisement.md index fad4f60f..cb98b22e 100644 --- a/wiki/src/aspnet-core/how-to/version-advertisement.md +++ b/wiki/src/aspnet-core/how-to/version-advertisement.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-advertisement-pre.md}} ```c# diff --git a/wiki/src/aspnet-core/how-to/version-by-header.md b/wiki/src/aspnet-core/how-to/version-by-header.md index bb127080..acdff918 100644 --- a/wiki/src/aspnet-core/how-to/version-by-header.md +++ b/wiki/src/aspnet-core/how-to/version-by-header.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-by-header-pre.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/how-to/version-by-media-type.md b/wiki/src/aspnet-core/how-to/version-by-media-type.md index 542c00e3..5178cb32 100644 --- a/wiki/src/aspnet-core/how-to/version-by-media-type.md +++ b/wiki/src/aspnet-core/how-to/version-by-media-type.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-by-media-type-pre.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/how-to/version-by-query-string.md b/wiki/src/aspnet-core/how-to/version-by-query-string.md index 5a964914..88f2aeb1 100644 --- a/wiki/src/aspnet-core/how-to/version-by-query-string.md +++ b/wiki/src/aspnet-core/how-to/version-by-query-string.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-by-query-string-pre.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/how-to/version-by-url.md b/wiki/src/aspnet-core/how-to/version-by-url.md index 19a26d90..69aada90 100644 --- a/wiki/src/aspnet-core/how-to/version-by-url.md +++ b/wiki/src/aspnet-core/how-to/version-by-url.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-by-url-pre.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/how-to/version-interleaving.md b/wiki/src/aspnet-core/how-to/version-interleaving.md index 479d6c12..20bf0ae5 100644 --- a/wiki/src/aspnet-core/how-to/version-interleaving.md +++ b/wiki/src/aspnet-core/how-to/version-interleaving.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-interleaving-pre.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/how-to/version-neutral.md b/wiki/src/aspnet-core/how-to/version-neutral.md index 44c13595..962b1efb 100644 --- a/wiki/src/aspnet-core/how-to/version-neutral.md +++ b/wiki/src/aspnet-core/how-to/version-neutral.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-neutral-pre.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/how-to/versioned-models.md b/wiki/src/aspnet-core/how-to/versioned-models.md index 2789ec3c..28c89255 100644 --- a/wiki/src/aspnet-core/how-to/versioned-models.md +++ b/wiki/src/aspnet-core/how-to/versioned-models.md @@ -1,3 +1,5 @@ + + # Versioned Models When an API is versioned, it is often necessary to version the models that are used in the API. This is especially true diff --git a/wiki/src/aspnet-core/limitations.md b/wiki/src/aspnet-core/limitations.md index 26c2911a..5df13bf9 100644 --- a/wiki/src/aspnet-core/limitations.md +++ b/wiki/src/aspnet-core/limitations.md @@ -1,3 +1,5 @@ + + # Known Limitations ## URL Path Segment diff --git a/wiki/src/aspnet-core/odata/batching.md b/wiki/src/aspnet-core/odata/batching.md index 35ad7fe9..32a51288 100644 --- a/wiki/src/aspnet-core/odata/batching.md +++ b/wiki/src/aspnet-core/odata/batching.md @@ -1,3 +1,5 @@ + + # Batching OData batch operations are meant to execute the same way that other requests do; however, there may be some minor, but diff --git a/wiki/src/aspnet-core/odata/controllers.md b/wiki/src/aspnet-core/odata/controllers.md index 7ecd626e..b4d8ade8 100644 --- a/wiki/src/aspnet-core/odata/controllers.md +++ b/wiki/src/aspnet-core/odata/controllers.md @@ -1 +1,3 @@ + + {{#include ../../shared/odata/controllers.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/odata/metadata.md b/wiki/src/aspnet-core/odata/metadata.md index e5662e48..a2a23cbc 100644 --- a/wiki/src/aspnet-core/odata/metadata.md +++ b/wiki/src/aspnet-core/odata/metadata.md @@ -1 +1,3 @@ + + {{#include ../../shared/odata/metadata.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/odata/model-builder.md b/wiki/src/aspnet-core/odata/model-builder.md index 819f21fd..ffa243f0 100644 --- a/wiki/src/aspnet-core/odata/model-builder.md +++ b/wiki/src/aspnet-core/odata/model-builder.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/odata/model-builder-pre.md}} >[!NOTE] diff --git a/wiki/src/aspnet-core/odata/model-config.md b/wiki/src/aspnet-core/odata/model-config.md index 0bc265ff..f7bc089a 100644 --- a/wiki/src/aspnet-core/odata/model-config.md +++ b/wiki/src/aspnet-core/odata/model-config.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/odata/model-config.md}} ## Dependency Injection diff --git a/wiki/src/aspnet-core/odata/model-substitution.md b/wiki/src/aspnet-core/odata/model-substitution.md index b98dc00c..7efc6894 100644 --- a/wiki/src/aspnet-core/odata/model-substitution.md +++ b/wiki/src/aspnet-core/odata/model-substitution.md @@ -1 +1,3 @@ + + {{#include ../../shared/odata/model-substitution.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/odata/overview.md b/wiki/src/aspnet-core/odata/overview.md index 05b8d4e4..aaf74cd2 100644 --- a/wiki/src/aspnet-core/odata/overview.md +++ b/wiki/src/aspnet-core/odata/overview.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/odata/overview-pre.md}} ```c# diff --git a/wiki/src/aspnet-core/quick-starts/existing-services.md b/wiki/src/aspnet-core/quick-starts/existing-services.md index f93bb745..fdb5153d 100644 --- a/wiki/src/aspnet-core/quick-starts/existing-services.md +++ b/wiki/src/aspnet-core/quick-starts/existing-services.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/quick-starts/existing-services.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/quick-starts/migration.md b/wiki/src/aspnet-core/quick-starts/migration.md index e6d8d7ae..aaa68b25 100644 --- a/wiki/src/aspnet-core/quick-starts/migration.md +++ b/wiki/src/aspnet-core/quick-starts/migration.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/quick-starts/migration-overview.md}} ## Package Identifiers diff --git a/wiki/src/aspnet-core/quick-starts/new-services.md b/wiki/src/aspnet-core/quick-starts/new-services.md index 6867a609..3633d9c5 100644 --- a/wiki/src/aspnet-core/quick-starts/new-services.md +++ b/wiki/src/aspnet-core/quick-starts/new-services.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/quick-starts/new-services.md}} ### Minimal API diff --git a/wiki/src/aspnet-core/version-discovery.md b/wiki/src/aspnet-core/version-discovery.md index 6dd544ff..2ecc20ec 100644 --- a/wiki/src/aspnet-core/version-discovery.md +++ b/wiki/src/aspnet-core/version-discovery.md @@ -1,3 +1,5 @@ + + {{#include ../shared/version-discovery.md}} diff --git a/wiki/src/aspnet-core/version-format.md b/wiki/src/aspnet-core/version-format.md index 31deaa1c..d99a7fbb 100644 --- a/wiki/src/aspnet-core/version-format.md +++ b/wiki/src/aspnet-core/version-format.md @@ -1 +1,3 @@ + + {{#include ../shared/version-format.md}} \ No newline at end of file diff --git a/wiki/src/aspnet-core/version-policies.md b/wiki/src/aspnet-core/version-policies.md index 109af93a..3c9deb03 100644 --- a/wiki/src/aspnet-core/version-policies.md +++ b/wiki/src/aspnet-core/version-policies.md @@ -1,3 +1,5 @@ + + {{#include ../shared/version-policies.md}} diff --git a/wiki/src/aspnet/config/conventions.md b/wiki/src/aspnet/config/conventions.md index 447e46eb..5cb7edde 100644 --- a/wiki/src/aspnet/config/conventions.md +++ b/wiki/src/aspnet/config/conventions.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/config/conventions-pre.md}} ```c# diff --git a/wiki/src/aspnet/config/options.md b/wiki/src/aspnet/config/options.md index 7dacf469..6277a0de 100644 --- a/wiki/src/aspnet/config/options.md +++ b/wiki/src/aspnet/config/options.md @@ -1 +1,3 @@ + + {{#include ../../shared/config/options.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/config/overview.md b/wiki/src/aspnet/config/overview.md index bb58eb85..347731ee 100644 --- a/wiki/src/aspnet/config/overview.md +++ b/wiki/src/aspnet/config/overview.md @@ -1,3 +1,5 @@ + + # Configuring Your Application Although different variations of ASP.NET have distinct application initialization methods, careful consideration was diff --git a/wiki/src/aspnet/config/reader.md b/wiki/src/aspnet/config/reader.md index 38d23c8e..69a64ff0 100644 --- a/wiki/src/aspnet/config/reader.md +++ b/wiki/src/aspnet/config/reader.md @@ -1 +1,3 @@ + + {{#include ../../shared/config/reader.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/config/selector.md b/wiki/src/aspnet/config/selector.md index cfc5e1f2..0f3a9aa8 100644 --- a/wiki/src/aspnet/config/selector.md +++ b/wiki/src/aspnet/config/selector.md @@ -1 +1,3 @@ + + {{#include ../../shared/config/selector.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/docs/odata-options.md b/wiki/src/aspnet/docs/odata-options.md index d31600ee..a0fa9f11 100644 --- a/wiki/src/aspnet/docs/odata-options.md +++ b/wiki/src/aspnet/docs/odata-options.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/docs/odata-options-pre.md}} - [UseApiExplorerSettings](#use-api-explorer-settings)1 diff --git a/wiki/src/aspnet/docs/options.md b/wiki/src/aspnet/docs/options.md index 67d7b7b0..7360b461 100644 --- a/wiki/src/aspnet/docs/options.md +++ b/wiki/src/aspnet/docs/options.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/docs/options-pre.md}} {{#include ../../shared/docs/odata-options-post.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/docs/overview.md b/wiki/src/aspnet/docs/overview.md index 71babd13..b3b6f8ca 100644 --- a/wiki/src/aspnet/docs/overview.md +++ b/wiki/src/aspnet/docs/overview.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/docs/overview-pre.md}} Any OpenAPI generator such as [Swashbuckle][openapi-swashbuckle], or [NSwag][openapi-nswag] that leverage the API diff --git a/wiki/src/aspnet/docs/swashbuckle.md b/wiki/src/aspnet/docs/swashbuckle.md index 8da22e5b..79d58b5d 100644 --- a/wiki/src/aspnet/docs/swashbuckle.md +++ b/wiki/src/aspnet/docs/swashbuckle.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/docs/swashbuckle-pre.md}} Remember to add the necessary references to one or both of the following: diff --git a/wiki/src/aspnet/errors.md b/wiki/src/aspnet/errors.md index 31f83126..de5314d7 100644 --- a/wiki/src/aspnet/errors.md +++ b/wiki/src/aspnet/errors.md @@ -1,3 +1,5 @@ + + {{#include ../shared/errors-pre.md}} ## Customization diff --git a/wiki/src/aspnet/examples.md b/wiki/src/aspnet/examples.md index 54c1e6d9..1033b603 100644 --- a/wiki/src/aspnet/examples.md +++ b/wiki/src/aspnet/examples.md @@ -1,3 +1,5 @@ + + # Examples Complete, runnable sample projects live in the [examples] folder of the repository. diff --git a/wiki/src/aspnet/ext/clients.md b/wiki/src/aspnet/ext/clients.md index 5960a704..2cc3db3b 100644 --- a/wiki/src/aspnet/ext/clients.md +++ b/wiki/src/aspnet/ext/clients.md @@ -1 +1,3 @@ + + {{#include ../../shared/ext/clients.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/ext/custom-attributes.md b/wiki/src/aspnet/ext/custom-attributes.md index 167d3492..74b92b42 100644 --- a/wiki/src/aspnet/ext/custom-attributes.md +++ b/wiki/src/aspnet/ext/custom-attributes.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/ext/custom-attributes-pre.md}} ``` diff --git a/wiki/src/aspnet/ext/custom-format.md b/wiki/src/aspnet/ext/custom-format.md index fee96ef7..86942eab 100644 --- a/wiki/src/aspnet/ext/custom-format.md +++ b/wiki/src/aspnet/ext/custom-format.md @@ -1 +1,3 @@ + + {{#include ../../shared/ext/custom-format.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/faq.md b/wiki/src/aspnet/faq.md index e008042c..e696b8db 100644 --- a/wiki/src/aspnet/faq.md +++ b/wiki/src/aspnet/faq.md @@ -1 +1,3 @@ + + {{#include ../shared/faq.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/how-to/define-service-version.md b/wiki/src/aspnet/how-to/define-service-version.md index 238be393..745b5533 100644 --- a/wiki/src/aspnet/how-to/define-service-version.md +++ b/wiki/src/aspnet/how-to/define-service-version.md @@ -1,2 +1,4 @@ + + {{#include ../../shared/how-to/define-service-version.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/how-to/deprecate-version.md b/wiki/src/aspnet/how-to/deprecate-version.md index 883f7624..acee9aaf 100644 --- a/wiki/src/aspnet/how-to/deprecate-version.md +++ b/wiki/src/aspnet/how-to/deprecate-version.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/deprecate-version-pre.md}} This example demonstrates API versioning using all non-URL segment methods. diff --git a/wiki/src/aspnet/how-to/existing-services.md b/wiki/src/aspnet/how-to/existing-services.md index 3fc69275..03c44331 100644 --- a/wiki/src/aspnet/how-to/existing-services.md +++ b/wiki/src/aspnet/how-to/existing-services.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/existing-services-pre.md}} ```c# diff --git a/wiki/src/aspnet/how-to/naming-conventions.md b/wiki/src/aspnet/how-to/naming-conventions.md index 9236b4cb..cde9b47a 100644 --- a/wiki/src/aspnet/how-to/naming-conventions.md +++ b/wiki/src/aspnet/how-to/naming-conventions.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/naming-conventions-pre.md}} ```c# diff --git a/wiki/src/aspnet/how-to/overview.md b/wiki/src/aspnet/how-to/overview.md index e1febded..9669c07d 100644 --- a/wiki/src/aspnet/how-to/overview.md +++ b/wiki/src/aspnet/how-to/overview.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/overview-pre.md}} >[!IMPORTANT] diff --git a/wiki/src/aspnet/how-to/requested-version.md b/wiki/src/aspnet/how-to/requested-version.md index 522302db..9b48ff02 100644 --- a/wiki/src/aspnet/how-to/requested-version.md +++ b/wiki/src/aspnet/how-to/requested-version.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/requested-version-pre.md}} ### Web API diff --git a/wiki/src/aspnet/how-to/version-advertisement.md b/wiki/src/aspnet/how-to/version-advertisement.md index cb5bb131..0092af25 100644 --- a/wiki/src/aspnet/how-to/version-advertisement.md +++ b/wiki/src/aspnet/how-to/version-advertisement.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-advertisement-pre.md}} ```c# diff --git a/wiki/src/aspnet/how-to/version-by-header.md b/wiki/src/aspnet/how-to/version-by-header.md index 9af32b00..17f912e3 100644 --- a/wiki/src/aspnet/how-to/version-by-header.md +++ b/wiki/src/aspnet/how-to/version-by-header.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-by-header-pre.md}} ### Web API diff --git a/wiki/src/aspnet/how-to/version-by-media-type.md b/wiki/src/aspnet/how-to/version-by-media-type.md index d110927a..bdd2289a 100644 --- a/wiki/src/aspnet/how-to/version-by-media-type.md +++ b/wiki/src/aspnet/how-to/version-by-media-type.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-by-media-type-pre.md}} ### Web API diff --git a/wiki/src/aspnet/how-to/version-by-query-string.md b/wiki/src/aspnet/how-to/version-by-query-string.md index 920d705d..60d14d0e 100644 --- a/wiki/src/aspnet/how-to/version-by-query-string.md +++ b/wiki/src/aspnet/how-to/version-by-query-string.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-by-query-string-pre.md}} ### Web API diff --git a/wiki/src/aspnet/how-to/version-by-url.md b/wiki/src/aspnet/how-to/version-by-url.md index 1318a02f..b78b4fce 100644 --- a/wiki/src/aspnet/how-to/version-by-url.md +++ b/wiki/src/aspnet/how-to/version-by-url.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-by-url-pre.md}} ### Web API diff --git a/wiki/src/aspnet/how-to/version-interleaving.md b/wiki/src/aspnet/how-to/version-interleaving.md index d13825ee..4742cc36 100644 --- a/wiki/src/aspnet/how-to/version-interleaving.md +++ b/wiki/src/aspnet/how-to/version-interleaving.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-interleaving-pre.md}} ### Web API diff --git a/wiki/src/aspnet/how-to/version-neutral.md b/wiki/src/aspnet/how-to/version-neutral.md index e8dd7457..fcd2cb3d 100644 --- a/wiki/src/aspnet/how-to/version-neutral.md +++ b/wiki/src/aspnet/how-to/version-neutral.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/how-to/version-neutral-pre.md}} ### Web API diff --git a/wiki/src/aspnet/limitations.md b/wiki/src/aspnet/limitations.md index b2a7483f..1d45210c 100644 --- a/wiki/src/aspnet/limitations.md +++ b/wiki/src/aspnet/limitations.md @@ -1,3 +1,5 @@ + + # Known Limitations ## URL Path Segment diff --git a/wiki/src/aspnet/odata/controllers.md b/wiki/src/aspnet/odata/controllers.md index 7ecd626e..a03af6d7 100644 --- a/wiki/src/aspnet/odata/controllers.md +++ b/wiki/src/aspnet/odata/controllers.md @@ -1 +1,3 @@ + + {{#include ../../shared/odata/controllers.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/odata/metadata.md b/wiki/src/aspnet/odata/metadata.md index e5662e48..2c4974af 100644 --- a/wiki/src/aspnet/odata/metadata.md +++ b/wiki/src/aspnet/odata/metadata.md @@ -1 +1,3 @@ + + {{#include ../../shared/odata/metadata.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/odata/model-builder.md b/wiki/src/aspnet/odata/model-builder.md index 4d93e265..b4c419e2 100644 --- a/wiki/src/aspnet/odata/model-builder.md +++ b/wiki/src/aspnet/odata/model-builder.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/odata/model-builder-pre.md}} {{#include ../../shared/odata/model-builder-post.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/odata/model-config.md b/wiki/src/aspnet/odata/model-config.md index facd3da5..31b8eded 100644 --- a/wiki/src/aspnet/odata/model-config.md +++ b/wiki/src/aspnet/odata/model-config.md @@ -1 +1,3 @@ + + {{#include ../../shared/odata/model-config.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/odata/model-substitution.md b/wiki/src/aspnet/odata/model-substitution.md index b98dc00c..7704503b 100644 --- a/wiki/src/aspnet/odata/model-substitution.md +++ b/wiki/src/aspnet/odata/model-substitution.md @@ -1 +1,3 @@ + + {{#include ../../shared/odata/model-substitution.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/odata/overview.md b/wiki/src/aspnet/odata/overview.md index 2027c737..e8037051 100644 --- a/wiki/src/aspnet/odata/overview.md +++ b/wiki/src/aspnet/odata/overview.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/odata/overview-pre.md}} ```c# diff --git a/wiki/src/aspnet/odata/protocol-transition.md b/wiki/src/aspnet/odata/protocol-transition.md index f2d794e3..88ca6ee9 100644 --- a/wiki/src/aspnet/odata/protocol-transition.md +++ b/wiki/src/aspnet/odata/protocol-transition.md @@ -1,3 +1,5 @@ + + # Protocol Transitions One of the primary reasons to version a service is to facilitate changes in behavior and/or data exchange with the diff --git a/wiki/src/aspnet/quick-starts/existing-services.md b/wiki/src/aspnet/quick-starts/existing-services.md index 83d17c43..98e65c73 100644 --- a/wiki/src/aspnet/quick-starts/existing-services.md +++ b/wiki/src/aspnet/quick-starts/existing-services.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/quick-starts/existing-services.md}} ### Web API diff --git a/wiki/src/aspnet/quick-starts/migration.md b/wiki/src/aspnet/quick-starts/migration.md index 78da3f64..940942d1 100644 --- a/wiki/src/aspnet/quick-starts/migration.md +++ b/wiki/src/aspnet/quick-starts/migration.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/quick-starts/migration-overview.md}} ## Package Identifiers diff --git a/wiki/src/aspnet/quick-starts/new-services.md b/wiki/src/aspnet/quick-starts/new-services.md index c95167e0..ea6d1183 100644 --- a/wiki/src/aspnet/quick-starts/new-services.md +++ b/wiki/src/aspnet/quick-starts/new-services.md @@ -1,3 +1,5 @@ + + {{#include ../../shared/quick-starts/new-services.md}} ### Web API diff --git a/wiki/src/aspnet/version-discovery.md b/wiki/src/aspnet/version-discovery.md index 97a4160b..c1e1aa54 100644 --- a/wiki/src/aspnet/version-discovery.md +++ b/wiki/src/aspnet/version-discovery.md @@ -1,3 +1,5 @@ + + {{#include ../shared/version-discovery.md}} ### Web API diff --git a/wiki/src/aspnet/version-format.md b/wiki/src/aspnet/version-format.md index 2d1f44d6..feae6d5d 100644 --- a/wiki/src/aspnet/version-format.md +++ b/wiki/src/aspnet/version-format.md @@ -1 +1,3 @@ -{{#include ../shared/how-to/define-service-version.md}} \ No newline at end of file + + +{{#include ../shared/version-format.md}} \ No newline at end of file diff --git a/wiki/src/aspnet/version-policies.md b/wiki/src/aspnet/version-policies.md index ca044b94..004cc535 100644 --- a/wiki/src/aspnet/version-policies.md +++ b/wiki/src/aspnet/version-policies.md @@ -1,2 +1,4 @@ + + {{#include ../shared/version-policies.md}} \ No newline at end of file diff --git a/wiki/src/diagnostic/av0001.md b/wiki/src/diagnostic/av0001.md index 0c48c25f..49bd2145 100644 --- a/wiki/src/diagnostic/av0001.md +++ b/wiki/src/diagnostic/av0001.md @@ -1,3 +1,5 @@ + + # AV0001: Invalid API version | | Value | @@ -28,7 +30,7 @@ public class ExampleController : ControllerBase } ``` -The text `"abc"` is not a valid API version. This would not detected until runtime. +The text `"abc"` is not a valid API version. This would not be detected until runtime. ## How to Fix Violations diff --git a/wiki/src/diagnostic/av0002.md b/wiki/src/diagnostic/av0002.md index b15f5ac9..f8687b12 100644 --- a/wiki/src/diagnostic/av0002.md +++ b/wiki/src/diagnostic/av0002.md @@ -1,3 +1,5 @@ + + # AV0002: Invalid API version range | | Value | @@ -30,7 +32,7 @@ public class Person } ``` -The text `")2.0,]"` is not a valid API version range. This would not detected until runtime. +The text `")2.0,]"` is not a valid API version range. This would not be detected until runtime. ## How to Fix Violations diff --git a/wiki/src/diagnostic/av0003.md b/wiki/src/diagnostic/av0003.md index d17eb861..d58017c4 100644 --- a/wiki/src/diagnostic/av0003.md +++ b/wiki/src/diagnostic/av0003.md @@ -1,3 +1,5 @@ + + # AV0003: Invalid API version status | | Value | @@ -28,7 +30,7 @@ public class ExampleController : ControllerBase } ``` -The text `"preview-1"` is not a valid API version status. This would not detected until runtime. +The text `"preview-1"` is not a valid API version status. This would not be detected until runtime. ## How to Fix Violations diff --git a/wiki/src/diagnostic/av0004.md b/wiki/src/diagnostic/av0004.md index ecfb8b90..18cd6c4f 100644 --- a/wiki/src/diagnostic/av0004.md +++ b/wiki/src/diagnostic/av0004.md @@ -1,3 +1,5 @@ + + # AV0004: Invalid API version number | | Value | @@ -28,7 +30,7 @@ public class ExampleController : ControllerBase } ``` -The text `-2.0` is not a valid API version. This would not detected until runtime. +The text `-2.0` is not a valid API version. This would not be detected until runtime. ## How to Fix Violations diff --git a/wiki/src/diagnostic/av0005.md b/wiki/src/diagnostic/av0005.md index e4d587a9..da8c3c30 100644 --- a/wiki/src/diagnostic/av0005.md +++ b/wiki/src/diagnostic/av0005.md @@ -1,3 +1,5 @@ + + # AV0005: Invalid API version year | | Value | @@ -27,7 +29,7 @@ public class ExampleController : ControllerBase } ``` -The year `10_000` is not a valid API version. The year must be between 1 and 9999. This would not detected until +The year `10_000` is not a valid API version. The year must be between 1 and 9999. This would not be detected until runtime. ## How to Fix Violations diff --git a/wiki/src/diagnostic/av0006.md b/wiki/src/diagnostic/av0006.md index 182dd3c8..46db08dd 100644 --- a/wiki/src/diagnostic/av0006.md +++ b/wiki/src/diagnostic/av0006.md @@ -1,3 +1,5 @@ + + # AV0006: Invalid API version month | | Value | @@ -27,7 +29,7 @@ public class ExampleController : ControllerBase } ``` -The month `13` is not a valid API version. The month must be between 1 and 12. This would not detected until runtime. +The month `13` is not a valid API version. The month must be between 1 and 12. This would not be detected until runtime. ## How to Fix Violations diff --git a/wiki/src/diagnostic/av0007.md b/wiki/src/diagnostic/av0007.md index 397581f7..f3361725 100644 --- a/wiki/src/diagnostic/av0007.md +++ b/wiki/src/diagnostic/av0007.md @@ -1,3 +1,5 @@ + + # AV0007: Invalid API version day | | Value | @@ -27,7 +29,7 @@ public class ExampleController : ControllerBase } ``` -The day `32` is not a valid API version. The day must be between 1 and 31. This would not detected until runtime. +The day `32` is not a valid API version. The day must be between 1 and 31. This would not be detected until runtime. ## How to Fix Violations diff --git a/wiki/src/diagnostic/av0008.md b/wiki/src/diagnostic/av0008.md index e5d3f37d..af8d294e 100644 --- a/wiki/src/diagnostic/av0008.md +++ b/wiki/src/diagnostic/av0008.md @@ -1,3 +1,5 @@ + + # AV0008: Invalid API version date | | Value | @@ -27,7 +29,7 @@ public class ExampleController : ControllerBase } ``` -The date `2026-02-29` is not a valid API version because 2026 is not a leap year. This would not detected until +The date `2026-02-29` is not a valid API version because 2026 is not a leap year. This would not be detected until runtime. ## How to Fix Violations diff --git a/wiki/src/diagnostic/av0009.md b/wiki/src/diagnostic/av0009.md index c0f02741..0770b5e2 100644 --- a/wiki/src/diagnostic/av0009.md +++ b/wiki/src/diagnostic/av0009.md @@ -1,3 +1,5 @@ + + # AV0009: Invalid API version format specifier | | Value | diff --git a/wiki/src/diagnostic/av0010.md b/wiki/src/diagnostic/av0010.md index c347c10a..7ba69c8d 100644 --- a/wiki/src/diagnostic/av0010.md +++ b/wiki/src/diagnostic/av0010.md @@ -1,3 +1,5 @@ + + # AV0010: Unexpected API version format | | Value | diff --git a/wiki/src/diagnostic/av0011.md b/wiki/src/diagnostic/av0011.md index 1620f8d4..e03922d6 100644 --- a/wiki/src/diagnostic/av0011.md +++ b/wiki/src/diagnostic/av0011.md @@ -1,3 +1,5 @@ + + # AV0011: Remove unnecessary default API version | | Value | diff --git a/wiki/src/diagnostic/av0012.md b/wiki/src/diagnostic/av0012.md index 98ec620c..27d65c1d 100644 --- a/wiki/src/diagnostic/av0012.md +++ b/wiki/src/diagnostic/av0012.md @@ -1,3 +1,5 @@ + + # AV0012: Invalid default API version | | Value | diff --git a/wiki/src/diagnostic/av0013.md b/wiki/src/diagnostic/av0013.md index be0259df..5c443fff 100644 --- a/wiki/src/diagnostic/av0013.md +++ b/wiki/src/diagnostic/av0013.md @@ -1,3 +1,5 @@ + + # AV0013: Missing AddMvc | | Value | diff --git a/wiki/src/diagnostic/av0014.md b/wiki/src/diagnostic/av0014.md index c3589237..199dd28d 100644 --- a/wiki/src/diagnostic/av0014.md +++ b/wiki/src/diagnostic/av0014.md @@ -1,3 +1,5 @@ + + # AV0014: Missing API behavior | | Value | diff --git a/wiki/src/diagnostic/av0015.md b/wiki/src/diagnostic/av0015.md index e25a5a74..29be74f6 100644 --- a/wiki/src/diagnostic/av0015.md +++ b/wiki/src/diagnostic/av0015.md @@ -1,3 +1,5 @@ + + # AV0015: Use a specific API version reader | | Value | diff --git a/wiki/src/diagnostic/av0016.md b/wiki/src/diagnostic/av0016.md index 8c6eeb40..8a9f7632 100644 --- a/wiki/src/diagnostic/av0016.md +++ b/wiki/src/diagnostic/av0016.md @@ -1,3 +1,5 @@ + + # AV0016: Do not assume default API version | | Value | diff --git a/wiki/src/diagnostic/av0017.md b/wiki/src/diagnostic/av0017.md index ff00b8bf..983976cb 100644 --- a/wiki/src/diagnostic/av0017.md +++ b/wiki/src/diagnostic/av0017.md @@ -1,3 +1,5 @@ + + # AV0017: Remove unnecessary default value | | Value | diff --git a/wiki/src/diagnostic/av0018.md b/wiki/src/diagnostic/av0018.md index 5c1ca216..2a8933e7 100644 --- a/wiki/src/diagnostic/av0018.md +++ b/wiki/src/diagnostic/av0018.md @@ -1,3 +1,5 @@ + + # AV0018: All endpoints are version-neutral | | Value | diff --git a/wiki/src/diagnostic/av0019.md b/wiki/src/diagnostic/av0019.md index e3c21ce3..c1102838 100644 --- a/wiki/src/diagnostic/av0019.md +++ b/wiki/src/diagnostic/av0019.md @@ -1,3 +1,5 @@ + + # AV0019: An API cannot be versioned and version-neutral at the same time | | Value | diff --git a/wiki/src/diagnostic/av0020.md b/wiki/src/diagnostic/av0020.md index 9d0c5042..2fbc4460 100644 --- a/wiki/src/diagnostic/av0020.md +++ b/wiki/src/diagnostic/av0020.md @@ -1,3 +1,5 @@ + + # AV0020: Remove unnecessary API explorer | | Value | diff --git a/wiki/src/diagnostic/av0021.md b/wiki/src/diagnostic/av0021.md index 0548f6bc..1decdcf6 100644 --- a/wiki/src/diagnostic/av0021.md +++ b/wiki/src/diagnostic/av0021.md @@ -1,3 +1,5 @@ + + # AV0021: Use the versioned API explorer | | Value | diff --git a/wiki/src/diagnostic/av0022.md b/wiki/src/diagnostic/av0022.md index 22b081fc..d7da2674 100644 --- a/wiki/src/diagnostic/av0022.md +++ b/wiki/src/diagnostic/av0022.md @@ -1,3 +1,5 @@ + + # AV0022: Missing AddOData | | Value | diff --git a/wiki/src/diagnostic/av0023.md b/wiki/src/diagnostic/av0023.md index 94611f48..2d59e133 100644 --- a/wiki/src/diagnostic/av0023.md +++ b/wiki/src/diagnostic/av0023.md @@ -1,3 +1,5 @@ + + # AV0023: Route components are ignored | | Value | diff --git a/wiki/src/diagnostic/av0024.md b/wiki/src/diagnostic/av0024.md index 3bd54c4a..7c79fecd 100644 --- a/wiki/src/diagnostic/av0024.md +++ b/wiki/src/diagnostic/av0024.md @@ -1,3 +1,5 @@ + + # AV0024: Remove unnecessary API explorer option | | Value | diff --git a/wiki/src/diagnostic/av0025.md b/wiki/src/diagnostic/av0025.md index b0d6a18b..c8d861d0 100644 --- a/wiki/src/diagnostic/av0025.md +++ b/wiki/src/diagnostic/av0025.md @@ -1,3 +1,5 @@ + + # AV0025: Missing OpenAPI document description | | Value | diff --git a/wiki/src/diagnostic/av0026.md b/wiki/src/diagnostic/av0026.md index 27096231..5974f099 100644 --- a/wiki/src/diagnostic/av0026.md +++ b/wiki/src/diagnostic/av0026.md @@ -1,3 +1,5 @@ + + # AV0026: Remove unnecessary group name format | | Value | diff --git a/wiki/src/diagnostic/av0027.md b/wiki/src/diagnostic/av0027.md index 0f33180f..059a5f47 100644 --- a/wiki/src/diagnostic/av0027.md +++ b/wiki/src/diagnostic/av0027.md @@ -1,3 +1,5 @@ + + # AV0027: Use DescribeApiVersions | | Value | diff --git a/wiki/src/diagnostic/av0028.md b/wiki/src/diagnostic/av0028.md index af72947e..69d751ef 100644 --- a/wiki/src/diagnostic/av0028.md +++ b/wiki/src/diagnostic/av0028.md @@ -1,3 +1,5 @@ + + # AV0028: Sunset policy takes effect before deprecation | | Value | diff --git a/wiki/src/diagnostic/av0029.md b/wiki/src/diagnostic/av0029.md index 8ffc685a..046ee489 100644 --- a/wiki/src/diagnostic/av0029.md +++ b/wiki/src/diagnostic/av0029.md @@ -1,3 +1,5 @@ + + # AV0029: Remove unnecessary OpenAPI services | | Value | diff --git a/wiki/src/diagnostic/av0030.md b/wiki/src/diagnostic/av0030.md index 54c60384..b79c907d 100644 --- a/wiki/src/diagnostic/av0030.md +++ b/wiki/src/diagnostic/av0030.md @@ -1,3 +1,5 @@ + + # AV0030: Missing WithDocumentPerVersion | | Value | diff --git a/wiki/src/diagnostic/av0031.md b/wiki/src/diagnostic/av0031.md index 67aec880..77384a16 100644 --- a/wiki/src/diagnostic/av0031.md +++ b/wiki/src/diagnostic/av0031.md @@ -1,3 +1,5 @@ + + # AV0031: Missing API explorer | | Value | diff --git a/wiki/src/diagnostic/overview.md b/wiki/src/diagnostic/overview.md index bfa2daa9..b392e578 100644 --- a/wiki/src/diagnostic/overview.md +++ b/wiki/src/diagnostic/overview.md @@ -1,3 +1,5 @@ + + # Diagnostic Code Analysis for ASP.NET API Versioning .NET compiler platform analyzers inspect application code for code quality and style issues using ASP.NET API diff --git a/wiki/src/getting-started.md b/wiki/src/getting-started.md index 06938877..ebb35392 100644 --- a/wiki/src/getting-started.md +++ b/wiki/src/getting-started.md @@ -1,3 +1,5 @@ + + # Getting Started The simplest way to get started is to install the library. diff --git a/wiki/src/og-image.png b/wiki/src/og-image.png new file mode 100644 index 00000000..e0174f31 Binary files /dev/null and b/wiki/src/og-image.png differ diff --git a/wiki/theme/custom.css b/wiki/theme/custom.css index 808faee3..3c373c53 100644 --- a/wiki/theme/custom.css +++ b/wiki/theme/custom.css @@ -213,3 +213,68 @@ strong { .severity-error { color: rgb(192, 0, 0); } + +/* + * The 404 page, authored as src/404.md. The logo mark is a ring, so it stands in for + * the zero of "404" rather than sitting beside it. The ring reads as static while the + * cobra inside it sways, which is the whole reason the rotation is on the mark itself. + */ +.not-found { + text-align: center; +} + +.not-found-code { + display: flex; + align-items: center; + justify-content: center; + gap: 0.05em; + /* Scales with the viewport so the mark stays legible on a phone without + overflowing the content column on a wide screen. */ + font-size: clamp(3.5rem, 16vw, 8rem); + font-weight: 700; + line-height: 1; + margin-bottom: 0.25em; +} + +.not-found-code .not-found-logo { + width: 1.15em; + height: 1.15em; + /* Resolved against this stylesheet, not the document, so the mdBook + sets on the 404 page does not apply. Same relative path as .menu-title::before. */ + background: url("../logo.svg") no-repeat center / contain; + animation: not-found-sway 5s ease-in-out infinite alternate; +} + +/* matches the header logo swap: the dark strokes vanish on the dark themes */ +.ayu .not-found-code .not-found-logo, +.coal .not-found-code .not-found-logo, +.navy .not-found-code .not-found-logo { + background-image: url("../logo-dark.svg"); +} + +@keyframes not-found-sway { + from { transform: rotate(-9deg); } + to { transform: rotate(9deg); } +} + +@media (prefers-reduced-motion: reduce) { + .not-found-code .not-found-logo { + animation: none; + } +} + +/* The headline is the page's own title; the numeral above it already shouts. */ +.not-found h1 { + margin-top: 0; +} + +/* + * Left-aligned so the response reads as a response. Sized to its content and centred + * rather than filling the column, so the two blocks line up as one quoted exchange. + */ +.not-found pre { + text-align: left; + width: fit-content; + max-width: 100%; + margin-inline: auto; +} diff --git a/wiki/theme/head.hbs b/wiki/theme/head.hbs new file mode 100644 index 00000000..006dc802 --- /dev/null +++ b/wiki/theme/head.hbs @@ -0,0 +1,32 @@ + + + + + + + + + +{{#if description}} + +{{/if}} + + + + +{{#if description}} + +{{/if}} diff --git a/wiki/tools/Add-PageMetadata.ps1 b/wiki/tools/Add-PageMetadata.ps1 new file mode 100644 index 00000000..1aa82acb --- /dev/null +++ b/wiki/tools/Add-PageMetadata.ps1 @@ -0,0 +1,141 @@ +<# +.SYNOPSIS +Injects per-page description, canonical, and Open Graph URL metadata into a built mdBook site. + +.DESCRIPTION +mdBook's description is book-level only: [book] description in book.toml applies to every page, +and the HTML renderer exposes no per-page equivalent. A preprocessor cannot supply one either -- +mdBook hands a preprocessor (PreprocessorContext, Book) and takes back only Book, so it can +rewrite chapter content but not the config the renderer reads for the page head. + +So pages declare their own description as an HTML comment in the markdown: + + + +Markdown passes the comment through verbatim, it renders invisibly, and mdBook's search indexer +ignores it. Crucially the comment lives in the *including* page rather than the shared partial, +so the aspnet/ and aspnet-core/ pages that share a body via {{#include ../shared/...}} still get +distinct descriptions. + +This script runs after `mdbook build`. For every page it lifts that comment into as +name="description", og:description, and twitter:description, and derives the absolute page URL for +og:url and -- which the Handlebars template cannot do, because mdBook +registers no string helpers and {{path}} is the source .md path. + +Rewriting is idempotent: existing tags it owns are removed before the fresh ones are inserted, so +running twice is harmless. + +.PARAMETER Book +Path to the generated book directory (the mdbook build output). + +.PARAMETER BaseUrl +Absolute origin the site is served from, used to build og:url and canonical. + +.PARAMETER Require +Fail the build when a page has no description comment. Off by default so descriptions can be +adopted a page at a time; pages without one simply get no description tags. + +.EXAMPLE + ./Add-PageMetadata.ps1 -Book ./wiki/book + ./Add-PageMetadata.ps1 -Book ./wiki/book -Require +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)][string]$Book, + [string]$BaseUrl = 'https://dotnet.github.io/aspnet-api-versioning', + [switch]$Require +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path -LiteralPath $Book)) { throw "book directory not found: $Book" } +$Book = (Resolve-Path $Book).Path +$BaseUrl = $BaseUrl.TrimEnd('/') + +$pages = Get-ChildItem -LiteralPath $Book -Recurse -Filter *.html -File +if (-not $pages) { throw "no HTML found under $Book - did mdbook build run?" } + +# Recommended upper bound before search engines truncate the snippet. +$maxLength = 160 + +$missing = New-Object System.Collections.Generic.List[string] +$long = New-Object System.Collections.Generic.List[object] +$written = 0 + +foreach ($p in $pages) { + $rel = $p.FullName.Substring($Book.Length).TrimStart('\', '/').Replace('\', '/') + + # 404.html is served for arbitrary URLs, so no single canonical applies. print.html + # concatenates every chapter, which would pick up the first page's description. + # toc.html is the sidebar fragment mdBook generates, not a navigable page. + if ($rel -eq '404.html' -or $rel -eq 'print.html' -or $rel -eq 'toc.html') { continue } + + $html = Get-Content -Raw -LiteralPath $p.FullName + + # Prefer the directory form so a page has one canonical spelling, not two. + if ($rel -eq 'index.html') { + $url = "$BaseUrl/" + } elseif ($rel.EndsWith('/index.html')) { + $url = "$BaseUrl/" + $rel.Substring(0, $rel.Length - 'index.html'.Length) + } else { + $url = "$BaseUrl/$rel" + } + + $description = $null + $m = [regex]::Match($html, '') + if ($m.Success) { + # Collapse any wrapping the author used to keep the source line readable. + $description = [regex]::Replace($m.Groups['text'].Value, '\s+', ' ').Trim() + } + + if ([string]::IsNullOrWhiteSpace($description)) { + $missing.Add($rel) + $description = $null + } elseif ($description.Length -gt $maxLength) { + $long.Add([pscustomobject]@{ Page = $rel; Length = $description.Length }) + } + + # --- drop the tags this script owns, so a re-run replaces rather than duplicates --- + $html = [regex]::Replace($html, '[ \t]*]*>\r?\n?', '') + $html = [regex]::Replace($html, '[ \t]*]*>\r?\n?', '') + $html = [regex]::Replace($html, '[ \t]*]*>\r?\n?', '') + $html = [regex]::Replace($html, '[ \t]*]*>\r?\n?', '') + $html = [regex]::Replace($html, '[ \t]*]*>\r?\n?', '') + + $tags = New-Object System.Collections.Generic.List[string] + if ($description) { + $escaped = [System.Net.WebUtility]::HtmlEncode($description) + $tags.Add("") + $tags.Add("") + $tags.Add("") + } + $tags.Add("") + $tags.Add("") + + $block = ($tags | ForEach-Object { " $_" }) -join "`n" + + if ($html -notmatch '') { throw "no in $rel" } + $html = [regex]::Replace($html, '', "$block`n ", 1) + + # -NoNewline: the content already carries its own trailing newline. + Set-Content -LiteralPath $p.FullName -Value $html -Encoding utf8NoBOM -NoNewline + $written++ +} + +Write-Output "wrote metadata to $written page(s); base url $BaseUrl" + +if ($long.Count -gt 0) { + Write-Output '' + Write-Output "LONG DESCRIPTIONS (over $maxLength chars, will be truncated in results): $($long.Count)" + foreach ($l in ($long | Sort-Object -Property Length -Descending)) { + Write-Output (" {0} ({1} chars)" -f $l.Page, $l.Length) + } +} + +if ($missing.Count -gt 0) { + Write-Output '' + Write-Output "PAGES WITHOUT A DESCRIPTION: $($missing.Count)" + Write-Output ' (add to the page markdown)' + foreach ($x in ($missing | Sort-Object)) { Write-Output " $x" } + if ($Require) { exit 1 } +}