55using System . Collections . Concurrent ;
66using System . IO ;
77using System . IO . Abstractions ;
8+ using System . IO . Compression ;
89using System . Text ;
910using Elastic . Documentation . Configuration ;
1011using 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
86- // Root index becomes llm-docs.md
8787 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+ 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
0 commit comments