Skip to content

Commit 4ae0f36

Browse files
committed
Also create zip file with top level llms.txt file
1 parent 4d347fb commit 4ae0f36

File tree

3 files changed

+36
-55
lines changed

3 files changed

+36
-55
lines changed

src/Elastic.Markdown/Exporters/LlmMarkdownExporter.cs

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Concurrent;
66
using System.IO;
77
using System.IO.Abstractions;
8+
using System.IO.Compression;
89
using System.Text;
910
using Elastic.Documentation.Configuration;
1011
using Elastic.Documentation.Configuration.Builder;
@@ -25,50 +26,51 @@ public class LlmMarkdownExporter : IMarkdownExporter
2526

2627
public ValueTask StopAsync(Cancel ctx = default) => ValueTask.CompletedTask;
2728

28-
public ValueTask<bool> FinishExportAsync(IDirectoryInfo outputFolder, Cancel ctx) => ValueTask.FromResult(true);
29+
public ValueTask<bool> FinishExportAsync(IDirectoryInfo outputFolder, Cancel ctx)
30+
{
31+
var outputDirectory = Path.Combine(outputFolder.FullName, "docs");
32+
var zipPath = Path.Combine(outputDirectory, "llm.zip");
33+
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
34+
{
35+
var llmsTxt = Path.Combine(outputFolder.FullName, "llms.txt");
36+
_ = zip.CreateEntryFromFile(llmsTxt, "llms.txt");
37+
38+
var markdownFiles = Directory.GetFiles(outputDirectory, "*.md", SearchOption.AllDirectories);
39+
40+
foreach (var file in markdownFiles)
41+
{
42+
var relativePath = Path.GetRelativePath(outputDirectory, file);
43+
_ = zip.CreateEntryFromFile(file, relativePath);
44+
}
45+
}
46+
return ValueTask.FromResult(true);
47+
}
2948

3049
public async ValueTask<bool> ExportAsync(MarkdownExportFileContext fileContext, Cancel ctx)
3150
{
32-
// Convert the parsed markdown document to LLM-friendly format using our custom renderers
3351
var llmMarkdown = ConvertToLlmMarkdown(fileContext.Document, fileContext);
34-
35-
// Determine output file path
3652
var outputFile = GetLlmOutputFile(fileContext);
37-
38-
// Ensure output directory exists
3953
if (outputFile.Directory is { Exists: false })
4054
outputFile.Directory.Create();
41-
42-
// Write LLM markdown with metadata header
4355
var contentWithMetadata = CreateLlmContentWithMetadata(fileContext, llmMarkdown);
4456
await fileContext.SourceFile.SourceFile.FileSystem.File.WriteAllTextAsync(
4557
outputFile.FullName,
4658
contentWithMetadata,
4759
Encoding.UTF8,
4860
ctx
4961
);
50-
5162
return true;
5263
}
5364

5465
public static string ConvertToLlmMarkdown(MarkdownDocument document, MarkdownExportFileContext context)
5566
{
5667
using var writer = new StringWriter();
57-
var state = new ParserState(context.BuildContext)
58-
{
59-
YamlFrontMatter = context.SourceFile.YamlFrontMatter,
60-
MarkdownSourcePath = context.SourceFile.SourceFile,
61-
CrossLinkResolver = context.Resolvers.CrossLinkResolver,
62-
DocumentationFileLookup = context.Resolvers.DocumentationFileLookup
63-
};
64-
var parserContext = new ParserContext(state);
6568
var renderer = new LlmMarkdownRenderer(writer)
6669
{
6770
BuildContext = context.BuildContext
6871
};
6972
_ = renderer.Render(document);
70-
var content = writer.ToString();
71-
return content;
73+
return writer.ToString();
7274
}
7375

7476
private static IFileInfo GetLlmOutputFile(MarkdownExportFileContext fileContext)
@@ -77,35 +79,26 @@ private static IFileInfo GetLlmOutputFile(MarkdownExportFileContext fileContext)
7779
var fs = source.FileSystem;
7880
var defaultOutputFile = fileContext.DefaultOutputFile;
7981

80-
// Handle both index.md and index.html files (HTML output files)
8182
var fileName = Path.GetFileNameWithoutExtension(defaultOutputFile.Name);
8283
if (fileName == "index")
8384
{
8485
var root = fileContext.BuildContext.DocumentationOutputDirectory;
8586

8687
// Root index becomes llm-docs.md
87-
if (defaultOutputFile.Directory!.FullName == root.FullName)
88-
{
89-
return fs.FileInfo.New(Path.Combine(root.FullName, "llm-docs.md"));
90-
}
91-
else
92-
{
93-
// For index files: /docs/section/index.html -> /docs/section.llm.md
94-
// This allows users to append .llm.md to any URL path
95-
var folderName = defaultOutputFile.Directory!.Name;
96-
return fs.FileInfo.New(Path.Combine(
97-
defaultOutputFile.Directory!.Parent!.FullName,
98-
$"{folderName}.md"
99-
));
100-
}
101-
}
102-
else
103-
{
104-
// Regular files: /docs/section/page.html -> /docs/section/page.llm.md
105-
var directory = defaultOutputFile.Directory!.FullName;
106-
var baseName = Path.GetFileNameWithoutExtension(defaultOutputFile.Name);
107-
return fs.FileInfo.New(Path.Combine(directory, $"{baseName}.md"));
88+
if (defaultOutputFile.Directory!.FullName == root.FullName) return fs.FileInfo.New(Path.Combine(root.FullName, "llms.txt"));
89+
90+
// For index files: /docs/section/index.html -> /docs/section.md
91+
// This allows users to append .md to any URL path
92+
var folderName = defaultOutputFile.Directory!.Name;
93+
return fs.FileInfo.New(Path.Combine(
94+
defaultOutputFile.Directory!.Parent!.FullName,
95+
$"{folderName}.md"
96+
));
10897
}
98+
// Regular files: /docs/section/page.html -> /docs/section/page.llm.md
99+
var directory = defaultOutputFile.Directory!.FullName;
100+
var baseName = Path.GetFileNameWithoutExtension(defaultOutputFile.Name);
101+
return fs.FileInfo.New(Path.Combine(directory, $"{baseName}.md"));
109102
}
110103

111104

tests/authoring/Framework/LlmTestAssertions.fs renamed to tests/authoring/Framework/LlmMarkdownAssertions.fs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ open System
88
open System.Diagnostics
99
open System.IO
1010
open Elastic.Markdown.Exporters
11-
open Elastic.Markdown.Myst.Renderers
1211
open JetBrains.Annotations
1312
open Xunit.Sdk
1413

1514
[<AutoOpen>]
16-
module LlmTestAssertions =
15+
module LlmMarkdownAssertions =
1716

1817
let toNewLLM (actual: MarkdownResult) =
1918
use writer = new StringWriter()
@@ -26,16 +25,12 @@ module LlmTestAssertions =
2625
)
2726
LlmMarkdownExporter.ConvertToLlmMarkdown(actual.Document, markdownExportFileContext).Trim()
2827

29-
3028
[<DebuggerStepThrough>]
3129
let convertsToNewLLM ([<LanguageInjection("markdown")>]expected: string) (actual: Lazy<GeneratorResults>) =
3230
let results = actual.Value
3331
let defaultFile = results.MarkdownResults |> Seq.find (fun r -> r.File.RelativePath = "index.md")
3432
let actualLLM = toNewLLM defaultFile
35-
36-
// The new exporter adds a title, so we need to account for that in the expected output.
3733
let expectedWithTitle = $"{expected}".Trim()
38-
3934
let difference = diff expectedWithTitle actualLLM
4035
match difference with
4136
| s when String.IsNullOrEmpty s -> ()

tests/authoring/authoring.fsproj

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<Compile Include="Framework\HtmlAssertions.fs"/>
3939
<Compile Include="Framework\ErrorCollectorAssertions.fs"/>
4040
<Compile Include="Framework\MarkdownDocumentAssertions.fs"/>
41-
<Compile Include="Framework\LlmTestAssertions.fs" />
41+
<Compile Include="Framework\LlmMarkdownAssertions.fs" />
4242
<Compile Include="Framework\CrossLinkResolverAssertions.fs" />
4343
<Compile Include="Inline\Substitutions.fs"/>
4444
<Compile Include="Inline\SubstitutionMutations.fs" />
@@ -61,14 +61,7 @@
6161
<Compile Include="Applicability\AppliesToFrontMatter.fs" />
6262
<Compile Include="Applicability\AppliesToDirective.fs" />
6363
<Compile Include="Directives\IncludeBlocks.fs" />
64-
</ItemGroup>
65-
66-
<ItemGroup>
6764
<Compile Include="Linters\WhiteSpaceNormalizers.fs" />
68-
</ItemGroup>
69-
70-
<ItemGroup>
7165
<Compile Include="LlmMarkdown\LlmMarkdownOutput.fs" />
7266
</ItemGroup>
73-
7467
</Project>

0 commit comments

Comments
 (0)