How can i create a less file, with all the modules active on the website?

Hello im finding out how i can create a less file, with all the modules active on the website.

I like to generate a efficient main css file with no modules that are inactive/not used on the website.

So for i came up with the following code.

The hook will look for page updates, $site->moduleList() will list the active modules.

This will make or overwrite modules.less

f::write( kirby()->roots()->assets() . '/less/modules.less' , $content , false); 

This code is a draft/doesn’t work.

kirby()->hook('panel.page.update', function($page) {

$kirby->plugin('modules');

$templates = $site->moduleList()->pluck('template', null, true);
    
$less = array_map(function($template) {
  return '@import' . $template . '.less' . ';' . '\n';
}, $templates);    
    
$content = $less;   
    
    
f::write( kirby()->roots()->assets() . '/less/modules.less' , $content , false); 

}); 

the result should be a modules.less file with the active modules,

@import "modules/accordion.less";
@import "modules/pricing-cards.less";
@import "modules/image-carousel.less";
@import "modules/tabs.less";
@import "modules/progress-tracker.less";
@import "modules/testimonials.less";
@import "modules/image-hero.less";

Im wondering where it goes wrong, can someone help me with this?

The $page->moduleList() method only returns the modules of the given page. So if you call $site->moduleList(), you don’t get the modules that are used on the site, but you get the modules on the top-level (which doesn’t make sense as the $site doesn’t have a template and therefore also no modules on its own).

To get a list of “active” modules, you need to loop through the site’s index like this:

$activeModules = [];
foreach(site()->index()->filterBy('isModule', true) as $m) {
  $moduleName = $m->module()->name();
  if(!in_array($moduleName, $activeModules)) $activeModules[] = $moduleName;
}

Embedded into a hook this would look something like this (untested!):

kirby()->hook('panel.page.*', function() {
  // get a list of modules that are currently active in the site
  $activeModules = [];
  foreach(site()->index()->filterBy('isModule', true) as $m) {
    $moduleName = $m->module()->name();
    if(!in_array($moduleName, $activeModules)) $activeModules[] = $moduleName;
  }
  
  // convert the list to a LESS string
  $content = array_reduce($activeModules, function($carry, $template) {
    return $carry . '@import' . $template . ".less;\n";
  }, '');
  
  // write the LESS file
  f::write(kirby()->roots()->assets() . DS . 'less' . DS . 'modules.less', $content);
});

You could optimize this to only update the LESS file with the changes from the page that called the hook. That would be a lot faster to process (better performance), but more complex to implement.

Hello Lukas,

Many thanks!
I need to debug it further… until now i’ve tested the following.

This part of de hook works in config.php

kirby()->hook('panel.page.*', function() {


  
  // convert the list to a LESS string
  $content = 'test12'; 
  
  // write the LESS file
  f::write(kirby()->roots()->assets() . DS . 'less' . DS . 'modules.less', $content, false);
});

This Part works on a page, but not in the hook.

<?php
$activeModules = [];
  foreach($site->index()->filterBy('isModule', true) as $m) {
    $moduleName = $m->module()->name();
    if(!in_array($moduleName, $activeModules)) $activeModules[] = $moduleName;
  }
  
  // convert the list to a LESS string
  $content = array_reduce($activeModules, function($carry, $template) {
    return $carry . '@import' . '"' . $template . '.less";' . "\n";
  }, '');


// write the LESS file
  f::write(kirby()->roots()->assets() . DS . 'less' . DS . '_md.less', $content, false); 

?>

Do you get an error message? My first thought would be that the plugin doesn’t get loaded correctly in the Panel.

By the way: You don’t need to pass the third param to f::write(). false is the default anyway. :slight_smile:

I didn’t got a error message, in the hook i changed $site to site() .

Now it works, extremely happy!

Cheers, Maarten

kirby()->hook('panel.page.*', function() {

    
$activeModules = [];
  foreach(site()->index()->filterBy('isModule', true) as $m) {
    $moduleName = $m->module()->name();
    if(!in_array($moduleName, $activeModules)) $activeModules[] = $moduleName;
  }
  
  // convert the list to a LESS string
  $content = array_reduce($activeModules, function($carry, $template) {
    return $carry . '@import' . ' "' . $template . '.less";' . "\n";
  }, '');
  
  // write the LESS file
  f::write(kirby()->roots()->assets() . DS . 'less' . DS . '_modules.less', $content, false);
});
``

Oh, of course. :slight_smile:
Glad it works now.

1 Like

Hi there,

are there any additional plugin needed to get this gem running? Can’t get this to work, but its exactly what i need :smiley:

Thanks
Fabian

@gfx_dude Do you mean other plugins in addition to the modules plugin?

@texnixe right. i’m using the modules plugin already and i also want to load css/less only if the module is active. this here seems to be a pretty usefull solution