diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml
index 1227ff8..2325032 100644
--- a/.mokogitea/workflows/auto-release.yml
+++ b/.mokogitea/workflows/auto-release.yml
@@ -131,6 +131,19 @@ jobs:
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
+ - name: Check for merge conflict markers
+ run: |
+ CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
+ if [ -n "$CONFLICTS" ]; then
+ echo "::error::Merge conflict markers found — aborting release"
+ echo "## Release Blocked: Conflict Markers" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+ echo "No conflict markers found"
+
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml
index 7796e32..1db46f7 100644
--- a/.mokogitea/workflows/issue-branch.yml
+++ b/.mokogitea/workflows/issue-branch.yml
@@ -5,17 +5,7 @@
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Automation
-<<<<<<< HEAD
-<<<<<<< HEAD
-# VERSION: 02.18.00
-=======
-# VERSION: 02.18.00
-=======
-# VERSION: 02.18.00
-=======
-# VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
+# VERSION: 02.18.03
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1a9007..2f31489 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,42 +8,18 @@
DEFGROUP: Joomla.Template.Site
INGROUP: MokoOnyx.Documentation
PATH: ./CHANGELOG.md
-<<<<<<< HEAD
-<<<<<<< HEAD
- VERSION: 02.18.00
+ VERSION: 02.18.03
BRIEF: Changelog file documenting version history of MokoOnyx
-->
-# Changelog — MokoOnyx (VERSION: 02.18.00)
+# Changelog — MokoOnyx (VERSION: 02.18.03)
## [Unreleased]
## [02.18.00] --- 2026-06-02
-=======
- VERSION: 02.18.00
- BRIEF: Changelog file documenting version history of MokoOnyx
- -->
-
-# Changelog — MokoOnyx (VERSION: 02.18.00)
->>>>>>> origin/main
-=======
- VERSION: 02.18.00
- BRIEF: Changelog file documenting version history of MokoOnyx
- -->
-
-# Changelog — MokoOnyx (VERSION: 02.18.00)
->>>>>>> origin/main
## [02.17.00] --- 2026-06-02
## [02.15.00] --- 2026-05-30
-
-=======
- VERSION: 02.18.00
- BRIEF: Changelog file documenting version history of MokoOnyx
- -->
-
-# Changelog — MokoOnyx (VERSION: 02.18.00)
->>>>>>> origin/main
## [02.14.00] --- 2026-05-30
## [02.13.00] --- 2026-05-30
diff --git a/SECURITY.md b/SECURITY.md
index 4e16eac..a60c876 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -10,17 +10,7 @@
INGROUP: MokoOnyx.Governance
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
FILE: SECURITY.md
-<<<<<<< HEAD
-<<<<<<< HEAD
- VERSION: 02.18.00
-=======
- VERSION: 02.18.00
-=======
- VERSION: 02.18.00
-=======
- VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
+ VERSION: 02.18.03
BRIEF: Security policy and vulnerability reporting process for MokoOnyx.
PATH: /SECURITY.md
NOTE: This policy is process oriented and does not replace secure engineering practices.
diff --git a/src/helper/minify.php b/src/helper/minify.php
index 9ffbe2f..09c4417 100644
--- a/src/helper/minify.php
+++ b/src/helper/minify.php
@@ -161,7 +161,7 @@ class MokoMinifyHelper
$js = preg_replace('/\s*([{}();,=+\-*\/<>!&|?:])\s*/', '$1', $js);
// Restore necessary spaces (after keywords)
- $js = preg_replace('/(var|let|const|return|typeof|instanceof|new|delete|throw|case|in|of)([^\s;})><=!&|?:,])/', '$1 $2', $js);
+ $js = preg_replace('/\b(var|let|const|return|typeof|instanceof|new|delete|throw|case|in|of)\b([^\s;})><=!&|?:,])/', '$1 $2', $js);
return trim($js);
}
diff --git a/src/html/com_joomgallery/category/default.php b/src/html/com_joomgallery/category/default.php
deleted file mode 100644
index f8ffb31..0000000
--- a/src/html/com_joomgallery/category/default.php
+++ /dev/null
@@ -1,61 +0,0 @@
-
- *
- * This file is part of a Moko Consulting project.
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- *
- * FILE INFORMATION
- * DEFGROUP: MokoOnyx.Override
- * INGROUP: MokoOnyx
- * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
- * PATH: /html/com_joomgallery/category/default.php
-<<<<<<< HEAD
-<<<<<<< HEAD
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
- * BRIEF: Category view override — password gate then loads default_cat sub-layout
- */
-
-// No direct access
-defined('_JEXEC') or die;
-
-use Joomla\CMS\Router\Route;
-use Joomla\CMS\Language\Text;
-use Joomla\CMS\HTML\HTMLHelper;
-
-// Import CSS & JS
-$wa = $this->document->getWebAssetManager();
-$wa->useStyle('com_joomgallery.site');
-$wa->useStyle('com_joomgallery.jg-icon-font');
-?>
-
-item->pw_protected) : ?>
-
-
- loadTemplate('cat'); ?>
-
diff --git a/src/html/com_joomgallery/category/default_cat.php b/src/html/com_joomgallery/category/default_cat.php
deleted file mode 100644
index 7582507..0000000
--- a/src/html/com_joomgallery/category/default_cat.php
+++ /dev/null
@@ -1,229 +0,0 @@
-
- *
- * This file is part of a Moko Consulting project.
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- *
- * FILE INFORMATION
- * DEFGROUP: MokoOnyx.Override
- * INGROUP: MokoOnyx
- * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
- * PATH: /html/com_joomgallery/category/default_cat.php
-<<<<<<< HEAD
-<<<<<<< HEAD
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
- * BRIEF: Category sub-layout — subcategories grid + images grid with pagination
- */
-
-// No direct access
-defined('_JEXEC') or die;
-
-use Joomla\CMS\Factory;
-use Joomla\CMS\Router\Route;
-use Joomla\CMS\Language\Text;
-use Joomla\CMS\Session\Session;
-use Joomla\CMS\HTML\HTMLHelper;
-use Joomla\CMS\Layout\LayoutHelper;
-use Joomgallery\Component\Joomgallery\Administrator\Helper\JoomHelper;
-
-// Image params
-$image_type = $this->params['configs']->get('jg_category_view_type_image', 'thumbnail', 'STRING');
-$gallery_class = $this->params['configs']->get('jg_category_view_class', 'masonry', 'STRING');
-$num_columns = $this->params['configs']->get('jg_category_view_num_columns', 3, 'INT');
-$image_class = $this->params['configs']->get('jg_category_view_image_class', 0, 'INT');
-$justified_height = $this->params['configs']->get('jg_category_view_justified_height', 200, 'INT');
-$justified_gap = $this->params['configs']->get('jg_category_view_justified_gap', 5, 'INT');
-$image_link = $this->params['configs']->get('jg_category_view_image_link', 'defaultview', 'STRING');
-$lightbox_image = $this->params['configs']->get('jg_category_view_lightbox_image', 'detail', 'STRING');
-$pagination_type = $this->params['configs']->get('jg_category_view_pagination', 0, 'INT');
-$show_subcategories = $this->params['configs']->get('jg_category_view_subcategories', 1, 'INT');
-$subcategory_type_image = $this->params['configs']->get('jg_category_view_type_subcategory_image', 'thumbnail', 'STRING');
-$num_columns_subcats = $this->params['configs']->get('jg_category_view_subcategories_num_columns', 3, 'INT');
-
-// Import CSS & JS
-$wa = $this->document->getWebAssetManager();
-
-if ($gallery_class == 'masonry') {
- $wa->useScript('com_joomgallery.masonry');
-}
-
-if ($gallery_class == 'justified') {
- $wa->useScript('com_joomgallery.justified');
- $wa->addInlineStyle('.jg-images[class*=" justified-"] .jg-image-caption-hover { right: ' . $justified_gap . 'px; }');
-}
-
-$lightbox = false;
-if ($image_link == 'lightgallery') {
- $lightbox = true;
- $wa->useScript('com_joomgallery.lightgallery');
- $wa->useScript('com_joomgallery.lg-thumbnail');
- $wa->useStyle('com_joomgallery.lightgallery-bundle');
-}
-
-// Initialise the grid script
-$iniJS = 'window.joomGrid = {';
-$iniJS .= ' itemid: ' . $this->item->id . ',';
-$iniJS .= ' pagination: ' . $pagination_type . ',';
-$iniJS .= ' layout: "' . $gallery_class . '",';
-$iniJS .= ' num_columns: ' . $num_columns . ',';
-$iniJS .= ' lightbox: ' . ($lightbox ? 'true' : 'false') . ',';
-$iniJS .= ' justified: {height: ' . $justified_height . ', gap: ' . $justified_gap . '}';
-$iniJS .= '};';
-
-$wa->addInlineScript($iniJS, ['position' => 'before'], [], ['com_joomgallery.joomgrid']);
-$wa->useScript('com_joomgallery.joomgrid');
-
-// Access check
-$canEdit = $this->getAcl()->checkACL('edit', 'com_joomgallery.category', $this->item->id, $this->item->parent_id, true);
-$canAdd = $this->getAcl()->checkACL('add', 'com_joomgallery.image', 0, $this->item->id, true);
-$canDelete = $this->getAcl()->checkACL('delete', 'com_joomgallery.category', $this->item->id, $this->item->parent_id, true);
-$canCheckin = $this->getAcl()->checkACL('editstate', 'com_joomgallery.category', $this->item->id, $this->item->parent_id, true) || $this->item->checked_out == Factory::getUser()->id;
-$returnURL = base64_encode(JoomHelper::getViewRoute('category', $this->item->id, $this->item->parent_id, $this->item->language, $this->getLayout()));
-
-$hasSubcats = $show_subcategories && !empty($this->item->children->items) && count($this->item->children->items) > 0;
-$hasImages = !empty($this->item->images->items) && count($this->item->images->items) > 0;
-?>
-
-
diff --git a/src/html/com_joomgallery/category/index.html b/src/html/com_joomgallery/category/index.html
deleted file mode 100644
index 2efb97f..0000000
--- a/src/html/com_joomgallery/category/index.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/html/com_joomgallery/gallery/default.php b/src/html/com_joomgallery/gallery/default.php
deleted file mode 100644
index fcf5105..0000000
--- a/src/html/com_joomgallery/gallery/default.php
+++ /dev/null
@@ -1,148 +0,0 @@
-
- *
- * This file is part of a Moko Consulting project.
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- *
- * FILE INFORMATION
- * DEFGROUP: MokoOnyx.Override
- * INGROUP: MokoOnyx
- * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
- * PATH: /html/com_joomgallery/gallery/default.php
-<<<<<<< HEAD
-<<<<<<< HEAD
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
- * BRIEF: Gallery view override — main image grid with masonry/justified layout
- */
-
-// No direct access
-defined('_JEXEC') or die;
-
-use Joomla\CMS\Router\Route;
-use Joomla\CMS\Language\Text;
-use Joomla\CMS\Layout\LayoutHelper;
-
-// Image params
-$image_type = $this->params['configs']->get('jg_gallery_view_type_image', 'thumbnail', 'STRING');
-$gallery_class = $this->params['configs']->get('jg_gallery_view_class', 'masonry', 'STRING');
-$num_columns = $this->params['configs']->get('jg_gallery_view_num_columns', 3, 'INT');
-$image_class = $this->params['configs']->get('jg_gallery_view_image_class', 0, 'INT');
-$justified_height = $this->params['configs']->get('jg_gallery_view_justified_height', 200, 'INT');
-$justified_gap = $this->params['configs']->get('jg_gallery_view_justified_gap', 5, 'INT');
-$image_link = $this->params['configs']->get('jg_gallery_view_image_link', 'defaultview', 'STRING');
-$lightbox_image = $this->params['configs']->get('jg_category_view_lightbox_image', 'detail', 'STRING');
-$browse_categories_link = $this->params['configs']->get('jg_gallery_view_browse_categories_link', 1, 'INT');
-
-// Import CSS & JS
-$wa = $this->document->getWebAssetManager();
-$wa->useStyle('com_joomgallery.site');
-$wa->useStyle('com_joomgallery.jg-icon-font');
-
-if ($gallery_class == 'masonry') {
- $wa->useScript('com_joomgallery.masonry');
-}
-
-if ($gallery_class == 'justified') {
- $wa->useScript('com_joomgallery.justified');
- $wa->addInlineStyle('.jg-images[class*=" justified-"] .jg-image-caption-hover { right: ' . $justified_gap . 'px; }');
-}
-
-$lightbox = false;
-if ($image_link == 'lightgallery') {
- $lightbox = true;
- $wa->useScript('com_joomgallery.lightgallery');
- $wa->useScript('com_joomgallery.lg-thumbnail');
- $wa->useStyle('com_joomgallery.lightgallery-bundle');
-}
-
-// Initialise the grid script
-$iniJS = 'window.joomGrid = {';
-$iniJS .= ' itemid: ' . $this->item->id . ',';
-$iniJS .= ' pagination: 0,';
-$iniJS .= ' layout: "' . $gallery_class . '",';
-$iniJS .= ' num_columns: ' . $num_columns . ',';
-$iniJS .= ' lightbox: ' . ($lightbox ? 'true' : 'false') . ',';
-$iniJS .= ' justified: {height: ' . $justified_height . ', gap: ' . $justified_gap . '}';
-$iniJS .= '};';
-
-$wa->addInlineScript($iniJS, ['position' => 'before'], [], ['com_joomgallery.joomgrid']);
-$wa->useScript('com_joomgallery.joomgrid');
-?>
-
-
diff --git a/src/html/com_joomgallery/gallery/index.html b/src/html/com_joomgallery/gallery/index.html
deleted file mode 100644
index 2efb97f..0000000
--- a/src/html/com_joomgallery/gallery/index.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/html/com_joomgallery/image/default.php b/src/html/com_joomgallery/image/default.php
deleted file mode 100644
index 7a6748e..0000000
--- a/src/html/com_joomgallery/image/default.php
+++ /dev/null
@@ -1,259 +0,0 @@
-
- *
- * This file is part of a Moko Consulting project.
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- *
- * FILE INFORMATION
- * DEFGROUP: MokoOnyx.Override
- * INGROUP: MokoOnyx
- * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
- * PATH: /html/com_joomgallery/image/default.php
-<<<<<<< HEAD
-<<<<<<< HEAD
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
- * BRIEF: Image detail view override — single image with metadata, tags, custom fields
- */
-
-// No direct access
-defined('_JEXEC') or die;
-
-use Joomla\CMS\Factory;
-use Joomla\CMS\Router\Route;
-use Joomla\CMS\Language\Text;
-use Joomla\CMS\Session\Session;
-use Joomla\CMS\HTML\HTMLHelper;
-use Joomla\CMS\Layout\FileLayout;
-use Joomla\CMS\User\UserFactoryInterface;
-use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
-use Joomgallery\Component\Joomgallery\Administrator\Helper\JoomHelper;
-
-// Image params
-$image_type = $this->params['configs']->get('jg_detail_view_type_image', 'detail', 'STRING');
-$show_title = $this->params['configs']->get('jg_detail_view_show_title', 0, 'INT');
-$show_category = $this->params['configs']->get('jg_detail_view_show_category', 0, 'INT');
-$show_description = $this->params['configs']->get('jg_detail_view_show_description', 0, 'INT');
-$show_imgdate = $this->params['configs']->get('jg_detail_view_show_imgdate', 0, 'INT');
-$show_imgauthor = $this->params['configs']->get('jg_detail_view_show_imgauthor', 0, 'INT');
-$show_created_by = $this->params['configs']->get('jg_detail_view_show_created_by', 0, 'INT');
-$show_votes = $this->params['configs']->get('jg_detail_view_show_votes', 0, 'INT');
-$show_rating = $this->params['configs']->get('jg_detail_view_show_rating', 0, 'INT');
-$show_hits = $this->params['configs']->get('jg_detail_view_show_hits', 0, 'INT');
-$show_downloads = $this->params['configs']->get('jg_detail_view_show_downloads', 0, 'INT');
-$show_tags = $this->params['configs']->get('jg_detail_view_show_tags', 0, 'INT');
-$show_metadata = $this->params['configs']->get('jg_detail_view_show_metadata', 0, 'INT');
-
-// Import CSS & JS
-$wa = $this->document->getWebAssetManager();
-$wa->useStyle('com_joomgallery.site');
-$wa->useStyle('com_joomgallery.jg-icon-font');
-
-// Access check
-$canEdit = $this->getAcl()->checkACL('edit', 'com_joomgallery.image', $this->item->id, $this->item->catid, true);
-$canDelete = $this->getAcl()->checkACL('delete', 'com_joomgallery.image', $this->item->id, $this->item->catid, true);
-$canCheckin = $this->getAcl()->checkACL('editstate', 'com_joomgallery.image', $this->item->id, $this->item->catid, true) || $this->item->checked_out == Factory::getUser()->id;
-$returnURL = base64_encode(JoomHelper::getViewRoute('image', $this->item->id, $this->item->catid, $this->item->language, $this->getLayout()));
-
-// Tags
-$tagLayout = new FileLayout('joomgallery.content.tags');
-$tags = $tagLayout->render($this->item->tags);
-
-// Metadata
-$metadataLayout = new FileLayout('joomgallery.content.metadata');
-$metadata = $metadataLayout->render($this->item->imgmetadata);
-
-// Custom Fields
-$fields = FieldsHelper::getFields('com_joomgallery.image', $this->item);
-
-// Check if we have any info rows to show
-$hasInfo = $show_category || $show_imgdate || $show_imgauthor || $show_created_by
- || $show_votes || $show_rating || $show_hits || $show_downloads
- || $show_tags || $show_metadata || count($fields) > 0;
-?>
-
-
diff --git a/src/html/com_joomgallery/image/index.html b/src/html/com_joomgallery/image/index.html
deleted file mode 100644
index 2efb97f..0000000
--- a/src/html/com_joomgallery/image/index.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/html/layouts/joomla/module/card.php b/src/html/layouts/joomla/module/card.php
index 3e737e0..3c6071d 100644
--- a/src/html/layouts/joomla/module/card.php
+++ b/src/html/layouts/joomla/module/card.php
@@ -10,17 +10,7 @@
* INGROUP: MokoOnyx
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: /html/layouts/joomla/module/card.php
-<<<<<<< HEAD
-<<<<<<< HEAD
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
+ * VERSION: 02.18.03
* BRIEF: Custom card module chrome — renders module titles for all modules
*/
diff --git a/src/html/layouts/mokoonyx/article-metadata.php b/src/html/layouts/mokoonyx/article-metadata.php
index c7cdb8f..45a27be 100644
--- a/src/html/layouts/mokoonyx/article-metadata.php
+++ b/src/html/layouts/mokoonyx/article-metadata.php
@@ -11,17 +11,7 @@
* INGROUP: MokoOnyx.Layouts
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: /src/html/layouts/mokoonyx/article-metadata.php
-<<<<<<< HEAD
-<<<<<<< HEAD
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
+ * VERSION: 02.18.03
* BRIEF: Article metadata footer layout -- renders jcfields grouped by field group
*/
diff --git a/src/media/css/a11y-high-contrast.css b/src/media/css/a11y-high-contrast.css
index 4101ca4..39c8e45 100644
--- a/src/media/css/a11y-high-contrast.css
+++ b/src/media/css/a11y-high-contrast.css
@@ -10,17 +10,7 @@
* INGROUP: MokoOnyx.Accessibility
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: ./media/css/a11y-high-contrast.css
-<<<<<<< HEAD
-<<<<<<< HEAD
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
-=======
- * VERSION: 02.18.00
->>>>>>> origin/main
->>>>>>> origin/main
+ * VERSION: 02.18.03
* BRIEF: High-contrast stylesheet for accessibility toolbar
*/
diff --git a/src/script.php b/src/script.php
index d78ceb6..c48027e 100644
--- a/src/script.php
+++ b/src/script.php
@@ -93,6 +93,7 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface
$this->replaceCassiopeiaReferences();
$this->clearFaviconStamp();
$this->cleanMediaFolder();
+ $this->removeDeletedFiles();
$this->lockExtension();
}
@@ -483,6 +484,68 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface
}
}
+ /**
+ * Remove files and directories that were shipped in previous versions
+ * but have since been deleted from the package.
+ *
+ * Joomla's installer never deletes files on upgrade — it only
+ * adds/overwrites. This method fills that gap so stale overrides
+ * and deprecated assets don't linger on disk.
+ *
+ * Maintain this list: when you delete a file from the repo, add its
+ * path here (relative to the template root) so existing installs
+ * get cleaned up on the next update.
+ */
+ private function removeDeletedFiles(): void
+ {
+ $templateRoot = JPATH_ROOT . '/templates/' . self::NEW_NAME;
+
+ // Paths relative to templates/mokoonyx/
+ $deletedFiles = [
+ // JoomGallery template overrides — removed in 02.19.00
+ 'html/com_joomgallery/category/default.php',
+ 'html/com_joomgallery/category/default_cat.php',
+ 'html/com_joomgallery/category/index.html',
+ 'html/com_joomgallery/gallery/default.php',
+ 'html/com_joomgallery/gallery/index.html',
+ 'html/com_joomgallery/image/default.php',
+ 'html/com_joomgallery/image/index.html',
+ ];
+
+ // Directories to remove (only if empty after file deletion)
+ $deletedDirs = [
+ 'html/com_joomgallery/image',
+ 'html/com_joomgallery/gallery',
+ 'html/com_joomgallery/category',
+ 'html/com_joomgallery',
+ ];
+
+ $removed = 0;
+
+ foreach ($deletedFiles as $relPath) {
+ $file = $templateRoot . '/' . $relPath;
+ if (is_file($file)) {
+ @unlink($file);
+ $removed++;
+ }
+ }
+
+ foreach ($deletedDirs as $relPath) {
+ $dir = $templateRoot . '/' . $relPath;
+ if (is_dir($dir)) {
+ // Only remove if empty
+ $entries = @scandir($dir);
+ if ($entries && count($entries) <= 2) { // . and .. only
+ @rmdir($dir);
+ }
+ }
+ }
+
+ if ($removed > 0) {
+ $this->logMessage("Removed {$removed} deprecated file(s) from previous versions.");
+ }
+ }
+
private function logMessage(string $message, string $priority = 'info'): void
{
$priorities = [
diff --git a/src/templateDetails.xml b/src/templateDetails.xml
index 90f2891..fadc206 100644
--- a/src/templateDetails.xml
+++ b/src/templateDetails.xml
@@ -36,11 +36,7 @@
mokoonyx
-<<<<<<< HEAD
- 02.18.00
-=======
- 02.18.00
->>>>>>> origin/main
+ 02.18.03-dev
script.php
2026-05-16
Jonathan Miller || Moko Consulting
diff --git a/updates.xml b/updates.xml
index 19fa583..81165d5 100644
--- a/updates.xml
+++ b/updates.xml
@@ -1,7 +1,7 @@
@@ -11,13 +11,13 @@
mokoonyx
template
site
- 02.16.03-dev
- 2026-06-03
+ 02.18.03-dev
+ 2026-06-04
https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/development
- https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/development/tpl_mokoonyx-02.16.03-dev.zip
+ https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/development/tpl_mokoonyx-02.18.03-dev.zip
- 24d67eb360fb9dbc40dfdb5b37167a9fabc8ca9b518987a8fc978a93b53731dc
+ 5ae848d5bf54e9c3ba4f3255e023658635e3371979bf88df38cb1478b98aeee6
dev
https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md
Moko Consulting