Class Sealed
public sealed class ThemeLoader

Namespace: Moka.Docs.Themes.Default

Loads theme templates, CSS, JS, and assets from the theme directory. Supports both embedded default theme and custom theme directories.

Constructors

NameDescription
ThemeLoader(IFileSystem fileSystem, ThemeLoader> logger) Loads theme templates, CSS, JS, and assets from the theme directory. Supports both embedded default theme and custom theme directories.

ThemeLoader(IFileSystem fileSystem, ThemeLoader> logger)

ThemeLoader.ThemeLoader(IFileSystem fileSystem, ILogger<ThemeLoader> logger)

Loads theme templates, CSS, JS, and assets from the theme directory. Supports both embedded default theme and custom theme directories.

Methods

NameDescription
CopyAssets(string themePath, string outputDir) Copies all theme static assets (CSS, JS, fonts, icons) to the output directory.
Load(string themePath) Loads a theme render context from the specified theme directory.

CopyAssets(string themePath, string outputDir)

void ThemeLoader.CopyAssets(string themePath, string outputDir)

Copies all theme static assets (CSS, JS, fonts, icons) to the output directory.

Parameters

NameTypeDescription
themePathstringSource theme directory.
outputDirstringTarget output directory.

Load(string themePath)

ThemeRenderContext ThemeLoader.Load(string themePath)

Loads a theme render context from the specified theme directory.

Parameters

NameTypeDescription
themePathstringAbsolute path to the theme directory.

Returns: The loaded theme context with templates, partials, and asset lists.

View Source
/// <summary>
///     Loads theme templates, CSS, JS, and assets from the theme directory.
///     Supports both embedded default theme and custom theme directories.
/// </summary>
public sealed class ThemeLoader(IFileSystem fileSystem, ILogger<ThemeLoader> logger)
{
    /// <summary>
    ///     Loads a theme render context from the specified theme directory.
    /// </summary>
    /// <param name = "themePath">Absolute path to the theme directory.</param>
    /// <returns>The loaded theme context with templates, partials, and asset lists.</returns>
    public ThemeRenderContext Load(string themePath)
    {
        var templates = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        var partials = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        var cssFiles = new List<string>();
        var jsFiles = new List<string>();
        // Load layout templates
        string layoutsDir = fileSystem.Path.Combine(themePath, "layouts");
        if (fileSystem.Directory.Exists(layoutsDir))
        {
            foreach (string file in fileSystem.Directory.GetFiles(layoutsDir, "*.html"))
            {
                string name = fileSystem.Path.GetFileNameWithoutExtension(file);
                templates[name] = fileSystem.File.ReadAllText(file);
                logger.LogDebug("Loaded layout: {Name}", name);
            }
        }

        // Load partials
        string partialsDir = fileSystem.Path.Combine(themePath, "partials");
        if (fileSystem.Directory.Exists(partialsDir))
        {
            foreach (string file in fileSystem.Directory.GetFiles(partialsDir, "*.html"))
            {
                string name = fileSystem.Path.GetFileNameWithoutExtension(file);
                partials[name] = fileSystem.File.ReadAllText(file);
                logger.LogDebug("Loaded partial: {Name}", name);
            }
        }

        // Discover CSS files
        string cssDir = fileSystem.Path.Combine(themePath, "css");
        if (fileSystem.Directory.Exists(cssDir))
        {
            cssFiles = fileSystem.Directory.GetFiles(cssDir, "*.css", SearchOption.AllDirectories).Select(f => "/_theme/" + fileSystem.Path.GetRelativePath(themePath, f).Replace('\\', '/')).OrderBy(f => f) // main.css first via alphabetical
            .ToList();
        }

        // Discover JS files
        string jsDir = fileSystem.Path.Combine(themePath, "js");
        if (fileSystem.Directory.Exists(jsDir))
        {
            jsFiles = fileSystem.Directory.GetFiles(jsDir, "*.js").Select(f => "/_theme/" + fileSystem.Path.GetRelativePath(themePath, f).Replace('\\', '/')).OrderBy(f => f).ToList();
        }

        logger.LogInformation("Loaded theme: {Layouts} layouts, {Partials} partials, {Css} CSS, {Js} JS", templates.Count, partials.Count, cssFiles.Count, jsFiles.Count);
        return new ThemeRenderContext
        {
            Config = null!, // Will be set by the render phase
            Templates = templates,
            Partials = partials,
            CssFiles = cssFiles,
            JsFiles = jsFiles
        };
    }

    /// <summary>
    ///     Copies all theme static assets (CSS, JS, fonts, icons) to the output directory.
    /// </summary>
    /// <param name = "themePath">Source theme directory.</param>
    /// <param name = "outputDir">Target output directory.</param>
    public void CopyAssets(string themePath, string outputDir)
    {
        string themeOutputDir = fileSystem.Path.Combine(outputDir, "_theme");
        string[] assetDirs = new[]
        {
            "css",
            "js",
            "assets"
        };
        foreach (string dir in assetDirs)
        {
            string sourceDir = fileSystem.Path.Combine(themePath, dir);
            if (!fileSystem.Directory.Exists(sourceDir))
            {
                continue;
            }

            string[] files = fileSystem.Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                string relativePath = fileSystem.Path.GetRelativePath(themePath, file);
                string destPath = fileSystem.Path.Combine(themeOutputDir, relativePath);
                string destDir = fileSystem.Path.GetDirectoryName(destPath)!;
                fileSystem.Directory.CreateDirectory(destDir);
                fileSystem.File.Copy(file, destPath, true);
            }
        }

        logger.LogInformation("Copied theme assets to {Path}", themeOutputDir);
    }
}
Was this page helpful?