diff --git a/.editorconfig b/.editorconfig index 0f8ee8c5..c4395e55 100644 --- a/.editorconfig +++ b/.editorconfig @@ -136,12 +136,12 @@ csharp_style_var_for_built_in_types = true:error csharp_style_var_when_type_is_apparent = true:error csharp_style_var_elsewhere = true:error -csharp_style_expression_bodied_methods = true:warning -csharp_style_expression_bodied_constructors = true:warning -csharp_style_expression_bodied_operators = true:warning -csharp_style_expression_bodied_properties = true:warning -csharp_style_expression_bodied_indexers = true:warning -csharp_style_expression_bodied_accessors = true:warning +csharp_style_expression_bodied_methods = true:suggestion +csharp_style_expression_bodied_constructors = true:suggestion +csharp_style_expression_bodied_operators = true:suggestion +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_indexers = true:suggestion +csharp_style_expression_bodied_accessors = true:suggestion # Suggest more modern language features when available csharp_style_pattern_matching_over_is_with_cast_check = true:error diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index c31d8434..00000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,62 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# For the full list of built-in configuration values, see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information - -project = 'Elastic' -copyright = '2024, Elasticsearch B.V. All Rights Reserved.' - -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration - -# If a project defines its own extension, the path to the extension -# should be added to the path so that Sphinx can find it. -import os -import sys -sys.path.append(os.path.abspath("./_ext")) - -extensions = [ - # Commenting out the myst_parser extensions, since it is already - # included in myst_nb. Including it again will cause an error. - #'myst_parser', - 'myst_nb', - 'sphinx_design', - 'sphinx.ext.duration', - 'sphinx_copybutton', - 'sphinx_togglebutton', - 'sphinxcontrib.mermaid', - 'sphinx_multiversion', - 'rejoin', - 'markitpy.extensions.yaml_to_md' -] - -templates_path = ['_templates'] -html_static_path = ['_static'] - -exclude_patterns = [] - -suppress_warnings = ["myst.strikethrough"] - -myst_enable_extensions = [ - 'substitution', - 'attrs_inline', - 'attrs_block', - 'tasklist', - 'strikethrough', - 'deflist' -] - -myst_substitutions = { - 'project': "MarkItPy", -} - -myst_title_to_header = True -# myst_heading_anchors = 0 - -this_dir = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(this_dir) -from theme_conf import * -from multiversion_conf import * diff --git a/docs/source/docset.yml b/docs/source/docset.yml new file mode 100644 index 00000000..7a8c0228 --- /dev/null +++ b/docs/source/docset.yml @@ -0,0 +1,16 @@ +project: 'doc-builder' +exclude: + - '_*.md' +toc: + - file: index.md + - file: config.md + - file: search.md + children: + - file: search-part2.md + - folder: search + - folder: my-folder1 + - folder: my-folder2 + children: + - file: subpath/file.md + - file: file.md + - folder: sub/folder \ No newline at end of file diff --git a/docs/source/elastic/index.md b/docs/source/elastic/index.md index 8f47d8a4..bd193931 100644 --- a/docs/source/elastic/index.md +++ b/docs/source/elastic/index.md @@ -10,12 +10,3 @@ Here's what we have so far: * [Search Labs Tutorial](search-labs/index.md) — A partial port of the Search Labs Tutorials content currently hosted [here](https://www.elastic.co/search-labs/tutorials). * [Automated Settings Reference](reference/index.md) — An example of an automatically automated setting * [Observability overview](observability/index.md) — Nothing special, just a bunch of images and text. - -```{toctree} -:hidden: - -Tutorial: Semantic search with the inference API -Search Labs -Automated Settings -Observability overview -``` \ No newline at end of file diff --git a/docs/source/elastic/reference/index.md b/docs/source/elastic/reference/index.md index cf6c160c..55ebb6c5 100644 --- a/docs/source/elastic/reference/index.md +++ b/docs/source/elastic/reference/index.md @@ -8,11 +8,4 @@ Simply supply a yaml spec and corresponding template file and content will be au This section includes one example yaml file and two auto-generated outputs based on that file: * [example `yaml` file](source.md) -* [generated output](generated.md) - -```{toctree} -:hidden: - -source.md -generated.md -``` \ No newline at end of file +* [generated output](generated.md) \ No newline at end of file diff --git a/docs/source/elastic/search-labs/chat.md b/docs/source/elastic/search-labs/chat.md index c4e4db55..699d81e2 100644 --- a/docs/source/elastic/search-labs/chat.md +++ b/docs/source/elastic/search-labs/chat.md @@ -2,13 +2,6 @@ title: Chatbot Tutorial --- -```{toctree} -:hidden: - -chat/req.md -chat/rag.md -``` - In this tutorial you are going to build a large language model (LLM) chatbot that uses a pattern known as [Retrieval-Augmented Generation (RAG)](https://www.elastic.co/what-is/retrieval-augmented-generation). diff --git a/docs/source/elastic/search-labs/index.md b/docs/source/elastic/search-labs/index.md index d84dd3aa..7ee685e4 100644 --- a/docs/source/elastic/search-labs/index.md +++ b/docs/source/elastic/search-labs/index.md @@ -2,15 +2,6 @@ title: Search Labs Tutorials --- -```{toctree} -:hidden: - -install.md -search.md -chat.md -``` - - ## Start here ````{grid} 3 diff --git a/docs/source/elastic/search-labs/install.md b/docs/source/elastic/search-labs/install.md index 09f93e5a..29b8337b 100644 --- a/docs/source/elastic/search-labs/install.md +++ b/docs/source/elastic/search-labs/install.md @@ -2,13 +2,6 @@ title: "Install Elasticsearch" --- -```{toctree} -:hidden: - -install/cloud.md -install/docker.md -``` - In this section you will learn about some of the options you have for running Elasticsearch. Most of the tutorials and content on this site will require you to first follow the instructions below for your chosen method of installation. ## How to run Elasticsearch diff --git a/docs/source/elastic/search-labs/search.md b/docs/source/elastic/search-labs/search.md index 73fd8354..9d318b43 100644 --- a/docs/source/elastic/search-labs/search.md +++ b/docs/source/elastic/search-labs/search.md @@ -2,13 +2,6 @@ title: "Search Tutorial" --- -```{toctree} -:hidden: - -search/req.md -search/setup.md -``` - Welcome! This hands-on tutorial will teach you how to build a complete search solution using [Elasticsearch](https://www.elastic.co/). In this tutorial you will learn: diff --git a/docs/source/elastic/semantic-search/index.md b/docs/source/elastic/semantic-search/index.md index 5e152419..70687f10 100644 --- a/docs/source/elastic/semantic-search/index.md +++ b/docs/source/elastic/semantic-search/index.md @@ -42,13 +42,3 @@ Amazon Bedrock examples use the `amazon.titan-embed-text-v1` model from the [Ama ```{tip} Not seeing the tutorial? Select a service above to get started. ``` - -```{toctree} -:hidden: - -Amazon Bedrock -Azure AI Studio -Azure OpenAI -Cohere -ELSER -``` diff --git a/docs/source/index.md b/docs/source/index.md index 6c2aa63d..f4feea35 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -36,14 +36,3 @@ Hate it? Love it? We want to hear it all. Say hello and leave your thoughts in [ Hosted docs are great and all, but what's the contributor experience like? Read the [quick start guide](https://github.com/elastic/markitpy/tree/main), clone the repository, and spin up the docs locally in seconds. - - -```{toctree} -:caption: Elastic Docs Guide -:hidden: - -elastic/index.md -markup/index.md -nested/index.md -versioning/index.md -``` diff --git a/docs/source/markup/index.md b/docs/source/markup/index.md index 16591f81..d2ea0a33 100644 --- a/docs/source/markup/index.md +++ b/docs/source/markup/index.md @@ -3,24 +3,3 @@ title: Markup guide --- Here are some samples to show some features that you might want to use in your documentation. - -```{toctree} -:hidden: - -admonitions.md -tables.md -code.md -tabs.md -dropdowns.md -cards_grids.md -diagrams.md -images.md -sundries.md -substitutions.md -file_inclusion.md -extensions_with_roles_and_directives.md -yaml_to_markdown.md -notebook.ipynb -rst.rst -rst_in_markdown.md -``` diff --git a/docs/source/multiversion_conf.py b/docs/source/multiversion_conf.py deleted file mode 100644 index 8314b505..00000000 --- a/docs/source/multiversion_conf.py +++ /dev/null @@ -1,21 +0,0 @@ -# -- Options for sphinx-multiversion ----------------------------------------- -# https://holzhaus.github.io/sphinx-multiversion/master/configuration.html - -# Whitelist pattern for tags (set to None to ignore all tags) -# smv_tag_whitelist = None # Ignore all tags - -# Whitelist pattern for branches (set to None to ignore all branches) -# smv_branch_whitelist = r'^\d+\.\d+$' # Include branches like "2.1" -smv_branch_whitelist = r'^.*$' # Include all branches - -smv_remote_whitelist = None # Only use local branches -#smv_remote_whitelist = r'^.*$' # Use branches from all remotes - -# Pattern for released versions -# smv_released_pattern = r'^refs/heads/\d+\.\d+$' # Branches like "2.1" - -# Format for versioned output directories inside the build directory -#smv_outputdir_format = '{ref.name}' - -# Determines whether remote or local git branches/tags are preferred if their output dirs conflict -#smv_prefer_remote_refs = False \ No newline at end of file diff --git a/docs/source/nested/content/index.md b/docs/source/nested/content/index.md index e6aaf233..dca63031 100644 --- a/docs/source/nested/content/index.md +++ b/docs/source/nested/content/index.md @@ -4,8 +4,3 @@ title: Content Welcome to Nested Content. -```{toctree} -:hidden: - -nest-cafe.md -``` diff --git a/docs/source/nested/index.md b/docs/source/nested/index.md index 2dafbc85..41430576 100644 --- a/docs/source/nested/index.md +++ b/docs/source/nested/index.md @@ -3,9 +3,3 @@ title: Nested content --- This bucket is an example of nested content. Head down the tree to see how it works. - -```{toctree} -:hidden: - -content/index.md -``` \ No newline at end of file diff --git a/docs/source/theme_conf.py b/docs/source/theme_conf.py deleted file mode 100644 index 6d9eaa0d..00000000 --- a/docs/source/theme_conf.py +++ /dev/null @@ -1,105 +0,0 @@ -# -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output - -html_theme = "shibuya" - -html_theme_options = { - "announcement": '
👋 Thanks for checking out our Elastic Docs v3 POC. Have feedback? Reach out here. Thanks!
', - "light_logo": "_static/logo-light.svg", - "dark_logo": "_static/logo-dark.svg", - "accent_color": "blue", - "globaltoc_expand_depth": 1, - "logo_target": "index.html", - "nav_links": [ - { - "title": "Elastic Docs v3", - "url": "index" - }, - { - "title": "Start Here", - "children": [ - { - "title": "Search", - "url": "index", - "summary": "Build custom applications with your data using Elasticsearch.", - }, - { - "title": "Observability", - "url": "index", - "summary": "Monitor applications and systems with Elastic Observability.", - }, - { - "title": "Security", - "url": "index", - "summary": "Detect, investigate, and respond to threats with Elastic Security.", - }, - ] - }, - { - "title": "Deploy", - "children": [ - { - "title": "Elastic Cloud", - "url": "index", - "summary": "Deploy instances of the Elastic Stack in the cloud, with the provider of your choice." - }, - { - "title": "Elastic Cloud Enterprise", - "url": "index", - "summary": "Deploy Elastic Cloud on public or private clouds, virtual machines, or your own premises." - }, - { - "title": "Elastic Cloud on Kubernetes", - "url": "index", - "summary": "Deploy Elastic Cloud on Kubernetes." - }, - { - "title": "Self managed", - "url": "index", - "summary": "Install, configure, and run Elastic products on your own premises." - } - ] - }, - { - "title": "Reference", - "children": [ - { - "title": "API Reference", - "url": "index", - "summary": "Description." - }, - { - "title": "Configuration Reference", - "url": "index", - "summary": "Description." - }, - { - "title": "Troubleshooting", - "url": "index", - "summary": "Description." - }, - ] - }, - { - "title": "What's New", - "url": "index" - } - ] -} - -html_context = { - "source_type": "github", - "source_user": "elastic", - "source_repo": "markitpy-samples", - "source_version": "master", # Optional - "source_docs_path": "/docs/source/", # Optional -} - -html_css_files = ["custom.css"] - -html_sidebars = { - "**": [ - "sidebars/localtoc.html", - "sidebars/edit-this-page.html", - ] -} diff --git a/docs/source/versioning/index.md b/docs/source/versioning/index.md index 4939ddf2..c4e16de5 100644 --- a/docs/source/versioning/index.md +++ b/docs/source/versioning/index.md @@ -9,8 +9,3 @@ Multiversion support This file demonstrates versioning support. See the `markitpy` readme to learn how to test this content. -```{toctree} -:hidden: - -versioned.md -``` diff --git a/src/Elastic.Markdown/Diagnostics/DiagnosticsChannel.cs b/src/Elastic.Markdown/Diagnostics/DiagnosticsChannel.cs index d69fc7a6..9522dcee 100644 --- a/src/Elastic.Markdown/Diagnostics/DiagnosticsChannel.cs +++ b/src/Elastic.Markdown/Diagnostics/DiagnosticsChannel.cs @@ -47,7 +47,7 @@ public enum Severity { Error, Warning } public readonly record struct Diagnostic { public Severity Severity { get; init; } - public int Line { get; init; } + public int? Line { get; init; } public int? Column { get; init; } public int? Length { get; init; } public string File { get; init; } diff --git a/src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs b/src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs index bf671472..dc7ada51 100644 --- a/src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs +++ b/src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs @@ -2,6 +2,7 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.IO.Abstractions; using Elastic.Markdown.Myst; using Markdig.Helpers; using Markdig.Parsers; @@ -72,4 +73,26 @@ public static void EmitWarning(this ParserContext context, int line, int column, }; context.Build.Collector.Channel.Write(d); } + + public static void EmitError(this BuildContext context, IFileInfo file, string message) + { + var d = new Diagnostic + { + Severity = Severity.Error, + File = file.FullName, + Message = message, + }; + context.Collector.Channel.Write(d); + } + + public static void EmitWarning(this BuildContext context, IFileInfo file, string message) + { + var d = new Diagnostic + { + Severity = Severity.Error, + File = file.FullName, + Message = message, + }; + context.Collector.Channel.Write(d); + } } diff --git a/src/Elastic.Markdown/IO/ConfigurationFile.cs b/src/Elastic.Markdown/IO/ConfigurationFile.cs new file mode 100644 index 00000000..245fef95 --- /dev/null +++ b/src/Elastic.Markdown/IO/ConfigurationFile.cs @@ -0,0 +1,207 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Data.SqlTypes; +using System.IO.Abstractions; +using Cysharp.IO; +using Elastic.Markdown.Diagnostics; +using Markdig.Helpers; +using YamlDotNet.Core; +using YamlDotNet.RepresentationModel; + +namespace Elastic.Markdown.IO; + +public class ConfigurationFile : DocumentationFile +{ + private readonly IFileInfo _sourceFile; + private readonly BuildContext _context; + public string? Project { get; } + public string[] Exclude { get; } = []; + + public IReadOnlyCollection TableOfContents { get; } = []; + + public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildContext context) + : base(sourceFile, rootPath) + { + _sourceFile = sourceFile; + _context = context; + if (!sourceFile.Exists) + { + Project = "unknown"; + TableOfContents = []; + context.EmitWarning(sourceFile, "No configuration file found"); + return; + } + + // Load the stream + var yaml = new YamlStream(); + var textReader = sourceFile.FileSystem.File.OpenText(sourceFile.FullName); + yaml.Load(textReader); + + if (yaml.Documents.Count == 0) + context.EmitWarning(sourceFile, "empty configuration"); + + // Examine the stream + var mapping = (YamlMappingNode)yaml.Documents[0].RootNode; + + foreach (var entry in mapping.Children) + { + var key = ((YamlScalarNode)entry.Key).Value; + switch (key) + { + case "project": + Project = ReadString(entry); + break; + case "exclude": + Exclude = ReadStringArray(entry) ?? []; + break; + case "toc": + var entries = ReadChildren(entry); + + TableOfContents = entries; + break; + default: + EmitWarning($"{key} is not a known configuration", entry.Key); + break; + } + } + + } + + private List ReadChildren(KeyValuePair entry) + { + var entries = new List(); + if (entry.Value is not YamlSequenceNode sequence) + { + var key = ((YamlScalarNode)entry.Key).Value; + EmitWarning($"'{key}' is not an array"); + return entries; + } + + foreach (var tocEntry in sequence.Children.OfType()) + { + var tocItem = ReadChild(tocEntry); + if (tocItem is not null) + entries.Add(tocItem); + } + + return entries; + } + + private ITocItem? ReadChild(YamlMappingNode tocEntry) + { + string? file = null; + string? folder = null; + IReadOnlyCollection? children = null; + foreach (var entry in tocEntry.Children) + { + var key = ((YamlScalarNode)entry.Key).Value; + switch (key) + { + case "file": + file = ReadString(entry); + break; + case "folder": + folder = ReadString(entry); + break; + case "children": + children = ReadChildren(entry); + break; + } + } + + if (file is not null) + return new TocFile(file, children); + if (folder is not null) + return new TocFile(folder, children); + + return null; + } + + private string? ReadString(KeyValuePair entry) + { + if (entry.Value is YamlScalarNode scalar) + return scalar.Value; + + var key = ((YamlScalarNode)entry.Key).Value; + + EmitError($"'{key}' is not a string", entry.Key); + return null; + } + private string[]? ReadStringArray(KeyValuePair entry) + { + var values = new List(); + if (entry.Value is YamlSequenceNode sequence) + { + foreach (var entryValue in sequence.Children.OfType()) + { + if (entryValue.Value is not null) + values.Add(entryValue.Value); + } + + } + return values.ToArray(); + } + + public void EmitError(string message, YamlNode? node) => EmitError(message, node?.Start, node?.End); + + public void EmitWarning(string message, YamlNode? node) => EmitError(message, node?.Start, node?.End); + + public void EmitError(string message, Mark? start = null, Mark? end = null) + { + var d = new Diagnostic + { + Severity = Severity.Error, + File = _sourceFile.FullName, + Message = message, + Line = start.HasValue ? (int)start.Value.Line : null, + Column = start.HasValue ? (int)start.Value.Column : null, + Length = start.HasValue && end.HasValue ? (int)start.Value.Column - (int)end.Value.Column : null + }; + _context.Collector.Channel.Write(d); + } + + public void EmitWarning(string message, Mark? start = null, Mark? end = null) + { + var d = new Diagnostic + { + Severity = Severity.Warning, + File = _sourceFile.FullName, + Message = message, + Line = start.HasValue ? (int)start.Value.Line : null, + Column = start.HasValue ? (int)start.Value.Column : null, + Length = start.HasValue && end.HasValue ? (int)start.Value.Column - (int)end.Value.Column : null + }; + _context.Collector.Channel.Write(d); + } +} + +public interface ITocItem; + +public record TocFile(string Path, IReadOnlyCollection? Children) : ITocItem; + +public record TocFolder(string Path, IReadOnlyCollection? Children) : ITocItem; + + +/* +exclude: + - notes.md + - '**ignore.md' +toc: +- file: index.md +- file: config.md +- file: search.md +children: +- file: search-part2.md +- folder: search +- folder: my-folder1 +exclude: +- '_*.md' +- folder: my-folder2 +children: +- file: subpath/file.md +- file: file.md +- pattern: *.md +- folder: sub/folder +*/ diff --git a/src/Elastic.Markdown/IO/DocumentationFolder.cs b/src/Elastic.Markdown/IO/DocumentationFolder.cs index c0fb442b..a5e3b139 100644 --- a/src/Elastic.Markdown/IO/DocumentationFolder.cs +++ b/src/Elastic.Markdown/IO/DocumentationFolder.cs @@ -69,39 +69,11 @@ public async Task Resolve(Cancel ctx = default) await Parallel.ForEachAsync(Files, ctx, async (file, token) => await file.ParseAsync(token)); await Parallel.ForEachAsync(Nested, ctx, async (group, token) => await group.Resolve(token)); - //foreach (var f in Files) await f.ParseAsync(ctx); - //foreach (var n in Nested) await n.Resolve(ctx); - await (Index?.ParseAsync(ctx) ?? Task.CompletedTask); - if (Index?.TocTree == null) - return; - var tree = Index.TocTree; var fileList = new OrderedList(); var groupList = new OrderedList(); - foreach (var link in tree) - { - var file = Files.FirstOrDefault(f => f.RelativePath.EndsWith(link.Link)); - if (file != null) - { - file.TocTitle = link.Title; - fileList.Add(file); - continue; - } - - var group = Nested.FirstOrDefault(f => f.Index != null && f.Index.RelativePath.EndsWith(link.Link)); - if (group != null) - { - groupList.Add(group); - if (group.Index != null && !string.IsNullOrEmpty(link.Title)) - group.Index.TocTitle = link.Title; - } - else if (group == null || file == null) - { - - } - } FilesInOrder = fileList; GroupsInOrder = groupList; diff --git a/src/Elastic.Markdown/IO/DocumentationSet.cs b/src/Elastic.Markdown/IO/DocumentationSet.cs index a98fa63b..b3422fd7 100644 --- a/src/Elastic.Markdown/IO/DocumentationSet.cs +++ b/src/Elastic.Markdown/IO/DocumentationSet.cs @@ -17,6 +17,7 @@ public class DocumentationSet public DateTimeOffset LastWrite { get; } public IFileInfo OutputStateFile { get; } + public ConfigurationFile Configuration { get; } private MarkdownParser MarkdownParser { get; } @@ -30,6 +31,9 @@ public DocumentationSet(IDirectoryInfo? sourcePath, IDirectoryInfo? outputPath, MarkdownParser = new MarkdownParser(SourcePath, context); OutputStateFile = OutputPath.FileSystem.FileInfo.New(Path.Combine(OutputPath.FullName, ".doc.state")); + var configurationFile = context.ReadFileSystem.FileInfo.New(Path.Combine(SourcePath.FullName, "docset.yml")); + Configuration = new ConfigurationFile(configurationFile, SourcePath, context); + Files = context.ReadFileSystem.Directory.EnumerateFiles(SourcePath.FullName, "*.*", SearchOption.AllDirectories) .Select(f => context.ReadFileSystem.FileInfo.New(f)) .Select(file => file.Extension switch diff --git a/src/Elastic.Markdown/IO/MarkdownFile.cs b/src/Elastic.Markdown/IO/MarkdownFile.cs index 3e2ec2b2..dfd8d29f 100644 --- a/src/Elastic.Markdown/IO/MarkdownFile.cs +++ b/src/Elastic.Markdown/IO/MarkdownFile.cs @@ -55,14 +55,6 @@ public async Task ParseFullAsync(Cancel ctx) Title = YamlFrontMatter.Title; } - if (SourceFile.Name == "index.md") - { - TocTree = document - .Where(block => block is TocTreeBlock) - .Cast() - .FirstOrDefault()?.Links ?? new OrderedList(); - } - var contents = document .Where(block => block is HeadingBlock { Level: 2 }) .Cast() @@ -75,8 +67,6 @@ public async Task ParseFullAsync(Cancel ctx) return document; } - public OrderedList? TocTree { get; private set; } - public async Task CreateHtmlAsync(YamlFrontMatter? matter, Cancel ctx) { var document = await MarkdownParser.ParseAsync(SourceFile, matter, ctx); diff --git a/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs b/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs index ccb0b39d..bfdf1902 100644 --- a/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs +++ b/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs @@ -70,10 +70,6 @@ protected override DirectiveBlock CreateFencedBlock(BlockProcessor processor) if (processor.Context is not ParserContext context) throw new Exception("Expected parser context to be of type ParserContext"); - - if (info.EndsWith("{toctree}")) - return new TocTreeBlock(this, _admonitionData); - if (info.IndexOf("{") == -1) return new CodeBlock(this, "raw", _admonitionData); @@ -101,7 +97,7 @@ protected override DirectiveBlock CreateFencedBlock(BlockProcessor processor) return new FigureBlock(this, _admonitionData, context); // this is currently listed as unsupported - // leaving the parsing in untill we are confident we don't want this + // leaving the parsing in until we are confident we don't want this // for dev-docs if (info.IndexOf("{mermaid}") > 0) return new MermaidBlock(this, _admonitionData); @@ -137,23 +133,7 @@ public override bool Close(BlockProcessor processor, Block block) if (block is DirectiveBlock directiveBlock) directiveBlock.FinalizeAndValidate(processor.GetContext()); - - if (block is not TocTreeBlock toc) - return base.Close(processor, block); - - if (toc is not { Count: > 0 } || toc[0] is not ParagraphBlock p) - return base.Close(processor, block); - - var text = p.Lines.ToSlice().AsSpan().ToString(); - foreach (var line in text.Split('\n')) - { - var tokens = line.Split('<', '>').Where(e => !string.IsNullOrWhiteSpace(e)).ToArray(); - var fileName = tokens.Last().Trim(); - var title = string.Join(" ", tokens.Take(tokens.Length - 1)).Trim(); - toc.Links.Add(new TocTreeLink { Title = title, Link = fileName }); - } - - return base.Close(processor, block); + return base.Close(processor, block); } public override BlockState TryContinue(BlockProcessor processor, Block block) diff --git a/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs b/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs index 7570290a..806976a9 100644 --- a/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs +++ b/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs @@ -26,9 +26,6 @@ public class DirectiveHtmlRenderer : HtmlObjectRenderer { protected override void Write(HtmlRenderer renderer, DirectiveBlock directiveBlock) { - if (directiveBlock is TocTreeBlock) - return; - renderer.EnsureLine(); switch (directiveBlock) diff --git a/src/Elastic.Markdown/Myst/Directives/TocTreeBlock.cs b/src/Elastic.Markdown/Myst/Directives/TocTreeBlock.cs deleted file mode 100644 index ef725548..00000000 --- a/src/Elastic.Markdown/Myst/Directives/TocTreeBlock.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information -using Markdig.Helpers; - -namespace Elastic.Markdown.Myst.Directives; - -public class TocTreeLink -{ - public required string Link { get; init; } - public string? Title { get; set; } -} - -public class TocTreeBlock(DirectiveBlockParser parser, Dictionary properties) - : DirectiveBlock(parser, properties) -{ - public OrderedList Links { get; } = new(); - - public override void FinalizeAndValidate(ParserContext context) - { - } -} diff --git a/src/docs-builder/Diagnostics/ErrorCollector.cs b/src/docs-builder/Diagnostics/ErrorCollector.cs index 4986b337..d10a13a7 100644 --- a/src/docs-builder/Diagnostics/ErrorCollector.cs +++ b/src/docs-builder/Diagnostics/ErrorCollector.cs @@ -66,7 +66,7 @@ public override async Task StopAsync(Cancel ctx) { Severity.Error => Errata.Diagnostic.Error(item.Message) - .WithLabel(new Label(item.File, new Location(item.Line, item.Column ?? 0), "bad substitution") + .WithLabel(new Label(item.File, new Location(item.Line ?? 0, item.Column ?? 0), "bad substitution") .WithLength(item.Length ?? 3) .WithPriority(1) .WithColor(Color.Red)), diff --git a/tests/Elastic.Markdown.Tests/SiteMap/NavigationTests.cs b/tests/Elastic.Markdown.Tests/SiteMap/NavigationTests.cs index 2c158dea..67972e1f 100644 --- a/tests/Elastic.Markdown.Tests/SiteMap/NavigationTests.cs +++ b/tests/Elastic.Markdown.Tests/SiteMap/NavigationTests.cs @@ -38,8 +38,8 @@ public async Task CreatesDefaultOutputDirectory() await generator.GenerateAll(default); - writeFs.Directory.Exists(".artifacts/docs/html").Should().BeTrue(); - readFs.Directory.Exists(".artifacts/docs/html").Should().BeFalse(); + var configuration = generator.DocumentationSet.Configuration; + configuration.TableOfContents.Should().NotBeNullOrEmpty(); } }