diff --git a/docs/source/_ext/rejoin.py b/docs/source/_ext/rejoin.py
deleted file mode 100644
index afa760c43..000000000
--- a/docs/source/_ext/rejoin.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from __future__ import annotations
-from docutils import nodes
-
-from sphinx.application import Sphinx
-from sphinx.util.docutils import SphinxDirective, SphinxRole, directives
-from sphinx.util.typing import ExtensionMetadata
-
-def rejoin_text(text: str, split_by: str, join_by: str) -> str:
- return join_by.join(text.lower().split(split_by))
-
-class RejoinRole(SphinxRole):
- """A role to split by a string and rejoin by another string !"""
-
- def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]:
- node = nodes.inline(text=rejoin_text(self.text, ' ', '-'))
- return [node], []
-
-class RejoinDirective(SphinxDirective):
- """A directive to split by a string and rejoin by another string !"""
-
- required_arguments = 1
- has_content = True
- FROM_OPTION = 'from'
- TO_OPTION = 'to'
- optional_arguments = 2
- option_spec = {
- FROM_OPTION: directives.unchanged,
- TO_OPTION: directives.unchanged
- }
-
- def run(self) -> list[nodes.Node]:
- label = self.arguments[0]
- text = ''.join(self.content)
- fr = self.options[self.FROM_OPTION]
- to = self.options[self.TO_OPTION]
- rejoined_text = rejoin_text(text, fr, to)
- converted_text = f"{label} : {rejoined_text}"
- paragraph_node = nodes.inline(text=converted_text)
- return [paragraph_node]
-
-def setup(app: Sphinx) -> ExtensionMetadata:
- app.add_role('rejoin', RejoinRole())
- app.add_directive('rejoin', RejoinDirective)
- return {
- 'version': '0.1',
- 'parallel_read_safe': True,
- 'parallel_write_safe': True,
- }
\ No newline at end of file
diff --git a/docs/source/_templates/header.html b/docs/source/_templates/header.html
deleted file mode 100644
index 3d6448719..000000000
--- a/docs/source/_templates/header.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% extends "!header.html" %}
-
-{{ super() }}
-
-{% block extrahead %}
-{# Included before the closing tag #}
-
-{% endblock %}
diff --git a/docs/source/_templates/partials/globaltoc-above.html b/docs/source/_templates/partials/globaltoc-above.html
deleted file mode 100644
index f7da18f8b..000000000
--- a/docs/source/_templates/partials/globaltoc-above.html
+++ /dev/null
@@ -1,59 +0,0 @@
-{% if versions %}
-
-
-
-
-
-{% endif %}
diff --git a/docs/source/_templates/versioning.html b/docs/source/_templates/versioning.html
deleted file mode 100644
index 5347ebbda..000000000
--- a/docs/source/_templates/versioning.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% if versions %}
-{{ _('Versions') }}
-
-{% endif %}
\ No newline at end of file
diff --git a/src/Elastic.Markdown/DocumentationGenerator.cs b/src/Elastic.Markdown/DocumentationGenerator.cs
index a8b2ce377..df0955b1c 100644
--- a/src/Elastic.Markdown/DocumentationGenerator.cs
+++ b/src/Elastic.Markdown/DocumentationGenerator.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 System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elastic.Markdown.IO;
@@ -110,6 +111,27 @@ await Parallel.ForEachAsync(DocumentationSet.Files, ctx, async (file, token) =>
if (item % 1_000 == 0)
_logger.LogInformation($"Handled {handledItems} files");
});
+
+ var embeddedStaticFiles = Assembly.GetExecutingAssembly()
+ .GetManifestResourceNames()
+ .ToList();
+ foreach (var a in embeddedStaticFiles)
+ {
+ await using var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(a);
+ if (resourceStream == null)
+ continue;
+
+ var path = a.Replace("Elastic.Markdown.", "").Replace("_static.", "_static/");
+
+ var outputFile = OutputFile(path);
+ if (outputFile.Directory is { Exists: false })
+ outputFile.Directory.Create();
+ await using var stream = outputFile.OpenWrite();
+ await resourceStream.CopyToAsync(stream, ctx);
+ _logger.LogInformation($"Copied static embedded resource {path}");
+ }
+
+
Context.Collector.Channel.TryComplete();
await GenerateDocumentationState(ctx);
diff --git a/src/Elastic.Markdown/Elastic.Markdown.csproj b/src/Elastic.Markdown/Elastic.Markdown.csproj
index c9721f6bf..f616d8770 100644
--- a/src/Elastic.Markdown/Elastic.Markdown.csproj
+++ b/src/Elastic.Markdown/Elastic.Markdown.csproj
@@ -26,5 +26,8 @@
-
+
+
+
+
diff --git a/src/Elastic.Markdown/IO/DocumentationSet.cs b/src/Elastic.Markdown/IO/DocumentationSet.cs
index ecee2e385..69e1053d1 100644
--- a/src/Elastic.Markdown/IO/DocumentationSet.cs
+++ b/src/Elastic.Markdown/IO/DocumentationSet.cs
@@ -47,7 +47,6 @@ public DocumentationSet(BuildContext context)
".md" => CreateMarkDownFile(file, context),
_ => new StaticFile(file, SourcePath)
})
-
.ToList();
LastWrite = Files.Max(f => f.SourceFile.LastWriteTimeUtc);
diff --git a/src/Elastic.Markdown/IO/Paths.cs b/src/Elastic.Markdown/IO/Paths.cs
index 8b630801c..3075ef061 100644
--- a/src/Elastic.Markdown/IO/Paths.cs
+++ b/src/Elastic.Markdown/IO/Paths.cs
@@ -15,4 +15,13 @@ private static DirectoryInfo RootDirectoryInfo()
}
public static readonly DirectoryInfo Root = RootDirectoryInfo();
+
+ /// Used in debug to locate static folder so we can change js/css files while the server is running
+ public static DirectoryInfo? GetSolutionDirectory()
+ {
+ var directory = new DirectoryInfo(Directory.GetCurrentDirectory());
+ while (directory != null && directory.GetFiles("*.sln").Length == 0)
+ directory = directory.Parent;
+ return directory;
+ }
}
diff --git a/src/Elastic.Markdown/Myst/InlineParsers/DiagnosticLinkInlineParser.cs b/src/Elastic.Markdown/Myst/InlineParsers/DiagnosticLinkInlineParser.cs
index 524cfa826..d4ce66dfd 100644
--- a/src/Elastic.Markdown/Myst/InlineParsers/DiagnosticLinkInlineParser.cs
+++ b/src/Elastic.Markdown/Myst/InlineParsers/DiagnosticLinkInlineParser.cs
@@ -108,6 +108,10 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
if (url.EndsWith(".md"))
link.Url = Path.ChangeExtension(url, ".html");
+ // rooted links might need the configured path prefix to properly link
+ var prefix = processor.GetBuildContext().UrlPathPrefix;
+ if (url.StartsWith("/") && !string.IsNullOrWhiteSpace(prefix))
+ link.Url = $"{prefix}/{link.Url}";
if (!string.IsNullOrEmpty(anchor))
link.Url += $"#{anchor}";
diff --git a/docs/source/_static/atom-one-light.css b/src/Elastic.Markdown/_static/atom-one-light.css
similarity index 100%
rename from docs/source/_static/atom-one-light.css
rename to src/Elastic.Markdown/_static/atom-one-light.css
diff --git a/docs/source/_static/clipboard.min.js b/src/Elastic.Markdown/_static/clipboard.min.js
similarity index 100%
rename from docs/source/_static/clipboard.min.js
rename to src/Elastic.Markdown/_static/clipboard.min.js
diff --git a/docs/source/_static/copybutton.css b/src/Elastic.Markdown/_static/copybutton.css
similarity index 100%
rename from docs/source/_static/copybutton.css
rename to src/Elastic.Markdown/_static/copybutton.css
diff --git a/docs/source/_static/copybutton.js b/src/Elastic.Markdown/_static/copybutton.js
similarity index 100%
rename from docs/source/_static/copybutton.js
rename to src/Elastic.Markdown/_static/copybutton.js
diff --git a/docs/source/_static/custom.css b/src/Elastic.Markdown/_static/custom.css
similarity index 100%
rename from docs/source/_static/custom.css
rename to src/Elastic.Markdown/_static/custom.css
diff --git a/docs/source/_static/design-tabs.js b/src/Elastic.Markdown/_static/design-tabs.js
similarity index 100%
rename from docs/source/_static/design-tabs.js
rename to src/Elastic.Markdown/_static/design-tabs.js
diff --git a/docs/source/_static/doctools.js b/src/Elastic.Markdown/_static/doctools.js
similarity index 100%
rename from docs/source/_static/doctools.js
rename to src/Elastic.Markdown/_static/doctools.js
diff --git a/docs/source/_static/documentation_options.js b/src/Elastic.Markdown/_static/documentation_options.js
similarity index 100%
rename from docs/source/_static/documentation_options.js
rename to src/Elastic.Markdown/_static/documentation_options.js
diff --git a/docs/source/_static/logo-dark.svg b/src/Elastic.Markdown/_static/logo-dark.svg
similarity index 100%
rename from docs/source/_static/logo-dark.svg
rename to src/Elastic.Markdown/_static/logo-dark.svg
diff --git a/docs/source/_static/logo-light.svg b/src/Elastic.Markdown/_static/logo-light.svg
similarity index 100%
rename from docs/source/_static/logo-light.svg
rename to src/Elastic.Markdown/_static/logo-light.svg
diff --git a/docs/source/_static/mystnb.css b/src/Elastic.Markdown/_static/mystnb.css
similarity index 100%
rename from docs/source/_static/mystnb.css
rename to src/Elastic.Markdown/_static/mystnb.css
diff --git a/docs/source/_static/print.css b/src/Elastic.Markdown/_static/print.css
similarity index 100%
rename from docs/source/_static/print.css
rename to src/Elastic.Markdown/_static/print.css
diff --git a/docs/source/_static/pygments.css b/src/Elastic.Markdown/_static/pygments.css
similarity index 100%
rename from docs/source/_static/pygments.css
rename to src/Elastic.Markdown/_static/pygments.css
diff --git a/docs/source/_static/shibuya.css b/src/Elastic.Markdown/_static/shibuya.css
similarity index 100%
rename from docs/source/_static/shibuya.css
rename to src/Elastic.Markdown/_static/shibuya.css
diff --git a/docs/source/_static/shibuya.js b/src/Elastic.Markdown/_static/shibuya.js
similarity index 100%
rename from docs/source/_static/shibuya.js
rename to src/Elastic.Markdown/_static/shibuya.js
diff --git a/docs/source/_static/sphinx-design.min.css b/src/Elastic.Markdown/_static/sphinx-design.min.css
similarity index 100%
rename from docs/source/_static/sphinx-design.min.css
rename to src/Elastic.Markdown/_static/sphinx-design.min.css
diff --git a/docs/source/_static/sphinx_highlight.js b/src/Elastic.Markdown/_static/sphinx_highlight.js
similarity index 100%
rename from docs/source/_static/sphinx_highlight.js
rename to src/Elastic.Markdown/_static/sphinx_highlight.js
diff --git a/docs/source/_static/togglebutton.css b/src/Elastic.Markdown/_static/togglebutton.css
similarity index 100%
rename from docs/source/_static/togglebutton.css
rename to src/Elastic.Markdown/_static/togglebutton.css
diff --git a/docs/source/_static/togglebutton.js b/src/Elastic.Markdown/_static/togglebutton.js
similarity index 100%
rename from docs/source/_static/togglebutton.js
rename to src/Elastic.Markdown/_static/togglebutton.js
diff --git a/src/docs-builder/Cli/Commands.cs b/src/docs-builder/Cli/Commands.cs
index 35eef9f7d..88dd4b2a5 100644
--- a/src/docs-builder/Cli/Commands.cs
+++ b/src/docs-builder/Cli/Commands.cs
@@ -7,7 +7,6 @@
using Documentation.Builder.Diagnostics;
using Documentation.Builder.Http;
using Elastic.Markdown;
-using Elastic.Markdown.Diagnostics;
using Elastic.Markdown.IO;
using Microsoft.Extensions.Logging;
diff --git a/src/docs-builder/Http/DocumentationWebHost.cs b/src/docs-builder/Http/DocumentationWebHost.cs
index c9537eacf..656e9bbc3 100644
--- a/src/docs-builder/Http/DocumentationWebHost.cs
+++ b/src/docs-builder/Http/DocumentationWebHost.cs
@@ -10,9 +10,12 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.FileProviders.Physical;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Primitives;
using Westwind.AspNetCore.LiveReload;
+using IFileInfo = Microsoft.Extensions.FileProviders.IFileInfo;
namespace Documentation.Builder.Http;
@@ -20,8 +23,7 @@ public class DocumentationWebHost
{
private readonly WebApplication _webApplication;
- private readonly string _staticFilesDirectory =
- Path.Combine(Paths.Root.FullName, "docs", "source", "_static");
+ private readonly string _staticFilesDirectory;
public DocumentationWebHost(string? path, ILoggerFactory logger, IFileSystem fileSystem)
{
@@ -40,6 +42,15 @@ public DocumentationWebHost(string? path, ILoggerFactory logger, IFileSystem fil
builder.Services.AddSingleton(logger);
builder.Logging.SetMinimumLevel(LogLevel.Warning);
+ _staticFilesDirectory = Path.Combine(context.SourcePath.FullName, "_static");
+ #if DEBUG
+ // this attempts to serve files directly from their source rather than the embedded resourses during development.
+ // this allows us to change js/css files without restarting the webserver
+ var solutionRoot = Paths.GetSolutionDirectory();
+ if (solutionRoot != null)
+ _staticFilesDirectory = Path.Combine(solutionRoot.FullName, "src", "Elastic.Markdown", "_static");
+ #endif
+
_webApplication = builder.Build();
SetUpRoutes();
}
@@ -52,7 +63,7 @@ private void SetUpRoutes()
_webApplication.UseLiveReload();
_webApplication.UseStaticFiles(new StaticFileOptions
{
- FileProvider = new PhysicalFileProvider(_staticFilesDirectory),
+ FileProvider = new EmbeddedOrPhysicalFileProvider(_staticFilesDirectory),
RequestPath = "/_static"
});
_webApplication.UseRouting();
@@ -86,3 +97,40 @@ private static async Task ServeDocumentationFile(ReloadableGeneratorSta
}
}
}
+
+
+public class EmbeddedOrPhysicalFileProvider : IFileProvider
+{
+ private readonly EmbeddedFileProvider _embeddedProvider;
+ private readonly PhysicalFileProvider _fileProvider;
+
+ public EmbeddedOrPhysicalFileProvider(string root)
+ {
+ _embeddedProvider = new EmbeddedFileProvider(typeof(BuildContext).Assembly, "Elastic.Markdown._static");
+ _fileProvider = new PhysicalFileProvider(root);
+ }
+
+ public IDirectoryContents GetDirectoryContents(string subpath)
+ {
+ var contents = _fileProvider.GetDirectoryContents(subpath);
+ if (!contents.Exists)
+ contents = _embeddedProvider.GetDirectoryContents(subpath);
+ return contents;
+ }
+
+ public IFileInfo GetFileInfo(string subpath)
+ {
+ var fileInfo = _fileProvider.GetFileInfo(subpath.Replace("/_static", ""));
+ if (!fileInfo.Exists)
+ fileInfo = _embeddedProvider.GetFileInfo(subpath);
+ return fileInfo;
+ }
+
+ public IChangeToken Watch(string filter)
+ {
+ var changeToken = _fileProvider.Watch(filter);
+ if (changeToken is NullChangeToken)
+ changeToken = _embeddedProvider.Watch(filter);
+ return changeToken;
+ }
+}
diff --git a/src/docs-builder/Program.cs b/src/docs-builder/Program.cs
index e10c1d960..25d9d388c 100644
--- a/src/docs-builder/Program.cs
+++ b/src/docs-builder/Program.cs
@@ -4,6 +4,7 @@
using Actions.Core.Extensions;
using ConsoleAppFramework;
+using Documentation.Builder;
using Documentation.Builder.Cli;
using Elastic.Markdown.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
@@ -28,6 +29,7 @@
services.AddSingleton();
services.AddSingleton();
+
await using var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetRequiredService>();
ConsoleApp.ServiceProvider = serviceProvider;
diff --git a/src/docs-builder/docs-builder.csproj b/src/docs-builder/docs-builder.csproj
index d1788fbfc..6c455cc2e 100644
--- a/src/docs-builder/docs-builder.csproj
+++ b/src/docs-builder/docs-builder.csproj
@@ -33,4 +33,5 @@
+
\ No newline at end of file
diff --git a/src/docs-generator/Cli/Commands.cs b/src/docs-generator/Cli/Commands.cs
index 924d1a41a..3f435da9e 100644
--- a/src/docs-generator/Cli/Commands.cs
+++ b/src/docs-generator/Cli/Commands.cs
@@ -95,7 +95,7 @@ public async Task Generate(
WriteMarkdownFile(outputFolder, file);
}
- var name = $"random-docset-{seedContent}-{seedFileSystem}";
+ var name = $"random-docset-{Determinism.Random.SeedFileSystem}-{Determinism.Random.SeedFileSystem}";
WriteIndexMarkdownFile(name, outputFolder);
var docset = Path.Combine(outputFolder.FullName, "docset.yml");
diff --git a/src/docs-generator/Domain/Generators.cs b/src/docs-generator/Domain/Generators.cs
index feef603f5..dad7b9049 100644
--- a/src/docs-generator/Domain/Generators.cs
+++ b/src/docs-generator/Domain/Generators.cs
@@ -2,7 +2,6 @@
// 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 Slugify;
using Soenneker.Utils.AutoBogus;
namespace Documentation.Generator.Domain;
@@ -12,7 +11,6 @@ public static class Generators
public static AutoFaker FolderName { get; } = new();
public static AutoFaker Section { get; } = new();
public static AutoFaker File { get; } = new();
- public static SlugHelper Slug { get; } = new();
static Generators()
{