Ejemplo n.º 1
0
        public async Task <IActionResult> ShowMarkdownFile(string path)
        {
            if (_startupOptions.Mode != StartupMode.Try)
            {
                return(NotFound());
            }

            if (string.IsNullOrEmpty(path))
            {
                const string documentSvg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Z\" /></svg>";
                var          links       = string.Join(
                    "\n",
                    _markdownProject.GetAllMarkdownFiles()
                    .Select(f =>
                            $@"<li><a href=""{f.Path.Value.HtmlAttributeEncode()}"">{documentSvg}<span>{f.Path.Value}</span></a></li>"));

                return(Content(Index(links).ToString(), "text/html"));
            }

            var relativeFilePath = new RelativeFilePath(path);

            if (!_markdownProject.TryGetMarkdownFile(relativeFilePath, out var markdownFile))
            {
                return(NotFound());
            }

            var hostUrl = Request.GetUri();

            var blocks = (await markdownFile.GetEditableAnnotatedCodeBlocks()).ToArray();

            var maxEditorPerSession = blocks.Length > 0
                                          ? blocks
                                      .GroupBy(b => b.Annotations.Session)
                                      .Max(editors => editors.Count())
                                          : 0;

            var pipeline = _markdownProject.GetMarkdownPipelineFor(markdownFile.Path);

            var extension = pipeline.Extensions.FindExact <CodeBlockAnnotationExtension>();

            if (extension != null)
            {
                extension.InlineControls        = maxEditorPerSession <= 1;
                extension.EnablePreviewFeatures = _startupOptions.EnablePreviewFeatures;
            }



            var content = maxEditorPerSession <= 1
                              ? await OneColumnLayoutScaffold(
                $"{hostUrl.Scheme}://{hostUrl.Authority}",
                markdownFile)
                              : await TwoColumnLayoutScaffold(
                $"{hostUrl.Scheme}://{hostUrl.Authority}",
                markdownFile);

            return(Content(content.ToString(), "text/html"));
        }
Ejemplo n.º 2
0
        public async Task <IActionResult> ShowIndex()
        {
            const string documentSvg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Z\" /></svg>";
            var          links       = string.Join(
                "\n",
                _markdownProject.GetAllMarkdownFiles()
                .Select(f =>
                        $@"<li><a href=""{f.Path.Value.HtmlAttributeEncode()}"">{documentSvg}<span>{f.Path.Value}</span></a></li>"));

            return(Content(Index(links).ToString(), "text/html"));
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
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"));
            }
Ejemplo n.º 5
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"));
            }
Ejemplo n.º 6
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}");
                }
            }
        }