171 Commits

Author SHA1 Message Date
mokogitea-actions[bot] 84a29cbe3a chore(version): pre-release bump to 02.28.09-dev [skip ci] 2026-07-13 09:49:42 +00:00
gitea-actions[bot] 9344b7b6bc chore(version): auto-bump patch 02.28.08-dev [skip ci] 2026-07-13 09:49:31 +00:00
mokogitea-actions[bot] 5a95d683ec Merge remote-tracking branch 'origin/main' into dev
Generic: Project CI / Lint & Validate (pull_request) Successful in 11s
Generic: Project CI / Tests (pull_request) Failing after 9s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 9s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 1s
Universal: PR Check / Require Docs Update (pull_request) Successful in 4s
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 9s
Universal: PR Check / Validate PR (pull_request) Failing after 14s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 13s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 15s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
# Conflicts:
#	.mokogitea/workflows/issue-branch.yml
2026-07-13 04:38:54 -05:00
mokogitea-actions[bot] a7f92dfe9f chore(version): pre-release bump to 02.28.07-dev [skip ci] 2026-07-13 09:32:54 +00:00
mokogitea-actions[bot] 3901b4ce36 chore(version): pre-release bump to 02.28.06-dev [skip ci] 2026-07-13 09:32:36 +00:00
jmiller ea21903738 chore(sync): CI notify retry + JEXEC whole-file scan from Template-Generic
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 11s
2026-07-13 09:31:36 +00:00
jmiller 74f31808d2 chore(sync): CI notify retry + JEXEC whole-file scan from Template-Generic
Universal: Auto Version Bump / Version Bump (push) Successful in 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 16s
2026-07-13 09:31:35 +00:00
jmiller 40faf56308 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-13 09:28:01 +00:00
jmiller ee22ee72ce chore: sync notify.yml from Template-Generic [skip ci] 2026-07-13 09:28:01 +00:00
jmiller bd2f955e9d chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-13 09:28:00 +00:00
mokogitea-actions[bot] 284a3f1c75 chore(version): pre-release bump to 02.28.05-dev [skip ci] 2026-07-13 02:24:44 +00:00
jmiller 9e9a3156ba Merge pull request 'chore: align to Joomla 6 / PHP 8.3' (#152) from fix/joomla6-php83 into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 11s
2026-07-13 02:24:07 +00:00
mokogitea-actions[bot] 5c14ee8c50 chore(version): pre-release bump to 02.28.04-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
2026-07-13 01:48:54 +00:00
mokogitea-actions[bot] 69f9b9cd53 chore(version): pre-release bump to 02.28.03-dev [skip ci] 2026-07-13 01:48:19 +00:00
mokogitea-actions[bot] 8eaf9d396b chore(version): pre-release bump to 02.28.02-dev [skip ci] 2026-07-13 01:48:07 +00:00
jmiller e0fd8b606e chore: align .mokogitea/CLAUDE.md to Joomla 6 / PHP 8.3
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s
Generic: Project CI / Tests (pull_request) Failing after 10s
Generic: Project CI / Lint & Validate (pull_request) Successful in 11s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 8s
Universal: PR Check / Validate PR (pull_request) Failing after 13s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-13 01:43:10 +00:00
jmiller 1cfc2086d4 chore: align README.md to Joomla 6 / PHP 8.3
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s
2026-07-13 01:43:09 +00:00
jmiller c0b4890fb3 chore: align composer.json to Joomla 6 / PHP 8.3
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 16s
2026-07-13 01:43:08 +00:00
mokogitea-actions[bot] 43527c543f chore(version): pre-release bump to 02.28.01-dev [skip ci] 2026-07-13 00:27:40 +00:00
jmiller 560736d1e0 Merge pull request 'chore(sync): cascade main -> dev' (#148) from main into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 13s
2026-07-13 00:27:29 +00:00
gitea-actions[bot] a34f1a58b8 chore(release): build 02.28.00 [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-07-13 00:27:25 +00:00
jmiller 2398f53d5c Merge pull request 'release: promote dev to main (social floating collapsible config + workflow cleanup)' (#150) from dev into main
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Generic: Project CI / Tests (pull_request) Failing after 8s
Universal: PR Check / Secret Scan (pull_request) Successful in 4s
Generic: Project CI / Lint & Validate (pull_request) Successful in 11s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 2s
Sync Workflows to Repos / sync (push) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 7s
Universal: PR Check / Validate PR (pull_request) Failing after 12s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-13 00:24:38 +00:00
mokogitea-actions[bot] 3986cad1b7 chore(version): pre-release bump to 02.27.11-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 14s
2026-07-13 00:22:52 +00:00
jmiller 5dee7aec96 Merge pull request 'chore: sync main into dev (resolve 98-commit infra/doc divergence)' (#151) from chore/sync-main-to-dev into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 11s
Generic: Project CI / Tests (pull_request) Failing after 9s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 14s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 4s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 9s
Universal: PR Check / Require Docs Update (pull_request) Failing after 4s
Universal: PR Check / Secret Scan (pull_request) Successful in 4s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 6s
Universal: PR Check / Validate PR (pull_request) Failing after 13s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
2026-07-13 00:22:39 +00:00
mokogitea-actions[bot] bdce98c35b chore(version): pre-release bump to 02.27.10-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-07-13 00:22:37 +00:00
jmiller 82e04b1818 chore: sync main into dev (resolve infra/doc divergence)
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Generic: Project CI / Tests (pull_request) Failing after 9s
Generic: Project CI / Lint & Validate (pull_request) Successful in 12s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 14s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 9s
Universal: PR Check / Validate PR (pull_request) Failing after 15s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
# Conflicts:
#	.mokogitea/workflows/issue-branch.yml
#	CHANGELOG.md
#	SECURITY.md
#	source/html/layouts/joomla/module/card.php
#	source/html/layouts/mokoonyx/article-metadata.php
#	source/media/css/a11y-high-contrast.css
#	source/templateDetails.xml
2026-07-12 19:22:08 -05:00
gitea-actions[bot] 69dbb4fecb chore(version): pre-release bump to 02.27.09-dev [skip ci] 2026-07-13 00:12:22 +00:00
jmiller 782abe81db Merge pull request 'feat(social): collapsible + collapsed-by-default config for floating social bar' (#149) from feature/social-floating-collapsible-config into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
2026-07-13 00:12:04 +00:00
gitea-actions[bot] 0fbff8671c chore(version): auto-bump patch 02.27.04-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-07-13 00:11:53 +00:00
jmiller abbd70b7f0 feat(social): add collapsible + collapsed-by-default config for floating social bar
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Secret Scan (pull_request) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Failing after 3s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 8s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Adds two template params for the floating social icons sidebar:
- social_floating_collapsible: show/hide the collapse toggle handle
- social_floating_collapsed: start collapsed on first visit (default on)

The layout renders the initial collapsed state server-side (no flash),
gates the toggle button behind the collapsible param, and exposes the
admin default via data-default-collapsed. The JS honors a visitor's
saved localStorage preference first, falling back to the admin default.
2026-07-12 19:11:05 -05:00
jmiller cd40561639 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-06 17:03:32 +00:00
jmiller 6c238ccb94 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-06 03:49:05 +00:00
jmiller fdd1f32003 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-06 03:49:03 +00:00
jmiller 2133ce8384 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-06 03:49:02 +00:00
jmiller 2deb05feb4 Merge chore/normalize-docs: normalize doc/config refs
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Generic: Project CI / Lint & Validate (pull_request) Successful in 16s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 4s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 13s
Universal: PR Check / Validate PR (pull_request) Failing after 1m3s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:50:39 +00:00
jmiller bd38e57788 chore(docs): normalize refs — MokoStandards->org wiki, moko-platform->mokocli, residual MokoGitea/MokoSuite
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 29s
Non-workflow docs/config only (CLAUDE.md, README, branch-protection, ISSUE_TEMPLATE/config.yml,
ci-issue-reporter). Workflow files, manifest schema, and Makefile install paths left for the
forge-rebrand gate. Authored-by: Moko Consulting
2026-07-05 22:50:36 +00:00
jmiller de6aa22bdb Merge fix/rebrand-wiki-docs: normalize in-repo wiki branding
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 17s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Failing after 29s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 17s
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m13s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:01:58 +00:00
jmiller 907b03e701 docs(wiki): normalize in-repo wiki branding (MokoGitea/mokocli/MokoStandards->org wiki/MokoSuite)
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 30s
2026-07-05 22:01:56 +00:00
jmiller 18558f0386 chore: sync workflow-sync-trigger.yml from Template-Generic [skip ci] 2026-07-05 21:31:37 +00:00
jmiller bab2a96148 chore: sync version-set.yml from Template-Generic [skip ci] 2026-07-05 21:31:36 +00:00
jmiller 0baf843677 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-07-05 21:31:35 +00:00
jmiller 1f56b49f64 chore: sync rc-revert.yml from Template-Generic [skip ci] 2026-07-05 21:31:34 +00:00
jmiller b50aeefbdf chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-05 21:31:33 +00:00
jmiller e91844013f chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-05 21:31:32 +00:00
jmiller d448aca8a8 chore: sync notify.yml from Template-Generic [skip ci] 2026-07-05 21:31:31 +00:00
jmiller 5103631d61 chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-05 21:31:30 +00:00
jmiller 25e23af1f7 chore: sync gitleaks.yml from Template-Generic [skip ci] 2026-07-05 21:31:29 +00:00
jmiller d24c3f95ad chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-05 21:31:28 +00:00
jmiller cc74944480 chore: sync ci-issue-reporter.yml from Template-Generic [skip ci] 2026-07-05 21:31:27 +00:00
jmiller 5f4dc490ca chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-05 21:31:25 +00:00
jmiller 9171576664 chore: sync cascade-dev.yml from Template-Generic [skip ci] 2026-07-05 21:31:24 +00:00
jmiller 8fc1ada2f7 chore: sync branch-cleanup.yml from Template-Generic [skip ci] 2026-07-05 21:31:23 +00:00
jmiller 3a4d518a14 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-05 21:31:21 +00:00
jmiller 8af693ca8f chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-07-05 21:31:19 +00:00
jmiller d9544de034 chore: sync workflow-sync-trigger.yml from Template-Generic [skip ci] 2026-07-05 21:08:05 +00:00
jmiller da1765f04d chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-05 21:08:03 +00:00
jmiller 5a52c5ed6f chore: sync version-set.yml from Template-Generic [skip ci] 2026-07-05 20:39:34 +00:00
jmiller 4f1abee85f chore: sync sync-on-merge.yml from Template-Generic [skip ci] 2026-07-05 20:39:32 +00:00
jmiller c19c43942a chore: sync rc-revert.yml from Template-Generic [skip ci] 2026-07-05 20:39:30 +00:00
jmiller b410550fd8 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-05 20:39:27 +00:00
jmiller 6ad1a3d937 chore: sync gitleaks.yml from Template-Generic [skip ci] 2026-07-05 20:39:25 +00:00
jmiller 08c8d22189 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-07-05 20:39:21 +00:00
jmiller dc9d2955e8 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-07-05 20:34:22 +00:00
jmiller 635577e699 chore: sync rc-revert.yml from Template-Generic [skip ci] 2026-07-05 20:34:20 +00:00
jmiller 21bfd03693 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-05 20:34:19 +00:00
jmiller cef5f897d3 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-05 20:34:17 +00:00
jmiller 1e1d372ff0 chore: sync gitleaks.yml from Template-Generic [skip ci] 2026-07-05 20:34:15 +00:00
jmiller 80cd0ee5ab chore: sync ci-issue-reporter.yml from Template-Generic [skip ci] 2026-07-05 20:34:13 +00:00
jmiller 0ac6dce06b chore: sync cascade-dev.yml from Template-Generic [skip ci] 2026-07-05 20:34:11 +00:00
jmiller 1820b98369 chore: sync branch-cleanup.yml from Template-Generic [skip ci] 2026-07-05 20:34:09 +00:00
jmiller a0f73280e4 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-05 20:34:08 +00:00
jmiller fc5bf68017 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-07-05 20:34:05 +00:00
jmiller b025362d92 chore: sync notify.yml from Template-Generic [skip ci] 2026-07-05 00:04:12 +00:00
jmiller c0a762d37e chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-05 00:04:11 +00:00
jmiller ddaed01a38 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-04 23:25:55 +00:00
jmiller f66d80d61e chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 20:27:22 +00:00
jmiller 9ce4223bb3 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 20:21:59 +00:00
jmiller 61b42fdfde chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 20:21:56 +00:00
jmiller 1962b10dec chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 19:37:21 +00:00
jmiller 57fb62ffc3 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 19:37:18 +00:00
jmiller 1ee461f2c9 chore: sync branch-cleanup.yml from Template-Generic [skip ci] 2026-07-04 19:37:16 +00:00
jmiller b55c9ff833 chore: sync sync-on-merge.yml from Template-Generic [skip ci] 2026-07-04 19:03:19 +00:00
jmiller 7ec42120fc chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-04 19:03:18 +00:00
jmiller e48c18449f chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 19:03:17 +00:00
jmiller c5d70581d5 chore: sync notify.yml from Template-Generic [skip ci] 2026-07-04 19:03:16 +00:00
jmiller a3bb855a1c chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-04 19:03:15 +00:00
jmiller e56a44aae2 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 19:03:14 +00:00
jmiller a93a12b504 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-04 19:03:12 +00:00
jmiller 6c343b5c42 Merge pull request 'fix: remove orphaned deploy-manual workflow' (#147) from fix/remove-deploy-manual into main
fix: remove orphaned deploy-manual workflow [skip ci]
2026-06-30 18:33:27 +00:00
jmiller 5dadb43748 fix: remove orphaned deploy-manual workflow [skip ci] 2026-06-30 18:06:53 +00:00
jmiller a9094817ca chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-29 16:01:18 +00:00
gitea-actions[bot] e08fccd1d9 chore: promote changelog [Unreleased] → [02.27.06] 2026-06-29 16:00:47 +00:00
gitea-actions[bot] 892bdee751 chore(release): build 02.27.06 [skip ci] 2026-06-29 16:00:44 +00:00
jmiller 0d205bcc65 Merge pull request 'refactor(css): remove redundant .text-bg-* combined utility' (#146) from fix/text-bg-background-only into main 2026-06-29 16:00:30 +00:00
gitea-actions[bot] c54b164826 chore(version): pre-release bump to 02.27.06-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 17s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 3m18s
2026-06-29 15:55:28 +00:00
jmiller 168c091352 refactor(css): remove redundant .text-bg-* combined utility
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 15s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 13s
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 18s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 36s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
.text-bg-* both (a) had a misleading prefix and (b) forced a black/white
foreground that fought the theme. The theme already provides separate,
theme-aware utilities: .text-* (color: var(--*-rgb)) and .bg-*
(background-color: var(--*-rgb)). Remove .text-bg-* and compose
.text-{ctx} + .bg-{ctx} instead.

Authored-by: Moko Consulting
2026-06-29 10:55:09 -05:00
jmiller 0aa0569ba3 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-29 06:34:25 +00:00
jmiller c3d54b2c2e chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-06-27 20:43:33 +00:00
jmiller 4ce0c67880 chore: sync rc-revert.yml from Template-Generic [skip ci] 2026-06-27 05:31:51 +00:00
jmiller 96b4b42787 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-06-27 00:48:58 +00:00
jmiller 1a7a856a09 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-06-25 19:45:49 +00:00
jmiller 5f3f94f5f6 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-25 19:45:48 +00:00
jmiller d3dee12348 chore: sync ci-issue-reporter.yml from Template-Generic [skip ci] 2026-06-25 19:45:46 +00:00
jmiller 2c43418933 chore: sync workflow-sync-trigger.yml from Template-Generic [skip ci] 2026-06-25 17:09:59 +00:00
jmiller f22f9dc440 chore: sync version-set.yml from Template-Generic [skip ci] 2026-06-25 17:09:58 +00:00
jmiller f78290d8fa chore: sync repo-health.yml from Template-Generic [skip ci] 2026-06-25 17:09:58 +00:00
jmiller b0e7e84cd5 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-06-25 17:09:57 +00:00
jmiller 9b9b6aed89 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-25 17:09:57 +00:00
jmiller 15e8dc15f0 chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-25 17:09:56 +00:00
jmiller 556d282550 chore: sync deploy-manual.yml from Template-Generic [skip ci] 2026-06-25 17:09:55 +00:00
jmiller bace9d0205 chore: sync cleanup.yml from Template-Generic [skip ci] 2026-06-25 17:09:55 +00:00
jmiller 69eda2d1c6 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-25 17:09:54 +00:00
jmiller 148aaecfa4 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-06-25 17:09:54 +00:00
jmiller bef3ce381c chore: sync version-set.yml from Template-Generic [skip ci] 2026-06-24 11:50:02 +00:00
jmiller 1ca4549994 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-24 11:50:00 +00:00
jmiller 0cf1fed629 chore: remove security-audit.yml -- handled by MokoGitea 2026-06-23 18:27:06 +00:00
gitea-actions[bot] 1d428d0944 chore(version): pre-release bump to 02.27.03-dev [skip ci] 2026-06-23 18:12:19 +00:00
gitea-actions[bot] 888be7ebc0 chore(version): auto-bump patch 02.27.02-dev [skip ci] 2026-06-23 18:11:56 +00:00
jmiller a97b985101 chore: remove security-audit.yml -- handled by MokoGitea
Universal: Auto Version Bump / Version Bump (push) Successful in 17s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 26s
2026-06-23 18:04:59 +00:00
gitea-actions[bot] cba1423546 chore(version): pre-release bump to 02.27.01-dev [skip ci] 2026-06-23 18:04:35 +00:00
gitea-actions[bot] a17361879f chore(version): auto-bump patch 02.26.03-dev [skip ci] 2026-06-23 18:04:14 +00:00
jmiller c81df6609f chore: remove deploy-manual.yml -- no longer needed
Universal: Auto Version Bump / Version Bump (push) Successful in 26s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 20s
2026-06-23 17:59:40 +00:00
jmiller bbe44cc31d chore: sync deploy-manual.yml from Template-Generic [skip ci] 2026-06-23 17:50:38 +00:00
jmiller b7ec2a7efa chore: remove deprecated .mokogitea/workflows/composer-publish.yml [skip ci] 2026-06-23 17:38:19 +00:00
jmiller d5bdb3871e chore: remove deprecated .mokogitea/workflows/deploy-manual.yml [skip ci] 2026-06-23 17:38:15 +00:00
jmiller 0947250568 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-22 00:34:38 +00:00
jmiller 71b7b3307a chore: remove unused Makefile - builds handled by CI auto-release 2026-06-21 23:55:20 +00:00
jmiller 56b8d3b78c chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-21 22:02:24 +00:00
jmiller 440cf41c3e chore: sync pre-release.yml from Template-Generic [skip ci] 2026-06-21 16:05:14 +00:00
jmiller 575588a14f chore: sync composer-publish.yml from Template-Generic [skip ci] 2026-06-21 06:34:43 +00:00
jmiller 6f67f7af37 chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-21 02:42:12 +00:00
gitea-actions[bot] 138ee2ac40 chore: promote changelog [Unreleased] → [02.27.00] 2026-06-21 02:42:04 +00:00
gitea-actions[bot] fe362d3b28 chore(release): build 02.27.00 [skip ci] 2026-06-21 02:42:00 +00:00
gitea-actions[bot] b1792627d7 chore(version): pre-release bump to 02.26.02-dev [skip ci] 2026-06-21 02:41:39 +00:00
jmiller ebf365dfb3 Merge pull request 'release: collapsible social bar, tooltips, URL validation, blog image fix' (#144) from dev into main 2026-06-21 02:41:21 +00:00
gitea-actions[bot] 254c06f1d6 chore(version): auto-bump patch 02.26.01-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 20s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 1m45s
2026-06-21 02:41:17 +00:00
Jonathan Miller a6f9352686 merge: resolve CHANGELOG conflict from main sync
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Blocked by required conditions
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Blocked by required conditions
Joomla: Extension CI / PHPStan Analysis (pull_request) Blocked by required conditions
Joomla: Extension CI / Build RC Pre-Release (pull_request) Blocked by required conditions
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 10s
Universal: PR Check / Validate PR (pull_request) Failing after 12s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 13s
Generic: Repo Health / Access control (pull_request) Successful in 3s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 19s
Universal: Auto Version Bump / Version Bump (push) Successful in 21s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 24s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 57s
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
2026-06-20 21:40:34 -05:00
jmiller d21dc84564 Merge pull request 'fix: set blog item image object-fit to none' (#143) from fix/blog-image-object-fit into dev
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Blocked by required conditions
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Blocked by required conditions
Joomla: Extension CI / PHPStan Analysis (pull_request) Blocked by required conditions
Joomla: Extension CI / Build RC Pre-Release (pull_request) Blocked by required conditions
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 4s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Failing after 5s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 7s
Generic: Project CI / Lint & Validate (pull_request) Successful in 13s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 35s
Universal: PR Check / Validate PR (pull_request) Successful in 35s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
2026-06-21 02:35:03 +00:00
Jonathan Miller ca4730c12f fix: set blog item image object-fit to none
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Project CI / Lint & Validate (pull_request) Successful in 12s
Universal: PR Check / Validate PR (pull_request) Successful in 13s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 11s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-06-20 21:22:02 -05:00
jmiller 83b18da22b Merge pull request 'docs: add social icons to README features and update version' (#142) from docs/readme-social-icons into dev 2026-06-21 01:38:41 +00:00
Jonathan Miller 6c2857820e docs: add social icons to README features and update version
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Project CI / Lint & Validate (pull_request) Successful in 26s
Universal: PR Check / Validate PR (pull_request) Successful in 32s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 12s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-06-20 20:36:54 -05:00
jmiller 363971ffa8 chore: sync deploy-manual.yml from Template-Generic [skip ci] 2026-06-21 01:27:30 +00:00
jmiller 5de3d6c25c Merge pull request 'feat: collapsible floating social bar, tooltips, and URL validation' (#141) from feature/social-floating-enhancements into dev 2026-06-21 01:25:24 +00:00
Jonathan Miller 7063b6d633 feat: add collapsible floating social bar, tooltips, and URL validation
Universal: Auto Version Bump / Version Bump (push) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Project CI / Lint & Validate (pull_request) Successful in 23s
Universal: PR Check / Validate PR (pull_request) Successful in 29s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 9s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
- Floating social bar now has a toggle button to collapse/expand,
  with state persisted in localStorage
- All social icon links show Bootstrap tooltips on hover with the
  platform name, placement-aware based on position
- Enhanced URL validation: server-side Joomla validate="url" on all
  social URL fields, stricter PHP regex with Joomla log warnings
  for skipped invalid URLs
- Updated CSS Variables tab docs for floating bar variables
2026-06-20 20:22:47 -05:00
jmiller 2b3bcbac9a chore: delete manifest.xml (no longer used) 2026-06-21 00:19:37 +00:00
jmiller c0aab513c0 chore: sync pr-check.yml from Template-Joomla [skip ci] 2026-06-20 23:45:55 +00:00
jmiller 24e0a1af85 chore: sync gitleaks.yml from Template-Joomla [skip ci] 2026-06-20 23:45:54 +00:00
jmiller a05a93af76 chore: sync ci-generic.yml from Template-Joomla [skip ci] 2026-06-20 23:45:53 +00:00
jmiller 4870336a5a chore: sync workflow-sync-trigger.yml from Template-Joomla [skip ci] 2026-06-20 23:07:40 +00:00
jmiller 5edcb6bd04 chore: sync rc-revert.yml from Template-Joomla [skip ci] 2026-06-20 23:07:40 +00:00
jmiller d1d2cb1f77 chore: sync issue-branch.yml from Template-Joomla [skip ci] 2026-06-20 23:07:39 +00:00
jmiller 388c9138c9 chore: sync ci-joomla.yml from Template-Joomla [skip ci] 2026-06-20 23:07:38 +00:00
jmiller a49bcd7e65 chore: sync auto-release.yml from Template-Joomla [skip ci] 2026-06-20 23:07:37 +00:00
jmiller 1592ab5efa chore: sync repo-health.yml from Template-Joomla [skip ci] 2026-06-20 22:29:54 +00:00
jmiller d5513b9517 chore: sync rc-revert.yml from Template-Joomla [skip ci] 2026-06-20 22:29:54 +00:00
jmiller 36f4eeb122 chore: sync pr-check.yml from Template-Joomla [skip ci] 2026-06-20 22:29:53 +00:00
jmiller 28d90a93a1 chore: sync cleanup.yml from Template-Joomla [skip ci] 2026-06-20 22:29:53 +00:00
jmiller 4dedece818 ci: sync security-audit.yml from Template-Joomla [skip ci] 2026-06-20 22:26:30 +00:00
jmiller 5e0d6720c6 ci: sync repo-health.yml from Template-Joomla [skip ci] 2026-06-20 22:26:02 +00:00
jmiller 2fd86c1f5b ci: sync rc-revert.yml from Template-Joomla [skip ci] 2026-06-20 22:25:53 +00:00
jmiller 07ec634dc0 ci: sync pr-check.yml from Template-Joomla [skip ci] 2026-06-20 22:24:46 +00:00
jmiller d6d67f8913 ci: sync issue-branch.yml from Template-Joomla [skip ci] 2026-06-20 22:22:20 +00:00
jmiller f27ca6330e ci: sync cleanup.yml from Template-Joomla [skip ci] 2026-06-20 22:15:34 +00:00
jmiller 9b195d2a14 chore: sync issue-branch.yml from Template-Joomla [skip ci] 2026-06-20 21:35:16 +00:00
jmiller 748bf45646 chore: sync ci-generic.yml from Template-Joomla [skip ci] 2026-06-20 21:35:15 +00:00
jmiller 3b041f7008 ci: sync ci-generic.yml from Template-Joomla [skip ci] 2026-06-20 21:34:01 +00:00
jmiller 3ec4c57f42 ci: sync cascade-dev.yml from Template-Joomla [skip ci] 2026-06-20 21:31:33 +00:00
jmiller 2170d8d83b ci: sync branch-cleanup.yml from Template-Joomla [skip ci] 2026-06-20 21:28:08 +00:00
jmiller 7692478e22 ci: sync auto-release.yml from Template-Joomla [skip ci] 2026-06-20 21:26:57 +00:00
gitea-actions[bot] 3f1c5a317f chore: promote changelog [Unreleased] → [02.26.00] 2026-06-20 20:56:35 +00:00
gitea-actions[bot] 7ffee71dee chore(release): build 02.26.00 [skip ci] 2026-06-20 20:56:33 +00:00
63 changed files with 3785 additions and 1898 deletions
View File
+5 -5
View File
@@ -1,6 +1,6 @@
# MokoOnyx # MokoOnyx
Joomla site template — successor to MokoCassiopeia. Base template for all WaaS client deployments. Joomla site template — successor to MokoCassiopeia. Base template for all MokoSuite client deployments.
## Quick Reference ## Quick Reference
@@ -8,7 +8,7 @@ Joomla site template — successor to MokoCassiopeia. Base template for all WaaS
|---|---| |---|---|
| **Element** | `tpl_mokoonyx` | | **Element** | `tpl_mokoonyx` |
| **Type** | Joomla site template | | **Type** | Joomla site template |
| **Language** | PHP 8.1+ / CSS / JS | | **Language** | PHP 8.3+ / CSS / JS |
| **Branch** | develop on `dev`, merge to `main` (protected) | | **Branch** | develop on `dev`, merge to `main` (protected) |
| **Wiki** | [MokoOnyx Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/wiki) | | **Wiki** | [MokoOnyx Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/wiki) |
@@ -53,11 +53,11 @@ Client repos (`client-clarksvillefurs`, `client-optainfunding`, etc.) install `t
- **Attribution**: `Authored-by: Moko Consulting` - **Attribution**: `Authored-by: Moko Consulting`
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) - **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
- **Minification**: handled at build time (CI) and runtime (MokoMinifyHelper) - **Minification**: handled at build time (CI) and runtime (MokoMinifyHelper)
- **Wiki**: documentation lives in the Gitea wiki, not `docs/` files - **Wiki**: documentation lives in the MokoGitea wiki, not `docs/` files
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home) - **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)
## Coding Standards ## Coding Standards
- PHP 8.1+ minimum - PHP 8.3+ minimum
- SPDX license headers on all PHP files - SPDX license headers on all PHP files
- `defined('_JEXEC') or die;` on all PHP files - `defined('_JEXEC') or die;` on all PHP files
+1 -1
View File
@@ -8,7 +8,7 @@ contact_links:
url: https://mokoconsulting.tech/ url: https://mokoconsulting.tech/
about: Get help or ask questions through our website about: Get help or ask questions through our website
- name: MokoStandards Documentation - name: MokoStandards Documentation
url: https://git.mokoconsulting.tech/MokoConsulting/moko-platform url: https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki
about: View our coding standards and best practices about: View our coding standards and best practices
- name: Report a Security Vulnerability - name: Report a Security Vulnerability
url: https://git.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new 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. Add any other context, mockups, or screenshots about the feature request here.
## Relevant Standards ## Relevant Standards
Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)?
- [ ] Accessibility (WCAG 2.1 AA) - [ ] Accessibility (WCAG 2.1 AA)
- [ ] Localization (en_US/en_GB) - [ ] Localization (en_US/en_GB)
- [ ] Security best practices - [ ] Security best practices
+1 -1
View File
@@ -35,7 +35,7 @@ Use this template only for:
<!-- Describe how this could be addressed --> <!-- Describe how this could be addressed -->
## Standards Reference ## Standards Reference
Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)?
- [ ] SPDX license identifiers - [ ] SPDX license identifiers
- [ ] Secret management - [ ] Secret management
- [ ] Dependency security - [ ] Dependency security
+5 -5
View File
@@ -1,8 +1,8 @@
--- ---
name: WaaS Client Site Issue name: MokoSuite Client Site Issue
about: Report an issue with a WaaS client site (branding, deployment, media sync) about: Report an issue with a MokoSuite client site (branding, deployment, media sync)
title: '[WAAS] ' title: '[WAAS] '
labels: 'waas, client-site' labels: 'mokosuite, client-site'
assignees: '' assignees: ''
--- ---
@@ -18,7 +18,7 @@ assignees: ''
## Client Site ## Client Site
- **Client Org**: [e.g., ClarksvilleFurs] - **Client Org**: [e.g., ClarksvilleFurs]
- **Repo**: [e.g., client-waas-clarksvillefurs] - **Repo**: [e.g., client-mokosuite-clarksvillefurs]
- **Environment**: [Dev / Production] - **Environment**: [Dev / Production]
- **Site URL**: [dev or production URL omit if private] - **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 ## Template Details
- **Joomla Version**: [e.g., 5.x] - **Joomla Version**: [e.g., 5.x]
- **Template Name**: [e.g., clienttemplate] - **Template Name**: [e.g., clienttemplate]
- **MokoWaaS Plugin**: [Active / Inactive] - **MokoSuite Plugin**: [Active / Inactive]
- **MokoOnyx Admin**: [Active / Inactive] - **MokoOnyx Admin**: [Active / Inactive]
## CSS Custom Properties ## CSS Custom Properties
-26
View File
@@ -1,26 +0,0 @@
<?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.25.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>
+6 -5
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release # INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/auto-bump.yml # PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00 # VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits) # BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
@@ -22,7 +22,7 @@ on:
env: env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions: permissions:
contents: write contents: write
@@ -34,7 +34,8 @@ jobs:
if: >- if: >-
!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') && !contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request') !startsWith(github.event.head_commit.message, 'Merge pull request') &&
!startsWith(github.event.repository.name, 'Template-')
steps: steps:
- name: Checkout - name: Checkout
@@ -52,7 +53,7 @@ jobs:
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV" echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
else else
git clone --depth 1 --branch main --quiet \ git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \ "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/MokoCLI.git" \
/tmp/mokocli /tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV" echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
+136 -42
View File
@@ -3,16 +3,16 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release # INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /templates/workflows/universal/auto-release.yml.template # PATH: /.mokogitea/workflows/auto-release.yml
# VERSION: 05.00.00 # VERSION: 05.01.00
# BRIEF: Universal build & release detects platform from manifest.xml # BRIEF: Universal build & release detects platform from manifest.xml
# #
# +========================================================================+ # +=======================================================================+
# | UNIVERSAL BUILD & RELEASE PIPELINE | # | UNIVERSAL BUILD & RELEASE PIPELINE |
# +========================================================================+ # +=======================================================================+
# | | # | |
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. | # | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
# | | # | |
@@ -21,15 +21,24 @@
# | dolibarr: mod*.class.php, update.txt, dev version reset | # | dolibarr: mod*.class.php, update.txt, dev version reset |
# | generic: README-only, no update stream | # | generic: README-only, no update stream |
# | | # | |
# +========================================================================+ # +=======================================================================+
name: "Universal: Build & Release" name: "Universal: Build & Release"
on: on:
pull_request: pull_request:
types: [opened, closed] types: [opened, synchronize, closed]
branches: branches:
- main - main
paths-ignore:
- '.mokogitea/workflows/**'
- '*.md'
- 'wiki/**'
- '.editorconfig'
- '.gitignore'
- '.gitattributes'
- '.gitmessage'
- 'LICENSE'
workflow_dispatch: workflow_dispatch:
inputs: inputs:
action: action:
@@ -43,7 +52,7 @@ on:
env: env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }} GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }} GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
@@ -51,13 +60,18 @@ permissions:
contents: write contents: write
jobs: jobs:
# ── PR Opened → Rename branch to RC and build RC release ───────────────────── # ── PR Opened → Rename branch to RC and build RC release ─────────────────────────
promote-rc: promote-rc:
name: Promote to RC name: Promote to RC
runs-on: release runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >- if: >-
!startsWith(github.event.repository.name, 'Template-') &&
(
(github.event.action == 'opened' && github.event.pull_request.merged != true) || (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_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
)
steps: steps:
- name: Checkout repository - name: Checkout repository
@@ -65,6 +79,7 @@ jobs:
with: with:
token: ${{ secrets.MOKOGITEA_TOKEN }} token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1 fetch-depth: 1
submodules: recursive
- name: Setup mokocli tools - name: Setup mokocli tools
env: env:
@@ -80,7 +95,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 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 fi
rm -rf /tmp/mokocli 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 git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet composer install --no-dev --no-interaction --quiet
@@ -89,18 +104,46 @@ jobs:
- name: Rename branch to rc - name: Rename branch to rc
run: | run: |
php ${MOKO_CLI}/branch_rename.php \ API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \ AUTH="Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}"
--token "${{ secrets.MOKOGITEA_TOKEN }}" \ FROM="${{ github.event.pull_request.head.ref || 'dev' }}"
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \ PR="${{ github.event.pull_request.number }}"
--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"
- name: Checkout rc and configure git - name: Checkout rc and configure git
run: | run: |
git fetch origin rc git fetch origin rc
git checkout rc git checkout rc
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]" git config --local user.name "mokogitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git" git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
- name: Publish RC release - name: Publish RC release
@@ -111,7 +154,7 @@ jobs:
- name: Update RC release notes from CHANGELOG.md - name: Update RC release notes from CHANGELOG.md
run: | run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Extract [Unreleased] section from changelog # Extract [Unreleased] section from changelog
@@ -149,13 +192,17 @@ jobs:
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
echo "Branch renamed to rc, minor bump, RC release built" >> $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: release:
name: Build & Release Pipeline name: Build & Release Pipeline
runs-on: release runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >- if: >-
!startsWith(github.event.repository.name, 'Template-') &&
(
github.event.pull_request.merged == true || github.event.pull_request.merged == true ||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc') (github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
)
steps: steps:
- name: Checkout repository - name: Checkout repository
@@ -163,11 +210,12 @@ jobs:
with: with:
token: ${{ secrets.MOKOGITEA_TOKEN }} token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 0 fetch-depth: 0
submodules: recursive
- name: Configure git for bot pushes - name: Configure git for bot pushes
run: | run: |
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]" git config --local user.name "mokogitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git" git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
- name: Check for merge conflict markers - name: Check for merge conflict markers
@@ -198,13 +246,19 @@ 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 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 fi
rm -rf /tmp/mokocli 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 git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
fi 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" - name: "Determine version bump level"
id: bump id: bump
run: | run: |
@@ -228,9 +282,57 @@ jobs:
--path . --stability stable ${BUMP_FLAG} --branch main \ --path . --stability stable ${BUMP_FLAG} --branch main \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --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 - name: Update release notes and promote changelog
run: | run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Get the stable release info (version and ID) # Get the stable release info (version and ID)
@@ -280,7 +382,7 @@ jobs:
content = open('CHANGELOG.md').read() content = open('CHANGELOG.md').read()
old = '## [Unreleased]' old = '## [Unreleased]'
new = f'## [Unreleased]\n\n## [{version}] --- {date}' new = f'## [Unreleased]\n\n## [{version}] --- {date}'
content = content.replace(old, new, 1) content = content if ('## [' + version + ']') in content else content.replace(old, new, 1)
open('CHANGELOG.md', 'w').write(content) open('CHANGELOG.md', 'w').write(content)
" "$VERSION" "$DATE" " "$VERSION" "$DATE"
git add CHANGELOG.md git add CHANGELOG.md
@@ -299,7 +401,7 @@ jobs:
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}" VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}" RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}" GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_mirror.php \ php ${MOKO_CLI}/release_mirror.php \
--version "$VERSION" --tag "$RELEASE_TAG" \ --version "$VERSION" --tag "$RELEASE_TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \ --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
@@ -324,11 +426,11 @@ jobs:
&& echo "main branch pushed to GitHub mirror" \ && echo "main branch pushed to GitHub mirror" \
|| echo "WARNING: GitHub mirror push failed" || echo "WARNING: GitHub mirror push failed"
- name: "Step 11: Delete rc branch and recreate dev from main" - name: "Step 11: Delete rc branch (dev reset moved to cascade-dev.yml)"
if: steps.version.outputs.skip != 'true' if: steps.version.outputs.skip != 'true'
continue-on-error: true continue-on-error: true
run: | run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Delete rc branch (ephemeral — created by promote-rc) # Delete rc branch (ephemeral — created by promote-rc)
@@ -336,23 +438,15 @@ jobs:
"${API_BASE}/branches/rc" 2>/dev/null \ "${API_BASE}/branches/rc" 2>/dev/null \
&& echo "Deleted rc branch" || echo "rc branch not found" && echo "Deleted rc branch" || echo "rc branch not found"
# Delete dev branch # dev is reset from main by the dedicated "Cascade Main -> Dev" workflow
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \ # (cascade-dev.yml), which runs after this release completes.
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch" echo "rc cleaned; dev reset handled by cascade-dev.yml" >> $GITHUB_STEP_SUMMARY
# 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" - name: "Step 12: Create version branch from main"
if: steps.version.outputs.skip != 'true' if: steps.version.outputs.skip != 'true'
continue-on-error: true continue-on-error: true
run: | run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}" VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
BRANCH_NAME="version/${VERSION}" BRANCH_NAME="version/${VERSION}"
@@ -373,7 +467,7 @@ jobs:
if: steps.version.outputs.skip != 'true' if: steps.version.outputs.skip != 'true'
continue-on-error: true continue-on-error: true
run: | run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/version_reset_dev.php \ php ${MOKO_CLI}/version_reset_dev.php \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \ --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
--branch dev --path . 2>&1 || true --branch dev --path . 2>&1 || true
@@ -399,5 +493,5 @@ jobs:
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY echo "| 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 echo "| Release | [View](${MOKOGITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
fi fi
+4 -3
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Universal # INGROUP: MokoStandards.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/branch-cleanup.yml # PATH: /.mokogitea/workflows/branch-cleanup.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: Delete feature branches after PR merge # BRIEF: Delete feature branches after PR merge
@@ -33,7 +33,8 @@ jobs:
run: | run: |
BRANCH="${{ github.event.pull_request.head.ref }}" BRANCH="${{ github.event.pull_request.head.ref }}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches" API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');") # URL-encode the branch name's slashes (no PHP dependency on the runner)
ENCODED=$(printf '%s' "${BRANCH}" | sed 's|/|%2F|g')
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \ STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \ -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
+103 -7
View File
@@ -1,10 +1,106 @@
# DISABLED — auto-release Step 11 recreates dev from main after every release. # Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# Cascade-dev is redundant and causes version conflicts when both main and dev #
# have different version numbers in templateDetails.xml / manifest.xml. # SPDX-License-Identifier: GPL-3.0-or-later
name: "Cascade Main → Dev (DISABLED)" #
on: workflow_dispatch # 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' }}
jobs: jobs:
noop: cascade:
name: Cascade main -> dev
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- run: echo "Cascade disabled — auto-release handles dev recreation" - 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
+9 -3
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.CI # INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.gitea/workflows/ci-generic.yml # PATH: /.mokogitea/workflows/ci-generic.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js) # BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js)
@@ -32,6 +32,8 @@ jobs:
lint: lint:
name: Lint & Validate name: Lint & Validate
runs-on: ubuntu-latest runs-on: ubuntu-latest
# Skip on template repos (Template-*) — they hold placeholder scaffolding, not buildable source.
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps: steps:
- name: Checkout - name: Checkout
@@ -129,7 +131,11 @@ jobs:
test: test:
name: Tests name: Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: lint # 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-') }}
steps: steps:
- name: Checkout - name: Checkout
@@ -0,0 +1,68 @@
# 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 fi
php -v && composer --version php -v && composer --version
- name: Setup moko-platform tools - name: Setup mokocli tools
env: env:
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN || github.token }} MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.GA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }} MOKO_CLONE_HOST: ${{ secrets.MOKOGITEA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
run: | run: |
if [ -d "/tmp/moko-platform" ] || [ -d "/opt/moko-platform" ]; then if [ -d "/opt/mokocli" ] || [ -d "/tmp/mokocli" ]; then
echo "moko-platform already available on runner — skipping clone" echo "mokocli already available on runner — skipping clone"
else else
git clone --depth 1 --branch main --quiet \ git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \ "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git" \
/tmp/moko-platform 2>/dev/null || echo "moko-platform clone skipped — continuing without it" /tmp/mokocli 2>/dev/null || echo "mokocli clone skipped — continuing without it"
fi fi
- name: Install dependencies - name: Install dependencies
+13 -13
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Maintenance # INGROUP: MokoStandards.Maintenance
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards # REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/cleanup.yml # PATH: /.mokogitea/workflows/cleanup.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: Scheduled cleanup — delete merged branches and old workflow runs # BRIEF: Scheduled cleanup — delete merged branches and old workflow runs
@@ -21,7 +21,7 @@ permissions:
contents: write contents: write
env: env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs: jobs:
cleanup: cleanup:
@@ -33,30 +33,30 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
token: ${{ secrets.GA_TOKEN }} token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Delete merged branches - name: Delete merged branches
env: env:
GA_TOKEN: ${{ secrets.GA_TOKEN }} MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: | run: |
echo "=== Merged Branch Cleanup ===" echo "=== Merged Branch Cleanup ==="
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}" API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
# List branches via API # List branches via API
BRANCHES=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \ BRANCHES=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${API}/branches?limit=50" | jq -r '.[].name') "${API}/branches?limit=50" | jq -r '.[].name')
DELETED=0 DELETED=0
for BRANCH in $BRANCHES; do for BRANCH in $BRANCHES; do
# Skip protected branches # Skip protected branches
case "$BRANCH" in case "$BRANCH" in
main|master|develop|release/*|hotfix/*) continue ;; main|master|dev|develop|rc|beta|alpha|release|release/*|production|stable|staging|hotfix/*|version/*) continue ;;
esac esac
# Check if branch is merged into main # Check if branch is merged into main
if git merge-base --is-ancestor "origin/${BRANCH}" origin/main 2>/dev/null; then if git merge-base --is-ancestor "origin/${BRANCH}" origin/main 2>/dev/null; then
echo " Deleting merged branch: ${BRANCH}" echo " Deleting merged branch: ${BRANCH}"
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \ curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${API}/branches/${BRANCH}" 2>/dev/null || true "${API}/branches/${BRANCH}" 2>/dev/null || true
DELETED=$((DELETED + 1)) DELETED=$((DELETED + 1))
fi fi
@@ -66,20 +66,20 @@ jobs:
- name: Clean old workflow runs - name: Clean old workflow runs
env: env:
GA_TOKEN: ${{ secrets.GA_TOKEN }} MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: | run: |
echo "=== Workflow Run Cleanup ===" echo "=== Workflow Run Cleanup ==="
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}" API="${MOKOGITEA_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) 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 # Get old completed runs
RUNS=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \ RUNS=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${API}/actions/runs?status=completed&limit=50" | \ "${API}/actions/runs?status=completed&limit=50" | \
jq -r ".workflow_runs[] | select(.created_at < \"${CUTOFF}\") | .id" 2>/dev/null) jq -r ".workflow_runs[] | select(.created_at < \"${CUTOFF}\") | .id" 2>/dev/null)
DELETED=0 DELETED=0
for RUN_ID in $RUNS; do for RUN_ID in $RUNS; do
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \ curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true "${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
DELETED=$((DELETED + 1)) DELETED=$((DELETED + 1))
done done
+3 -7
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Security # INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API # REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
# PATH: /templates/workflows/gitleaks.yml.template # PATH: /.mokogitea/workflows/gitleaks.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens # BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
# #
@@ -25,10 +25,6 @@
name: "Universal: Secret Scanning" name: "Universal: Secret Scanning"
on: on:
pull_request:
branches:
- main
- 'dev/**'
schedule: schedule:
- cron: '0 5 * * 1' # Weekly Monday 05:00 UTC - cron: '0 5 * * 1' # Weekly Monday 05:00 UTC
workflow_dispatch: workflow_dispatch:
+7 -7
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: moko-platform.Automation # INGROUP: mokocli.Automation
# VERSION: 01.00.00 # VERSION: 02.28.09
# BRIEF: Auto-create feature branch when an issue is opened # BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch" name: "Universal: Issue Branch"
@@ -19,7 +19,7 @@ permissions:
issues: write issues: write
env: env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs: jobs:
create-branch: create-branch:
@@ -28,8 +28,8 @@ jobs:
steps: steps:
- name: Create branch and comment - name: Create branch and comment
run: | run: |
TOKEN="${{ secrets.GA_TOKEN }}" TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}" API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
ISSUE_NUM="${{ github.event.issue.number }}" ISSUE_NUM="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}" ISSUE_TITLE="${{ github.event.issue.title }}"
@@ -58,7 +58,7 @@ jobs:
echo "Created branch: ${BRANCH}" echo "Created branch: ${BRANCH}"
# Comment on issue with branch link # Comment on issue with branch link
REPO_URL="${GITEA_URL}/${{ github.repository }}" REPO_URL="${MOKOGITEA_URL}/${{ github.repository }}"
BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`" BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`"
curl -sf -X POST \ curl -sf -X POST \
+9 -9
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Notifications # INGROUP: MokoStandards.Notifications
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards # REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/notify.yml # PATH: /.mokogitea/workflows/notify.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: Push notifications via ntfy on release success or workflow failure # BRIEF: Push notifications via ntfy on release success or workflow failure
@@ -15,9 +15,9 @@ name: "Universal: Notifications"
on: on:
workflow_run: workflow_run:
workflows: workflows:
- "Joomla Build & Release" - "Universal: Build & Release"
- "Joomla Extension CI" - "Joomla: Extension CI"
- "Deploy" - "Generic: Project CI"
types: types:
- completed - completed
@@ -46,13 +46,13 @@ jobs:
WORKFLOW="${{ github.event.workflow_run.name }}" WORKFLOW="${{ github.event.workflow_run.name }}"
URL="${{ github.event.workflow_run.html_url }}" URL="${{ github.event.workflow_run.html_url }}"
curl -sS \ curl -sS --retry 3 --retry-connrefused --retry-delay 2 --max-time 20 \
-H "Title: ${REPO} released" \ -H "Title: ${REPO} released" \
-H "Tags: white_check_mark,package" \ -H "Tags: white_check_mark,package" \
-H "Priority: default" \ -H "Priority: default" \
-H "Click: ${URL}" \ -H "Click: ${URL}" \
-d "${WORKFLOW} completed successfully." \ -d "${WORKFLOW} completed successfully." \
"${NTFY_URL}/${NTFY_TOPIC}" "${NTFY_URL}/${NTFY_TOPIC}" || echo "::warning::ntfy notification could not be delivered (non-fatal)"
- name: Notify on failure - name: Notify on failure
if: github.event.workflow_run.conclusion == 'failure' if: github.event.workflow_run.conclusion == 'failure'
@@ -61,10 +61,10 @@ jobs:
WORKFLOW="${{ github.event.workflow_run.name }}" WORKFLOW="${{ github.event.workflow_run.name }}"
URL="${{ github.event.workflow_run.html_url }}" URL="${{ github.event.workflow_run.html_url }}"
curl -sS \ curl -sS --retry 3 --retry-connrefused --retry-delay 2 --max-time 20 \
-H "Title: ${REPO} workflow failed" \ -H "Title: ${REPO} workflow failed" \
-H "Tags: x,warning" \ -H "Tags: x,warning" \
-H "Priority: high" \ -H "Priority: high" \
-H "Click: ${URL}" \ -H "Click: ${URL}" \
-d "${WORKFLOW} failed. Check the run for details." \ -d "${WORKFLOW} failed. Check the run for details." \
"${NTFY_URL}/${NTFY_TOPIC}" "${NTFY_URL}/${NTFY_TOPIC}" || echo "::warning::ntfy notification could not be delivered (non-fatal)"
+133 -38
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.CI # INGROUP: mokocli.CI
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /templates/workflows/universal/pr-check.yml.template # PATH: /.mokogitea/workflows/pr-check.yml
# VERSION: 09.23.00 # VERSION: 09.23.00
# BRIEF: PR gate — branch policy + code validation before merge # BRIEF: PR gate — branch policy + code validation before merge
@@ -47,15 +47,15 @@ jobs:
fi fi
;; ;;
fix/*|bugfix/*) fix/*|bugfix/*)
if [ "$BASE" != "dev" ]; then if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
ALLOWED=false ALLOWED=false
REASON="Fix branches must target 'dev', not '${BASE}'" REASON="Fix branches must target 'dev' or 'main', not '${BASE}'"
fi fi
;; ;;
patch/*) patch/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ] && [ "$BASE" != "main" ]; then
ALLOWED=false ALLOWED=false
REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'" REASON="Patch branches must target 'dev', 'rc', or 'main', not '${BASE}'"
fi fi
;; ;;
hotfix/*) hotfix/*)
@@ -86,7 +86,8 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY echo "- \`fix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`patch/*\` → \`dev\`, \`rc\`, or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY
@@ -96,10 +97,112 @@ jobs:
echo "Branch policy: OK (${HEAD} → ${BASE})" echo "Branch policy: OK (${HEAD} → ${BASE})"
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
# ── Docs Update Gate (main PRs) ─────────────────────────────────────────
require-docs:
name: Require Docs Update
runs-on: ubuntu-latest
# Enforce only on PRs merging into main: README.md + CHANGELOG.md must both be updated.
if: ${{ github.base_ref == 'main' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Require README.md and CHANGELOG.md in the PR diff
run: |
BASE="${{ github.event.pull_request.base.sha }}"
HEAD="${{ github.event.pull_request.head.sha }}"
CHANGED="$(git diff --name-only "$BASE" "$HEAD" 2>/dev/null || true)"
if [ -z "$CHANGED" ]; then
git fetch -q origin "${{ github.base_ref }}" 2>/dev/null || true
CHANGED="$(git diff --name-only "origin/${{ github.base_ref }}...HEAD" 2>/dev/null || true)"
fi
echo "Changed files in PR:"
echo "$CHANGED"
MISSING=""
echo "$CHANGED" | grep -qxE 'README\.md' || MISSING="README.md"
echo "$CHANGED" | grep -qxE 'CHANGELOG\.md' || MISSING="${MISSING:+$MISSING, }CHANGELOG.md"
if [ -n "$MISSING" ]; then
echo "::error::PRs into main must update: ${MISSING}"
{
echo "## Docs Update Required"
echo ""
echo "PRs merging into \`main\` must update both **README.md** and **CHANGELOG.md**."
echo ""
echo "Not updated in this PR: **${MISSING}**"
} >> "$GITHUB_STEP_SUMMARY"
exit 1
fi
echo "Docs update present (README.md + CHANGELOG.md)"
echo "## Docs Update: Passed" >> "$GITHUB_STEP_SUMMARY"
# ── Wiki Update Reminder (main PRs, non-blocking) ───────────────────────
wiki-reminder:
name: Wiki Update Reminder
runs-on: ubuntu-latest
if: ${{ github.base_ref == 'main' }}
steps:
- name: Remind to update the wiki
env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
SERVER: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
REPO: ${{ github.repository }}
PR: ${{ github.event.pull_request.number }}
run: |
set -uo pipefail
{
echo "## Wiki Update Reminder"
echo ""
echo "Docs are **wiki-first** at MokoConsulting. If this change affects behavior, usage, configuration, or standards, update the repo wiki:"
echo ""
echo "- ${SERVER}/${REPO}/wiki"
echo ""
echo "_Non-blocking reminder._"
} >> "$GITHUB_STEP_SUMMARY"
# Post a single PR comment (idempotent via hidden marker); best-effort, never fails.
API="${SERVER}/api/v1/repos/${REPO}/issues/${PR}/comments"
if [ -n "${TOKEN:-}" ] && [ -n "${PR:-}" ]; then
existing="$(curl -sf -H "Authorization: token ${TOKEN}" "$API" 2>/dev/null | grep -c 'wiki-reminder' || true)"
if [ "${existing:-0}" -eq 0 ]; then
curl -sf -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" -X POST "$API" \
-d '{"body":"<!-- wiki-reminder -->\n\n**Wiki reminder:** docs are wiki-first -- if this PR changes behavior, usage, config, or standards, please update the repo wiki before/after merge. _(non-blocking)_"}' >/dev/null 2>&1 || true
fi
fi
echo "Wiki reminder emitted (non-blocking)."
# ── Secret Scanning ──────────────────────────────────────────────────
gitleaks:
name: Secret Scan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Gitleaks
run: |
GITLEAKS_VERSION="8.21.2"
curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz -C /usr/local/bin gitleaks
- name: Scan PR commits for secrets
run: |
if gitleaks detect --source . --verbose \
--log-opts=${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} 2>&1; then
echo "**No secrets detected.**" >> $GITHUB_STEP_SUMMARY
else
echo "::error::Potential secrets detected in PR commits"
exit 1
fi
# ── Code Validation ──────────────────────────────────────────────────── # ── Code Validation ────────────────────────────────────────────────────
validate: validate:
name: Validate PR name: Validate PR
runs-on: ubuntu-latest runs-on: ubuntu-latest
# Skip on template repos (Template-*) — no real manifest/source/changelog to validate.
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps: steps:
- name: Checkout - name: Checkout
@@ -107,7 +210,7 @@ jobs:
- name: Check for merge conflict markers - name: Check for merge conflict markers
run: | run: |
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true) CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --exclude-dir='.git' --exclude-dir='.mokogitea' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
if [ -n "$CONFLICTS" ]; then if [ -n "$CONFLICTS" ]; then
echo "::error::Merge conflict markers found in source files" echo "::error::Merge conflict markers found in source files"
echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY
@@ -121,11 +224,12 @@ jobs:
- name: Detect platform - name: Detect platform
id: platform id: platform
run: | run: |
# Read platform from XML manifest (<platform> tag) or plain text fallback # Platform comes from the MokoGitea metadata API (public GET); manifest.xml is no longer used.
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1) API="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${GITHUB_REPOSITORY}/metadata"
[ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]') PLATFORM="$(curl -sf "$API" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('platform') or '')" 2>/dev/null || true)"
[ -z "$PLATFORM" ] && PLATFORM="generic" [ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT" echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
echo "Detected platform: $PLATFORM"
- name: Setup PHP - name: Setup PHP
if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr' if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr'
@@ -154,8 +258,9 @@ jobs:
while IFS= read -r -d '' file; do while IFS= read -r -d '' file; do
# Skip vendor, node_modules, and index.html stub files # Skip vendor, node_modules, and index.html stub files
case "$file" in ./vendor/*|./node_modules/*) continue ;; esac case "$file" in ./vendor/*|./node_modules/*) continue ;; esac
# Check first 10 lines for JEXEC or JPATH guard # Scan the whole file for the JEXEC/JPATH guard: it is placed after
if ! head -20 "$file" | grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]"; then # the SPDX/file-header docblock, which commonly runs past 20 lines.
if ! grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]" "$file"; then
echo "::error file=${file}::Missing JEXEC guard: ${file}" echo "::error file=${file}::Missing JEXEC guard: ${file}"
ERRORS=$((ERRORS + 1)) ERRORS=$((ERRORS + 1))
fi fi
@@ -246,7 +351,7 @@ jobs:
joomla) joomla)
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1) MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
if [ -z "$MANIFEST" ]; then if [ -z "$MANIFEST" ]; then
echo "::warning::No Joomla manifest found (WaaS site)" echo "::warning::No Joomla manifest found (MokoSuite site)"
exit 0 exit 0
fi fi
echo "Manifest: ${MANIFEST}" echo "Manifest: ${MANIFEST}"
@@ -259,7 +364,7 @@ jobs:
# Block legacy raw/branch update server URLs on MokoGitea # Block legacy raw/branch update server URLs on MokoGitea
RAW_URLS=$(grep -n 'raw/branch' "$MANIFEST" | grep -i 'mokoconsulting\|mokogitea\|git\.mokoconsulting\.tech' || true) RAW_URLS=$(grep -n 'raw/branch' "$MANIFEST" | grep -i 'mokoconsulting\|mokogitea\|git\.mokoconsulting\.tech' || true)
if [ -n "$RAW_URLS" ]; then if [ -n "$RAW_URLS" ]; then
echo "::error::Manifest contains legacy raw/branch update server URL on MokoGitea. Use the Gitea Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)" echo "::error::Manifest contains legacy raw/branch update server URL on MokoGitea. Use the MokoGitea Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)"
echo "$RAW_URLS" echo "$RAW_URLS"
exit 1 exit 1
fi fi
@@ -466,43 +571,33 @@ jobs:
name: Build RC Package name: Build RC Package
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [branch-policy, validate] needs: [branch-policy, validate]
# Run only when both gates succeeded; always() forces evaluation so a skipped
# validate (e.g. template repos) skips this job cleanly instead of hanging.
if: ${{ always() && needs.branch-policy.result == 'success' && needs.validate.result == 'success' }}
steps: steps:
- name: Trigger RC pre-release - name: Trigger RC pre-release
env: env:
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }} REPO: ${{ github.repository }}
BRANCH: ${{ github.head_ref }} BRANCH: ${{ github.head_ref }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: | run: |
curl -s -X POST "${GITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}" curl -s -X POST "${MOKOGITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${MOKOGITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY
echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY
# ── Issue Reporter ────────────────────────────────────────────────────── # ── Issue Reporter ──────────────────────────────────────────────────────
report-issues: report-issues:
name: Report Issues name: Report Issues
runs-on: ubuntu-latest
needs: [branch-policy, validate] needs: [branch-policy, validate]
if: >- if: >-
always() && always() &&
needs.validate.result == 'failure' needs.validate.result == 'failure'
uses: ./.mokogitea/workflows/ci-issue-reporter.yml
steps:
- name: Checkout
uses: actions/checkout@v4
with: with:
sparse-checkout: automation/ci-issue-reporter.sh gate: "PR Validation"
sparse-checkout-cone-mode: false workflow: "PR Check"
severity: error
- name: "File issue for PR validation failure" details: "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed."
env: secrets: inherit
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x automation/ci-issue-reporter.sh
./automation/ci-issue-reporter.sh \
--gate "PR Validation" \
--workflow "PR Check" \
--severity error \
--details "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed."
+39 -8
View File
@@ -3,11 +3,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release # INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /templates/workflows/universal/pre-release.yml.template # PATH: /.mokogitea/workflows/pre-release.yml
# VERSION: 05.01.00 # VERSION: 05.02.01
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches # BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
name: "Universal: Pre-Release" name: "Universal: Pre-Release"
@@ -48,9 +48,13 @@ jobs:
build: build:
name: "Build Pre-Release (${{ inputs.stability || github.ref_name }})" name: "Build Pre-Release (${{ inputs.stability || github.ref_name }})"
runs-on: release runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >- if: >-
!startsWith(github.event.repository.name, 'Template-') &&
(
github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_dispatch' ||
github.event_name == 'push' github.event_name == 'push'
)
steps: steps:
- name: Checkout - name: Checkout
@@ -59,6 +63,11 @@ jobs:
fetch-depth: 0 fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }} token: ${{ secrets.MOKOGITEA_TOKEN }}
ref: ${{ github.ref_name }} 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 - name: Setup mokocli tools
env: env:
@@ -75,7 +84,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 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 fi
rm -rf /tmp/mokocli 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 git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
@@ -88,8 +97,20 @@ jobs:
php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
php ${MOKO_CLI}/manifest_read.php --path . --github-output 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 - name: Resolve metadata and bump version
id: meta id: meta
if: steps.eligibility.outputs.proceed == 'true'
run: | run: |
# Auto-detect stability from branch name on push, or use input on dispatch # Auto-detect stability from branch name on push, or use input on dispatch
if [ "${{ github.event_name }}" = "push" ]; then if [ "${{ github.event_name }}" = "push" ]; then
@@ -135,13 +156,19 @@ jobs:
fi fi
# Commit version bump # Commit version bump
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]" git config --local user.name "mokogitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git" git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
git add -A git add -A
git diff --cached --quiet || { git diff --cached --quiet || {
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]" git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
git push origin HEAD 2>&1 # 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
} }
# Auto-detect element via manifest_element.php # Auto-detect element via manifest_element.php
@@ -166,6 +193,7 @@ jobs:
- name: Create release - name: Create release
id: release id: release
if: steps.eligibility.outputs.proceed == 'true'
run: | run: |
TAG="${{ steps.meta.outputs.tag }}" TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}" VERSION="${{ steps.meta.outputs.version }}"
@@ -176,6 +204,7 @@ jobs:
--repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease --repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease
- name: Update release notes from CHANGELOG.md - name: Update release notes from CHANGELOG.md
if: steps.eligibility.outputs.proceed == 'true'
run: | run: |
TAG="${{ steps.meta.outputs.tag }}" TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}" VERSION="${{ steps.meta.outputs.version }}"
@@ -212,6 +241,7 @@ jobs:
- name: Build package and upload - name: Build package and upload
id: package id: package
if: steps.eligibility.outputs.proceed == 'true'
run: | run: |
VERSION="${{ steps.meta.outputs.version }}" VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}" TAG="${{ steps.meta.outputs.tag }}"
@@ -225,6 +255,7 @@ jobs:
# No need to build, commit, or sync updates.xml from workflows # No need to build, commit, or sync updates.xml from workflows
- name: "Delete lesser pre-release channels (cascade)" - name: "Delete lesser pre-release channels (cascade)"
if: steps.eligibility.outputs.proceed == 'true'
continue-on-error: true continue-on-error: true
run: | run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
+23 -17
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoPlatform.Universal # INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/rc-revert.yml # PATH: /.mokogitea/workflows/rc-revert.yml
# VERSION: 09.23.00 # VERSION: 09.23.00
# BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge # BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge
@@ -25,16 +25,25 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: >- if: >-
github.event.pull_request.merged == false && github.event.pull_request.merged == false &&
startsWith(github.event.pull_request.head.ref, 'rc/') startsWith(github.event.pull_request.head.ref, 'rc/') &&
!startsWith(github.event.repository.name, 'Template-')
steps: steps:
- name: Rename branch - 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: | run: |
BRANCH="${{ github.event.pull_request.head.ref }}" 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
SUFFIX="${BRANCH#rc/}" SUFFIX="${BRANCH#rc/}"
DEV_BRANCH="dev/${SUFFIX}" DEV_BRANCH="dev/${SUFFIX}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches" API="${GITEA_URL}/api/v1/repos/${REPO}/branches"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Create dev/ branch from rc/ branch # Create dev/ branch from rc/ branch
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \ STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \
@@ -42,25 +51,22 @@ jobs:
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "{\"new_branch_name\": \"${DEV_BRANCH}\", \"old_branch_name\": \"${BRANCH}\"}" \ -d "{\"new_branch_name\": \"${DEV_BRANCH}\", \"old_branch_name\": \"${BRANCH}\"}" \
"${API}" 2>/dev/null || true) "${API}" 2>/dev/null || true)
if [ "$STATUS" = "201" ]; then if [ "$STATUS" = "201" ]; then
echo "Created branch: ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY echo "Created branch: ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
else else
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})" echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"; exit 1
exit 1
fi fi
# Delete rc/ branch # Read BRANCH from the environment inside PHP (getenv, no string interpolation -> no PHP injection)
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');") ENCODED=$(php -r 'echo rawurlencode(getenv("BRANCH"));')
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \ STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${TOKEN}" \ -H "Authorization: token ${TOKEN}" \
"${API}/${ENCODED}" 2>/dev/null || true) "${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then if [ "$STATUS" = "204" ]; then
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY echo "Deleted branch: ${BRANCH}" >> "$GITHUB_STEP_SUMMARY"
else else
echo "::warning::Failed to delete ${BRANCH} (HTTP ${STATUS})" echo "::warning::Failed to delete ${BRANCH} (HTTP ${STATUS})"
fi fi
echo "### RC Reverted" >> $GITHUB_STEP_SUMMARY echo "### RC Reverted" >> "$GITHUB_STEP_SUMMARY"
echo "${BRANCH} → ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY echo "${BRANCH} → ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
+28 -40
View File
@@ -6,10 +6,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Validation # INGROUP: mokocli.Validation
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /templates/workflows/joomla/repo_health.yml.template # PATH: /.mokogitea/workflows/repo-health.yml
# VERSION: 09.23.00 # VERSION: 09.23.00
# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts. # BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts.
# ============================================================================ # ============================================================================
@@ -77,7 +77,7 @@ jobs:
- name: Check actor permission (admin only) - name: Check actor permission (admin only)
id: perm id: perm
env: env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }} TOKEN: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
REPO: ${{ github.repository }} REPO: ${{ github.repository }}
ACTOR: ${{ github.actor }} ACTOR: ${{ github.actor }}
run: | run: |
@@ -88,7 +88,7 @@ jobs:
# Hardcoded authorized users — always allowed # Hardcoded authorized users — always allowed
case "$ACTOR" in case "$ACTOR" in
jmiller|gitea-actions[bot]) jmiller|mokogitea-actions[bot])
ALLOWED=true ALLOWED=true
PERMISSION=admin PERMISSION=admin
METHOD="hardcoded allowlist" METHOD="hardcoded allowlist"
@@ -671,42 +671,30 @@ jobs:
# ═══════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════
# Issue Reporter — file issues for failed gates # Issue Reporter — file issues for failed gates
# ═══════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════
report-issues: report-scripts:
name: "Report Issues" name: "Report: Scripts Governance"
runs-on: ubuntu-latest needs: [access_check, scripts_governance]
needs: [access_check, scripts_governance, repo_health]
if: >- if: >-
always() && always() &&
(needs.scripts_governance.result == 'failure' || needs.scripts_governance.result == 'failure'
needs.repo_health.result == 'failure') uses: ./.mokogitea/workflows/ci-issue-reporter.yml
steps:
- name: Checkout
uses: actions/checkout@v4
with: with:
sparse-checkout: automation/ci-issue-reporter.sh gate: "Scripts Governance"
sparse-checkout-cone-mode: false workflow: "Repo Health"
severity: error
details: "Scripts directory policy violations detected. Review required and allowed directories."
secrets: inherit
- name: "File issues for failed gates" report-health:
env: name: "Report: Repository Health"
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} needs: [access_check, repo_health]
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} if: >-
run: | always() &&
chmod +x automation/ci-issue-reporter.sh needs.repo_health.result == 'failure'
REPORTER="./automation/ci-issue-reporter.sh" uses: ./.mokogitea/workflows/ci-issue-reporter.yml
WF="Repo Health" with:
gate: "Repository Health"
report_gate() { workflow: "Repo Health"
local gate="$1" result="$2" details="$3" severity: error
if [ "$result" = "failure" ]; then details: "Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary."
"$REPORTER" --gate "$gate" --details "$details" --workflow "$WF" --severity error secrets: inherit
fi
}
report_gate "Scripts Governance" \
"${{ needs.scripts_governance.result }}" \
"Scripts directory policy violations detected. Review required and allowed directories."
report_gate "Repository Health" \
"${{ needs.repo_health.result }}" \
"Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary."
-82
View File
@@ -1,82 +0,0 @@
# 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
@@ -0,0 +1,32 @@
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
@@ -0,0 +1,131 @@
# 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
+19 -10
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: Gitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoPlatform.Universal # INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/workflow-sync-trigger.yml # PATH: /.mokogitea/workflows/workflow-sync-trigger.yml
# VERSION: 01.01.00 # VERSION: 01.01.00
# BRIEF: Trigger workflow sync to live repos when a PR is merged to main # BRIEF: Trigger workflow sync to live repos when a PR is merged to main
@@ -13,6 +13,7 @@
name: "Universal: Workflow Sync Trigger" name: "Universal: Workflow Sync Trigger"
on: on:
workflow_dispatch:
pull_request: pull_request:
types: [closed] types: [closed]
branches: branches:
@@ -26,8 +27,10 @@ jobs:
name: Sync workflows to live repos name: Sync workflows to live repos
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: >- if: >-
github.event.pull_request.merged == true && startsWith(github.event.repository.name, 'Template-') &&
!contains(github.event.pull_request.title, '[skip sync]') (github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')))
steps: steps:
- name: Determine platform from repo name - name: Determine platform from repo name
@@ -45,16 +48,22 @@ jobs:
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT" echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
echo "Platform: ${PLATFORM:-all}" echo "Platform: ${PLATFORM:-all}"
- name: Clone mokoplatform - name: Clone mokocli
env: env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: | run: |
GITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}" MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${GITEA_URL}/MokoConsulting/mokoplatform.git" /tmp/mokoplatform 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
- name: Install dependencies - name: Install dependencies
run: | run: |
cd /tmp/mokoplatform cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet 2>/dev/null || true composer install --no-dev --no-interaction --quiet 2>/dev/null || true
- name: Run workflow sync - name: Run workflow sync
@@ -70,4 +79,4 @@ jobs:
ARGS="${ARGS} --platform-filter ${PLATFORM}" ARGS="${ARGS} --platform-filter ${PLATFORM}"
fi fi
php /tmp/mokoplatform/cli/workflow_sync.php ${ARGS} php /tmp/mokocli/cli/workflow_sync.php ${ARGS}
+13 -8
View File
@@ -8,22 +8,27 @@
DEFGROUP: Joomla.Template.Site DEFGROUP: Joomla.Template.Site
INGROUP: MokoOnyx.Documentation INGROUP: MokoOnyx.Documentation
PATH: ./CHANGELOG.md PATH: ./CHANGELOG.md
VERSION: 02.25.00 VERSION: 02.28.09
BRIEF: Changelog file documenting version history of MokoOnyx BRIEF: Changelog file documenting version history of MokoOnyx
--> -->
# Changelog — MokoOnyx (VERSION: 02.25.00) # Changelog — MokoOnyx (VERSION: 02.28.09)
## [Unreleased] ## [Unreleased]
## [02.25.00] --- 2026-06-20 ## [02.28.00] --- 2026-07-13
## [02.25.00] --- 2026-06-20 ## [02.27.06] --- 2026-06-29
## [02.24.00] --- 2026-06-20 ## [02.27.06] --- 2026-06-29
## [02.24.00] --- 2026-06-20 ## [02.27.00] --- 2026-06-21
## [02.23.02] --- 2026-06-20 ## [02.27.00] --- 2026-06-21
### 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)
## [02.23.02] --- 2026-06-20 ### Fixed
- Moved footer social icons below footer-menu and footer module positions for correct display order
+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: 7. **Merging to main** triggers the stable release pipeline:
- Minor version bump (e.g., `02.09.xx` → `02.10.00`) - Minor version bump (e.g., `02.09.xx` → `02.10.00`)
- Stability suffix stripped (clean version) - Stability suffix stripped (clean version)
- Gitea release created with ZIP/tar.gz packages - MokoGitea release created with ZIP/tar.gz packages
- `updates.xml` updated (Joomla extensions) - `updates.xml` updated (Joomla extensions)
- `dev` branch recreated from `main` - `dev` branch recreated from `main`
-213
View File
@@ -1,213 +0,0 @@
# 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
+12 -10
View File
@@ -12,12 +12,12 @@ A modern, lightweight Joomla site template built on Cassiopeia with Font Awesome
| | | | | |
|---|---| |---|---|
| **Type** | Joomla Site Template | | **Type** | Joomla Site Template |
| **Version** | 02.07.00 | | **Version** | 02.22.00 |
| **Joomla** | 5.x / 6.x | | **Joomla** | 6.x+ |
| **PHP** | 8.1+ | | **PHP** | 8.3+ |
| **License** | GPL-3.0-or-later | | **License** | GPL-3.0-or-later |
| **Replaces** | MokoCassiopeia (auto-migrates on install) | | **Replaces** | MokoCassiopeia (auto-migrates on install) |
| **Repository** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) (primary) | | **Repository** | [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) (primary) |
--- ---
@@ -39,6 +39,7 @@ On install, MokoOnyx automatically migrates settings, content references, and cu
| **Table of Contents** | Automatic TOC generation for long articles | | **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) | | **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 | | **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 | | **Cassiopeia Base** | Minimal core overrides for maximum Joomla upgrade compatibility |
--- ---
@@ -52,8 +53,8 @@ On install, MokoOnyx automatically migrates settings, content references, and cu
### Requirements ### Requirements
- Joomla 5.x or 6.x - Joomla 6.x or higher
- PHP 8.1 or higher - PHP 8.3 or higher
--- ---
@@ -79,6 +80,7 @@ Key parameters include:
- **Google Tag Manager**: GTM container ID - **Google Tag Manager**: GTM container ID
- **GA4**: Measurement ID and tracking options - **GA4**: Measurement ID and tracking options
- **Table of Contents**: Auto-generate TOC for articles with heading threshold - **Table of Contents**: Auto-generate TOC for articles with heading threshold
- **Social Icons**: Display positions, icon style, and platform URLs
--- ---
@@ -86,14 +88,14 @@ Key parameters include:
| Repo | Purpose | | Repo | Purpose |
|------|---------| |------|---------|
| [Template-Client-WaaS](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-WaaS/wiki) | Client site template (extends MokoOnyx) | | [Template-Client-MokoSuite](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-MokoSuite/wiki) | Client site template (extends MokoOnyx) |
| [MokoWaaS](https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/wiki) | WaaS system plugin | | [MokoSuite](https://git.mokoconsulting.tech/MokoConsulting/MokoSuite/wiki) | MokoSuite system plugin |
| [joomla-api-mcp](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki) | Joomla Web Services API MCP | | [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 | | [deploy-mcp](https://git.mokoconsulting.tech/MokoConsulting/deploy-mcp/wiki) | Git-based deployment MCP |
--- ---
> **[MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki)** -- central standards hub for all Moko Consulting projects. > **[MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)** -- central standards hub for all Moko Consulting projects.
--- ---
@@ -115,4 +117,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/moko-platform/wiki/Home)* *[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)*
+1 -1
View File
@@ -10,7 +10,7 @@
INGROUP: MokoOnyx.Governance INGROUP: MokoOnyx.Governance
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
FILE: SECURITY.md FILE: SECURITY.md
VERSION: 02.25.00 VERSION: 02.28.09
BRIEF: Security policy and vulnerability reporting process for MokoOnyx. BRIEF: Security policy and vulnerability reporting process for MokoOnyx.
PATH: /SECURITY.md PATH: /SECURITY.md
NOTE: This policy is process oriented and does not replace secure engineering practices. NOTE: This policy is process oriented and does not replace secure engineering practices.
+1 -1
View File
@@ -11,7 +11,7 @@
], ],
"require": { "require": {
"ext-zip": "*", "ext-zip": "*",
"php": ">=8.1" "php": ">=8.3"
}, },
"require-dev": { "require-dev": {
"mokoconsulting-tech/enterprise": "^4.0" "mokoconsulting-tech/enterprise": "^4.0"
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: MokoOnyx * INGROUP: MokoOnyx
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: /html/layouts/joomla/module/card.php * PATH: /html/layouts/joomla/module/card.php
* VERSION: 02.25.00 * VERSION: 02.28.09
* BRIEF: Custom card module chrome — renders module titles for all modules * BRIEF: Custom card module chrome — renders module titles for all modules
*/ */
@@ -11,7 +11,7 @@
* INGROUP: MokoOnyx.Layouts * INGROUP: MokoOnyx.Layouts
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: /src/html/layouts/mokoonyx/article-metadata.php * PATH: /src/html/layouts/mokoonyx/article-metadata.php
* VERSION: 02.25.00 * VERSION: 02.28.09
* BRIEF: Article metadata footer layout -- renders jcfields grouped by field group * BRIEF: Article metadata footer layout -- renders jcfields grouped by field group
*/ */
+38 -3
View File
@@ -52,14 +52,23 @@ $platforms = [
$active = []; $active = [];
foreach ($platforms as $key => [$iconClass, $langKey]) { foreach ($platforms as $key => [$iconClass, $langKey]) {
$url = trim((string) $params->get('social_' . $key . '_url', '')); $url = trim((string) $params->get('social_' . $key . '_url', ''));
if ($url !== '' && preg_match('#^(https?://|mailto:|/)#i', $url)) { if ($url === '') {
continue;
}
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[] = [ $active[] = [
'url' => $url, 'url' => $url,
'iconClass' => $iconClass, 'iconClass' => $iconClass,
'label' => Text::_($langKey), 'label' => Text::_($langKey),
]; ];
} }
}
if (empty($active)) { if (empty($active)) {
return; return;
@@ -75,6 +84,10 @@ $floatingPos = in_array($params->get('social_floating_pos'), ['left', 'right'],
$colorMode = in_array($params->get('social_icon_color'), ['theme', 'brand', 'black', 'white'], true) $colorMode = in_array($params->get('social_icon_color'), ['theme', 'brand', 'black', 'white'], true)
? $params->get('social_icon_color') : 'theme'; ? $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';
$listClass .= ' moko-social-icons--' . htmlspecialchars($style, ENT_QUOTES, 'UTF-8'); $listClass .= ' moko-social-icons--' . htmlspecialchars($style, ENT_QUOTES, 'UTF-8');
$listClass .= ' moko-social-icons--' . htmlspecialchars($size, ENT_QUOTES, 'UTF-8'); $listClass .= ' moko-social-icons--' . htmlspecialchars($size, ENT_QUOTES, 'UTF-8');
@@ -84,6 +97,12 @@ if ($position === 'floating') {
$listClass .= ' moko-social-icons--floating-' . $floatingPos; $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'); ?>"> <nav class="<?php echo $listClass; ?>" aria-label="<?php echo Text::_('TPL_MOKOONYX_SOCIAL_NAV_LABEL'); ?>">
<ul> <ul>
<?php foreach ($active as $item) : ?> <?php foreach ($active as $item) : ?>
@@ -91,10 +110,26 @@ if ($position === 'floating') {
<a href="<?php echo htmlspecialchars($item['url'], ENT_QUOTES, 'UTF-8'); ?>" <a href="<?php echo htmlspecialchars($item['url'], ENT_QUOTES, 'UTF-8'); ?>"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
aria-label="<?php echo htmlspecialchars($item['label'], ENT_QUOTES, 'UTF-8'); ?>"> 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'); ?>">
<span class="<?php echo htmlspecialchars($item['iconClass'], ENT_QUOTES, 'UTF-8'); ?>" aria-hidden="true"></span> <span class="<?php echo htmlspecialchars($item['iconClass'], ENT_QUOTES, 'UTF-8'); ?>" aria-hidden="true"></span>
</a> </a>
</li> </li>
<?php endforeach; ?> <?php endforeach; ?>
</ul> </ul>
</nav> </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; ?>
+6 -1
View File
@@ -286,6 +286,11 @@ 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_DESC="Which side of the screen the floating social bar appears on."
TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT="Left" TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT="Left"
TPL_MOKOONYX_SOCIAL_FLOATING_POS_RIGHT="Right" 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_LABEL="Icon Colour"
TPL_MOKOONYX_SOCIAL_COLOR_DESC="Choose the colour scheme for social icons." TPL_MOKOONYX_SOCIAL_COLOR_DESC="Choose the colour scheme for social icons."
TPL_MOKOONYX_SOCIAL_COLOR_THEME="Theme (CSS variables)" TPL_MOKOONYX_SOCIAL_COLOR_THEME="Theme (CSS variables)"
@@ -321,7 +326,7 @@ TPL_MOKOONYX_SOCIAL_MAIL="Email us"
; ===== CSS Variables tab (social) ===== ; ===== CSS Variables tab (social) =====
TPL_MOKOONYX_CSS_VARS_SOCIAL_LABEL="Social Icons" 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>)" 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."
; ===== Misc ===== ; ===== Misc =====
MOD_BREADCRUMBS_HERE="YOU ARE HERE:" MOD_BREADCRUMBS_HERE="YOU ARE HERE:"
+6 -1
View File
@@ -286,6 +286,11 @@ 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_DESC="Which side of the screen the floating social bar appears on."
TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT="Left" TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT="Left"
TPL_MOKOONYX_SOCIAL_FLOATING_POS_RIGHT="Right" 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_LABEL="Icon Color"
TPL_MOKOONYX_SOCIAL_COLOR_DESC="Choose the color scheme for social icons." TPL_MOKOONYX_SOCIAL_COLOR_DESC="Choose the color scheme for social icons."
TPL_MOKOONYX_SOCIAL_COLOR_THEME="Theme (CSS variables)" TPL_MOKOONYX_SOCIAL_COLOR_THEME="Theme (CSS variables)"
@@ -321,7 +326,7 @@ TPL_MOKOONYX_SOCIAL_MAIL="Email us"
; ===== CSS Variables tab (social) ===== ; ===== CSS Variables tab (social) =====
TPL_MOKOONYX_CSS_VARS_SOCIAL_LABEL="Social Icons" 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>)" 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."
; ===== Misc ===== ; ===== Misc =====
MOD_BREADCRUMBS_HERE="YOU ARE HERE:" MOD_BREADCRUMBS_HERE="YOU ARE HERE:"
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: MokoOnyx.Accessibility * INGROUP: MokoOnyx.Accessibility
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
* PATH: ./media/css/a11y-high-contrast.css * PATH: ./media/css/a11y-high-contrast.css
* VERSION: 02.25.00 * VERSION: 02.28.09
* BRIEF: High-contrast stylesheet for accessibility toolbar * BRIEF: High-contrast stylesheet for accessibility toolbar
*/ */
+67 -51
View File
@@ -8046,46 +8046,6 @@ fieldset:disabled .btn {
content: ""; 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 { .link-primary {
color: var(--link-primary-color, hsl(240, 98%, 50%)); color: var(--link-primary-color, hsl(240, 98%, 50%));
@@ -23522,7 +23482,7 @@ font-size: 0.8125rem;
.blog-item .item-image img { .blog-item .item-image img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: none;
} }
.fa-brands { .fa-brands {
@@ -23679,26 +23639,42 @@ font-size: 0.8125rem;
} }
/* Position: floating — fixed sidebar, hidden on mobile */ /* Position: floating — fixed sidebar, hidden on mobile */
.moko-social-icons--floating { .moko-social-floating-wrap {
position: fixed; position: fixed;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
z-index: 1030; z-index: 1030;
display: flex; 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 { .moko-social-icons--floating ul {
flex-direction: column; flex-direction: column;
} }
.moko-social-icons--floating-left {
left: 0;
}
.moko-social-icons--floating-right {
right: 0;
}
.moko-social-icons--floating-left a { .moko-social-icons--floating-left a {
border-radius: 0 var(--social-icon-radius, 0.375rem) var(--social-icon-radius, 0.375rem) 0; border-radius: 0 var(--social-icon-radius, 0.375rem) var(--social-icon-radius, 0.375rem) 0;
} }
@@ -23712,8 +23688,48 @@ font-size: 0.8125rem;
border-radius: inherit; 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) { @media (max-width: 991.98px) {
.moko-social-icons--floating { .moko-social-floating-wrap {
display: none; display: none;
} }
} }
+49
View File
@@ -789,6 +789,53 @@
}); });
} }
// ========================================================================
// 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 * Run all template JS initializations
*/ */
@@ -815,6 +862,8 @@
initBackTop(); initBackTop();
initSearchToggle(); initSearchToggle();
initSidebarAccordion(); initSidebarAccordion();
initSocialFloating();
initSocialTooltips();
initVarCopy(); initVarCopy();
} }
+37 -23
View File
@@ -35,7 +35,7 @@
</updateservers> </updateservers>
<dlid prefix="dlid=" suffix=""/> <dlid prefix="dlid=" suffix=""/>
<name>mokoonyx</name> <name>mokoonyx</name>
<version>02.25.00</version> <version>02.28.09</version>
<scriptfile>script.php</scriptfile> <scriptfile>script.php</scriptfile>
<creationDate>2026-05-16</creationDate> <creationDate>2026-05-16</creationDate>
<author>Jonathan Miller || Moko Consulting</author> <author>Jonathan Miller || Moko Consulting</author>
@@ -354,6 +354,20 @@
<option value="left">TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT</option> <option value="left">TPL_MOKOONYX_SOCIAL_FLOATING_POS_LEFT</option>
<option value="right">TPL_MOKOONYX_SOCIAL_FLOATING_POS_RIGHT</option> <option value="right">TPL_MOKOONYX_SOCIAL_FLOATING_POS_RIGHT</option>
</field> </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 --> <!-- Style options -->
<field name="social_sep_style" type="spacer" label="Style" hr="false" class="text fw-bold" <field name="social_sep_style" type="spacer" label="Style" hr="false" class="text fw-bold"
@@ -387,28 +401,28 @@
showon="social_topbar:1[OR]social_footer:1[OR]social_floating:1" /> 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" <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" /> showon="social_topbar:1[OR]social_footer:1[OR]social_floating:1" />
<field name="social_facebook_url" type="url" default="" label="Facebook" filter="url" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <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" /> <field name="social_linktree_url" type="url" default="" label="Linktree" filter="url" validate="url" />
<field name="social_mail_url" type="url" default="" label="Email" description="TPL_MOKOONYX_SOCIAL_MAIL_DESC" filter="string" /> <field name="social_mail_url" type="url" default="" label="Email" description="TPL_MOKOONYX_SOCIAL_MAIL_DESC" filter="string" />
</fieldset> </fieldset>
+2 -2
View File
@@ -136,11 +136,11 @@ A read-only reference tab displaying all available CSS custom properties organiz
--- ---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting* *Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | Revision | Date | Author | Description |
|---|---|---|---| |---|---|---|---|
+2 -2
View File
@@ -223,11 +223,11 @@ Additional variables are defined for: VirtueMart (`--vm-*`), Gable (`--gab-*`),
--- ---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting* *Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | 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 [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting* *Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | Revision | Date | Author | Description |
|---|---|---|---| |---|---|---|---|
+8 -8
View File
@@ -46,7 +46,7 @@ MokoOnyx/
│ ├── dark.custom.css # Custom dark palette template │ ├── dark.custom.css # Custom dark palette template
│ └── brand-showcase.html # Brand showcase HTML template │ └── brand-showcase.html # Brand showcase HTML template
├── Makefile # Build and validation automation ├── Makefile # Build and validation automation
├── composer.json # PHP dependencies (moko-platform) ├── composer.json # PHP dependencies (mokocli)
├── package.json # Node.js dependencies (minification) ├── package.json # Node.js dependencies (minification)
├── phpcs.xml # PHP CodeSniffer configuration ├── phpcs.xml # PHP CodeSniffer configuration
├── phpstan.neon # PHPStan static analysis configuration ├── phpstan.neon # PHPStan static analysis configuration
@@ -63,7 +63,7 @@ MokoOnyx/
## Prerequisites ## Prerequisites
- **PHP** 8.1+ - **PHP** 8.1+
- **Composer** (for moko-platform CLI and dependencies) - **Composer** (for mokocli CLI and dependencies)
- **Node.js** (optional, for build-time minification with terser/clean-css) - **Node.js** (optional, for build-time minification with terser/clean-css)
- **Make** (GNU Make or compatible) - **Make** (GNU Make or compatible)
- **zip** (or PowerShell for Windows) - **zip** (or PowerShell for Windows)
@@ -110,7 +110,7 @@ Creates `dist/mokoonyx-{version}-beta.zip` (skips minification).
## Validation ## Validation
MokoOnyx uses the **moko-platform CLI** for code quality checks. MokoOnyx uses the **mokocli CLI** for code quality checks.
```bash ```bash
# Run all validation checks # Run all validation checks
@@ -144,7 +144,7 @@ After the release package is built:
1. Tag the release: `git tag {version}` 1. Tag the release: `git tag {version}`
2. Push tags: `git push origin --tags` 2. Push tags: `git push origin --tags`
3. Create a Gitea release and attach the ZIP from `dist/` 3. Create a MokoGitea release and attach the ZIP from `dist/`
### Generate checksums ### Generate checksums
@@ -185,7 +185,7 @@ Creates SHA-256 checksums for all ZIP files in `dist/`.
## Contributing ## Contributing
1. Fork the repository on [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) 1. Fork the repository on [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx)
2. Create a feature branch from `dev` 2. Create a feature branch from `dev`
3. Make your changes in `src/` 3. Make your changes in `src/`
4. Run `make validate` to ensure all checks pass 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`) 1. The minor version is bumped (e.g., `02.08.xx` -> `02.09.00`)
2. Stability suffixes are stripped (stable release) 2. Stability suffixes are stripped (stable release)
3. A Gitea release is created with the build package (ZIP + tar.gz + SHA-256) 3. A MokoGitea release is created with the build package (ZIP + tar.gz + SHA-256)
4. `updates.xml` is updated for the Joomla update server 4. `updates.xml` is updated for the Joomla update server
5. The `dev` branch is recreated from `main` 5. The `dev` branch is recreated from `main`
6. A `version/XX.YY.ZZ` archive branch is created 6. A `version/XX.YY.ZZ` archive branch is created
@@ -277,11 +277,11 @@ vendor/bin/codecept run
--- ---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting* *Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | Revision | Date | Author | Description |
|---|---|---|---| |---|---|---|---|
+185
View File
@@ -0,0 +1,185 @@
[← 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
@@ -0,0 +1,125 @@
[← 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
@@ -0,0 +1,66 @@
[← 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
@@ -0,0 +1,119 @@
[← 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
@@ -0,0 +1,113 @@
[← 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+ | | **PHP** | 8.1+ |
| **License** | GPL-3.0-or-later | | **License** | GPL-3.0-or-later |
| **Replaces** | MokoCassiopeia (auto-migrates on install) | | **Replaces** | MokoCassiopeia (auto-migrates on install) |
| **Platform** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) (primary) | | **Platform** | [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) (primary) |
--- ---
@@ -81,18 +81,18 @@ Key parameters include:
| Repo | Purpose | | Repo | Purpose |
|------|---------| |------|---------|
| [Template-Client-WaaS](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-WaaS/wiki) | Client site template (extends MokoOnyx) | | [Template-Client-MokoSuite](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-MokoSuite/wiki) | Client site template (extends MokoOnyx) |
| [MokoWaaS](https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/wiki) | WaaS system plugin | | [MokoSuite](https://git.mokoconsulting.tech/MokoConsulting/MokoSuite/wiki) | MokoSuite system plugin |
| [joomla-api-mcp](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki) | Joomla Web Services API MCP | | [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 | | [deploy-mcp](https://git.mokoconsulting.tech/MokoConsulting/deploy-mcp/wiki) | Git-based deployment MCP |
--- ---
> **[moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki)** -- central standards hub for all Moko Consulting projects. > **[mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki)** -- central standards hub for all Moko Consulting projects.
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | 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 | | Priority | Server |
|----------|--------| |----------|--------|
| 1 | Gitea (git.mokoconsulting.tech) | | 1 | MokoGitea (git.mokoconsulting.tech) |
| 2 | GitHub (github.com) | | 2 | GitHub (github.com) |
--- ---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting* *Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | Revision | Date | Author | Description |
|---|---|---|---| |---|---|---|---|
+2 -2
View File
@@ -108,11 +108,11 @@ Once you have confirmed everything is working:
--- ---
*Built with [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting* *Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | Revision | Date | Author | Description |
|---|---|---|---| |---|---|---|---|
+3 -3
View File
@@ -84,7 +84,7 @@ The JS minifier performs these transformations:
| Context | What Happens | | 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). | | **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. | | **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. |
| **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. | | **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 [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting* *Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | Revision | Date | Author | Description |
|---|---|---|---| |---|---|---|---|
+61
View File
@@ -0,0 +1,61 @@
## 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
@@ -0,0 +1,92 @@
## 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
@@ -0,0 +1,249 @@
[← 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
@@ -0,0 +1,289 @@
[← 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
@@ -0,0 +1,78 @@
## 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
@@ -0,0 +1,23 @@
# 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
@@ -0,0 +1,123 @@
[← 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 [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform) -- Moko Consulting* *Built with [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli) -- Moko Consulting*
--- ---
*Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Revision | Date | Author | Description | | 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) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)* *Repo: [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx) · [mokocli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)*
| Field | Value | | Field | Value |
|---|---| |---|---|
+1 -1
View File
@@ -70,7 +70,7 @@ Commit messages should:
## Reporting Issues ## Reporting Issues
Bug reports and enhancement requests should be filed as Gitea issues and include: Bug reports and enhancement requests should be filed as MokoGitea issues and include:
* Clear reproduction steps or use cases * Clear reproduction steps or use cases
* Expected versus actual behavior * Expected versus actual behavior