Пример #1
0
        /// <summary>
        /// Builds the content for the markdown project page
        /// </summary>
        /// <param name="project">The markdown project item to be rendered</param>
        /// <returns>The markdown content</returns>
        public string BuildPage(MarkdownProject project)
        {
            DefaultTheme.ThemeLogger?.LogDebug("Building Main Api Page");
            var homeBuilder = new MarkdownBuilder();

            homeBuilder.HeaderWithLink(1, _options.RootTitle, project.To(project));
            homeBuilder.AppendLine();

            if (!string.IsNullOrEmpty(_options.RootSummary))
            {
                homeBuilder
                .Header(2, "Summary")
                .AppendLine(_options.RootSummary)
                .AppendLine();
            }

            homeBuilder.Header(2, "Namespaces").AppendLine();

            foreach (var tempItem in project.AllItems.Values.Where(i => i.ItemType == MarkdownItemTypes.Namespace))
            {
                var g = tempItem.As <MarkdownNamespace>();

                if (!String.IsNullOrEmpty(g.FileName))
                {
                    homeBuilder.HeaderWithLink(3, g.FullName, project.To(g));
                }
                else
                {
                    homeBuilder.Header(3, g.Name);
                }

                homeBuilder.AppendLine();

                if (!_options.ShowTypesOnRootPage)
                {
                    continue;
                }

                foreach (var item in g.Types.OrderBy(x => x.Name))
                {
                    if (!String.IsNullOrEmpty(item.FileName))
                    {
                        homeBuilder.List(Cleaner.CreateFullTypeWithLinks(project, item.InternalType, false, true));
                    }
                    else
                    {
                        homeBuilder.List(item.Name);
                    }

                    if (!string.IsNullOrEmpty(item.Summary))
                    {
                        homeBuilder.Tab().List(item.Summary);
                    }
                }
            }

            homeBuilder.AppendLine();

            return(homeBuilder.ToString());
        }
Пример #2
0
            public async Task Should_parse_markdown_file_and_set_package_with_fully_resolved_path()
            {
                var workingDir = TestAssets.SampleConsole;
                var packagePathRelativeToBaseDir = "src/sample/sample.csproj";

                var dirAccessor = new InMemoryDirectoryAccessor(workingDir)
                {
                    ("src/sample/Program.cs", ""),
                    (packagePathRelativeToBaseDir, ""),
                    ("docs/Readme.md",
                     $@"```cs --project ../{packagePathRelativeToBaseDir} --source-file ../src/sample/Program.cs
```")
                };

                var project = new MarkdownProject(dirAccessor, Default.PackageFinder);

                project.TryGetMarkdownFile(new RelativeFilePath("docs/Readme.md"), out var markdownFile).Should().BeTrue();
                var htmlDocument = new HtmlDocument();

                htmlDocument.LoadHtml((await markdownFile.ToHtmlContentAsync()).ToString());
                var output = htmlDocument.DocumentNode
                             .SelectSingleNode("//pre/code").Attributes["data-trydotnet-package"];

                var fullProjectPath = dirAccessor.GetFullyQualifiedPath(new RelativeFilePath(packagePathRelativeToBaseDir));

                output.Value.Should().Be(fullProjectPath.FullName);
            }
Пример #3
0
 public DocumentationController(MarkdownProject markdownProject, StartupOptions startupOptions, PackageRegistry packageRegistry)
 {
     _markdownProject = markdownProject ??
                        throw new ArgumentNullException(nameof(markdownProject));
     _startupOptions  = startupOptions;
     _packageRegistry = packageRegistry ??
                        throw new ArgumentNullException(nameof(packageRegistry));
 }
Пример #4
0
            public async Task Returns_false_for_nonexistent_file()
            {
                var workingDir  = TestAssets.SampleConsole;
                var dirAccessor = new InMemoryDirectoryAccessor(workingDir);
                var project     = new MarkdownProject(dirAccessor, await Default.PackageRegistry.ValueAsync());
                var path        = new RelativeFilePath("DOESNOTEXIST");

                project.TryGetMarkdownFile(path, out _).Should().BeFalse();
            }
Пример #5
0
            public void Returns_false_for_nonexistent_file()
            {
                var workingDir  = TestAssets.SampleConsole;
                var dirAccessor = new InMemoryDirectoryAccessor(workingDir);
                var project     = new MarkdownProject(dirAccessor, PackageRegistry.CreateForHostedMode());
                var path        = new RelativeFilePath("DOESNOTEXIST");

                project.TryGetMarkdownFile(path, out _).Should().BeFalse();
            }
Пример #6
0
        public static MarkdownProject Load(string searchArea, string namespaceMatch)
        {
            List <MarkdownType> types = new List <MarkdownType>();

            MarkdownProject project = new MarkdownProject();

            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

            var matcher = new Matcher();

            foreach (var searchPath in searchArea.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                matcher.AddInclude(searchPath);
            }
            var rootDir = Directory.GetCurrentDirectory();
            var results = matcher.GetResultsInFullPath(rootDir);

            Constants.Logger?.LogInformation($"Found {results.Count()} dlls from {rootDir} using {searchArea}");
            List <string> processedDlls = new List <string>();

            foreach (var dllPath in results)
            {
                var dllName = Path.GetFileName(dllPath);
                Constants.Logger?.LogInformation("Loading Dll: {dllName}", dllPath);

                if (processedDlls.Contains(dllName))
                {
                    Constants.Logger?.LogWarning("Duplicate Dll: {dllName}", dllName);
                    continue;
                }

                try
                {
                    if (File.Exists(dllPath) && Path.GetExtension(dllPath) == ".dll")
                    {
                        LoadDll(dllPath, namespaceMatch);
                        processedDlls.Add(dllName);
                    }
                    else
                    {
                        Constants.Logger?.LogError($"Failed to find {dllPath} dll");
                    }
                }
                catch (Exception e)
                {
                    Constants.Logger?.LogError(e, "Failed to Load {dllName}", dllPath);
                }
            }

            return(project);
        }
        public void TestSetup()
        {
            _project = MarkdownApiGenerator.GenerateProject("./igloo15.MarkdownApi.Tests.dll", null);

            _project.Build(new DefaultTheme(new DefaultOptions
            {
                BuildNamespacePages = true,
                BuildTypePages      = true,
                RootFileName        = "README.md",
                RootTitle           = "API",
                RootSummary         = "The Root Page Summary",
                ShowParameterNames  = true
            }),
                           @".\testdocs"
                           );
        }
Пример #8
0
        public static async Task <int> Do(
            PublishOptions publishOptions,
            IConsole console,
            StartupOptions startupOptions = null,
            WriteOutput writeOutput       = null
            )
        {
            writeOutput ??= (path, content) => File.WriteAllText(path, content);

            var sourceDirectoryAccessor = publishOptions.RootDirectory;
            var packageRegistry         = PackageRegistry.CreateForTryMode(sourceDirectoryAccessor);
            var markdownProject         = new MarkdownProject(
                sourceDirectoryAccessor,
                packageRegistry,
                startupOptions);

            var markdownFiles = markdownProject.GetAllMarkdownFiles().ToArray();

            if (markdownFiles.Length == 0)
            {
                console.Error.WriteLine($"No markdown files found under {sourceDirectoryAccessor.GetFullyQualifiedRoot()}");
                return(-1);
            }

            var targetDirectoryAccessor      = publishOptions.TargetDirectory;
            var targetIsSubDirectoryOfSource = targetDirectoryAccessor.IsSubDirectoryOf(sourceDirectoryAccessor);

            foreach (var markdownFile in markdownFiles)
            {
                var markdownFilePath = markdownFile.Path;
                var fullSourcePath   = sourceDirectoryAccessor.GetFullyQualifiedPath(markdownFilePath);
                if (targetIsSubDirectoryOfSource && fullSourcePath.IsChildOf(targetDirectoryAccessor))
                {
                    continue;
                }

                var(document, newLine) = ParseMarkdownDocument(markdownFile);

                var rendered = await Render(publishOptions.Format, document, newLine);

                var targetPath = WriteTargetFile(rendered, markdownFilePath, targetDirectoryAccessor, publishOptions, writeOutput);

                console.Out.WriteLine($"Published '{fullSourcePath}' to {targetPath}");
            }

            return(0);
        }
Пример #9
0
            public async Task Returns_list_of_all_relative_paths_to_all_markdown_files()
            {
                var dirAccessor = new InMemoryDirectoryAccessor()
                {
                    ("Readme.md", ""),
                    ("Subdirectory/Tutorial.md", ""),
                    ("Program.cs", "")
                };

                var project = new MarkdownProject(dirAccessor, await Default.PackageRegistry.ValueAsync());

                var files = project.GetAllMarkdownFiles();

                files.Should().HaveCount(2);
                files.Should().Contain(f => f.Path.Value.Equals("./Readme.md"));
                files.Should().Contain(f => f.Path.Value.Equals("./Subdirectory/Tutorial.md"));
            }
Пример #10
0
            public void Returns_list_of_all_relative_paths_to_all_markdown_files()
            {
                var workingDir  = TestAssets.SampleConsole;
                var dirAccessor = new InMemoryDirectoryAccessor(workingDir)
                {
                    ("Readme.md", ""),
                    ("Subdirectory/Tutorial.md", ""),
                    ("Program.cs", "")
                };

                var project = new MarkdownProject(dirAccessor, Default.PackageFinder);

                var files = project.GetAllMarkdownFiles();

                files.Should().HaveCount(2);
                files.Should().Contain(f => f.Path.Value.Equals("./Readme.md"));
                files.Should().Contain(f => f.Path.Value.Equals("./Subdirectory/Tutorial.md"));
            }
Пример #11
0
        public MarkdownProcessingContext(
            IDirectoryAccessor rootDirectory,
            IDefaultCodeBlockAnnotations defaultAnnotations = null,
            WriteFile writeFile = null,
            IConsole console    = null)
        {
            RootDirectory = rootDirectory;
            Console       = console ?? new SystemConsole();

            var packageRegistry = PackageRegistry.CreateForTryMode(rootDirectory);

            Project = new MarkdownProject(
                rootDirectory,
                packageRegistry,
                defaultAnnotations ?? new DefaultCodeBlockAnnotations());

            _lazyWorkspaceServer = new Lazy <IWorkspaceServer>(() => new WorkspaceServerMultiplexer(packageRegistry));

            WriteFile = writeFile ?? File.WriteAllText;
        }
Пример #12
0
        public static async Task <int> Do(
            VerifyOptions verifyOptions,
            IConsole console,
            StartupOptions startupOptions = null)
        {
            var directoryAccessor = verifyOptions.RootDirectory;
            var packageRegistry   = PackageRegistry.CreateForTryMode(directoryAccessor);
            var markdownProject   = new MarkdownProject(
                directoryAccessor,
                packageRegistry,
                startupOptions);
            var errorCount      = 0;
            var workspaceServer = new Lazy <IWorkspaceServer>(() => new WorkspaceServerMultiplexer(packageRegistry));

            var markdownFiles = markdownProject.GetAllMarkdownFiles().ToArray();

            if (markdownFiles.Length == 0)
            {
                console.Error.WriteLine($"No markdown files found under {directoryAccessor.GetFullyQualifiedRoot()}");
                return(-1);
            }

            foreach (var markdownFile in markdownFiles)
            {
                var fullName = directoryAccessor.GetFullyQualifiedPath(markdownFile.Path).FullName;
                var markdownFileDirectoryAccessor = directoryAccessor.GetDirectoryAccessorForRelativePath(markdownFile.Path.Directory);

                console.Out.WriteLine();
                console.Out.WriteLine(fullName);
                console.Out.WriteLine(new string('-', fullName.Length));

                var codeLinkBlocks = await markdownFile.GetAnnotatedCodeBlocks();

                var sessions = codeLinkBlocks.GroupBy(block => block.Annotations?.Session);

                foreach (var session in sessions)
                {
                    if (session.Select(block => block.ProjectOrPackageName()).Distinct().Count() != 1)
                    {
                        SetError();
                        console.Out.WriteLine($"Session cannot span projects or packages: --session {session.Key}");
                        continue;
                    }

                    foreach (var codeLinkBlock in session)
                    {
                        ReportCodeLinkageResults(codeLinkBlock, markdownFileDirectoryAccessor);
                    }

                    Console.ResetColor();

                    if (!session.Any(block => block.Diagnostics.Any()))
                    {
                        var(buffersToInclude, filesToInclude) = await markdownFile.GetIncludes(markdownFileDirectoryAccessor);

                        await ReportCompileResults(
                            session,
                            markdownFile,
                            filesToInclude,
                            buffersToInclude,
                            markdownFileDirectoryAccessor);
                    }

                    Console.ResetColor();
                }
            }

            if (errorCount > 0)
            {
                SetError(false);
            }
            else
            {
                SetOk();
            }

            console.Out.WriteLine($"\n\ndotnet try verify found {errorCount} error(s)");

            Console.ResetColor();

            return(errorCount == 0
                       ? 0
                       : 1);

            void SetError(bool incrementCount = true)
            {
                Console.ForegroundColor = ConsoleColor.Red;

                if (incrementCount)
                {
                    errorCount++;
                }
            }

            void SetOk()
            {
                Console.ForegroundColor = ConsoleColor.Green;
            }

            async Task ReportCompileResults(
                IGrouping <string, AnnotatedCodeBlock> session,
                MarkdownFile markdownFile,
                Dictionary <string, File[]> filesToInclude,
                IReadOnlyDictionary <string, Buffer[]> buffersToInclude,
                IDirectoryAccessor accessor)
            {
                var description = session.Count() == 1 || string.IsNullOrWhiteSpace(session.Key)
                                      ? $"region \"{session.Select(s => s.Annotations.Region).Distinct().First()}\""
                                      : $"session \"{session.Key}\"";

                console.Out.WriteLine($"\n  Compiling samples for {description}\n");

                var projectOrPackageName = session
                                           .Select(b => b.ProjectOrPackageName())
                                           .FirstOrDefault(name => !string.IsNullOrWhiteSpace(name));

                var language = session
                               .Select(b => b.Language())
                               .FirstOrDefault(name => !string.IsNullOrWhiteSpace(name));

                if (!ProjectIsCompatibleWithLanguage(new UriOrFileInfo(projectOrPackageName), language))
                {
                    SetError();

                    console.Out.WriteLine($"    Build failed as project {projectOrPackageName} is not compatible with language {language}");
                }

                var editableCodeBlocks = session.Where(b => b.Annotations.Editable).ToList();

                var buffers = editableCodeBlocks
                              .Select(block => block.GetBufferAsync(accessor, markdownFile))
                              .ToList();

                var files = new List <File>();

                if (filesToInclude.TryGetValue("global", out var globalIncludes))
                {
                    files.AddRange(globalIncludes);
                }

                if (!string.IsNullOrWhiteSpace(session.Key) && filesToInclude.TryGetValue(session.Key, out var sessionIncludes))
                {
                    files.AddRange(sessionIncludes);
                }

                if (buffersToInclude.TryGetValue("global", out var globalSessionBuffersToInclude))
                {
                    buffers.AddRange(globalSessionBuffersToInclude);
                }

                if (!string.IsNullOrWhiteSpace(session.Key) && buffersToInclude.TryGetValue(session.Key, out var localSessionBuffersToInclude))
                {
                    buffers.AddRange(localSessionBuffersToInclude);
                }

                var workspace = new Workspace(
                    workspaceType: projectOrPackageName,
                    language: language,
                    files: files.ToArray(),
                    buffers: buffers.ToArray());

                var mergeTransformer    = new CodeMergeTransformer();
                var inliningTransformer = new BufferInliningTransformer();

                var processed = await mergeTransformer.TransformAsync(workspace);

                processed = await inliningTransformer.TransformAsync(processed);

                processed = new Workspace(usings: processed.Usings, workspaceType: processed.WorkspaceType, language: processed.Language, files: processed.Files);

                var result = await workspaceServer.Value.Compile(new WorkspaceRequest(processed));

                var projectDiagnostics = result.GetFeature <ProjectDiagnostics>()
                                         .Where(e => e.Severity == DiagnosticSeverity.Error)
                                         .ToArray();

                if (projectDiagnostics.Any())
                {
                    SetError();

                    console.Out.WriteLine($"    Build failed for project {projectOrPackageName}");

                    foreach (var diagnostic in projectDiagnostics)
                    {
                        console.Out.WriteLine($"\t\t{diagnostic.Location}: {diagnostic.Message}");
                    }
                }
                else
                {
                    var symbol = !result.Succeeded
                                     ? "X"
                                     : "✓";

                    if (result.Succeeded)
                    {
                        SetOk();
                        console.Out.WriteLine($"    {symbol}  No errors found within samples for {description}");
                    }
                    else
                    {
                        SetError();

                        console.Out.WriteLine($"    {symbol}  Errors found within samples for {description}");

                        foreach (var diagnostic in result.GetFeature <Diagnostics>())
                        {
                            console.Out.WriteLine($"\t\t{diagnostic.Message}");
                        }
                    }
                }
            }

            void ReportCodeLinkageResults(
                AnnotatedCodeBlock codeLinkBlock,
                IDirectoryAccessor accessor)
            {
                var diagnostics = codeLinkBlock.Diagnostics.ToArray();

                Console.ResetColor();

                console.Out.WriteLine("  Checking Markdown...");

                if (diagnostics.Any())
                {
                    SetError();
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                }

                var blockOptions = (LocalCodeBlockAnnotations)codeLinkBlock.Annotations;

                var file = blockOptions?.SourceFile ?? blockOptions?.DestinationFile;
                var fullyQualifiedPath =
                    file != null
                        ? accessor.GetFullyQualifiedPath(file).FullName
                        : "UNKNOWN";

                var project = codeLinkBlock.ProjectOrPackageName() ?? "UNKNOWN";

                var symbol = diagnostics.Any()
                                 ? "X"
                                 : "✓";

                console.Out.WriteLine($"    {symbol}  Line {codeLinkBlock.Line + 1}:\t{fullyQualifiedPath} (in project {project})");

                foreach (var diagnostic in diagnostics)
                {
                    console.Out.WriteLine($"\t\t{diagnostic}");
                }
            }
        }
Пример #13
0
 public DocumentationController(MarkdownProject markdownProject, StartupOptions startupOptions)
 {
     _markdownProject = markdownProject ??
                        throw new ArgumentNullException(nameof(markdownProject));
     _startupOptions = startupOptions;
 }
Пример #14
0
 /// <summary>
 /// Builds Project Pages with the given MarkdownProject Item
 /// </summary>
 /// <param name="item">The MarkdownProject item to build the page with</param>
 /// <returns>A string of the markdown content or "" if no page created</returns>
 public string BuildPage(MarkdownProject item)
 {
     return(_projectBuilder.BuildPage(item));
 }