Создать ThemeBuilder для динамических тем - PullRequest
0 голосов
/ 01 октября 2019

Я работаю над мультитенантным приложением, в котором есть построитель тем, основанный на их определенных настройках, таких как цвет темы и т. Д.

Я использовал этот подход http://bundletransformer -theme-builder. azurewebsites.net/ для начальной загрузки 3. Однако, поскольку мы обновились до Bootstrap 4, он теперь находится в .scss.

Поэтому мой подход к реализации Bootstrap 4 в проекте заключается в добавлении следующего:

theme / theme-variables.scss

/*
 * Application global variables.
 */


$orcid-color : #96D72F;
$primary-color: #1c223d;

@import "../bootstrap/_functions.scss";
@import "../bootstrap/_variables.scss";

theme / theme.scss

/*
 * Global application theme.
 */
@import "theme-variables";
html,
body {
    height: 100%;
}
body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
// ...

main.scss

/*
 * Entry point of global application style.
 */

// Theme variables, must be included before the libraries to allow overriding defaults
@import "theme/theme-variables";

// 3rd party libraries
@import "bootstrap/bootstrap.scss";


// Theme customization
@import "theme/theme";

Теперь в BundleConfig определено это ниже

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new CustomStyleBundle("~/bundles/styles")
            .Include("~/Contents/main.scss"));
    }
}

Затем создайте следующие коды ..

[Route("bundles/themes/{id}"), AllowAnonymous]
public ContentResult Themes(int id)
{
    var id = 1;
    var institutionPath = string.Format("~/bundles/themes/{0}", id);

    if (BundleTable.Bundles.All(x => x.Path != institutionPath))
    {
        var themeStyles = new CustomStyleBundle(institutionPath)
            .Include("~/Contents/main.scss", new InjectContentItemTransform($"$primary-color: red;"));

        BundleTable.Bundles.Add(themeStyles);
    }

    return null;
}


public sealed class InjectContentItemTransform : IItemTransform
{
    private readonly string _content;

    public InjectContentItemTransform(string content)
    {
        _content = content;
    }

    public string Process(string includedVirtualPath, string input)
    {
        if (!_content.HasValue())
        {
            return input;
        }

        var builder = new StringBuilder();

        builder.Append(_content);

        return builder.ToString();
    }
}

Затем в основном макете ...

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="shortcut icon" href="~/favicon.ico">

    @Styles.Render(string.Format("~/bundles/themes/{0}", 1))

    @Styles.Render("~/bundles/styles")

    <title>@ViewBag.Title</title>
</head>
<body class="body">
    <!-- //.... -->
</body>
</html>

Как правильно добавить переменную или переопределить переменную для применения значения, такого как цвет?

1 Ответ

1 голос
/ 02 октября 2019

Sass, в отличие от LESS, не поддерживает изменение значений переменных, поэтому с помощью преобразования элемента мы можем только определять переменные.

Во-первых, вам следует удалить определение переменной из файла theme/theme-variables.scss:

/*
 * Application global variables.
 */


$orcid-color : #96D72F;
//$primary-color: #1c223d;

@import "../bootstrap/_functions.scss";
@import "../bootstrap/_variables.scss";

Ваша реализация класса InjectContentItemTransform содержит ошибку: в определение содержимого пакета всегда включаются только определения переменных. Вот правильная реализация:

public sealed class InjectContentItemTransform : IItemTransform
{
    private readonly string _content;

    public InjectContentItemTransform(string content)
    {
        _content = content;
    }

    public string Process(string includedVirtualPath, string input)
    {
        if (!_content.HasValue())
        {
            return input;
        }

        var builder = new StringBuilder();
        builder.AppendLine(_content);
        builder.Append(input);

        return builder.ToString();
    }
}

Чтобы преобразования элементов применялись в режиме отладки, необходимо зарегистрировать пользовательский преобразователь пакетов:

…
using BundleTransformer.Core.Resolvers;
…

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        BundleResolver.Current = new CustomBundleResolver();
        …
    }
}

Многие разработчики, которые создают мультитенантвеб-приложение должно написать собственную реализацию интерфейса System.Web.Optimization.IBundleCache, класс System.Web.Hosting.VirtualPathProvider и собственную версию класса BundleTransformer.SassAndScss.HttpHandlers.SassAndScssAssetHandler с переопределенным методом GetCacheKey. Я рекомендую вам ознакомиться с исходным кодом проекта SmartStore.NET .

...