Skip to content

Commit bfae0fe

Browse files
authored
Ensure links to directive anchors are validated (#76)
1 parent 95b60cd commit bfae0fe

32 files changed

+401
-146
lines changed

docs/source/docset.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
project: 'doc-builder'
2+
# docs-builder will warn for links to external hosts not declared here
3+
external_hosts:
4+
- slack.com
5+
- mystmd.org
6+
- microsoft.com
7+
- azure.com
8+
- mistral.ai
9+
- amazon.com
10+
- python.org
11+
- cohere.com
12+
- docker.com
13+
- langchain.com
14+
- nodejs.org
15+
- yarnpkg.com
16+
- react.dev
17+
- palletsprojects.com
218
exclude:
319
- '_*.md'
420
toc:
521
- file: index.md
22+
- folder: markup
623
- folder: elastic
724
children:
825
- file: index.md
@@ -24,7 +41,6 @@ toc:
2441
children:
2542
- file: search/req.md
2643
- file: search/setup.md
27-
- folder: markup
2844
- folder: nested
2945
children:
3046
- folder: content

docs/source/elastic/search-labs/chat.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ title: Chatbot Tutorial
44

55
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).
66

7-
<!-- ![Chatbot App Demo](/assets/images/guides/chatbot-app-demo.gif) -->
8-
97
Chatbots built with RAG can overcome some of the limitations that general-purpose conversational models such as ChatGPT have. In particular, they are able to discuss and answer questions about:
108

119
- Information that is private to your organization.

docs/source/elastic/search-labs/install/cloud.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,10 @@ Follow these steps to obtain your Cloud ID:
3030
1. Locate your deployment, and click the **Manage** link under the **Actions** column.
3131
1. The Cloud ID is displayed on the right side of the page. See the screenshot below as a reference.
3232

33-
<!-- ![My deployment](/assets/images/guides/elastic-cloud-my-deployment.png) -->
34-
3533
## Creating an API Key
3634

3735
For security purposes, it is recommended that you create an API Key to use when authenticating to the Elasticsearch service.
3836

39-
<!-- ![my deployment](/assets/images/guides/elastic-cloud-api-key.png) -->
40-
4137
Follow these steps to create an API Key:
4238

4339
1. Navigate to your [Elastic Cloud](https://cloud.elastic.co/home) home page.

docs/source/elastic/search-labs/search/setup.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ Download the starter search application by clicking on the link below.
1212

1313
Find a suitable parent directory for your project, such as your *Documents* directory, and extract the contents of the zip file there. This should add a *search-tutorial* directory with several sub-directories and files inside.
1414

15-
<!-- ![Search Starter App](/assets/images/guides/starter-app-structure.png) -->
16-
1715

1816
## Install the Python Dependencies
1917

@@ -69,8 +67,6 @@ flask run
6967

7068
To confirm that the application is running, open your browser and navigate to http://localhost:5001.
7169

72-
<!-- ![Search Starter App](/assets/images/guides/starter-app-screenshot.png) -->
73-
7470
```{note}
7571
The application in this early stage is just an empty shell. You can type something in the search box and request a search if you like, but the response is always going to be that there are no results. In the following sections you will learn how to load some content in an Elasticsearch index and perform searches.
7672
```

docs/source/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ title: Elastic Docs v3
44

55
Elastic Docs v3 is built with
66

7+
Test during zoom with colleen
8+
79
TODO ADD README for doc-builder
810

911
:::{tip}

docs/source/markup/admonitions.md

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,15 @@ Admonitions bring the attention of readers.
66

77
## Basic admonitions
88

9-
```{attention}
10-
:name: attention_ref
11-
This is an 'attention' admonition
12-
```
13-
149
```{caution}
10+
:name: caution_ref
1511
This is a 'caution' admonition
1612
```
1713

18-
```{danger}
19-
This is a 'danger' admonition
20-
```
21-
22-
```{error}
23-
This is an 'error' admonition
24-
```
25-
26-
```{hint}
27-
This is an 'hint' admonition
28-
```
29-
30-
```{important}
31-
This is an 'important' admonition
32-
```
33-
3414
```{note}
3515
This is a 'note' admonition
3616
```
3717

38-
```{seealso}
39-
This is a 'seealso' admonition
40-
```
41-
4218
```{tip}
4319
This is a tip
4420
```
@@ -84,4 +60,4 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
8460
## Link to admonitions
8561
You can add a 'name' option to an admonition, so that you can link to it elsewhere
8662

87-
Here is a [link to attention](#attention_ref)
63+
Here is a [link to attention](#caution_ref)

src/Elastic.Markdown/BuildContext.cs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@
33
// See the LICENSE file in the project root for more information
44
using System.IO.Abstractions;
55
using Elastic.Markdown.Diagnostics;
6+
using Elastic.Markdown.IO;
67

78
namespace Elastic.Markdown;
89

910
public record BuildContext
1011
{
11-
public required IFileSystem ReadFileSystem { get; init; }
12-
public required IFileSystem WriteFileSystem { get; init; }
12+
public IFileSystem ReadFileSystem { get; }
13+
public IFileSystem WriteFileSystem { get; }
14+
15+
public IDirectoryInfo SourcePath { get; }
16+
public IDirectoryInfo OutputPath { get; }
17+
18+
public IFileInfo ConfigurationPath { get; }
19+
1320
public required DiagnosticsCollector Collector { get; init; }
1421

1522
public bool Force { get; init; }
@@ -22,4 +29,32 @@ public string? UrlPathPrefix
2229

2330
private readonly string? _urlPathPrefix;
2431

32+
public BuildContext(IFileSystem fileSystem)
33+
: this(fileSystem, fileSystem, null, null) { }
34+
35+
public BuildContext(IFileSystem readFileSystem, IFileSystem writeFileSystem)
36+
: this(readFileSystem, writeFileSystem, null, null) { }
37+
38+
public BuildContext(IFileSystem readFileSystem, IFileSystem writeFileSystem, string? source, string? output)
39+
{
40+
ReadFileSystem = readFileSystem;
41+
WriteFileSystem = writeFileSystem;
42+
43+
SourcePath = !string.IsNullOrWhiteSpace(source)
44+
? ReadFileSystem.DirectoryInfo.New(source)
45+
: ReadFileSystem.DirectoryInfo.New(Path.Combine(Paths.Root.FullName, "docs/source"));
46+
OutputPath = !string.IsNullOrWhiteSpace(output)
47+
? WriteFileSystem.DirectoryInfo.New(output)
48+
: WriteFileSystem.DirectoryInfo.New(Path.Combine(Paths.Root.FullName, ".artifacts/docs/html"));
49+
50+
ConfigurationPath =
51+
SourcePath.EnumerateFiles("docset.yml", SearchOption.AllDirectories).FirstOrDefault()
52+
?? ReadFileSystem.FileInfo.New(Path.Combine(SourcePath.FullName, "docset.yml"));
53+
54+
if (ConfigurationPath.FullName != SourcePath.FullName)
55+
SourcePath = ConfigurationPath.Directory!;
56+
57+
58+
}
59+
2560
}

src/Elastic.Markdown/DocumentationGenerator.cs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,36 +33,22 @@ public class DocumentationGenerator
3333

3434
public DocumentationGenerator(
3535
DocumentationSet docSet,
36-
BuildContext context,
3736
ILoggerFactory logger
3837
)
3938
{
40-
_readFileSystem = context.ReadFileSystem;
41-
_writeFileSystem = context.WriteFileSystem;
39+
_readFileSystem = docSet.Context.ReadFileSystem;
40+
_writeFileSystem = docSet.Context.WriteFileSystem;
4241
_logger = logger.CreateLogger(nameof(DocumentationGenerator));
4342

4443
DocumentationSet = docSet;
45-
Context = context;
44+
Context = docSet.Context;
4645
HtmlWriter = new HtmlWriter(DocumentationSet, _writeFileSystem);
4746

4847
_logger.LogInformation($"Created documentation set for: {DocumentationSet.Name}");
4948
_logger.LogInformation($"Source directory: {docSet.SourcePath} Exists: {docSet.SourcePath.Exists}");
5049
_logger.LogInformation($"Output directory: {docSet.OutputPath} Exists: {docSet.OutputPath.Exists}");
5150
}
5251

53-
public static DocumentationGenerator Create(
54-
string? path,
55-
string? output,
56-
BuildContext context,
57-
ILoggerFactory logger
58-
)
59-
{
60-
var sourcePath = path != null ? context.ReadFileSystem.DirectoryInfo.New(path) : null;
61-
var outputPath = output != null ? context.WriteFileSystem.DirectoryInfo.New(output) : null;
62-
var docSet = new DocumentationSet(sourcePath, outputPath, context);
63-
return new DocumentationGenerator(docSet, context, logger);
64-
}
65-
6652
public OutputState? OutputState
6753
{
6854
get

src/Elastic.Markdown/IO/ConfigurationFile.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ public record ConfigurationFile : DocumentationFile
2323
public HashSet<string> Files { get; } = new(StringComparer.OrdinalIgnoreCase);
2424
public HashSet<string> ImplicitFolders { get; } = new(StringComparer.OrdinalIgnoreCase);
2525
public Glob[] Globs { get; } = [];
26+
public HashSet<string> ExternalLinkHosts { get; } = new(StringComparer.OrdinalIgnoreCase)
27+
{
28+
"elastic.co",
29+
"github.com",
30+
};
2631

2732
public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildContext context)
2833
: base(sourceFile, rootPath)
@@ -62,6 +67,12 @@ public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildCon
6267
.Select(Glob.Parse)
6368
.ToArray();
6469
break;
70+
case "external_hosts":
71+
var hosts = ReadStringArray(entry)
72+
.ToArray();
73+
foreach (var host in hosts)
74+
ExternalLinkHosts.Add(host);
75+
break;
6576
case "toc":
6677
var entries = ReadChildren(entry, string.Empty);
6778

src/Elastic.Markdown/IO/DocumentationSet.cs

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,31 @@ namespace Elastic.Markdown.IO;
1010

1111
public class DocumentationSet
1212
{
13+
public BuildContext Context { get; }
1314
public string Name { get; }
15+
public IFileInfo OutputStateFile { get; }
16+
1417
public IDirectoryInfo SourcePath { get; }
1518
public IDirectoryInfo OutputPath { get; }
16-
public IFileInfo OutputStateFile { get; }
1719

1820
public DateTimeOffset LastWrite { get; }
1921

2022
public ConfigurationFile Configuration { get; }
2123

2224
public MarkdownParser MarkdownParser { get; }
2325

24-
public DocumentationSet(BuildContext context) : this(null, null, context) { }
25-
26-
public DocumentationSet(IDirectoryInfo? sourcePath, IDirectoryInfo? outputPath, BuildContext context)
26+
public DocumentationSet(BuildContext context)
2727
{
28-
SourcePath = sourcePath ?? context.ReadFileSystem.DirectoryInfo.New(Path.Combine(Paths.Root.FullName, "docs/source"));
29-
OutputPath = outputPath ?? context.WriteFileSystem.DirectoryInfo.New(Path.Combine(Paths.Root.FullName, ".artifacts/docs/html"));
28+
Context = context;
29+
SourcePath = context.SourcePath;
30+
OutputPath = context.OutputPath;
31+
Configuration = new ConfigurationFile(context.ConfigurationPath, SourcePath, context);
3032

31-
var configurationFile = SourcePath.EnumerateFiles("docset.yml", SearchOption.AllDirectories).FirstOrDefault();
32-
if (configurationFile is null)
33-
{
34-
configurationFile = context.ReadFileSystem.FileInfo.New(Path.Combine(SourcePath.FullName, "docset.yml"));
35-
context.EmitWarning(configurationFile, "No configuration file found");
36-
}
37-
38-
if (configurationFile.Directory!.FullName != SourcePath.FullName)
39-
SourcePath = configurationFile.Directory;
40-
41-
MarkdownParser = new MarkdownParser(SourcePath, context, GetTitle);
33+
MarkdownParser = new MarkdownParser(SourcePath, context, GetMarkdownFile, Configuration);
4234

4335
Name = SourcePath.FullName;
4436
OutputStateFile = OutputPath.FileSystem.FileInfo.New(Path.Combine(OutputPath.FullName, ".doc.state"));
4537

46-
Configuration = new ConfigurationFile(configurationFile, SourcePath, context);
47-
4838
Files = context.ReadFileSystem.Directory
4939
.EnumerateFiles(SourcePath.FullName, "*.*", SearchOption.AllDirectories)
5040
.Select(f => context.ReadFileSystem.FileInfo.New(f))
@@ -68,10 +58,9 @@ public DocumentationSet(IDirectoryInfo? sourcePath, IDirectoryInfo? outputPath,
6858
Tree = new DocumentationFolder(Configuration.TableOfContents, FlatMappedFiles, folderFiles);
6959
}
7060

71-
private string? GetTitle(string relativePath) => GetMarkdownFile(relativePath)?.YamlFrontMatter?.Title;
72-
73-
public MarkdownFile? GetMarkdownFile(string relativePath)
61+
public MarkdownFile? GetMarkdownFile(IFileInfo sourceFile)
7462
{
63+
var relativePath = Path.GetRelativePath(SourcePath.FullName, sourceFile.FullName);
7564
if (FlatMappedFiles.TryGetValue(relativePath, out var file) && file is MarkdownFile markdownFile)
7665
return markdownFile;
7766
return null;

0 commit comments

Comments
 (0)