Merge branch 'dev' into version/03
This commit is contained in:
376
.github/CLAUDE.md
vendored
376
.github/CLAUDE.md
vendored
@@ -1,3 +1,22 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
|
||||||
|
This file is part of a Moko Consulting project.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
# FILE INFORMATION
|
||||||
|
DEFGROUP: MokoStandards.Templates.GitHub
|
||||||
|
INGROUP: MokoStandards.Templates
|
||||||
|
REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||||
|
PATH: /templates/github/copilot-instructions.joomla.md.template
|
||||||
|
VERSION: XX.YY.ZZ
|
||||||
|
BRIEF: GitHub Copilot custom instructions template for Joomla/MokoWaaS governed repositories
|
||||||
|
NOTE: Synced to .github/copilot-instructions.md in all Joomla/WaaS repos via bulk sync.
|
||||||
|
Tokens replaced at sync time: MokoCassiopeia, https://github.com/mokoconsulting-tech/MokoCassiopeia, {{EXTENSION_NAME}},
|
||||||
|
{{EXTENSION_TYPE}}, {{EXTENSION_ELEMENT}}
|
||||||
|
-->
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> **🔧 AI Self-Update Required on First Use**
|
> **🔧 AI Self-Update Required on First Use**
|
||||||
>
|
>
|
||||||
@@ -19,135 +38,34 @@
|
|||||||
> |---|---|
|
> |---|---|
|
||||||
> | `MokoCassiopeia` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) |
|
> | `MokoCassiopeia` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) |
|
||||||
> | `https://github.com/mokoconsulting-tech/MokoCassiopeia` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/<repo-name>` |
|
> | `https://github.com/mokoconsulting-tech/MokoCassiopeia` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/<repo-name>` |
|
||||||
> | `A modern enhancement layer for Joomla’s Cassiopeia template. Moko-Cassiopeia adds Font Awesome 7, Bootstrap 5 helpers, an automatic Table of Contents (TOC) utility, and optional expansions including Google Tag Manager and Google Analytics (GA4) hooks.` | First paragraph of `README.md` body, or the GitHub repo description |
|
|
||||||
> | `{{EXTENSION_NAME}}` | The `<name>` element in `manifest.xml` at the repository root |
|
> | `{{EXTENSION_NAME}}` | The `<name>` element in `manifest.xml` at the repository root |
|
||||||
> | `{{EXTENSION_TYPE}}` | The `type` attribute of the `<extension>` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) |
|
> | `{{EXTENSION_TYPE}}` | The `type` attribute of the `<extension>` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) |
|
||||||
> | `{{EXTENSION_ELEMENT}}` | The `<element>` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) |
|
> | `{{EXTENSION_ELEMENT}}` | The `<element>` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) |
|
||||||
>
|
>
|
||||||
> ---
|
> ---
|
||||||
|
|
||||||
# What This Repo Is
|
# MokoCassiopeia — GitHub Copilot Custom Instructions
|
||||||
|
|
||||||
**MokoCassiopeia** is a Moko Consulting **MokoWaaS** (Joomla) extension repository.
|
## What This Repo Is
|
||||||
|
|
||||||
A modern enhancement layer for Joomla’s Cassiopeia template. Moko-Cassiopeia adds Font Awesome 7, Bootstrap 5 helpers, an automatic Table of Contents (TOC) utility, and optional expansions including Google Tag Manager and Google Analytics (GA4) hooks.
|
This is a **Moko Consulting MokoWaaS** (Joomla) repository governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). All coding standards, workflows, and policies are defined there and enforced here via bulk sync.
|
||||||
|
|
||||||
|
Repository URL: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||||
Extension name: **{{EXTENSION_NAME}}**
|
Extension name: **{{EXTENSION_NAME}}**
|
||||||
Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`)
|
Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`)
|
||||||
Repository URL: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
Platform: **Joomla 4.x / MokoWaaS**
|
||||||
|
|
||||||
This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Repo Structure
|
## Primary Language
|
||||||
|
|
||||||
```
|
**PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`.
|
||||||
MokoCassiopeia/
|
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
|
||||||
├── update.xml # Update server manifest (root — required)
|
|
||||||
├── site/ # Frontend (site) code
|
|
||||||
│ ├── controller.php
|
|
||||||
│ ├── controllers/
|
|
||||||
│ ├── models/
|
|
||||||
│ └── views/
|
|
||||||
├── admin/ # Backend (admin) code
|
|
||||||
│ ├── controller.php
|
|
||||||
│ ├── controllers/
|
|
||||||
│ ├── models/
|
|
||||||
│ ├── views/
|
|
||||||
│ └── sql/
|
|
||||||
├── language/ # Language INI files
|
|
||||||
├── media/ # CSS, JS, images
|
|
||||||
├── docs/ # Technical documentation
|
|
||||||
├── tests/ # Test suite
|
|
||||||
├── .github/
|
|
||||||
│ ├── workflows/ # CI/CD workflows (synced from MokoStandards)
|
|
||||||
│ ├── copilot-instructions.md
|
|
||||||
│ └── CLAUDE.md # This file
|
|
||||||
├── README.md # Version source of truth
|
|
||||||
├── CHANGELOG.md
|
|
||||||
├── CONTRIBUTING.md
|
|
||||||
└── LICENSE # GPL-3.0-or-later
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Primary Language
|
## File Header — Always Required on New Files
|
||||||
|
|
||||||
**PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`.
|
Every new file needs a copyright header as its first content.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Version Management
|
|
||||||
|
|
||||||
**`README.md` is the single source of truth for the repository version.**
|
|
||||||
|
|
||||||
- **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it to all `FILE INFORMATION` headers automatically on merge.
|
|
||||||
- Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`).
|
|
||||||
- Never hardcode a version number in body text — use the badge or FILE INFORMATION header only.
|
|
||||||
|
|
||||||
### Joomla Version Alignment
|
|
||||||
|
|
||||||
Three files must **always have the same version**:
|
|
||||||
|
|
||||||
| File | Where the version lives |
|
|
||||||
|------|------------------------|
|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
|
||||||
| `manifest.xml` | `<version>` tag |
|
|
||||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
|
||||||
|
|
||||||
The `make release` command / release workflow syncs all three automatically.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# update.xml — Required in Repo Root
|
|
||||||
|
|
||||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<!-- In manifest.xml -->
|
|
||||||
<updateservers>
|
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
|
||||||
https://github.com/mokoconsulting-tech/MokoCassiopeia/raw/main/update.xml
|
|
||||||
</server>
|
|
||||||
</updateservers>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Rules:**
|
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
|
||||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
|
||||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
|
||||||
|
|
||||||
Example `update.xml` entry for a new release:
|
|
||||||
```xml
|
|
||||||
<updates>
|
|
||||||
<update>
|
|
||||||
<name>{{EXTENSION_NAME}}</name>
|
|
||||||
<description>MokoCassiopeia</description>
|
|
||||||
<element>{{EXTENSION_ELEMENT}}</element>
|
|
||||||
<type>{{EXTENSION_TYPE}}</type>
|
|
||||||
<version>01.02.04</version>
|
|
||||||
<infourl title="Release Information">https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/tag/01.02.04</infourl>
|
|
||||||
<downloads>
|
|
||||||
<downloadurl type="full" format="zip">
|
|
||||||
https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip
|
|
||||||
</downloadurl>
|
|
||||||
</downloads>
|
|
||||||
<targetplatform name="joomla" version="4\.[0-9]+" />
|
|
||||||
<php_minimum>7.4</php_minimum>
|
|
||||||
<maintainer>Moko Consulting</maintainer>
|
|
||||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
|
||||||
</update>
|
|
||||||
</updates>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# File Header Requirements
|
|
||||||
|
|
||||||
Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt.
|
|
||||||
|
|
||||||
**PHP:**
|
**PHP:**
|
||||||
```php
|
```php
|
||||||
@@ -162,47 +80,141 @@ Every new file **must** have a copyright header as its first content. JSON files
|
|||||||
* DEFGROUP: MokoCassiopeia.{{EXTENSION_TYPE}}
|
* DEFGROUP: MokoCassiopeia.{{EXTENSION_TYPE}}
|
||||||
* INGROUP: MokoCassiopeia
|
* INGROUP: MokoCassiopeia
|
||||||
* REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
* REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||||
* PATH: /site/controllers/item.php
|
* PATH: /path/to/file.php
|
||||||
* VERSION: XX.YY.ZZ
|
* VERSION: XX.YY.ZZ
|
||||||
* BRIEF: One-line description of file purpose
|
* BRIEF: One-line description of purpose
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
defined('_JEXEC') or die;
|
||||||
```
|
```
|
||||||
|
|
||||||
**Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields.
|
**Markdown:**
|
||||||
|
```markdown
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
|
||||||
|
This file is part of a Moko Consulting project.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
# FILE INFORMATION
|
||||||
|
DEFGROUP: MokoCassiopeia.Documentation
|
||||||
|
INGROUP: MokoCassiopeia
|
||||||
|
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||||
|
PATH: /docs/file.md
|
||||||
|
VERSION: XX.YY.ZZ
|
||||||
|
BRIEF: One-line description
|
||||||
|
-->
|
||||||
|
```
|
||||||
|
|
||||||
|
**YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. JSON files are exempt.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Coding Standards
|
## Version Management
|
||||||
|
|
||||||
## Naming Conventions
|
**`README.md` is the single source of truth for the repository version.**
|
||||||
|
|
||||||
| Context | Convention | Example |
|
- **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`.
|
||||||
|---------|-----------|---------|
|
- The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references.
|
||||||
| PHP class | `PascalCase` | `ItemModel` |
|
- Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`).
|
||||||
| PHP method / function | `camelCase` | `getItems()` |
|
- Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only.
|
||||||
| PHP variable | `$snake_case` | `$item_id` |
|
|
||||||
| PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` |
|
|
||||||
| PHP class file | `PascalCase.php` | `ItemModel.php` |
|
|
||||||
| YAML workflow | `kebab-case.yml` | `ci-joomla.yml` |
|
|
||||||
| Markdown doc | `kebab-case.md` | `installation-guide.md` |
|
|
||||||
|
|
||||||
## Commit Messages
|
### Joomla Version Alignment
|
||||||
|
|
||||||
Format: `<type>(<scope>): <subject>` — imperative, lower-case subject, no trailing period.
|
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||||
|
|
||||||
Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build`
|
```xml
|
||||||
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
|
<version>01.02.04</version>
|
||||||
|
|
||||||
## Branch Naming
|
<!-- In update.xml — prepend a new <update> block for every release.
|
||||||
|
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||||
Format: `<prefix>/<MAJOR.MINOR.PATCH>[/description]`
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
|
regular expression, so \. matches a literal dot. -->
|
||||||
Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/`
|
<updates>
|
||||||
|
<update>
|
||||||
|
<name>{{EXTENSION_NAME}}</name>
|
||||||
|
<version>01.02.04</version>
|
||||||
|
<downloads>
|
||||||
|
<downloadurl type="full" format="zip">
|
||||||
|
https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip
|
||||||
|
</downloadurl>
|
||||||
|
</downloads>
|
||||||
|
<targetplatform name="joomla" version="4\.[0-9]+" />
|
||||||
|
</update>
|
||||||
|
<!-- … older entries preserved below … -->
|
||||||
|
</updates>
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# GitHub Actions — Token Usage
|
## Joomla Extension Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
MokoCassiopeia/
|
||||||
|
├── manifest.xml # Joomla installer manifest (root — required)
|
||||||
|
├── update.xml # Update server manifest (root — required, see below)
|
||||||
|
├── site/ # Frontend (site) code
|
||||||
|
│ ├── controller.php
|
||||||
|
│ ├── controllers/
|
||||||
|
│ ├── models/
|
||||||
|
│ └── views/
|
||||||
|
├── admin/ # Backend (admin) code
|
||||||
|
│ ├── controller.php
|
||||||
|
│ ├── controllers/
|
||||||
|
│ ├── models/
|
||||||
|
│ ├── views/
|
||||||
|
│ └── sql/
|
||||||
|
├── language/ # Language INI files
|
||||||
|
├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/)
|
||||||
|
├── docs/ # Technical documentation
|
||||||
|
├── tests/ # Test suite
|
||||||
|
├── .github/
|
||||||
|
│ ├── workflows/
|
||||||
|
│ ├── copilot-instructions.md # This file
|
||||||
|
│ └── CLAUDE.md
|
||||||
|
├── README.md # Version source of truth
|
||||||
|
├── CHANGELOG.md
|
||||||
|
├── CONTRIBUTING.md
|
||||||
|
├── LICENSE # GPL-3.0-or-later
|
||||||
|
└── Makefile # Build automation
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## update.xml — Required in Repo Root
|
||||||
|
|
||||||
|
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||||
|
|
||||||
|
The `manifest.xml` must reference it via:
|
||||||
|
```xml
|
||||||
|
<updateservers>
|
||||||
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
|
https://github.com/mokoconsulting-tech/MokoCassiopeia/raw/main/update.xml
|
||||||
|
</server>
|
||||||
|
</updateservers>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rules:**
|
||||||
|
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||||
|
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||||
|
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||||
|
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## manifest.xml Rules
|
||||||
|
|
||||||
|
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||||
|
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||||
|
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||||
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## GitHub Actions — Token Usage
|
||||||
|
|
||||||
Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token).
|
Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token).
|
||||||
|
|
||||||
@@ -217,58 +229,76 @@ env:
|
|||||||
```
|
```
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# ❌ Wrong — never use these
|
# ❌ Wrong — never use these in workflows
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Keeping Documentation Current
|
## MokoStandards Reference
|
||||||
|
|
||||||
| Change type | Documentation to update |
|
This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). Authoritative policies:
|
||||||
|-------------|------------------------|
|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
|
||||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
|
||||||
| **Every PR** | **Bump the patch version** — increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# What NOT to Do
|
|
||||||
|
|
||||||
- **Never commit directly to `main`** — all changes go through a PR.
|
|
||||||
- **Never hardcode version numbers** in body text — update `README.md` and let automation propagate.
|
|
||||||
- **Never let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
|
||||||
- **Never skip the FILE INFORMATION block** on a new source file.
|
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
|
||||||
- **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`.
|
|
||||||
- **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# PR Checklist
|
|
||||||
|
|
||||||
Before opening a PR, verify:
|
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
|
||||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
|
||||||
- [ ] FILE INFORMATION headers updated in modified files
|
|
||||||
- [ ] CHANGELOG.md updated
|
|
||||||
- [ ] Tests pass
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Key Policy Documents (MokoStandards)
|
|
||||||
|
|
||||||
| Document | Purpose |
|
| Document | Purpose |
|
||||||
|----------|---------|
|
|----------|---------|
|
||||||
| [file-header-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type |
|
| [file-header-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type |
|
||||||
| [coding-style-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions |
|
| [coding-style-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions |
|
||||||
| [branching-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow |
|
| [branching-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow |
|
||||||
| [merge-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR conventions |
|
| [merge-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR title/body conventions |
|
||||||
| [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md |
|
| [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md |
|
||||||
| [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide |
|
| [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Naming Conventions
|
||||||
|
|
||||||
|
| Context | Convention | Example |
|
||||||
|
|---------|-----------|---------|
|
||||||
|
| PHP class | `PascalCase` | `MyController` |
|
||||||
|
| PHP method / function | `camelCase` | `getItems()` |
|
||||||
|
| PHP variable | `$snake_case` | `$item_id` |
|
||||||
|
| PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` |
|
||||||
|
| PHP class file | `PascalCase.php` | `ItemModel.php` |
|
||||||
|
| YAML workflow | `kebab-case.yml` | `ci-joomla.yml` |
|
||||||
|
| Markdown doc | `kebab-case.md` | `installation-guide.md` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit Messages
|
||||||
|
|
||||||
|
Format: `<type>(<scope>): <subject>` — imperative, lower-case subject, no trailing period.
|
||||||
|
|
||||||
|
Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Branch Naming
|
||||||
|
|
||||||
|
Format: `<prefix>/<MAJOR.MINOR.PATCH>[/description]`
|
||||||
|
|
||||||
|
Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Keeping Documentation Current
|
||||||
|
|
||||||
|
| Change type | Documentation to update |
|
||||||
|
|-------------|------------------------|
|
||||||
|
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||||
|
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||||
|
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||||
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
|
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
||||||
|
| **Every PR** | **Bump the patch version** — increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Constraints
|
||||||
|
|
||||||
|
- Never commit directly to `main` — all changes go via PR, squash-merged
|
||||||
|
- Never skip the FILE INFORMATION block on a new file
|
||||||
|
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||||
|
- Never hardcode version numbers in body text — update `README.md` and let automation propagate
|
||||||
|
- Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows — always use `secrets.GH_TOKEN`
|
||||||
|
- Never let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||||
|
|||||||
19
.github/copilot-instructions.md
vendored
19
.github/copilot-instructions.md
vendored
@@ -1,3 +1,22 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
|
||||||
|
This file is part of a Moko Consulting project.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
# FILE INFORMATION
|
||||||
|
DEFGROUP: MokoStandards.Templates.GitHub
|
||||||
|
INGROUP: MokoStandards.Templates
|
||||||
|
REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||||
|
PATH: /templates/github/copilot-instructions.joomla.md.template
|
||||||
|
VERSION: XX.YY.ZZ
|
||||||
|
BRIEF: GitHub Copilot custom instructions template for Joomla/MokoWaaS governed repositories
|
||||||
|
NOTE: Synced to .github/copilot-instructions.md in all Joomla/WaaS repos via bulk sync.
|
||||||
|
Tokens replaced at sync time: MokoCassiopeia, https://github.com/mokoconsulting-tech/MokoCassiopeia, {{EXTENSION_NAME}},
|
||||||
|
{{EXTENSION_TYPE}}, {{EXTENSION_ELEMENT}}
|
||||||
|
-->
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> **🔧 AI Self-Update Required on First Use**
|
> **🔧 AI Self-Update Required on First Use**
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -13,13 +13,14 @@
|
|||||||
BRIEF: Documentation for MokoCassiopeia template
|
BRIEF: Documentation for MokoCassiopeia template
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# README - MokoCassiopeia (VERSION: 03.09.03)
|
# MokoCassiopeia
|
||||||
|
|
||||||
**A Modern, Lightweight Joomla Template Based on Cassiopeia**
|
**A Modern, Lightweight Joomla Template Based on Cassiopeia**
|
||||||
|
|
||||||
|
[](https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/tag/v03)
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||||
[](https://www.joomla.org)
|
[](https://www.joomla.org)
|
||||||
[](https://www.php.net)
|
[](https://www.php.net)
|
||||||
|
|
||||||
MokoCassiopeia is a modern, lightweight enhancement layer built on top of Joomla's Cassiopeia template. It adds **Font Awesome 7**, **Bootstrap 5** helpers, an automatic **Table of Contents (TOC)** utility, advanced **Dark Mode** theming, and optional integrations for **Google Tag Manager** and **Google Analytics (GA4)**—all while maintaining minimal core template overrides for maximum upgrade compatibility.
|
MokoCassiopeia is a modern, lightweight enhancement layer built on top of Joomla's Cassiopeia template. It adds **Font Awesome 7**, **Bootstrap 5** helpers, an automatic **Table of Contents (TOC)** utility, advanced **Dark Mode** theming, and optional integrations for **Google Tag Manager** and **Google Analytics (GA4)**—all while maintaining minimal core template overrides for maximum upgrade compatibility.
|
||||||
|
|
||||||
|
|||||||
@@ -1,276 +0,0 @@
|
|||||||
# Scripts — MokoCassiopeia
|
|
||||||
|
|
||||||
This directory contains utility scripts for building, releasing, and managing the MokoCassiopeia Joomla template.
|
|
||||||
|
|
||||||
## Available Scripts
|
|
||||||
|
|
||||||
### build-release.sh
|
|
||||||
|
|
||||||
**Purpose**: Build a release package for MokoCassiopeia template.
|
|
||||||
|
|
||||||
**Usage**:
|
|
||||||
```bash
|
|
||||||
# Build with auto-detected version from templateDetails.xml
|
|
||||||
./scripts/build-release.sh
|
|
||||||
|
|
||||||
# Build with specific version
|
|
||||||
./scripts/build-release.sh 03.08.03
|
|
||||||
```
|
|
||||||
|
|
||||||
**What it does**:
|
|
||||||
1. Creates a `build/` directory
|
|
||||||
2. Copies template files from `src/`
|
|
||||||
3. Copies media files from `src/media/` to `media/`
|
|
||||||
4. Creates a ZIP package: `mokocassiopeia-src-{version}.zip`
|
|
||||||
5. Generates SHA-256 and MD5 checksums
|
|
||||||
6. Outputs package location and checksums
|
|
||||||
|
|
||||||
**Output**:
|
|
||||||
- `build/mokocassiopeia-src-{version}.zip` - Installation package
|
|
||||||
- `build/mokocassiopeia-src-{version}.zip.sha256` - SHA-256 checksum
|
|
||||||
- `build/mokocassiopeia-src-{version}.zip.md5` - MD5 checksum
|
|
||||||
|
|
||||||
**Requirements**:
|
|
||||||
- `rsync` for file copying
|
|
||||||
- `zip` for package creation
|
|
||||||
- `sha256sum` and `md5sum` for checksums
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Automated Workflows
|
|
||||||
|
|
||||||
The repository includes GitHub Actions workflows that automate the build and release process:
|
|
||||||
|
|
||||||
### `.github/workflows/release.yml`
|
|
||||||
|
|
||||||
**Purpose**: Automated release creation when tags are pushed.
|
|
||||||
|
|
||||||
**Triggers**:
|
|
||||||
- Push of version tag (e.g., `03.08.03`)
|
|
||||||
- Manual workflow dispatch with version input
|
|
||||||
|
|
||||||
**Process**:
|
|
||||||
1. Checks out repository
|
|
||||||
2. Sets up PHP environment
|
|
||||||
3. Installs dependencies (if composer.json exists)
|
|
||||||
4. Updates version numbers in manifest files
|
|
||||||
5. Creates package structure
|
|
||||||
6. Builds ZIP package
|
|
||||||
7. Generates checksums
|
|
||||||
8. Creates GitHub Release with artifacts
|
|
||||||
|
|
||||||
**Usage**:
|
|
||||||
```bash
|
|
||||||
# Create and push a tag
|
|
||||||
git tag 03.08.04
|
|
||||||
git push origin 03.08.04
|
|
||||||
|
|
||||||
# Or use GitHub UI to run manually
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `.github/workflows/auto-update-sha.yml`
|
|
||||||
|
|
||||||
**Purpose**: Automatically update SHA-256 hash in `updates.xml` after a release is published.
|
|
||||||
|
|
||||||
**Triggers**:
|
|
||||||
- GitHub Release published
|
|
||||||
- Manual workflow dispatch with tag input
|
|
||||||
|
|
||||||
**Process**:
|
|
||||||
1. Downloads the release package
|
|
||||||
2. Calculates SHA-256 hash
|
|
||||||
3. Updates `updates.xml` with:
|
|
||||||
- New version number
|
|
||||||
- Current date
|
|
||||||
- Download URL
|
|
||||||
- SHA-256 hash
|
|
||||||
4. Commits and pushes changes to main branch
|
|
||||||
|
|
||||||
**Benefits**:
|
|
||||||
- Ensures `updates.xml` always has correct SHA-256 hash
|
|
||||||
- Enables Joomla update server functionality
|
|
||||||
- Reduces manual update errors
|
|
||||||
- Automates security verification
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Release Process
|
|
||||||
|
|
||||||
### Manual Release (Local Build)
|
|
||||||
|
|
||||||
1. **Update version numbers**:
|
|
||||||
```bash
|
|
||||||
# Update these files manually:
|
|
||||||
# - src/templateDetails.xml
|
|
||||||
# - updates.xml
|
|
||||||
# - CHANGELOG.md
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Build package**:
|
|
||||||
```bash
|
|
||||||
./scripts/build-release.sh 03.08.04
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Test package**:
|
|
||||||
- Install ZIP in Joomla test environment
|
|
||||||
- Verify all features work correctly
|
|
||||||
|
|
||||||
4. **Create GitHub Release**:
|
|
||||||
- Go to GitHub Releases
|
|
||||||
- Click "Create a new release"
|
|
||||||
- Upload the ZIP, SHA256, and MD5 files
|
|
||||||
- Add release notes from CHANGELOG.md
|
|
||||||
|
|
||||||
5. **Update updates.xml**:
|
|
||||||
- Copy SHA-256 hash from `.sha256` file
|
|
||||||
- Update `updates.xml` with new hash
|
|
||||||
- Commit and push changes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Automated Release (GitHub Actions)
|
|
||||||
|
|
||||||
1. **Update version numbers**:
|
|
||||||
```bash
|
|
||||||
# Update these files in a branch:
|
|
||||||
# - src/templateDetails.xml
|
|
||||||
# - CHANGELOG.md
|
|
||||||
|
|
||||||
git checkout -b release/03.08.04
|
|
||||||
# Make changes
|
|
||||||
git commit -m "chore: Prepare release 03.08.04"
|
|
||||||
git push origin release/03.08.04
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Create and merge PR**:
|
|
||||||
- Create PR from release branch
|
|
||||||
- Review changes
|
|
||||||
- Merge to main
|
|
||||||
|
|
||||||
3. **Create and push tag**:
|
|
||||||
```bash
|
|
||||||
git checkout main
|
|
||||||
git pull
|
|
||||||
git tag 03.08.04
|
|
||||||
git push origin 03.08.04
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Automated process**:
|
|
||||||
- GitHub Actions builds package automatically
|
|
||||||
- Creates GitHub Release with artifacts
|
|
||||||
- `auto-update-sha` workflow updates `updates.xml`
|
|
||||||
|
|
||||||
5. **Verify**:
|
|
||||||
- Check GitHub Release is created
|
|
||||||
- Verify `updates.xml` has correct SHA-256
|
|
||||||
- Test Joomla update server
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Development Workflow
|
|
||||||
|
|
||||||
### Testing Local Builds
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build current version
|
|
||||||
./scripts/build-release.sh
|
|
||||||
|
|
||||||
# Install in Joomla
|
|
||||||
# Navigate to Extensions > Manage > Install > Upload Package File
|
|
||||||
# Select: build/mokocassiopeia-src-{version}.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
### Pre-Release Checklist
|
|
||||||
|
|
||||||
- [ ] All code changes merged to main
|
|
||||||
- [ ] Version numbers updated:
|
|
||||||
- [ ] `src/templateDetails.xml`
|
|
||||||
- [ ] `CHANGELOG.md`
|
|
||||||
- [ ] CHANGELOG.md updated with release notes
|
|
||||||
- [ ] Tests passing
|
|
||||||
- [ ] Documentation updated
|
|
||||||
- [ ] Local build tested in Joomla
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Build Fails
|
|
||||||
|
|
||||||
**Problem**: `rsync: command not found`
|
|
||||||
```bash
|
|
||||||
# Ubuntu/Debian
|
|
||||||
sudo apt-get install rsync
|
|
||||||
|
|
||||||
# macOS
|
|
||||||
brew install rsync
|
|
||||||
```
|
|
||||||
|
|
||||||
**Problem**: `zip: command not found`
|
|
||||||
```bash
|
|
||||||
# Ubuntu/Debian
|
|
||||||
sudo apt-get install zip
|
|
||||||
|
|
||||||
# macOS (usually pre-installed)
|
|
||||||
brew install zip
|
|
||||||
```
|
|
||||||
|
|
||||||
### GitHub Actions Fails
|
|
||||||
|
|
||||||
**Problem**: Release workflow fails on tag push
|
|
||||||
|
|
||||||
Check:
|
|
||||||
1. Tag format matches pattern: `[0-9][0-9].[0-9][0-9].[0-9][0-9]`
|
|
||||||
2. Repository has write permissions for GITHUB_TOKEN
|
|
||||||
3. `src/` and `src/media/` directories exist
|
|
||||||
|
|
||||||
**Problem**: auto-update-sha fails
|
|
||||||
|
|
||||||
Check:
|
|
||||||
1. Release package was published successfully
|
|
||||||
2. Workflow has write permissions
|
|
||||||
3. Package naming matches expected format
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## File Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
scripts/
|
|
||||||
├── README.md # This file
|
|
||||||
└── build-release.sh # Local build script
|
|
||||||
|
|
||||||
.github/workflows/
|
|
||||||
├── release.yml # Automated release workflow
|
|
||||||
└── auto-update-sha.yml # SHA hash update workflow
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
When adding new scripts:
|
|
||||||
|
|
||||||
1. Add GPL-3.0-or-later license header
|
|
||||||
2. Include FILE INFORMATION block
|
|
||||||
3. Add usage documentation in this README
|
|
||||||
4. Make scripts executable: `chmod +x scripts/your-script.sh`
|
|
||||||
5. Test thoroughly before committing
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
- **Issues**: [GitHub Issues](https://github.com/mokoconsulting-tech/MokoCassiopeia/issues)
|
|
||||||
- **Email**: hello@mokoconsulting.tech
|
|
||||||
- **Documentation**: [docs/](../docs/)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
All scripts are licensed under GPL-3.0-or-later.
|
|
||||||
|
|
||||||
Copyright (C) 2026 Moko Consulting
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
#
|
|
||||||
# FILE INFORMATION
|
|
||||||
# DEFGROUP: Build.Scripts
|
|
||||||
# INGROUP: MokoCassiopeia.Build
|
|
||||||
# REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
|
||||||
# PATH: /scripts/build-release.sh
|
|
||||||
# VERSION: 01.00.00
|
|
||||||
# BRIEF: Build release package for MokoCassiopeia template
|
|
||||||
# USAGE: ./scripts/build-release.sh [version]
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Script directory
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
||||||
|
|
||||||
# Functions
|
|
||||||
log_info() {
|
|
||||||
echo -e "${BLUE}[INFO]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_success() {
|
|
||||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warning() {
|
|
||||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
echo -e "${RED}[ERROR]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if version is provided
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
# Try to extract version from templateDetails.xml
|
|
||||||
if [ -f "${PROJECT_ROOT}/src/templateDetails.xml" ]; then
|
|
||||||
VERSION=$(grep -oP '<version>\K[^<]+' "${PROJECT_ROOT}/src/templateDetails.xml" | head -1)
|
|
||||||
log_info "Detected version: ${VERSION}"
|
|
||||||
else
|
|
||||||
log_error "Please provide version as argument: ./build-release.sh 03.08.03"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
VERSION="$1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "Building MokoCassiopeia release package"
|
|
||||||
log_info "Version: ${VERSION}"
|
|
||||||
|
|
||||||
# Change to project root
|
|
||||||
cd "${PROJECT_ROOT}"
|
|
||||||
|
|
||||||
# Create build directory
|
|
||||||
BUILD_DIR="${PROJECT_ROOT}/build"
|
|
||||||
PACKAGE_DIR="${BUILD_DIR}/package"
|
|
||||||
rm -rf "${BUILD_DIR}"
|
|
||||||
mkdir -p "${PACKAGE_DIR}"
|
|
||||||
|
|
||||||
log_info "Creating package structure..."
|
|
||||||
|
|
||||||
# Copy template files from src (excluding media directory)
|
|
||||||
if [ -d "src" ]; then
|
|
||||||
rsync -av --exclude='.git*' --exclude='media' src/ "${PACKAGE_DIR}/"
|
|
||||||
else
|
|
||||||
log_error "src directory not found!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy media files from src/media
|
|
||||||
if [ -d "src/media" ]; then
|
|
||||||
mkdir -p "${PACKAGE_DIR}/media"
|
|
||||||
rsync -av --exclude='.git*' src/media/ "${PACKAGE_DIR}/media/"
|
|
||||||
else
|
|
||||||
log_warning "src/media directory not found, skipping media files"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "Package structure created"
|
|
||||||
|
|
||||||
# Create ZIP package
|
|
||||||
cd "${PACKAGE_DIR}"
|
|
||||||
ZIP_NAME="mokocassiopeia-src-${VERSION}.zip"
|
|
||||||
log_info "Creating ZIP package: ${ZIP_NAME}"
|
|
||||||
|
|
||||||
zip -r "../${ZIP_NAME}" . -q
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
log_error "Failed to create ZIP package"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "${BUILD_DIR}"
|
|
||||||
log_success "Created: ${ZIP_NAME}"
|
|
||||||
|
|
||||||
# Generate checksums
|
|
||||||
log_info "Generating checksums..."
|
|
||||||
sha256sum "${ZIP_NAME}" > "${ZIP_NAME}.sha256"
|
|
||||||
md5sum "${ZIP_NAME}" > "${ZIP_NAME}.md5"
|
|
||||||
|
|
||||||
# Extract just the hash
|
|
||||||
SHA256_HASH=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1)
|
|
||||||
|
|
||||||
log_success "SHA-256: ${SHA256_HASH}"
|
|
||||||
log_success "MD5: $(md5sum "${ZIP_NAME}" | cut -d' ' -f1)"
|
|
||||||
|
|
||||||
# Show file info
|
|
||||||
FILE_SIZE=$(du -h "${ZIP_NAME}" | cut -f1)
|
|
||||||
log_info "Package size: ${FILE_SIZE}"
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
echo ""
|
|
||||||
log_success "Build completed successfully!"
|
|
||||||
echo ""
|
|
||||||
echo "Package: ${BUILD_DIR}/${ZIP_NAME}"
|
|
||||||
echo "SHA-256: ${BUILD_DIR}/${ZIP_NAME}.sha256"
|
|
||||||
echo "MD5: ${BUILD_DIR}/${ZIP_NAME}.md5"
|
|
||||||
echo ""
|
|
||||||
echo "Next steps:"
|
|
||||||
echo "1. Test the package installation in Joomla"
|
|
||||||
echo "2. Create a GitHub release with this package"
|
|
||||||
echo "3. Update updates.xml with the new version and SHA-256 hash"
|
|
||||||
echo ""
|
|
||||||
73
scripts/download-google-fonts.php
Normal file
73
scripts/download-google-fonts.php
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
*
|
||||||
|
* This file is part of a Moko Consulting project.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* # FILE INFORMATION
|
||||||
|
* DEFGROUP: Joomla.Template.Site
|
||||||
|
* INGROUP: MokoCassiopeia
|
||||||
|
* PATH: scripts/download-google-fonts.php
|
||||||
|
* VERSION: 03.09.05
|
||||||
|
* BRIEF: Download Google Fonts (woff2) for local self-hosting
|
||||||
|
*/
|
||||||
|
|
||||||
|
$fontsDir = __DIR__ . '/../src/media/fonts';
|
||||||
|
|
||||||
|
if (!is_dir($fontsDir)) {
|
||||||
|
fwrite(STDERR, "Error: Fonts directory not found: {$fontsDir}\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fonts = [
|
||||||
|
'Roboto' => 'https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;700&display=swap',
|
||||||
|
'Noto Sans' => 'https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&display=swap',
|
||||||
|
'Fira Sans' => 'https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&display=swap',
|
||||||
|
];
|
||||||
|
|
||||||
|
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
||||||
|
|
||||||
|
echo "Google Fonts Downloader for MokoCassiopeia\n";
|
||||||
|
echo str_repeat('=', 48) . "\n";
|
||||||
|
echo "Target: {$fontsDir}\n\n";
|
||||||
|
|
||||||
|
foreach ($fonts as $name => $url) {
|
||||||
|
echo "Downloading {$name}...\n";
|
||||||
|
|
||||||
|
$ctx = stream_context_create(['http' => ['header' => "User-Agent: {$userAgent}\r\n"]]);
|
||||||
|
$css = @file_get_contents($url, false, $ctx);
|
||||||
|
|
||||||
|
if ($css === false) {
|
||||||
|
fwrite(STDERR, " FAIL: could not fetch CSS for {$name}\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match_all('#https://fonts\.gstatic\.com[^)]*\.woff2#', $css, $matches);
|
||||||
|
|
||||||
|
if (empty($matches[0])) {
|
||||||
|
fwrite(STDERR, " FAIL: no woff2 URLs found for {$name}\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
foreach ($matches[0] as $fontUrl) {
|
||||||
|
$filename = basename($fontUrl);
|
||||||
|
$dest = $fontsDir . '/' . $filename;
|
||||||
|
|
||||||
|
$data = @file_get_contents($fontUrl, false, $ctx);
|
||||||
|
if ($data === false) {
|
||||||
|
fwrite(STDERR, " FAIL: {$filename}\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($dest, $data);
|
||||||
|
$size = round(strlen($data) / 1024, 1);
|
||||||
|
echo " OK: {$filename} ({$size} KB)\n";
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " {$count} file(s) downloaded\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Done.\n";
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
#
|
|
||||||
# Download Google Fonts for self-hosting
|
|
||||||
# This script downloads Roboto, Noto Sans, and Fira Sans fonts
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Target directory
|
|
||||||
FONTS_DIR="../src/media/fonts"
|
|
||||||
|
|
||||||
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
|
|
||||||
echo -e "${BLUE}║ Google Fonts Downloader for MokoCassiopeia ║${NC}"
|
|
||||||
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if fonts directory exists
|
|
||||||
if [ ! -d "$FONTS_DIR" ]; then
|
|
||||||
echo -e "${RED}✗ Error: Fonts directory not found: $FONTS_DIR${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$FONTS_DIR"
|
|
||||||
|
|
||||||
echo -e "${YELLOW}Target directory: $(pwd)${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Function to download font CSS and extract font files
|
|
||||||
download_font() {
|
|
||||||
local font_name="$1"
|
|
||||||
local font_url="$2"
|
|
||||||
local display_name="$3"
|
|
||||||
|
|
||||||
echo -e "${GREEN}Downloading $display_name...${NC}"
|
|
||||||
|
|
||||||
# Download CSS with user agent for woff2 format
|
|
||||||
css=$(curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "$font_url")
|
|
||||||
|
|
||||||
if [ -z "$css" ]; then
|
|
||||||
echo -e "${RED} ✗ Failed to download CSS${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Extract woff2 URLs
|
|
||||||
urls=$(echo "$css" | grep -oP 'https://fonts\.gstatic\.com[^\)]*\.woff2' || true)
|
|
||||||
|
|
||||||
if [ -z "$urls" ]; then
|
|
||||||
echo -e "${RED} ✗ No font URLs found in CSS${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
count=0
|
|
||||||
while IFS= read -r url; do
|
|
||||||
if [ -z "$url" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
filename=$(basename "$url")
|
|
||||||
echo -e " → Downloading ${filename}..."
|
|
||||||
|
|
||||||
if curl -s "$url" -o "$filename"; then
|
|
||||||
size=$(du -h "$filename" | cut -f1)
|
|
||||||
echo -e "${GREEN} ✓ Downloaded ($size)${NC}"
|
|
||||||
((count++))
|
|
||||||
else
|
|
||||||
echo -e "${RED} ✗ Failed${NC}"
|
|
||||||
fi
|
|
||||||
done <<< "$urls"
|
|
||||||
|
|
||||||
echo -e "${GREEN} ✓ Downloaded $count font files${NC}"
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
# Download fonts
|
|
||||||
download_font "roboto" "https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;700&display=swap" "Roboto"
|
|
||||||
download_font "noto-sans" "https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&display=swap" "Noto Sans"
|
|
||||||
download_font "fira-sans" "https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&display=swap" "Fira Sans"
|
|
||||||
|
|
||||||
echo -e "${GREEN}╔════════════════════════════════════════════╗${NC}"
|
|
||||||
echo -e "${GREEN}║ ✓ All fonts downloaded successfully! ║${NC}"
|
|
||||||
echo -e "${GREEN}╚════════════════════════════════════════════╝${NC}"
|
|
||||||
echo ""
|
|
||||||
echo -e "Font files saved to: ${BLUE}$(pwd)${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "Next steps:"
|
|
||||||
echo "1. Verify font files are present"
|
|
||||||
echo "2. Update templateDetails.xml font options (if needed)"
|
|
||||||
echo "3. Remove Google Fonts CDN preconnect links from PHP templates"
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
*
|
|
||||||
* This file is part of a Moko Consulting project.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*
|
|
||||||
* # FILE INFORMATION
|
|
||||||
* DEFGROUP: Joomla.Template.Site
|
|
||||||
* INGROUP: MokoCassiopeia
|
|
||||||
* REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
|
||||||
* PATH: ./scripts/minify.js
|
|
||||||
* VERSION: 03.09.03
|
|
||||||
* BRIEF: Generates .min.css and .min.js files from the Joomla asset manifest
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const CleanCSS = require('clean-css');
|
|
||||||
const { minify: terserMinify } = require('terser');
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Config
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const ROOT = path.resolve(__dirname, '..');
|
|
||||||
const SRC_MEDIA = path.join(ROOT, 'src', 'media');
|
|
||||||
const ASSET_JSON = path.join(ROOT, 'src', 'joomla.asset.json');
|
|
||||||
|
|
||||||
// URI prefix used in the manifest — maps to SRC_MEDIA on disk.
|
|
||||||
// e.g. "media/templates/site/mokocassiopeia/css/template.css"
|
|
||||||
const URI_PREFIX = 'media/templates/site/mokocassiopeia/';
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Helpers
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve a manifest URI to an absolute disk path under src/media/.
|
|
||||||
*
|
|
||||||
* @param {string} uri e.g. "media/templates/site/mokocassiopeia/css/foo.css"
|
|
||||||
* @returns {string|null}
|
|
||||||
*/
|
|
||||||
function uriToPath(uri) {
|
|
||||||
if (!uri.startsWith(URI_PREFIX)) return null;
|
|
||||||
return path.join(SRC_MEDIA, uri.slice(URI_PREFIX.length));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the filename looks like an already-minified file or belongs
|
|
||||||
* to a vendor bundle we don't own.
|
|
||||||
*/
|
|
||||||
function isVendorOrUserFile(filePath) {
|
|
||||||
const rel = filePath.replace(SRC_MEDIA + path.sep, '');
|
|
||||||
return rel.startsWith('vendor' + path.sep)
|
|
||||||
|| path.basename(filePath).startsWith('user.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Pair detection
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the asset manifest and return an array of { src, dest, type } pairs
|
|
||||||
* where dest is a minified version of src that doesn't already exist or is
|
|
||||||
* older than src.
|
|
||||||
*
|
|
||||||
* Pairing logic: for every non-.min asset, check whether the manifest also
|
|
||||||
* contains a corresponding .min asset. If so, that's our pair.
|
|
||||||
*/
|
|
||||||
function detectPairs(assets) {
|
|
||||||
// Build a lookup of all URIs in the manifest.
|
|
||||||
const uriSet = new Set(assets.map(a => a.uri));
|
|
||||||
|
|
||||||
const pairs = [];
|
|
||||||
|
|
||||||
for (const asset of assets) {
|
|
||||||
const { uri, type } = asset;
|
|
||||||
if (type !== 'style' && type !== 'script') continue;
|
|
||||||
|
|
||||||
// Skip already-minified entries.
|
|
||||||
if (/\.min\.(css|js)$/.test(uri)) continue;
|
|
||||||
|
|
||||||
// Derive the expected .min URI.
|
|
||||||
const minUri = uri.replace(/\.(css|js)$/, '.min.$1');
|
|
||||||
if (!uriSet.has(minUri)) continue;
|
|
||||||
|
|
||||||
const srcPath = uriToPath(uri);
|
|
||||||
const destPath = uriToPath(minUri);
|
|
||||||
if (!srcPath || !destPath) continue;
|
|
||||||
|
|
||||||
if (isVendorOrUserFile(srcPath)) continue;
|
|
||||||
|
|
||||||
if (!fs.existsSync(srcPath)) {
|
|
||||||
console.warn(` [skip] source missing: ${srcPath}`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pairs.push({ src: srcPath, dest: destPath, type });
|
|
||||||
}
|
|
||||||
|
|
||||||
return pairs;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Minifiers
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
async function minifyCSS(srcPath, destPath) {
|
|
||||||
const source = fs.readFileSync(srcPath, 'utf8');
|
|
||||||
const result = new CleanCSS({ level: 2, returnPromise: true });
|
|
||||||
const output = await result.minify(source);
|
|
||||||
|
|
||||||
if (output.errors && output.errors.length) {
|
|
||||||
throw new Error(output.errors.join('\n'));
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
||||||
fs.writeFileSync(destPath, output.styles, 'utf8');
|
|
||||||
|
|
||||||
const srcSize = Buffer.byteLength(source, 'utf8');
|
|
||||||
const destSize = Buffer.byteLength(output.styles, 'utf8');
|
|
||||||
const saving = (100 - (destSize / srcSize * 100)).toFixed(1);
|
|
||||||
|
|
||||||
return { srcSize, destSize, saving };
|
|
||||||
}
|
|
||||||
|
|
||||||
async function minifyJS(srcPath, destPath) {
|
|
||||||
const source = fs.readFileSync(srcPath, 'utf8');
|
|
||||||
const result = await terserMinify(source, {
|
|
||||||
compress: { drop_console: false },
|
|
||||||
mangle: true,
|
|
||||||
format: { comments: false }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result.code) throw new Error('terser returned no output');
|
|
||||||
|
|
||||||
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
||||||
fs.writeFileSync(destPath, result.code, 'utf8');
|
|
||||||
|
|
||||||
const srcSize = Buffer.byteLength(source, 'utf8');
|
|
||||||
const destSize = Buffer.byteLength(result.code, 'utf8');
|
|
||||||
const saving = (100 - (destSize / srcSize * 100)).toFixed(1);
|
|
||||||
|
|
||||||
return { srcSize, destSize, saving };
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Main
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
const manifest = JSON.parse(fs.readFileSync(ASSET_JSON, 'utf8'));
|
|
||||||
const pairs = detectPairs(manifest.assets);
|
|
||||||
|
|
||||||
if (pairs.length === 0) {
|
|
||||||
console.log('No pairs found — nothing to minify.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`\nMinifying ${pairs.length} file(s)...\n`);
|
|
||||||
|
|
||||||
let ok = 0, fail = 0;
|
|
||||||
|
|
||||||
for (const { src, dest, type } of pairs) {
|
|
||||||
const label = path.relative(ROOT, src);
|
|
||||||
process.stdout.write(` ${label} ... `);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const stats = type === 'style'
|
|
||||||
? await minifyCSS(src, dest)
|
|
||||||
: await minifyJS(src, dest);
|
|
||||||
|
|
||||||
const kb = n => (n / 1024).toFixed(1) + ' kB';
|
|
||||||
console.log(`${kb(stats.srcSize)} → ${kb(stats.destSize)} (${stats.saving}% saved)`);
|
|
||||||
ok++;
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`FAILED\n ${err.message}`);
|
|
||||||
fail++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`\nDone. ${ok} succeeded, ${fail} failed.\n`);
|
|
||||||
if (fail > 0) process.exit(1);
|
|
||||||
})();
|
|
||||||
@@ -448,7 +448,10 @@ $wa->useScript('user.js'); // js/user.js
|
|||||||
</nav>
|
</nav>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if ($this->countModules('search', true)) : ?>
|
<?php if ($this->countModules('search', true)) : ?>
|
||||||
<div class="container-search">
|
<button class="search-toggler d-lg-none" type="button" data-bs-toggle="collapse" data-bs-target="#headerSearchCollapse" aria-controls="headerSearchCollapse" aria-expanded="false" aria-label="<?php echo Text::_('JSEARCH_FILTER_SUBMIT'); ?>">
|
||||||
|
<span class="fa-solid fa-magnifying-glass" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
<div class="container-search collapse d-lg-block" id="headerSearchCollapse">
|
||||||
<jdoc:include type="modules" name="search" style="none" />
|
<jdoc:include type="modules" name="search" style="none" />
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
@@ -14477,13 +14477,20 @@ li.current a {
|
|||||||
min-width: 12rem;
|
min-width: 12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-header .navbar-toggler {
|
.container-header .navbar-toggler,
|
||||||
|
.container-header .search-toggler {
|
||||||
color: var(--mainmenu-nav-link-color, #fff);
|
color: var(--mainmenu-nav-link-color, #fff);
|
||||||
border-color: var(--mainmenu-nav-link-color, #fff);
|
border-color: var(--mainmenu-nav-link-color, #fff);
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container-header .search-toggler {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.container-header .container-search {
|
.container-header .container-search {
|
||||||
margin-top: 0.75em;
|
margin-top: 0.75em;
|
||||||
}
|
}
|
||||||
@@ -18665,6 +18672,10 @@ nav[data-toggle=toc] .nav-link.active+ul{
|
|||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container-header .container-search.collapse:not(.show) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.mod-finder__search.input-group {
|
.mod-finder__search.input-group {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
@@ -18683,8 +18694,8 @@ nav[data-toggle=toc] .nav-link.active+ul{
|
|||||||
}
|
}
|
||||||
|
|
||||||
.container-header .container-search {
|
.container-header .container-search {
|
||||||
flex: 0 0 25%;
|
flex: 0 0 15%;
|
||||||
max-width: 25%;
|
max-width: 15%;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
<name>MokoCassiopeia</name>
|
<name>MokoCassiopeia</name>
|
||||||
<version>03.09.04</version>
|
<version>03.09.07</version>
|
||||||
<scriptfile>script.php</scriptfile>
|
<scriptfile>script.php</scriptfile>
|
||||||
<creationDate>2026-03-26</creationDate>
|
<creationDate>2026-03-26</creationDate>
|
||||||
<author>Jonathan Miller || Moko Consulting</author>
|
<author>Jonathan Miller || Moko Consulting</author>
|
||||||
|
|||||||
22
update.xml
22
update.xml
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<updates>
|
|
||||||
<update>
|
|
||||||
<name>MokoCassiopeia</name>
|
|
||||||
<description>Moko Consulting site template based on Cassiopeia.</description>
|
|
||||||
<element>mokocassiopeia</element>
|
|
||||||
<type>template</type>
|
|
||||||
<version>03.09.04</version>
|
|
||||||
<client>site</client>
|
|
||||||
<tags>
|
|
||||||
<tag>stable</tag>
|
|
||||||
</tags>
|
|
||||||
<infourl title="MokoCassiopeia">https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/tag/v03</infourl>
|
|
||||||
<downloads>
|
|
||||||
<downloadurl type="full" format="zip">https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/v03/mokocassiopeia-03.09.04.zip</downloadurl>
|
|
||||||
</downloads>
|
|
||||||
<sha256>da85bf5a34cafadbae26df199ed36c04438e7dab440d046e0e4117d25510feaf</sha256>
|
|
||||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
|
||||||
<maintainer>Moko Consulting</maintainer>
|
|
||||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
|
||||||
</update>
|
|
||||||
</updates>
|
|
||||||
141
updates.xml
141
updates.xml
@@ -10,11 +10,15 @@
|
|||||||
INGROUP: MokoCassiopeia
|
INGROUP: MokoCassiopeia
|
||||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||||
PATH: ./updates.xml
|
PATH: ./updates.xml
|
||||||
VERSION: 03.09.04
|
VERSION: 03.09.05
|
||||||
BRIEF: Update manifest XML file for MokoCassiopeia
|
BRIEF: Update manifest XML — stable, rc, and development channels
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<updates>
|
<updates>
|
||||||
|
|
||||||
|
<!-- ══════════════════════════════════════════════════════════════
|
||||||
|
STABLE — production releases from main branch
|
||||||
|
══════════════════════════════════════════════════════════════ -->
|
||||||
<update>
|
<update>
|
||||||
<name>MokoCassiopeia</name>
|
<name>MokoCassiopeia</name>
|
||||||
<description>Moko Consulting's site template based on Cassiopeia.</description>
|
<description>Moko Consulting's site template based on Cassiopeia.</description>
|
||||||
@@ -44,4 +48,137 @@
|
|||||||
|
|
||||||
<targetplatform name='joomla' version='(5|6)\..*'/>
|
<targetplatform name='joomla' version='(5|6)\..*'/>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<!-- ══════════════════════════════════════════════════════════════
|
||||||
|
RC — release candidates for testing and validation
|
||||||
|
══════════════════════════════════════════════════════════════ -->
|
||||||
|
<update>
|
||||||
|
<name>MokoCassiopeia</name>
|
||||||
|
<description>MokoCassiopeia release candidate — testing only.</description>
|
||||||
|
<element>mokocassiopeia</element>
|
||||||
|
<type>template</type>
|
||||||
|
<client>site</client>
|
||||||
|
|
||||||
|
<version>03.09.06</version>
|
||||||
|
<creationDate>2026-04-07</creationDate>
|
||||||
|
<author>Jonathan Miller || Moko Consulting</author>
|
||||||
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
<copyright>(C)GNU General Public License Version 3 - 2026 Moko Consulting</copyright>
|
||||||
|
|
||||||
|
<infourl title='MokoCassiopeia RC'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/tag/release-candidate</infourl>
|
||||||
|
|
||||||
|
<downloads>
|
||||||
|
<downloadurl type='full' format='zip'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/release-candidate/mokocassiopeia-rc.zip</downloadurl>
|
||||||
|
</downloads>
|
||||||
|
<sha256>99b868a54466138d22a544d3e489559e7303960922c8eb3a142c504225b0e647</sha256>
|
||||||
|
|
||||||
|
<tags>
|
||||||
|
<tag>rc</tag>
|
||||||
|
</tags>
|
||||||
|
|
||||||
|
<maintainer>Moko Consulting</maintainer>
|
||||||
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
|
|
||||||
|
<targetplatform name='joomla' version='(5|6)\..*'/>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- ══════════════════════════════════════════════════════════════
|
||||||
|
DEVELOPMENT — latest dev branch builds, not for production
|
||||||
|
══════════════════════════════════════════════════════════════ -->
|
||||||
|
<update>
|
||||||
|
<name>MokoCassiopeia</name>
|
||||||
|
<description>MokoCassiopeia development build — unstable.</description>
|
||||||
|
<element>mokocassiopeia</element>
|
||||||
|
<type>template</type>
|
||||||
|
<client>site</client>
|
||||||
|
|
||||||
|
<version>03.09.07</version>
|
||||||
|
<creationDate>2026-04-07</creationDate>
|
||||||
|
<author>Jonathan Miller || Moko Consulting</author>
|
||||||
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
<copyright>(C)GNU General Public License Version 3 - 2026 Moko Consulting</copyright>
|
||||||
|
|
||||||
|
<infourl title='MokoCassiopeia Dev'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/tag/development</infourl>
|
||||||
|
|
||||||
|
<downloads>
|
||||||
|
<downloadurl type='full' format='zip'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/development/mokocassiopeia-dev.zip</downloadurl>
|
||||||
|
</downloads>
|
||||||
|
<sha256>b6403918c5f65f4f52b889fbe4bd217c903f0d9c2fcf90f8eb59df1e7b4b7333</sha256>
|
||||||
|
|
||||||
|
<tags>
|
||||||
|
<tag>development</tag>
|
||||||
|
</tags>
|
||||||
|
|
||||||
|
<maintainer>Moko Consulting</maintainer>
|
||||||
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
|
|
||||||
|
<targetplatform name='joomla' version='(5|6)\..*'/>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- ══════════════════════════════════════════════════════════════
|
||||||
|
ALPHA — early testing, expect breaking changes
|
||||||
|
══════════════════════════════════════════════════════════════ -->
|
||||||
|
<update>
|
||||||
|
<name>MokoCassiopeia</name>
|
||||||
|
<description>MokoCassiopeia alpha build — early testing.</description>
|
||||||
|
<element>mokocassiopeia</element>
|
||||||
|
<type>template</type>
|
||||||
|
<client>site</client>
|
||||||
|
|
||||||
|
<version>03.09.07</version>
|
||||||
|
<creationDate>2026-04-07</creationDate>
|
||||||
|
<author>Jonathan Miller || Moko Consulting</author>
|
||||||
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
<copyright>(C)GNU General Public License Version 3 - 2026 Moko Consulting</copyright>
|
||||||
|
|
||||||
|
<infourl title='MokoCassiopeia Alpha'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/tag/alpha</infourl>
|
||||||
|
|
||||||
|
<downloads>
|
||||||
|
<downloadurl type='full' format='zip'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/alpha/mokocassiopeia-alpha.zip</downloadurl>
|
||||||
|
</downloads>
|
||||||
|
<sha256>b5f6d073d126f0041ddd475e61bc4eaa050e060e9b51f4fe0e8a348f188c40b2</sha256>
|
||||||
|
|
||||||
|
<tags>
|
||||||
|
<tag>alpha</tag>
|
||||||
|
</tags>
|
||||||
|
|
||||||
|
<maintainer>Moko Consulting</maintainer>
|
||||||
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
|
|
||||||
|
<targetplatform name='joomla' version='(5|6)\..*'/>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- ══════════════════════════════════════════════════════════════
|
||||||
|
BETA — feature complete, testing for stability
|
||||||
|
══════════════════════════════════════════════════════════════ -->
|
||||||
|
<update>
|
||||||
|
<name>MokoCassiopeia</name>
|
||||||
|
<description>MokoCassiopeia beta build — feature complete, stability testing.</description>
|
||||||
|
<element>mokocassiopeia</element>
|
||||||
|
<type>template</type>
|
||||||
|
<client>site</client>
|
||||||
|
|
||||||
|
<version>03.09.07</version>
|
||||||
|
<creationDate>2026-04-07</creationDate>
|
||||||
|
<author>Jonathan Miller || Moko Consulting</author>
|
||||||
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
<copyright>(C)GNU General Public License Version 3 - 2026 Moko Consulting</copyright>
|
||||||
|
|
||||||
|
<infourl title='MokoCassiopeia Beta'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/tag/beta</infourl>
|
||||||
|
|
||||||
|
<downloads>
|
||||||
|
<downloadurl type='full' format='zip'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/beta/mokocassiopeia-beta.zip</downloadurl>
|
||||||
|
</downloads>
|
||||||
|
<sha256>b5f6d073d126f0041ddd475e61bc4eaa050e060e9b51f4fe0e8a348f188c40b2</sha256>
|
||||||
|
|
||||||
|
<tags>
|
||||||
|
<tag>beta</tag>
|
||||||
|
</tags>
|
||||||
|
|
||||||
|
<maintainer>Moko Consulting</maintainer>
|
||||||
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
|
|
||||||
|
<targetplatform name='joomla' version='(5|6)\..*'/>
|
||||||
|
</update>
|
||||||
|
|
||||||
</updates>
|
</updates>
|
||||||
|
|||||||
Reference in New Issue
Block a user