Merge branch 'version/03'
This commit is contained in:
4
.github/workflows/changelog-validation.yml
vendored
4
.github/workflows/changelog-validation.yml
vendored
@@ -19,9 +19,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- version/*
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
||||
9
.github/workflows/ci-joomla.yml
vendored
9
.github/workflows/ci-joomla.yml
vendored
@@ -19,14 +19,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev/**
|
||||
- rc/**
|
||||
- version/**
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- dev/**
|
||||
- rc/**
|
||||
- version/*
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
||||
9
.github/workflows/codeql-analysis.yml
vendored
9
.github/workflows/codeql-analysis.yml
vendored
@@ -21,14 +21,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev/**
|
||||
- rc/**
|
||||
- version/**
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- dev/**
|
||||
- rc/**
|
||||
- version/*
|
||||
schedule:
|
||||
# Weekly on Monday at 06:00 UTC
|
||||
- cron: '0 6 * * 1'
|
||||
|
||||
4
.github/workflows/standards-compliance.yml
vendored
4
.github/workflows/standards-compliance.yml
vendored
@@ -89,9 +89,7 @@ env:
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev/**, rc/**, version/**]
|
||||
pull_request:
|
||||
branches: [main, dev/**, rc/**]
|
||||
branches: [main, version/*]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
||||
6
.github/workflows/update-server.yml
vendored
6
.github/workflows/update-server.yml
vendored
@@ -22,10 +22,8 @@ name: Update Joomla Update Server XML Feed
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'dev/**'
|
||||
- 'alpha/**'
|
||||
- 'beta/**'
|
||||
- 'rc/**'
|
||||
- main
|
||||
- version/*
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'htdocs/**'
|
||||
|
||||
@@ -10,49 +10,20 @@
|
||||
/**
|
||||
* Default layout override for mod_breadcrumbs.
|
||||
* Bootstrap 5 breadcrumb with schema.org BreadcrumbList markup.
|
||||
* Respects showHome, showLast, homeText module settings.
|
||||
* Module settings (showHome, showLast, homeText) are handled by Joomla core
|
||||
* before $list reaches this template.
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
Factory::getApplication()->getLanguage()->load('mod_breadcrumbs', JPATH_SITE);
|
||||
|
||||
$suffix = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
$headerTag = htmlspecialchars($params->get('header_tag', 'h3'), ENT_COMPAT, 'UTF-8');
|
||||
$headerClass = htmlspecialchars($params->get('header_class', ''), ENT_COMPAT, 'UTF-8');
|
||||
$showHome = $params->get('showHome', 1);
|
||||
$showLast = $params->get('showLast', 1);
|
||||
$homeText = $params->get('homeText', '') ?: Text::_('MOD_BREADCRUMBS_HOME');
|
||||
$showHere = $params->get('showHere', 1);
|
||||
|
||||
// Build filtered list respecting module settings
|
||||
$items = [];
|
||||
$count = count($list);
|
||||
|
||||
foreach ($list as $key => $item) {
|
||||
// Skip Home item if showHome is off
|
||||
if ($key === 0 && !$showHome) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Replace Home text if custom homeText is set
|
||||
if ($key === 0 && $showHome) {
|
||||
$item->name = $homeText;
|
||||
}
|
||||
|
||||
// Skip last item if showLast is off
|
||||
if ($key === $count - 1 && !$showLast) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$items[] = $item;
|
||||
}
|
||||
|
||||
if (empty($items)) {
|
||||
if (empty($list)) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
@@ -60,9 +31,12 @@ if (empty($items)) {
|
||||
<?php if ($module->showtitle) : ?>
|
||||
<<?php echo $headerTag; ?> class="mod-breadcrumbs__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
|
||||
<?php endif; ?>
|
||||
<?php if ($showHere) : ?>
|
||||
<span class="mod-breadcrumbs__here"><?php echo Text::_('MOD_BREADCRUMBS_HERE'); ?></span>
|
||||
<?php endif; ?>
|
||||
<ol class="breadcrumb" itemscope itemtype="https://schema.org/BreadcrumbList">
|
||||
<?php foreach ($items as $key => $item) : ?>
|
||||
<?php $isLast = ($key === array_key_last($items)); ?>
|
||||
<?php foreach ($list as $key => $item) : ?>
|
||||
<?php $isLast = ($key === array_key_last($list)); ?>
|
||||
<li class="breadcrumb-item<?php echo $isLast ? ' active' : ''; ?>" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"
|
||||
<?php echo $isLast ? ' aria-current="page"' : ''; ?>>
|
||||
<?php if (!$isLast && !empty($item->link)) : ?>
|
||||
|
||||
106
src/html/mod_menu/horizontal.php
Normal file
106
src/html/mod_menu/horizontal.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main Menu - Mobile responsive collapsible dropdown menu override
|
||||
* Bootstrap 5 responsive navbar with hamburger menu
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Helper\ModuleHelper;
|
||||
|
||||
$id = '';
|
||||
|
||||
if ($tagId = $params->get('tag_id', '')) {
|
||||
$id = ' id="' . $tagId . '"';
|
||||
}
|
||||
|
||||
// Get module class suffix
|
||||
$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
// The menu class is deprecated. Use mod-menu instead
|
||||
?>
|
||||
<nav class="mod-menu mod-menu-main navbar navbar-expand-lg<?php echo $moduleclass_sfx; ?>"<?php echo $id; ?>>
|
||||
<div class="container-fluid">
|
||||
<!-- Hamburger toggle button for mobile -->
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#horizontalMenuCollapse-<?php echo $module->id; ?>" aria-controls="horizontalMenuCollapse-<?php echo $module->id; ?>" aria-expanded="false" aria-label="Toggle Menu">
|
||||
<span class="fa-solid fa-bars" aria-hidden="true"></span>
|
||||
</button>
|
||||
|
||||
<!-- Collapsible menu content -->
|
||||
<div class="collapse navbar-collapse" id="horizontalMenuCollapse-<?php echo $module->id; ?>">
|
||||
<ul class="navbar-nav mod-menu-main__list">
|
||||
<?php foreach ($list as $i => &$item) :
|
||||
$itemParams = $item->getParams();
|
||||
$class = 'nav-item mod-menu-main__item item-' . $item->id;
|
||||
|
||||
if ($item->id == $default_id) {
|
||||
$class .= ' default';
|
||||
}
|
||||
|
||||
if ($item->id == $active_id || ($item->type === 'alias' && $itemParams->get('aliasoptions') == $active_id)) {
|
||||
$class .= ' current';
|
||||
}
|
||||
|
||||
if (in_array($item->id, $path)) {
|
||||
$class .= ' active';
|
||||
} elseif ($item->type === 'alias') {
|
||||
$aliasToId = $itemParams->get('aliasoptions');
|
||||
|
||||
if (count($path) > 0 && $aliasToId == $path[count($path) - 1]) {
|
||||
$class .= ' active';
|
||||
} elseif (in_array($aliasToId, $path)) {
|
||||
$class .= ' alias-parent-active';
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->type === 'separator') {
|
||||
$class .= ' divider';
|
||||
}
|
||||
|
||||
if ($item->deeper) {
|
||||
$class .= ' deeper dropdown';
|
||||
}
|
||||
|
||||
if ($item->parent) {
|
||||
$class .= ' parent';
|
||||
}
|
||||
|
||||
echo '<li class="' . $class . '">';
|
||||
|
||||
switch ($item->type) :
|
||||
case 'separator':
|
||||
case 'component':
|
||||
case 'heading':
|
||||
case 'url':
|
||||
require ModuleHelper::getLayoutPath('mod_menu', 'horizontal_' . $item->type);
|
||||
break;
|
||||
|
||||
default:
|
||||
require ModuleHelper::getLayoutPath('mod_menu', 'horizontal_url');
|
||||
break;
|
||||
endswitch;
|
||||
|
||||
// The next item is deeper.
|
||||
if ($item->deeper) {
|
||||
echo '<ul class="dropdown-menu mod-menu-main__dropdown">';
|
||||
} elseif ($item->shallower) {
|
||||
// The next item is shallower.
|
||||
echo '</li>';
|
||||
echo str_repeat('</ul></li>', $item->level_diff);
|
||||
} else {
|
||||
// The next item is on the same level.
|
||||
echo '</li>';
|
||||
}
|
||||
endforeach;
|
||||
?></ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
66
src/html/mod_menu/horizontal_component.php
Normal file
66
src/html/mod_menu/horizontal_component.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main Menu - Component item layout
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Filter\OutputFilter;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
$attributes = [];
|
||||
|
||||
if ($item->anchor_title) {
|
||||
$attributes['title'] = $item->anchor_title;
|
||||
}
|
||||
|
||||
if ($item->anchor_css) {
|
||||
$attributes['class'] = $item->anchor_css;
|
||||
}
|
||||
|
||||
if ($item->anchor_rel) {
|
||||
$attributes['rel'] = $item->anchor_rel;
|
||||
}
|
||||
|
||||
$linktype = $item->title;
|
||||
|
||||
if ($item->menu_icon) {
|
||||
// The link is an icon
|
||||
if ($itemParams->get('menu_text', 1)) {
|
||||
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||
} else {
|
||||
// If the icon itself is the link, it needs a visually hidden text
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->browserNav == 1) {
|
||||
$attributes['target'] = '_blank';
|
||||
$attributes['rel'] = 'noopener noreferrer';
|
||||
} elseif ($item->browserNav == 2) {
|
||||
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
|
||||
|
||||
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
|
||||
}
|
||||
|
||||
// Add dropdown toggle for items with children
|
||||
$linkClass = 'nav-link mod-menu-main__link';
|
||||
if ($item->deeper) {
|
||||
$linkClass .= ' dropdown-toggle';
|
||||
$attributes['data-bs-toggle'] = 'dropdown';
|
||||
$attributes['role'] = 'button';
|
||||
$attributes['aria-expanded'] = 'false';
|
||||
}
|
||||
|
||||
$attributes['class'] = $linkClass;
|
||||
|
||||
echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
|
||||
39
src/html/mod_menu/horizontal_heading.php
Normal file
39
src/html/mod_menu/horizontal_heading.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main Menu - Heading item layout
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : '';
|
||||
$anchor_css = $item->anchor_css ?: '';
|
||||
|
||||
$linktype = $item->title;
|
||||
|
||||
if ($item->menu_icon) {
|
||||
// The link is an icon
|
||||
if ($itemParams->get('menu_text', 1)) {
|
||||
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||
} else {
|
||||
// If the icon itself is the link, it needs a visually hidden text
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
// Add dropdown toggle for items with children
|
||||
$headingClass = 'nav-link mod-menu-main__heading';
|
||||
if ($item->deeper) {
|
||||
$headingClass .= ' dropdown-toggle';
|
||||
}
|
||||
|
||||
?>
|
||||
<span class="<?php echo $headingClass . ' ' . $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
|
||||
33
src/html/mod_menu/horizontal_separator.php
Normal file
33
src/html/mod_menu/horizontal_separator.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main Menu - Separator item layout
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : '';
|
||||
$anchor_css = $item->anchor_css ?: '';
|
||||
|
||||
$linktype = $item->title;
|
||||
|
||||
if ($item->menu_icon) {
|
||||
// The link is an icon
|
||||
if ($itemParams->get('menu_text', 1)) {
|
||||
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||
} else {
|
||||
// If the icon itself is the link, it needs a visually hidden text
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<span class="dropdown-divider mod-menu-main__separator <?php echo $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
|
||||
71
src/html/mod_menu/horizontal_url.php
Normal file
71
src/html/mod_menu/horizontal_url.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main Menu - URL item layout
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Filter\OutputFilter;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
$attributes = [];
|
||||
|
||||
if ($item->anchor_title) {
|
||||
$attributes['title'] = $item->anchor_title;
|
||||
}
|
||||
|
||||
if ($item->anchor_css) {
|
||||
$attributes['class'] = $item->anchor_css;
|
||||
}
|
||||
|
||||
if ($item->anchor_rel) {
|
||||
$attributes['rel'] = $item->anchor_rel;
|
||||
}
|
||||
|
||||
$linktype = $item->title;
|
||||
|
||||
if ($item->menu_icon) {
|
||||
// The link is an icon
|
||||
if ($itemParams->get('menu_text', 1)) {
|
||||
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||
} else {
|
||||
// If the icon itself is the link, it needs a visually hidden text
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->browserNav == 1) {
|
||||
$attributes['target'] = '_blank';
|
||||
$attributes['rel'] = 'noopener noreferrer';
|
||||
} elseif ($item->browserNav == 2) {
|
||||
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
|
||||
|
||||
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
|
||||
}
|
||||
|
||||
// Add dropdown toggle for items with children
|
||||
$linkClass = 'nav-link mod-menu-main__link';
|
||||
if ($item->deeper) {
|
||||
$linkClass .= ' dropdown-toggle';
|
||||
$attributes['data-bs-toggle'] = 'dropdown';
|
||||
$attributes['role'] = 'button';
|
||||
$attributes['aria-expanded'] = 'false';
|
||||
}
|
||||
|
||||
// Merge existing class with our class
|
||||
if (isset($attributes['class'])) {
|
||||
$attributes['class'] .= ' ' . $linkClass;
|
||||
} else {
|
||||
$attributes['class'] = $linkClass;
|
||||
}
|
||||
|
||||
echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
|
||||
@@ -30,12 +30,12 @@ $moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COM
|
||||
<nav class="mod-menu mod-menu-main navbar navbar-expand-lg<?php echo $moduleclass_sfx; ?>"<?php echo $id; ?>>
|
||||
<div class="container-fluid">
|
||||
<!-- Hamburger toggle button for mobile -->
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainMenuCollapse" aria-controls="mainMenuCollapse" aria-expanded="false" aria-label="Toggle Main Menu">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainMenuCollapse-<?php echo $module->id; ?>" aria-controls="mainMenuCollapse-<?php echo $module->id; ?>" aria-expanded="false" aria-label="Toggle Main Menu">
|
||||
<span class="fa-solid fa-bars" aria-hidden="true"></span>
|
||||
</button>
|
||||
|
||||
<!-- Collapsible menu content -->
|
||||
<div class="collapse navbar-collapse" id="mainMenuCollapse">
|
||||
<div class="collapse navbar-collapse" id="mainMenuCollapse-<?php echo $module->id; ?>">
|
||||
<ul class="navbar-nav mod-menu-main__list">
|
||||
<?php foreach ($list as $i => &$item) :
|
||||
$itemParams = $item->getParams();
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* IMPORTANT: Font files must be downloaded separately
|
||||
*
|
||||
* This CSS file references Fira Sans font files that must be manually downloaded
|
||||
* and placed in the fonts directory. See GOOGLE_FONTS_README.md in the fonts
|
||||
* directory for download instructions.
|
||||
*
|
||||
* Required files:
|
||||
* - fira-sans-v17-latin-100.woff2
|
||||
* - fira-sans-v17-latin-300.woff2
|
||||
* - fira-sans-v17-latin-regular.woff2
|
||||
* - fira-sans-v17-latin-700.woff2
|
||||
*/
|
||||
|
||||
/* Fira Sans Thin (100) */
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/fira-sans-v17-latin-100.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Fira Sans Light (300) */
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/fira-sans-v17-latin-300.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Fira Sans Regular (400) */
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/fira-sans-v17-latin-regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Fira Sans Bold (700) */
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/fira-sans-v17-latin-700.woff2') format('woff2');
|
||||
}
|
||||
10
src/media/css/fonts/fredoka.css
Normal file
10
src/media/css/fonts/fredoka.css
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Fredoka — self-hosted from src/media/fonts/
|
||||
*/
|
||||
|
||||
@font-face { font-family: 'Fredoka'; font-style: normal; font-weight: 300; font-display: swap; src: url('../../fonts/fredoka-v17-latin-300.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Fredoka'; font-style: normal; font-weight: 400; font-display: swap; src: url('../../fonts/fredoka-v17-latin-regular.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Fredoka'; font-style: normal; font-weight: 500; font-display: swap; src: url('../../fonts/fredoka-v17-latin-500.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Fredoka'; font-style: normal; font-weight: 600; font-display: swap; src: url('../../fonts/fredoka-v17-latin-600.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Fredoka'; font-style: normal; font-weight: 700; font-display: swap; src: url('../../fonts/fredoka-v17-latin-700.woff2') format('woff2'); }
|
||||
@@ -1,56 +0,0 @@
|
||||
/* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* IMPORTANT: Font files must be downloaded separately
|
||||
*
|
||||
* This CSS file references Noto Sans font files that must be manually downloaded
|
||||
* and placed in the fonts directory. See GOOGLE_FONTS_README.md in the fonts
|
||||
* directory for download instructions.
|
||||
*
|
||||
* Required files:
|
||||
* - noto-sans-v36-latin-100.woff2
|
||||
* - noto-sans-v36-latin-300.woff2
|
||||
* - noto-sans-v36-latin-regular.woff2
|
||||
* - noto-sans-v36-latin-700.woff2
|
||||
*/
|
||||
|
||||
/* Noto Sans Thin (100) */
|
||||
@font-face {
|
||||
font-family: 'Noto Sans';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/noto-sans-v36-latin-100.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Noto Sans Light (300) */
|
||||
@font-face {
|
||||
font-family: 'Noto Sans';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/noto-sans-v36-latin-300.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Noto Sans Regular (400) */
|
||||
@font-face {
|
||||
font-family: 'Noto Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/noto-sans-v36-latin-regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Noto Sans Bold (700) */
|
||||
@font-face {
|
||||
font-family: 'Noto Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/noto-sans-v36-latin-700.woff2') format('woff2');
|
||||
}
|
||||
6
src/media/css/fonts/pacifico.css
Normal file
6
src/media/css/fonts/pacifico.css
Normal file
@@ -0,0 +1,6 @@
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Pacifico — self-hosted from src/media/fonts/
|
||||
*/
|
||||
|
||||
@font-face { font-family: 'Pacifico'; font-style: normal; font-weight: 400; font-display: swap; src: url('../../fonts/pacifico-v23-latin-regular.woff2') format('woff2'); }
|
||||
@@ -1,56 +1,23 @@
|
||||
/* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Roboto — self-hosted from src/media/fonts/
|
||||
*/
|
||||
|
||||
/*
|
||||
* IMPORTANT: Font files must be downloaded separately
|
||||
*
|
||||
* This CSS file references Roboto font files that must be manually downloaded
|
||||
* and placed in the fonts directory. See GOOGLE_FONTS_README.md in the fonts
|
||||
* directory for download instructions.
|
||||
*
|
||||
* Required files:
|
||||
* - roboto-v30-latin-100.woff2
|
||||
* - roboto-v30-latin-300.woff2
|
||||
* - roboto-v30-latin-regular.woff2
|
||||
* - roboto-v30-latin-700.woff2
|
||||
*/
|
||||
|
||||
/* Roboto Thin (100) */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/roboto-v30-latin-100.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Roboto Light (300) */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/roboto-v30-latin-300.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Roboto Regular (400) */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/roboto-v30-latin-regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Roboto Bold (700) */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../../fonts/roboto-v30-latin-700.woff2') format('woff2');
|
||||
}
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 100; font-display: swap; src: url('../../fonts/roboto-v51-latin-100.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 100; font-display: swap; src: url('../../fonts/roboto-v51-latin-100italic.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 200; font-display: swap; src: url('../../fonts/roboto-v51-latin-200.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 200; font-display: swap; src: url('../../fonts/roboto-v51-latin-200italic.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 300; font-display: swap; src: url('../../fonts/roboto-v51-latin-300.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 300; font-display: swap; src: url('../../fonts/roboto-v51-latin-300italic.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400; font-display: swap; src: url('../../fonts/roboto-v51-latin-regular.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 400; font-display: swap; src: url('../../fonts/roboto-v51-latin-italic.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 500; font-display: swap; src: url('../../fonts/roboto-v51-latin-500.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 500; font-display: swap; src: url('../../fonts/roboto-v51-latin-500italic.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 600; font-display: swap; src: url('../../fonts/roboto-v51-latin-600.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 600; font-display: swap; src: url('../../fonts/roboto-v51-latin-600italic.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 700; font-display: swap; src: url('../../fonts/roboto-v51-latin-700.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 700; font-display: swap; src: url('../../fonts/roboto-v51-latin-700italic.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 800; font-display: swap; src: url('../../fonts/roboto-v51-latin-800.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 800; font-display: swap; src: url('../../fonts/roboto-v51-latin-800italic.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 900; font-display: swap; src: url('../../fonts/roboto-v51-latin-900.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Roboto'; font-style: italic; font-weight: 900; font-display: swap; src: url('../../fonts/roboto-v51-latin-900italic.woff2') format('woff2'); }
|
||||
|
||||
@@ -13987,21 +13987,10 @@ meter {
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 1em;
|
||||
padding-top: 1rem;
|
||||
color: var(--body-bg, #e6ebf1);
|
||||
background-color: var(--nav-bg-color);
|
||||
padding-left: 100px;
|
||||
padding-right: 60px;
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
|
||||
/* Increase footer right padding when floating controls are present */
|
||||
body[data-theme-fab-enabled="1"] .footer {
|
||||
padding-right: 220px;
|
||||
}
|
||||
|
||||
body[data-theme-fab-enabled="1"][data-a11y-toolbar="1"] .footer {
|
||||
padding-right: 420px;
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
.footer .grid-child {
|
||||
@@ -14624,6 +14613,10 @@ iframe {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Module title alignment — apply via module class suffix */
|
||||
.title-center [class*="__title"] { text-align: center; }
|
||||
.title-right [class*="__title"] { text-align: right; }
|
||||
|
||||
/* ── MODULE: Statistics ── */
|
||||
.mod-stats__list {
|
||||
margin: 0;
|
||||
@@ -14760,6 +14753,21 @@ iframe {
|
||||
}
|
||||
|
||||
/* Breadcrumbs module */
|
||||
.mod-breadcrumbs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.mod-breadcrumbs__here {
|
||||
float: left;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
color: var(--body-font-color, #444);
|
||||
padding-right: .15rem;
|
||||
}
|
||||
|
||||
.mod-breadcrumbs .breadcrumb {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
@@ -14853,8 +14861,10 @@ iframe {
|
||||
.container-top-a,
|
||||
.container-top-b,
|
||||
.container-bottom-a,
|
||||
.container-bottom-b {
|
||||
.container-bottom-b,
|
||||
.mod-breadcrumbs {
|
||||
position: relative;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.container-top-a>*,
|
||||
@@ -15771,7 +15781,7 @@ body.wrapper-fluid header>.grid-child {
|
||||
}
|
||||
|
||||
footer .grid-child>div {
|
||||
padding: 1rem 4em;
|
||||
padding: 1rem 0 0;
|
||||
}
|
||||
|
||||
header .grid-child .navbar-brand {
|
||||
|
||||
1143
src/media/css/theme/dark.custom.css
Normal file
1143
src/media/css/theme/dark.custom.css
Normal file
File diff suppressed because it is too large
Load Diff
1152
src/media/css/theme/light.custom.css
Normal file
1152
src/media/css/theme/light.custom.css
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,131 +1,31 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: MokoCassiopeia.Documentation
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
FILE: src/media/fonts/GOOGLE_FONTS_README.md
|
||||
VERSION: 03.09.03
|
||||
BRIEF: Instructions for downloading Google Fonts for self-hosting
|
||||
-->
|
||||
VERSION: 03.09.10
|
||||
-->
|
||||
|
||||
# Google Fonts - Download Instructions
|
||||
# Self-Hosted Google Fonts
|
||||
|
||||
This directory should contain self-hosted Google Font files to eliminate CDN dependencies.
|
||||
Fonts are served locally to avoid external CDN dependencies and improve privacy/performance.
|
||||
|
||||
## ⚠️ Manual Download Required
|
||||
## Available Fonts
|
||||
|
||||
The Google Font `.woff2` files are **NOT included** in the repository and must be downloaded manually before using non-default font schemes.
|
||||
| Font | Weights | Styles | CSS File |
|
||||
|------|---------|--------|----------|
|
||||
| Roboto | 100–900 | Normal + Italic | `css/fonts/roboto.css` |
|
||||
| Fredoka | 300–700 | Normal | `css/fonts/fredoka.css` |
|
||||
| Pacifico | 400 | Normal | `css/fonts/pacifico.css` |
|
||||
| Osaka | — | — | `css/fonts/osaka.css` |
|
||||
|
||||
**Currently Available:**
|
||||
- ✅ Osaka font (local TTF file, included)
|
||||
## Adding New Fonts
|
||||
|
||||
**Requires Manual Download:**
|
||||
- ❌ Roboto fonts (4 weight variants)
|
||||
- ❌ Noto Sans fonts (4 weight variants)
|
||||
- ❌ Fira Sans fonts (4 weight variants)
|
||||
1. Run `php scripts/download-google-fonts.php` or manually download woff2 files
|
||||
2. Place files in `src/media/fonts/`
|
||||
3. Create a CSS file in `src/media/css/fonts/` with `@font-face` declarations
|
||||
4. Register the CSS in `joomla.asset.json`
|
||||
5. Add the font as an option in `templateDetails.xml` font selector
|
||||
|
||||
## Required Font Files
|
||||
## File Naming Convention
|
||||
|
||||
Download the following `.woff2` font files and place them in this directory:
|
||||
`{font-name}-v{version}-latin-{weight}.woff2`
|
||||
|
||||
### Roboto Font Files
|
||||
- `roboto-v30-latin-100.woff2` (Thin)
|
||||
- `roboto-v30-latin-300.woff2` (Light)
|
||||
- `roboto-v30-latin-regular.woff2` (Regular)
|
||||
- `roboto-v30-latin-700.woff2` (Bold)
|
||||
|
||||
### Noto Sans Font Files
|
||||
- `noto-sans-v36-latin-100.woff2` (Thin)
|
||||
- `noto-sans-v36-latin-300.woff2` (Light)
|
||||
- `noto-sans-v36-latin-regular.woff2` (Regular)
|
||||
- `noto-sans-v36-latin-700.woff2` (Bold)
|
||||
|
||||
### Fira Sans Font Files
|
||||
- `fira-sans-v17-latin-100.woff2` (Thin)
|
||||
- `fira-sans-v17-latin-300.woff2` (Light)
|
||||
- `fira-sans-v17-latin-regular.woff2` (Regular)
|
||||
- `fira-sans-v17-latin-700.woff2` (Bold)
|
||||
|
||||
## How to Download
|
||||
|
||||
### Option 1: Using google-webfonts-helper (Recommended)
|
||||
|
||||
1. Visit https://gwfh.mranftl.com/
|
||||
2. Search for each font (Roboto, Noto Sans, Fira Sans)
|
||||
3. Select character sets: **latin** (or add latin-ext if needed)
|
||||
4. Select styles:
|
||||
- ☑ 100 (thin)
|
||||
- ☑ 300 (light)
|
||||
- ☑ 400 (regular)
|
||||
- ☑ 700 (bold)
|
||||
5. In step 3, ensure **Modern Browsers** is selected (woff2 format)
|
||||
6. In step 4, click **Download files**
|
||||
7. Extract the `.woff2` files to this directory
|
||||
|
||||
### Option 2: Using google-font-installer (Node.js)
|
||||
|
||||
```bash
|
||||
npm install -g google-font-installer
|
||||
cd src/media/fonts/
|
||||
|
||||
# Download Roboto
|
||||
google-font-installer Roboto:100,300,400,700
|
||||
|
||||
# Download Noto Sans
|
||||
google-font-installer "Noto Sans:100,300,400,700"
|
||||
|
||||
# Download Fira Sans
|
||||
google-font-installer "Fira Sans:100,300,400,700"
|
||||
```
|
||||
|
||||
### Option 3: Manual Download Script (Linux/macOS)
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Run this from src/media/fonts/ directory
|
||||
|
||||
download_font() {
|
||||
local font_url="$1"
|
||||
local output_dir="."
|
||||
|
||||
# Download CSS
|
||||
css=$(curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" "$font_url")
|
||||
|
||||
# Extract and download woff2 files
|
||||
echo "$css" | grep -oP 'https://fonts\.gstatic\.com[^\)]*\.woff2' | while read url; do
|
||||
filename=$(basename "$url")
|
||||
echo "Downloading $filename..."
|
||||
curl -s "$url" -o "$output_dir/$filename"
|
||||
done
|
||||
}
|
||||
|
||||
download_font "https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;700&display=swap"
|
||||
download_font "https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&display=swap"
|
||||
download_font "https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&display=swap"
|
||||
```
|
||||
|
||||
## Font CSS Files
|
||||
|
||||
The corresponding CSS files with `@font-face` declarations are located in:
|
||||
- `../css/fonts/roboto.css`
|
||||
- `../css/fonts/noto-sans.css`
|
||||
- `../css/fonts/fira-sans.css`
|
||||
|
||||
These CSS files reference the `.woff2` files in this directory.
|
||||
|
||||
## License
|
||||
|
||||
All Google Fonts are open source and licensed under the SIL Open Font License (OFL).
|
||||
- Roboto: Apache License 2.0
|
||||
- Noto Sans: SIL Open Font License 1.1
|
||||
- Fira Sans: SIL Open Font License 1.1
|
||||
|
||||
## References
|
||||
|
||||
- Google Fonts: https://fonts.google.com/
|
||||
- google-webfonts-helper: https://gwfh.mranftl.com/
|
||||
- Font Licensing: https://fonts.google.com/attribution
|
||||
Examples: `roboto-v51-latin-regular.woff2`, `fredoka-v17-latin-700.woff2`
|
||||
|
||||
@@ -36,13 +36,13 @@
|
||||
</server>
|
||||
</updateservers>
|
||||
<name>MokoCassiopeia</name>
|
||||
<version>03.09.09</version>
|
||||
<version>03.09.12</version>
|
||||
<scriptfile>script.php</scriptfile>
|
||||
<creationDate>2026-03-26</creationDate>
|
||||
<author>Jonathan Miller || Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<copyright>(C)GNU General Public License Version 3 - 2026 Moko Consulting</copyright>
|
||||
<description><![CDATA[<h3>MokoCassiopeia Template Description</h3> <p> <strong>MokoCassiopeia</strong> continues Joomla's tradition of space-themed default templates— building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5), and <em>Protostar</em> (Joomla 3.0). </p> <p> This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting. </p> <h4>Custom Colour Themes</h4> <p> Starter palette files are included with the template. To create a custom colour scheme, copy <code>templates/mokocassiopeia/templates/light.custom.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/light.custom.css</code>, or <code>templates/mokocassiopeia/templates/dark.custom.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/dark.custom.css</code>. Customise the CSS variables to match your brand, then activate your palette in <em>System → Site Templates → MokoCassiopeia → Theme tab</em> by selecting "Custom" for the Light or Dark Mode Palette. A full variable reference is available in the <em>CSS Variables</em> tab in template options. </p> <h4>Custom CSS & JavaScript</h4> <p> For site-specific styles and scripts that should survive template updates, create the following files: </p> <ul> <li><code>media/templates/site/mokocassiopeia/css/user.css</code> — loaded on every page for custom CSS overrides.</li> <li><code>media/templates/site/mokocassiopeia/js/user.js</code> — loaded on every page for custom JavaScript.</li> </ul> <p> These files are gitignored and will not be overwritten by template updates. </p> <h4>Code Attribution</h4> <p> This template is based on the original <strong>Cassiopeia</strong> template developed by the <a href="https://www.joomla.org" target="_blank" rel="noopener">Joomla! Project</a> and released under the GNU General Public License. </p> <p> Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. </p> <p> It includes integration with <a href="https://afeld.github.io/bootstrap-toc/" target="_blank" rel="noopener">Bootstrap TOC</a>, an open-source table of contents generator by A. Feld, licensed under the MIT License. </p> <p> All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. </p>]]></description>
|
||||
<description><![CDATA[<p><img src="https://img.shields.io/badge/version-03.09.12-blue.svg?logo=v&logoColor=white" alt="Version 03.09.12" /> <img src="https://img.shields.io/badge/license-GPL--3.0--or--later-green.svg?logo=gnu&logoColor=white" alt="License" /> <img src="https://img.shields.io/badge/Joomla-5.x%20%7C%206.x-red.svg?logo=joomla&logoColor=white" alt="Joomla" /> <img src="https://img.shields.io/badge/PHP-8.1%2B-777BB4.svg?logo=php&logoColor=white" alt="PHP" /></p> <h3>MokoCassiopeia Template Description</h3> <p> <strong>MokoCassiopeia</strong> continues Joomla's tradition of space-themed default templates— building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5), and <em>Protostar</em> (Joomla 3.0). </p> <p> This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting. </p> <h4>Custom Colour Themes</h4> <p> Starter palette files are included with the template. To create a custom colour scheme, copy <code>templates/mokocassiopeia/templates/light.custom.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/light.custom.css</code>, or <code>templates/mokocassiopeia/templates/dark.custom.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/dark.custom.css</code>. Customise the CSS variables to match your brand, then activate your palette in <em>System → Site Templates → MokoCassiopeia → Theme tab</em> by selecting "Custom" for the Light or Dark Mode Palette. A full variable reference is available in the <em>CSS Variables</em> tab in template options. </p> <h4>Custom CSS & JavaScript</h4> <p> For site-specific styles and scripts that should survive template updates, create the following files: </p> <ul> <li><code>media/templates/site/mokocassiopeia/css/user.css</code> — loaded on every page for custom CSS overrides.</li> <li><code>media/templates/site/mokocassiopeia/js/user.js</code> — loaded on every page for custom JavaScript.</li> </ul> <p> These files are gitignored and will not be overwritten by template updates. </p> <h4>Code Attribution</h4> <p> This template is based on the original <strong>Cassiopeia</strong> template developed by the <a href="https://www.joomla.org" target="_blank" rel="noopener">Joomla! Project</a> and released under the GNU General Public License. </p> <p> Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. </p> <p> It includes integration with <a href="https://afeld.github.io/bootstrap-toc/" target="_blank" rel="noopener">Bootstrap TOC</a>, an open-source table of contents generator by A. Feld, licensed under the MIT License. </p> <p> All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. </p>]]></description>
|
||||
<inheritable>1</inheritable>
|
||||
<files>
|
||||
<filename>component.php</filename>
|
||||
|
||||
Reference in New Issue
Block a user