/// <summary> /// Print a list of the methods (request/responses) discovered in the documentation to the console. /// </summary> /// <param name="options"></param> /// <param name="docset"></param> /// <returns></returns> private static async Task PrintMethodsAsync(DocSetOptions options, DocSet docset) { docset = docset ?? await GetDocSetAsync(options); if (null == docset) { return; } FancyConsole.WriteLine(); FancyConsole.WriteLine(FancyConsole.ConsoleHeaderColor, "Defined methods:"); FancyConsole.WriteLine(); foreach (var method in docset.Methods) { FancyConsole.WriteLine(FancyConsole.ConsoleHeaderColor, "Method '{0}' in file '{1}'", method.Identifier, method.SourceFile.DisplayName); var requestMetadata = options.EnableVerboseOutput ? JsonConvert.SerializeObject(method.RequestMetadata) : string.Empty; FancyConsole.WriteLineIndented(" ", FancyConsole.ConsoleSubheaderColor, "Request: {0}", requestMetadata); FancyConsole.WriteLineIndented(" ", FancyConsole.ConsoleCodeColor, method.Request); if (options.EnableVerboseOutput) { FancyConsole.WriteLine(); var responseMetadata = JsonConvert.SerializeObject(method.ExpectedResponseMetadata); FancyConsole.WriteLineIndented(" ", FancyConsole.ConsoleSubheaderColor, "Expected Response: {0}", responseMetadata); FancyConsole.WriteLineIndented(" ", FancyConsole.ConsoleCodeColor, method.ExpectedResponse); FancyConsole.WriteLine(); } FancyConsole.WriteLine(); } }
/// <summary> /// Perform internal consistency checks on the documentation, including verify that /// code blocks have proper formatting, that resources are used properly, and that expected /// responses and examples conform to the resource definitions. /// </summary> /// <param name="options"></param> /// <param name="docs"></param> /// <returns></returns> private static async Task <bool> CheckDocsAsync(BasicCheckOptions options, DocSet docs = null) { var docset = docs ?? await GetDocSetAsync(options); if (null == docset) { return(false); } FancyConsole.WriteLine(); var resultMethods = await CheckMethodsAsync(options, docset); CheckResults resultExamples = new CheckResults(); if (string.IsNullOrEmpty(options.MethodName)) { resultExamples = await CheckExamplesAsync(options, docset); } var combinedResults = resultMethods + resultExamples; if (options.IgnoreWarnings) { combinedResults.ConvertWarningsToSuccess(); } combinedResults.PrintToConsole(); return(combinedResults.FailureCount == 0); }
/// <summary> /// Validate that the CSDL metadata defined for a service matches the documentation. /// </summary> /// <param name="options"></param> /// <returns></returns> private static async Task <bool> CheckServiceMetadataAsync(CheckMetadataOptions options) { List <Schema> schemas = await TryGetMetadataSchemasAsync(options); if (null == schemas) { return(false); } FancyConsole.WriteLine(FancyConsole.ConsoleSuccessColor, " found {0} schema definitions: {1}", schemas.Count, (from s in schemas select s.Namespace).ComponentsJoinedByString(", ")); var docSet = await GetDocSetAsync(options); if (null == docSet) { return(false); } const string testname = "validate-service-metadata"; TestReport.StartTest(testname); List <ResourceDefinition> foundResources = ODataParser.GenerateResourcesFromSchemas(schemas); CheckResults results = new CheckResults(); List <ValidationError> collectedErrors = new List <ValidationError>(); foreach (var resource in foundResources) { FancyConsole.WriteLine(); FancyConsole.Write(FancyConsole.ConsoleHeaderColor, "Checking resource: {0}...", resource.Metadata.ResourceType); FancyConsole.VerboseWriteLine(); FancyConsole.VerboseWriteLine(resource.JsonExample); FancyConsole.VerboseWriteLine(); // Verify that this resource matches the documentation ValidationError[] errors; docSet.ResourceCollection.ValidateJsonExample(resource.Metadata, resource.JsonExample, out errors, new ValidationOptions { RelaxedStringValidation = true }); results.IncrementResultCount(errors); collectedErrors.AddRange(errors); await WriteOutErrorsAndFinishTestAsync(errors, options.SilenceWarnings, successMessage : " no errors."); } if (options.IgnoreWarnings) { results.ConvertWarningsToSuccess(); } var output = (from e in collectedErrors select e.ErrorText).ComponentsJoinedByString("\r\n"); await TestReport.FinishTestAsync(testname, results.WereFailures?TestOutcome.Failed : TestOutcome.Passed, stdOut : output); results.PrintToConsole(); return(!results.WereFailures); }
/// <summary> /// Print a list of the resources detected in the documentation set to the console. /// </summary> /// <param name="options"></param> /// <param name="docset"></param> /// <returns></returns> private static async Task PrintResourcesAsync(DocSetOptions options, DocSet docset) { docset = docset ?? await GetDocSetAsync(options); if (null == docset) { return; } FancyConsole.WriteLine(); FancyConsole.WriteLine(FancyConsole.ConsoleHeaderColor, "Defined resources:"); FancyConsole.WriteLine(); var sortedResources = docset.Resources.OrderBy(x => x.ResourceType); foreach (var resource in sortedResources) { if (options.EnableVerboseOutput) { string metadata = JsonConvert.SerializeObject(resource.Metadata); FancyConsole.Write(" "); FancyConsole.Write(FancyConsole.ConsoleHeaderColor, resource.ResourceType); FancyConsole.WriteLine(" flags: {1}", resource.ResourceType, metadata); } else { FancyConsole.WriteLineIndented(" ", FancyConsole.ConsoleHeaderColor, resource.ResourceType); } FancyConsole.WriteLineIndented(" ", FancyConsole.ConsoleCodeColor, resource.JsonExample); FancyConsole.WriteLine(); } }
public static void RecordError(string format, params object[] variables) { var message = string.Format(format, variables); FancyConsole.WriteLine(FancyConsole.ConsoleErrorColor, message); Task.Run(() => BuildWorker.AddMessageAsync(message, MessageCategory.Error)); }
private static async Task <List <Schema> > TryGetMetadataSchemasAsync(CheckMetadataOptions options) { if (string.IsNullOrEmpty(options.ServiceMetadataLocation)) { RecordError("No service metadata file location specified."); return(null); } FancyConsole.WriteLine(FancyConsole.ConsoleHeaderColor, "Loading service metadata from '{0}'...", options.ServiceMetadataLocation); List <Schema> schemas; try { Uri metadataUrl; if (Uri.TryCreate(options.ServiceMetadataLocation, UriKind.Absolute, out metadataUrl)) { schemas = await ODataParser.ReadSchemaFromMetadataUrlAsync(metadataUrl); } else { schemas = await ODataParser.ReadSchemaFromFileAsync(options.ServiceMetadataLocation); } } catch (Exception ex) { RecordError("Error parsing service metadata: {0}", ex.Message); return(null); } return(schemas); }
/// <summary> /// Parse the command line parameters into a set of methods that match the command line parameters. /// </summary> /// <param name="options"></param> /// <param name="docset"></param> /// <returns></returns> private static MethodDefinition[] FindTestMethods(BasicCheckOptions options, DocSet docset) { MethodDefinition[] methods = null; if (!string.IsNullOrEmpty(options.MethodName)) { var foundMethod = LookUpMethod(docset, options.MethodName); if (null == foundMethod) { FancyConsole.WriteLine(FancyConsole.ConsoleErrorColor, "Unable to locate method '{0}' in docset.", options.MethodName); Exit(failure: true); } methods = new MethodDefinition[] { LookUpMethod(docset, options.MethodName) }; } else if (!string.IsNullOrEmpty(options.FileName)) { var selectedFileQuery = from f in docset.Files where f.DisplayName == options.FileName select f; var selectedFile = selectedFileQuery.SingleOrDefault(); if (selectedFile == null) { FancyConsole.WriteLine(FancyConsole.ConsoleErrorColor, "Unable to locate file '{0}' in docset.", options.FileName); Exit(failure: true); } methods = selectedFile.Requests; } else { methods = docset.Methods; } return(methods); }
/// <summary> /// Execute the provided methods on the given account. /// </summary> /// <param name="options"></param> /// <param name="account"></param> /// <param name="methods"></param> /// <param name="docset"></param> /// <returns>True if the methods all passed, false if there were failures.</returns> private static async Task <bool> CheckMethodsForAccountAsync(CheckServiceOptions options, IServiceAccount account, MethodDefinition[] methods, DocSet docset) { //CheckResults results = new CheckResults(); ConfigureAdditionalHeadersForAccount(options, account); string testNamePrefix = account.Name.ToLower() + ": "; FancyConsole.WriteLine(FancyConsole.ConsoleHeaderColor, "Testing with account: {0}", account.Name); FancyConsole.WriteLine(FancyConsole.ConsoleCodeColor, "Preparing authentication for requests...", account.Name); try { await account.PrepareForRequestAsync(); } catch (Exception ex) { RecordError(ex.Message); return(false); } AuthenicationCredentials credentials = account.CreateCredentials(); int concurrentTasks = options.ParallelTests ? ParallelTaskCount : 1; CheckResults docSetResults = new CheckResults(); await ForEachAsync(methods, concurrentTasks, async method => { FancyConsole.WriteLine( FancyConsole.ConsoleCodeColor, "Running validation for method: {0}", method.Identifier); ScenarioDefinition[] scenarios = docset.TestScenarios.ScenariosForMethod(method); ValidationResults results = await method.ValidateServiceResponseAsync(scenarios, account, credentials); PrintResultsToConsole(method, account, results, options); await TestReport.LogMethodTestResults(method, account, results); docSetResults.RecordResults(results, options); if (concurrentTasks == 1) { AddPause(options); } }); if (options.IgnoreWarnings || options.SilenceWarnings) { // Remove the warning flag from the outcomes docSetResults.ConvertWarningsToSuccess(); } docSetResults.PrintToConsole(); bool hadWarnings = docSetResults.WarningCount > 0; bool hadErrors = docSetResults.FailureCount > 0; return(!(hadErrors | hadWarnings)); }
private static void PrintAboutMessage() { FancyConsole.WriteLine(); FancyConsole.WriteLine(ConsoleColor.Cyan, "apidocs.exe - API Documentation Test Tool"); FancyConsole.WriteLine(ConsoleColor.Cyan, "Copyright (c) 2015 Microsoft Corporation"); FancyConsole.WriteLine(); FancyConsole.WriteLine(ConsoleColor.Cyan, "For more information see http://github.com/onedrive/markdown-scanner/"); FancyConsole.WriteLine(); }
private static void AddPause(CheckServiceOptions options) { if (options.PauseBetweenRequests) { FancyConsole.WriteLine("Press any key to continue"); Console.ReadKey(); FancyConsole.WriteLine(); } }
/// <summary> /// Executes the remote service tests defined in the documentation. This is similar to CheckDocs, expect /// that the actual requests come from the service instead of the documentation. Prints the errors to /// the console. /// </summary> /// <param name="options"></param> /// <returns></returns> private static async Task <bool> CheckServiceAsync(CheckServiceOptions options) { // See if we're supposed to run check-service on this branch (assuming we know what branch we're running on) if (!string.IsNullOrEmpty(options.BranchName)) { string[] validBranches = null; if (null != CurrentConfiguration) { validBranches = CurrentConfiguration.CheckServiceEnabledBranches; } if (null != validBranches && !validBranches.Contains(options.BranchName)) { RecordWarning("Aborting check-service run. Branch \"{0}\" wasn't in the checkServiceEnabledBranches configuration list.", options.BranchName); return(true); } } var docset = await GetDocSetAsync(options); if (null == docset) { return(false); } FancyConsole.WriteLine(); if (!string.IsNullOrEmpty(options.ODataMetadataLevel)) { ValidationConfig.ODataMetadataLevel = options.ODataMetadataLevel; } if (options.FoundAccounts == null || !options.FoundAccounts.Any()) { RecordError("No account was found. Cannot connect to the service."); return(false); } var accountsToProcess = options.FoundAccounts.Where( x => string.IsNullOrEmpty(options.AccountName) ? x.Enabled : options.AccountName.Equals(x.Name)); var methods = FindTestMethods(options, docset); bool allSuccessful = true; foreach (var account in accountsToProcess) { allSuccessful &= await CheckMethodsForAccountAsync(options, account, methods, docset); } return(allSuccessful); }
/// <summary> /// Write the results of a test to the output console. /// </summary> /// <param name="method"></param> /// <param name="account"></param> /// <param name="results"></param> /// <param name="options"></param> private static void PrintResultsToConsole(MethodDefinition method, IServiceAccount account, ValidationResults output, CheckServiceOptions options) { // Only allow one thread at a time to write to the console so we don't interleave our results. lock (typeof(Program)) { FancyConsole.WriteLine( FancyConsole.ConsoleHeaderColor, "Testing method {0} with account {1}", method.Identifier, account.Name); foreach (var scenario in output.Results) { if (scenario.Errors.Count > 0) { FancyConsole.WriteLineIndented( " ", FancyConsole.ConsoleSubheaderColor, "Scenario: {0}", scenario.Name); foreach (var message in scenario.Errors) { if (options.EnableVerboseOutput || message.IsWarningOrError) { FancyConsole.WriteLineIndented( " ", FancyConsole.ConsoleDefaultColor, message.ErrorText); } } if (options.SilenceWarnings && scenario.Outcome == ValidationOutcome.Warning) { scenario.Outcome = ValidationOutcome.Passed; } FancyConsole.WriteLineIndented( " ", scenario.Outcome.ConsoleColor(), "Scenario finished with outcome: {0}. Duration: {1}", scenario.Outcome, scenario.Duration); } } FancyConsole.WriteLineIndented( " ", output.OverallOutcome.ConsoleColor(), "Method testing finished with overall outcome: {0}", output.OverallOutcome); FancyConsole.WriteLine(); } }
/// <summary> /// Checks to see if this options block has all the required properties (or that we had values in the settings for them) /// </summary> /// <returns></returns> public override bool HasRequiredProperties(out string[] missingArguments) { if (string.IsNullOrEmpty(this.DocumentationSetPath)) { this.DocumentationSetPath = Environment.CurrentDirectory; } FancyConsole.WriteLine("Documentation path: " + this.DocumentationSetPath); missingArguments = new string[0]; return(true); }
static void Main(string[] args) { Logging.ProviderLogger(new ConsoleAppLogger()); FancyConsole.WriteLine(ConsoleColor.Green, "APIDocs tool, version {0}", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); FancyConsole.WriteLine(); if (args.Length > 0) { FancyConsole.WriteLine("Command line: " + args.ComponentsJoinedByString(" ")); } string verbName = null; BaseOptions verbOptions = null; var options = new CommandLineOptions(); if (!Parser.Default.ParseArguments(args, options, (verb, subOptions) => { // if parsing succeeds the verb name and correct instance // will be passed to onVerbCommand delegate (string,object) verbName = verb; verbOptions = (BaseOptions)subOptions; })) { Exit(failure: true); } #if DEBUG if (verbOptions.AttachDebugger) { Debugger.Launch(); } #endif if (!string.IsNullOrEmpty(verbOptions.AppVeyorServiceUrl)) { BuildWorker.UrlEndPoint = new Uri(verbOptions.AppVeyorServiceUrl); } var commandOptions = verbOptions as DocSetOptions; if (null != commandOptions) { FancyConsole.WriteVerboseOutput = commandOptions.EnableVerboseOutput; } FancyConsole.LogFileName = verbOptions.LogFile; var task = Task.Run(() => RunInvokedMethodAsync(options, verbName, verbOptions)); task.Wait(); }
public static void StartTest(string testName, string filename = null) { FancyConsole.WriteLine(); FancyConsole.Write(FancyConsole.ConsoleHeaderColor, "Starting test: "); FancyConsole.Write(FancyConsole.ConsoleDefaultColor, testName); if (null != filename) { FancyConsole.Write(" [{0}]", filename); TestStartFilename[testName] = filename; } FancyConsole.WriteLine(); TestStartTimes[testName] = DateTimeOffset.Now.Ticks; }
public static async Task FinishTestAsync(string testName, TestOutcome outcome, string message = null, string filename = null, string stdOut = null, bool printFailuresOnly = false) { var endTime = DateTimeOffset.Now.Ticks; TimeSpan duration; long startTime; if (TestStartTimes.TryGetValue(testName, out startTime)) { duration = new TimeSpan(endTime - startTime); TestStartTimes.Remove(testName); } else { duration = TimeSpan.Zero; } if (null == filename) { TestStartFilename.TryGetValue(testName, out filename); TestStartFilename.Remove(testName); } if (!printFailuresOnly || outcome != TestOutcome.Passed) { FancyConsole.Write("Test {0} complete.", testName); switch (outcome) { case TestOutcome.Failed: FancyConsole.Write(ConsoleColor.Red, " Failed: {0}", message); break; case TestOutcome.Passed: FancyConsole.Write(ConsoleColor.Green, " Passed: {0}", message); break; default: FancyConsole.Write(" {0}: {1}", outcome, message); break; } FancyConsole.WriteLine(" duration: {0}", duration); } await BuildWorkerApi.RecordTestAsync(testName, TestFrameworkName, outcome : outcome, durationInMilliseconds : (long)duration.TotalMilliseconds, errorMessage : message, filename : filename, stdOut : stdOut); }
public void PrintToConsole(bool addNewLine = true) { if (addNewLine) { FancyConsole.WriteLine(); FancyConsole.Write("Runs completed. "); } const string percentCompleteFormat = "{0:0.00}% passed"; FancyConsole.Write( this.PercentSuccessful == 100.0 ? FancyConsole.ConsoleSuccessColor : FancyConsole.ConsoleWarningColor, percentCompleteFormat, this.PercentSuccessful); List <string> resultsOutput = new List <string>(); if (this.FailureCount > 0 || this.WarningCount > 0) { FancyConsole.Write(" ("); if (this.FailureCount > 0) { FancyConsole.Write(FancyConsole.ConsoleErrorColor, "{0} errors", this.FailureCount); } if (this.WarningCount > 0 && this.FailureCount > 0) { FancyConsole.Write(", "); } if (this.WarningCount > 0) { FancyConsole.Write(FancyConsole.ConsoleWarningColor, "{0} warnings", this.WarningCount); } if ((this.WarningCount > 0 || this.FailureCount > 0) && this.SuccessCount > 0) { FancyConsole.Write(", "); } if (this.SuccessCount > 0) { FancyConsole.Write(FancyConsole.ConsoleSuccessColor, "{0} successful", this.SuccessCount); } FancyConsole.Write(")"); } FancyConsole.WriteLine(); }
/// <summary> /// Prints a list of the documentation files in a docset to the console. /// </summary> /// <param name="options"></param> /// <param name="docset"></param> /// <returns></returns> private static async Task PrintFilesAsync(DocSetOptions options, DocSet docset) { docset = docset ?? await GetDocSetAsync(options); if (null == docset) { return; } if (null == docset) { return; } FancyConsole.WriteLine(); FancyConsole.WriteLine(FancyConsole.ConsoleHeaderColor, "Documentation files"); string format = null; if (options.EnableVerboseOutput) { format = "{1} (resources: {2}, methods: {3})"; } else { format = "{0} (r:{2}, m:{3})"; } foreach (var file in docset.Files) { ConsoleColor color = FancyConsole.ConsoleSuccessColor; if (file.Resources.Length == 0 && file.Requests.Length == 0) { color = FancyConsole.ConsoleWarningColor; } FancyConsole.WriteLineIndented(" ", color, format, file.DisplayName, file.FullPath, file.Resources.Length, file.Requests.Length); } }
public void PrintToConsole() { FancyConsole.WriteLine(); FancyConsole.Write("Runs completed. "); const string percentCompleteFormat = "{0:0.00}% passed"; FancyConsole.Write( this.PercentSuccessful == 100.0 ? FancyConsole.ConsoleSuccessColor : FancyConsole.ConsoleWarningColor, percentCompleteFormat, this.PercentSuccessful); if (this.FailureCount > 0 || this.WarningCount > 0) { FancyConsole.Write(" ("); if (this.FailureCount > 0) { FancyConsole.Write(FancyConsole.ConsoleErrorColor, "{0} errors", this.FailureCount); } if (this.WarningCount > 0 && this.FailureCount > 0) { FancyConsole.Write(", "); } if (this.WarningCount > 0) { FancyConsole.Write(FancyConsole.ConsoleWarningColor, "{0} warnings", this.WarningCount); } if (this.WarningCount > 0 || this.FailureCount > 0 && this.SuccessCount > 0) { FancyConsole.Write(", "); } if (this.SuccessCount > 0) { FancyConsole.Write(FancyConsole.ConsoleSuccessColor, "{0} successful", this.SuccessCount); } FancyConsole.Write(")"); } FancyConsole.WriteLine(); }
/// <summary> /// Perform an internal consistency check on the examples defined in the documentation. Prints /// the results of the tests to the console. /// </summary> /// <param name="options"></param> /// <param name="docset"></param> /// <returns></returns> private static async Task <CheckResults> CheckExamplesAsync(BasicCheckOptions options, DocSet docset) { var results = new CheckResults(); foreach (var doc in docset.Files) { if (doc.Examples.Length == 0) { continue; } FancyConsole.WriteLine(FancyConsole.ConsoleHeaderColor, "Checking examples in \"{0}\"...", doc.DisplayName); foreach (var example in doc.Examples) { if (example.Metadata == null) { continue; } if (example.Language != CodeLanguage.Json) { continue; } var testName = string.Format("check-example: {0}", example.Metadata.MethodName, example.Metadata.ResourceType); TestReport.StartTest(testName, doc.DisplayName); ValidationError[] errors; docset.ResourceCollection.ValidateJsonExample(example.Metadata, example.SourceExample, out errors); await WriteOutErrorsAndFinishTestAsync(errors, options.SilenceWarnings, " ", "No errors.", false, testName, "Warnings detected", "Errors detected"); results.IncrementResultCount(errors); } } return(results); }
/// <summary> /// Prints ValidationError messages to the console, optionally excluding warnings and messages. /// </summary> /// <param name="validationErrors"></param> /// <param name="errorsOnly"></param> /// <param name="indent"></param> /// <param name="endLineBeforeWriting"></param> private static void WriteMessages(ValidationError[] validationErrors, bool errorsOnly = false, string indent = "", bool endLineBeforeWriting = false) { foreach (var error in validationErrors) { // Skip messages if verbose output is off if (!error.IsWarning && !error.IsError && !FancyConsole.WriteVerboseOutput) { continue; } // Skip warnings if silence warnings is enabled. if (errorsOnly && !error.IsError) { continue; } if (endLineBeforeWriting) { FancyConsole.WriteLine(); } WriteValidationError(indent, error); } }
private static async Task RunInvokedMethodAsync(CommandLineOptions origCommandLineOpts, string invokedVerb, BaseOptions options) { string[] missingProps; if (!options.HasRequiredProperties(out missingProps)) { var error = new ValidationError(ValidationErrorCode.MissingRequiredArguments, null, "Command line is missing required arguments: {0}", missingProps.ComponentsJoinedByString(", ")); FancyConsole.WriteLine(origCommandLineOpts.GetUsage(invokedVerb)); await WriteOutErrorsAndFinishTestAsync(new ValidationError[] { error }, options.SilenceWarnings); Exit(failure: true); } LoadCurrentConfiguration(options as DocSetOptions); bool returnSuccess = true; switch (invokedVerb) { case CommandLineOptions.VerbPrint: await PrintDocInformationAsync((PrintOptions)options); break; case CommandLineOptions.VerbCheckLinks: returnSuccess = await CheckLinksAsync((DocSetOptions)options); break; case CommandLineOptions.VerbDocs: returnSuccess = await CheckDocsAsync((BasicCheckOptions)options); break; case CommandLineOptions.VerbCheckAll: returnSuccess = await CheckDocsAllAsync((BasicCheckOptions)options); break; case CommandLineOptions.VerbService: returnSuccess = await CheckServiceAsync((CheckServiceOptions)options); break; case CommandLineOptions.VerbPublish: returnSuccess = await PublishDocumentationAsync((PublishOptions)options); break; case CommandLineOptions.VerbMetadata: await CheckServiceMetadataAsync((CheckMetadataOptions)options); break; case CommandLineOptions.VerbAbout: PrintAboutMessage(); Exit(failure: false); break; } Exit(failure: !returnSuccess); }
private static async Task <bool> PublishDocumentationAsync(PublishOptions options) { var outputPath = options.OutputDirectory; FancyConsole.WriteLine("Publishing documentation to {0}", outputPath); DocSet docs = await GetDocSetAsync(options); if (null == docs) { return(false); } DocumentPublisher publisher = null; switch (options.Format) { case PublishOptions.PublishFormat.Markdown: publisher = new MarkdownPublisher(docs); break; case PublishOptions.PublishFormat.Html: publisher = new DocumentPublisherHtml(docs, options); break; case PublishOptions.PublishFormat.Mustache: publisher = new HtmlMustacheWriter(docs, options); break; case PublishOptions.PublishFormat.Swagger2: publisher = new SwaggerWriter(docs, "https://service.org") // TODO: Plumb in the base URL. { Title = options.Title, Description = options.Description, Version = options.Version }; break; case PublishOptions.PublishFormat.Outline: publisher = new OutlinePublisher(docs); break; default: FancyConsole.WriteLine( FancyConsole.ConsoleErrorColor, "Unsupported publishing format: {0}", options.Format); return(false); } FancyConsole.WriteLineIndented(" ", "Format: {0}", publisher.GetType().Name); publisher.VerboseLogging = options.EnableVerboseOutput; FancyConsole.WriteLine(); FancyConsole.WriteLine("Publishing content..."); publisher.NewMessage += publisher_NewMessage; try { await publisher.PublishToFolderAsync(outputPath); FancyConsole.WriteLine(FancyConsole.ConsoleSuccessColor, "Finished publishing documentation to: {0}", outputPath); } catch (Exception ex) { FancyConsole.WriteLine( FancyConsole.ConsoleErrorColor, "An error occured while publishing: {0}", ex.Message); FancyConsole.VerboseWriteLine(ex.ToString()); return(false); } return(true); }