10 Commits

Author SHA1 Message Date
gitea-actions[bot] 4b45e57c5b chore(version): pre-release bump to 02.26.00-rc [skip ci] 2026-06-20 21:35:27 +00:00
Jonathan Miller 6f2e903048 merge: update rc from main
Universal: Auto Version Bump / Version Bump (push) Successful in 6s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 11s
Resolved conflicts by accepting main's versions. Removed stale src/
files (renamed to source/) and deleted updates.xml.
2026-06-20 16:34:00 -05:00
jmiller 5bc3b049e3 chore: sync updates.xml 02.22.00 from main [skip ci] 2026-06-18 17:07:20 +00:00
jmiller 1424e3aeea chore: sync updates.xml 02.20.00 from main [skip ci] 2026-06-04 15:53:57 +00:00
jmiller b87afa03a2 chore: sync updates.xml 02.20.00 from main [skip ci] 2026-06-04 14:03:31 +00:00
jmiller 9a40286ff0 chore: sync updates.xml 02.19.00 from main [skip ci] 2026-06-04 12:18:59 +00:00
jmiller 5e11138bc4 chore: sync updates.xml 02.18.00 from main [skip ci] 2026-06-02 19:40:39 +00:00
jmiller c237e7a178 chore: sync updates.xml 02.17.00 from main [skip ci] 2026-06-02 19:04:35 +00:00
gitea-actions[bot] d6bb35d89e chore: update channels for 02.17.00-rc [skip ci] 2026-05-30 23:37:29 +00:00
gitea-actions[bot] f6e8c2f171 chore(release): build 02.17.00-rc [skip ci] 2026-05-30 23:37:22 +00:00
62 changed files with 1887 additions and 3773 deletions
View File
+3 -3
View File
@@ -1,6 +1,6 @@
# MokoOnyx
Joomla site template — successor to MokoCassiopeia. Base template for all MokoSuite client deployments.
Joomla site template — successor to MokoCassiopeia. Base template for all WaaS client deployments.
## Quick Reference
@@ -53,8 +53,8 @@ Client repos (`client-clarksvillefurs`, `client-optainfunding`, etc.) install `t
- **Attribution**: `Authored-by: Moko Consulting`
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
- **Minification**: handled at build time (CI) and runtime (MokoMinifyHelper)
- **Wiki**: documentation lives in the MokoGitea wiki, not `docs/` files
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)
- **Wiki**: documentation lives in the Gitea wiki, not `docs/` files
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)
## Coding Standards
+1 -1
View File
@@ -8,7 +8,7 @@ contact_links:
url: https://mokoconsulting.tech/
about: Get help or ask questions through our website
- name: MokoStandards Documentation
url: https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki
url: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
about: View our coding standards and best practices
- name: Report a Security Vulnerability
url: https://git.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new
+1 -1
View File
@@ -37,7 +37,7 @@ If you have ideas about how this could be implemented, share them here:
Add any other context, mockups, or screenshots about the feature request here.
## Relevant Standards
Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)?
Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)?
- [ ] Accessibility (WCAG 2.1 AA)
- [ ] Localization (en_US/en_GB)
- [ ] Security best practices
+1 -1
View File
@@ -35,7 +35,7 @@ Use this template only for:
<!-- Describe how this could be addressed -->
## Standards Reference
Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)?
Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)?
- [ ] SPDX license identifiers
- [ ] Secret management
- [ ] Dependency security
+5 -5
View File
@@ -1,8 +1,8 @@
---
name: MokoSuite Client Site Issue
about: Report an issue with a MokoSuite client site (branding, deployment, media sync)
name: WaaS Client Site Issue
about: Report an issue with a WaaS client site (branding, deployment, media sync)
title: '[WAAS] '
labels: 'mokosuite, client-site'
labels: 'waas, client-site'
assignees: ''
---
@@ -18,7 +18,7 @@ assignees: ''
## Client Site
- **Client Org**: [e.g., ClarksvilleFurs]
- **Repo**: [e.g., client-mokosuite-clarksvillefurs]
- **Repo**: [e.g., client-waas-clarksvillefurs]
- **Environment**: [Dev / Production]
- **Site URL**: [dev or production URL omit if private]
@@ -52,7 +52,7 @@ Attach screenshots showing the issue (desktop and mobile if relevant).
## Template Details
- **Joomla Version**: [e.g., 5.x]
- **Template Name**: [e.g., clienttemplate]
- **MokoSuite Plugin**: [Active / Inactive]
- **MokoWaaS Plugin**: [Active / Inactive]
- **MokoOnyx Admin**: [Active / Inactive]
## CSS Custom Properties
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Moko Platform Repository Manifest
See: https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home
-->
<moko-platform xmlns="https://standards.mokoconsulting.tech/moko-platform/1.0" schema-version="1.0">
<identity>
<name>MokoOnyx</name>
<display-name>Template - MokoOnyx</display-name>
<org>MokoConsulting</org>
<description>MokoOnyx - Joomla site template (successor to MokoCassiopeia)</description>
<version>02.26.00</version>
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
</identity>
<governance>
<platform>joomla</platform>
<standards-version>04.07.00</standards-version>
<standards-source>https://git.mokoconsulting.tech/MokoConsulting/moko-platform</standards-source>
<last-synced>2026-05-10T19:51:09+00:00</last-synced>
</governance>
<build>
<language>PHP</language>
<package-type>joomla</package-type>
<entry-point>src/</entry-point>
</build>
</moko-platform>
+66 -67
View File
@@ -1,67 +1,66 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
name: "Universal: Auto Version Bump"
on:
push:
branches:
- dev
- rc
- 'feature/**'
- 'patch/**'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
jobs:
bump:
name: Version Bump
runs-on: release
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request') &&
!startsWith(github.event.repository.name, 'Template-')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup mokocli tools
run: |
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
if [ -d "/opt/mokocli/cli" ]; then
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
else
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/MokoCLI.git" \
/tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
fi
- name: Bump version
run: |
php ${MOKO_CLI}/version_auto_bump.php \
--path . --branch "${GITHUB_REF_NAME}" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--repo-url "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
name: "Universal: Auto Version Bump"
on:
push:
branches:
- dev
- rc
- 'feature/**'
- 'patch/**'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
jobs:
bump:
name: Version Bump
runs-on: release
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup mokocli tools
run: |
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
if [ -d "/opt/mokocli/cli" ]; then
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
else
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \
/tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
fi
- name: Bump version
run: |
php ${MOKO_CLI}/version_auto_bump.php \
--path . --branch "${GITHUB_REF_NAME}" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--repo-url "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
+46 -140
View File
@@ -3,16 +3,16 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/auto-release.yml
# VERSION: 05.01.00
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
# PATH: /templates/workflows/universal/auto-release.yml.template
# VERSION: 05.00.00
# BRIEF: Universal build & release detects platform from manifest.xml
#
# +=======================================================================+
# +========================================================================+
# | UNIVERSAL BUILD & RELEASE PIPELINE |
# +=======================================================================+
# +========================================================================+
# | |
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
# | |
@@ -21,24 +21,15 @@
# | dolibarr: mod*.class.php, update.txt, dev version reset |
# | generic: README-only, no update stream |
# | |
# +=======================================================================+
# +========================================================================+
name: "Universal: Build & Release"
on:
pull_request:
types: [opened, synchronize, closed]
types: [opened, closed]
branches:
- main
paths-ignore:
- '.mokogitea/workflows/**'
- '*.md'
- 'wiki/**'
- '.editorconfig'
- '.gitignore'
- '.gitattributes'
- '.gitmessage'
- 'LICENSE'
workflow_dispatch:
inputs:
action:
@@ -52,7 +43,7 @@ on:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
@@ -60,18 +51,13 @@ permissions:
contents: write
jobs:
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────────
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────
promote-rc:
name: Promote to RC
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
!startsWith(github.event.repository.name, 'Template-') &&
(
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
(github.event.action == 'synchronize' && github.event.pull_request.merged != true) ||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
)
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
steps:
- name: Checkout repository
@@ -79,7 +65,6 @@ jobs:
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
submodules: recursive
- name: Setup mokocli tools
env:
@@ -95,7 +80,7 @@ jobs:
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet
@@ -104,46 +89,18 @@ jobs:
- name: Rename branch to rc
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
AUTH="Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}"
FROM="${{ github.event.pull_request.head.ref || 'dev' }}"
PR="${{ github.event.pull_request.number }}"
# Resolve the source branch HEAD commit.
SRC_JSON=$(curl -sf -H "$AUTH" "${API_BASE}/branches/${FROM}") \
|| { echo "::error::Source branch ${FROM} not found"; exit 1; }
SRC_SHA=$(printf '%s' "$SRC_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['commit']['id'])" 2>/dev/null || true)
[ -n "$SRC_SHA" ] || { echo "::error::Could not resolve HEAD of ${FROM}"; exit 1; }
# Point rc at the source commit. If rc already exists (a protected branch that
# cannot be deleted), force-update its ref in place instead of delete+recreate:
# deleting a protected branch fails, which then makes the recreate return HTTP 409.
if curl -sf -o /dev/null -H "$AUTH" "${API_BASE}/branches/rc"; then
echo "rc exists - force-updating to ${FROM} (${SRC_SHA})"
curl -sf -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/git/refs/heads/rc" -d "{\"sha\":\"${SRC_SHA}\",\"force\":true}" \
|| { echo "::error::Failed to force-update rc (CI token needs force-push on the protected rc branch)"; exit 1; }
else
echo "Creating rc from ${FROM}"
curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/branches" -d "{\"new_branch_name\":\"rc\",\"old_branch_name\":\"${FROM}\"}" \
|| { echo "::error::Failed to create rc from ${FROM}"; exit 1; }
fi
# Repoint the PR at rc, then delete the old source branch (non-fatal).
if [ -n "$PR" ]; then
curl -s -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/pulls/${PR}" -d '{"head":"rc"}' >/dev/null || true
fi
curl -s -X DELETE -H "$AUTH" "${API_BASE}/branches/${FROM}" >/dev/null || true
echo "Renamed ${FROM} -> rc"
php ${MOKO_CLI}/branch_rename.php \
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
--pr "${{ github.event.pull_request.number }}"
- name: Checkout rc and configure git
run: |
git fetch origin rc
git checkout rc
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "mokogitea-actions[bot]"
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
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: Publish RC release
@@ -154,7 +111,7 @@ jobs:
- name: Update RC release notes from CHANGELOG.md
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Extract [Unreleased] section from changelog
@@ -192,17 +149,13 @@ jobs:
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
# ── Merged PR → Build & Release (or promote RC to stable) ─────────────────────────
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
release:
name: Build & Release Pipeline
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
!startsWith(github.event.repository.name, 'Template-') &&
(
github.event.pull_request.merged == true ||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
)
github.event.pull_request.merged == true ||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
steps:
- name: Checkout repository
@@ -210,12 +163,11 @@ jobs:
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 0
submodules: recursive
- name: Configure git for bot pushes
run: |
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "mokogitea-actions[bot]"
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
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
@@ -246,19 +198,13 @@ jobs:
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
fi
- name: "Detect platform"
id: platform
run: |
php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
php ${MOKO_CLI}/manifest_read.php --path . --github-output 2>/dev/null || true
- name: "Determine version bump level"
id: bump
run: |
@@ -282,57 +228,9 @@ jobs:
--path . --stability stable ${BUMP_FLAG} --branch main \
--token "${{ secrets.MOKOGITEA_TOKEN }}"
- name: "Read published version"
id: version
run: |
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "")
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
[ -z "$VERSION" ] && VERSION="00.00.00" && echo "skip=true" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
PLATFORM="${{ steps.platform.outputs.platform }}"
if [[ "$PLATFORM" == joomla* ]]; then
echo "tag=stable" >> "$GITHUB_OUTPUT"
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
else
echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
echo "release_tag=v${VERSION}" >> "$GITHUB_OUTPUT"
fi
echo "branch=main" >> "$GITHUB_OUTPUT"
echo "Published version: ${VERSION}"
- name: "Create semver tag for non-Joomla repos"
id: semver
if: |
steps.version.outputs.skip != 'true' &&
!startsWith(steps.platform.outputs.platform, 'joomla')
run: |
VERSION="${{ steps.version.outputs.version }}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
SEMVER_TAG="v${VERSION}"
echo "Creating semver tag: ${SEMVER_TAG}"
# Create the git tag via API
HTTP_CODE=$(curl -sf -o /dev/null -w "%{http_code}" \
-X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API_BASE}/tags" \
-d "{\"tag_name\":\"${SEMVER_TAG}\",\"target\":\"main\",\"message\":\"Release ${VERSION}\"}" 2>/dev/null || echo "000")
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then
echo "Created semver tag: ${SEMVER_TAG}"
elif [ "$HTTP_CODE" = "409" ]; then
echo "Semver tag ${SEMVER_TAG} already exists (skipped)"
else
echo "::warning::Failed to create semver tag ${SEMVER_TAG} (HTTP ${HTTP_CODE})"
fi
echo "semver_tag=${SEMVER_TAG}" >> "$GITHUB_OUTPUT"
- name: Update release notes and promote changelog
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Get the stable release info (version and ID)
@@ -382,7 +280,7 @@ jobs:
content = open('CHANGELOG.md').read()
old = '## [Unreleased]'
new = f'## [Unreleased]\n\n## [{version}] --- {date}'
content = content if ('## [' + version + ']') in content else content.replace(old, new, 1)
content = content.replace(old, new, 1)
open('CHANGELOG.md', 'w').write(content)
" "$VERSION" "$DATE"
git add CHANGELOG.md
@@ -401,7 +299,7 @@ jobs:
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_mirror.php \
--version "$VERSION" --tag "$RELEASE_TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
@@ -426,11 +324,11 @@ jobs:
&& echo "main branch pushed to GitHub mirror" \
|| echo "WARNING: GitHub mirror push failed"
- name: "Step 11: Delete rc branch (dev reset moved to cascade-dev.yml)"
- name: "Step 11: Delete rc branch and recreate dev from main"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Delete rc branch (ephemeral — created by promote-rc)
@@ -438,15 +336,23 @@ jobs:
"${API_BASE}/branches/rc" 2>/dev/null \
&& echo "Deleted rc branch" || echo "rc branch not found"
# dev is reset from main by the dedicated "Cascade Main -> Dev" workflow
# (cascade-dev.yml), which runs after this release completes.
echo "rc cleaned; dev reset handled by cascade-dev.yml" >> $GITHUB_STEP_SUMMARY
# Delete dev branch
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
# Recreate dev from main (now includes version bump + changelog promotion)
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API_BASE}/branches" \
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
echo "Pre-release branches cleaned, dev reset from main" >> $GITHUB_STEP_SUMMARY
- name: "Step 12: Create version branch from main"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
BRANCH_NAME="version/${VERSION}"
@@ -467,7 +373,7 @@ jobs:
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/version_reset_dev.php \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
--branch dev --path . 2>&1 || true
@@ -493,5 +399,5 @@ jobs:
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${MOKOGITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
fi
+3 -4
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/branch-cleanup.yml
# VERSION: 01.00.00
# BRIEF: Delete feature branches after PR merge
@@ -33,8 +33,7 @@ jobs:
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
# URL-encode the branch name's slashes (no PHP dependency on the runner)
ENCODED=$(printf '%s' "${BRANCH}" | sed 's|/|%2F|g')
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
+7 -103
View File
@@ -1,106 +1,10 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Cascade
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/cascade-dev.yml
# VERSION: 02.00.00
# BRIEF: Cascade main -> dev via PR; auto-merge only if conflict-free, else notify
name: "Cascade Main -> Dev"
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
pull-requests: write
env:
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
# ntfy destination is configured via repo or org variables (org vars are inherited).
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.CASCADE_NTFY_TOPIC || vars.NTFY_TOPIC || 'gitea-releases' }}
# DISABLED — auto-release Step 11 recreates dev from main after every release.
# Cascade-dev is redundant and causes version conflicts when both main and dev
# have different version numbers in templateDetails.xml / manifest.xml.
name: "Cascade Main → Dev (DISABLED)"
on: workflow_dispatch
jobs:
cascade:
name: Cascade main -> dev
noop:
runs-on: ubuntu-latest
steps:
- name: Open main -> dev PR (auto-merge if clean, else notify)
env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }}
run: |
set -uo pipefail
API="${MOKOGITEA_URL}/api/v1/repos/${REPO}"
AUTH="Authorization: token ${TOKEN}"
jqnum() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; }
# 0. dev must exist
if ! curl -sf -H "$AUTH" "${API}/branches/dev" >/dev/null 2>&1; then
echo "No dev branch - nothing to cascade."; exit 0
fi
# 1. is main ahead of dev?
AHEAD=$(curl -sf -H "$AUTH" "${API}/compare/dev...main" \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('total_commits',0))" 2>/dev/null || echo 0)
if [ "${AHEAD:-0}" -eq 0 ]; then
echo "dev already up to date with main."; exit 0
fi
echo "main is ${AHEAD} commit(s) ahead of dev."
# 2. reuse an open main->dev PR, else create one
PR=$(curl -sf -H "$AUTH" "${API}/pulls?state=open&base=dev" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(next((str(p['number']) for p in d if p.get('head',{}).get('ref')=='main'), ''))" 2>/dev/null || echo "")
if [ -z "$PR" ]; then
RESP=$(curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/pulls" \
-d '{"head":"main","base":"dev","title":"chore(sync): cascade main -> dev","body":"Automated cascade of main into dev. Auto-merges only if conflict-free; otherwise left open for manual resolution."}')
PR=$(printf '%s' "$RESP" | jqnum number)
if [ -z "$PR" ]; then
echo "::warning::Could not open cascade PR: $RESP"; exit 0
fi
echo "Opened cascade PR #${PR}"
else
echo "Reusing open cascade PR #${PR}"
fi
# 3. wait for MokoGitea to compute mergeability (conflict detection)
MERGEABLE=""
for _ in 1 2 3 4 5 6; do
MERGEABLE=$(curl -sf -H "$AUTH" "${API}/pulls/${PR}" | jqnum mergeable)
case "$MERGEABLE" in True|False) break ;; esac
sleep 3
done
echo "mergeable=${MERGEABLE}"
notify() {
curl -sS \
-H "Title: ${REPO}: dev cascade needs manual merge" \
-H "Tags: warning,twisted_rightwards_arrows" \
-H "Priority: high" \
-H "Click: ${MOKOGITEA_URL}/${REPO}/pulls/${PR}" \
-d "main -> dev cascade PR #${PR} $1 It was NOT auto-merged; resolve it manually." \
"${NTFY_URL}/${NTFY_TOPIC}" || true
}
# 4. auto-merge only if conflict-free; otherwise notify
if [ "$MERGEABLE" = "True" ]; then
CODE=$(curl -s -o /tmp/merge.json -w "%{http_code}" -H "$AUTH" -H "Content-Type: application/json" \
-X POST "${API}/pulls/${PR}/merge" -d '{"Do":"merge","merge_when_checks_succeed":true}')
if [ "$CODE" -ge 200 ] && [ "$CODE" -lt 300 ]; then
echo "Cascade PR #${PR} merged (or scheduled to merge when checks pass)."
else
echo "::warning::Auto-merge returned HTTP ${CODE}: $(cat /tmp/merge.json)"
notify "could not be auto-merged (HTTP ${CODE})."
fi
else
echo "::warning::Cascade PR #${PR} has conflicts (mergeable=${MERGEABLE}); sending notification."
notify "has conflicts and cannot be merged automatically."
fi
- run: echo "Cascade disabled — auto-release handles dev recreation"
+3 -9
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/ci-generic.yml
# PATH: /.gitea/workflows/ci-generic.yml
# VERSION: 01.00.00
# BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js)
@@ -32,8 +32,6 @@ jobs:
lint:
name: Lint & Validate
runs-on: ubuntu-latest
# Skip on template repos (Template-*) — they hold placeholder scaffolding, not buildable source.
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Checkout
@@ -131,11 +129,7 @@ jobs:
test:
name: Tests
runs-on: ubuntu-latest
# Independent job (no `needs: lint`): the Gitea Actions scheduler does not
# offer the dependent 2nd job of a needs-chain to runners, so it stalls in
# "waiting" and is reaped by ABANDONED_JOB_TIMEOUT. Guard template repos
# directly (same condition lint uses) instead of gating on lint's result.
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
needs: lint
steps:
- name: Checkout
@@ -1,68 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/ci-issue-reporter.yml
# VERSION: 01.00.00
# BRIEF: Reusable workflow — creates/updates a MokoGitea issue when a CI gate fails.
# Clones MokoCLI and runs cli/ci_issue_reporter.sh.
name: "Universal: CI Issue Reporter"
on:
workflow_call:
inputs:
gate:
description: "CI gate name (e.g. PR Validation, Repository Health)"
required: true
type: string
details:
description: "Human-readable failure description"
required: true
type: string
severity:
description: "error or warning"
required: false
type: string
default: "error"
workflow:
description: "Workflow name for the issue title"
required: false
type: string
default: ""
secrets:
MOKOGITEA_TOKEN:
required: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
report:
name: "Report: ${{ inputs.gate }}"
runs-on: ubuntu-latest
steps:
- name: Clone MokoCLI
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 --filter=blob:none --sparse "${MOKOGITEA_URL}/MokoConsulting/MokoCLI.git" /tmp/mokocli
cd /tmp/mokocli && git sparse-checkout set cli/ci_issue_reporter.sh
- name: Report CI failure
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x /tmp/mokocli/cli/ci_issue_reporter.sh
/tmp/mokocli/cli/ci_issue_reporter.sh \
--gate "${{ inputs.gate }}" \
--details "${{ inputs.details }}" \
--severity "${{ inputs.severity }}" \
--workflow "${{ inputs.workflow }}"
+7 -7
View File
@@ -45,17 +45,17 @@ jobs:
fi
php -v && composer --version
- name: Setup mokocli tools
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.GA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.MOKOGITEA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
run: |
if [ -d "/opt/mokocli" ] || [ -d "/tmp/mokocli" ]; then
echo "mokocli already available on runner — skipping clone"
if [ -d "/tmp/moko-platform" ] || [ -d "/opt/moko-platform" ]; then
echo "moko-platform already available on runner — skipping clone"
else
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git" \
/tmp/mokocli 2>/dev/null || echo "mokocli clone skipped — continuing without it"
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
/tmp/moko-platform 2>/dev/null || echo "moko-platform clone skipped — continuing without it"
fi
- name: Install dependencies
+13 -13
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Maintenance
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.mokogitea/workflows/cleanup.yml
# PATH: /.gitea/workflows/cleanup.yml
# VERSION: 01.00.00
# BRIEF: Scheduled cleanup — delete merged branches and old workflow runs
@@ -21,7 +21,7 @@ permissions:
contents: write
env:
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
cleanup:
@@ -33,30 +33,30 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
token: ${{ secrets.GA_TOKEN }}
- name: Delete merged branches
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
echo "=== Merged Branch Cleanup ==="
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
# List branches via API
BRANCHES=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
BRANCHES=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
"${API}/branches?limit=50" | jq -r '.[].name')
DELETED=0
for BRANCH in $BRANCHES; do
# Skip protected branches
case "$BRANCH" in
main|master|dev|develop|rc|beta|alpha|release|release/*|production|stable|staging|hotfix/*|version/*) continue ;;
main|master|develop|release/*|hotfix/*) continue ;;
esac
# Check if branch is merged into main
if git merge-base --is-ancestor "origin/${BRANCH}" origin/main 2>/dev/null; then
echo " Deleting merged branch: ${BRANCH}"
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
"${API}/branches/${BRANCH}" 2>/dev/null || true
DELETED=$((DELETED + 1))
fi
@@ -66,20 +66,20 @@ jobs:
- name: Clean old workflow runs
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
echo "=== Workflow Run Cleanup ==="
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
CUTOFF=$(date -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-30d +%Y-%m-%dT%H:%M:%SZ)
# Get old completed runs
RUNS=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
RUNS=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
"${API}/actions/runs?status=completed&limit=50" | \
jq -r ".workflow_runs[] | select(.created_at < \"${CUTOFF}\") | .id" 2>/dev/null)
DELETED=0
for RUN_ID in $RUNS; do
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
DELETED=$((DELETED + 1))
done
+7 -3
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
# PATH: /.mokogitea/workflows/gitleaks.yml
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
# PATH: /templates/workflows/gitleaks.yml.template
# VERSION: 01.00.00
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
#
@@ -25,6 +25,10 @@
name: "Universal: Secret Scanning"
on:
pull_request:
branches:
- main
- 'dev/**'
schedule:
- cron: '0 5 * * 1' # Weekly Monday 05:00 UTC
workflow_dispatch:
+7 -7
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Automation
# VERSION: 02.28.00
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Automation
# VERSION: 02.26.00
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
@@ -19,7 +19,7 @@ permissions:
issues: write
env:
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
create-branch:
@@ -28,8 +28,8 @@ jobs:
steps:
- name: Create branch and comment
run: |
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
ISSUE_NUM="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
@@ -58,7 +58,7 @@ jobs:
echo "Created branch: ${BRANCH}"
# Comment on issue with branch link
REPO_URL="${MOKOGITEA_URL}/${{ github.repository }}"
REPO_URL="${GITEA_URL}/${{ github.repository }}"
BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`"
curl -sf -X POST \
+5 -5
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Notifications
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.mokogitea/workflows/notify.yml
# PATH: /.gitea/workflows/notify.yml
# VERSION: 01.00.00
# BRIEF: Push notifications via ntfy on release success or workflow failure
@@ -15,9 +15,9 @@ name: "Universal: Notifications"
on:
workflow_run:
workflows:
- "Universal: Build & Release"
- "Joomla: Extension CI"
- "Generic: Project CI"
- "Joomla Build & Release"
- "Joomla Extension CI"
- "Deploy"
types:
- completed
File diff suppressed because it is too large Load Diff
+11 -42
View File
@@ -3,11 +3,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/pre-release.yml
# VERSION: 05.02.01
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.01.00
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
name: "Universal: Pre-Release"
@@ -48,13 +48,9 @@ jobs:
build:
name: "Build Pre-Release (${{ inputs.stability || github.ref_name }})"
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
!startsWith(github.event.repository.name, 'Template-') &&
(
github.event_name == 'workflow_dispatch' ||
github.event_name == 'push'
)
github.event_name == 'workflow_dispatch' ||
github.event_name == 'push'
steps:
- name: Checkout
@@ -63,11 +59,6 @@ jobs:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
ref: ${{ github.ref_name }}
submodules: recursive
- name: Update submodules to main
run: |
git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true
- name: Setup mokocli tools
env:
@@ -84,7 +75,7 @@ jobs:
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
@@ -97,20 +88,8 @@ jobs:
php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
php ${MOKO_CLI}/manifest_read.php --path . --github-output
- name: Check platform eligibility (Joomla only)
id: eligibility
run: |
PLATFORM="${{ steps.platform.outputs.platform }}"
if [[ "$PLATFORM" == joomla* ]] || [[ "$PLATFORM" == "joomla" ]]; then
echo "proceed=true" >> "$GITHUB_OUTPUT"
else
echo "proceed=false" >> "$GITHUB_OUTPUT"
echo "::notice::Platform '$PLATFORM' — non-Joomla, skipping pre-release auto-bump"
fi
- name: Resolve metadata and bump version
id: meta
if: steps.eligibility.outputs.proceed == 'true'
run: |
# Auto-detect stability from branch name on push, or use input on dispatch
if [ "${{ github.event_name }}" = "push" ]; then
@@ -156,19 +135,13 @@ jobs:
fi
# Commit version bump
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "mokogitea-actions[bot]"
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
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"
git add -A
git diff --cached --quiet || {
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
# Push the bump commit, but do NOT fail the release if the target branch
# is protected and the release identity is not on the push allowlist.
# The build proceeds from the in-tree bumped version regardless; if the
# push is rejected, the next run simply re-bumps from the same base.
if ! git push origin HEAD 2>&1; then
echo "::warning::Version-bump commit could not be pushed (protected branch?). Building from in-tree version ${VERSION} anyway."
fi
git push origin HEAD 2>&1
}
# Auto-detect element via manifest_element.php
@@ -193,7 +166,6 @@ jobs:
- name: Create release
id: release
if: steps.eligibility.outputs.proceed == 'true'
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
@@ -204,7 +176,6 @@ jobs:
--repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease
- name: Update release notes from CHANGELOG.md
if: steps.eligibility.outputs.proceed == 'true'
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
@@ -241,7 +212,6 @@ jobs:
- name: Build package and upload
id: package
if: steps.eligibility.outputs.proceed == 'true'
run: |
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
@@ -255,7 +225,6 @@ jobs:
# No need to build, commit, or sync updates.xml from workflows
- name: "Delete lesser pre-release channels (cascade)"
if: steps.eligibility.outputs.proceed == 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
@@ -280,4 +249,4 @@ jobs:
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
+17 -23
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoPlatform.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.mokogitea/workflows/rc-revert.yml
# VERSION: 09.23.00
# BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge
@@ -25,25 +25,16 @@ jobs:
runs-on: ubuntu-latest
if: >-
github.event.pull_request.merged == false &&
startsWith(github.event.pull_request.head.ref, 'rc/') &&
!startsWith(github.event.repository.name, 'Template-')
startsWith(github.event.pull_request.head.ref, 'rc/')
steps:
- name: Rename branch
env:
BRANCH: ${{ github.event.pull_request.head.ref }}
REPO: ${{ github.repository }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
set -euo pipefail
# BRANCH is attacker-controlled (PR head ref). Strict allowlist before ANY use.
if ! printf '%s' "$BRANCH" | grep -Eq '^rc/[A-Za-z0-9._/-]+$'; then
echo "::error::Refusing unsafe branch name: $BRANCH"; exit 1
fi
BRANCH="${{ github.event.pull_request.head.ref }}"
SUFFIX="${BRANCH#rc/}"
DEV_BRANCH="dev/${SUFFIX}"
API="${GITEA_URL}/api/v1/repos/${REPO}/branches"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Create dev/ branch from rc/ branch
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \
@@ -51,22 +42,25 @@ jobs:
-H "Content-Type: application/json" \
-d "{\"new_branch_name\": \"${DEV_BRANCH}\", \"old_branch_name\": \"${BRANCH}\"}" \
"${API}" 2>/dev/null || true)
if [ "$STATUS" = "201" ]; then
echo "Created branch: ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "Created branch: ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"; exit 1
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"
exit 1
fi
# Read BRANCH from the environment inside PHP (getenv, no string interpolation -> no PHP injection)
ENCODED=$(php -r 'echo rawurlencode(getenv("BRANCH"));')
# Delete rc/ branch
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${TOKEN}" \
"${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then
echo "Deleted branch: ${BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::warning::Failed to delete ${BRANCH} (HTTP ${STATUS})"
fi
echo "### RC Reverted" >> "$GITHUB_STEP_SUMMARY"
echo "${BRANCH} → ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "### RC Reverted" >> $GITHUB_STEP_SUMMARY
echo "${BRANCH} → ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
File diff suppressed because it is too large Load Diff
+82
View File
@@ -0,0 +1,82 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/security-audit.yml
# VERSION: 01.00.00
# BRIEF: Dependency vulnerability scanning for composer and npm packages
name: "Universal: Security Audit"
on:
schedule:
- cron: '0 6 * * 1' # Weekly on Monday at 06:00 UTC
pull_request:
branches:
- main
paths:
- 'composer.json'
- 'composer.lock'
- 'package.json'
- 'package-lock.json'
workflow_dispatch:
permissions:
contents: read
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }}
jobs:
audit:
name: Dependency Audit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Composer audit
if: hashFiles('composer.lock') != ''
run: |
echo "=== Composer Security Audit ==="
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli composer >/dev/null 2>&1
fi
composer audit --format=plain 2>&1 | tee /tmp/composer-audit.txt
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "::warning::Composer vulnerabilities found"
echo "composer_vulnerable=true" >> "$GITHUB_ENV"
else
echo "No known vulnerabilities in composer dependencies"
fi
- name: NPM audit
if: hashFiles('package-lock.json') != ''
run: |
echo "=== NPM Security Audit ==="
npm audit --production 2>&1 | tee /tmp/npm-audit.txt || true
if npm audit --production 2>&1 | grep -q "found 0 vulnerabilities"; then
echo "No known vulnerabilities in npm dependencies"
else
echo "::warning::NPM vulnerabilities found"
echo "npm_vulnerable=true" >> "$GITHUB_ENV"
fi
- name: Notify on vulnerabilities
if: env.composer_vulnerable == 'true' || env.npm_vulnerable == 'true'
run: |
REPO="${{ github.event.repository.name }}"
curl -sS \
-H "Title: ${REPO} has vulnerable dependencies" \
-H "Tags: lock,warning" \
-H "Priority: high" \
-d "Security audit found vulnerabilities. Review dependency updates." \
"${NTFY_URL}/${NTFY_TOPIC}" || true
-32
View File
@@ -1,32 +0,0 @@
name: Sync Workflows to Repos
on:
push:
branches:
- main
paths:
- '.mokogitea/workflows/**'
jobs:
sync:
runs-on: ubuntu-latest
if: ${{ startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Checkout mokocli
uses: actions/checkout@v4
with:
repository: MokoConsulting/MokoCLI
token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Setup PHP
uses: https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/raw/branch/main/actions/setup-php@v1
with:
php-version: '8.1'
- name: Install dependencies
run: composer install --no-dev --no-interaction
- name: Sync workflows to generic repos
run: php automation/bulk_sync.php --platform generic --org MokoConsulting --workflows-only --auto-merge --token "${{ secrets.MOKOGITEA_TOKEN }}"
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
-131
View File
@@ -1,131 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow.Template
# INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
# PATH: /.mokogitea/workflows/version-set.yml
# VERSION: 01.00.00
# BRIEF: Set or reset the extension version across all version-bearing files
name: "Joomla: Set Version"
on:
workflow_dispatch:
inputs:
version:
description: "Version number (e.g. 01.00.00)"
required: true
type: string
branch:
description: "Branch to update (default: current)"
required: false
type: string
permissions:
contents: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
set-version:
name: Set Version to ${{ inputs.version }}
runs-on: ubuntu-latest
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Validate version format
run: |
VERSION="${{ inputs.version }}"
if ! echo "$VERSION" | grep -qP '^\d{2}\.\d{2}\.\d{2}$'; then
echo "::error::Invalid version format '${VERSION}' — expected XX.YY.ZZ (e.g. 01.00.00)"
exit 1
fi
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
ref: ${{ inputs.branch || github.ref }}
fetch-depth: 1
- name: Update manifest version
run: |
MANIFEST=""
for XML_FILE in $(find . -maxdepth 3 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do
if grep -q "<extension" "$XML_FILE" 2>/dev/null; then
MANIFEST="$XML_FILE"
break
fi
done
if [ -z "$MANIFEST" ]; then
echo "::warning::No Joomla extension manifest found — skipping manifest update"
else
OLD_VER=$(grep -oP '<version>\K[^<]+' "$MANIFEST" | head -1)
sed -i "s|<version>${OLD_VER}</version>|<version>${VERSION}</version>|" "$MANIFEST"
echo "Manifest: ${OLD_VER} → ${VERSION} (${MANIFEST})"
fi
- name: Update README.md version
run: |
if [ -f "README.md" ]; then
if grep -qP '^\s*VERSION:\s*\d' README.md; then
sed -i -E "s/(VERSION:\s*)[0-9]{2}\.[0-9]{2}\.[0-9]{2}/\1${VERSION}/" README.md
echo "README.md version updated to ${VERSION}"
else
echo "::warning::No VERSION line found in README.md — skipping"
fi
fi
- name: Update CHANGELOG.md
run: |
if [ -f "CHANGELOG.md" ]; then
DATE=$(date +%Y-%m-%d)
# Check if this version already has an entry
if grep -q "^\#\# \[${VERSION}\]" CHANGELOG.md; then
echo "CHANGELOG.md already has entry for ${VERSION} — skipping"
else
# Insert new version entry after [Unreleased] or at the top after header
if grep -q '^\#\# \[Unreleased\]' CHANGELOG.md; then
sed -i "/^\#\# \[Unreleased\]/a\\\\n## [${VERSION}] --- ${DATE}" CHANGELOG.md
else
sed -i "/^\# Changelog/a\\\\n## [Unreleased]\n\n## [${VERSION}] --- ${DATE}" CHANGELOG.md
fi
echo "CHANGELOG.md: added entry for ${VERSION}"
fi
else
echo "::warning::No CHANGELOG.md found — skipping"
fi
- name: Update FILE INFORMATION blocks
run: |
# Update VERSION in file header blocks (# VERSION: XX.YY.ZZ)
find . -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" -o -name "*.php" -o -name "*.md" \) \
-not -path "./.git/*" -not -path "./vendor/*" -print0 2>/dev/null | \
while IFS= read -r -d '' FILE; do
if head -20 "$FILE" | grep -qP '^\s*#?\s*VERSION:\s*\d{2}\.\d{2}\.\d{2}'; then
sed -i -E "s/(#?\s*VERSION:\s*)[0-9]{2}\.[0-9]{2}\.[0-9]{2}/\1${VERSION}/" "$FILE"
echo "Updated FILE INFORMATION VERSION in ${FILE}"
fi
done
- name: Commit and push
run: |
git config user.name "Moko Consulting [bot]"
git config user.email "hello@mokoconsulting.tech"
git add -A
if git diff --cached --quiet; then
echo "No version changes detected — nothing to commit"
else
git commit -m "chore: set version to ${VERSION} [skip bump]
Authored-by: Moko Consulting"
git push
echo "### Version Set" >> $GITHUB_STEP_SUMMARY
echo "Version updated to \`${VERSION}\` on branch \`${GITHUB_REF_NAME}\`" >> $GITHUB_STEP_SUMMARY
fi
+10 -19
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoPlatform.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform
# PATH: /.mokogitea/workflows/workflow-sync-trigger.yml
# VERSION: 01.01.00
# BRIEF: Trigger workflow sync to live repos when a PR is merged to main
@@ -13,7 +13,6 @@
name: "Universal: Workflow Sync Trigger"
on:
workflow_dispatch:
pull_request:
types: [closed]
branches:
@@ -27,10 +26,8 @@ jobs:
name: Sync workflows to live repos
runs-on: ubuntu-latest
if: >-
startsWith(github.event.repository.name, 'Template-') &&
(github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')))
github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')
steps:
- name: Determine platform from repo name
@@ -48,22 +45,16 @@ jobs:
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
echo "Platform: ${PLATFORM:-all}"
- name: Clone mokocli
- name: Clone mokoplatform
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${MOKOGITEA_URL}/MokoConsulting/MokoCLI.git" /tmp/mokocli
- name: Install PHP
run: |
if ! command -v php &> /dev/null; then
apt-get update -qq && apt-get install -y -qq php-cli php-json php-curl > /dev/null 2>&1
fi
GITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${GITEA_URL}/MokoConsulting/mokoplatform.git" /tmp/mokoplatform
- name: Install dependencies
run: |
cd /tmp/mokocli
cd /tmp/mokoplatform
composer install --no-dev --no-interaction --quiet 2>/dev/null || true
- name: Run workflow sync
@@ -79,4 +70,4 @@ jobs:
ARGS="${ARGS} --platform-filter ${PLATFORM}"
fi
php /tmp/mokocli/cli/workflow_sync.php ${ARGS}
php /tmp/mokoplatform/cli/workflow_sync.php ${ARGS}
+8 -13
View File
@@ -8,27 +8,22 @@
DEFGROUP: Joomla.Template.Site
INGROUP: MokoOnyx.Documentation
PATH: ./CHANGELOG.md
VERSION: 02.28.00
VERSION: 02.26.00
BRIEF: Changelog file documenting version history of MokoOnyx
-->
# Changelog — MokoOnyx (VERSION: 02.28.00)
# Changelog — MokoOnyx (VERSION: 02.26.00)
## [Unreleased]
## [02.28.00] --- 2026-07-13
## [02.25.00] --- 2026-06-20
## [02.27.06] --- 2026-06-29
## [02.25.00] --- 2026-06-20
## [02.27.06] --- 2026-06-29
## [02.24.00] --- 2026-06-20
## [02.27.00] --- 2026-06-21
## [02.24.00] --- 2026-06-20
## [02.27.00] --- 2026-06-21
## [02.23.02] --- 2026-06-20
### Added
- Collapsible floating social bar with toggle button and localStorage persistence
- Bootstrap tooltips on all social icon links showing platform name on hover
- URL validation on social platform fields (browser, Joomla server-side, and PHP layout logging)
### Fixed
- Moved footer social icons below footer-menu and footer module positions for correct display order
## [02.23.02] --- 2026-06-20
+1 -1
View File
@@ -34,7 +34,7 @@ feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge
7. **Merging to main** triggers the stable release pipeline:
- Minor version bump (e.g., `02.09.xx` → `02.10.00`)
- Stability suffix stripped (clean version)
- MokoGitea release created with ZIP/tar.gz packages
- Gitea release created with ZIP/tar.gz packages
- `updates.xml` updated (Joomla extensions)
- `dev` branch recreated from `main`
+213
View File
@@ -0,0 +1,213 @@
# Makefile for MokoOnyx Joomla Template
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Build and validation powered by MokoStandards Enterprise API
# Install: composer install
# ==============================================================================
# CONFIGURATION
# ==============================================================================
EXTENSION_NAME := mokoonyx
EXTENSION_TYPE := template
EXTENSION_VERSION := $(shell grep -oP 'VERSION:\s*\K[0-9.]+' README.md 2>/dev/null || echo "0.0.0")
SRC_DIR := src
BUILD_DIR := build
DIST_DIR := dist
PHP := php
COMPOSER := composer
MOKO := vendor/bin/moko
# Colors
COLOR_RESET := \033[0m
COLOR_GREEN := \033[32m
COLOR_YELLOW := \033[33m
COLOR_BLUE := \033[34m
COLOR_RED := \033[31m
# ==============================================================================
# TARGETS
# ==============================================================================
.PHONY: help
help: ## Show this help message
@echo "$(COLOR_BLUE)╔════════════════════════════════════════════════════════════╗$(COLOR_RESET)"
@echo "$(COLOR_BLUE)║ MokoOnyx Template Build ║$(COLOR_RESET)"
@echo "$(COLOR_BLUE)╚════════════════════════════════════════════════════════════╝$(COLOR_RESET)"
@echo ""
@echo "Extension: $(EXTENSION_NAME) ($(EXTENSION_TYPE)) v$(EXTENSION_VERSION)"
@echo "Powered by: MokoStandards Enterprise API"
@echo ""
@echo "$(COLOR_GREEN)Available targets:$(COLOR_RESET)"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " $(COLOR_BLUE)%-20s$(COLOR_RESET) %s\n", $$1, $$2}'
@echo ""
# ── Dependencies ──────────────────────────────────────────────────────────────
.PHONY: install-deps
install-deps: ## Install Composer dependencies (includes MokoStandards API)
@echo "$(COLOR_BLUE)Installing dependencies...$(COLOR_RESET)"
@$(COMPOSER) install
@echo "$(COLOR_GREEN)✓ Dependencies installed$(COLOR_RESET)"
.PHONY: update-deps
update-deps: ## Update Composer dependencies
@echo "$(COLOR_BLUE)Updating dependencies...$(COLOR_RESET)"
@$(COMPOSER) update
@echo "$(COLOR_GREEN)✓ Dependencies updated$(COLOR_RESET)"
# ── Validation (MokoStandards API) ────────────────────────────────────────────
.PHONY: check-moko
check-moko:
@if [ ! -f "$(MOKO)" ]; then \
echo "$(COLOR_RED)✗ MokoStandards CLI not found. Run: make install-deps$(COLOR_RESET)"; \
exit 1; \
fi
.PHONY: lint
lint: check-moko ## PHP syntax check via MokoStandards
@echo "$(COLOR_BLUE)Running PHP syntax check...$(COLOR_RESET)"
@$(PHP) $(MOKO) check:syntax -- --path .
@echo "$(COLOR_GREEN)✓ PHP syntax OK$(COLOR_RESET)"
.PHONY: check-joomla
check-joomla: check-moko ## Validate Joomla manifest via MokoStandards
@echo "$(COLOR_BLUE)Validating Joomla manifest...$(COLOR_RESET)"
@$(PHP) $(MOKO) check:joomla -- --path .
@echo "$(COLOR_GREEN)✓ Joomla manifest valid$(COLOR_RESET)"
.PHONY: check-version
check-version: check-moko ## Verify version consistency across files
@echo "$(COLOR_BLUE)Checking version consistency...$(COLOR_RESET)"
@$(PHP) $(MOKO) check:version -- --path .
@echo "$(COLOR_GREEN)✓ Versions consistent$(COLOR_RESET)"
.PHONY: check-headers
check-headers: check-moko ## Check license headers on source files
@echo "$(COLOR_BLUE)Checking license headers...$(COLOR_RESET)"
@$(PHP) $(MOKO) check:headers -- --path .
@echo "$(COLOR_GREEN)✓ Headers OK$(COLOR_RESET)"
.PHONY: check-secrets
check-secrets: check-moko ## Scan for leaked credentials
@echo "$(COLOR_BLUE)Scanning for secrets...$(COLOR_RESET)"
@$(PHP) $(MOKO) check:secrets -- --path .
@echo "$(COLOR_GREEN)✓ No secrets found$(COLOR_RESET)"
.PHONY: check-xml
check-xml: check-moko ## Validate XML files are well-formed
@echo "$(COLOR_BLUE)Checking XML files...$(COLOR_RESET)"
@$(PHP) $(MOKO) check:xml -- --path .
@echo "$(COLOR_GREEN)✓ XML well-formed$(COLOR_RESET)"
.PHONY: validate
validate: lint check-joomla check-version check-xml check-headers check-secrets ## Run all MokoStandards validation checks
@echo "$(COLOR_GREEN)✓ All validation checks passed$(COLOR_RESET)"
.PHONY: health
health: check-moko ## Full repository health check via MokoStandards
@echo "$(COLOR_BLUE)Running full health check...$(COLOR_RESET)"
@$(PHP) $(MOKO) health -- --path .
# ── Build ─────────────────────────────────────────────────────────────────────
.PHONY: clean
clean: ## Clean build artifacts
@echo "$(COLOR_BLUE)Cleaning build artifacts...$(COLOR_RESET)"
@rm -rf $(BUILD_DIR) $(DIST_DIR)
@echo "$(COLOR_GREEN)✓ Build artifacts cleaned$(COLOR_RESET)"
MOKO_PLATFORM ?= $(or $(wildcard ../moko-platform),$(wildcard $(HOME)/moko-platform),$(wildcard /opt/moko-platform))
MINIFY_SCRIPT := $(MOKO_PLATFORM)/build/minify.js
.PHONY: minify
minify: ## Minify CSS/JS assets (requires terser + clean-css)
@echo "$(COLOR_BLUE)Minifying assets...$(COLOR_RESET)"
@if [ -f "$(MINIFY_SCRIPT)" ]; then \
node "$(MINIFY_SCRIPT)" $(SRC_DIR); \
elif [ -f "scripts/minify.js" ]; then \
node scripts/minify.js; \
else \
echo "$(COLOR_YELLOW)⚠ No minify script found$(COLOR_RESET)"; \
fi
.PHONY: build
build: clean minify ## Build template installable ZIP from src/
@echo "$(COLOR_BLUE)Building $(EXTENSION_NAME) v$(EXTENSION_VERSION)...$(COLOR_RESET)"
@mkdir -p $(BUILD_DIR)/package $(DIST_DIR)
@cp -r $(SRC_DIR)/* $(BUILD_DIR)/package/
@cd $(BUILD_DIR)/package && \
if command -v zip >/dev/null 2>&1; then \
zip -r "../../$(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip" .; \
elif command -v pwsh >/dev/null 2>&1; then \
pwsh -Command "Compress-Archive -Path '*' -DestinationPath '../../$(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip' -Force"; \
elif command -v powershell >/dev/null 2>&1; then \
powershell -Command "Compress-Archive -Path '*' -DestinationPath '../../$(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip' -Force"; \
else \
echo "$(COLOR_RED)✗ No zip tool found (zip, pwsh, powershell)$(COLOR_RESET)"; \
exit 1; \
fi
@echo "$(COLOR_GREEN)✓ Package: $(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip$(COLOR_RESET)"
.PHONY: build-beta
build-beta: clean ## Build beta release ZIP
@echo "$(COLOR_BLUE)Building $(EXTENSION_NAME) v$(EXTENSION_VERSION)-beta...$(COLOR_RESET)"
@mkdir -p $(BUILD_DIR)/package $(DIST_DIR)
@cp -r $(SRC_DIR)/* $(BUILD_DIR)/package/
@cd $(BUILD_DIR)/package && \
if command -v zip >/dev/null 2>&1; then \
zip -r "../../$(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION)-beta.zip" .; \
elif command -v pwsh >/dev/null 2>&1; then \
pwsh -Command "Compress-Archive -Path '*' -DestinationPath '../../$(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION)-beta.zip' -Force"; \
elif command -v powershell >/dev/null 2>&1; then \
powershell -Command "Compress-Archive -Path '*' -DestinationPath '../../$(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION)-beta.zip' -Force"; \
else \
echo "$(COLOR_RED)✗ No zip tool found$(COLOR_RESET)"; \
exit 1; \
fi
@echo "$(COLOR_GREEN)✓ Package: $(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION)-beta.zip$(COLOR_RESET)"
.PHONY: checksum
checksum: ## Generate SHA-256 checksums for dist packages
@echo "$(COLOR_BLUE)Generating checksums...$(COLOR_RESET)"
@for f in $(DIST_DIR)/*.zip; do \
sha256sum "$$f" | tee "$${f}.sha256"; \
done
@echo "$(COLOR_GREEN)✓ Checksums generated$(COLOR_RESET)"
# ── Release ───────────────────────────────────────────────────────────────────
.PHONY: release
release: validate build checksum ## Full release pipeline (validate + build + checksum)
@echo "$(COLOR_GREEN)✓ Release package ready$(COLOR_RESET)"
@echo ""
@echo "$(COLOR_BLUE)Next steps:$(COLOR_RESET)"
@echo " 1. Tag: git tag $(EXTENSION_VERSION)"
@echo " 2. Push: git push origin --tags"
@echo " 3. Create Gitea release and attach $(DIST_DIR)/$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip"
@echo ""
# ── Info ──────────────────────────────────────────────────────────────────────
.PHONY: version
version: ## Display version and extension info
@echo "$(COLOR_BLUE)Extension Information:$(COLOR_RESET)"
@echo " Name: $(EXTENSION_NAME)"
@echo " Type: $(EXTENSION_TYPE)"
@echo " Version: $(EXTENSION_VERSION)"
.PHONY: security-check
security-check: ## Run Composer security audit
@echo "$(COLOR_BLUE)Running security checks...$(COLOR_RESET)"
@$(COMPOSER) audit
@echo "$(COLOR_GREEN)✓ Security check complete$(COLOR_RESET)"
.PHONY: all
all: install-deps validate build checksum ## Full pipeline: deps → validate → build → checksum
@echo "$(COLOR_GREEN)✓ Complete build pipeline finished$(COLOR_RESET)"
.DEFAULT_GOAL := help
+6 -8
View File
@@ -12,12 +12,12 @@ A modern, lightweight Joomla site template built on Cassiopeia with Font Awesome
| | |
|---|---|
| **Type** | Joomla Site Template |
| **Version** | 02.22.00 |
| **Version** | 02.07.00 |
| **Joomla** | 5.x / 6.x |
| **PHP** | 8.1+ |
| **License** | GPL-3.0-or-later |
| **Replaces** | MokoCassiopeia (auto-migrates on install) |
| **Repository** | [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) (primary) |
| **Repository** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) (primary) |
---
@@ -39,7 +39,6 @@ On install, MokoOnyx automatically migrates settings, content references, and cu
| **Table of Contents** | Automatic TOC generation for long articles |
| **GTM / GA4** | Google Tag Manager and Analytics integration with smart visitor detection (login status, user group, page type) |
| **Template Overrides** | Overrides for all core Joomla modules, Community Builder, and DPCalendar |
| **Social Icons** | Configurable social media links in topbar, footer, or collapsible floating sidebar with tooltips and URL validation |
| **Cassiopeia Base** | Minimal core overrides for maximum Joomla upgrade compatibility |
---
@@ -80,7 +79,6 @@ Key parameters include:
- **Google Tag Manager**: GTM container ID
- **GA4**: Measurement ID and tracking options
- **Table of Contents**: Auto-generate TOC for articles with heading threshold
- **Social Icons**: Display positions, icon style, and platform URLs
---
@@ -88,14 +86,14 @@ Key parameters include:
| Repo | Purpose |
|------|---------|
| [Template-Client-MokoSuite](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-MokoSuite/wiki) | Client site template (extends MokoOnyx) |
| [MokoSuite](https://git.mokoconsulting.tech/MokoConsulting/MokoSuite/wiki) | MokoSuite system plugin |
| [Template-Client-WaaS](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-WaaS/wiki) | Client site template (extends MokoOnyx) |
| [MokoWaaS](https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/wiki) | WaaS system plugin |
| [joomla-api-mcp](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki) | Joomla Web Services API MCP |
| [deploy-mcp](https://git.mokoconsulting.tech/MokoConsulting/deploy-mcp/wiki) | Git-based deployment MCP |
---
> **[MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)** -- central standards hub for all Moko Consulting projects.
> **[MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki)** -- central standards hub for all Moko Consulting projects.
---
@@ -117,4 +115,4 @@ This project is licensed under the GNU General Public License v3.0 or later -- s
---
*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)*
*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
+1 -1
View File
@@ -10,7 +10,7 @@
INGROUP: MokoOnyx.Governance
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
FILE: SECURITY.md
VERSION: 02.28.00
VERSION: 02.26.00
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.
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: MokoOnyx
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: /html/layouts/joomla/module/card.php
* VERSION: 02.28.00
* VERSION: 02.26.00
* BRIEF: Custom card module chrome — renders module titles for all modules
*/
@@ -11,7 +11,7 @@
* INGROUP: MokoOnyx.Layouts
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: /src/html/layouts/mokoonyx/article-metadata.php
* VERSION: 02.28.00
* VERSION: 02.26.00
* BRIEF: Article metadata footer layout -- renders jcfields grouped by field group
*/
+7 -42
View File
@@ -52,22 +52,13 @@ $platforms = [
$active = [];
foreach ($platforms as $key => [$iconClass, $langKey]) {
$url = trim((string) $params->get('social_' . $key . '_url', ''));
if ($url === '') {
continue;
if ($url !== '' && preg_match('#^(https?://|mailto:|/)#i', $url)) {
$active[] = [
'url' => $url,
'iconClass' => $iconClass,
'label' => Text::_($langKey),
];
}
if (!preg_match('#^(https?://[^\s<>"]+|mailto:[^\s<>"]+|/[^\s<>"]*)$#i', $url)) {
\Joomla\CMS\Log\Log::add(
'MokoOnyx social: skipped invalid URL for "' . $key . '": ' . $url,
\Joomla\CMS\Log\Log::WARNING,
'template'
);
continue;
}
$active[] = [
'url' => $url,
'iconClass' => $iconClass,
'label' => Text::_($langKey),
];
}
if (empty($active)) {
@@ -84,10 +75,6 @@ $floatingPos = in_array($params->get('social_floating_pos'), ['left', 'right'],
$colorMode = in_array($params->get('social_icon_color'), ['theme', 'brand', 'black', 'white'], true)
? $params->get('social_icon_color') : 'theme';
// Floating collapse behaviour (only meaningful for the floating position)
$collapsible = (bool) $params->get('social_floating_collapsible', 1);
$collapsedDefault = $collapsible && (bool) $params->get('social_floating_collapsed', 1);
$listClass = 'moko-social-icons';
$listClass .= ' moko-social-icons--' . htmlspecialchars($style, ENT_QUOTES, 'UTF-8');
$listClass .= ' moko-social-icons--' . htmlspecialchars($size, ENT_QUOTES, 'UTF-8');
@@ -97,12 +84,6 @@ if ($position === 'floating') {
$listClass .= ' moko-social-icons--floating-' . $floatingPos;
}
?>
<?php if ($position === 'floating') : ?>
<div class="moko-social-floating-wrap moko-social-floating-wrap--<?php echo htmlspecialchars($floatingPos, ENT_QUOTES, 'UTF-8'); ?><?php echo $collapsedDefault ? ' is-collapsed' : ''; ?>"
id="mokoSocialFloating"
data-collapsible="<?php echo $collapsible ? '1' : '0'; ?>"
data-default-collapsed="<?php echo $collapsedDefault ? '1' : '0'; ?>">
<?php endif; ?>
<nav class="<?php echo $listClass; ?>" aria-label="<?php echo Text::_('TPL_MOKOONYX_SOCIAL_NAV_LABEL'); ?>">
<ul>
<?php foreach ($active as $item) : ?>
@@ -110,26 +91,10 @@ if ($position === 'floating') {
<a href="<?php echo htmlspecialchars($item['url'], ENT_QUOTES, 'UTF-8'); ?>"
target="_blank"
rel="noopener noreferrer"
aria-label="<?php echo htmlspecialchars($item['label'], ENT_QUOTES, 'UTF-8'); ?>"
data-bs-toggle="tooltip"
data-bs-placement="<?php echo $position === 'floating' ? ($floatingPos === 'left' ? 'right' : 'left') : 'top'; ?>"
title="<?php echo htmlspecialchars($item['label'], ENT_QUOTES, 'UTF-8'); ?>">
aria-label="<?php echo htmlspecialchars($item['label'], ENT_QUOTES, 'UTF-8'); ?>">
<span class="<?php echo htmlspecialchars($item['iconClass'], ENT_QUOTES, 'UTF-8'); ?>" aria-hidden="true"></span>
</a>
</li>
<?php endforeach; ?>
</ul>
</nav>
<?php if ($position === 'floating' && $collapsible) : ?>
<button type="button"
class="moko-social-floating-toggle"
id="mokoSocialFloatingToggle"
aria-controls="mokoSocialFloating"
aria-label="<?php echo Text::_('TPL_MOKOONYX_SOCIAL_FLOATING_TOGGLE'); ?>"
aria-expanded="<?php echo $collapsedDefault ? 'false' : 'true'; ?>">
<span class="fa-solid fa-chevron-<?php echo $floatingPos === 'left' ? 'left' : 'right'; ?>" aria-hidden="true"></span>
</button>
<?php endif; ?>
<?php if ($position === 'floating') : ?>
</div>
<?php endif; ?>
+1 -6
View File
@@ -286,11 +286,6 @@ TPL_MOKOONYX_SOCIAL_FLOATING_POS_LABEL="Floating Position"
TPL_MOKOONYX_SOCIAL_FLOATING_POS_DESC="Which side of the screen the floating social bar appears on."
TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT="Left"
TPL_MOKOONYX_SOCIAL_FLOATING_POS_RIGHT="Right"
TPL_MOKOONYX_SOCIAL_FLOATING_TOGGLE="Toggle social icons sidebar"
TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSIBLE_LABEL="Collapsible"
TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSIBLE_DESC="Show a toggle handle so visitors can collapse and expand the floating social bar. Their choice is remembered on their device."
TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSED_LABEL="Collapsed by Default"
TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSED_DESC="Start the floating social bar collapsed on a visitor's first visit. Visitors who have already set their own preference keep it."
TPL_MOKOONYX_SOCIAL_COLOR_LABEL="Icon Colour"
TPL_MOKOONYX_SOCIAL_COLOR_DESC="Choose the colour scheme for social icons."
TPL_MOKOONYX_SOCIAL_COLOR_THEME="Theme (CSS variables)"
@@ -326,7 +321,7 @@ TPL_MOKOONYX_SOCIAL_MAIL="Email us"
; ===== CSS Variables tab (social) =====
TPL_MOKOONYX_CSS_VARS_SOCIAL_LABEL="Social Icons"
TPL_MOKOONYX_CSS_VARS_SOCIAL_DESC="<code>--social-icon-size</code> — Icon font size (overrides size preset)<br><code>--social-icon-gap</code> — Gap between icons (default: <code>0.5rem</code>)<br><code>--social-icon-color</code> — Icon colour (default: <code>currentColor</code>)<br><code>--social-icon-hover-color</code> — Hover colour (default: <code>var(--accent-color-primary)</code>)<br><code>--social-icon-bg</code> — Background for circle/rounded styles<br><code>--social-icon-hover-bg</code> — Hover background<br><code>--social-icon-radius</code> — Border radius for rounded style (default: <code>0.375rem</code>)<br><br><strong>Floating bar</strong><br>The collapse toggle button inherits <code>--social-icon-bg</code>, <code>--social-icon-color</code>, and <code>--social-icon-hover-bg</code>. Tooltips appear automatically on hover showing the platform name."
TPL_MOKOONYX_CSS_VARS_SOCIAL_DESC="<code>--social-icon-size</code> — Icon font size (overrides size preset)<br><code>--social-icon-gap</code> — Gap between icons (default: <code>0.5rem</code>)<br><code>--social-icon-color</code> — Icon colour (default: <code>currentColor</code>)<br><code>--social-icon-hover-color</code> — Hover colour (default: <code>var(--accent-color-primary)</code>)<br><code>--social-icon-bg</code> — Background for circle/rounded styles<br><code>--social-icon-hover-bg</code> — Hover background<br><code>--social-icon-radius</code> — Border radius for rounded style (default: <code>0.375rem</code>)"
; ===== Misc =====
MOD_BREADCRUMBS_HERE="YOU ARE HERE:"
+1 -6
View File
@@ -286,11 +286,6 @@ TPL_MOKOONYX_SOCIAL_FLOATING_POS_LABEL="Floating Position"
TPL_MOKOONYX_SOCIAL_FLOATING_POS_DESC="Which side of the screen the floating social bar appears on."
TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT="Left"
TPL_MOKOONYX_SOCIAL_FLOATING_POS_RIGHT="Right"
TPL_MOKOONYX_SOCIAL_FLOATING_TOGGLE="Toggle social icons sidebar"
TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSIBLE_LABEL="Collapsible"
TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSIBLE_DESC="Show a toggle handle so visitors can collapse and expand the floating social bar. Their choice is remembered on their device."
TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSED_LABEL="Collapsed by Default"
TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSED_DESC="Start the floating social bar collapsed on a visitor's first visit. Visitors who have already set their own preference keep it."
TPL_MOKOONYX_SOCIAL_COLOR_LABEL="Icon Color"
TPL_MOKOONYX_SOCIAL_COLOR_DESC="Choose the color scheme for social icons."
TPL_MOKOONYX_SOCIAL_COLOR_THEME="Theme (CSS variables)"
@@ -326,7 +321,7 @@ TPL_MOKOONYX_SOCIAL_MAIL="Email us"
; ===== CSS Variables tab (social) =====
TPL_MOKOONYX_CSS_VARS_SOCIAL_LABEL="Social Icons"
TPL_MOKOONYX_CSS_VARS_SOCIAL_DESC="<code>--social-icon-size</code> — Icon font size (overrides size preset)<br><code>--social-icon-gap</code> — Gap between icons (default: <code>0.5rem</code>)<br><code>--social-icon-color</code> — Icon color (default: <code>currentColor</code>)<br><code>--social-icon-hover-color</code> — Hover color (default: <code>var(--accent-color-primary)</code>)<br><code>--social-icon-bg</code> — Background for circle/rounded styles<br><code>--social-icon-hover-bg</code> — Hover background<br><code>--social-icon-radius</code> — Border radius for rounded style (default: <code>0.375rem</code>)<br><br><strong>Floating bar</strong><br>The collapse toggle button inherits <code>--social-icon-bg</code>, <code>--social-icon-color</code>, and <code>--social-icon-hover-bg</code>. Tooltips appear automatically on hover showing the platform name."
TPL_MOKOONYX_CSS_VARS_SOCIAL_DESC="<code>--social-icon-size</code> — Icon font size (overrides size preset)<br><code>--social-icon-gap</code> — Gap between icons (default: <code>0.5rem</code>)<br><code>--social-icon-color</code> — Icon color (default: <code>currentColor</code>)<br><code>--social-icon-hover-color</code> — Hover color (default: <code>var(--accent-color-primary)</code>)<br><code>--social-icon-bg</code> — Background for circle/rounded styles<br><code>--social-icon-hover-bg</code> — Hover background<br><code>--social-icon-radius</code> — Border radius for rounded style (default: <code>0.375rem</code>)"
; ===== Misc =====
MOD_BREADCRUMBS_HERE="YOU ARE HERE:"
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: MokoOnyx.Accessibility
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: ./media/css/a11y-high-contrast.css
* VERSION: 02.28.00
* VERSION: 02.26.00
* BRIEF: High-contrast stylesheet for accessibility toolbar
*/
+51 -67
View File
@@ -8046,6 +8046,46 @@ fieldset:disabled .btn {
content: "";
}
.text-bg-primary {
color: var(--body-color, #22262a);
background-color: var(--primary, #010156);
}
.text-bg-secondary {
color: var(--body-color, #22262a) ;
background-color: RGBA(109, 117, 126, var(--bg-opacity, 1)) ;
}
.text-bg-success {
color: var(--body-color, #22262a) ;
background-color: RGBA(68, 131, 68, var(--bg-opacity, 1)) ;
}
.text-bg-info {
color: var(--body-color, #22262a) ;
background-color: RGBA(48, 99, 141, var(--bg-opacity, 1)) ;
}
.text-bg-warning {
color: var(--body-color, #22262a) ;
background-color: RGBA(173, 98, 0, var(--bg-opacity, 1)) ;
}
.text-bg-danger {
color: var(--body-color, #22262a) ;
background-color: RGBA(165, 31, 24, var(--bg-opacity, 1)) ;
}
.text-bg-light {
color: hsl(0, 0%, 0%) ;
background-color: RGBA(249, 250, 251, var(--bg-opacity, 1)) ;
}
.text-bg-dark {
color: var(--body-color, #22262a) ;
background-color: RGBA(53, 59, 65, var(--bg-opacity, 1)) ;
}
.link-primary {
color: var(--link-primary-color, hsl(240, 98%, 50%));
@@ -23482,7 +23522,7 @@ font-size: 0.8125rem;
.blog-item .item-image img {
width: 100%;
height: 100%;
object-fit: none;
object-fit: cover;
}
.fa-brands {
@@ -23639,42 +23679,26 @@ font-size: 0.8125rem;
}
/* Position: floating — fixed sidebar, hidden on mobile */
.moko-social-floating-wrap {
.moko-social-icons--floating {
position: fixed;
top: 50%;
transform: translateY(-50%);
z-index: 1030;
display: flex;
align-items: center;
transition: transform 0.3s ease;
}
.moko-social-floating-wrap--left {
left: 0;
flex-direction: row;
}
.moko-social-floating-wrap--right {
right: 0;
flex-direction: row-reverse;
}
.moko-social-floating-wrap--left.is-collapsed {
transform: translateY(-50%) translateX(calc(-100% + 1.5rem));
}
.moko-social-floating-wrap--right.is-collapsed {
transform: translateY(-50%) translateX(calc(100% - 1.5rem));
}
.moko-social-icons--floating {
display: flex;
}
.moko-social-icons--floating ul {
flex-direction: column;
}
.moko-social-icons--floating-left {
left: 0;
}
.moko-social-icons--floating-right {
right: 0;
}
.moko-social-icons--floating-left a {
border-radius: 0 var(--social-icon-radius, 0.375rem) var(--social-icon-radius, 0.375rem) 0;
}
@@ -23688,48 +23712,8 @@ font-size: 0.8125rem;
border-radius: inherit;
}
/* Floating toggle button */
.moko-social-floating-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 1.5rem;
height: 2.5rem;
padding: 0;
border: 1px solid var(--social-icon-bg, var(--border-color, hsl(0, 0%, 80%)));
background: var(--social-icon-bg, var(--body-bg, hsl(0, 0%, 100%)));
color: var(--social-icon-color, currentColor);
cursor: pointer;
font-size: 0.65rem;
transition: background 0.2s, color 0.2s;
flex-shrink: 0;
}
.moko-social-floating-wrap--left .moko-social-floating-toggle {
border-radius: 0 var(--social-icon-radius, 0.375rem) var(--social-icon-radius, 0.375rem) 0;
border-left: 0;
}
.moko-social-floating-wrap--right .moko-social-floating-toggle {
border-radius: var(--social-icon-radius, 0.375rem) 0 0 var(--social-icon-radius, 0.375rem);
border-right: 0;
}
.moko-social-floating-toggle:hover {
background: var(--social-icon-hover-bg, var(--accent-color-primary, hsl(220, 70%, 50%)));
color: #fff;
}
.moko-social-floating-toggle .fa-solid {
transition: transform 0.3s ease;
}
.is-collapsed .moko-social-floating-toggle .fa-solid {
transform: rotate(180deg);
}
@media (max-width: 991.98px) {
.moko-social-floating-wrap {
.moko-social-icons--floating {
display: none;
}
}
-49
View File
@@ -789,53 +789,6 @@
});
}
// ========================================================================
// FLOATING SOCIAL BAR (collapsible)
// ========================================================================
var socialStorageKey = "moko-social-collapsed";
function initSocialFloating() {
var wrap = doc.getElementById("mokoSocialFloating");
var toggle = doc.getElementById("mokoSocialFloatingToggle");
// The toggle is only rendered when the "collapsible" param is enabled.
if (!wrap || !toggle) return;
// Resolve the initial collapsed state:
// - A returning visitor's explicit choice (localStorage) always wins.
// - Otherwise fall back to the admin's "collapsed by default" setting,
// which the layout also renders server-side to avoid a state flash.
var saved = null;
try { saved = localStorage.getItem(socialStorageKey); } catch (e) {}
var collapsed = (saved === "1" || saved === "0")
? (saved === "1")
: (wrap.getAttribute("data-default-collapsed") === "1");
wrap.classList.toggle("is-collapsed", collapsed);
toggle.setAttribute("aria-expanded", collapsed ? "false" : "true");
toggle.addEventListener("click", function () {
var isCollapsed = wrap.classList.toggle("is-collapsed");
toggle.setAttribute("aria-expanded", isCollapsed ? "false" : "true");
try { localStorage.setItem(socialStorageKey, isCollapsed ? "1" : "0"); } catch (e) {}
});
}
// ========================================================================
// SOCIAL ICON TOOLTIPS
// ========================================================================
function initSocialTooltips() {
var triggers = doc.querySelectorAll('.moko-social-icons [data-bs-toggle="tooltip"]');
if (!triggers.length) return;
// Bootstrap 5 tooltip init
if (typeof bootstrap !== "undefined" && bootstrap.Tooltip) {
triggers.forEach(function (el) {
new bootstrap.Tooltip(el, { trigger: "hover focus" });
});
}
}
/**
* Run all template JS initializations
*/
@@ -862,8 +815,6 @@
initBackTop();
initSearchToggle();
initSidebarAccordion();
initSocialFloating();
initSocialTooltips();
initVarCopy();
}
+23 -37
View File
@@ -35,7 +35,7 @@
</updateservers>
<dlid prefix="dlid=" suffix=""/>
<name>mokoonyx</name>
<version>02.28.00</version>
<version>02.26.00-rc</version>
<scriptfile>script.php</scriptfile>
<creationDate>2026-05-16</creationDate>
<author>Jonathan Miller || Moko Consulting</author>
@@ -354,20 +354,6 @@
<option value="left">TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT</option>
<option value="right">TPL_MOKOONYX_SOCIAL_FLOATING_POS_RIGHT</option>
</field>
<field name="social_floating_collapsible" type="radio" default="1"
label="TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSIBLE_LABEL" description="TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSIBLE_DESC"
layout="joomla.form.field.radio.switcher" filter="boolean"
showon="social_floating:1">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="social_floating_collapsed" type="radio" default="1"
label="TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSED_LABEL" description="TPL_MOKOONYX_SOCIAL_FLOATING_COLLAPSED_DESC"
layout="joomla.form.field.radio.switcher" filter="boolean"
showon="social_floating:1[AND]social_floating_collapsible:1">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<!-- Style options -->
<field name="social_sep_style" type="spacer" label="Style" hr="false" class="text fw-bold"
@@ -401,28 +387,28 @@
showon="social_topbar:1[OR]social_footer:1[OR]social_floating:1" />
<field name="social_urls_note" type="note" description="TPL_MOKOONYX_SOCIAL_URLS_NOTE"
showon="social_topbar:1[OR]social_footer:1[OR]social_floating:1" />
<field name="social_facebook_url" type="url" default="" label="Facebook" filter="url" validate="url" />
<field name="social_twitter_url" type="url" default="" label="X / Twitter" filter="url" validate="url" />
<field name="social_instagram_url" type="url" default="" label="Instagram" filter="url" validate="url" />
<field name="social_linkedin_url" type="url" default="" label="LinkedIn" filter="url" validate="url" />
<field name="social_youtube_url" type="url" default="" label="YouTube" filter="url" validate="url" />
<field name="social_github_url" type="url" default="" label="GitHub" filter="url" validate="url" />
<field name="social_bluesky_url" type="url" default="" label="Bluesky" filter="url" validate="url" />
<field name="social_threads_url" type="url" default="" label="Threads" filter="url" validate="url" />
<field name="social_discord_url" type="url" default="" label="Discord" filter="url" validate="url" />
<field name="social_tiktok_url" type="url" default="" label="TikTok" filter="url" validate="url" />
<field name="social_reddit_url" type="url" default="" label="Reddit" filter="url" validate="url" />
<field name="social_pinterest_url" type="url" default="" label="Pinterest" filter="url" validate="url" />
<field name="social_snapchat_url" type="url" default="" label="Snapchat" filter="url" validate="url" />
<field name="social_telegram_url" type="url" default="" label="Telegram" filter="url" validate="url" />
<field name="social_whatsapp_url" type="url" default="" label="WhatsApp" filter="url" validate="url" />
<field name="social_tumblr_url" type="url" default="" label="Tumblr" filter="url" validate="url" />
<field name="social_twitch_url" type="url" default="" label="Twitch" filter="url" validate="url" />
<field name="social_spotify_url" type="url" default="" label="Spotify" filter="url" validate="url" />
<field name="social_soundcloud_url" type="url" default="" label="SoundCloud" filter="url" validate="url" />
<field name="social_flickr_url" type="url" default="" label="Flickr" filter="url" validate="url" />
<field name="social_vimeo_url" type="url" default="" label="Vimeo" filter="url" validate="url" />
<field name="social_linktree_url" type="url" default="" label="Linktree" filter="url" validate="url" />
<field name="social_facebook_url" type="url" default="" label="Facebook" filter="url" />
<field name="social_twitter_url" type="url" default="" label="X / Twitter" filter="url" />
<field name="social_instagram_url" type="url" default="" label="Instagram" filter="url" />
<field name="social_linkedin_url" type="url" default="" label="LinkedIn" filter="url" />
<field name="social_youtube_url" type="url" default="" label="YouTube" filter="url" />
<field name="social_github_url" type="url" default="" label="GitHub" filter="url" />
<field name="social_bluesky_url" type="url" default="" label="Bluesky" filter="url" />
<field name="social_threads_url" type="url" default="" label="Threads" filter="url" />
<field name="social_discord_url" type="url" default="" label="Discord" filter="url" />
<field name="social_tiktok_url" type="url" default="" label="TikTok" filter="url" />
<field name="social_reddit_url" type="url" default="" label="Reddit" filter="url" />
<field name="social_pinterest_url" type="url" default="" label="Pinterest" filter="url" />
<field name="social_snapchat_url" type="url" default="" label="Snapchat" filter="url" />
<field name="social_telegram_url" type="url" default="" label="Telegram" filter="url" />
<field name="social_whatsapp_url" type="url" default="" label="WhatsApp" filter="url" />
<field name="social_tumblr_url" type="url" default="" label="Tumblr" filter="url" />
<field name="social_twitch_url" type="url" default="" label="Twitch" filter="url" />
<field name="social_spotify_url" type="url" default="" label="Spotify" filter="url" />
<field name="social_soundcloud_url" type="url" default="" label="SoundCloud" filter="url" />
<field name="social_flickr_url" type="url" default="" label="Flickr" filter="url" />
<field name="social_vimeo_url" type="url" default="" label="Vimeo" filter="url" />
<field name="social_linktree_url" type="url" default="" label="Linktree" filter="url" />
<field name="social_mail_url" type="url" default="" label="Email" description="TPL_MOKOONYX_SOCIAL_MAIL_DESC" filter="string" />
</fieldset>
+2 -2
View File
@@ -136,11 +136,11 @@ A read-only reference tab displaying all available CSS custom properties organiz
---
*Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
+2 -2
View File
@@ -223,11 +223,11 @@ Additional variables are defined for: VirtueMart (`--vm-*`), Gable (`--gab-*`),
---
*Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
+2 -2
View File
@@ -114,11 +114,11 @@ For additional overrides beyond theme variables, use these files (also update-sa
---
*Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
+8 -8
View File
@@ -46,7 +46,7 @@ MokoOnyx/
│ ├── dark.custom.css # Custom dark palette template
│ └── brand-showcase.html # Brand showcase HTML template
├── Makefile # Build and validation automation
├── composer.json # PHP dependencies (mokocli)
├── composer.json # PHP dependencies (moko-platform)
├── package.json # Node.js dependencies (minification)
├── phpcs.xml # PHP CodeSniffer configuration
├── phpstan.neon # PHPStan static analysis configuration
@@ -63,7 +63,7 @@ MokoOnyx/
## Prerequisites
- **PHP** 8.1+
- **Composer** (for mokocli CLI and dependencies)
- **Composer** (for moko-platform CLI and dependencies)
- **Node.js** (optional, for build-time minification with terser/clean-css)
- **Make** (GNU Make or compatible)
- **zip** (or PowerShell for Windows)
@@ -110,7 +110,7 @@ Creates `dist/mokoonyx-{version}-beta.zip` (skips minification).
## Validation
MokoOnyx uses the **mokocli CLI** for code quality checks.
MokoOnyx uses the **moko-platform CLI** for code quality checks.
```bash
# Run all validation checks
@@ -144,7 +144,7 @@ After the release package is built:
1. Tag the release: `git tag {version}`
2. Push tags: `git push origin --tags`
3. Create a MokoGitea release and attach the ZIP from `dist/`
3. Create a Gitea release and attach the ZIP from `dist/`
### Generate checksums
@@ -185,7 +185,7 @@ Creates SHA-256 checksums for all ZIP files in `dist/`.
## Contributing
1. Fork the repository on [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx)
1. Fork the repository on [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx)
2. Create a feature branch from `dev`
3. Make your changes in `src/`
4. Run `make validate` to ensure all checks pass
@@ -245,7 +245,7 @@ When a PR is merged from `dev` to `main`:
1. The minor version is bumped (e.g., `02.08.xx` -> `02.09.00`)
2. Stability suffixes are stripped (stable release)
3. A MokoGitea release is created with the build package (ZIP + tar.gz + SHA-256)
3. A Gitea release is created with the build package (ZIP + tar.gz + SHA-256)
4. `updates.xml` is updated for the Joomla update server
5. The `dev` branch is recreated from `main`
6. A `version/XX.YY.ZZ` archive branch is created
@@ -277,11 +277,11 @@ vendor/bin/codecept run
---
*Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
-185
View File
@@ -1,185 +0,0 @@
[← Back to Home](Home)
# Configuration
MokoOnyx is configured through the Joomla template style editor at **System → Site Templates → MokoOnyx**. Parameters are organized into tabbed fieldsets.
---
## Migration Tab
Informational notes about the MokoCassiopeia migration process. No editable parameters -- this tab provides guidance only.
---
## Advanced Tab
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `developmentmode` | Toggle | Off | Enables development mode. When on, `.min` files are deleted and unminified source files are served. When off, minified files are auto-generated. |
| `fluidContainer` | Toggle | Static | Controls whether the main layout uses a fixed-width (`container`) or full-width (`container-fluid`) wrapper. |
---
## Favicon Tab
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `favicon_source` | Media picker | _(none)_ | Upload a PNG image. MokoOnyx auto-generates all required favicon sizes, `apple-touch-icon.png`, and `site.webmanifest` on the next page load. |
---
## Google Tab
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `googletagmanager` | Toggle | Off | Enable Google Tag Manager integration. |
| `googletagmanagerid` | Text | _(empty)_ | Your GTM container ID (e.g., `GTM-XXXXXXX`). Shown when GTM is enabled. |
| `googleanalytics` | Toggle | Off | Enable Google Analytics (GA4) integration. |
| `googleanalyticsid` | Text | _(empty)_ | Your GA4 measurement ID (e.g., `G-XXXXXXXXXX`). Shown when GA4 is enabled. |
| `googlesitekey` | Text | _(empty)_ | Google site verification meta tag value. |
| `googlevisitordetection` | Toggle | On | When enabled, sends visitor context to GTM/GA4: login status, user group, and page type. Shown when GTM or GA4 is enabled. |
---
## Custom Code Tab
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `custom_head_start` | Textarea | _(empty)_ | Raw HTML/JS injected at the **start** of `<head>`. Useful for consent managers or early scripts. |
| `custom_head_end` | Textarea | _(empty)_ | Raw HTML/JS injected at the **end** of `<head>`, before `</head>`. |
---
## Drawers Tab
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `drawerLeftIcon` | Text | `fa-solid fa-chevron-right` | Font Awesome class for the left drawer toggle button icon. |
| `drawerRightIcon` | Text | `fa-solid fa-chevron-left` | Font Awesome class for the right drawer toggle button icon. |
---
## Theme Tab
The Theme tab is the largest configuration area, organized into sub-sections.
### General
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `theme_enabled` | Toggle | On | Master switch for the theme system (light/dark mode). |
| `theme_control_type` | List | Radios | How the user switches themes: **Switch** (Light/Dark toggle), **Radios** (Light/Dark/System), or **None** (no visible control). |
| `theme_default_choice` | List | System | Default theme when no user preference is stored: **System**, **Light**, or **Dark**. |
| `theme_auto_dark` | Toggle | Off | Automatically switch to dark mode based on time of day. |
| `theme_meta_color_scheme` | Toggle | On | Output `<meta name="color-scheme">` tag for browser chrome theming. |
| `theme_meta_theme_color` | Toggle | On | Output `<meta name="theme-color">` tag for mobile browser address bar. |
| `theme_bridge_bs_aria` | Toggle | On | Bridge Bootstrap `data-bs-theme` attribute with ARIA attributes for screen readers. |
### Variables and Palettes
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `colorLightName` | List | Standard | Light theme palette: **Standard** (built-in) or **Custom** (loads `light.custom.css`). |
| `colorDarkName` | List | Standard | Dark theme palette: **Standard** (built-in) or **Custom** (loads `dark.custom.css`). |
See [Custom Themes](Custom-Themes) for how to create custom palettes.
### Typography
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `useFontScheme` | Grouped list | Roboto (local) | Font family. Options: **None**, **Roboto** (local), **Noto Sans** (local), **Fira Sans** (local). All local fonts are self-hosted for GDPR compliance. |
### Branding and Icons
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `brand` | Toggle | On | Show the brand/logo area in the header. |
| `logoFile` | Media picker | _(none)_ | Logo image file. Shown when brand is enabled. |
| `siteTitle` | Text | MokoOnyx | Site title displayed next to the logo. |
| `siteDescription` | Text | _(empty)_ | Tagline displayed below the site title. |
| `fA6KitCode` | Text | _(empty)_ | Font Awesome 7 Pro Kit code. If empty, the bundled Font Awesome 7 Free is used (2,000+ icons). |
### Header and Navigation
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `stickyHeader` | Toggle | Off | Make the header stick to the top of the viewport on scroll. |
| `backTop` | Toggle | Off | Show a "Back to Top" button when the user scrolls down. |
### Accessibility
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `a11y_toolbar_enabled` | Toggle | On | Master switch for the accessibility toolbar. |
| `a11y_text_resize` | Toggle | On | Allow users to increase/decrease text size. |
| `a11y_color_inversion` | Toggle | On | Allow users to invert page colors. |
| `a11y_high_contrast` | Toggle | On | Allow users to enable high-contrast mode. |
| `a11y_highlight_links` | Toggle | On | Allow users to highlight all links on the page. |
| `a11y_readable_font` | Toggle | On | Allow users to switch to a more readable font. |
| `a11y_pause_animations` | Toggle | On | Allow users to pause CSS animations. |
| `a11y_toolbar_pos` | Hidden | Bottom-right | Toolbar position (fixed to bottom-right in code). |
### Theme Toggle UI
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `theme_fab_enabled` | Toggle | On | Show the floating action button (FAB) for theme switching. |
| `theme_fab_pos` | Hidden | Bottom-right | FAB position (fixed to bottom-right in code). |
---
## Social Icons Tab
Configure social media icon links displayed in the topbar, footer, and/or as a floating sidebar.
### Display Positions
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `social_topbar` | Toggle | Off | Show social icons in the topbar. |
| `social_footer` | Toggle | Off | Show social icons in the footer. |
| `social_floating` | Toggle | Off | Show social icons as a fixed floating sidebar (hidden on mobile). |
| `social_floating_pos` | List | Left | Which side of the screen the floating bar appears on. Shown when floating is enabled. |
The floating sidebar includes a **collapsible toggle** — visitors can click the chevron to collapse/expand the bar. The collapsed state is remembered across page loads via localStorage.
### Style Options
Shown when at least one display position is enabled.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `social_icon_style` | List | Plain | Icon shape: **Plain**, **Square**, **Circle**, or **Rounded**. |
| `social_icon_size` | List | Medium | Icon size: **Small**, **Medium**, or **Large**. |
| `social_icon_color` | List | Theme | Colour scheme: **Theme** (CSS variables), **Brand** (platform colours), **Black**, or **White**. |
### Platform URLs
All URL fields use Joomla's `type="url"` with server-side `validate="url"` validation. Invalid URLs are silently skipped at render time and logged via `Joomla\CMS\Log\Log` for debugging.
Supported platforms: Facebook, X/Twitter, Instagram, LinkedIn, YouTube, GitHub, Bluesky, Threads, Discord, TikTok, Reddit, Pinterest, Snapchat, Telegram, WhatsApp, Tumblr, Twitch, Spotify, SoundCloud, Flickr, Vimeo, Linktree, and Email (`mailto:` or contact page URL).
### Tooltips
All social icon links display a **Bootstrap tooltip** on hover showing the platform name (e.g. "Follow us on GitHub"). Tooltip placement is context-aware — floating-left bars show tooltips on the right, floating-right on the left, and topbar/footer icons show tooltips above.
---
## CSS Variables Tab
A read-only reference tab displaying all available CSS custom properties organized by category. See the [CSS Variables](CSS-Variables) page for the full reference.
---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
| 1.1 | 2026-06-20 | Moko Consulting | Added Social Icons tab documentation |
-125
View File
@@ -1,125 +0,0 @@
[← Back to Home](Home)
# Custom Themes
MokoOnyx ships with **standard** light and dark palettes. You can create fully custom colour palettes by overriding CSS variables in dedicated files.
---
## How It Works
1. MokoOnyx loads a theme CSS file based on the `colorLightName` and `colorDarkName` template parameters
2. When set to **Standard**, it loads `light.standard.css` or `dark.standard.css`
3. When set to **Custom**, it loads `light.custom.css` or `dark.custom.css`
4. The theme file sets all CSS variables inside `:root[data-bs-theme="light"]` or `:root[data-bs-theme="dark"]`
---
## Creating a Custom Palette
### Step 1: Copy the Template
MokoOnyx ships starter templates in the `templates/` directory within the template source:
```
templates/mokoonyx/templates/light.custom.css
templates/mokoonyx/templates/dark.custom.css
```
These are full copies of the standard palettes -- every variable is included so you have a complete starting point.
### Step 2: Place Files in the Media Directory
Copy your customized files to the **media** directory (this location survives template updates):
```
media/templates/site/mokoonyx/css/theme/light.custom.css
media/templates/site/mokoonyx/css/theme/dark.custom.css
```
### Step 3: Select "Custom" in Template Settings
1. Go to **System → Site Templates → MokoOnyx**
2. Open the **Theme** tab
3. Under **Variables & Palettes**:
- Set **Light Theme** to **Custom**
- Set **Dark Theme** to **Custom**
4. Save
---
## File Locations
| File | Path | Purpose |
|------|------|---------|
| Light standard | `media/templates/site/mokoonyx/css/theme/light.standard.css` | Built-in light palette (do not edit) |
| Dark standard | `media/templates/site/mokoonyx/css/theme/dark.standard.css` | Built-in dark palette (do not edit) |
| Light custom | `media/templates/site/mokoonyx/css/theme/light.custom.css` | Your custom light palette |
| Dark custom | `media/templates/site/mokoonyx/css/theme/dark.custom.css` | Your custom dark palette |
| Light template | `templates/mokoonyx/templates/light.custom.css` | Starter template (copy from here) |
| Dark template | `templates/mokoonyx/templates/dark.custom.css` | Starter template (copy from here) |
---
## Key Variables to Customize
The most impactful variables to change for a quick rebrand:
```css
:root[data-bs-theme="light"] {
/* Brand colours -- the foundation of the entire palette */
--color-primary: #112855;
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #6fb3ff;
/* Body */
--body-color: #22262a;
--body-bg: #fff;
/* Links */
--color-link: #224FAA;
--link-color: #224faa;
--link-hover-color: #424077;
/* Navigation */
--mainmenu-nav-link-color: white;
--nav-text-color: white;
--nav-bg-color: var(--color-link);
/* Header */
--header-background-color: #adadad;
}
```
See the [CSS Variables](CSS-Variables) page for a complete reference of all available variables.
---
## Variable Sync on Update
When MokoOnyx is updated, the installer runs a **CSS variable sync** process. If new variables have been added to the standard palettes, they are automatically appended to your custom palette files with their default values. A notice is displayed in the admin panel telling you how many variables were added.
This ensures your custom palettes stay compatible with new template features without breaking existing customizations.
---
## Custom CSS and JavaScript
For additional overrides beyond theme variables, use these files (also update-safe):
| File | Path |
|------|------|
| Custom CSS | `media/templates/site/mokoonyx/css/user.css` |
| Custom JS | `media/templates/site/mokoonyx/js/user.js` |
---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
-66
View File
@@ -1,66 +0,0 @@
[← Back to Home](Home)
# Installation
## Requirements
| Requirement | Minimum Version |
|-------------|----------------|
| Joomla | 5.x or 6.x |
| PHP | 8.1 or higher |
## Download
Download the latest `mokoonyx-{version}.zip` from the [Releases page](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable).
## Install via Joomla Admin
1. Log in to your Joomla administrator panel
2. Navigate to **System → Install → Extensions**
3. Upload the `mokoonyx-{version}.zip` file
4. Wait for the installer to complete
The installer performs a preflight check to verify your PHP and Joomla versions meet the minimum requirements. If they do not, installation will be blocked with an error message.
## Set as Default Template
1. Navigate to **System → Site Templates**
2. Click the star icon next to **MokoOnyx** to set it as the default site template
## First Page Load (Migration)
If you are migrating from MokoCassiopeia, the migration runs automatically during install:
1. **Visit any page on your site** after installation -- the template activates immediately
2. Check **administrator/logs/mokoonyx.log.php** to confirm the migration completed
3. Once confirmed, uninstall MokoCassiopeia from **Extensions → Manage**
See the [Migration](Migration) page for full details on what gets migrated.
## Post-Install Notes
- The extension is automatically **locked** after install to prevent accidental uninstallation
- Stale `.min` files from previous versions are cleaned automatically
- Favicon stamps are cleared so favicons regenerate on the next page load
- MokoCassiopeia references in article content and modules are automatically updated to MokoOnyx
## Update Server
MokoOnyx includes an automatic update server. Joomla will notify you when new versions are available via **System → Update → Extensions**. Two update servers are configured for redundancy:
| Priority | Server |
|----------|--------|
| 1 | Gitea (git.mokoconsulting.tech) |
| 2 | GitHub (github.com) |
---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
-119
View File
@@ -1,119 +0,0 @@
[← Back to Home](Home)
# Migration from MokoCassiopeia
MokoOnyx is the successor to MokoCassiopeia. The migration runs **automatically during install/update** -- no manual steps are required beyond installing MokoOnyx.
---
## When Does Migration Run?
The migration runs in the `postflight()` method of the installer script (`script.php`), which executes during both `install` and `update` operations. It checks for existing MokoCassiopeia template styles in the database and only runs if they are found.
---
## What Gets Migrated
### 1. Template Styles and Parameters
- All MokoCassiopeia template styles are detected from the `#__template_styles` table
- For each MokoCassiopeia style, a matching MokoOnyx style is created with the same parameters
- The first MokoCassiopeia style's parameters are applied to the installer-created default MokoOnyx style
- Additional styles are created as new entries
- Parameter values are updated to replace `mokocassiopeia` references with `mokoonyx`
### 2. Default Template Assignment
If MokoCassiopeia was set as the default site template (`home = 1`), MokoOnyx automatically takes over as the default. The MokoCassiopeia style is unset as default.
### 3. Custom User Files
The following files are copied from the MokoCassiopeia media directory to MokoOnyx (only if the destination file does not already exist):
| File | Purpose |
|------|---------|
| `css/theme/light.custom.css` | Custom light palette |
| `css/theme/dark.custom.css` | Custom dark palette |
| `css/theme/light.custom.min.css` | Minified custom light palette |
| `css/theme/dark.custom.min.css` | Minified custom dark palette |
| `css/user.css` | Custom CSS overrides |
| `css/user.min.css` | Minified custom CSS |
| `js/user.js` | Custom JavaScript |
| `js/user.min.js` | Minified custom JavaScript |
Source: `media/templates/site/mokocassiopeia/`
Destination: `media/templates/site/mokoonyx/`
### 4. Content References
All references to "MokoCassiopeia" and "mokocassiopeia" in article content (`introtext` and `fulltext` columns) and module content are automatically replaced with "MokoOnyx" and "mokoonyx". This covers:
- Image paths (e.g., `media/templates/site/mokocassiopeia/...`)
- Template name references in custom HTML modules
- Any other text references in content
### 5. Additional Post-Install Tasks
These tasks run during every install/update (not just migration):
| Task | Description |
|------|-------------|
| **Favicon stamp cleared** | Deletes `.favicon_generated` stamp so favicons regenerate. Also removes the old `/images/favicons/` directory and root-level favicon files from previous versions. |
| **Media folder cleaned** | Removes stale `.min.css` and `.min.js` files (regenerated by `MokoMinifyHelper`), unminified vendor files, and deprecated files (`custom.css`, `custom.js`, `template-rtl.css`). |
| **Extension locked** | Sets `locked = 1` in `#__extensions` to prevent accidental uninstallation. |
---
## How to Trigger Migration
Migration runs automatically during installation. If you need to observe the results:
1. Install MokoOnyx via **System → Install → Extensions**
2. Go to **System → Site Templates** and verify MokoOnyx appears with your settings
3. Visit any page on your site to confirm the template is active
4. Check **administrator/logs/mokoonyx.log.php** for migration log entries
---
## Re-Running Migration
The migration runs on every install/update operation via the `postflight()` method. It is safe to re-run because:
- Style creation checks for existing styles before creating duplicates
- File copies only occur when the destination file does not exist
- Content replacements are idempotent (replacing "MokoOnyx" with "MokoOnyx" is a no-op)
To force a fresh migration, you can reinstall MokoOnyx by uploading the ZIP package again.
---
## After Migration
Once you have confirmed everything is working:
1. Uninstall MokoCassiopeia from **Extensions → Manage**
2. Optionally clean up any remaining MokoCassiopeia files in `media/templates/site/mokocassiopeia/`
---
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Settings not migrated | Check `administrator/logs/mokoonyx.log.php` for error messages. Verify MokoCassiopeia styles exist in `#__template_styles`. |
| Custom theme files missing | Verify files exist in `media/templates/site/mokocassiopeia/css/theme/`. The copy only runs if the destination does not already exist -- if MokoOnyx files are already present, they are not overwritten. |
| Content references not updated | Check the log for "Content replacement failed" or "Module replacement failed" warnings. Database permissions may be insufficient. |
| PHP version error | MokoOnyx requires PHP 8.1+. The preflight check blocks installation if this is not met. |
| Joomla version error | MokoOnyx requires Joomla 4.4+. The preflight check blocks installation if this is not met. |
---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
-113
View File
@@ -1,113 +0,0 @@
[← Back to Home](Home)
# Minification
MokoOnyx includes an automatic CSS/JS minification system that generates `.min` files at runtime based on the development mode setting.
---
## How It Works
The minification system is implemented in `MokoMinifyHelper` (`helper/minify.php`). It is called from the template's `index.php` on every page load and follows a simple rule:
- **Development mode OFF** (production): `.min` files are generated from source files when the source is newer or the `.min` file is missing
- **Development mode ON**: all `.min` files are **deleted** so the browser loads unminified source files for debugging
---
## Files Managed
### CSS Files
| Source File | Minified Output |
|-------------|----------------|
| `css/template.css` | `css/template.min.css` |
| `css/offline.css` | `css/offline.min.css` |
| `css/editor.css` | `css/editor.min.css` |
| `css/a11y-high-contrast.css` | `css/a11y-high-contrast.min.css` |
| `css/user.css` | `css/user.min.css` |
| `css/theme/light.standard.css` | `css/theme/light.standard.min.css` |
| `css/theme/dark.standard.css` | `css/theme/dark.standard.min.css` |
| `css/theme/light.custom.css` | `css/theme/light.custom.min.css` |
| `css/theme/dark.custom.css` | `css/theme/dark.custom.min.css` |
### JavaScript Files
| Source File | Minified Output |
|-------------|----------------|
| `js/template.js` | `js/template.min.js` |
| `js/gtm.js` | `js/gtm.min.js` |
| `js/user.js` | `js/user.min.js` |
All paths are relative to `media/templates/site/mokoonyx/`.
---
## Staleness Check
The system uses filesystem modification times to determine whether a `.min` file needs regenerating:
1. If the source file does not exist, skip it
2. If the `.min` file exists and its modification time is **newer or equal** to the source, skip it
3. Otherwise, read the source, minify it, and write the `.min` file
This means minification only runs when source files actually change, keeping page load overhead minimal.
---
## CSS Minification
The CSS minifier performs these transformations:
1. Remove CSS comments (preserving IE hacks)
2. Remove whitespace around `{ } : ; , > + ~`
3. Collapse remaining whitespace to single spaces
4. Remove trailing semicolons before closing braces (`;}` becomes `}`)
5. Strip leading/trailing whitespace
---
## JavaScript Minification
The JS minifier performs these transformations:
1. Remove multi-line comments (`/* ... */`)
2. Remove single-line comments (`//`) while preserving URLs
3. Collapse whitespace
4. Remove spaces around operators and punctuation
5. Restore necessary spaces after keywords (`var`, `let`, `const`, `return`, `typeof`, `instanceof`, `new`, `delete`, `throw`, `case`, `in`, `of`)
---
## Build-Time vs Runtime
| Context | What Happens |
|---------|-------------|
| **Runtime** (page load) | `MokoMinifyHelper::sync()` runs on every page load. In production mode, it checks timestamps and regenerates stale `.min` files. The overhead is negligible (filesystem stat calls only when files have not changed). |
| **Build-time** (`make build`) | The Makefile runs `make minify` before packaging. This uses the moko-platform `minify.js` script (Node.js) with `terser` and `clean-css` for higher-quality minification. |
| **Install/Update** | The installer script (`script.php`) deletes all `.min.css` and `.min.js` files in the `css/` and `js/` directories so they are cleanly regenerated by the runtime minifier on the first page load. Vendor `.min` files in `vendor/` are not touched. |
---
## Debug Mode Behaviour
To debug CSS or JS issues:
1. Go to **System → Site Templates → MokoOnyx**
2. Open the **Advanced** tab
3. Set **Development Mode** to **Yes**
4. Save
This immediately deletes all `.min` files. The template will load the unminified source files, making browser DevTools inspection straightforward. Remember to turn development mode **off** for production.
---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
+5 -5
View File
@@ -12,7 +12,7 @@ A modern, lightweight Joomla site template built on Cassiopeia with Font Awesome
| **PHP** | 8.1+ |
| **License** | GPL-3.0-or-later |
| **Replaces** | MokoCassiopeia (auto-migrates on install) |
| **Platform** | [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) (primary) |
| **Platform** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) (primary) |
---
@@ -81,18 +81,18 @@ Key parameters include:
| Repo | Purpose |
|------|---------|
| [Template-Client-MokoSuite](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-MokoSuite/wiki) | Client site template (extends MokoOnyx) |
| [MokoSuite](https://git.mokoconsulting.tech/MokoConsulting/MokoSuite/wiki) | MokoSuite system plugin |
| [Template-Client-WaaS](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-WaaS/wiki) | Client site template (extends MokoOnyx) |
| [MokoWaaS](https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/wiki) | WaaS system plugin |
| [joomla-api-mcp](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki) | Joomla Web Services API MCP |
| [deploy-mcp](https://git.mokoconsulting.tech/MokoConsulting/deploy-mcp/wiki) | Git-based deployment MCP |
---
> **[mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki)** -- central standards hub for all Moko Consulting projects.
> **[moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki)** -- central standards hub for all Moko Consulting projects.
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
+3 -3
View File
@@ -50,16 +50,16 @@ MokoOnyx includes an automatic update server. Joomla will notify you when new ve
| Priority | Server |
|----------|--------|
| 1 | MokoGitea (git.mokoconsulting.tech) |
| 1 | Gitea (git.mokoconsulting.tech) |
| 2 | GitHub (github.com) |
---
*Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
+2 -2
View File
@@ -108,11 +108,11 @@ Once you have confirmed everything is working:
---
*Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
+3 -3
View File
@@ -84,7 +84,7 @@ The JS minifier performs these transformations:
| Context | What Happens |
|---------|-------------|
| **Runtime** (page load) | `MokoMinifyHelper::sync()` runs on every page load. In production mode, it checks timestamps and regenerates stale `.min` files. The overhead is negligible (filesystem stat calls only when files have not changed). |
| **Build-time** (`make build`) | The Makefile runs `make minify` before packaging. This uses the mokocli `minify.js` script (Node.js) with `terser` and `clean-css` for higher-quality minification. |
| **Build-time** (`make build`) | The Makefile runs `make minify` before packaging. This uses the moko-platform `minify.js` script (Node.js) with `terser` and `clean-css` for higher-quality minification. |
| **Install/Update** | The installer script (`script.php`) deletes all `.min.css` and `.min.js` files in the `css/` and `js/` directories so they are cleanly regenerated by the runtime minifier on the first page load. Vendor `.min` files in `vendor/` are not touched. |
---
@@ -102,11 +102,11 @@ This immediately deletes all `.min` files. The template will load the unminified
---
*Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
-61
View File
@@ -1,61 +0,0 @@
## Code of Conduct
This Code of Conduct establishes expectations for behavior within the MokoOnyx project community. The objective is to maintain a professional, inclusive, and respectful environment aligned with open source governance best practices.
## Scope
This Code of Conduct applies to all project spaces, including:
* Repositories, issues, pull requests, discussions, and security advisories.
* Project documentation, workflows, and release processes.
* Any communication channels officially associated with the project.
## Our Standards
Participants are expected to:
* Communicate professionally and respectfully.
* Provide constructive feedback focused on technical merit and project objectives.
* Respect differing viewpoints, experience levels, and backgrounds.
* Follow documented contribution, security, and governance policies.
Unacceptable behavior includes:
* Harassment, discrimination, or exclusionary conduct.
* Personal attacks, insults, or inflammatory comments.
* Publishing private information without consent.
* Disruptive behavior that materially interferes with project operations.
## Enforcement Responsibilities
Project maintainers are responsible for:
* Clarifying standards when questions arise.
* Taking appropriate and proportionate corrective action when violations occur.
* Maintaining confidentiality to the extent practical during investigations.
## Reporting
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported through:
* Email: `hello@mokoconsulting.tech` with subject `CODE OF CONDUCT: MokoOnyx`.
Reports should include relevant context, links, screenshots, or other supporting information.
## Enforcement Guidelines
Corrective actions may include, but are not limited to:
* Private warning or request for corrective action.
* Temporary or permanent restriction from project participation.
* Removal of content that violates this Code of Conduct.
Decisions are made based on impact, severity, and pattern of behavior.
## No Retaliation
Retaliation against individuals who report concerns in good faith is not tolerated. Any retaliatory behavior will be treated as a separate violation.
## Jurisdiction
This project is managed from Tennessee, USA. This statement is informational and does not constitute legal advice.
-92
View File
@@ -1,92 +0,0 @@
## Contributing
This document defines how to contribute to Moko Consulting projects.
## Branching Strategy
All repositories follow this branching model:
```
feature/* --> dev --> main
```
| Branch | Purpose | Direct push? |
|--------|---------|-------------|
| `main` | Production/release branch | No -- PR merge only |
| `dev` | Integration branch | No -- PR merge only (CI bot whitelisted) |
| `feature/*` | Feature/bugfix work | Yes -- create freely |
| `rc/*` | Release candidates | No -- PR merge only |
| `alpha/*` | Alpha pre-releases | No -- PR merge only |
| `beta/*` | Beta pre-releases | No -- PR merge only |
| `version/*` | Release archive branches | Auto-created by CI |
### Workflow
1. Create a `feature/*` branch from `dev`
2. Make changes on the feature branch
3. Open a PR from `feature/*` to `dev`
4. After review, merge to `dev`
5. When ready for release, open a PR from `dev` to `main`
6. Merging to `main` triggers the auto-release pipeline
### Automated syncing
- `cascade-dev.yml` automatically forward-merges `main` to `dev` after every push to main
- If there are conflicts, a PR is created automatically
## Prerequisites
Contributors are expected to:
* Have a working understanding of the project's platform (Joomla or generic)
* Be familiar with Git and pull request workflows
* Review repository governance documents prior to submitting changes
### Quick Setup
```bash
git clone https://git.mokoconsulting.tech/MokoConsulting/<repo>.git
cd <repo>
git checkout dev
git checkout -b feature/my-change
```
## Coding and Formatting Standards
All contributions must:
* Follow platform coding standards (Joomla, PHP PSR) where applicable
* Conform to Moko Consulting repository standards for headers, metadata, and file structure
* Keep YAML workflow files ASCII-only (no em dashes, arrows, or emoji)
## Commit Messages
Commit messages should:
* Use conventional commits format: `type(scope): description`
* Types: feat, fix, chore, docs, refactor, test, ci
* Focus on what changed and why
* Include `[skip ci]` suffix for documentation-only changes
## Reporting Issues
Bug reports and enhancement requests should be filed as Gitea issues and include:
* Clear reproduction steps or use cases
* Expected versus actual behavior
* Relevant environment details
Security issues must follow the process in SECURITY.md and must not be reported publicly.
## Review Process
All pull requests are subject to review. Review criteria include:
* Technical correctness
* Alignment with project goals
* Maintainability and clarity
* Risk introduced to release and update processes
## License
By contributing, you agree that your contributions will be licensed under GPL-3.0-or-later, consistent with the rest of the project.
-249
View File
@@ -1,249 +0,0 @@
[← Back to Home](Home)
# CSS Variables Reference
All CSS variables are defined in the theme palette files (`light.standard.css` / `dark.standard.css`) under `:root[data-bs-theme="light"]` or `:root[data-bs-theme="dark"]`. Override any of these in your [custom theme](Custom-Themes) files.
---
## Brand and Theme Colors
| Variable | Light Default | Dark Default | Description |
|----------|--------------|-------------|-------------|
| `--color-primary` | `#112855` | `#112855` | Primary brand colour |
| `--accent-color-primary` | `#3f8ff0` | `#3f8ff0` | Primary accent colour |
| `--accent-color-secondary` | `#6fb3ff` | `#6fb3ff` | Secondary accent colour |
## Typography and Body
| Variable | Light Default | Dark Default | Description |
|----------|--------------|-------------|-------------|
| `--body-font-family` | System sans-serif stack | System sans-serif stack | Base font family |
| `--body-font-size` | `1rem` | `1rem` | Base font size |
| `--body-font-weight` | `400` | `400` | Base font weight |
| `--body-line-height` | `1.5` | `1.5` | Base line height |
| `--body-color` | `#22262a` | `#e6ebf1` | Body text colour |
| `--body-bg` | `#fff` | `#0e1318` | Body background colour |
| `--heading-color` | `inherit` | `#f1f5f9` | Heading text colour |
| `--emphasis-color` | `#000` | `#fff` | Emphasis text colour |
| `--secondary-color` | `#22262abf` | `#e6ebf1bf` | Secondary text colour |
| `--tertiary-color` | `#22262a80` | `#e6ebf180` | Tertiary text colour |
| `--muted-color` | `#6d757e` | `#6d757e` | Muted text colour |
| `--highlight-color` | `#22262a` | `#111` | Highlight text colour |
| `--highlight-bg` | `#fbeea8` | `#ffe28a1a` | Highlight background |
## Standard Colors
| Variable | Light Default | Dark Default |
|----------|--------------|-------------|
| `--blue` | `#010156` | `#91a4ff` |
| `--indigo` | `#6812f3` | `#b19cff` |
| `--purple` | `#6f42c2` | `#c0a5ff` |
| `--pink` | `#e93f8e` | `#ff8fc0` |
| `--red` | `#a51f18` | `#ff7a73` |
| `--orange` | `#fd7e17` | `#ff9c4d` |
| `--yellow` | `#ad6200` | `#ffd166` |
| `--green` | `#448344` | `#78d694` |
| `--teal` | `#5abfdd` | `#76e3ff` |
| `--cyan` | `#30638d` | `#6fb7ff` |
## Gray Scale
| Variable | Light Default | Dark Default |
|----------|--------------|-------------|
| `--gray-100` | `#f9fafb` | `#161a20` |
| `--gray-200` | `#eaedf0` | `#1b2027` |
| `--gray-300` | `#dfe3e7` | `#222831` |
| `--gray-400` | `#ced4da` | `#2b323b` |
| `--gray-500` | `#adb5bd` | `#36404a` |
| `--gray-600` | `#6d757e` | `#48525d` |
| `--gray-700` | `#484f56` | `#5b6672` |
| `--gray-800` | `#353b41` | `#cfd6de` |
| `--gray-900` | `#22262a` | `#e6ebf1` |
## Links
| Variable | Light Default | Dark Default | Description |
|----------|--------------|-------------|-------------|
| `--color-link` | `#224FAA` | `white` | Navigation link colour |
| `--color-hover` | `var(--accent-color-primary)` | `gray` | Navigation hover colour |
| `--link-color` | `#224faa` | `#8ab4f8` | Content link colour |
| `--link-hover-color` | `#424077` | `#c3d6ff` | Content link hover colour |
| `--link-decoration` | `underline` | `underline` | Link text decoration |
## Navigation
| Variable | Light Default | Dark Default | Description |
|----------|--------------|-------------|-------------|
| `--mainmenu-nav-link-color` | `white` | `#fff` | Main menu active link colour |
| `--nav-text-color` | `white` | `gray` | Navigation text colour |
| `--nav-bg-color` | `var(--color-link)` | `var(--color-primary)` | Navigation background colour |
## Layout and Spacing
| Variable | Light Default | Dark Default | Description |
|----------|--------------|-------------|-------------|
| `--padding-x` | `0.15rem` | `0.15rem` | Horizontal padding |
| `--padding-y` | `0.15rem` | `0.15rem` | Vertical padding |
| `--secondary-bg` | `#eaedf0` | `#151b22` | Secondary background |
| `--tertiary-bg` | `#f9fafb` | `#10151b` | Tertiary background |
| `--nav-toggle-size` | `3rem` | `3rem` | Mobile nav toggle size |
## Breakpoints
| Variable | Value | Description |
|----------|-------|-------------|
| `--bp-xs` | `0` | Extra small |
| `--bp-sm` | `576px` | Small |
| `--bp-md` | `768px` | Medium |
| `--bp-lg` | `992px` | Large |
| `--bp-xl` | `1200px` | Extra large |
## Borders
| Variable | Light Default | Dark Default |
|----------|--------------|-------------|
| `--border-width` | `1px` | `1px` |
| `--border-style` | `solid` | `solid` |
| `--border-color` | `#dfe3e7` | `#2b323b` |
| `--border-radius` | `.25rem` | `.25rem` |
| `--border-radius-sm` | `.2rem` | `.2rem` |
| `--border-radius-lg` | `.3rem` | `.3rem` |
| `--border-radius-pill` | `50rem` | `50rem` |
## Shadows
| Variable | Light Default | Dark Default |
|----------|--------------|-------------|
| `--box-shadow` | `0 .5rem 1rem #00000026` | `0 .5rem 1rem #00000066` |
| `--box-shadow-sm` | `0 .125rem .25rem #00000013` | `0 .125rem .25rem #00000040` |
| `--box-shadow-lg` | `0 1rem 3rem #0000002d` | `0 1rem 3rem #00000080` |
## Header Background
| Variable | Light Default | Dark Default | Description |
|----------|--------------|-------------|-------------|
| `--header-background-color` | `#adadad` | `#1a1f2b` | Header fallback colour |
| `--header-background-image` | `url(.../bg.svg)` | `url(.../bg.svg)` | Header background image |
| `--header-background-attachment` | `fixed` | `fixed` | CSS attachment |
| `--header-background-repeat` | `repeat` | `repeat` | CSS repeat |
## Container Backgrounds
Each container position (below-topbar, top-a, top-b, sidebar, bottom-a, bottom-b) has these variables:
| Variable Pattern | Description |
|-----------------|-------------|
| `--container-{position}-bg-image` | Background image (default: `none`) |
| `--container-{position}-bg-color` | Background colour (default: `transparent`) |
| `--container-{position}-bg-position` | Background position |
| `--container-{position}-bg-attachment` | Background attachment |
| `--container-{position}-bg-repeat` | Background repeat |
| `--container-{position}-bg-size` | Background size |
| `--container-{position}-border` | Border style |
| `--container-{position}-border-radius` | Border radius |
## Forms
| Variable | Light Default | Dark Default |
|----------|--------------|-------------|
| `--input-color` | `hsl(210, 11%, 15%)` | `#e6ebf1` |
| `--input-bg` | `hsl(210, 20%, 98%)` | `#1a2332` |
| `--input-border-color` | `hsl(210, 14%, 83%)` | `#3a4250` |
| `--input-focus-border-color` | `#8894aa` | `#5472ff` |
| `--form-valid-color` | `#448344` | `#78d694` |
| `--form-invalid-color` | `#a51f18` | `#ff8e86` |
## Bootstrap Palette
| Variable | Light Default | Dark Default |
|----------|--------------|-------------|
| `--primary` | `#010156` | `#010156` |
| `--secondary` | `#6d757e` | `#48525d` |
| `--success` | `#448344` | `#4aa664` |
| `--info` | `#30638d` | `#4f7aa0` |
| `--warning` | `#ad6200` | `#c77a00` |
| `--danger` | `#a51f18` | `#c23a31` |
| `--light` | `#f9fafb` | `#1b2027` |
| `--dark` | `#353b41` | `#0f1318` |
Each palette colour also has `-rgb`, `-text-emphasis`, `-bg-subtle`, and `-border-subtle` variants.
## Hero / Banner
| Variable | Description |
|----------|-------------|
| `--hero-height` | Banner height (default: `60vh`) |
| `--hero-color` | Banner text colour |
| `--hero-bg-repeat` | Background repeat |
| `--hero-bg-attachment` | Background attachment |
| `--hero-bg-position` | Background position |
| `--hero-bg-size` | Background size |
| `--hero-overlay-bg` | Overlay background colour |
| `--hero-primary-bg-color` | Primary variant background |
| `--hero-primary-overlay` | Primary variant overlay gradient |
| `--hero-secondary-bg-color` | Secondary variant background |
| `--hero-secondary-overlay` | Secondary variant overlay gradient |
| `--hero-card-*` | Hero card styling (bg, color, overlay, border-radius, padding, max-width) |
| `--hero-alt-card-*` | Alternative hero card styling |
## Block Colors
Used for top-a, top-b, bottom-a, bottom-b section backgrounds:
| Variable | Description |
|----------|-------------|
| `--block-color-1` through `--block-color-4` | Background colours |
| `--block-text-1` through `--block-text-4` | Text colours |
| `--block-highlight-bg` / `--block-highlight-text` | Highlight block |
| `--block-cta-bg` / `--block-cta-text` | Call-to-action block |
| `--block-alert-bg` / `--block-alert-text` | Alert block |
## Footer
| Variable | Default | Description |
|----------|---------|-------------|
| `--footer-padding-top` | `1rem` | Top padding |
| `--footer-padding-bottom` | `80px` | Bottom padding (accounts for FAB) |
| `--footer-grid-padding-y` | `2.5rem` | Grid vertical padding |
| `--footer-grid-padding-x` | `0.5em` | Grid horizontal padding |
## Theme FAB
| Variable | Light Default | Dark Default | Description |
|----------|--------------|-------------|-------------|
| `--theme-fab-bg` | `var(--color-primary)` | `#e6ebf1` | FAB background |
| `--theme-fab-color` | `#fff` | `#0e1318` | FAB icon colour |
| `--theme-fab-btn-bg` | `rgba(255,255,255,.15)` | `transparent` | FAB button background |
| `--theme-fab-border` | `rgba(255,255,255,0.3)` | `rgba(0,0,0,0.15)` | FAB border colour |
## Social Icons
| Variable | Default | Description |
|----------|---------|-------------|
| `--social-icon-size` | _(size preset)_ | Icon font size (overrides size preset) |
| `--social-icon-gap` | `0.5rem` | Gap between icons |
| `--social-icon-color` | `currentColor` | Icon colour |
| `--social-icon-hover-color` | `var(--accent-color-primary)` | Hover colour |
| `--social-icon-bg` | _(transparent)_ | Background for circle/rounded/square styles |
| `--social-icon-hover-bg` | _(varies)_ | Hover background |
| `--social-icon-radius` | `0.375rem` | Border radius for rounded style |
The floating bar's collapse toggle button inherits `--social-icon-bg`, `--social-icon-color`, and `--social-icon-hover-bg`.
## Component-Specific Variables
Additional variables are defined for: VirtueMart (`--vm-*`), Gable (`--gab-*`), accordion, alert, badge, breadcrumb, cards, dropdown, list group, modal, nav tabs/pills, offcanvas, pagination, popover, progress, spinner, table, toast, and tooltip components. See the theme palette files for the complete list.
---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
| 1.1 | 2026-06-20 | Moko Consulting | Added Social Icons variables |
-289
View File
@@ -1,289 +0,0 @@
[← Back to Home](Home)
# Development
This page covers the repository structure, build process, release workflow, and contributing guidelines for MokoOnyx.
---
## Repository Structure
```
MokoOnyx/
├── src/ # Template source (this becomes the installable package)
│ ├── component.php # Component-only page layout
│ ├── error.php # Error page layout
│ ├── index.php # Main template entry point
│ ├── joomla.asset.json # Joomla Web Asset Manager definitions
│ ├── offline.php # Offline page layout
│ ├── script.php # Install/update/uninstall script
│ ├── sync_custom_vars.php # CSS variable sync for custom palettes
│ ├── templateDetails.xml # Joomla template manifest
│ ├── helper/ # PHP helper classes
│ │ └── minify.php # CSS/JS auto-minification
│ ├── html/ # Template overrides (modules, components, layouts)
│ ├── language/ # Language files (en-GB, en-US)
│ ├── media/ # Static assets (installed to media/templates/site/mokoonyx/)
│ │ ├── css/ # Stylesheets
│ │ │ ├── template.css # Main template stylesheet
│ │ │ ├── editor.css # Backend editor stylesheet
│ │ │ ├── offline.css # Offline page styles
│ │ │ ├── a11y-high-contrast.css # High-contrast accessibility mode
│ │ │ ├── user.css # User custom CSS (survives updates)
│ │ │ ├── fonts/ # Local font files (Roboto, Noto Sans, Fira Sans)
│ │ │ └── theme/ # Theme palette files
│ │ │ ├── light.standard.css
│ │ │ └── dark.standard.css
│ │ ├── js/ # JavaScript
│ │ │ ├── template.js # Main template JS
│ │ │ ├── gtm.js # Google Tag Manager integration
│ │ │ └── user.js # User custom JS (survives updates)
│ │ ├── images/ # Template images (bg.svg, etc.)
│ │ ├── fonts/ # Font files
│ │ └── vendor/ # Third-party assets (Font Awesome 7 Free)
│ └── templates/ # Starter files for users
│ ├── light.custom.css # Custom light palette template
│ ├── dark.custom.css # Custom dark palette template
│ └── brand-showcase.html # Brand showcase HTML template
├── Makefile # Build and validation automation
├── composer.json # PHP dependencies (moko-platform)
├── package.json # Node.js dependencies (minification)
├── phpcs.xml # PHP CodeSniffer configuration
├── phpstan.neon # PHPStan static analysis configuration
├── codeception.yml # Testing configuration
├── updates.xml # Joomla update server manifest
├── tests/ # Test suites
├── scripts/ # Build scripts
├── docs/ # Documentation source
└── build/ / dist/ # Build output (gitignored)
```
---
## Prerequisites
- **PHP** 8.1+
- **Composer** (for moko-platform CLI and dependencies)
- **Node.js** (optional, for build-time minification with terser/clean-css)
- **Make** (GNU Make or compatible)
- **zip** (or PowerShell for Windows)
---
## Setup
```bash
# Clone the repository
git clone https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx.git
cd MokoOnyx
# Install dependencies
make install-deps
```
---
## Building Packages
### Build an installable ZIP
```bash
make build
```
This will:
1. Clean previous build artifacts (`build/` and `dist/`)
2. Minify CSS and JS assets
3. Copy `src/` contents to `build/package/`
4. Create `dist/mokoonyx-{version}.zip`
### Build a beta release
```bash
make build-beta
```
Creates `dist/mokoonyx-{version}-beta.zip` (skips minification).
---
## Validation
MokoOnyx uses the **moko-platform CLI** for code quality checks.
```bash
# Run all validation checks
make validate
# Individual checks
make lint # PHP syntax check
make check-joomla # Joomla manifest validation
make check-version # Version consistency across files
make check-xml # XML well-formedness
make check-headers # License header verification
make check-secrets # Credential leak scanning
# Full repository health check
make health
```
---
## Releasing
### Full release pipeline
```bash
make release
```
This runs the complete pipeline: `validate``build``checksum`
After the release package is built:
1. Tag the release: `git tag {version}`
2. Push tags: `git push origin --tags`
3. Create a Gitea release and attach the ZIP from `dist/`
### Generate checksums
```bash
make checksum
```
Creates SHA-256 checksums for all ZIP files in `dist/`.
---
## Available Make Targets
| Target | Description |
|--------|-------------|
| `make help` | Show all available targets |
| `make install-deps` | Install Composer dependencies |
| `make update-deps` | Update Composer dependencies |
| `make lint` | PHP syntax check |
| `make check-joomla` | Validate Joomla manifest |
| `make check-version` | Verify version consistency |
| `make check-headers` | Check license headers |
| `make check-secrets` | Scan for leaked credentials |
| `make check-xml` | Validate XML files |
| `make validate` | Run all validation checks |
| `make health` | Full repository health check |
| `make clean` | Clean build artifacts |
| `make minify` | Minify CSS/JS assets |
| `make build` | Build installable ZIP |
| `make build-beta` | Build beta release ZIP |
| `make checksum` | Generate SHA-256 checksums |
| `make release` | Full release pipeline |
| `make version` | Display version and extension info |
| `make security-check` | Composer security audit |
| `make all` | Full pipeline (deps, validate, build, checksum) |
---
## Contributing
1. Fork the repository on [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx)
2. Create a feature branch from `dev`
3. Make your changes in `src/`
4. Run `make validate` to ensure all checks pass
5. Submit a pull request against `dev`
### Code Standards
- All PHP files must include the GPL-3.0-or-later license header
- PHP code must pass syntax checks and PHPStan analysis
- XML files must be well-formed
- Version numbers must be consistent across `README.md`, `templateDetails.xml`, and other version-bearing files
- Attribution goes to **Moko Consulting**, not individual contributors
### Branching Model
| Branch | Purpose | Stability Suffix |
|--------|---------|-----------------|
| `main` | Stable releases | (none) |
| `dev` | Active development | `-dev` |
| `alpha` | Alpha pre-releases | `-alpha` |
| `beta` | Beta pre-releases | `-beta` |
| `rc` | Release candidates | `-rc` |
| `feature/*` | Feature development | `-dev` |
| `version/XX.YY.ZZ` | Archived release snapshots | (none) |
### Version Numbering
Versions use the format `XX.YY.ZZ` (two-digit segments, zero-padded):
- **XX** -- Major version (breaking changes)
- **YY** -- Minor version (new features, bumped on release to main)
- **ZZ** -- Patch version (auto-incremented on every push to dev/feature branches)
Stability suffixes are appended during development:
- `02.09.00-dev` -- Development build
- `02.09.00-alpha` -- Alpha pre-release
- `02.09.00-beta` -- Beta pre-release
- `02.09.00-rc` -- Release candidate
On merge to `main`, suffixes are stripped and the minor version is bumped.
### Auto Version Bump
On every push to `dev`, `alpha`, `beta`, `rc`, or `feature/*`:
1. The patch version is incremented (e.g., `02.08.05` -> `02.08.06`)
2. The stability suffix is applied based on the branch name
3. All version-bearing files are updated (manifests, CHANGELOG, PHP headers, etc.)
4. A commit is created with `[skip ci]` to avoid infinite loops
Commits with `[skip ci]` or `[skip bump]` in the message are ignored.
### Auto Release
When a PR is merged from `dev` to `main`:
1. The minor version is bumped (e.g., `02.08.xx` -> `02.09.00`)
2. Stability suffixes are stripped (stable release)
3. A Gitea release is created with the build package (ZIP + tar.gz + SHA-256)
4. `updates.xml` is updated for the Joomla update server
5. The `dev` branch is recreated from `main`
6. A `version/XX.YY.ZZ` archive branch is created
### Release Channels
The `updates.xml` file provides update streams for Joomla sites:
| Channel | Tag | Description |
|---------|-----|-------------|
| Development | `dev` | Latest dev build (or stable if higher) |
| Alpha | `alpha` | Alpha pre-release |
| Beta | `beta` | Beta pre-release |
| Release Candidate | `rc` | RC pre-release |
| Stable | `stable` | Production-ready release |
Joomla sites check the channel matching their configured stability level.
---
## Testing
The repository includes a `codeception.yml` configuration for automated testing:
```bash
# Run tests (requires Codeception via Composer)
vendor/bin/codecept run
```
---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
-78
View File
@@ -1,78 +0,0 @@
## Governance Overview
This document defines the governance framework for the MokoOnyx project. The objective is to ensure clear ownership, predictable decision making, and accountable stewardship across development, releases, and community interaction.
## Project Ownership
MokoOnyx is owned and maintained by **Moko Consulting**. Final authority for project direction, releases, and policy enforcement resides with the project owner.
## Roles and Responsibilities
### Maintainers
Maintainers are responsible for:
* Setting technical direction and release priorities.
* Reviewing and approving pull requests.
* Managing releases and distribution artifacts.
* Enforcing repository policies, including security and conduct requirements.
### Contributors
Contributors may:
* Submit pull requests and issues.
* Propose enhancements and report defects.
* Participate in technical discussions.
Contributors do not have merge authority unless explicitly granted.
## Decision Making
Decisions are made using a maintainers led model:
* Routine changes are approved through pull request review.
* Material changes affecting architecture, branding, licensing, or release processes require maintainer consensus.
* The project owner retains final decision authority if consensus cannot be reached.
## Change Management
Significant changes should:
* Be documented through issues or pull requests with clear rationale.
* Consider backward compatibility and upgrade impact.
* Include documentation updates when behavior or usage changes.
## Release Authority
Only maintainers may:
* Cut releases and publish artifacts.
* Update version numbers and manifests.
* Publish update metadata or advisories.
Release processes follow documented workflows and automation standards.
## Security Governance
Security issues are governed by the Security Policy (SECURITY.md in the repository). Maintainers are responsible for confidential handling, coordinated disclosure, and publication of advisories when appropriate.
## Conduct Enforcement
Behavior within the project is governed by the [Code of Conduct](Code-of-Conduct). Maintainers are responsible for enforcement actions and escalation handling.
## Conflict Resolution
Conflicts are handled through:
* Direct discussion between involved parties when appropriate.
* Maintainer mediation when necessary.
* Final determination by the project owner if required.
## External Dependencies
The project depends on Joomla core and other third party components. Governance of upstream projects remains outside the scope of this repository, but upstream changes may influence project decisions.
## Jurisdiction
This project is managed from Tennessee, USA. This statement is informational and does not constitute legal advice.
-23
View File
@@ -1,23 +0,0 @@
# Roadmap
> Auto-generated from project milestones and issues.
> Last updated: 2026-05-11 17:09 UTC
## Active Milestones
_No active milestones._
## Backlog
_Issues not yet assigned to a milestone._
- [ ] feat: AI-generated page layouts from text prompts (#21) `type: feature`
- [ ] feat: Visual page builder with drag-and-drop (#20) `type: feature`
- [ ] feat: Export/import themes (#19) `type: feature`
- [ ] feat: CSS variable editor (#18) `type: feature`
- [ ] feat: Theme presets (#17) `type: feature`
- [ ] feat: Live preview customizer (#16) `type: feature`
- [ ] bug: site.webmanifest 404 — favicon generator not creating manifest (#1)
---
_Generated by [sync-roadmap-wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/actions) workflow._
-123
View File
@@ -1,123 +0,0 @@
[← Back to Home](Home)
# Template Overrides
MokoOnyx includes template overrides for Joomla core modules, third-party extensions, and layout files. These overrides are located in `templates/mokoonyx/html/`.
---
## Joomla Core Module Overrides
| Module | Override File(s) | Description |
|--------|-----------------|-------------|
| `mod_articles_archive` | `default.php` | Articles archive module |
| `mod_articles_categories` | `default.php` | Article categories listing |
| `mod_articles_category` | `default.php` | Articles from a single category |
| `mod_articles_latest` | `default.php` | Latest articles module |
| `mod_articles_news` | `default.php` | News flash / articles newsflash |
| `mod_articles_popular` | `default.php` | Most-read articles |
| `mod_banners` | `default.php` | Banner display module |
| `mod_breadcrumbs` | `default.php` | Breadcrumb navigation |
| `mod_custom` | `default.php`, `hero.php` | Custom HTML module (includes a hero layout variant) |
| `mod_feed` | `default.php` | RSS/Atom feed display |
| `mod_finder` | `default.php` | Smart Search box |
| `mod_footer` | `default.php` | Footer information |
| `mod_languages` | `default.php` | Language switcher |
| `mod_login` | `default.php` | Login form |
| `mod_menu` | `default.php`, `horizontal.php`, `horizontal_component.php`, `horizontal_heading.php`, `horizontal_separator.php`, `horizontal_url.php`, `mainmenu.php`, `mainmenu_component.php`, `mainmenu_heading.php`, `mainmenu_separator.php`, `mainmenu_url.php` | Menu module with horizontal and main menu layouts |
| `mod_random_image` | `default.php` | Random image display |
| `mod_related_items` | `default.php` | Related articles |
| `mod_stats` | `default.php` | Site statistics |
| `mod_syndicate` | `default.php` | Syndication / RSS link |
| `mod_tags_popular` | `default.php` | Popular tags |
| `mod_tags_similar` | `default.php` | Similar tags |
| `mod_users_latest` | `default.php` | Latest registered users |
| `mod_whosonline` | `default.php` | Who's online |
| `mod_wrapper` | `default.php` | iFrame wrapper |
---
## Third-Party Extension Overrides
### Community Builder
| Module | Override File(s) | Description |
|--------|-----------------|-------------|
| `mod_cblogin` | `default.php`, `default_logout.php` | Community Builder login/logout module |
| `mod_comprofilermoderator` | `default.php` | CB moderator panel |
| `mod_comprofileronline` | `default.php` | CB online users |
### DPCalendar
| Module | Override File(s) | Description |
|--------|-----------------|-------------|
| `mod_dpcalendar_counter` | `default.php` | Event countdown timer |
| `mod_dpcalendar_map` | `default.php` | Event map display |
| `mod_dpcalendar_mini` | `default.php`, `default_icons.php`, `default_map.php`, `default_quickadd.php`, `_scripts.php` | Mini calendar widget |
| `mod_dpcalendar_upcoming` | `default.php`, `_scripts.php` | Upcoming events list |
### JoomGallery
| Component View | Override File(s) | Description |
|---------------|-----------------|-------------|
| `com_joomgallery/category` | `default.php`, `default_cat.php` | Gallery category view |
| `com_joomgallery/gallery` | `default.php` | Main gallery view |
| `com_joomgallery/image` | `default.php` | Single image view |
---
## Component Overrides
| Component | View | Override File(s) | Description |
|-----------|------|-----------------|-------------|
| `com_content` | `article` | `toc-left.php`, `toc-right.php` | Article views with Table of Contents positioned left or right |
---
## Layout Overrides
| Layout | Override File | Description |
|--------|--------------|-------------|
| `joomla.module` | `card.php` | Module chrome -- wraps any module in a Bootstrap card layout |
---
## Hero Layout (mod_custom)
The `hero.php` layout for `mod_custom` provides a full-width hero/banner module. It uses the hero CSS variables (`--hero-*`) for styling. Assign a custom HTML module to positions like `banner` or `top-a` and select the "hero" layout in the module's Advanced tab.
---
## Menu Layouts
MokoOnyx provides two specialized menu layouts:
- **horizontal** -- A horizontal navigation bar with dropdown support, used for the main site navigation
- **mainmenu** -- An enhanced main menu layout with support for component links, headings, separators, and URL items
Each layout has sub-templates for different menu item types: `_component`, `_heading`, `_separator`, and `_url`.
---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Field | Value |
|---|---|
| Minimum Version | 04.07.00 |
| Platform | joomla |
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-16 | Moko Consulting | Standards compliance update |
+3 -3
View File
@@ -99,11 +99,11 @@ Each layout has sub-templates for different menu item types: `_component`, `_hea
---
*Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting*
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
@@ -111,7 +111,7 @@ Each layout has sub-templates for different menu item types: `_component`, `_hea
---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Field | Value |
|---|---|
+1 -1
View File
@@ -70,7 +70,7 @@ Commit messages should:
## Reporting Issues
Bug reports and enhancement requests should be filed as MokoGitea issues and include:
Bug reports and enhancement requests should be filed as Gitea issues and include:
* Clear reproduction steps or use cases
* Expected versus actual behavior