MokoOnyx v01.00.00 — initial release (successor to MokoCassiopeia)
Some checks failed
Standards Compliance / Secret Scanning (push) Successful in 3s
Standards Compliance / License Header Validation (push) Successful in 4s
Standards Compliance / Repository Structure Validation (push) Successful in 5s
Standards Compliance / Coding Standards Check (push) Failing after 3s
Standards Compliance / Version Consistency Check (push) Successful in 3s
Standards Compliance / Workflow Configuration Check (push) Failing after 2s
Standards Compliance / Documentation Quality Check (push) Successful in 3s
Standards Compliance / README Completeness Check (push) Successful in 3s
Standards Compliance / Git Repository Hygiene (push) Successful in 2s
Standards Compliance / Script Integrity Validation (push) Successful in 4s
Standards Compliance / Line Length Check (push) Failing after 4s
Standards Compliance / File Naming Standards (push) Successful in 2s
Standards Compliance / Insecure Code Pattern Detection (push) Successful in 3s
Standards Compliance / Code Complexity Analysis (push) Successful in 3s
Standards Compliance / Code Duplication Detection (push) Successful in 4s
Standards Compliance / Dead Code Detection (push) Successful in 3s
Standards Compliance / File Size Limits (push) Successful in 2s
CodeQL Security Scanning / Analyze (javascript) (push) Failing after 1m9s
Standards Compliance / Binary File Detection (push) Successful in 4s
CodeQL Security Scanning / Analyze (actions) (push) Failing after 1m11s
Standards Compliance / TODO/FIXME Tracking (push) Successful in 3s
Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 5s
Standards Compliance / Broken Link Detection (push) Successful in 5s
Standards Compliance / Unused Dependencies Check (push) Successful in 7s
Standards Compliance / API Documentation Coverage (push) Successful in 3s
Standards Compliance / Accessibility Check (push) Successful in 3s
Standards Compliance / Performance Metrics (push) Successful in 3s
Standards Compliance / Enterprise Readiness Check (push) Successful in 3s
Standards Compliance / Repository Health Check (push) Successful in 4s
Standards Compliance / Terraform Configuration Validation (push) Successful in 6s
CodeQL Security Scanning / Security Scan Summary (push) Successful in 1s
Standards Compliance / Compliance Summary (push) Successful in 1s
Repo Health / Access control (push) Successful in 1s
Auto-Update SHA Hash / Update SHA-256 Hash in updates.xml (release) Successful in 4s
Repo Health / Release configuration (push) Failing after 3s
Repo Health / Scripts governance (push) Successful in 3s
Repo Health / Repository health (push) Failing after 3s

All files renamed from mokocassiopeia to mokoonyx.
Update server points to MokoOnyx repo.
Bridge migration removed (clean standalone template).
Version reset to 01.00.00.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan Miller
2026-04-19 17:19:03 -05:00
parent 3ba2214614
commit 8258ed804a
238 changed files with 85443 additions and 2 deletions

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,135 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
// Load Bootstrap TOC assets
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->useStyle('vendor.bootstrap-toc');
$wa->useScript('vendor.bootstrap-toc.js');
// Get article params
$params = $this->item->params;
$images = json_decode($this->item->images);
$urls = json_decode($this->item->urls);
$canEdit = $params->get('access-edit');
$info = $params->get('info_block_position', 0);
// Check if associations are implemented
$assocParam = (Associations::isEnabled() && $params->get('show_associations'));
?>
<div class="com-content-article item-page<?php echo $this->pageclass_sfx; ?>">
<div class="row">
<!-- Table of Contents - Left Side -->
<div class="col-lg-3 col-md-4 order-md-1 mb-4">
<div class="sticky-top toc-wrapper" style="top: 20px;">
<nav id="toc" data-toggle="toc" class="toc-container">
<h5 class="toc-title"><?php echo Text::_('TPL_MOKOONYX_TOC_TITLE'); ?></h5>
</nav>
</div>
</div>
<!-- Article Content -->
<div class="col-lg-9 col-md-8 order-md-2">
<meta itemprop="inLanguage" content="<?php echo ($this->item->language === '*') ? Factory::getApplication()->get('language') : $this->item->language; ?>" />
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1><?php echo $this->escape($this->params->get('page_heading')); ?></h1>
</div>
<?php endif; ?>
<?php if (!$this->print) : ?>
<?php if ($canEdit || $params->get('show_print_icon') || $params->get('show_email_icon')) : ?>
<?php echo LayoutHelper::render('joomla.content.icons', ['params' => $params, 'item' => $this->item, 'print' => false]); ?>
<?php endif; ?>
<?php else : ?>
<?php if ($params->get('show_print_icon')) : ?>
<?php echo LayoutHelper::render('joomla.content.icons', ['params' => $params, 'item' => $this->item, 'print' => true]); ?>
<?php endif; ?>
<?php endif; ?>
<?php echo $this->item->event->afterDisplayTitle; ?>
<?php if ($params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>
<?php echo $this->item->event->beforeDisplayContent; ?>
<?php if (isset($urls) && ((!empty($urls->urls_position) && $urls->urls_position == '0') || ($params->get('urls_position') == '0' && empty($urls->urls_position))) || (empty($urls->urls_position) && (!$params->get('urls_position')))) : ?>
<?php echo $this->loadTemplate('links'); ?>
<?php endif; ?>
<?php if ($params->get('access-view')) : ?>
<?php echo LayoutHelper::render('joomla.content.full_image', $this->item); ?>
<?php if (isset($info) && $info == 0 && $params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php echo LayoutHelper::render('joomla.content.info_block', ['item' => $this->item, 'params' => $params, 'position' => 'above']); ?>
<?php endif; ?>
<?php if ($info == 0 && $params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>
<div class="article-content" itemprop="articleBody" data-toc-scope>
<?php echo $this->item->text; ?>
</div>
<?php if (isset($urls) && ((!empty($urls->urls_position) && $urls->urls_position == '1') || ($params->get('urls_position') == '1'))) : ?>
<?php echo $this->loadTemplate('links'); ?>
<?php endif; ?>
<?php elseif ($params->get('show_noauth') == true && $this->user->get('guest')) : ?>
<?php echo LayoutHelper::render('joomla.content.intro_image', $this->item); ?>
<?php echo HTMLHelper::_('content.prepare', $this->item->introtext); ?>
<?php endif; ?>
<?php echo $this->item->event->afterDisplayContent; ?>
<?php if (isset($info) && ($info == 1 || $info == 2)) : ?>
<?php if ($params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>
<?php echo LayoutHelper::render('joomla.content.info_block', ['item' => $this->item, 'params' => $params, 'position' => 'below']); ?>
<?php endif; ?>
</div>
</div>
</div>
<style>
.toc-container {
background: var(--cassiopeia-color-bg, #fff);
border: 1px solid var(--cassiopeia-color-border, #dee2e6);
border-radius: 0.375rem;
padding: 1rem;
}
.toc-title {
margin-bottom: 0.75rem;
font-size: 1rem;
font-weight: 600;
color: var(--cassiopeia-color-text, #212529);
border-bottom: 1px solid var(--cassiopeia-color-border, #dee2e6);
padding-bottom: 0.5rem;
}
@media (max-width: 767.98px) {
.toc-wrapper {
position: static !important;
margin-bottom: 1.5rem;
}
}
</style>

View File

@@ -0,0 +1,135 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
// Load Bootstrap TOC assets
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->useStyle('vendor.bootstrap-toc');
$wa->useScript('vendor.bootstrap-toc.js');
// Get article params
$params = $this->item->params;
$images = json_decode($this->item->images);
$urls = json_decode($this->item->urls);
$canEdit = $params->get('access-edit');
$info = $params->get('info_block_position', 0);
// Check if associations are implemented
$assocParam = (Associations::isEnabled() && $params->get('show_associations'));
?>
<div class="com-content-article item-page<?php echo $this->pageclass_sfx; ?>">
<div class="row">
<!-- Article Content -->
<div class="col-lg-9 col-md-8 order-md-1">
<meta itemprop="inLanguage" content="<?php echo ($this->item->language === '*') ? Factory::getApplication()->get('language') : $this->item->language; ?>" />
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1><?php echo $this->escape($this->params->get('page_heading')); ?></h1>
</div>
<?php endif; ?>
<?php if (!$this->print) : ?>
<?php if ($canEdit || $params->get('show_print_icon') || $params->get('show_email_icon')) : ?>
<?php echo LayoutHelper::render('joomla.content.icons', ['params' => $params, 'item' => $this->item, 'print' => false]); ?>
<?php endif; ?>
<?php else : ?>
<?php if ($params->get('show_print_icon')) : ?>
<?php echo LayoutHelper::render('joomla.content.icons', ['params' => $params, 'item' => $this->item, 'print' => true]); ?>
<?php endif; ?>
<?php endif; ?>
<?php echo $this->item->event->afterDisplayTitle; ?>
<?php if ($params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>
<?php echo $this->item->event->beforeDisplayContent; ?>
<?php if (isset($urls) && ((!empty($urls->urls_position) && $urls->urls_position == '0') || ($params->get('urls_position') == '0' && empty($urls->urls_position))) || (empty($urls->urls_position) && (!$params->get('urls_position')))) : ?>
<?php echo $this->loadTemplate('links'); ?>
<?php endif; ?>
<?php if ($params->get('access-view')) : ?>
<?php echo LayoutHelper::render('joomla.content.full_image', $this->item); ?>
<?php if (isset($info) && $info == 0 && $params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php echo LayoutHelper::render('joomla.content.info_block', ['item' => $this->item, 'params' => $params, 'position' => 'above']); ?>
<?php endif; ?>
<?php if ($info == 0 && $params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>
<div class="article-content" itemprop="articleBody" data-toc-scope>
<?php echo $this->item->text; ?>
</div>
<?php if (isset($urls) && ((!empty($urls->urls_position) && $urls->urls_position == '1') || ($params->get('urls_position') == '1'))) : ?>
<?php echo $this->loadTemplate('links'); ?>
<?php endif; ?>
<?php elseif ($params->get('show_noauth') == true && $this->user->get('guest')) : ?>
<?php echo LayoutHelper::render('joomla.content.intro_image', $this->item); ?>
<?php echo HTMLHelper::_('content.prepare', $this->item->introtext); ?>
<?php endif; ?>
<?php echo $this->item->event->afterDisplayContent; ?>
<?php if (isset($info) && ($info == 1 || $info == 2)) : ?>
<?php if ($params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>
<?php echo LayoutHelper::render('joomla.content.info_block', ['item' => $this->item, 'params' => $params, 'position' => 'below']); ?>
<?php endif; ?>
</div>
<!-- Table of Contents - Right Side -->
<div class="col-lg-3 col-md-4 order-md-2 mb-4">
<div class="sticky-top toc-wrapper" style="top: 20px;">
<nav id="toc" data-toggle="toc" class="toc-container">
<h5 class="toc-title"><?php echo Text::_('TPL_MOKOONYX_TOC_TITLE'); ?></h5>
</nav>
</div>
</div>
</div>
</div>
<style>
.toc-container {
background: var(--cassiopeia-color-bg, #fff);
border: 1px solid var(--cassiopeia-color-border, #dee2e6);
border-radius: 0.375rem;
padding: 1rem;
}
.toc-title {
margin-bottom: 0.75rem;
font-size: 1rem;
font-weight: 600;
color: var(--cassiopeia-color-text, #212529);
border-bottom: 1px solid var(--cassiopeia-color-border, #dee2e6);
padding-bottom: 0.5rem;
}
@media (max-width: 767.98px) {
.toc-wrapper {
position: static !important;
margin-bottom: 1.5rem;
}
}
</style>

View File

@@ -0,0 +1,36 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_articles_archive.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-articles-archive<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-articles-archive__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-articles-archive__list">
<?php foreach ($list as $item) : ?>
<li class="mod-articles-archive__item">
<a href="<?php echo $item->link; ?>"><?php echo $item->text; ?></a>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_articles_categories.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
if (empty($list)) {
return;
}
$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');
$showDescription = $params->get('show_description', 0);
$numitems = $params->get('numitems', 0);
?>
<div class="mod-articles-categories<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-articles-categories__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-articles-categories__list">
<?php foreach ($list as $item) : ?>
<li class="mod-articles-categories__item">
<a href="<?php echo $item->link; ?>"><?php echo $item->title; ?></a>
<?php if ($numitems) : ?>
<span class="mod-articles-categories__count">(<?php echo $item->numitems; ?>)</span>
<?php endif; ?>
<?php if ($showDescription && !empty($item->description)) : ?>
<p class="mod-articles-categories__description"><?php echo $item->description; ?></p>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,78 @@
<?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
*/
/**
* Default layout override for mod_articles_category.
* Adds showtitle support and respects module settings.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
Factory::getApplication()->getLanguage()->load('mod_articles_category', JPATH_SITE);
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-articles-category<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-articles-category__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-articles-category__list">
<?php foreach ($list as $item) : ?>
<li class="mod-articles-category__item" itemscope itemtype="https://schema.org/Article">
<?php if ($params->get('link_titles') == 1) : ?>
<a class="mod-articles-category__link" href="<?php echo $item->link; ?>" itemprop="url">
<span itemprop="name"><?php echo $item->title; ?></span>
</a>
<?php else : ?>
<span itemprop="name"><?php echo $item->title; ?></span>
<?php endif; ?>
<?php if ($item->displayHits) : ?>
<span class="mod-articles-category__hits">
(<?php echo $item->displayHits; ?>)
</span>
<?php endif; ?>
<?php if ($params->get('show_author', 0)) : ?>
<span class="mod-articles-category__author">
<?php echo $item->displayAuthorName; ?>
</span>
<?php endif; ?>
<?php if ($item->displayDate) : ?>
<time class="mod-articles-category__date" datetime="<?php echo HTMLHelper::_('date', $item->displayDate, 'c'); ?>" itemprop="datePublished">
<?php echo $item->displayDate; ?>
</time>
<?php endif; ?>
<?php if ($params->get('show_introtext', 0)) : ?>
<div class="mod-articles-category__intro" itemprop="description">
<?php echo $item->displayIntrotext; ?>
</div>
<?php endif; ?>
<?php if ($params->get('show_readmore', 0)) : ?>
<a class="mod-articles-category__readmore" href="<?php echo $item->link; ?>" itemprop="url">
<?php echo Text::_('MOD_ARTICLES_CATEGORY_READ_MORE_TITLE'); ?>
</a>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,40 @@
<?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
*/
/**
* Default layout override for mod_articles_latest.
* Adds showtitle support and respects module settings.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-articles-latest<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-articles-latest__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-articles-latest__list">
<?php foreach ($list as $item) : ?>
<li class="mod-articles-latest__item" itemscope itemtype="https://schema.org/Article">
<a href="<?php echo $item->link; ?>" itemprop="url">
<span itemprop="name"><?php echo $item->title; ?></span>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,58 @@
<?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
*/
/**
* Default layout override for mod_articles_news (newsflash).
* Adds showtitle support with card-based layout.
*/
defined('_JEXEC') or die;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-articles-news newsflash<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-articles-news__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<?php foreach ($list as $item) : ?>
<div class="mod-articles-news__item" itemscope itemtype="https://schema.org/Article">
<?php if ($params->get('item_title')) : ?>
<h4 class="mod-articles-news__item-title" itemprop="name">
<?php if ($item->link !== '' && $params->get('link_titles')) : ?>
<a href="<?php echo $item->link; ?>" itemprop="url"><?php echo $item->title; ?></a>
<?php else : ?>
<?php echo $item->title; ?>
<?php endif; ?>
</h4>
<?php endif; ?>
<?php if (!empty($item->afterDisplayTitle)) : ?>
<?php echo $item->afterDisplayTitle; ?>
<?php endif; ?>
<?php if ($params->get('show_introtext', 1)) : ?>
<div class="mod-articles-news__intro" itemprop="description">
<?php echo $item->introtext; ?>
</div>
<?php endif; ?>
<?php if (isset($item->readmore) && $item->readmore) : ?>
<a class="mod-articles-news__readmore" href="<?php echo $item->link; ?>" itemprop="url">
<?php echo $item->linkText; ?>
</a>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,38 @@
<?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
*/
/**
* Default layout override for mod_articles_popular.
* Adds showtitle support and respects module settings.
*/
defined('_JEXEC') or die;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-articles-popular<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-articles-popular__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-articles-popular__list">
<?php foreach ($list as $item) : ?>
<li class="mod-articles-popular__item" itemscope itemtype="https://schema.org/Article">
<a href="<?php echo $item->link; ?>" itemprop="url">
<span itemprop="name"><?php echo $item->title; ?></span>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,52 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_banners.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-banners<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-banners__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<?php foreach ($list as $item) : ?>
<div class="mod-banners__item">
<?php $link = $item->params->get('url') ?: ''; ?>
<?php if ($item->type == 1) : ?>
<?php // Image banner ?>
<?php $imageUrl = $item->params->get('imageurl', ''); ?>
<?php $alt = htmlspecialchars($item->name, ENT_COMPAT, 'UTF-8'); ?>
<?php if ($link) : ?>
<a href="<?php echo htmlspecialchars($link, ENT_COMPAT, 'UTF-8'); ?>" target="_blank" rel="noopener noreferrer">
<img src="<?php echo htmlspecialchars($imageUrl, ENT_COMPAT, 'UTF-8'); ?>" alt="<?php echo $alt; ?>" class="mod-banners__image" loading="lazy" />
</a>
<?php else : ?>
<img src="<?php echo htmlspecialchars($imageUrl, ENT_COMPAT, 'UTF-8'); ?>" alt="<?php echo $alt; ?>" class="mod-banners__image" loading="lazy" />
<?php endif; ?>
<?php else : ?>
<?php // Custom HTML banner ?>
<?php echo $item->custombannercode; ?>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,53 @@
<?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
*/
/**
* Default layout override for mod_breadcrumbs.
* Bootstrap 5 breadcrumb with schema.org BreadcrumbList markup.
* Module settings (showHome, showLast, homeText) are handled by Joomla core
* before $list reaches this template.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
$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');
$showHere = $params->get('showHere', 1);
if (empty($list)) {
return;
}
?>
<nav class="mod-breadcrumbs<?php echo $suffix ? ' ' . $suffix : ''; ?>" aria-label="<?php echo Text::_('MOD_BREADCRUMBS_HERE'); ?>">
<?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 ($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)) : ?>
<a href="<?php echo $item->link; ?>" itemprop="item">
<span itemprop="name"><?php echo $item->name; ?></span>
</a>
<?php else : ?>
<span itemprop="name"><?php echo $item->name; ?></span>
<?php endif; ?>
<meta itemprop="position" content="<?php echo $key + 1; ?>" />
</li>
<?php endforeach; ?>
</ol>
</nav>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View 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
*/
/**
* Default layout override for mod_custom.
* Adds showtitle support and respects all module settings.
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Uri\Uri;
$modId = 'mod-custom' . $module->id;
$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');
if ($params->get('backgroundimage')) {
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $app->getDocument()->getWebAssetManager();
$wa->addInlineStyle(
'#' . $modId . '{background-image: url("' . Uri::root(true) . '/' . HTMLHelper::_('cleanImageURL', $params->get('backgroundimage'))->url . '");}',
['name' => $modId]
);
}
?>
<div class="mod-custom custom<?php echo $suffix ? ' ' . $suffix : ''; ?>" id="<?php echo $modId; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-custom__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<?php echo $module->content; ?>
</div>

View File

@@ -0,0 +1,42 @@
<?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
*/
/**
* Template override for mod_custom adding banner-overlay wrapper pattern.
* Based on Cassiopeia's banner layout approach.
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Uri\Uri;
$modId = 'mod-custom' . $module->id;
$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');
if ($params->get('backgroundimage')) {
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $app->getDocument()->getWebAssetManager();
$wa->addInlineStyle(
'#' . $modId . '{background-image: url("' . Uri::root(true) . '/' . HTMLHelper::_('cleanImageURL', $params->get('backgroundimage'))->url . '");}',
['name' => $modId]
);
}
?>
<div class="mod-custom custom banner-overlay custom-hero<?php echo $suffix ? ' ' . $suffix : ''; ?>" id="<?php echo $modId; ?>">
<div class="overlay">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-custom__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<?php echo $module->content; ?>
</div>
</div>

View File

@@ -0,0 +1,88 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_feed.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
if (!$feed) {
return;
}
$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');
$rssurl = $params->get('rssurl', '');
$rsstitle = $params->get('rsstitle', 1);
$rssdesc = $params->get('rssrtl', 0) ? ' feed-rtl' : '';
$rssimage = $params->get('rssimage', 1);
$rssitems = $params->get('rssitems', 5);
$rssitemdesc = $params->get('rssitemdesc', 1);
$word_count = $params->get('word_count', 0);
?>
<div class="mod-feed<?php echo $suffix ? ' ' . $suffix : ''; ?><?php echo $rssdesc; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-feed__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<?php if ($feed->title && $rsstitle) : ?>
<h4 class="mod-feed__feed-title">
<?php if (!empty($rssurl)) : ?>
<a href="<?php echo htmlspecialchars($rssurl, ENT_COMPAT, 'UTF-8'); ?>" target="_blank" rel="noopener noreferrer">
<?php echo $feed->title; ?>
</a>
<?php else : ?>
<?php echo $feed->title; ?>
<?php endif; ?>
</h4>
<?php endif; ?>
<?php if ($feed->description && $rssdesc) : ?>
<p class="mod-feed__description"><?php echo $feed->description; ?></p>
<?php endif; ?>
<?php if ($rssimage && $feed->image) : ?>
<img src="<?php echo $feed->image->uri; ?>" alt="<?php echo $feed->image->title ?? ''; ?>" class="mod-feed__image" />
<?php endif; ?>
<?php if (!empty($feed->items)) : ?>
<ul class="mod-feed__list">
<?php for ($i = 0, $max = min(count($feed->items), $rssitems); $i < $max; $i++) :
$item = $feed->items[$i];
?>
<li class="mod-feed__item">
<?php if (!empty($item->uri)) : ?>
<a href="<?php echo htmlspecialchars($item->uri, ENT_COMPAT, 'UTF-8'); ?>" target="_blank" rel="noopener noreferrer">
<?php echo $item->title; ?>
</a>
<?php else : ?>
<?php echo $item->title; ?>
<?php endif; ?>
<?php if ($rssitemdesc && !empty($item->content)) :
$desc = $item->content;
if ($word_count) {
$words = explode(' ', strip_tags($desc));
if (count($words) > $word_count) {
$desc = implode(' ', array_slice($words, 0, $word_count)) . '&hellip;';
}
}
?>
<p class="mod-feed__item-description"><?php echo $desc; ?></p>
<?php endif; ?>
</li>
<?php endfor; ?>
</ul>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,85 @@
<?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
*/
/**
* Default layout override for mod_finder (Smart Search).
* Bootstrap 5 search form with showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
// Load component language for search labels
$lang = $app->getLanguage();
$lang->load('com_finder', 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');
$showLabel = $params->get('show_label', 1);
$labelClass = (!$showLabel ? 'visually-hidden ' : '') . 'finder';
Text::script('MOD_FINDER_SEARCH_VALUE');
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $app->getDocument()->getWebAssetManager();
$wa->getRegistry()->addExtensionRegistryFile('com_finder');
if ($params->get('show_autosuggest', 1)) {
$wa->usePreset('awesomplete');
$app->getDocument()->addScriptOptions('finder-search', ['url' => Route::_('index.php?option=com_finder&task=suggestions.suggest&format=json&tmpl=component', false)]);
Text::script('COM_FINDER_SEARCH_FORM_LIST_LABEL');
Text::script('JLIB_JS_AJAX_ERROR_OTHER');
Text::script('JLIB_JS_AJAX_ERROR_PARSE');
}
$wa->useScript('com_finder.finder');
?>
<div class="mod-finder<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-finder__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<form class="mod-finder__form js-finder-searchform form-search" action="<?php echo Route::_($route); ?>" method="get" role="search">
<label for="mod-finder-searchword<?php echo $module->id; ?>" class="<?php echo $labelClass; ?>">
<?php echo $params->get('alt_label', Text::_('JSEARCH_FILTER_SUBMIT')); ?>
</label>
<div class="input-group">
<input type="text" name="q" id="mod-finder-searchword<?php echo $module->id; ?>"
class="js-finder-search-query form-control"
value="<?php echo htmlspecialchars($app->getInput()->get('q', '', 'string'), ENT_COMPAT, 'UTF-8'); ?>"
placeholder="<?php echo Text::_('MOD_FINDER_SEARCH_VALUE'); ?>">
<?php if ($params->get('show_button', 0)) : ?>
<button class="btn btn-primary" type="submit">
<span class="fa-solid fa-magnifying-glass" aria-hidden="true"></span>
<span class="visually-hidden"><?php echo Text::_('JSEARCH_FILTER_SUBMIT'); ?></span>
</button>
<?php endif; ?>
</div>
<?php $show_advanced = $params->get('show_advanced', 0); ?>
<?php if ($show_advanced == 2) : ?>
<a href="<?php echo Route::_($route); ?>" class="mod-finder__advanced-link mt-2 d-inline-block">
<?php echo Text::_('COM_FINDER_ADVANCED_SEARCH'); ?>
</a>
<?php elseif ($show_advanced == 1) : ?>
<div class="mod-finder__advanced js-finder-advanced mt-2">
<?php echo HTMLHelper::_('filter.select', $query, $params); ?>
</div>
<?php endif; ?>
<?php
$finderHelper = $app->bootModule('mod_finder', 'site')->getHelper('FinderHelper');
echo $finderHelper->getHiddenFields($route);
?>
</form>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<?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
*/
/**
* Default layout override for mod_footer.
* Adds showtitle support and respects module settings.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
$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');
?>
<div class="mod-footer<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-footer__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<div class="mod-footer__line1"><?php echo $lineone; ?></div>
<div class="mod-footer__line2"><?php echo Text::_('MOD_FOOTER_LINE2'); ?></div>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,63 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_languages.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-languages<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-languages__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-languages__list">
<?php foreach ($list as $language) : ?>
<?php $isActive = $language->active ? ' active' : ''; ?>
<li class="mod-languages__item<?php echo $isActive; ?>" dir="<?php echo $language->rtl ? 'rtl' : 'ltr'; ?>">
<?php if ($language->active) : ?>
<span class="mod-languages__link mod-languages__link--active" lang="<?php echo $language->sef; ?>">
<?php else : ?>
<a class="mod-languages__link" href="<?php echo htmlspecialchars($language->link, ENT_COMPAT, 'UTF-8'); ?>" lang="<?php echo $language->sef; ?>">
<?php endif; ?>
<?php if ($params->get('image', 1)) : ?>
<?php if ($language->image) : ?>
<?php echo HTMLHelper::_('image', 'mod_languages/' . $language->image . '.gif', '', null, true); ?>
<?php else : ?>
<span class="mod-languages__badge badge bg-secondary"><?php echo strtoupper($language->sef); ?></span>
<?php endif; ?>
<?php endif; ?>
<?php if ($params->get('show_name', 1)) : ?>
<?php echo $language->title_native; ?>
<?php endif; ?>
<?php if ($language->active) : ?>
</span>
<?php else : ?>
</a>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,126 @@
<?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
*/
/**
* Default layout override for mod_login.
* Bootstrap 5 login form with showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
Factory::getApplication()->getLanguage()->load('mod_login', 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');
?>
<div class="mod-login<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-login__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<?php if ($type === 'logout') : ?>
<form action="<?php echo Route::_('index.php', true); ?>" method="post" class="mod-login__form mod-login__form--logout">
<?php if ($params->get('greeting', 1)) : ?>
<div class="mod-login__greeting">
<?php if (!empty($user->name)) : ?>
<span class="mod-login__name"><?php echo Text::sprintf('MOD_LOGIN_HINAME', htmlspecialchars($user->name, ENT_COMPAT, 'UTF-8')); ?></span>
<?php else : ?>
<span class="mod-login__name"><?php echo Text::sprintf('MOD_LOGIN_HINAME', htmlspecialchars($user->username, ENT_COMPAT, 'UTF-8')); ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="mod-login__submit">
<button type="submit" name="Submit" class="btn btn-primary w-100"><?php echo Text::_('JLOGOUT'); ?></button>
</div>
<input type="hidden" name="option" value="com_users">
<input type="hidden" name="task" value="user.logout">
<input type="hidden" name="return" value="<?php echo $return; ?>">
<?php echo HTMLHelper::_('form.token'); ?>
</form>
<?php else : ?>
<form action="<?php echo Route::_('index.php', true); ?>" method="post" class="mod-login__form mod-login__form--login">
<?php if ($params->get('pretext')) : ?>
<div class="mod-login__pretext"><?php echo $params->get('pretext'); ?></div>
<?php endif; ?>
<div class="mod-login__field mb-3">
<label for="modlgn-username-<?php echo $module->id; ?>" class="form-label visually-hidden"><?php echo Text::_('JGLOBAL_USERNAME'); ?></label>
<div class="input-group">
<span class="input-group-text"><i class="fa-solid fa-user" aria-hidden="true"></i></span>
<input id="modlgn-username-<?php echo $module->id; ?>" type="text" name="username" class="form-control" autocomplete="username" placeholder="<?php echo Text::_('JGLOBAL_USERNAME'); ?>">
</div>
</div>
<div class="mod-login__field mb-3">
<label for="modlgn-passwd-<?php echo $module->id; ?>" class="form-label visually-hidden"><?php echo Text::_('JGLOBAL_PASSWORD'); ?></label>
<div class="input-group">
<span class="input-group-text"><i class="fa-solid fa-lock" aria-hidden="true"></i></span>
<input id="modlgn-passwd-<?php echo $module->id; ?>" type="password" name="password" class="form-control" autocomplete="current-password" placeholder="<?php echo Text::_('JGLOBAL_PASSWORD'); ?>">
</div>
</div>
<?php if (!empty($twofactormethods) && count($twofactormethods) > 1) : ?>
<div class="mod-login__field mb-3">
<label for="modlgn-secretkey-<?php echo $module->id; ?>" class="form-label visually-hidden"><?php echo Text::_('JGLOBAL_SECRETKEY'); ?></label>
<div class="input-group">
<span class="input-group-text"><i class="fa-solid fa-shield-halved" aria-hidden="true"></i></span>
<input id="modlgn-secretkey-<?php echo $module->id; ?>" type="text" name="secretkey" class="form-control" autocomplete="one-time-code" placeholder="<?php echo Text::_('JGLOBAL_SECRETKEY'); ?>">
</div>
</div>
<?php endif; ?>
<?php if ($params->get('remember', 1)) : ?>
<div class="mod-login__remember form-check mb-3">
<input id="modlgn-remember-<?php echo $module->id; ?>" type="checkbox" name="remember" class="form-check-input" value="yes">
<label for="modlgn-remember-<?php echo $module->id; ?>" class="form-check-label"><?php echo Text::_('JGLOBAL_REMEMBER_ME'); ?></label>
</div>
<?php endif; ?>
<div class="mod-login__submit mb-3">
<button type="submit" name="Submit" class="btn btn-primary w-100"><?php echo Text::_('JLOGIN'); ?></button>
</div>
<?php $usersConfig = \Joomla\CMS\Component\ComponentHelper::getParams('com_users'); ?>
<ul class="mod-login__options list-unstyled small">
<?php if ($usersConfig->get('allowUserRegistration')) : ?>
<li>
<a href="<?php echo Route::_('index.php?option=com_users&view=registration'); ?>">
<?php echo Text::_('MOD_LOGIN_REGISTER'); ?>
</a>
</li>
<?php endif; ?>
<li>
<a href="<?php echo Route::_('index.php?option=com_users&view=remind'); ?>">
<?php echo Text::_('MOD_LOGIN_FORGOT_YOUR_USERNAME'); ?>
</a>
</li>
<li>
<a href="<?php echo Route::_('index.php?option=com_users&view=reset'); ?>">
<?php echo Text::_('MOD_LOGIN_FORGOT_YOUR_PASSWORD'); ?>
</a>
</li>
</ul>
<input type="hidden" name="option" value="com_users">
<input type="hidden" name="task" value="user.login">
<input type="hidden" name="return" value="<?php echo $return; ?>">
<?php echo HTMLHelper::_('form.token'); ?>
<?php if ($params->get('posttext')) : ?>
<div class="mod-login__posttext"><?php echo $params->get('posttext'); ?></div>
<?php endif; ?>
</form>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,95 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_menu.
* Simple list menu with showtitle support, suitable for sidebars and footers.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Helper\ModuleHelper;
$id = '';
if ($tagId = $params->get('tag_id', '')) {
$id = ' id="' . $tagId . '"';
}
$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');
?>
<nav class="mod-menu<?php echo $suffix ? ' ' . $suffix : ''; ?>"<?php echo $id; ?> aria-label="<?php echo htmlspecialchars($module->title, ENT_COMPAT, 'UTF-8'); ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-menu__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-menu__list nav flex-column">
<?php foreach ($list as $i => &$item) :
$itemParams = $item->getParams();
$class = 'nav-item mod-menu__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';
}
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', 'default_' . $item->type);
break;
default:
require ModuleHelper::getLayoutPath('mod_menu', 'default_url');
break;
endswitch;
if ($item->deeper) {
echo '<ul class="mod-menu__sub nav flex-column ms-3">';
} elseif ($item->shallower) {
echo '</li>';
echo str_repeat('</ul></li>', $item->level_diff);
} else {
echo '</li>';
}
endforeach;
?></ul>
</nav>

View 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>

View 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);

View 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>

View 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>

View 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);

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View 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="#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-<?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', 'mainmenu_' . $item->type);
break;
default:
require ModuleHelper::getLayoutPath('mod_menu', 'mainmenu_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>

View 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);

View 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>

View 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>

View 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);

View File

@@ -0,0 +1,41 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_random_image.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
if (empty($image)) {
return;
}
$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');
?>
<div class="mod-random-image<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-random-image__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<?php if ($link) : ?>
<a href="<?php echo htmlspecialchars($link, ENT_COMPAT, 'UTF-8'); ?>">
<?php endif; ?>
<img src="<?php echo htmlspecialchars($image->folder . '/' . $image->name, ENT_COMPAT, 'UTF-8'); ?>"
alt="<?php echo htmlspecialchars($image->name, ENT_COMPAT, 'UTF-8'); ?>"
<?php if ($image->width) : ?>width="<?php echo $image->width; ?>"<?php endif; ?>
<?php if ($image->height) : ?>height="<?php echo $image->height; ?>"<?php endif; ?>
class="mod-random-image__img"
loading="lazy" />
<?php if ($link) : ?>
</a>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<?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
*/
/**
* Default layout override for mod_related_items.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
if (empty($list)) {
return;
}
$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');
$showDate = $params->get('showDate', 0);
?>
<div class="mod-related-items<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-related-items__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-related-items__list">
<?php foreach ($list as $item) : ?>
<li class="mod-related-items__item">
<a href="<?php echo $item->route; ?>"><?php echo $item->title; ?></a>
<?php if ($showDate) : ?>
<time class="mod-related-items__date" datetime="<?php echo HTMLHelper::_('date', $item->created, 'c'); ?>">
<?php echo HTMLHelper::_('date', $item->created, 'DATE_FORMAT_LC3'); ?>
</time>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,39 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_stats.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-stats<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-stats__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<table class="mod_stats__table">
<tbody>
<?php foreach ($list as $item) : ?>
<tr>
<th class="mod_stats__label" scope="row"><?php echo $item->title; ?></th>
<td class="mod_stats__data"><?php echo $item->data; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,31 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_syndicate.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
$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');
?>
<div class="mod-syndicate<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-syndicate__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<a href="<?php echo $link; ?>" class="mod-syndicate__link">
<span class="fa-solid fa-rss" aria-hidden="true"></span>
<?php echo htmlspecialchars($text, ENT_COMPAT, 'UTF-8'); ?>
</a>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,41 @@
<?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
*/
/**
* Default layout override for mod_tags_popular.
* Adds showtitle support with Bootstrap badge-style tags.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-tags-popular<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-tags-popular__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<div class="mod-tags-popular__list d-flex flex-wrap gap-2">
<?php foreach ($list as $item) : ?>
<a class="badge bg-secondary text-decoration-none mod-tags-popular__tag" href="<?php echo $item->link; ?>">
<?php echo htmlspecialchars($item->title, ENT_COMPAT, 'UTF-8'); ?>
<?php if ($params->get('show_tag_count', 0)) : ?>
<span class="mod-tags-popular__count">(<?php echo $item->count; ?>)</span>
<?php endif; ?>
</a>
<?php endforeach; ?>
</div>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,38 @@
<?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
*/
/**
* Default layout override for mod_tags_similar.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
if (empty($list)) {
return;
}
$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');
?>
<div class="mod-tags-similar<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-tags-similar__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-tags-similar__list">
<?php foreach ($list as $item) : ?>
<li class="mod-tags-similar__item">
<a href="<?php echo $item->link; ?>"><?php echo htmlspecialchars($item->core_title, ENT_COMPAT, 'UTF-8'); ?></a>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,41 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_users_latest.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
if (empty($names)) {
return;
}
$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');
?>
<div class="mod-users-latest<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-users-latest__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<ul class="mod-users-latest__list">
<?php foreach ($names as $name) : ?>
<li class="mod-users-latest__item">
<?php echo htmlspecialchars($name->name, ENT_COMPAT, 'UTF-8'); ?>
<time class="mod-users-latest__date" datetime="<?php echo HTMLHelper::_('date', $name->registerDate, 'c'); ?>">
<?php echo HTMLHelper::_('date', $name->registerDate, 'DATE_FORMAT_LC3'); ?>
</time>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,43 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_whosonline.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
$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');
$showmode = $params->get('showmode', 0);
?>
<div class="mod-whosonline<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-whosonline__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<?php if ($showmode == 0 || $showmode == 2) : ?>
<p class="mod-whosonline__count">
<?php echo Text::plural('MOD_WHOSONLINE_GUESTS', $count['guest']); ?><br />
<?php echo Text::plural('MOD_WHOSONLINE_MEMBERS', $count['user']); ?>
</p>
<?php endif; ?>
<?php if (($showmode == 1 || $showmode == 2) && !empty($names)) : ?>
<ul class="mod-whosonline__list">
<?php foreach ($names as $name) : ?>
<li class="mod-whosonline__item"><?php echo $name->username; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -0,0 +1,39 @@
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default layout override for mod_wrapper.
* Adds showtitle support.
*/
defined('_JEXEC') or die;
$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');
$url = htmlspecialchars($params->get('url', ''), ENT_COMPAT, 'UTF-8');
$width = htmlspecialchars($params->get('width', '100%'), ENT_COMPAT, 'UTF-8');
$height = htmlspecialchars($params->get('height', '500'), ENT_COMPAT, 'UTF-8');
$scrolling = $params->get('scrolling', 'auto');
$frameborder = $params->get('frameborder', 0) ? '1' : '0';
?>
<div class="mod-wrapper<?php echo $suffix ? ' ' . $suffix : ''; ?>">
<?php if ($module->showtitle) : ?>
<<?php echo $headerTag; ?> class="mod-wrapper__title<?php echo $headerClass ? ' ' . $headerClass : ''; ?>"><?php echo $module->title; ?></<?php echo $headerTag; ?>>
<?php endif; ?>
<iframe src="<?php echo $url; ?>"
width="<?php echo $width; ?>"
height="<?php echo $height; ?>"
scrolling="<?php echo $scrolling; ?>"
frameborder="<?php echo $frameborder; ?>"
title="<?php echo htmlspecialchars($module->title, ENT_COMPAT, 'UTF-8'); ?>"
class="mod-wrapper__iframe"
loading="lazy">
</iframe>
</div>

View File

@@ -0,0 +1,76 @@
<!-- 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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>