Laravel Themes Manager

repository·master·Indexed 41 days ago

https://github.com/hexadog/laravel-themes-manager

A package for developing multi-theme Laravel applications. It provides tools for theme scaffolding via `theme:make`, theme discovery through `ThemeFinder`, and a `ThemeLoader` middleware to apply active themes to requests. Includes Blade components and directives for resolving theme-specific assets, styles, scripts, and page titles, as well as facades for managing active themes.

Tokens
4.7K
Snippets
21
Records
23
Agent score
51%

What's inside Laravel Themes Manager

  1. Configure the themes directory

    master

    The ThemeFinder uses the themes-manager.directory configuration key to determine where to look for theme packages. If this key is not set, it defaults to the themes directory at the root of your Laravel application (base_path('themes')).

    // In config/themes-manager.php
    return [
        'directory' => 'custom_themes_folder', // Defaults to 'themes'
    ];
  2. Use the <x-script> Blade component to render theme assets

    master

    The <x-script> Blade component is used to render script tags with URLs resolved through the ThemesManager. It automatically handles asset path resolution based on the active theme.

    Pass the relative path to the script as the src attribute. By default, the component generates an absolute URL. You can toggle this behavior using the absolute boolean attribute.

    {{-- Renders an absolute URL to the script --}}
    <x-script src="js/app.js" />
    
    {{-- Renders a relative URL to the script --}}
    <x-script src="js/app.js" :absolute="false" />
  3. Locate and resolve available themes with ThemeFinder::find()

    master

    The ThemeFinder::find() method scans the configured themes directory to identify and instantiate available theme packages. It looks for directories containing a composer.json file (up to 2 levels deep) and ignores node_modules and vendor directories.

    For each discovered package, it extracts metadata from composer.json to create a Theme object. The following metadata is mapped:

    • name: The unique identifier for the theme.
    • version: The theme version (defaults to 0.1).
    • description: A brief description of the theme.
    • extra.theme.parent: The parent theme identifier.
    • extra.theme: An array of additional theme configuration.
    • extra.theme.screenshot: A path or URL to a theme screenshot.

    The method returns an Illuminate Support\ Collection of Theme objects, keyed by the theme's name.

    use Hexadog\ThemesManager\ThemeFinder;
    
    // Returns a collection of Theme objects keyed by their name
    $themes = ThemeFinder::find();
    
    foreach ($themes as $name => $theme) {
        echo "Found theme: " . $name . " (Version: " . $theme->getVersion() . ")\n";
    }
  4. Manage active themes with ThemesManager

    master

    The ThemesManager class is the primary entrypoint for controlling which theme is currently active in your Laravel application. You can retrieve all available themes, check for existence, or switch the active theme.

    • all(): Returns a Collection of all scanned themes.
    • has(?string $name): Checks if a theme with the specified name exists.
    • get(?string $name): Retrieves a specific Theme instance by name. If no name is provided, it returns all themes.
    • set(string $name): Sets a new active theme. This method disables the current theme before enabling the new one. It throws a ThemeNotFoundException if the theme does not exist.
    • current(): Returns the currently enabled Theme instance.
    • enable(string $name, bool $withEvent = true): Enables a specific theme by name.
    • disable(string $name, bool $withEvent = true): Disables a specific theme by name.
    // Get all themes
    $themes = $themesManager->all();
    
    // Check if a theme exists
    if ($themesManager->has('my-theme')) {
        // Switch to the theme
        $themesManager->set('my-theme');
    }
    
    // Get the currently active theme
    $currentTheme = $themesManager->current();
  5. Use ThemeLoader middleware to apply themes to requests

    master

    The ThemeLoader middleware is responsible for detecting and applying the active theme to an incoming HTTP request.

    Behavior:

    • Exclusions: It automatically skips theme loading if the request expects JSON ($request->expectsJson()) or if the application is running in the console (app()->runningInConsole()).
    • Explicit Theme: If a theme name is passed as a parameter to the middleware, it sets that theme using ThemesManager::set($theme).
    • Fallback Theme: If no theme is explicitly provided, the middleware attempts to load the theme defined in the themes-manager.fallback_theme configuration key.

    To use it, register the middleware in your app/Http/Kernel.php or within your route definitions.

    // Example: Applying a specific theme to a route group
    Route::middleware(['theme:dark'])->group(function () {
        // Routes in this group will use the 'dark' theme
    });
  6. Use the <x-style /> Blade component to render theme assets

    master

    The <x-style /> Blade component is used to render theme-specific style URLs. It automatically resolves the provided source path to the correct asset URL using the ThemesManager::asset() method.

    Pass the relative path to the asset as the src attribute. By default, the component resolves the path as an absolute URL (absolute = true).

    {{-- Render an absolute theme asset URL --}}
    <link rel="stylesheet" href="<x-style src="css/theme.css" />">
    
    {{-- Render a relative theme asset URL --}}
    <link rel="stylesheet" href="<x-style src="css/theme.css" :absolute="false" />">
  7. Find themes by name and vendor

    master

    The findByName method allows you to locate a specific theme. It handles name normalization by stripping -theme or theme- suffixes.

    It supports finding themes using:

    • Simple Name: Matches the theme name (case-insensitive).
    • Vendor Prefix: If the name contains a / (e.g., vendor/name), it treats the part before the slash as the vendor and the part after as the theme name.
    • Explicit Vendor: You can pass a separate $vendor string to the method to narrow the search.
    // Find by simple name
    $theme = $themesManager->findByName('my-theme');
    
    // Find by vendor/name syntax
    $theme = $themesManager->findByName('hexadog/default');
    
    // Find by name with explicit vendor parameter
    $theme = $themesManager->findByName('default', 'hexadog');
  8. Generate theme asset HTML tags

    master

    The ThemesManager provides helper methods to generate HTML tags for assets (CSS, JS, Images) belonging to the currently active theme. This ensures that paths are correctly resolved to the theme's directory.

    • asset(string $asset, bool $absolute = true): Returns the URL for a theme asset.
    • style(string $asset, bool $absolute = true): Returns a <link> HTML tag for a CSS stylesheet.
    • script(string $asset, string $mode = '', bool $absolute = true, string $type = 'text/javascript', string $level = 'functionality'): Returns a <script> HTML tag. Includes data-type and data-level attributes.
    • image(string $asset, string $alt = '', string $class = '', array $attributes = [], bool $absolute = true): Returns an <img> HTML tag with support for alt text, classes, and custom attributes.
    • mix(string $asset, string $manifestDirectory = ''): Returns the path to a versioned asset using Laravel Mix, resolved against the current theme's URL.
    // CSS link tag
    echo $themesManager->style('css/app.css');
    
    // JavaScript script tag
    echo $themesManager->script('js/app.js', '', true, 'module', 'core');
    
    // Image tag
    echo $themesManager->image('images/logo.png', 'Company Logo', 'img-fluid', ['id' => 'logo']);
    
    // Laravel Mix integration
    $url = $themesManager->mix('js/app.js');
  9. Use @pagetitle Blade directive

    master

    The @pagetitle directive generates a <title> tag using the page_title() helper. It accepts two arguments:

    1. $with_app_name (boolean): Whether to include the application name in the title. Defaults to true if not provided or if a truthy value is passed.
    2. $separator (string): The character used to separate the page title from the app name. Defaults to '-' if not provided.

    Note: The first argument must be a boolean literal or a string that can be validated as a boolean.

    {{-- Default: includes app name with '-' separator --}}
    @pagetitle
    
    {{-- Custom: no app name, using ' | ' separator --}}
    @pagetitle(false, ' | ')