Merge pull request #82 from mokoconsulting-tech/copilot/fix-breaking-overrides
Simplify component.php to minimal layout with conditional analytics
This commit was merged in pull request #82.
This commit is contained in:
545
.github/CLAUDE.md
vendored
Normal file
545
.github/CLAUDE.md
vendored
Normal file
@@ -0,0 +1,545 @@
|
||||
# What This Repo Is
|
||||
|
||||
MokoCassiopeia is a modern, lightweight Joomla template that extends Cassiopeia (Joomla's default template) with enhanced features while maintaining maximum upgrade compatibility. It is used by Joomla 4.4.x and 5.x site administrators who want Font Awesome 7, Bootstrap 5 helpers, dark mode theming, and table of contents features without breaking core Joomla upgrades. This is NOT a standalone theme framework, NOT a template builder, and NOT a general-purpose UI library—it is specifically a Joomla site template extension that must be installed via Joomla's Extension Manager. Repository: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
|
||||
# Repo Structure
|
||||
|
||||
```
|
||||
MokoCassiopeia/
|
||||
├── .github/ # GitHub workflows (CI, testing, release), Copilot instructions
|
||||
├── docs/ # Comprehensive documentation (guides, philosophy, CSS reference)
|
||||
├── scripts/ # Build scripts (build-release.sh)
|
||||
├── src/ # MAIN WORKING DIRECTORY: template source files
|
||||
│ ├── index.php # Main template rendering file
|
||||
│ ├── templateDetails.xml # Joomla manifest (metadata, params, files)
|
||||
│ ├── joomla.asset.json # Web Asset Manager registration
|
||||
│ ├── language/ # Frontend language files (en-GB, en-US .ini and .sys.ini)
|
||||
│ ├── html/ # Alternative layout overrides (never replace defaults!)
|
||||
│ └── media/ # CSS, JS, images, fonts, vendor libraries
|
||||
├── templates/ # Color scheme templates for client customization
|
||||
├── tests/ # Codeception acceptance and unit tests
|
||||
├── phpcs.xml # PHP_CodeSniffer configuration (PSR-12 + Joomla standards)
|
||||
└── phpstan.neon # PHPStan static analysis configuration
|
||||
```
|
||||
|
||||
# File Header Requirements
|
||||
|
||||
## Header Format
|
||||
|
||||
All source files MUST include this standardized copyright header:
|
||||
|
||||
### PHP Files (Full Header)
|
||||
|
||||
```php
|
||||
<?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
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: MokoCassiopeia.Template
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
PATH: ./templates/mokocassiopeia/filename.php
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: Brief description of file purpose
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
```
|
||||
|
||||
### JavaScript Files
|
||||
|
||||
```javascript
|
||||
/* 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: ./media/templates/site/mokocassiopeia/js/filename.js
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: Brief description of file purpose
|
||||
*/
|
||||
|
||||
(function (win, doc) {
|
||||
"use strict";
|
||||
// Implementation
|
||||
})(window, document);
|
||||
```
|
||||
|
||||
### CSS Files
|
||||
|
||||
```css
|
||||
/* 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.Styles
|
||||
PATH: ./media/templates/site/mokocassiopeia/css/filename.css
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: Brief description of file purpose
|
||||
*/
|
||||
```
|
||||
|
||||
### Markdown Documentation
|
||||
|
||||
```markdown
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: MokoCassiopeia.Documentation
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
FILE: docs/FILENAME.md
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: Brief description
|
||||
-->
|
||||
```
|
||||
|
||||
## FILE INFORMATION Block Fields
|
||||
|
||||
- **DEFGROUP**: Top-level group (always `Joomla.Template.Site`)
|
||||
- **INGROUP**: Subgroup (e.g., `MokoCassiopeia.Template`, `MokoCassiopeia.Documentation`)
|
||||
- **REPO**: GitHub repository URL (required in docs, optional in code)
|
||||
- **PATH** or **FILE**: Relative path from repository root
|
||||
- **VERSION**: Semantic version `XX.YY.ZZ`
|
||||
- **BRIEF**: One-line description of file purpose
|
||||
|
||||
## Exempt Files
|
||||
|
||||
These file types DO NOT require headers:
|
||||
- `joomla.asset.json` and other JSON data files (metadata in `x-header` field instead)
|
||||
- Binary files (images, fonts, compiled assets)
|
||||
- Third-party vendor libraries in `src/media/vendor/`
|
||||
- Generated files (minified CSS/JS with `.min.` in name)
|
||||
- Empty placeholder files
|
||||
|
||||
## When to Use Full vs Minimal Header
|
||||
|
||||
- **Full header with GPL notice**: Required in all PHP files (use example above)
|
||||
- **Minimal header without GPL notice**: JavaScript and CSS files (shorter version shown above)
|
||||
- **Markdown format**: All documentation files in `docs/`
|
||||
|
||||
# Coding Standards
|
||||
|
||||
## Indentation
|
||||
|
||||
From `.editorconfig`:
|
||||
- **Default**: Tabs with 2-space visual width
|
||||
- **PHP**: Tabs (PSR-12 uses tabs, Joomla uses tabs)
|
||||
- **JavaScript**: Tabs with 2-space visual width
|
||||
- **CSS**: Tabs with 2-space visual width
|
||||
- **JSON/YAML**: Tabs with 2-space visual width
|
||||
- **Markdown**: Spaces (for compatibility), trim_trailing_whitespace = false
|
||||
- **Makefiles**: Always tabs
|
||||
|
||||
## Line Length
|
||||
|
||||
From `phpcs.xml`:
|
||||
- **General**: No strict limit (Generic.Files.LineLength excluded)
|
||||
- **Practical guideline**: Keep lines under 120 characters when reasonable
|
||||
- **Long lines accepted for**: URLs, array definitions, Joomla HTML helpers
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
### PHP (Joomla Standards + PSR-12)
|
||||
|
||||
- **Classes**: `PascalCase` (e.g., `TemplateHelper`)
|
||||
- **Methods**: `camelCase` (e.g., `getThemeOptions()`)
|
||||
- **Variables**: `$camelCase` or `$snake_case` (Joomla prefers snake_case for local vars)
|
||||
- **Constants**: `UPPER_SNAKE_CASE` (e.g., `THEME_LIGHT_MODE`)
|
||||
- **Files**: Lowercase with hyphens for layouts (e.g., `mobile.php`, `toc-left.php`)
|
||||
- **Private properties**: Prefix with underscore (e.g., `$_privateData`)
|
||||
|
||||
### JavaScript (ES6+)
|
||||
|
||||
- **Functions**: `camelCase` (e.g., `applyTheme()`)
|
||||
- **Constants**: `UPPER_SNAKE_CASE` or `camelCase` (e.g., `storageKey`)
|
||||
- **Classes**: `PascalCase` (e.g., `ThemeController`)
|
||||
- **Files**: Lowercase with hyphens (e.g., `template.js`, `menu-metismenu.js`)
|
||||
|
||||
### CSS
|
||||
|
||||
- **Classes**: Kebab-case (e.g., `.theme-toggle`, `.fab-button`)
|
||||
- **IDs**: Kebab-case (e.g., `#main-content`)
|
||||
- **CSS Variables**: Kebab-case with double hyphen prefix (e.g., `--color-primary`, `--body-bg`)
|
||||
- **Files**: Lowercase with dots and descriptive names (e.g., `light.standard.css`, `dark.custom.css`, `light.custom.css`)
|
||||
|
||||
### General File Naming
|
||||
|
||||
- **Alternative layouts**: Descriptive name + `.php` (e.g., `mobile.php`, `mainmenu.php`, `toc-left.php`)
|
||||
- **NEVER use**: `default.php` (replaces core layout—FORBIDDEN)
|
||||
- **Scripts**: Lowercase with hyphens (e.g., `build-release.sh`)
|
||||
|
||||
## Primary Language
|
||||
|
||||
- **PHP**: All new template logic, Joomla integration code
|
||||
- **JavaScript**: All new client-side functionality (ES6+ syntax)
|
||||
- **CSS**: All new styling (CSS variables for theming)
|
||||
- **Bash**: Build and automation scripts (`.sh` files)
|
||||
|
||||
# Language-Specific Requirements
|
||||
|
||||
## PHP
|
||||
|
||||
### Type Hints
|
||||
|
||||
Required for all function signatures in PHP 8.0+ code:
|
||||
|
||||
```php
|
||||
public function getThemeOption(string $key, mixed $default = null): mixed
|
||||
{
|
||||
return $this->params->get($key, $default);
|
||||
}
|
||||
```
|
||||
|
||||
### Docstring Format
|
||||
|
||||
Use DocBlocks for all classes, methods, and functions:
|
||||
|
||||
```php
|
||||
/**
|
||||
* Apply theme settings to document
|
||||
*
|
||||
* @param string $theme Theme name (light|dark)
|
||||
* @param object $params Template parameters
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public function applyTheme(string $theme, object $params): void
|
||||
{
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
Required DocBlock sections:
|
||||
- Brief description (first line)
|
||||
- `@param` for each parameter (type, name, description)
|
||||
- `@return` for return value
|
||||
- `@since` for version introduced
|
||||
- `@throws` if exceptions are thrown
|
||||
|
||||
### Script Structure
|
||||
|
||||
All PHP files must follow this pattern:
|
||||
|
||||
```php
|
||||
<?php
|
||||
/* [Copyright header - see above] */
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
// Other imports
|
||||
|
||||
/** @var Joomla\CMS\Document\HtmlDocument $this */
|
||||
|
||||
// Constants (if needed)
|
||||
const THEME_LIGHT = 'light';
|
||||
|
||||
// Implementation
|
||||
$app = Factory::getApplication();
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Use `defined('_JEXEC') or die;` at the start of EVERY PHP file
|
||||
- Catch exceptions with specific types: `catch (RuntimeException $e)`
|
||||
- Log errors using Joomla's logging: `JLog::add($message, JLog::ERROR)`
|
||||
- Never expose internal paths or sensitive data in error messages
|
||||
- Use `try-catch` blocks for database operations
|
||||
|
||||
## JavaScript
|
||||
|
||||
### Type Hints
|
||||
|
||||
Use JSDoc type annotations:
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Apply theme to document root
|
||||
* @param {"light"|"dark"} theme - Theme name
|
||||
* @returns {void}
|
||||
*/
|
||||
function applyTheme(theme) {
|
||||
root.setAttribute("data-bs-theme", theme);
|
||||
}
|
||||
```
|
||||
|
||||
### Docstring Format
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Toggle theme between light and dark modes
|
||||
*
|
||||
* Toggles the theme attribute on the root element and updates
|
||||
* localStorage with the new preference.
|
||||
*
|
||||
* @param {Event} event - Click event from toggle button
|
||||
* @returns {void}
|
||||
*/
|
||||
function toggleTheme(event) {
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
### Script Structure
|
||||
|
||||
```javascript
|
||||
/* [Copyright header - see above] */
|
||||
|
||||
(function (win, doc) {
|
||||
"use strict";
|
||||
|
||||
// Constants
|
||||
const STORAGE_KEY = "theme";
|
||||
const root = doc.documentElement;
|
||||
|
||||
// Private functions
|
||||
function applyTheme(theme) {
|
||||
// Implementation
|
||||
}
|
||||
|
||||
// Public API (if needed)
|
||||
win.TemplateAPI = {
|
||||
applyTheme: applyTheme
|
||||
};
|
||||
|
||||
})(window, document);
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Always use `"use strict";` at the top of IIFE
|
||||
- Wrap localStorage access in try-catch (may throw in private mode)
|
||||
- Use `console.error()` for logging errors (not `console.log()`)
|
||||
- Validate function parameters at the start
|
||||
- Return early on error conditions
|
||||
|
||||
## CSS
|
||||
|
||||
No specific requirements beyond standard CSS syntax. Use CSS variables for theming (see `docs/CSS_VARIABLES.md`).
|
||||
|
||||
# Commit Message Format
|
||||
|
||||
No `.gitmessage` file exists. Follow this format:
|
||||
|
||||
```
|
||||
Brief summary (50 chars or less)
|
||||
|
||||
Detailed explanation if needed:
|
||||
- What changed
|
||||
- Why it changed
|
||||
- Impact of the change
|
||||
|
||||
Refs: #issue-number (if applicable)
|
||||
```
|
||||
|
||||
**Good examples:**
|
||||
|
||||
```
|
||||
Fix language file installation paths in templateDetails.xml
|
||||
|
||||
- Remove folder attribute from <languages> section
|
||||
- Update paths to be relative from package root
|
||||
- Ensures proper installation to JOOMLA_ROOT/language/
|
||||
|
||||
Refs: #42
|
||||
```
|
||||
|
||||
```
|
||||
Add dark mode color variables for custom themes
|
||||
|
||||
- Add --color-primary-dark, --color-secondary-dark
|
||||
- Update theme toggle to respect custom colors
|
||||
- Document new variables in CSS_VARIABLES.md
|
||||
```
|
||||
|
||||
**Bad examples:**
|
||||
|
||||
```
|
||||
Update files
|
||||
```
|
||||
|
||||
```
|
||||
WIP
|
||||
```
|
||||
|
||||
```
|
||||
Fixed bug
|
||||
```
|
||||
|
||||
## Commit Rules
|
||||
|
||||
- Keep subject line under 50 characters
|
||||
- Use imperative mood ("Add feature" not "Added feature")
|
||||
- Capitalize first letter
|
||||
- No period at end of subject
|
||||
- Blank line between subject and body
|
||||
- Wrap body at 72 characters
|
||||
- Explain WHAT and WHY, not HOW (code shows HOW)
|
||||
|
||||
# Running Validation
|
||||
|
||||
Before committing, run these commands from repository root:
|
||||
|
||||
```bash
|
||||
# 1. PHP CodeSniffer (code style)
|
||||
phpcs --standard=phpcs.xml src/
|
||||
|
||||
# 2. PHPStan (static analysis)
|
||||
phpstan analyse --configuration=phpstan.neon
|
||||
|
||||
# 3. XML validation (template manifest)
|
||||
xmllint --noout src/templateDetails.xml
|
||||
|
||||
# 4. Check file headers (if script exists)
|
||||
# ./scripts/validate-headers.sh
|
||||
|
||||
# 5. Run tests (if Codeception installed)
|
||||
codecept run
|
||||
```
|
||||
|
||||
If you don't have tools installed:
|
||||
|
||||
```bash
|
||||
# Install PHP quality tools globally
|
||||
composer global require "squizlabs/php_codesniffer:^3.0" --with-all-dependencies
|
||||
composer global require "phpstan/phpstan:^1.0" --with-all-dependencies
|
||||
|
||||
# Install Codeception
|
||||
composer global require "codeception/codeception" --with-all-dependencies
|
||||
```
|
||||
|
||||
**Note:** CI runs these automatically on push, but running locally saves time.
|
||||
|
||||
# Contribution Workflow
|
||||
|
||||
1. **Fork** the repository on GitHub
|
||||
2. **Clone** your fork locally: `git clone https://github.com/YOUR-USERNAME/MokoCassiopeia.git`
|
||||
3. **Create branch** from current development branch: `git checkout -b feature/your-feature-name`
|
||||
- Branch naming: `feature/description`, `fix/issue-description`, `docs/topic`
|
||||
4. **Make changes** in the `src/` directory (this is the working copy)
|
||||
5. **Run validation** (see commands above)
|
||||
6. **Commit changes** with descriptive messages
|
||||
7. **Push to your fork**: `git push origin feature/your-feature-name`
|
||||
8. **Open Pull Request** on GitHub targeting the appropriate base branch
|
||||
|
||||
## Branch Strategy
|
||||
|
||||
- **main**: Stable releases only (protected)
|
||||
- **version/XX.YY**: Version-specific branches (protected)
|
||||
- **dev/XX.YY.ZZ**: Active development branches
|
||||
- **rc/XX.YY.ZZ**: Release candidate branches
|
||||
- **feature/**, **fix/**, **docs/**: Working branches
|
||||
|
||||
## Merge Strategy
|
||||
|
||||
- Pull requests use **squash merge** to main/version branches
|
||||
- Commits go to development branches first, then promoted through rc → version → main
|
||||
- NEVER commit directly to protected branches (main, version/*)
|
||||
|
||||
# PR Checklist
|
||||
|
||||
Before opening a pull request:
|
||||
|
||||
- [ ] Code follows Joomla coding standards (PSR-12 + Joomla)
|
||||
- [ ] All files have proper copyright headers
|
||||
- [ ] PHP files have `defined('_JEXEC') or die;` at top
|
||||
- [ ] No `default.php` layout files (use alternative layout names)
|
||||
- [ ] Language files: metadata in `.sys.ini`, runtime strings in `.ini`
|
||||
- [ ] Assets registered in `joomla.asset.json` (not inline in template)
|
||||
- [ ] CSS uses CSS variables for colors (supports light/dark themes)
|
||||
- [ ] PHP CodeSniffer passes: `phpcs --standard=phpcs.xml src/`
|
||||
- [ ] PHPStan passes: `phpstan analyse --configuration=phpstan.neon`
|
||||
- [ ] Tested in Joomla 4.4.x AND 5.x
|
||||
- [ ] Tested in light mode AND dark mode
|
||||
- [ ] Documentation updated if adding features
|
||||
- [ ] No hardcoded absolute paths (use Joomla path constants)
|
||||
- [ ] No credentials, API keys, or secrets in code
|
||||
- [ ] Version numbers NOT added to revision history tables
|
||||
- [ ] Alternative layouts documented with activation instructions
|
||||
|
||||
# What NOT to Do
|
||||
|
||||
## Absolutely Forbidden
|
||||
|
||||
- ❌ **NEVER create `default.php` layout files** - This replaces core layouts and breaks upgrades. Use alternative layout names like `mobile.php`, `mainmenu.php`
|
||||
- ❌ **NEVER commit without copyright headers** - All source files must have proper headers
|
||||
- ❌ **NEVER add `folder` attribute to `<languages>` section in templateDetails.xml** - Language file paths must be relative from package root
|
||||
- ❌ **NEVER put template metadata in `.ini` files** - Template name and description belong ONLY in `.sys.ini` files
|
||||
- ❌ **NEVER hardcode absolute paths** - Use Joomla path constants (`JPATH_ROOT`, `JPATH_SITE`, etc.)
|
||||
- ❌ **NEVER commit credentials or API keys** - Use Joomla's configuration management
|
||||
- ❌ **NEVER modify vendor libraries** - Third-party code in `src/media/vendor/` is immutable
|
||||
- ❌ **NEVER remove `defined('_JEXEC') or die;`** - This is a critical security check
|
||||
|
||||
## Strong Discouragements
|
||||
|
||||
- ⚠️ Avoid committing without running `phpcs` and `phpstan`
|
||||
- ⚠️ Avoid adding version numbers to revision history tables (use VERSION metadata instead)
|
||||
- ⚠️ Avoid inline styles or scripts (register assets in `joomla.asset.json`)
|
||||
- ⚠️ Avoid hardcoded color values (use CSS variables: `--color-primary`, etc.)
|
||||
- ⚠️ Avoid direct commits to `main` or `version/*` branches (use PRs)
|
||||
- ⚠️ Avoid changing more than one concern per commit
|
||||
- ⚠️ Avoid long lines when reasonable (aim for 120 chars)
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Using spaces instead of tabs (check `.editorconfig`)
|
||||
- Forgetting `SPDX-License-Identifier: GPL-3.0-or-later` in headers
|
||||
- Mixing frontend strings (.ini) and metadata strings (.sys.ini)
|
||||
- Creating layout overrides that replace defaults instead of providing alternatives
|
||||
- Not testing in both Joomla 4.x and 5.x
|
||||
- Not testing light/dark mode theme switching
|
||||
|
||||
# Key Policy Documents
|
||||
|
||||
Must-read before contributing:
|
||||
|
||||
1. **[OVERRIDE_PHILOSOPHY.md](./docs/OVERRIDE_PHILOSOPHY.md)** - CRITICAL: Explains why we NEVER replace default layouts and how alternative layouts work
|
||||
2. **[QUICK_START.md](./docs/QUICK_START.md)** - 5-minute setup guide for first-time contributors
|
||||
3. **[JOOMLA_DEVELOPMENT.md](./docs/JOOMLA_DEVELOPMENT.md)** - Complete development guide: testing, quality checks, deployment
|
||||
4. **[WORKFLOW_GUIDE.md](./docs/WORKFLOW_GUIDE.md)** - Git workflow, branching strategy, CI/CD pipelines
|
||||
5. **[CSS_VARIABLES.md](./docs/CSS_VARIABLES.md)** - Complete reference for theme customization
|
||||
6. **[CONTRIBUTING.md](./CONTRIBUTING.md)** - Formal contribution guidelines and governance
|
||||
7. **[SECURITY.md](./SECURITY.md)** - Security reporting procedures (never report publicly)
|
||||
8. **[MODULE_OVERRIDES.md](./docs/MODULE_OVERRIDES.md)** - Documentation of all alternative layouts and activation instructions
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- **README.md** - Overview, features, installation, configuration
|
||||
- **CHANGELOG.md** - Version history and release notes
|
||||
- **GOVERNANCE.md** - Project governance model and decision-making
|
||||
- **CODE_OF_CONDUCT.md** - Community standards and expectations
|
||||
346
.github/copilot-instructions.md
vendored
Normal file
346
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,346 @@
|
||||
# GitHub Copilot Instructions for MokoCassiopeia
|
||||
|
||||
## Repository Context
|
||||
|
||||
MokoCassiopeia is a modern, lightweight Joomla template that extends Cassiopeia (Joomla's default template). It follows a strict **non-replacement philosophy** for maximum upgrade compatibility.
|
||||
|
||||
**Key Characteristics:**
|
||||
- Joomla 4.4.x and 5.x compatible
|
||||
- PHP 8.0+ required
|
||||
- Built on Cassiopeia template
|
||||
- Minimal core template overrides
|
||||
- Alternative layout naming convention (not default replacements)
|
||||
- GPL-3.0-or-later license
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
MokoCassiopeia/
|
||||
├── .github/ # GitHub workflows and configuration
|
||||
├── docs/ # Comprehensive documentation
|
||||
├── scripts/ # Build and deployment scripts
|
||||
├── src/ # Template source files (main working directory)
|
||||
│ ├── index.php # Main template file
|
||||
│ ├── templateDetails.xml # Joomla template manifest
|
||||
│ ├── joomla.asset.json # Web Asset Manager configuration
|
||||
│ ├── language/ # Frontend language files (en-GB, en-US)
|
||||
│ ├── html/ # Alternative layout overrides
|
||||
│ └── media/ # CSS, JS, images, fonts, vendors
|
||||
├── templates/ # Custom color scheme templates
|
||||
└── tests/ # Codeception tests
|
||||
```
|
||||
|
||||
## Critical Conventions
|
||||
|
||||
### 1. Override Philosophy: Alternative Layouts Only
|
||||
|
||||
**NEVER replace default layouts.** All overrides must use alternative layout names.
|
||||
|
||||
✅ **Correct:**
|
||||
- `mobile.php` (alternative layout)
|
||||
- `mainmenu.php` (alternative layout for mod_menu)
|
||||
- `toc-left.php`, `toc-right.php` (alternative layouts with TOC)
|
||||
|
||||
❌ **Incorrect:**
|
||||
- `default.php` (replaces core layout - FORBIDDEN)
|
||||
- Any file that replaces Cassiopeia's default behavior
|
||||
|
||||
**Rationale:** Ensures Joomla core updates don't break the template and gives users choice.
|
||||
|
||||
### 2. File Headers
|
||||
|
||||
All source files must include standardized copyright headers:
|
||||
|
||||
```php
|
||||
<?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
|
||||
*
|
||||
* @defgroup Joomla.Template.Site
|
||||
* @ingroup MokoCassiopeia.Template
|
||||
* @brief [Brief description]
|
||||
* @version [Version number]
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
```
|
||||
|
||||
### 3. Language Files
|
||||
|
||||
**Key Rules:**
|
||||
- Template metadata (name, description) goes in `.sys.ini` files ONLY
|
||||
- Frontend runtime strings go in `.ini` files
|
||||
- Language files location: `src/language/{locale}/`
|
||||
- NO `folder` attribute in `<languages>` section of templateDetails.xml
|
||||
- Paths must be relative from package root (e.g., `language/en-GB/tpl_mokocassiopeia.sys.ini`)
|
||||
|
||||
**Example templateDetails.xml:**
|
||||
```xml
|
||||
<languages folder="language">
|
||||
<language tag="en-GB">en-GB/tpl_mokocassiopeia.ini</language>
|
||||
<language tag="en-GB">en-GB/tpl_mokocassiopeia.sys.ini</language>
|
||||
</languages>
|
||||
```
|
||||
|
||||
### 4. Hardcoded XML Description
|
||||
|
||||
The template description in `templateDetails.xml` is **hardcoded using CDATA**, not a language constant:
|
||||
|
||||
```xml
|
||||
<description><![CDATA[Modern, lightweight Joomla template...]]></description>
|
||||
```
|
||||
|
||||
**Rationale:** Ensures immediate availability during installation without language file dependency.
|
||||
|
||||
### 5. Version Format
|
||||
|
||||
Follow semantic versioning: `XX.YY.ZZ`
|
||||
- XX: Major version
|
||||
- YY: Minor version
|
||||
- ZZ: Patch version
|
||||
|
||||
**Examples:** `03.06.03`, `03.08.04`
|
||||
|
||||
## Coding Standards
|
||||
|
||||
### PHP
|
||||
|
||||
- **PSR-12 compliant** where not conflicting with Joomla standards
|
||||
- **Joomla Coding Standards** for Joomla-specific code
|
||||
- Use `defined('_JEXEC') or die;` at the top of every PHP file
|
||||
- Type hints for PHP 8.0+ features
|
||||
- Strict types declarations where appropriate
|
||||
|
||||
### JavaScript
|
||||
|
||||
- **ES6+** syntax
|
||||
- Use `'use strict';`
|
||||
- Prefer `const` and `let` over `var`
|
||||
- Document functions with JSDoc comments
|
||||
- Integrate with Joomla's Web Asset Manager
|
||||
|
||||
### CSS
|
||||
|
||||
- **CSS Variables** for theming (see `docs/CSS_VARIABLES.md`)
|
||||
- Light/dark mode support via `data-bs-theme` attribute
|
||||
- Bootstrap 5 utility classes
|
||||
- Mobile-first responsive design
|
||||
- Namespace custom classes to avoid conflicts
|
||||
|
||||
### Asset Management
|
||||
|
||||
All assets must be registered in `joomla.asset.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "template.mokocassiopeia.custom",
|
||||
"version": "1.0.0",
|
||||
"description": "Custom asset",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": ["core"],
|
||||
"js": ["js/custom.js"],
|
||||
"css": ["css/custom.css"]
|
||||
}
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Branching Strategy
|
||||
|
||||
- **Development:** Work on feature branches
|
||||
- **Branch naming:** `feature/description`, `fix/issue-description`
|
||||
- **Protected branches:** Cannot commit directly to `main` or version branches
|
||||
- See `docs/WORKFLOW_GUIDE.md` for complete workflow
|
||||
|
||||
### Commit Messages
|
||||
|
||||
```
|
||||
Brief summary (50 chars or less)
|
||||
|
||||
Detailed explanation if needed:
|
||||
- What changed
|
||||
- Why it changed
|
||||
- Impact of the change
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Fix language file installation paths in templateDetails.xml
|
||||
|
||||
- Remove folder attribute from <languages> section
|
||||
- Update paths to be relative from package root
|
||||
- Ensures proper installation to JOOMLA_ROOT/language/
|
||||
```
|
||||
|
||||
### Quality Checks
|
||||
|
||||
Before committing:
|
||||
1. **PHP CodeSniffer:** `phpcs --standard=Joomla src/`
|
||||
2. **PHPStan:** Static analysis for PHP code
|
||||
3. **Pre-commit hooks:** Automatically run validation
|
||||
|
||||
## Testing
|
||||
|
||||
### Manual Testing
|
||||
- Test in Joomla 4.4.x and 5.x
|
||||
- Test on PHP 8.0, 8.1, 8.2
|
||||
- Test light/dark mode switching
|
||||
- Test responsive layouts (mobile/tablet/desktop)
|
||||
- Test alternative layouts activation
|
||||
|
||||
### Test Environment
|
||||
- Use local Joomla installation
|
||||
- See `docs/JOOMLA_DEVELOPMENT.md` for setup
|
||||
|
||||
## Documentation Standards
|
||||
|
||||
### Markdown Files
|
||||
|
||||
All documentation must include:
|
||||
|
||||
1. **Copyright header**
|
||||
```markdown
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: [Group]
|
||||
INGROUP: [Subgroup]
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
FILE: [filename]
|
||||
VERSION: [version]
|
||||
BRIEF: [Brief description]
|
||||
-->
|
||||
```
|
||||
|
||||
2. **Metadata section** (at end)
|
||||
3. **Revision history table** (at end)
|
||||
|
||||
### Code Comments
|
||||
|
||||
- Use DocBlocks for functions and classes
|
||||
- Explain "why" not just "what"
|
||||
- Keep comments up-to-date with code changes
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Theme System Integration
|
||||
|
||||
Use CSS variables for colors:
|
||||
```css
|
||||
:root[data-bs-theme="light"] {
|
||||
--color-primary: #1e40af;
|
||||
--body-bg: #ffffff;
|
||||
}
|
||||
|
||||
:root[data-bs-theme="dark"] {
|
||||
--color-primary: #60a5fa;
|
||||
--body-bg: #1f2937;
|
||||
}
|
||||
```
|
||||
|
||||
### Alternative Layout Structure
|
||||
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* Alternative layout: mobile
|
||||
* Activated via: Advanced → Alternative Layout → "mobile"
|
||||
*/
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
|
||||
// Layout implementation
|
||||
?>
|
||||
```
|
||||
|
||||
### JavaScript Asset Loading
|
||||
|
||||
```javascript
|
||||
// Register in joomla.asset.json, then use:
|
||||
Joomla.getOptions('template.mokocassiopeia.options');
|
||||
```
|
||||
|
||||
## Build and Release
|
||||
|
||||
### Local Build
|
||||
```bash
|
||||
cd scripts
|
||||
./build-release.sh
|
||||
```
|
||||
|
||||
### Automated Release
|
||||
- Tags trigger GitHub Actions workflow
|
||||
- Format: `XX.YY.ZZ`
|
||||
- Generates ZIP packages with checksums
|
||||
- Updates `updates.xml` automatically
|
||||
|
||||
## Important Don'ts
|
||||
|
||||
❌ **Never:**
|
||||
- Replace default Joomla layouts (use alternative layouts)
|
||||
- Commit without running code quality checks
|
||||
- Add version numbers to revision history (use VERSION metadata)
|
||||
- Hardcode absolute paths (use Joomla path constants)
|
||||
- Remove copyright headers
|
||||
- Modify `vendor/` directory contents
|
||||
- Change language constants location (.sys.ini vs .ini)
|
||||
- Add `folder` attribute to `<languages>` in templateDetails.xml
|
||||
|
||||
## Important Do's
|
||||
|
||||
✅ **Always:**
|
||||
- Use alternative layout names (mobile.php, mainmenu.php, etc.)
|
||||
- Include copyright headers in all files
|
||||
- Test in both Joomla 4.x and 5.x
|
||||
- Test light/dark mode themes
|
||||
- Update documentation when changing functionality
|
||||
- Follow semantic versioning
|
||||
- Register assets in joomla.asset.json
|
||||
- Use CSS variables for theming
|
||||
- Keep minimal overrides philosophy
|
||||
- Document activation steps for alternative layouts
|
||||
|
||||
## Key Documentation References
|
||||
|
||||
- **Quick Start:** `docs/QUICK_START.md` - First-time setup
|
||||
- **Override Philosophy:** `docs/OVERRIDE_PHILOSOPHY.md` - Critical reading
|
||||
- **Development Guide:** `docs/JOOMLA_DEVELOPMENT.md` - Complete dev workflow
|
||||
- **CSS Variables:** `docs/CSS_VARIABLES.md` - Theming reference
|
||||
- **Workflow Guide:** `docs/WORKFLOW_GUIDE.md` - Git workflow
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Follow `SECURITY.md` for security issues
|
||||
- Never commit credentials or API keys
|
||||
- Validate and sanitize all user inputs
|
||||
- Use Joomla's security features (CSRF tokens, etc.)
|
||||
- Keep dependencies updated
|
||||
|
||||
## License Compliance
|
||||
|
||||
All code contributions must be:
|
||||
- GPL-3.0-or-later compatible
|
||||
- Properly attributed (third-party code)
|
||||
- Include SPDX license identifiers
|
||||
- Maintain existing copyright notices
|
||||
|
||||
## Contact and Support
|
||||
|
||||
- **Issues:** GitHub Issues
|
||||
- **Discussions:** GitHub Discussions
|
||||
- **Security:** Follow SECURITY.md procedures
|
||||
- **Maintainer:** Moko Consulting Engineering
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-03-04
|
||||
**Repository:** https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
**Version:** 03.08.04
|
||||
147
.github/workflows/auto-update-sha.yml
vendored
Normal file
147
.github/workflows/auto-update-sha.yml
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: GitHub.Workflow
|
||||
# INGROUP: MokoCassiopeia.Automation
|
||||
# REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
# PATH: /.github/workflows/auto-update-sha.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Automatically update SHA-256 hash in updates.xml after release
|
||||
# NOTE: Ensures updates.xml stays synchronized with release packages
|
||||
|
||||
name: Auto-Update SHA Hash
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to update SHA for (e.g., 03.08.03)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
update-sha:
|
||||
name: Update SHA-256 Hash in updates.xml
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: main
|
||||
|
||||
- name: Get release tag
|
||||
id: tag
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
TAG="${{ inputs.tag }}"
|
||||
else
|
||||
TAG="${{ github.event.release.tag_name }}"
|
||||
fi
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo "Processing release: ${TAG}"
|
||||
|
||||
- name: Download release package
|
||||
run: |
|
||||
TAG="${{ steps.tag.outputs.tag }}"
|
||||
PACKAGE_NAME="mokocassiopeia-src-${TAG}.zip"
|
||||
DOWNLOAD_URL="https://github.com/${{ github.repository }}/releases/download/${TAG}/${PACKAGE_NAME}"
|
||||
|
||||
echo "Downloading: ${DOWNLOAD_URL}"
|
||||
curl -L -o "${PACKAGE_NAME}" "${DOWNLOAD_URL}"
|
||||
|
||||
if [ ! -f "${PACKAGE_NAME}" ]; then
|
||||
echo "Error: Failed to download package"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "PACKAGE_NAME=${PACKAGE_NAME}" >> $GITHUB_ENV
|
||||
|
||||
- name: Calculate SHA-256 hash
|
||||
id: sha
|
||||
run: |
|
||||
SHA256_HASH=$(sha256sum "${PACKAGE_NAME}" | cut -d' ' -f1)
|
||||
echo "sha256=${SHA256_HASH}" >> $GITHUB_OUTPUT
|
||||
echo "SHA-256 Hash: ${SHA256_HASH}"
|
||||
|
||||
- name: Update updates.xml
|
||||
run: |
|
||||
TAG="${{ steps.tag.outputs.tag }}"
|
||||
SHA256="${{ steps.sha.outputs.sha256 }}"
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
|
||||
# Update version
|
||||
sed -i "s|<version>.*</version>|<version>${TAG}</version>|" updates.xml
|
||||
|
||||
# Update creation date
|
||||
sed -i "s|<creationDate>.*</creationDate>|<creationDate>${DATE}</creationDate>|" updates.xml
|
||||
|
||||
# Update download URL
|
||||
sed -i "s|<downloadurl type='full' format='zip'>.*</downloadurl>|<downloadurl type='full' format='zip'>https://github.com/${{ github.repository }}/releases/download/${TAG}/mokocassiopeia-src-${TAG}.zip</downloadurl>|" updates.xml
|
||||
|
||||
# Update or add SHA-256 hash
|
||||
if grep -q "<sha256>" updates.xml; then
|
||||
sed -i "s|<sha256>.*</sha256>|<sha256>sha256:${SHA256}</sha256>|" updates.xml
|
||||
else
|
||||
# Add SHA-256 after downloadurl
|
||||
sed -i "/<\/downloadurl>/a\ <sha256>sha256:${SHA256}<\/sha256>" updates.xml
|
||||
fi
|
||||
|
||||
echo "Updated updates.xml with:"
|
||||
echo " Version: ${TAG}"
|
||||
echo " Date: ${DATE}"
|
||||
echo " SHA-256: ${SHA256}"
|
||||
|
||||
- name: Check for changes
|
||||
id: changes
|
||||
run: |
|
||||
if git diff --quiet updates.xml; then
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No changes to updates.xml"
|
||||
else
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "Changes detected in updates.xml"
|
||||
git diff updates.xml
|
||||
fi
|
||||
|
||||
- name: Commit and push changes
|
||||
if: steps.changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
TAG="${{ steps.tag.outputs.tag }}"
|
||||
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
|
||||
git add updates.xml
|
||||
git commit -m "chore: Update SHA-256 hash for release ${TAG}
|
||||
|
||||
Auto-generated by auto-update-sha workflow
|
||||
SHA-256: ${{ steps.sha.outputs.sha256 }}"
|
||||
|
||||
git push origin main
|
||||
|
||||
echo "Successfully updated updates.xml with SHA-256 hash for release ${TAG}"
|
||||
|
||||
- name: Summary
|
||||
if: steps.changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
echo "### SHA-256 Hash Updated Successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Release: ${{ steps.tag.outputs.tag }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- SHA-256: \`${{ steps.sha.outputs.sha256 }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- File: updates.xml" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "The Joomla update server will now provide the correct package hash." >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Summary (no changes)
|
||||
if: steps.changes.outputs.has_changes == 'false'
|
||||
run: |
|
||||
echo "### No Updates Needed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "updates.xml already contains the correct SHA-256 hash for release ${{ steps.tag.outputs.tag }}" >> $GITHUB_STEP_SUMMARY
|
||||
210
.github/workflows/release.yml
vendored
Normal file
210
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
# 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
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: GitHub.Workflow
|
||||
# INGROUP: MokoCassiopeia.Release
|
||||
# REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
# PATH: /.github/workflows/release.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Automated release workflow for MokoCassiopeia Joomla template
|
||||
# NOTE: Creates release packages and publishes to GitHub Releases
|
||||
|
||||
name: Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9][0-9].[0-9][0-9].[0-9][0-9]'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Release version (e.g., 03.08.03)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Mark as pre-release'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build Release Package
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.1'
|
||||
extensions: mbstring, xml, zip
|
||||
tools: composer:v2
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
VERSION="${{ inputs.version }}"
|
||||
else
|
||||
VERSION=${GITHUB_REF#refs/tags/}
|
||||
fi
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
echo "Building version: ${VERSION}"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
if [ -f "composer.json" ]; then
|
||||
composer install --no-dev --optimize-autoloader
|
||||
fi
|
||||
|
||||
- name: Update version in manifest files
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
# Update version in templateDetails.xml
|
||||
sed -i "s/<version>.*<\/version>/<version>${VERSION}<\/version>/g" src/templateDetails.xml
|
||||
# Update version in updates.xml
|
||||
sed -i "s/<version>.*<\/version>/<version>${VERSION}<\/version>/g" updates.xml
|
||||
# Update creation date to today
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
sed -i "s/<creationDate>.*<\/creationDate>/<creationDate>${DATE}<\/creationDate>/g" src/templateDetails.xml
|
||||
sed -i "s/<creationDate>.*<\/creationDate>/<creationDate>${DATE}<\/creationDate>/g" updates.xml
|
||||
|
||||
- name: Create package structure
|
||||
run: |
|
||||
mkdir -p build/package
|
||||
|
||||
# Copy template files from src (excluding media directory)
|
||||
rsync -av --exclude='media' src/ build/package/
|
||||
|
||||
# Copy media files from src/media to package/media directory
|
||||
mkdir -p build/package/media
|
||||
rsync -av src/media/ build/package/media/
|
||||
|
||||
- name: Create source ZIP package
|
||||
run: |
|
||||
cd build/package
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
ZIP_NAME="mokocassiopeia-src-${VERSION}.zip"
|
||||
zip -r "../${ZIP_NAME}" .
|
||||
cd ../..
|
||||
echo "ZIP_NAME=${ZIP_NAME}" >> $GITHUB_ENV
|
||||
echo "Created package: ${ZIP_NAME}"
|
||||
|
||||
- name: Generate checksums
|
||||
run: |
|
||||
cd build
|
||||
sha256sum "${ZIP_NAME}" > "${ZIP_NAME}.sha256"
|
||||
md5sum "${ZIP_NAME}" > "${ZIP_NAME}.md5"
|
||||
|
||||
# Extract just the hash for updates.xml
|
||||
SHA256_HASH=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1)
|
||||
echo "SHA256_HASH=${SHA256_HASH}" >> $GITHUB_ENV
|
||||
echo "SHA-256: ${SHA256_HASH}"
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-package
|
||||
path: |
|
||||
build/*.zip
|
||||
build/*.sha256
|
||||
build/*.md5
|
||||
|
||||
release:
|
||||
name: Create GitHub Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release-package
|
||||
path: ./artifacts
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
VERSION="${{ inputs.version }}"
|
||||
else
|
||||
VERSION=${GITHUB_REF#refs/tags/}
|
||||
fi
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Extract changelog
|
||||
id: changelog
|
||||
run: |
|
||||
if [ -f "CHANGELOG.md" ]; then
|
||||
# Extract changelog for this version
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
awk "/## \[${VERSION}\]/,/## \[/{if(/## \[${VERSION}\]/)print;else if(/## \[/)exit;else print}" CHANGELOG.md > release_notes.md
|
||||
|
||||
if [ ! -s release_notes.md ]; then
|
||||
echo "No specific changelog found for version ${VERSION}" > release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
echo "Please refer to the full CHANGELOG.md for details." >> release_notes.md
|
||||
fi
|
||||
else
|
||||
echo "Release version ${{ steps.version.outputs.version }}" > release_notes.md
|
||||
fi
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ steps.version.outputs.version }}
|
||||
name: Release ${{ steps.version.outputs.version }}
|
||||
body_path: release_notes.md
|
||||
draft: false
|
||||
prerelease: ${{ inputs.prerelease || false }}
|
||||
files: |
|
||||
artifacts/*.zip
|
||||
artifacts/*.sha256
|
||||
artifacts/*.md5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Release summary
|
||||
run: |
|
||||
echo "### Release Created Successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Version: ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Repository: $GITHUB_REPOSITORY" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Tag: ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Pre-release: ${{ inputs.prerelease || false }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Package files:" >> $GITHUB_STEP_SUMMARY
|
||||
ls -lh artifacts/ >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Next Steps" >> $GITHUB_STEP_SUMMARY
|
||||
echo "1. Verify the release at: https://github.com/$GITHUB_REPOSITORY/releases/tag/${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "2. Update updates.xml with the SHA-256 hash from the .sha256 file" >> $GITHUB_STEP_SUMMARY
|
||||
echo "3. Test the installation package" >> $GITHUB_STEP_SUMMARY
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -208,9 +208,13 @@ htdocs/logs/
|
||||
# ============================================================
|
||||
# Template Customizations
|
||||
# ============================================================
|
||||
# Ignore custom color scheme files to prevent fork-specific customizations
|
||||
src/media/css/colors/light/colors_custom.css
|
||||
src/media/css/colors/dark/colors_custom.css
|
||||
# Ignore custom theme files to prevent fork-specific customizations
|
||||
src/media/css/theme/light.custom.css
|
||||
src/media/css/theme/dark.custom.css
|
||||
|
||||
# Ignore user customization files to prevent local development overrides
|
||||
src/media/css/user.css
|
||||
src/media/js/user.js
|
||||
|
||||
# ============================================================
|
||||
# Joomla Core
|
||||
|
||||
166
CHANGELOG.md
166
CHANGELOG.md
@@ -8,17 +8,179 @@
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: MokoCassiopeia.Documentation
|
||||
PATH: ./CHANGELOG.md
|
||||
VERSION: 03.08.00
|
||||
VERSION: 03.08.03
|
||||
BRIEF: Changelog file documenting version history of MokoCassiopeia
|
||||
-->
|
||||
|
||||
# Changelog — MokoCassiopeia (VERSION: 03.08.00)
|
||||
# Changelog — MokoCassiopeia (VERSION: 03.08.03)
|
||||
|
||||
All notable changes to the MokoCassiopeia Joomla template are documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [03.08.03] - 2026-02-27
|
||||
|
||||
### Added - Main Menu Collapsible Dropdown Override
|
||||
|
||||
**New feature**: Added responsive "Main Menu" mod_menu override with Bootstrap 5 collapsible dropdown functionality.
|
||||
|
||||
#### What's New
|
||||
- **Main Menu module override** with full Bootstrap 5 responsive navbar
|
||||
- Collapsible hamburger menu for mobile devices
|
||||
- Multi-level dropdown support with hover on desktop, tap on mobile
|
||||
- WCAG 2.1 compliant touch targets (48px on mobile, 44px on desktop)
|
||||
- BEM naming convention: `.mod-menu-main__*`
|
||||
- **Appears as "Mainmenu" layout option** in Joomla admin module settings
|
||||
|
||||
#### Files Added
|
||||
- `src/templates/html/mod_menu/mainmenu.php` - Main layout with Bootstrap navbar
|
||||
- `src/templates/html/mod_menu/mainmenu_component.php` - Component menu items
|
||||
- `src/templates/html/mod_menu/mainmenu_heading.php` - Heading menu items
|
||||
- `src/templates/html/mod_menu/mainmenu_separator.php` - Separator menu items
|
||||
- `src/templates/html/mod_menu/mainmenu_url.php` - URL menu items
|
||||
- `src/templates/html/mod_menu/index.html` - Security file
|
||||
|
||||
#### Features
|
||||
- **Bootstrap 5 Navbar**: Uses Bootstrap's native navbar-nav structure
|
||||
- **Collapsible on Mobile**: Hamburger menu with smooth collapse animation
|
||||
- **Dropdown Menus**: Multi-level dropdown support with caret indicators
|
||||
- **Responsive Breakpoints**: Mobile-first design adapting at 768px and 992px
|
||||
- **Touch-Friendly**: 48px minimum touch targets on mobile
|
||||
- **Accessible**: ARIA labels and keyboard navigation support
|
||||
- **Active States**: Visual indicators for current and active menu items
|
||||
- **Alternative Layout**: Named `mainmenu.php` (not `default.php`) to appear as selectable layout option in Joomla admin
|
||||
|
||||
#### CSS Architecture
|
||||
- 200+ lines of responsive CSS in template.css
|
||||
- BEM naming: `.mod-menu-main`, `.mod-menu-main__list`, `.mod-menu-main__link`
|
||||
- CSS variables integration for colors and borders
|
||||
- Hover effects on desktop, tap effects on mobile
|
||||
- Smooth transitions and animations
|
||||
|
||||
#### Module Count Update
|
||||
- **Before**: 16 module overrides
|
||||
- **After**: 17 module overrides (added mod_menu "Main Menu")
|
||||
- **Component overrides**: Still 7 (unchanged)
|
||||
|
||||
### Removed - mod_search Override
|
||||
|
||||
**Cassiopeia approach**: Removed mod_search override to align with Cassiopeia template philosophy of not overriding standard Joomla modules.
|
||||
|
||||
#### Reason for Removal
|
||||
- mod_search is a standard Joomla core module
|
||||
- Following Cassiopeia template approach: use core layouts for standard modules
|
||||
- Prevents potential language loading issues
|
||||
- Ensures compatibility with future Joomla updates
|
||||
- Core mod_search already includes responsive design and accessibility features
|
||||
|
||||
#### Files Removed
|
||||
- `src/templates/html/mod_search/default.php` - Custom search module layout
|
||||
- `src/templates/html/mod_search/index.html` - Security file
|
||||
|
||||
#### Module Count Update (After Removal)
|
||||
- **Before**: 17 module overrides
|
||||
- **After**: 16 module overrides (removed mod_search)
|
||||
- **Component overrides**: Still 7 (unchanged)
|
||||
|
||||
### Removed - Documentation Cleanup
|
||||
|
||||
**Documentation policy**: Removed all markdown files from `src/templates/html/` directory. All documentation belongs in `docs/` folder only.
|
||||
|
||||
#### Files Removed (9 markdown files)
|
||||
- `src/templates/html/STANDARD_MODULES_README.md`
|
||||
- `src/templates/html/INDUSTRY_MODULES_README.md`
|
||||
- `src/templates/html/VIRTUEMART_MODULES_README.md`
|
||||
- `src/templates/html/mod_virtuemart_cart/README.md`
|
||||
- `src/templates/html/mod_virtuemart_category/README.md`
|
||||
- `src/templates/html/mod_virtuemart_currencies/README.md`
|
||||
- `src/templates/html/mod_virtuemart_manufacturer/README.md`
|
||||
- `src/templates/html/mod_virtuemart_product/README.md`
|
||||
- `src/templates/html/mod_search/README.md`
|
||||
|
||||
**Note**: All module override documentation is consolidated in `docs/MODULE_OVERRIDES.md`. The `src/templates/html/` directory now contains only PHP override files and `index.html` security files.
|
||||
|
||||
**Note**: Unlike the previously removed mod_menu override (v03.08.01), this new "Main Menu" override is properly structured based on Joomla core layouts and Bootstrap 5, ensuring language strings load correctly and menu functionality works as expected. The layout is named `mainmenu.php` (not `default.php`) to appear as an alternative layout option "Mainmenu" in the Joomla admin module dropdown selector, preserving Joomla's core default menu layout.
|
||||
|
||||
## [03.08.02] - 2026-02-27
|
||||
|
||||
### Removed - Fix Language Loading in All Module Overrides
|
||||
|
||||
**Critical fix**: Removed standard Joomla module overrides to fix language string loading issues. Following Cassiopeia template approach.
|
||||
|
||||
#### Problem
|
||||
- Default language strings not loading in module overrides (mod_breadcrumbs, mod_login, mod_articles_latest)
|
||||
- Language constants displayed instead of translated text (e.g., "MOD_LOGIN_VALUE_USERNAME" instead of "Username")
|
||||
- Custom overrides interfered with Joomla's module initialization and language loading process
|
||||
|
||||
#### Solution - Cassiopeia Approach
|
||||
- **Removed** standard Joomla module overrides:
|
||||
- `src/templates/html/mod_breadcrumbs/` (2 files)
|
||||
- `src/templates/html/mod_login/` (2 files)
|
||||
- `src/templates/html/mod_articles_latest/` (2 files)
|
||||
- Template now uses Joomla's core module layouts for standard modules
|
||||
- Language files load automatically via Joomla's module system
|
||||
- Custom styling can still be applied via CSS using module-specific classes
|
||||
- **Retained** third-party extension overrides where they add mobile-responsive value:
|
||||
- VirtueMart modules (5): mod_virtuemart_cart, _category, _currencies, _manufacturer, _product
|
||||
- Community Builder modules (2): mod_cblogin, mod_comprofilerOnline
|
||||
- Other extensions (9): mod_acymailing, mod_hikashop_cart, mod_k2_content, mod_kunena*, mod_osmembership, mod_search
|
||||
|
||||
#### Cassiopeia Template Philosophy
|
||||
- Cassiopeia (Joomla's default template) does NOT override standard module layouts
|
||||
- It relies on core Joomla module files and applies styling via CSS
|
||||
- Overrides are only created when structural changes are absolutely necessary
|
||||
- This ensures compatibility, automatic language loading, and easier maintenance
|
||||
|
||||
#### Module Count Update
|
||||
- **Before**: 19 module overrides
|
||||
- **After**: 16 module overrides
|
||||
- **Removed**: 3 standard Joomla modules (breadcrumbs, login, articles_latest)
|
||||
- **Component overrides**: Still 7 (unchanged)
|
||||
|
||||
#### Files Removed
|
||||
- `src/templates/html/mod_breadcrumbs/default.php`
|
||||
- `src/templates/html/mod_breadcrumbs/index.html`
|
||||
- `src/templates/html/mod_login/default.php`
|
||||
- `src/templates/html/mod_login/index.html`
|
||||
- `src/templates/html/mod_articles_latest/default.php`
|
||||
- `src/templates/html/mod_articles_latest/index.html`
|
||||
|
||||
**Note**: This follows Joomla best practices by using core layouts for standard modules. Styling is handled via CSS. Third-party extension overrides remain for mobile responsiveness.
|
||||
|
||||
## [03.08.01] - 2026-02-27
|
||||
|
||||
### Removed - Fix Breaking Overrides
|
||||
|
||||
**Critical fix**: Removed mod_menu override that was causing menu links to break and language strings not to load.
|
||||
|
||||
#### Problem
|
||||
- mod_menu override files (default.php, default_component.php, default_url.php) were attempting to load menu-specific layouts that don't exist in the template
|
||||
- This broke Joomla's core menu rendering system
|
||||
- Menu links were not functional
|
||||
- Language strings were not loading properly in menus
|
||||
|
||||
#### Solution
|
||||
- **Removed** entire `src/templates/html/mod_menu/` directory (4 files)
|
||||
- Template now uses Joomla's default menu rendering
|
||||
- Custom styling can still be applied via CSS using `.mod-menu` class
|
||||
- All menu functionality restored to standard Joomla behavior
|
||||
|
||||
#### Documentation Updates
|
||||
- Updated MODULE_OVERRIDES.md: Changed count from 20 to 19 module overrides, removed mod_menu section, added note about removal
|
||||
- Updated STANDARD_MODULES_README.md: Removed mod_menu documentation, renumbered remaining modules, updated file structure
|
||||
- Updated testing checklists to remove mod_menu references
|
||||
- **Added clarification**: MokoCassiopeia is a standalone template extension (not a package)
|
||||
- Updated updates.xml to version 03.08.01
|
||||
|
||||
#### Files Removed
|
||||
- `src/templates/html/mod_menu/default.php`
|
||||
- `src/templates/html/mod_menu/default_component.php`
|
||||
- `src/templates/html/mod_menu/default_url.php`
|
||||
- `src/templates/html/mod_menu/index.html`
|
||||
|
||||
**Note**: This is a patch release that removes problematic overrides to restore core functionality. Menu styling via CSS remains intact. MokoCassiopeia remains a standalone Joomla template extension (type="template"), not bundled as a package.
|
||||
|
||||
## [03.08.00] - 2026-02-22
|
||||
|
||||
### Added - Community Builder Component Overrides
|
||||
|
||||
@@ -1,455 +0,0 @@
|
||||
<!-- 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.Documentation
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
FILE: ./CLIENT_FORK_README.md
|
||||
VERSION: 03.06.03
|
||||
BRIEF: Template README for client custom code forks
|
||||
-->
|
||||
|
||||
# [CLIENT NAME] - MokoCassiopeia Custom Fork
|
||||
|
||||
**Custom Joomla Template Fork for [CLIENT NAME]**
|
||||
|
||||
This is a customized fork of the [MokoCassiopeia](https://github.com/mokoconsulting-tech/MokoCassiopeia) Joomla template, tailored specifically for [CLIENT NAME]'s website.
|
||||
|
||||
> **💡 Tip**: This fork was likely created using the automated [Client Fork Workflow](./docs/CLIENT_FORK_WORKFLOW.md). If you're creating a new client fork, use the workflow for instant setup!
|
||||
|
||||
---
|
||||
|
||||
## 📋 About This Fork
|
||||
|
||||
This repository contains client-specific customizations built on top of the MokoCassiopeia template. The template provides a modern, lightweight enhancement layer for Joomla with advanced theming, Font Awesome 7, Bootstrap 5, and dark mode support.
|
||||
|
||||
### Customization Strategy
|
||||
|
||||
This fork maintains the following customizations:
|
||||
- **Custom Color Schemes**: Brand-specific colors for light and dark modes
|
||||
- **Custom Code**: Client-specific HTML, CSS, and JavaScript customizations
|
||||
- **Configuration**: Pre-configured template settings for the client environment
|
||||
|
||||
All customizations are designed to be preserved when syncing with upstream MokoCassiopeia updates.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Joomla**: 4.4.x or 5.x
|
||||
- **PHP**: 8.0 or higher
|
||||
- **Git**: For version control and syncing with upstream
|
||||
- **Local Development**: MAMP/XAMPP/Docker for local testing
|
||||
|
||||
### Installation for Development
|
||||
|
||||
1. **Clone this repository**:
|
||||
```bash
|
||||
git clone [YOUR-FORK-URL]
|
||||
cd [YOUR-FORK-NAME]
|
||||
```
|
||||
|
||||
2. **Set up upstream remote** (for syncing updates):
|
||||
```bash
|
||||
git remote add upstream https://github.com/mokoconsulting-tech/MokoCassiopeia.git
|
||||
git fetch upstream
|
||||
```
|
||||
|
||||
3. **Install into Joomla**:
|
||||
- Copy the `src/` directory contents to your Joomla installation:
|
||||
- `src/templates/` → `[joomla]/templates/`
|
||||
- `src/media/` → `[joomla]/media/templates/site/mokocassiopeia/`
|
||||
- `src/language/` → `[joomla]/language/`
|
||||
- `src/administrator/language/` → `[joomla]/administrator/language/`
|
||||
|
||||
4. **Enable the template**:
|
||||
- Log into Joomla admin
|
||||
- Navigate to **System → Site Templates**
|
||||
- Set **MokoCassiopeia** as the default template
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Custom Branding & Colors
|
||||
|
||||
### Custom Color Schemes
|
||||
|
||||
This fork includes custom color schemes specific to [CLIENT NAME]'s brand:
|
||||
|
||||
**Location**:
|
||||
- Light mode: `src/media/css/colors/light/colors_custom.css`
|
||||
- Dark mode: `src/media/css/colors/dark/colors_custom.css`
|
||||
|
||||
**Note**: These files are gitignored in the upstream repository to prevent conflicts, but are tracked in this fork.
|
||||
|
||||
### Modifying Brand Colors
|
||||
|
||||
1. **Edit the custom color files**:
|
||||
```bash
|
||||
# Light mode colors
|
||||
edit src/media/css/colors/light/colors_custom.css
|
||||
|
||||
# Dark mode colors
|
||||
edit src/media/css/colors/dark/colors_custom.css
|
||||
```
|
||||
|
||||
2. **Key variables to customize**:
|
||||
```css
|
||||
:root[data-bs-theme="light"] {
|
||||
--color-primary: #YOUR-BRAND-COLOR;
|
||||
--accent-color-primary: #YOUR-ACCENT-COLOR;
|
||||
--color-link: #YOUR-LINK-COLOR;
|
||||
--nav-bg-color: #YOUR-NAV-BG;
|
||||
}
|
||||
```
|
||||
|
||||
3. **Test your changes**:
|
||||
- Clear Joomla cache: System → Clear Cache
|
||||
- Clear browser cache (Ctrl+Shift+R / Cmd+Shift+R)
|
||||
- View your site in light and dark modes
|
||||
|
||||
### Available CSS Variables
|
||||
|
||||
For a complete reference of all customizable CSS variables, see the [CSS Variables Documentation](./docs/CSS_VARIABLES.md) in the upstream repository.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Custom Code Injection
|
||||
|
||||
### Using custom.php
|
||||
|
||||
The `src/templates/custom.php` file allows for custom PHP functions and HTML snippets:
|
||||
|
||||
**Location**: `src/templates/custom.php`
|
||||
|
||||
**Example Use Cases**:
|
||||
- Custom helper functions
|
||||
- Client-specific HTML snippets
|
||||
- Custom console logging
|
||||
- Integration code
|
||||
|
||||
**Example**:
|
||||
```php
|
||||
<?php
|
||||
// Custom helper function
|
||||
function console_log($output, $with_script_tags = true) {
|
||||
$js_code = 'console.log(' . json_encode($output, JSON_HEX_TAG) . ');';
|
||||
if ($with_script_tags) {
|
||||
$js_code = '<script>' . $js_code . '</script>';
|
||||
}
|
||||
echo $js_code;
|
||||
}
|
||||
?>
|
||||
<!--
|
||||
Custom HTML code can be added here
|
||||
-->
|
||||
```
|
||||
|
||||
### Custom Code via Joomla Template Settings
|
||||
|
||||
You can also inject custom code via the Joomla admin interface:
|
||||
|
||||
1. Navigate to **System → Site Templates → MokoCassiopeia**
|
||||
2. Go to the **Custom Code** tab
|
||||
3. Add custom HTML/CSS/JS in:
|
||||
- **Custom Head Start**: Injected at the beginning of `<head>`
|
||||
- **Custom Head End**: Injected at the end of `<head>`
|
||||
|
||||
This approach is ideal for:
|
||||
- Analytics tracking codes
|
||||
- Custom meta tags
|
||||
- External script includes
|
||||
- Custom CSS snippets
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Syncing with Upstream Updates
|
||||
|
||||
To keep your fork up-to-date with new features and bug fixes from the upstream MokoCassiopeia repository:
|
||||
|
||||
### 1. Fetch Upstream Changes
|
||||
|
||||
```bash
|
||||
# Ensure upstream remote is configured
|
||||
git remote -v
|
||||
# If upstream is not listed, add it:
|
||||
# git remote add upstream https://github.com/mokoconsulting-tech/MokoCassiopeia.git
|
||||
|
||||
# Fetch latest changes
|
||||
git fetch upstream
|
||||
```
|
||||
|
||||
### 2. Review Changes
|
||||
|
||||
```bash
|
||||
# See what changed in upstream
|
||||
git log HEAD..upstream/main --oneline
|
||||
|
||||
# Review the diff
|
||||
git diff HEAD..upstream/main
|
||||
```
|
||||
|
||||
### 3. Merge Upstream Changes
|
||||
|
||||
```bash
|
||||
# Switch to your main branch
|
||||
git checkout main
|
||||
|
||||
# Merge upstream changes
|
||||
git merge upstream/main
|
||||
|
||||
# Or rebase (preserves cleaner history):
|
||||
# git rebase upstream/main
|
||||
```
|
||||
|
||||
### 4. Resolve Conflicts
|
||||
|
||||
If conflicts occur (typically in custom files):
|
||||
|
||||
1. **Check conflict status**:
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
2. **Resolve conflicts manually** in your editor:
|
||||
- Look for conflict markers: `<<<<<<<`, `=======`, `>>>>>>>`
|
||||
- Keep your custom changes
|
||||
- Remove conflict markers
|
||||
|
||||
3. **Complete the merge**:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Merge upstream updates and resolve conflicts"
|
||||
```
|
||||
|
||||
### 5. Test After Merging
|
||||
|
||||
- Clear Joomla cache
|
||||
- Test critical functionality:
|
||||
- Homepage loads correctly
|
||||
- Custom colors are preserved
|
||||
- Dark mode toggle works
|
||||
- Navigation functions properly
|
||||
- Custom code still executes
|
||||
|
||||
### Protected Files
|
||||
|
||||
The following files contain your customizations and should be carefully reviewed during merges:
|
||||
|
||||
- `src/media/css/colors/light/colors_custom.css` (custom light mode colors)
|
||||
- `src/media/css/colors/dark/colors_custom.css` (custom dark mode colors)
|
||||
- `src/templates/custom.php` (custom PHP code)
|
||||
- Template configuration (stored in Joomla database, not in files)
|
||||
|
||||
---
|
||||
|
||||
## 📦 Building & Deployment
|
||||
|
||||
### Creating a Template Package
|
||||
|
||||
To create an installable ZIP package of your customized template:
|
||||
|
||||
1. **Prepare the package**:
|
||||
```bash
|
||||
cd src
|
||||
zip -r ../mokocassiopeia-[CLIENT-NAME]-[VERSION].zip . -x "*.git*" "*.DS_Store"
|
||||
```
|
||||
|
||||
2. **Install via Joomla**:
|
||||
- Upload the ZIP file via **System → Install → Extensions**
|
||||
- Or manually copy files to the Joomla installation
|
||||
|
||||
### Deployment to Production
|
||||
|
||||
**Recommended Deployment Methods**:
|
||||
|
||||
1. **Via Joomla Extension Manager** (Easiest):
|
||||
- Create a ZIP package as described above
|
||||
- Upload via Joomla admin interface
|
||||
- The template will automatically overwrite the existing installation
|
||||
|
||||
2. **Via FTP/SFTP**:
|
||||
- Upload changed files directly to the server
|
||||
- Clear Joomla cache after deployment
|
||||
|
||||
3. **Via Git** (Advanced):
|
||||
- Push changes to a deployment branch
|
||||
- Use Git hooks or CI/CD to deploy to production
|
||||
- Ensure proper file permissions
|
||||
|
||||
**Post-Deployment Checklist**:
|
||||
- [ ] Clear Joomla cache (System → Clear Cache)
|
||||
- [ ] Test homepage
|
||||
- [ ] Test navigation and menus
|
||||
- [ ] Verify custom colors appear correctly
|
||||
- [ ] Test dark mode toggle
|
||||
- [ ] Check mobile responsiveness
|
||||
- [ ] Verify analytics tracking (if enabled)
|
||||
|
||||
---
|
||||
|
||||
## 🛠 Local Development Setup
|
||||
|
||||
### Setting Up a Local Joomla Environment
|
||||
|
||||
1. **Install a local server stack**:
|
||||
- **MAMP** (Mac/Windows): https://www.mamp.info/
|
||||
- **XAMPP** (Cross-platform): https://www.apachefriends.org/
|
||||
- **Docker**: https://github.com/joomla-docker/docker-joomla
|
||||
|
||||
2. **Install Joomla**:
|
||||
- Download Joomla from https://downloads.joomla.org/
|
||||
- Extract to your local server's web directory
|
||||
- Follow the Joomla installation wizard
|
||||
|
||||
3. **Install this template**:
|
||||
- Copy files from this repository to your Joomla installation
|
||||
- Or upload the ZIP package via Joomla's Extension Manager
|
||||
|
||||
4. **Enable development mode**:
|
||||
- Edit `configuration.php`:
|
||||
```php
|
||||
public $debug = '1';
|
||||
public $error_reporting = 'maximum';
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
|
||||
1. **Make changes** to template files in your local Joomla installation
|
||||
2. **Test changes** in your browser
|
||||
3. **Copy changes back** to this repository:
|
||||
```bash
|
||||
# From Joomla installation
|
||||
cp [joomla]/templates/mokocassiopeia/* [repo]/src/templates/
|
||||
cp [joomla]/media/templates/site/mokocassiopeia/css/* [repo]/src/media/css/
|
||||
```
|
||||
4. **Commit and push** to your fork
|
||||
5. **Deploy** to staging/production when ready
|
||||
|
||||
### Quick Testing Commands
|
||||
|
||||
```bash
|
||||
# Clear Joomla cache from command line
|
||||
rm -rf [joomla]/cache/*
|
||||
rm -rf [joomla]/administrator/cache/*
|
||||
|
||||
# Watch for CSS changes (if using a build tool)
|
||||
# npm run watch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Customization Checklist
|
||||
|
||||
Use this checklist when setting up or modifying your custom fork:
|
||||
|
||||
### Initial Setup
|
||||
- [ ] Fork the MokoCassiopeia repository
|
||||
- [ ] Update this README with client name and details
|
||||
- [ ] Configure custom brand colors
|
||||
- [ ] Test light and dark modes
|
||||
- [ ] Add custom code if needed
|
||||
- [ ] Configure template settings in Joomla
|
||||
- [ ] Set up analytics tracking (if required)
|
||||
- [ ] Test on multiple devices and browsers
|
||||
|
||||
### Ongoing Maintenance
|
||||
- [ ] Sync with upstream periodically (monthly recommended)
|
||||
- [ ] Review upstream changelog for breaking changes
|
||||
- [ ] Test thoroughly after merging upstream updates
|
||||
- [ ] Keep this README updated with customization notes
|
||||
- [ ] Document any client-specific configurations
|
||||
- [ ] Maintain backup before major updates
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentation Resources
|
||||
|
||||
### MokoCassiopeia Documentation
|
||||
|
||||
- **[Main README](https://github.com/mokoconsulting-tech/MokoCassiopeia/blob/main/README.md)** - Features and overview
|
||||
- **[CSS Variables Reference](./docs/CSS_VARIABLES.md)** - Complete CSS customization guide
|
||||
- **[Development Guide](./docs/JOOMLA_DEVELOPMENT.md)** - Development and testing
|
||||
- **[Quick Start](./docs/QUICK_START.md)** - Quick setup guide
|
||||
- **[Changelog](./CHANGELOG.md)** - Version history
|
||||
|
||||
### Joomla Resources
|
||||
|
||||
- **[Joomla Documentation](https://docs.joomla.org/)** - Official Joomla docs
|
||||
- **[Joomla Templates](https://docs.joomla.org/J4.x:How_to_Create_a_Joomla_Template)** - Template development guide
|
||||
- **[Cassiopeia Documentation](https://docs.joomla.org/J4.x:Cassiopeia)** - Parent template docs
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security & Best Practices
|
||||
|
||||
### Security Considerations
|
||||
|
||||
1. **Keep Joomla Updated**: Always run the latest stable Joomla version
|
||||
2. **Update Dependencies**: Regularly sync with upstream MokoCassiopeia for security patches
|
||||
3. **Secure Custom Code**: Review all custom code for security vulnerabilities
|
||||
4. **Use HTTPS**: Always serve production sites over HTTPS
|
||||
5. **Regular Backups**: Maintain regular backups of both files and database
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Version Control**: Commit changes frequently with clear messages
|
||||
2. **Testing**: Always test changes locally before deploying to production
|
||||
3. **Documentation**: Document all customizations in this README
|
||||
4. **Code Review**: Have changes reviewed before deploying to production
|
||||
5. **Staging Environment**: Use a staging site to test updates before production
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support & Contact
|
||||
|
||||
### Client-Specific Support
|
||||
|
||||
**Client Contact**: [CLIENT CONTACT INFO]
|
||||
**Developer Contact**: [DEVELOPER CONTACT INFO]
|
||||
**Hosting Provider**: [HOSTING INFO]
|
||||
|
||||
### Upstream MokoCassiopeia Support
|
||||
|
||||
- **Repository**: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
- **Issues**: https://github.com/mokoconsulting-tech/MokoCassiopeia/issues
|
||||
- **Documentation**: https://github.com/mokoconsulting-tech/MokoCassiopeia/blob/main/README.md
|
||||
- **Moko Consulting**: https://mokoconsulting.tech
|
||||
|
||||
---
|
||||
|
||||
## 📄 License
|
||||
|
||||
This fork maintains the original GPL-3.0-or-later license from MokoCassiopeia.
|
||||
|
||||
- **MokoCassiopeia**: GPL-3.0-or-later
|
||||
- **Client Customizations**: GPL-3.0-or-later (or as specified by client agreement)
|
||||
- **Third-Party Libraries**: See [Included Libraries](https://github.com/mokoconsulting-tech/MokoCassiopeia#-included-libraries)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Fork Information
|
||||
|
||||
- **Upstream Repository**: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
- **Fork Repository**: [YOUR-FORK-URL]
|
||||
- **Client**: [CLIENT NAME]
|
||||
- **Created**: [DATE]
|
||||
- **Last Synced with Upstream**: [DATE]
|
||||
- **Current Version**: 03.06.03
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Revision History
|
||||
|
||||
| Date | Version | Change Summary | Author |
|
||||
|------|---------|----------------|--------|
|
||||
| [DATE] | 03.06.03 | Initial fork setup with custom colors and branding | [YOUR NAME] |
|
||||
|
||||
---
|
||||
|
||||
**Maintained by [CLIENT NAME] / [DEVELOPER NAME]**
|
||||
33
README.md
33
README.md
@@ -96,6 +96,8 @@ MokoCassiopeia is a modern, lightweight enhancement layer built on top of Joomla
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
**Note**: MokoCassiopeia is a **standalone Joomla template extension** (not bundled as a package). Install it directly via Joomla's Extension Manager.
|
||||
|
||||
### Via Joomla Extension Manager
|
||||
|
||||
1. Download the latest `mokocassiopeia-{version}.zip` from [Releases](https://github.com/mokoconsulting-tech/MokoCassiopeia/releases)
|
||||
@@ -201,13 +203,13 @@ Access template configuration via **System → Site Templates → MokoCassiopeia
|
||||
- **Left Drawer Icon**: Font Awesome icon class (e.g., `fa-solid fa-chevron-right`)
|
||||
- **Right Drawer Icon**: Font Awesome icon class (e.g., `fa-solid fa-chevron-left`)
|
||||
|
||||
### Custom Color Palettes
|
||||
### Custom Theme Palettes
|
||||
|
||||
MokoCassiopeia supports custom color schemes:
|
||||
MokoCassiopeia supports custom theme schemes:
|
||||
|
||||
1. **Copy template files** from `/templates/` directory:
|
||||
- `colors_custom_light.css` → `media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css`
|
||||
- `colors_custom_dark.css` → `media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css`
|
||||
- `light.custom.css` → `media/templates/site/mokocassiopeia/css/theme/light.custom.css`
|
||||
- `dark.custom.css` → `media/templates/site/mokocassiopeia/css/theme/dark.custom.css`
|
||||
2. **Customize** the CSS variables to match your brand colors
|
||||
3. **Enable in Joomla**: System → Site Templates → MokoCassiopeia → Theme tab → Set palette to "Custom"
|
||||
4. **Save** and view your site with custom colors
|
||||
@@ -326,16 +328,6 @@ See [Joomla Development Guide](./docs/JOOMLA_DEVELOPMENT.md) for packaging instr
|
||||
- **[CSS Variables Reference](./docs/CSS_VARIABLES.md)** - Complete CSS customization guide
|
||||
- **[Documentation Index](./docs/README.md)** - All documentation links
|
||||
|
||||
### Customization Resources
|
||||
|
||||
- **[Template Files](./templates/)** - Ready-to-use templates for customization
|
||||
- `colors_custom.css` - Custom color palette template
|
||||
- `CLIENT_FORK_README_TEMPLATE.md` - Template for client fork documentation
|
||||
|
||||
### Client Forks
|
||||
|
||||
- **[Client Fork Guide](./CLIENT_FORK_README.md)** - Comprehensive guide for creating and maintaining client custom code forks
|
||||
|
||||
### Governance
|
||||
|
||||
- **[Contributing](./CONTRIBUTING.md)** - How to contribute
|
||||
@@ -402,18 +394,9 @@ We welcome contributions! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for gu
|
||||
|
||||
See [Workflow Guide](./docs/WORKFLOW_GUIDE.md) for detailed Git workflow.
|
||||
|
||||
### Client Custom Forks
|
||||
### Customizations
|
||||
|
||||
Creating a custom fork for client-specific branding and code?
|
||||
|
||||
**Quick Setup**: Use our automated workflow to create a client fork in minutes:
|
||||
- **[Client Fork Workflow Guide](./docs/CLIENT_FORK_WORKFLOW.md)** - Automated GitHub Actions workflow or local bash script
|
||||
|
||||
**Comprehensive Guide**: See our [Client Fork Guide](./CLIENT_FORK_README.md) for:
|
||||
- Setting up custom color schemes
|
||||
- Maintaining fork-specific customizations
|
||||
- Syncing with upstream updates
|
||||
- Deployment workflows
|
||||
For template customizations, use Joomla's built-in template settings (System → Site Templates → MokoCassiopeia → Custom Code tab) for HTML/CSS/JS customizations.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
BRIEF: Documentation for client fork creation workflow
|
||||
-->
|
||||
|
||||
# Client Fork Creation Workflow
|
||||
|
||||
This document explains how to use the automated client fork creation tools to set up a new client-specific fork of MokoCassiopeia.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The client fork creation workflow automates the process of preparing a repository for a client-specific fork. It performs the following actions:
|
||||
|
||||
1. ✅ Copies `templates/colors_custom.css` to `src/media/css/colors/light/colors_custom.css`
|
||||
2. ✅ Copies `templates/colors_custom.css` to `src/media/css/colors/dark/colors_custom.css`
|
||||
3. ✅ Replaces `README.md` with customized `CLIENT_FORK_README.md`
|
||||
4. ✅ Removes `CLIENT_FORK_README.md` from root
|
||||
5. ✅ Removes `templates/CLIENT_FORK_README_TEMPLATE.md`
|
||||
6. ✅ Updates `templates/README.md` to remove fork template references
|
||||
7. ✅ Keeps `templates/colors_custom.css` as a template for reference
|
||||
|
||||
---
|
||||
|
||||
## Method 1: GitHub Actions Workflow (Recommended)
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Repository admin or maintainer access
|
||||
- GitHub Actions enabled for the repository
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Navigate to Actions**
|
||||
- Go to your repository on GitHub
|
||||
- Click on the "Actions" tab
|
||||
|
||||
2. **Run the Workflow**
|
||||
- Select "Create Client Fork" from the workflow list
|
||||
- Click "Run workflow"
|
||||
- Fill in the required inputs:
|
||||
- **Client Name**: Full client name (e.g., "Acme Corporation")
|
||||
- **Confirm**: Type "CONFIRM" to proceed
|
||||
- Click "Run workflow" button
|
||||
|
||||
3. **Monitor Progress**
|
||||
- The workflow will create a new branch named `client-fork/{client-slug}`
|
||||
- You can monitor the progress in the Actions tab
|
||||
- Once complete, you'll see a summary of changes
|
||||
|
||||
4. **Review the Branch**
|
||||
- Navigate to the new branch: `client-fork/{client-slug}`
|
||||
- Review the changes made
|
||||
- The README will be customized with the client name
|
||||
- Custom color files will be in place
|
||||
|
||||
5. **Create Client Repository**
|
||||
- Create a new repository for the client
|
||||
- Push the branch to the new repository:
|
||||
```bash
|
||||
git remote add client-repo <CLIENT_REPO_URL>
|
||||
git push client-repo client-fork/{client-slug}:main
|
||||
```
|
||||
|
||||
### Workflow Features
|
||||
|
||||
- ✅ **Safe Confirmation**: Requires typing "CONFIRM" to prevent accidental runs
|
||||
- ✅ **Automated Branch Creation**: Creates a properly named branch automatically
|
||||
- ✅ **Customized README**: Automatically fills in client name and date
|
||||
- ✅ **Git Tracking**: Commits all changes with a descriptive message
|
||||
- ✅ **Summary Report**: Provides a complete summary of actions taken
|
||||
|
||||
---
|
||||
|
||||
## Method 2: Local Bash Script
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Git installed on your local machine
|
||||
- Bash shell (Linux, macOS, or Git Bash on Windows)
|
||||
- Local clone of the MokoCassiopeia repository
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Clone the Repository**
|
||||
```bash
|
||||
git clone https://github.com/mokoconsulting-tech/MokoCassiopeia.git
|
||||
cd MokoCassiopeia
|
||||
```
|
||||
|
||||
2. **Make Script Executable**
|
||||
```bash
|
||||
chmod +x scripts/create-client-fork.sh
|
||||
```
|
||||
|
||||
3. **Run the Script**
|
||||
```bash
|
||||
./scripts/create-client-fork.sh "Client Name"
|
||||
```
|
||||
|
||||
Example:
|
||||
```bash
|
||||
./scripts/create-client-fork.sh "Acme Corporation"
|
||||
```
|
||||
|
||||
4. **Confirm Actions**
|
||||
- The script will show you what it will do
|
||||
- Type "yes" to proceed
|
||||
- Review the changes shown
|
||||
- Type "yes" to commit
|
||||
|
||||
5. **Push to New Repository**
|
||||
```bash
|
||||
# Add the client's repository as a remote
|
||||
git remote add client-repo <CLIENT_REPO_URL>
|
||||
|
||||
# Push the branch
|
||||
git push client-repo client-fork/{client-slug}:main
|
||||
```
|
||||
|
||||
### Script Features
|
||||
|
||||
- 🎨 **Colored Output**: Easy-to-read colored terminal output
|
||||
- ✅ **Interactive Confirmation**: Asks for confirmation before making changes
|
||||
- ✅ **Safety Checks**: Verifies you're in the correct directory
|
||||
- ✅ **Progress Indicators**: Shows each step as it completes
|
||||
- ✅ **Git Status**: Shows what files changed before committing
|
||||
- ✅ **Summary**: Provides a complete summary at the end
|
||||
|
||||
---
|
||||
|
||||
## What Gets Changed
|
||||
|
||||
### Files Created
|
||||
|
||||
```
|
||||
src/media/css/colors/light/colors_custom.css [NEW]
|
||||
src/media/css/colors/dark/colors_custom.css [NEW]
|
||||
```
|
||||
|
||||
### Files Modified
|
||||
|
||||
```
|
||||
README.md [REPLACED]
|
||||
templates/README.md [UPDATED]
|
||||
```
|
||||
|
||||
### Files Removed
|
||||
|
||||
```
|
||||
CLIENT_FORK_README.md [DELETED]
|
||||
templates/CLIENT_FORK_README_TEMPLATE.md [DELETED]
|
||||
```
|
||||
|
||||
### Files Kept
|
||||
|
||||
```
|
||||
templates/colors_custom.css [UNCHANGED]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Post-Setup Steps
|
||||
|
||||
After running the workflow or script, you should:
|
||||
|
||||
1. **Customize Brand Colors**
|
||||
- Edit `src/media/css/colors/light/colors_custom.css`
|
||||
- Edit `src/media/css/colors/dark/colors_custom.css`
|
||||
- Update CSS variables to match client branding
|
||||
|
||||
2. **Update README**
|
||||
- Fill in client-specific contact information
|
||||
- Add custom notes or configurations
|
||||
- Update fork URL references
|
||||
|
||||
3. **Test Locally**
|
||||
- Install the template in a local Joomla instance
|
||||
- Test light and dark modes
|
||||
- Verify custom colors appear correctly
|
||||
|
||||
4. **Create Client Repository**
|
||||
- Create a new repository for the client
|
||||
- Push the prepared branch to the new repo
|
||||
- Set up appropriate access controls
|
||||
|
||||
5. **Enable Custom Palette in Joomla**
|
||||
- Log into Joomla admin
|
||||
- Navigate to System → Site Templates → MokoCassiopeia
|
||||
- Under Theme tab, set palette to "Custom"
|
||||
- Save and test
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Workflow Fails with "CONFIRM" Error
|
||||
|
||||
**Problem**: Workflow stops immediately with confirmation error.
|
||||
|
||||
**Solution**: Make sure you type "CONFIRM" (in all caps) in the confirmation field.
|
||||
|
||||
### Script Says "CLIENT_FORK_README.md not found"
|
||||
|
||||
**Problem**: Script can't find required files.
|
||||
|
||||
**Solution**: Make sure you're running the script from the repository root directory:
|
||||
```bash
|
||||
cd /path/to/MokoCassiopeia
|
||||
./scripts/create-client-fork.sh "Client Name"
|
||||
```
|
||||
|
||||
### Colors Don't Appear After Setup
|
||||
|
||||
**Problem**: Custom colors don't show in Joomla.
|
||||
|
||||
**Solution**:
|
||||
1. Enable custom palette in template settings
|
||||
2. Clear Joomla cache (System → Clear Cache)
|
||||
3. Clear browser cache (Ctrl+Shift+R / Cmd+Shift+R)
|
||||
|
||||
### Branch Already Exists
|
||||
|
||||
**Problem**: Branch name conflicts with existing branch.
|
||||
|
||||
**Solution**: Either delete the old branch or choose a different client name:
|
||||
```bash
|
||||
# Delete old branch
|
||||
git branch -D client-fork/{client-slug}
|
||||
|
||||
# Or use a more specific client name
|
||||
./scripts/create-client-fork.sh "Client Name - Division"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Simple Client Fork
|
||||
|
||||
```bash
|
||||
# Using the script
|
||||
./scripts/create-client-fork.sh "Acme Corporation"
|
||||
```
|
||||
|
||||
This creates:
|
||||
- Branch: `client-fork/acme-corporation`
|
||||
- README title: "Acme Corporation - MokoCassiopeia Custom Fork"
|
||||
|
||||
### Example 2: Client with Multiple Words
|
||||
|
||||
```bash
|
||||
# Using the script
|
||||
./scripts/create-client-fork.sh "Global Tech Solutions Inc"
|
||||
```
|
||||
|
||||
This creates:
|
||||
- Branch: `client-fork/global-tech-solutions-inc`
|
||||
- README title: "Global Tech Solutions Inc - MokoCassiopeia Custom Fork"
|
||||
|
||||
### Example 3: Using GitHub Actions
|
||||
|
||||
1. Go to Actions → Create Client Fork
|
||||
2. Enter: "Mountain View Medical Center"
|
||||
3. Enter: "CONFIRM"
|
||||
4. Click "Run workflow"
|
||||
|
||||
Result:
|
||||
- Branch: `client-fork/mountain-view-medical-center`
|
||||
- README title: "Mountain View Medical Center - MokoCassiopeia Custom Fork"
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Naming Convention**: Use the official client name as it should appear in documentation
|
||||
|
||||
2. **Branch Management**:
|
||||
- Keep the branch until the client repository is set up
|
||||
- Don't merge client fork branches back to main
|
||||
|
||||
3. **Custom Colors**:
|
||||
- Document color choices in README
|
||||
- Keep a backup of custom color files
|
||||
- Test in both light and dark modes
|
||||
|
||||
4. **Version Tracking**:
|
||||
- Note the upstream version in fork README
|
||||
- Track when you last synced with upstream
|
||||
|
||||
5. **Security**:
|
||||
- Don't commit client-specific credentials
|
||||
- Review custom code before deployment
|
||||
- Keep client forks private if they contain sensitive branding
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- **[CLIENT_FORK_README.md](../CLIENT_FORK_README.md)** - Full client fork guide
|
||||
- **[CSS Variables](../docs/CSS_VARIABLES.md)** - Complete CSS variable reference
|
||||
- **[Main README](../README.md)** - MokoCassiopeia documentation
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
For issues with the workflow or script:
|
||||
- Check this documentation first
|
||||
- Review error messages carefully
|
||||
- Contact: hello@mokoconsulting.tech
|
||||
|
||||
---
|
||||
|
||||
**Document Version**: 1.0
|
||||
**Last Updated**: 2026-02-20
|
||||
**Maintained by**: Moko Consulting
|
||||
@@ -46,8 +46,8 @@ This document provides a complete reference of all CSS variables available in th
|
||||
To create custom color schemes:
|
||||
|
||||
1. **Copy template files** from `./templates/` directory:
|
||||
- `colors_custom_light.css` → `media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css`
|
||||
- `colors_custom_dark.css` → `media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css`
|
||||
- `light.custom.css` → `media/templates/site/mokocassiopeia/css/theme/light.custom.css`
|
||||
- `dark.custom.css` → `media/templates/site/mokocassiopeia/css/theme/dark.custom.css`
|
||||
|
||||
2. **Edit the variables** in the copied files to match your brand
|
||||
|
||||
@@ -403,6 +403,51 @@ Available in 9 shades: `--gray-100` through `--gray-900`
|
||||
Light mode ranges from very light (`#f9fafb`) to very dark (`#22262a`).
|
||||
Dark mode ranges are inverted for better contrast on dark backgrounds.
|
||||
|
||||
### Opacity Utilities
|
||||
|
||||
**New in v03.08.04**: Opacity utility variables for creating translucent colors:
|
||||
|
||||
- `--opacity-0`: `0` (fully transparent)
|
||||
- `--opacity-5`: `0.05`
|
||||
- `--opacity-10`: `0.1`
|
||||
- `--opacity-15`: `0.15`
|
||||
- `--opacity-20`: `0.2`
|
||||
- `--opacity-25`: `0.25`
|
||||
- `--opacity-30`: `0.3`
|
||||
- `--opacity-50`: `0.5`
|
||||
- `--opacity-75`: `0.75`
|
||||
- `--opacity-100`: `1` (fully opaque)
|
||||
|
||||
**Usage Example:**
|
||||
```css
|
||||
background-color: rgba(var(--black-rgb), var(--opacity-10));
|
||||
border-color: rgba(var(--white-rgb), var(--opacity-25));
|
||||
```
|
||||
|
||||
### Shadow Color Utilities
|
||||
|
||||
**New in v03.08.04**: Pre-defined shadow color variables for consistent shadow styling:
|
||||
|
||||
**Light Theme:**
|
||||
- `--shadow-color-light`: `rgba(var(--black-rgb), var(--opacity-15))` - Light shadows
|
||||
- `--shadow-color-medium`: `rgba(var(--black-rgb), var(--opacity-25))` - Medium shadows
|
||||
- `--shadow-color-dark`: `rgba(var(--black-rgb), var(--opacity-30))` - Dark shadows
|
||||
- `--border-color-translucent`: `rgba(var(--black-rgb), var(--opacity-10))` - Translucent borders
|
||||
- `--highlight-translucent`: `rgba(var(--white-rgb), var(--opacity-15))` - Highlight overlays
|
||||
|
||||
**Dark Theme:**
|
||||
- `--shadow-color-light`: `rgba(var(--black-rgb), var(--opacity-30))` - Adjusted for dark backgrounds
|
||||
- `--shadow-color-medium`: `rgba(var(--black-rgb), var(--opacity-50))`
|
||||
- `--shadow-color-dark`: `rgba(var(--black-rgb), var(--opacity-75))`
|
||||
- `--border-color-translucent`: `rgba(var(--white-rgb), var(--opacity-10))`
|
||||
- `--highlight-translucent`: `rgba(var(--white-rgb), var(--opacity-5))`
|
||||
|
||||
**Usage Example:**
|
||||
```css
|
||||
box-shadow: 0 0.5rem 1rem var(--shadow-color-light);
|
||||
border: 1px solid var(--border-color-translucent);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Body & Typography
|
||||
@@ -535,6 +580,68 @@ Dark mode ranges are inverted for better contrast on dark backgrounds.
|
||||
|
||||
---
|
||||
|
||||
## Bootstrap Button Variants
|
||||
|
||||
**New in v03.08.04**: Complete Bootstrap button color definitions for both light and dark themes.
|
||||
|
||||
### Available Button Classes
|
||||
|
||||
All button variants support hover, active, focus, and disabled states using CSS variables:
|
||||
|
||||
**Solid Buttons:**
|
||||
- `.btn-primary` - Primary brand button
|
||||
- `.btn-secondary` - Secondary button
|
||||
- `.btn-success` - Success/positive action button
|
||||
- `.btn-info` - Informational button
|
||||
- `.btn-warning` - Warning/caution button
|
||||
- `.btn-danger` - Danger/destructive action button
|
||||
- `.btn-light` - Light background button
|
||||
- `.btn-dark` - Dark background button
|
||||
|
||||
**Outline Buttons:**
|
||||
- `.btn-outline-primary` through `.btn-outline-dark` - Outlined variants of above
|
||||
|
||||
### Button CSS Variables
|
||||
|
||||
Each button variant defines the following CSS variables:
|
||||
|
||||
- `--btn-color`: Text color
|
||||
- `--btn-bg`: Background color
|
||||
- `--btn-border-color`: Border color
|
||||
- `--btn-hover-color`: Hover state text color
|
||||
- `--btn-hover-bg`: Hover state background
|
||||
- `--btn-hover-border-color`: Hover state border
|
||||
- `--btn-focus-shadow-rgb`: Focus ring RGB values
|
||||
- `--btn-active-color`: Active state text color
|
||||
- `--btn-active-bg`: Active state background
|
||||
- `--btn-active-border-color`: Active state border
|
||||
- `--btn-active-shadow`: Active state shadow
|
||||
- `--btn-disabled-color`: Disabled state text color
|
||||
- `--btn-disabled-bg`: Disabled state background
|
||||
- `--btn-disabled-border-color`: Disabled state border
|
||||
|
||||
### Customizing Button Colors
|
||||
|
||||
To customize button colors in your custom color palette:
|
||||
|
||||
```css
|
||||
:root[data-bs-theme="light"] {
|
||||
/* Override Bootstrap state colors */
|
||||
--success: #28a745;
|
||||
--danger: #dc3545;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
--btn-bg: var(--color-primary);
|
||||
--btn-border-color: var(--color-primary);
|
||||
/* Other button states... */
|
||||
}
|
||||
```
|
||||
|
||||
See `templates/light.custom.css` and `templates/dark.custom.css` for complete examples.
|
||||
|
||||
---
|
||||
|
||||
## Button Utilities
|
||||
|
||||
### `--btn-border-radius`
|
||||
@@ -673,6 +780,35 @@ Dark mode ranges are inverted for better contrast on dark backgrounds.
|
||||
- Dark: `#ff8e86`
|
||||
- `--form-invalid-border-color`: Matching border color
|
||||
|
||||
### Form Control Enhancements
|
||||
|
||||
**New in v03.08.04**: Additional form control color variables:
|
||||
|
||||
#### `--input-file-button-active-bg`
|
||||
- **Light Mode**: `#dee1e4`
|
||||
- **Dark Mode**: `#2b3441`
|
||||
- **Usage**: Background color for file input button in active state
|
||||
|
||||
#### `--form-range-thumb-active-bg`
|
||||
- **Light Mode**: `#b8bfcc`
|
||||
- **Dark Mode**: `#4a5766`
|
||||
- **Usage**: Background color for range slider thumb in active state
|
||||
|
||||
### Alert Link Colors
|
||||
|
||||
**New in v03.08.04**: Dedicated variables for alert link colors:
|
||||
|
||||
- `--alert-primary-link-color`: Link color in primary alerts
|
||||
- `--alert-secondary-link-color`: Link color in secondary alerts
|
||||
- `--alert-success-link-color`: Link color in success alerts
|
||||
- `--alert-info-link-color`: Link color in info alerts
|
||||
- `--alert-warning-link-color`: Link color in warning alerts
|
||||
- `--alert-danger-link-color`: Link color in danger alerts
|
||||
- `--alert-light-link-color`: Link color in light alerts
|
||||
- `--alert-dark-link-color`: Link color in dark alerts
|
||||
|
||||
These ensure optimal readability for links within alert boxes.
|
||||
|
||||
---
|
||||
|
||||
## Responsive Tokens & Breakpoints
|
||||
|
||||
310
docs/MANUAL_DEPLOYMENT.md
Normal file
310
docs/MANUAL_DEPLOYMENT.md
Normal file
@@ -0,0 +1,310 @@
|
||||
# Manual Deployment Guide - MokoCassiopeia
|
||||
|
||||
This guide explains how to manually deploy the MokoCassiopeia template from the `src` directory to a Joomla installation without using the build/packaging process.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Understanding the Structure](#understanding-the-structure)
|
||||
- [Manual Deployment Methods](#manual-deployment-methods)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [When to Use Manual Deployment](#when-to-use-manual-deployment)
|
||||
|
||||
## Overview
|
||||
|
||||
**Important**: The `src` directory in this repository is the development source, not a ready-to-install package. For production use, we recommend using the packaged ZIP file from [Releases](https://github.com/mokoconsulting-tech/MokoCassiopeia/releases).
|
||||
|
||||
However, for development or testing purposes, you can manually deploy files from the `src` directory to your Joomla installation.
|
||||
|
||||
## Understanding the Structure
|
||||
|
||||
### Repository Structure
|
||||
|
||||
The `src/` directory contains:
|
||||
|
||||
```
|
||||
src/
|
||||
├── component.php # Template file
|
||||
├── error.php # Template file
|
||||
├── index.php # Main template file
|
||||
├── offline.php # Template file
|
||||
├── templateDetails.xml # Template manifest
|
||||
├── joomla.asset.json # Asset registration
|
||||
├── html/ # Module & component overrides
|
||||
├── language/ # Frontend language files
|
||||
├── administrator/ # Backend language files
|
||||
│ └── language/
|
||||
└── media/ # Assets (CSS, JS, images, fonts)
|
||||
├── css/
|
||||
├── js/
|
||||
├── images/
|
||||
└── fonts/
|
||||
```
|
||||
|
||||
### Joomla Installation Structure
|
||||
|
||||
Joomla expects template files in these locations:
|
||||
|
||||
```
|
||||
YOUR_JOOMLA_ROOT/
|
||||
├── templates/
|
||||
│ └── mokocassiopeia/ # Template files go here
|
||||
│ ├── component.php
|
||||
│ ├── error.php
|
||||
│ ├── index.php
|
||||
│ ├── offline.php
|
||||
│ ├── templateDetails.xml
|
||||
│ ├── joomla.asset.json
|
||||
│ ├── html/
|
||||
│ ├── language/
|
||||
│ └── administrator/
|
||||
└── media/
|
||||
└── templates/
|
||||
└── site/
|
||||
└── mokocassiopeia/ # Media files go here
|
||||
├── css/
|
||||
├── js/
|
||||
├── images/
|
||||
└── fonts/
|
||||
```
|
||||
|
||||
**Key Point**: Template files and media files go to **different locations** in Joomla!
|
||||
|
||||
## Manual Deployment Methods
|
||||
|
||||
### Method 1: Recommended - Upload as ZIP (Still Manual)
|
||||
|
||||
This method mimics what Joomla's installer does automatically.
|
||||
|
||||
1. **Prepare the template directory**:
|
||||
```bash
|
||||
# From the repository root
|
||||
cd src
|
||||
|
||||
# Copy all files EXCEPT media to a temp directory
|
||||
mkdir -p /tmp/mokocassiopeia
|
||||
cp component.php /tmp/mokocassiopeia/
|
||||
cp error.php /tmp/mokocassiopeia/
|
||||
cp index.php /tmp/mokocassiopeia/
|
||||
cp offline.php /tmp/mokocassiopeia/
|
||||
cp templateDetails.xml /tmp/mokocassiopeia/
|
||||
cp joomla.asset.json /tmp/mokocassiopeia/
|
||||
cp -r html /tmp/mokocassiopeia/
|
||||
cp -r language /tmp/mokocassiopeia/
|
||||
cp -r administrator /tmp/mokocassiopeia/
|
||||
|
||||
# Copy media to a separate temp directory
|
||||
mkdir -p /tmp/mokocassiopeia_media
|
||||
cp -r media/* /tmp/mokocassiopeia_media/
|
||||
```
|
||||
|
||||
2. **Upload to Joomla via FTP/SFTP**:
|
||||
```bash
|
||||
# Upload template files
|
||||
# Replace with your actual Joomla path
|
||||
scp -r /tmp/mokocassiopeia/* user@yourserver:/path/to/joomla/templates/mokocassiopeia/
|
||||
|
||||
# Upload media files
|
||||
scp -r /tmp/mokocassiopeia_media/* user@yourserver:/path/to/joomla/media/templates/site/mokocassiopeia/
|
||||
```
|
||||
|
||||
3. **Set proper permissions**:
|
||||
```bash
|
||||
# On your server
|
||||
cd /path/to/joomla
|
||||
chmod 755 templates/mokocassiopeia
|
||||
chmod 644 templates/mokocassiopeia/*
|
||||
chmod 755 templates/mokocassiopeia/html
|
||||
chmod 755 media/templates/site/mokocassiopeia
|
||||
```
|
||||
|
||||
### Method 2: Direct Copy to Existing Installation
|
||||
|
||||
If you have direct filesystem access (e.g., local development):
|
||||
|
||||
1. **Copy template files** (excluding media):
|
||||
```bash
|
||||
# From repository root
|
||||
cd src
|
||||
|
||||
# Copy to Joomla templates directory
|
||||
cp component.php /path/to/joomla/templates/mokocassiopeia/
|
||||
cp error.php /path/to/joomla/templates/mokocassiopeia/
|
||||
cp index.php /path/to/joomla/templates/mokocassiopeia/
|
||||
cp offline.php /path/to/joomla/templates/mokocassiopeia/
|
||||
cp templateDetails.xml /path/to/joomla/templates/mokocassiopeia/
|
||||
cp joomla.asset.json /path/to/joomla/templates/mokocassiopeia/
|
||||
|
||||
# Copy directories
|
||||
cp -r html /path/to/joomla/templates/mokocassiopeia/
|
||||
cp -r language /path/to/joomla/templates/mokocassiopeia/
|
||||
cp -r administrator /path/to/joomla/templates/mokocassiopeia/
|
||||
```
|
||||
|
||||
2. **Copy media files separately**:
|
||||
```bash
|
||||
# Copy media to the media directory
|
||||
cp -r media/* /path/to/joomla/media/templates/site/mokocassiopeia/
|
||||
```
|
||||
|
||||
3. **Clear Joomla cache**:
|
||||
- In Joomla admin: **System → Clear Cache**
|
||||
- Or delete: `/path/to/joomla/cache/*` and `/path/to/joomla/administrator/cache/*`
|
||||
|
||||
### Method 3: Symlink for Development (Linux/Mac only)
|
||||
|
||||
For active development where you want changes to immediately reflect:
|
||||
|
||||
1. **Create symlinks**:
|
||||
```bash
|
||||
# Remove existing directory if present
|
||||
rm -rf /path/to/joomla/templates/mokocassiopeia
|
||||
rm -rf /path/to/joomla/media/templates/site/mokocassiopeia
|
||||
|
||||
# Create parent directories if needed
|
||||
mkdir -p /path/to/joomla/templates
|
||||
mkdir -p /path/to/joomla/media/templates/site
|
||||
|
||||
# Symlink template files
|
||||
ln -s /path/to/MokoCassiopeia/src /path/to/joomla/templates/mokocassiopeia
|
||||
|
||||
# Symlink media files
|
||||
ln -s /path/to/MokoCassiopeia/src/media /path/to/joomla/media/templates/site/mokocassiopeia
|
||||
```
|
||||
|
||||
2. **Note**: This won't work as-is because the src directory includes the media folder. You'll need to:
|
||||
```bash
|
||||
# Better approach for symlinks:
|
||||
# Link everything except media at template root
|
||||
cd /path/to/joomla/templates
|
||||
mkdir -p mokocassiopeia
|
||||
cd mokocassiopeia
|
||||
|
||||
ln -s /path/to/MokoCassiopeia/src/component.php
|
||||
ln -s /path/to/MokoCassiopeia/src/error.php
|
||||
ln -s /path/to/MokoCassiopeia/src/index.php
|
||||
ln -s /path/to/MokoCassiopeia/src/offline.php
|
||||
ln -s /path/to/MokoCassiopeia/src/templateDetails.xml
|
||||
ln -s /path/to/MokoCassiopeia/src/joomla.asset.json
|
||||
ln -s /path/to/MokoCassiopeia/src/html
|
||||
ln -s /path/to/MokoCassiopeia/src/language
|
||||
ln -s /path/to/MokoCassiopeia/src/administrator
|
||||
|
||||
# Link media separately
|
||||
ln -s /path/to/MokoCassiopeia/src/media /path/to/joomla/media/templates/site/mokocassiopeia
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Language Files Not Loading
|
||||
|
||||
**Problem**: Language strings appear as language keys (e.g., `TPL_MOKOCASSIOPEIA_LABEL`)
|
||||
|
||||
**Solution**: Ensure the `language` and `administrator` folders are present in your template directory:
|
||||
|
||||
```bash
|
||||
# Check if folders exist
|
||||
ls -la /path/to/joomla/templates/mokocassiopeia/language
|
||||
ls -la /path/to/joomla/templates/mokocassiopeia/administrator
|
||||
```
|
||||
|
||||
The `templateDetails.xml` should contain (lines 54-55):
|
||||
```xml
|
||||
<files>
|
||||
<!-- ... other files ... -->
|
||||
<folder>language</folder>
|
||||
<folder>administrator</folder>
|
||||
</files>
|
||||
```
|
||||
|
||||
### CSS/JS Not Loading
|
||||
|
||||
**Problem**: Styles or scripts don't apply
|
||||
|
||||
**Solution**: Verify media files are in the correct location:
|
||||
|
||||
```bash
|
||||
# Check media directory structure
|
||||
ls -la /path/to/joomla/media/templates/site/mokocassiopeia/
|
||||
# Should show: css/, js/, images/, fonts/
|
||||
```
|
||||
|
||||
Clear Joomla cache:
|
||||
- Admin: **System → Clear Cache**
|
||||
- Check browser developer console for 404 errors
|
||||
|
||||
### Template Not Appearing in Template Manager
|
||||
|
||||
**Problem**: MokoCassiopeia doesn't show in **System → Site Templates**
|
||||
|
||||
**Solution**:
|
||||
1. Verify `templateDetails.xml` is present in `/path/to/joomla/templates/mokocassiopeia/`
|
||||
2. Check file permissions (should be readable by web server)
|
||||
3. Verify XML is well-formed:
|
||||
```bash
|
||||
xmllint --noout /path/to/joomla/templates/mokocassiopeia/templateDetails.xml
|
||||
```
|
||||
4. Check Joomla's error logs for XML parsing errors
|
||||
|
||||
### File Permission Issues
|
||||
|
||||
**Problem**: "Permission denied" or template files not readable
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
# Set proper ownership (replace www-data with your web server user)
|
||||
chown -R www-data:www-data /path/to/joomla/templates/mokocassiopeia
|
||||
chown -R www-data:www-data /path/to/joomla/media/templates/site/mokocassiopeia
|
||||
|
||||
# Set proper permissions
|
||||
find /path/to/joomla/templates/mokocassiopeia -type d -exec chmod 755 {} \;
|
||||
find /path/to/joomla/templates/mokocassiopeia -type f -exec chmod 644 {} \;
|
||||
find /path/to/joomla/media/templates/site/mokocassiopeia -type d -exec chmod 755 {} \;
|
||||
find /path/to/joomla/media/templates/site/mokocassiopeia -type f -exec chmod 644 {} \;
|
||||
```
|
||||
|
||||
## When to Use Manual Deployment
|
||||
|
||||
### ✅ Use Manual Deployment For:
|
||||
|
||||
- **Active Development**: Testing changes immediately without rebuilding packages
|
||||
- **Local Development**: Working on a local Joomla instance
|
||||
- **Quick Fixes**: Making emergency hotfixes directly on a development server
|
||||
- **Learning**: Understanding the template structure and Joomla's file organization
|
||||
|
||||
### ❌ Don't Use Manual Deployment For:
|
||||
|
||||
- **Production Sites**: Always use packaged ZIP files from releases
|
||||
- **Client Sites**: Use proper Joomla extension installation
|
||||
- **Version Control**: Can lead to inconsistent deployments
|
||||
- **Staging Environments**: Use CI/CD or release packages
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always Test Locally First**: Don't deploy untested changes to production
|
||||
2. **Keep Backups**: Back up both template and media directories before updating
|
||||
3. **Use Version Control**: Track your customizations separately from manual deployments
|
||||
4. **Document Changes**: Note any manual file modifications
|
||||
5. **Clear Cache**: Always clear Joomla cache after manual file updates
|
||||
6. **Verify Permissions**: Ensure web server can read all files
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- **[Quick Start Guide](QUICK_START.md)** - Development environment setup
|
||||
- **[Joomla Development Guide](JOOMLA_DEVELOPMENT.md)** - Complete development workflows
|
||||
- **[Release Process](RELEASE_PROCESS.md)** - How to create proper release packages
|
||||
|
||||
## Support
|
||||
|
||||
If you encounter issues with manual deployment:
|
||||
|
||||
1. Check this troubleshooting guide first
|
||||
2. Review [Joomla's template documentation](https://docs.joomla.org/J4.x:Creating_a_Simple_Template)
|
||||
3. Open an issue on [GitHub](https://github.com/mokoconsulting-tech/MokoCassiopeia/issues)
|
||||
4. Contact: hello@mokoconsulting.tech
|
||||
|
||||
---
|
||||
|
||||
**Document Version**: 1.0.0
|
||||
**Last Updated**: 2026-03-01
|
||||
**Status**: Active
|
||||
@@ -24,7 +24,7 @@
|
||||
INGROUP: MokoCassiopeia.Documentation
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
FILE: docs/MODULE_OVERRIDES.md
|
||||
VERSION: 03.08.00
|
||||
VERSION: 03.08.03
|
||||
BRIEF: Comprehensive guide to MokoCassiopeia mobile-responsive module overrides
|
||||
PATH: /docs/MODULE_OVERRIDES.md
|
||||
-->
|
||||
@@ -35,7 +35,20 @@ This document provides a comprehensive guide to all mobile-responsive module and
|
||||
|
||||
## Overview
|
||||
|
||||
MokoCassiopeia includes **20 mobile-responsive module overrides** and **7 component view overrides** designed to enhance the mobile user experience across standard Joomla, VirtueMart, Community Builder, and popular third-party extensions.
|
||||
MokoCassiopeia includes **16 mobile-responsive module overrides** and **12 component view overrides** designed to enhance the mobile user experience for third-party extensions and the Main Menu navigation.
|
||||
|
||||
**Important**: Following Cassiopeia template best practices, MokoCassiopeia avoids overriding standard Joomla core modules (such as mod_search, mod_login, mod_breadcrumbs) to ensure proper language loading and compatibility. **Exception**: mod_menu "Main Menu" override provides essential Bootstrap 5 collapsible dropdown functionality.
|
||||
|
||||
### Alternative Layouts, Not Replacements
|
||||
|
||||
**All MokoCassiopeia overrides use alternative layout names (`mobile.php`) instead of replacing default layouts (`default.php`).** This means:
|
||||
|
||||
- ✅ Default Joomla layouts continue to work unchanged
|
||||
- ✅ You must explicitly select the "mobile" layout in module/menu item settings
|
||||
- ✅ Joomla core updates don't break your site
|
||||
- ✅ Full control over which modules use enhanced layouts
|
||||
|
||||
**📖 See [OVERRIDE_PHILOSOPHY.md](OVERRIDE_PHILOSOPHY.md) for complete details on how to activate and use these alternative layouts.**
|
||||
|
||||
### Key Features
|
||||
|
||||
@@ -52,31 +65,14 @@ All module overrides share these characteristics:
|
||||
|
||||
## Module Categories
|
||||
|
||||
### 1. Search Module
|
||||
|
||||
#### mod_search
|
||||
**Location**: `src/templates/html/mod_search/`
|
||||
|
||||
Search box with multiple button position options and responsive design.
|
||||
|
||||
**Features**:
|
||||
- Button positions: left, right, top, bottom
|
||||
- Text, icon, or both display modes
|
||||
- 48px touch targets on mobile
|
||||
- Prevents iOS zoom with 16px input font
|
||||
|
||||
**Documentation**: [mod_search/README.md](../src/templates/html/mod_search/README.md)
|
||||
|
||||
---
|
||||
|
||||
### 2. VirtueMart E-Commerce Modules
|
||||
### 1. VirtueMart E-Commerce Modules
|
||||
|
||||
Five comprehensive overrides for VirtueMart shopping functionality.
|
||||
|
||||
**Master Documentation**: [VIRTUEMART_MODULES_README.md](../src/templates/html/VIRTUEMART_MODULES_README.md)
|
||||
**Master Documentation**: [VIRTUEMART_MODULES_README.md](../src/html/VIRTUEMART_MODULES_README.md)
|
||||
|
||||
#### mod_virtuemart_cart
|
||||
**Location**: `src/templates/html/mod_virtuemart_cart/`
|
||||
**Location**: `src/html/mod_virtuemart_cart/`
|
||||
|
||||
Shopping cart display with product list and checkout button.
|
||||
|
||||
@@ -87,7 +83,7 @@ Shopping cart display with product list and checkout button.
|
||||
- Checkout button with prominent styling
|
||||
|
||||
#### mod_virtuemart_product
|
||||
**Location**: `src/templates/html/mod_virtuemart_product/`
|
||||
**Location**: `src/html/mod_virtuemart_product/`
|
||||
|
||||
Product showcase with grid layouts.
|
||||
|
||||
@@ -98,7 +94,7 @@ Product showcase with grid layouts.
|
||||
- Rating display support
|
||||
|
||||
#### mod_virtuemart_currencies
|
||||
**Location**: `src/templates/html/mod_virtuemart_currencies/`
|
||||
**Location**: `src/html/mod_virtuemart_currencies/`
|
||||
|
||||
Currency selector dropdown for multi-currency stores.
|
||||
|
||||
@@ -108,7 +104,7 @@ Currency selector dropdown for multi-currency stores.
|
||||
- Responsive button styling
|
||||
|
||||
#### mod_virtuemart_category
|
||||
**Location**: `src/templates/html/mod_virtuemart_category/`
|
||||
**Location**: `src/html/mod_virtuemart_category/`
|
||||
|
||||
Category navigation with hierarchical display.
|
||||
|
||||
@@ -119,7 +115,7 @@ Category navigation with hierarchical display.
|
||||
- Active category highlighting
|
||||
|
||||
#### mod_virtuemart_manufacturer
|
||||
**Location**: `src/templates/html/mod_virtuemart_manufacturer/`
|
||||
**Location**: `src/html/mod_virtuemart_manufacturer/`
|
||||
|
||||
Manufacturer/brand display with grid layout.
|
||||
|
||||
@@ -130,63 +126,37 @@ Manufacturer/brand display with grid layout.
|
||||
|
||||
---
|
||||
|
||||
### 3. Standard Joomla & Community Builder Modules
|
||||
### 2. Main Menu & Community Builder Modules
|
||||
|
||||
Six essential Joomla core and Community Builder module overrides.
|
||||
Three essential Community Builder and navigation module overrides.
|
||||
|
||||
**Master Documentation**: [STANDARD_MODULES_README.md](../src/templates/html/STANDARD_MODULES_README.md)
|
||||
#### mod_menu (Main Menu)
|
||||
**Location**: `src/html/mod_menu/`
|
||||
|
||||
#### mod_menu
|
||||
**Location**: `src/templates/html/mod_menu/`
|
||||
|
||||
Main navigation menu with multiple layout files.
|
||||
|
||||
**Features**:
|
||||
- Responsive horizontal/vertical layouts
|
||||
- Multi-level menu support
|
||||
- Active state highlighting
|
||||
- Keyboard navigation
|
||||
Bootstrap 5 responsive navigation menu with collapsible dropdown functionality.
|
||||
|
||||
**Files**:
|
||||
- `default.php` - Main menu layout
|
||||
- `default_component.php` - Component links
|
||||
- `default_url.php` - External URLs
|
||||
|
||||
#### mod_breadcrumbs
|
||||
**Location**: `src/templates/html/mod_breadcrumbs/`
|
||||
|
||||
Breadcrumb navigation with Schema.org markup.
|
||||
- `mainmenu.php` - Main layout with Bootstrap navbar
|
||||
- `mainmenu_component.php` - Component menu items
|
||||
- `mainmenu_heading.php` - Heading menu items
|
||||
- `mainmenu_separator.php` - Separator menu items
|
||||
- `mainmenu_url.php` - URL menu items
|
||||
|
||||
**Features**:
|
||||
- Structured data for SEO
|
||||
- Responsive text truncation
|
||||
- Proper separators
|
||||
- Home icon support
|
||||
- Bootstrap 5 navbar structure with collapsible hamburger menu
|
||||
- Multi-level dropdown support (hover on desktop, tap on mobile)
|
||||
- WCAG 2.1 compliant touch targets (48px mobile, 44px desktop)
|
||||
- BEM naming convention: `.mod-menu-main__*`
|
||||
- Active state indicators for current menu items
|
||||
- ARIA labels and keyboard navigation support
|
||||
- Alternative layout named `mainmenu.php` (not `default.php`)
|
||||
|
||||
#### mod_login
|
||||
**Location**: `src/templates/html/mod_login/`
|
||||
**Activation**: Select "Mainmenu" layout in Joomla Administrator → Modules → Menu Module → Advanced Tab → Alternative Layout
|
||||
|
||||
User login/logout form with 2FA support.
|
||||
|
||||
**Features**:
|
||||
- Login and logout states
|
||||
- Two-factor authentication fields
|
||||
- Remember me checkbox
|
||||
- User greeting when logged in
|
||||
|
||||
#### mod_articles_latest
|
||||
**Location**: `src/templates/html/mod_articles_latest/`
|
||||
|
||||
Latest articles display with metadata.
|
||||
|
||||
**Features**:
|
||||
- Responsive article cards
|
||||
- Author, date, category metadata
|
||||
- Read more links
|
||||
- Featured article badges
|
||||
**Note**: Unlike the broken mod_menu override removed in v03.08.01, this v03.08.03 version is properly structured based on Joomla core layouts and Bootstrap 5, ensuring language strings load correctly and menu functionality works as expected.
|
||||
|
||||
#### mod_cblogin
|
||||
**Location**: `src/templates/html/mod_cblogin/`
|
||||
**Location**: `src/html/mod_cblogin/`
|
||||
|
||||
Community Builder login with avatar display.
|
||||
|
||||
@@ -197,7 +167,7 @@ Community Builder login with avatar display.
|
||||
- Logout button
|
||||
|
||||
#### mod_comprofilerOnline
|
||||
**Location**: `src/templates/html/mod_comprofilerOnline/`
|
||||
**Location**: `src/html/mod_comprofilerOnline/`
|
||||
|
||||
Community Builder online users display.
|
||||
|
||||
@@ -209,16 +179,14 @@ Community Builder online users display.
|
||||
|
||||
---
|
||||
|
||||
### 4. Industry Extension Modules
|
||||
### 3. Industry Extension Modules
|
||||
|
||||
Eight popular third-party extension module overrides plus component views.
|
||||
|
||||
**Master Documentation**: [INDUSTRY_MODULES_README.md](../src/templates/html/INDUSTRY_MODULES_README.md)
|
||||
|
||||
#### K2 Content Extension
|
||||
|
||||
##### mod_k2_content
|
||||
**Location**: `src/templates/html/mod_k2_content/`
|
||||
**Location**: `src/html/mod_k2_content/`
|
||||
|
||||
K2 content display with advanced layouts.
|
||||
|
||||
@@ -232,7 +200,7 @@ K2 content display with advanced layouts.
|
||||
#### AcyMailing Newsletter
|
||||
|
||||
##### mod_acymailing
|
||||
**Location**: `src/templates/html/mod_acymailing/`
|
||||
**Location**: `src/html/mod_acymailing/`
|
||||
|
||||
Newsletter subscription form.
|
||||
|
||||
@@ -245,7 +213,7 @@ Newsletter subscription form.
|
||||
#### HikaShop E-Commerce
|
||||
|
||||
##### mod_hikashop_cart
|
||||
**Location**: `src/templates/html/mod_hikashop_cart/`
|
||||
**Location**: `src/html/mod_hikashop_cart/`
|
||||
|
||||
HikaShop shopping cart module.
|
||||
|
||||
@@ -260,7 +228,7 @@ HikaShop shopping cart module.
|
||||
Four comprehensive forum modules plus component view.
|
||||
|
||||
##### mod_kunenalatest
|
||||
**Location**: `src/templates/html/mod_kunenalatest/`
|
||||
**Location**: `src/html/mod_kunenalatest/`
|
||||
|
||||
Latest forum posts display.
|
||||
|
||||
@@ -271,7 +239,7 @@ Latest forum posts display.
|
||||
- Post date
|
||||
|
||||
##### mod_kunenalogin
|
||||
**Location**: `src/templates/html/mod_kunenalogin/`
|
||||
**Location**: `src/html/mod_kunenalogin/`
|
||||
|
||||
Forum-specific login module.
|
||||
|
||||
@@ -282,7 +250,7 @@ Forum-specific login module.
|
||||
- Profile link
|
||||
|
||||
##### mod_kunenasearch
|
||||
**Location**: `src/templates/html/mod_kunenasearch/`
|
||||
**Location**: `src/html/mod_kunenasearch/`
|
||||
|
||||
Forum search with button positions.
|
||||
|
||||
@@ -293,7 +261,7 @@ Forum search with button positions.
|
||||
- 48px touch targets
|
||||
|
||||
##### mod_kunenastats
|
||||
**Location**: `src/templates/html/mod_kunenastats/`
|
||||
**Location**: `src/html/mod_kunenastats/`
|
||||
|
||||
Forum statistics display.
|
||||
|
||||
@@ -305,7 +273,7 @@ Forum statistics display.
|
||||
- Responsive grid layout
|
||||
|
||||
##### com_kunena (Component)
|
||||
**Location**: `src/templates/html/com_kunena/`
|
||||
**Location**: `src/html/com_kunena/`
|
||||
|
||||
Forum category list view.
|
||||
|
||||
@@ -317,7 +285,7 @@ Forum category list view.
|
||||
Module and component overrides for membership management.
|
||||
|
||||
##### mod_osmembership
|
||||
**Location**: `src/templates/html/mod_osmembership/`
|
||||
**Location**: `src/html/mod_osmembership/`
|
||||
|
||||
Membership plans module.
|
||||
|
||||
@@ -328,7 +296,7 @@ Membership plans module.
|
||||
- Badge displays (popular, featured)
|
||||
|
||||
##### com_osmembership (Component)
|
||||
**Location**: `src/templates/html/com_osmembership/`
|
||||
**Location**: `src/html/com_osmembership/`
|
||||
|
||||
Membership pricing tables.
|
||||
|
||||
@@ -337,12 +305,12 @@ Membership pricing tables.
|
||||
|
||||
---
|
||||
|
||||
### 5. Community Builder Components
|
||||
### 4. Community Builder Components
|
||||
|
||||
Four comprehensive component view overrides for Community Builder user management.
|
||||
|
||||
#### com_comprofiler
|
||||
**Location**: `src/templates/html/com_comprofiler/`
|
||||
**Location**: `src/html/com_comprofiler/`
|
||||
|
||||
Mobile-responsive views for Community Builder user profiles, registration, and login.
|
||||
|
||||
@@ -390,6 +358,79 @@ Login page with remember me and helper links.
|
||||
- CSRF token support
|
||||
- Responsive padding adjustments
|
||||
|
||||
### 5. JEM (Joomla Event Manager) Components
|
||||
|
||||
Five comprehensive component view overrides for JEM event management.
|
||||
|
||||
#### com_jem
|
||||
**Location**: `src/html/com_jem/`
|
||||
|
||||
Mobile-responsive views for JEM event listings, details, calendar, venues, and categories.
|
||||
|
||||
##### eventslist
|
||||
Event listing with card-based layout.
|
||||
|
||||
**Features**:
|
||||
- Event cards with date, time, and venue
|
||||
- Category badges with color coding
|
||||
- Responsive event grid layout
|
||||
- Event description excerpts
|
||||
- Read more buttons with clear calls-to-action
|
||||
- Pagination support
|
||||
- Empty state messaging
|
||||
|
||||
##### event
|
||||
Single event details view with comprehensive information.
|
||||
|
||||
**Features**:
|
||||
- Large event image display (responsive)
|
||||
- Date and time with structured data
|
||||
- Venue information with maps link
|
||||
- Event description with full content
|
||||
- Category display with badges
|
||||
- Registration information (if enabled)
|
||||
- Contact information display
|
||||
- Back to events navigation
|
||||
- Meta information with icons
|
||||
|
||||
##### calendar
|
||||
Monthly calendar view with event indicators.
|
||||
|
||||
**Features**:
|
||||
- Month navigation (previous/next)
|
||||
- Calendar grid with weekday headers
|
||||
- Event indicators on dates with events
|
||||
- Responsive calendar layout
|
||||
- Today highlighting
|
||||
- Event list for selected month
|
||||
- Event count per day display
|
||||
- Touch-friendly navigation buttons
|
||||
|
||||
##### venue
|
||||
Venue details with location and upcoming events.
|
||||
|
||||
**Features**:
|
||||
- Venue image display
|
||||
- Complete address information
|
||||
- Website link (external)
|
||||
- Google Maps integration
|
||||
- Venue description
|
||||
- Upcoming events at venue
|
||||
- Location coordinates display
|
||||
- Back navigation
|
||||
|
||||
##### categories
|
||||
Event category listing with descriptions.
|
||||
|
||||
**Features**:
|
||||
- Category cards with images
|
||||
- Category descriptions
|
||||
- Event count per category
|
||||
- View category buttons
|
||||
- Responsive grid layout
|
||||
- Empty state messaging
|
||||
- Pagination support
|
||||
|
||||
---
|
||||
|
||||
## CSS Architecture
|
||||
@@ -431,6 +472,13 @@ All module styles are located in `src/media/css/template.css` with dedicated sec
|
||||
- Login pages
|
||||
- Tab interfaces
|
||||
|
||||
6. **JEM COMPONENT STYLES** (Lines ~22000+)
|
||||
- Event list cards
|
||||
- Event details layout
|
||||
- Calendar grid
|
||||
- Venue information
|
||||
- Category displays
|
||||
|
||||
### CSS Variables Integration
|
||||
|
||||
All modules integrate with template CSS variables:
|
||||
@@ -509,17 +557,17 @@ Each module can be customized in two ways:
|
||||
Edit `src/media/css/user.css` to add custom styles:
|
||||
|
||||
```css
|
||||
/* Example: Customize search button color */
|
||||
.mod-search__button {
|
||||
background-color: #ff6600;
|
||||
}
|
||||
|
||||
/* Example: Change product grid columns */
|
||||
@media (min-width: 768px) {
|
||||
.mod-vm-product__grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Example: Customize cart button */
|
||||
.mod-vm-cart__checkout-button {
|
||||
background-color: #28a745;
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Template Override Customization
|
||||
@@ -528,10 +576,10 @@ Copy the entire module directory and modify:
|
||||
|
||||
```bash
|
||||
# Keep original override as reference
|
||||
cp -r src/templates/html/mod_search src/templates/html/mod_search_original
|
||||
cp -r src/html/mod_virtuemart_cart src/html/mod_virtuemart_cart_original
|
||||
|
||||
# Modify your version
|
||||
# Edit src/templates/html/mod_search/default.php
|
||||
# Edit src/html/mod_virtuemart_cart/default.php
|
||||
```
|
||||
|
||||
### CSS Variables Override
|
||||
@@ -539,11 +587,11 @@ cp -r src/templates/html/mod_search src/templates/html/mod_search_original
|
||||
Override CSS variables in your custom color scheme:
|
||||
|
||||
```css
|
||||
/* src/media/css/colors/light/colors_custom.css */
|
||||
/* src/media/css/theme/light.custom.css */
|
||||
:root {
|
||||
--mod-search-bg: #f8f9fa;
|
||||
--mod-search-border: #dee2e6;
|
||||
--vm-price-color: #28a745;
|
||||
--vm-cart-bg: #f8f9fa;
|
||||
--vm-button-primary: #007bff;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -604,16 +652,54 @@ Override CSS variables in your custom color scheme:
|
||||
|
||||
---
|
||||
|
||||
## How to Activate Alternative Layouts
|
||||
|
||||
All MokoCassiopeia overrides are **alternative layouts** that must be explicitly activated. They do not automatically replace default layouts.
|
||||
|
||||
### Quick Start: Enable Mobile Layout
|
||||
|
||||
1. **Go to Joomla Administrator** → Extensions → Modules
|
||||
2. **Open the module** you want to enhance (e.g., VirtueMart Cart)
|
||||
3. **Navigate to Advanced tab**
|
||||
4. **Find "Alternative Layout" field**
|
||||
5. **Select "MokoCassiopeia - mobile"** from dropdown
|
||||
6. **Save & Close**
|
||||
|
||||
### For Menu Items (Component Views)
|
||||
|
||||
1. **Go to Menus** → Select your menu
|
||||
2. **Open the menu item** (e.g., Events List)
|
||||
3. **Navigate to Advanced Options or Page Display tab**
|
||||
4. **Find "Alternative Layout" field**
|
||||
5. **Select "MokoCassiopeia - mobile"** from dropdown
|
||||
6. **Save & Close**
|
||||
|
||||
### Apply to All Modules in a Position
|
||||
|
||||
In your template's `index.php`, specify layout for entire module position:
|
||||
|
||||
```php
|
||||
<jdoc:include type="modules" name="sidebar-left" style="none" layout="mobile" />
|
||||
```
|
||||
|
||||
**📖 For complete documentation, see [OVERRIDE_PHILOSOPHY.md](OVERRIDE_PHILOSOPHY.md)**
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Changes |
|
||||
|----------|------------|--------------------------------------------------|
|
||||
| 03.08.04 | 2026-02-27 | Added alternative layout activation instructions, JEM overrides |
|
||||
| 03.08.03 | 2026-02-25 | Removed mod_search override per Cassiopeia philosophy |
|
||||
| 03.08.00 | 2026-02-22 | Added Community Builder component overrides |
|
||||
| 03.07.00 | 2026-02-22 | Initial release of all mobile-responsive overrides |
|
||||
|
||||
---
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- **Override Philosophy**: [OVERRIDE_PHILOSOPHY.md](OVERRIDE_PHILOSOPHY.md) ⭐ **Start here**
|
||||
- **Main README**: [README.md](../README.md)
|
||||
- **Changelog**: [CHANGELOG.md](../CHANGELOG.md)
|
||||
- **CSS Variables**: [CSS_VARIABLES.md](CSS_VARIABLES.md)
|
||||
|
||||
332
docs/OVERRIDE_PHILOSOPHY.md
Normal file
332
docs/OVERRIDE_PHILOSOPHY.md
Normal file
@@ -0,0 +1,332 @@
|
||||
<!--
|
||||
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
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: MokoCassiopeia.Documentation
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
FILE: docs/OVERRIDE_PHILOSOPHY.md
|
||||
VERSION: 03.08.04
|
||||
BRIEF: Philosophy and implementation of non-replacing alternative layouts
|
||||
PATH: /docs/OVERRIDE_PHILOSOPHY.md
|
||||
-->
|
||||
|
||||
# Override Philosophy — MokoCassiopeia
|
||||
|
||||
## Core Principle: Add-On, Not Replacement
|
||||
|
||||
**MokoCassiopeia overrides are designed as alternative layouts, not replacements of default Joomla layouts.**
|
||||
|
||||
This means:
|
||||
- ✅ Default Joomla layouts continue to work unchanged
|
||||
- ✅ Site administrators can choose when to use our enhanced layouts
|
||||
- ✅ Updates to Joomla core layouts don't break the site
|
||||
- ✅ Compatibility with other extensions is maintained
|
||||
- ✅ Users have control over which layouts to use
|
||||
|
||||
---
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Layout Naming Convention
|
||||
|
||||
All MokoCassiopeia overrides use **`mobile.php`** naming instead of **`default.php`**:
|
||||
|
||||
```
|
||||
❌ BAD (Replaces default):
|
||||
src/html/mod_virtuemart_cart/default.php
|
||||
|
||||
✅ GOOD (Alternative layout):
|
||||
src/html/mod_virtuemart_cart/mobile.php
|
||||
```
|
||||
|
||||
### How Joomla Handles Layouts
|
||||
|
||||
When a module or component looks for a layout, Joomla searches in this order:
|
||||
|
||||
1. **Template override with specified layout name**: `templates/mokocassiopeia/html/{extension}/{view}/{layout}.php`
|
||||
2. **Extension's specified layout**: `{extension}/tmpl/{view}/{layout}.php`
|
||||
3. **Template override for default layout**: `templates/mokocassiopeia/html/{extension}/{view}/default.php`
|
||||
4. **Extension's default layout**: `{extension}/tmpl/{view}/default.php`
|
||||
|
||||
By naming our overrides `mobile.php` instead of `default.php`, they become **step 1** alternatives that must be explicitly selected, rather than **step 3** replacements that are automatically used.
|
||||
|
||||
---
|
||||
|
||||
## How to Use Alternative Layouts
|
||||
|
||||
### Method 1: Module/Menu Item Settings
|
||||
|
||||
When editing a module or menu item in Joomla administrator:
|
||||
|
||||
1. Open the module/menu item for editing
|
||||
2. Navigate to the **Advanced** tab
|
||||
3. Find the **Alternative Layout** field
|
||||
4. Select **MokoCassiopeia - mobile** from the dropdown
|
||||
5. Save
|
||||
|
||||
### Method 2: Override in Module Position
|
||||
|
||||
If you want all modules in a specific position to use the mobile layout:
|
||||
|
||||
```php
|
||||
<!-- In your index.php template file -->
|
||||
<?php if ($this->countModules('sidebar-left')) : ?>
|
||||
<jdoc:include type="modules" name="sidebar-left" style="none" layout="mobile" />
|
||||
<?php endif; ?>
|
||||
```
|
||||
|
||||
### Method 3: Module Chrome (Advanced)
|
||||
|
||||
Create a custom module chrome in `templates/mokocassiopeia/html/layouts/chromes/` that automatically applies the mobile layout.
|
||||
|
||||
---
|
||||
|
||||
## Exception: Main Menu
|
||||
|
||||
**The only exception** to this philosophy is `mod_menu` with the "Main Menu" module type.
|
||||
|
||||
The template includes files like:
|
||||
- `src/html/mod_menu/mainmenu.php`
|
||||
- `src/html/mod_menu/mainmenu_component.php`
|
||||
- `src/html/mod_menu/mainmenu_heading.php`
|
||||
- `src/html/mod_menu/mainmenu_url.php`
|
||||
- `src/html/mod_menu/mainmenu_separator.php`
|
||||
|
||||
These use a **custom layout name** (`mainmenu`) instead of replacing `default.php`, which allows the site to:
|
||||
- Use the enhanced Bootstrap 5 collapsible menu for main navigation
|
||||
- Keep standard Joomla menus working in other positions
|
||||
- Provide better mobile navigation without breaking existing menus
|
||||
|
||||
To use this layout, set the module's **Alternative Layout** to **MokoCassiopeia - mainmenu**.
|
||||
|
||||
---
|
||||
|
||||
## Override Inventory
|
||||
|
||||
### Module Overrides (16 total)
|
||||
|
||||
All use `mobile.php` naming (alternative layout):
|
||||
|
||||
**VirtueMart (5)**:
|
||||
- `mod_virtuemart_cart/mobile.php`
|
||||
- `mod_virtuemart_product/mobile.php`
|
||||
- `mod_virtuemart_currencies/mobile.php`
|
||||
- `mod_virtuemart_category/mobile.php`
|
||||
- `mod_virtuemart_manufacturer/mobile.php`
|
||||
|
||||
**Community Builder (2)**:
|
||||
- `mod_cblogin/mobile.php`
|
||||
- `mod_comprofilerOnline/mobile.php`
|
||||
|
||||
**Main Menu (1)**:
|
||||
- `mod_menu/mainmenu.php` (custom layout name)
|
||||
|
||||
**Industry Extensions (8)**:
|
||||
- `mod_k2_content/mobile.php`
|
||||
- `mod_acymailing/mobile.php`
|
||||
- `mod_hikashop_cart/mobile.php`
|
||||
- `mod_kunenalatest/mobile.php`
|
||||
- `mod_kunenalogin/mobile.php`
|
||||
- `mod_kunenasearch/mobile.php`
|
||||
- `mod_kunenastats/mobile.php`
|
||||
- `mod_osmembership/mobile.php`
|
||||
|
||||
### Component View Overrides (12 total)
|
||||
|
||||
All use `mobile.php` naming (alternative layout):
|
||||
|
||||
**Community Builder (4)**:
|
||||
- `com_comprofiler/userprofile/mobile.php`
|
||||
- `com_comprofiler/userslist/mobile.php`
|
||||
- `com_comprofiler/registers/mobile.php`
|
||||
- `com_comprofiler/login/mobile.php`
|
||||
|
||||
**JEM - Joomla Event Manager (5)**:
|
||||
- `com_jem/eventslist/mobile.php`
|
||||
- `com_jem/event/mobile.php`
|
||||
- `com_jem/calendar/mobile.php`
|
||||
- `com_jem/venue/mobile.php`
|
||||
- `com_jem/categories/mobile.php`
|
||||
|
||||
**Kunena Forum (1)**:
|
||||
- `com_kunena/category/mobile.php`
|
||||
|
||||
**OSMembership (2)**:
|
||||
- `com_osmembership/plan/mobile.php`
|
||||
- `com_osmembership/plans/mobile.php`
|
||||
|
||||
**Joomla Core (2)**:
|
||||
- `com_content/article/toc-left.php` (custom layout name)
|
||||
- `com_content/article/toc-right.php` (custom layout name)
|
||||
|
||||
---
|
||||
|
||||
## Benefits of This Approach
|
||||
|
||||
### 1. **Zero Breaking Changes**
|
||||
|
||||
Existing sites continue to work exactly as before. No layouts are forcibly changed.
|
||||
|
||||
### 2. **Gradual Adoption**
|
||||
|
||||
Site administrators can:
|
||||
- Test mobile layouts on specific modules first
|
||||
- Roll out changes module-by-module
|
||||
- Keep some modules using default layouts if needed
|
||||
- Easily revert by changing the Alternative Layout setting
|
||||
|
||||
### 3. **Extension Compatibility**
|
||||
|
||||
Third-party extensions' default layouts remain untouched, preventing conflicts with:
|
||||
- Extension updates
|
||||
- Other templates
|
||||
- Custom development
|
||||
|
||||
### 4. **Joomla Core Updates**
|
||||
|
||||
When Joomla core updates:
|
||||
- Default layouts get new features/bug fixes automatically
|
||||
- Mobile layouts remain stable and tested
|
||||
- No emergency fixes needed after Joomla updates
|
||||
|
||||
### 5. **Multi-Language Support**
|
||||
|
||||
Joomla's language system loads extension language files properly because:
|
||||
- Extensions aren't hijacked by template overrides
|
||||
- Language strings come from the correct source
|
||||
- Translations work as expected
|
||||
|
||||
---
|
||||
|
||||
## Standards Not Overridden
|
||||
|
||||
Following Cassiopeia template best practices, MokoCassiopeia **does not override** standard Joomla core modules:
|
||||
|
||||
- ❌ `mod_breadcrumbs` - Use Joomla core layout
|
||||
- ❌ `mod_login` - Use Joomla core layout
|
||||
- ❌ `mod_articles_latest` - Use Joomla core layout
|
||||
- ❌ `mod_articles_category` - Use Joomla core layout
|
||||
- ❌ `mod_articles_news` - Use Joomla core layout
|
||||
- ❌ `mod_search` - Use Joomla core layout (removed in v03.08.03)
|
||||
|
||||
**Reason**: These modules have robust core layouts with proper language loading, accessibility, and ongoing Joomla maintenance.
|
||||
|
||||
---
|
||||
|
||||
## Developer Guidelines
|
||||
|
||||
When adding new overrides to MokoCassiopeia:
|
||||
|
||||
### ✅ DO:
|
||||
|
||||
1. Name files `mobile.php` or use descriptive custom names (`mainmenu.php`, `toc-left.php`)
|
||||
2. Document the alternative layout in MODULE_OVERRIDES.md
|
||||
3. Add CSS with BEM naming: `.{extension}-{view}__element`
|
||||
4. Test that default layouts still work
|
||||
5. Provide clear instructions for selecting the layout
|
||||
|
||||
### ❌ DON'T:
|
||||
|
||||
1. Create `default.php` files that replace core layouts
|
||||
2. Override standard Joomla core modules without strong justification
|
||||
3. Break backward compatibility
|
||||
4. Assume users will automatically get your layout
|
||||
5. Forget to document how to enable the alternative layout
|
||||
|
||||
---
|
||||
|
||||
## Migration from Replacing Overrides
|
||||
|
||||
If you're migrating from a template that used `default.php` overrides:
|
||||
|
||||
### Step 1: Identify Replaced Layouts
|
||||
|
||||
```bash
|
||||
find templates/oldtemplate/html -name "default.php"
|
||||
```
|
||||
|
||||
### Step 2: Rename to Alternative Layouts
|
||||
|
||||
```bash
|
||||
# For each default.php found:
|
||||
mv default.php mobile.php
|
||||
```
|
||||
|
||||
### Step 3: Update Module Settings
|
||||
|
||||
For each module using the old override:
|
||||
1. Edit module in administrator
|
||||
2. Advanced tab → Alternative Layout
|
||||
3. Select "mobile" from dropdown
|
||||
4. Save
|
||||
|
||||
### Step 4: Test
|
||||
|
||||
- Verify module displays correctly
|
||||
- Check that other modules still use default layouts
|
||||
- Confirm language strings load properly
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### My Alternative Layout Doesn't Appear in Dropdown
|
||||
|
||||
**Check:**
|
||||
1. File is in correct location: `templates/mokocassiopeia/html/{extension}/{view}/`
|
||||
2. File has `.php` extension
|
||||
3. File is not named `default.php`
|
||||
4. Cache is cleared (System → Clear Cache)
|
||||
|
||||
### Module Still Uses Default Layout
|
||||
|
||||
**Check:**
|
||||
1. Module's Alternative Layout setting in administrator
|
||||
2. Module position's `layout` parameter in `<jdoc:include>` tag
|
||||
3. File permissions (must be readable)
|
||||
4. Template is assigned to correct pages
|
||||
|
||||
### Layout Works But Looks Wrong
|
||||
|
||||
**Check:**
|
||||
1. CSS is loaded: inspect element and check for `.{extension}-{view}__` classes
|
||||
2. `template.css` is up to date
|
||||
3. Browser cache is cleared
|
||||
4. CSS variables are defined in template
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [Joomla Docs: Layout Overrides](https://docs.joomla.org/Layout_Overrides_in_Joomla)
|
||||
- [Joomla Docs: Alternative Layouts](https://docs.joomla.org/J3.x:How_to_use_the_alternative_layout_feature)
|
||||
- [MODULE_OVERRIDES.md](MODULE_OVERRIDES.md) - Complete override inventory
|
||||
- [CSS_VARIABLES.md](CSS_VARIABLES.md) - Template styling system
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
- **03.08.04**: Created OVERRIDE_PHILOSOPHY.md document
|
||||
- **03.08.03**: Removed mod_search override to align with philosophy
|
||||
- **03.08.02**: Removed standard Joomla module overrides for proper language loading
|
||||
- **Earlier**: Renamed all overrides from default.php to mobile.php (21 files)
|
||||
@@ -50,7 +50,7 @@ make validate
|
||||
|
||||
```bash
|
||||
# 1. Make your changes
|
||||
vim src/templates/index.php
|
||||
vim src/index.php
|
||||
|
||||
# 2. Validate locally
|
||||
make validate-required
|
||||
@@ -143,13 +143,20 @@ make all # Complete build pipeline
|
||||
|
||||
```
|
||||
moko-cassiopeia/
|
||||
├── src/ # Joomla template source
|
||||
│ ├── templates/ # Template files
|
||||
│ ├── media/ # Assets (CSS, JS, images)
|
||||
│ ├── language/ # Language files
|
||||
│ └── administrator/ # Admin files
|
||||
├── src/ # Joomla template source (template root)
|
||||
│ ├── component.php # Component template file
|
||||
│ ├── index.php # Main template file
|
||||
│ ├── offline.php # Offline page template
|
||||
│ ├── error.php # Error page template
|
||||
│ ├── templateDetails.xml # Template manifest
|
||||
│ ├── html/ # Module & component overrides
|
||||
│ ├── media/ # Assets (CSS, JS, images, fonts)
|
||||
│ ├── language/ # Frontend language files (en-GB, en-US)
|
||||
│ └── administrator/ # Backend files
|
||||
│ └── language/ # Backend language files
|
||||
├── tests/ # Test suites
|
||||
├── docs/ # Documentation
|
||||
├── scripts/ # Build scripts
|
||||
├── .github/workflows/ # CI/CD workflows
|
||||
├── Makefile # Make commands
|
||||
└── README.md # Project overview
|
||||
@@ -179,7 +186,7 @@ moko-cassiopeia/
|
||||
3. **Make changes and test**:
|
||||
```bash
|
||||
# Edit files
|
||||
vim src/templates/index.php
|
||||
vim src/index.php
|
||||
|
||||
# Validate
|
||||
make validate-required
|
||||
|
||||
@@ -45,15 +45,27 @@ This directory contains comprehensive documentation for the MokoCassiopeia Jooml
|
||||
* **[Workflow Guide](WORKFLOW_GUIDE.md)** - Complete workflow reference
|
||||
* Git branching strategy
|
||||
* Development workflow
|
||||
* Release process
|
||||
* Pull request guidelines
|
||||
|
||||
* **[Release Process](RELEASE_PROCESS.md)** ⭐ - Complete release documentation
|
||||
* Automated release workflow with GitHub Actions
|
||||
* Manual release procedures
|
||||
* Update server configuration
|
||||
* Testing and rollback procedures
|
||||
* Build scripts and tools
|
||||
|
||||
* **[Joomla Development Guide](JOOMLA_DEVELOPMENT.md)** - Joomla-specific development
|
||||
* Testing with Codeception
|
||||
* PHP quality checks (PHPStan, PHPCS)
|
||||
* Joomla extension packaging
|
||||
* Multi-version testing
|
||||
|
||||
* **[Manual Deployment Guide](MANUAL_DEPLOYMENT.md)** - Deploy src directory without building
|
||||
* Understanding src vs. installed structure
|
||||
* Manual deployment methods (copy, symlink)
|
||||
* Troubleshooting language files and media
|
||||
* Best practices for development deployments
|
||||
|
||||
* **[CSS Variables Reference](CSS_VARIABLES.md)** - Complete CSS customization guide
|
||||
* All available CSS variables
|
||||
* Custom color palette creation
|
||||
@@ -61,11 +73,17 @@ This directory contains comprehensive documentation for the MokoCassiopeia Jooml
|
||||
* Light and dark mode theming
|
||||
|
||||
* **[Module & Component Overrides](MODULE_OVERRIDES.md)** - Mobile-responsive overrides guide
|
||||
* 20 module overrides + 3 component overrides
|
||||
* VirtueMart, Joomla core, Community Builder, industry extensions
|
||||
* 16 module overrides + 12 component overrides
|
||||
* VirtueMart, Community Builder, JEM, Kunena, industry extensions
|
||||
* Mobile-first responsive design patterns
|
||||
* Accessibility features and customization
|
||||
|
||||
* **[Override Philosophy](OVERRIDE_PHILOSOPHY.md)** ⭐ - Alternative layouts, not replacements
|
||||
* Why overrides use `mobile.php` naming instead of `default.php`
|
||||
* How to activate alternative layouts in Joomla
|
||||
* Benefits of non-replacing overrides
|
||||
* Developer guidelines and best practices
|
||||
|
||||
* **[Roadmap](ROADMAP.md)** - Version-specific roadmap
|
||||
* Current features (v03.07.00)
|
||||
* Feature evolution timeline
|
||||
@@ -76,21 +94,6 @@ This directory contains comprehensive documentation for the MokoCassiopeia Jooml
|
||||
|
||||
For end-user documentation, installation instructions, and feature guides, see the main [README.md](../README.md) in the repository root.
|
||||
|
||||
### Client Fork Documentation
|
||||
|
||||
* **[Client Fork Workflow](CLIENT_FORK_WORKFLOW.md)** - Automated client fork creation
|
||||
* GitHub Actions workflow for instant fork setup
|
||||
* Local bash script alternative
|
||||
* Complete setup automation in minutes
|
||||
* Post-setup customization guide
|
||||
|
||||
* **[Client Fork Guide](../CLIENT_FORK_README.md)** - Comprehensive guide for client custom code forks
|
||||
* Setting up custom branding and colors
|
||||
* Maintaining fork-specific customizations
|
||||
* Syncing with upstream MokoCassiopeia
|
||||
* Deployment and development workflows
|
||||
* Template README for client forks
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
@@ -103,20 +106,32 @@ moko-cassiopeia/
|
||||
│ ├── CSS_VARIABLES.md # CSS variables reference
|
||||
│ ├── MODULE_OVERRIDES.md # Module & component overrides guide
|
||||
│ └── ROADMAP.md # Version-specific roadmap
|
||||
├── src/ # Template source code
|
||||
│ ├── templates/ # Joomla template files
|
||||
│ │ └── html/ # Module & component overrides (20 modules, 3 components)
|
||||
│ ├── media/ # Assets (CSS, JS, images)
|
||||
│ │ └── css/colors/ # Color schemes (light/dark subdirectories)
|
||||
│ │ ├── light/ # Light mode color files (colors_custom.css)
|
||||
│ │ └── dark/ # Dark mode color files (colors_custom.css)
|
||||
│ └── language/ # Translation files
|
||||
├── templates/ # Template files for customization
|
||||
│ ├── colors_custom.css # Custom color palette template (copy to src/media/css/colors/)
|
||||
│ ├── CLIENT_FORK_README_TEMPLATE.md # Template for client fork docs
|
||||
│ └── README.md # Guide to using templates
|
||||
├── src/ # Template source code (Joomla template root)
|
||||
│ ├── component.php # Component template
|
||||
│ ├── index.php # Main template file
|
||||
│ ├── offline.php # Offline template
|
||||
│ ├── error.php # Error page template
|
||||
│ ├── templateDetails.xml # Template manifest
|
||||
│ ├── html/ # Module & component overrides (16 modules, 12 components)
|
||||
│ ├── media/ # Assets (CSS, JS, images, fonts)
|
||||
│ │ ├── css/ # Stylesheets
|
||||
│ │ │ └── colors/ # Color schemes
|
||||
│ │ │ ├── light/ # Light mode color files (colors_standard.css)
|
||||
│ │ │ └── dark/ # Dark mode color files (colors_standard.css)
|
||||
│ │ ├── js/ # JavaScript files
|
||||
│ │ ├── images/ # Image assets
|
||||
│ │ └── fonts/ # Font files
|
||||
│ ├── language/ # Frontend language files
|
||||
│ │ ├── en-GB/ # English (UK) translations
|
||||
│ │ └── en-US/ # English (US) translations
|
||||
│ └── administrator/ # Backend files
|
||||
│ └── language/ # Backend language files
|
||||
│ ├── en-GB/ # English (UK) system translations
|
||||
│ └── en-US/ # English (US) system translations
|
||||
├── templates/ # Reserved for future template files
|
||||
│ └── README.md # Templates directory guide
|
||||
├── scripts/ # Build and utility scripts
|
||||
├── tests/ # Automated tests
|
||||
├── CLIENT_FORK_README.md # Client fork guide
|
||||
└── .github/ # GitHub configuration and workflows
|
||||
```
|
||||
|
||||
|
||||
638
docs/RELEASE_PROCESS.md
Normal file
638
docs/RELEASE_PROCESS.md
Normal file
@@ -0,0 +1,638 @@
|
||||
<!--
|
||||
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
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: MokoCassiopeia.Documentation
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
FILE: docs/RELEASE_PROCESS.md
|
||||
VERSION: 01.00.00
|
||||
BRIEF: Complete release process documentation for MokoCassiopeia
|
||||
PATH: /docs/RELEASE_PROCESS.md
|
||||
-->
|
||||
|
||||
# Release Process — MokoCassiopeia
|
||||
|
||||
This document describes the complete release process for MokoCassiopeia Joomla template, including automated workflows and manual procedures.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Overview](#overview)
|
||||
2. [Release Types](#release-types)
|
||||
3. [Automated Release Process](#automated-release-process)
|
||||
4. [Manual Release Process](#manual-release-process)
|
||||
5. [Update Server Configuration](#update-server-configuration)
|
||||
6. [Testing Releases](#testing-releases)
|
||||
7. [Rollback Procedures](#rollback-procedures)
|
||||
8. [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
MokoCassiopeia uses an automated release system powered by GitHub Actions. The system:
|
||||
|
||||
- **Builds** installation packages automatically
|
||||
- **Generates** checksums for security verification
|
||||
- **Creates** GitHub Releases with downloadable artifacts
|
||||
- **Updates** the Joomla update server (`updates.xml`) automatically
|
||||
- **Validates** package integrity with SHA-256 hashes
|
||||
|
||||
### Key Components
|
||||
|
||||
1. **Release Workflow** (`.github/workflows/release.yml`): Builds and publishes releases
|
||||
2. **Auto-Update SHA** (`.github/workflows/auto-update-sha.yml`): Updates `updates.xml` after release
|
||||
3. **Build Script** (`scripts/build-release.sh`): Local development builds
|
||||
4. **Update Server** (`updates.xml`): Joomla update server manifest
|
||||
|
||||
---
|
||||
|
||||
## Release Types
|
||||
|
||||
### Patch Release (Third Digit)
|
||||
|
||||
**Format**: `XX.XX.XX` → `XX.XX.XX+1` (e.g., `03.08.03` → `03.08.04`)
|
||||
|
||||
**When to use**:
|
||||
- Bug fixes
|
||||
- Security patches
|
||||
- Documentation updates
|
||||
- Minor CSS/styling tweaks
|
||||
- No breaking changes
|
||||
|
||||
**Example**: `03.08.03` → `03.08.04`
|
||||
|
||||
### Minor Release (Second Digit)
|
||||
|
||||
**Format**: `XX.XX.00` → `XX.XX+1.00` (e.g., `03.08.03` → `03.09.00`)
|
||||
|
||||
**When to use**:
|
||||
- New features
|
||||
- New module/component overrides
|
||||
- Significant styling changes
|
||||
- Backward-compatible changes
|
||||
|
||||
**Example**: `03.08.03` → `03.09.00`
|
||||
|
||||
### Major Release (First Digit)
|
||||
|
||||
**Format**: `XX.00.00` → `XX+1.00.00` (e.g., `03.08.03` → `04.00.00`)
|
||||
|
||||
**When to use**:
|
||||
- Breaking changes
|
||||
- Major architecture changes
|
||||
- Joomla version upgrades
|
||||
- Complete redesigns
|
||||
|
||||
**Example**: `03.08.03` → `04.00.00`
|
||||
|
||||
---
|
||||
|
||||
## Automated Release Process
|
||||
|
||||
**Recommended for most releases**
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [ ] All changes merged to `main` branch
|
||||
- [ ] Tests passing
|
||||
- [ ] Documentation updated
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Local testing completed
|
||||
|
||||
### Step 1: Prepare Release Branch
|
||||
|
||||
```bash
|
||||
# Create release branch
|
||||
git checkout main
|
||||
git pull
|
||||
git checkout -b release/03.08.04
|
||||
|
||||
# Update version in templateDetails.xml
|
||||
# Edit: src/templateDetails.xml
|
||||
# Change: <version>03.08.03</version>
|
||||
# To: <version>03.08.04</version>
|
||||
|
||||
# Update CHANGELOG.md
|
||||
# Add new section:
|
||||
## [03.08.04] - 2026-02-27
|
||||
|
||||
### Added
|
||||
- Feature descriptions
|
||||
|
||||
### Fixed
|
||||
- Bug fix descriptions
|
||||
|
||||
### Changed
|
||||
- Change descriptions
|
||||
|
||||
# Commit changes
|
||||
git add src/templateDetails.xml CHANGELOG.md
|
||||
git commit -m "chore: Prepare release 03.08.04"
|
||||
git push origin release/03.08.04
|
||||
```
|
||||
|
||||
### Step 2: Create Pull Request
|
||||
|
||||
1. Go to GitHub repository
|
||||
2. Click "Pull requests" → "New pull request"
|
||||
3. Base: `main`, Compare: `release/03.08.04`
|
||||
4. Title: `Release 03.08.04`
|
||||
5. Description: Copy relevant CHANGELOG entries
|
||||
6. Create pull request
|
||||
7. Review and merge
|
||||
|
||||
### Step 3: Create and Push Tag
|
||||
|
||||
```bash
|
||||
# Switch to main and pull changes
|
||||
git checkout main
|
||||
git pull
|
||||
|
||||
# Create tag
|
||||
git tag 03.08.04
|
||||
|
||||
# Push tag (triggers release workflow)
|
||||
git push origin 03.08.04
|
||||
```
|
||||
|
||||
### Step 4: Monitor Automated Process
|
||||
|
||||
1. **Go to GitHub Actions tab**
|
||||
2. **Watch "Create Release" workflow**:
|
||||
- Builds package
|
||||
- Generates checksums
|
||||
- Creates GitHub Release
|
||||
- Uploads artifacts
|
||||
|
||||
3. **Watch "Auto-Update SHA Hash" workflow**:
|
||||
- Downloads release package
|
||||
- Calculates SHA-256 hash
|
||||
- Updates `updates.xml`
|
||||
- Commits to main branch
|
||||
|
||||
### Step 5: Verify Release
|
||||
|
||||
1. **Check GitHub Release**:
|
||||
- Go to Releases tab
|
||||
- Verify release `03.08.04` exists
|
||||
- Download ZIP package
|
||||
- Verify checksums match
|
||||
|
||||
2. **Check updates.xml**:
|
||||
```bash
|
||||
git pull
|
||||
cat updates.xml
|
||||
```
|
||||
- Verify version is `03.08.04`
|
||||
- Verify download URL is correct
|
||||
- Verify SHA-256 hash is present
|
||||
|
||||
3. **Test Joomla Update**:
|
||||
- Install previous version in Joomla
|
||||
- Go to Extensions → Update
|
||||
- Verify update is detected
|
||||
- Perform update
|
||||
- Verify template works correctly
|
||||
|
||||
---
|
||||
|
||||
## Manual Release Process
|
||||
|
||||
**Use when automation fails or for local testing**
|
||||
|
||||
### Step 1: Prepare Repository
|
||||
|
||||
```bash
|
||||
# Update version numbers
|
||||
# Edit: src/templateDetails.xml
|
||||
# Edit: CHANGELOG.md
|
||||
|
||||
# Commit changes
|
||||
git add src/templateDetails.xml CHANGELOG.md
|
||||
git commit -m "chore: Prepare release 03.08.04"
|
||||
git push
|
||||
```
|
||||
|
||||
### Step 2: Build Package Locally
|
||||
|
||||
```bash
|
||||
# Run build script
|
||||
./scripts/build-release.sh 03.08.04
|
||||
|
||||
# Output will be in build/ directory:
|
||||
# - mokocassiopeia-src-03.08.04.zip
|
||||
# - mokocassiopeia-src-03.08.04.zip.sha256
|
||||
# - mokocassiopeia-src-03.08.04.zip.md5
|
||||
```
|
||||
|
||||
### Step 3: Test Package
|
||||
|
||||
```bash
|
||||
# Install in Joomla test environment
|
||||
# Extensions → Manage → Install → Upload Package File
|
||||
# Select: build/mokocassiopeia-src-03.08.04.zip
|
||||
|
||||
# Test all features:
|
||||
# - Template displays correctly
|
||||
# - Module overrides work
|
||||
# - Alternative layouts selectable
|
||||
# - Dark mode works
|
||||
# - No JavaScript errors
|
||||
```
|
||||
|
||||
### Step 4: Create GitHub Release
|
||||
|
||||
1. **Go to GitHub Releases**
|
||||
2. **Click "Create a new release"**
|
||||
3. **Tag**: `03.08.04` (create new tag)
|
||||
4. **Release title**: `Release 03.08.04`
|
||||
5. **Description**: Copy from CHANGELOG.md
|
||||
6. **Upload files**:
|
||||
- `mokocassiopeia-src-03.08.04.zip`
|
||||
- `mokocassiopeia-src-03.08.04.zip.sha256`
|
||||
- `mokocassiopeia-src-03.08.04.zip.md5`
|
||||
7. **Publish release**
|
||||
|
||||
### Step 5: Update updates.xml Manually
|
||||
|
||||
```bash
|
||||
# Extract SHA-256 hash
|
||||
cat build/mokocassiopeia-src-03.08.04.zip.sha256
|
||||
# Example output: a1b2c3d4e5f6...
|
||||
|
||||
# Edit updates.xml
|
||||
# Update <version>03.08.04</version>
|
||||
# Update <creationDate>2026-02-27</creationDate>
|
||||
# Update <downloadurl>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/03.08.04/mokocassiopeia-src-03.08.04.zip</downloadurl>
|
||||
# Update <sha256>sha256:a1b2c3d4e5f6...</sha256>
|
||||
|
||||
# Commit and push
|
||||
git add updates.xml
|
||||
git commit -m "chore: Update updates.xml for release 03.08.04"
|
||||
git push
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Update Server Configuration
|
||||
|
||||
### updates.xml Structure
|
||||
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
<name>MokoCassiopeia</name>
|
||||
<description>Moko Consulting's site template based on Cassiopeia.</description>
|
||||
<element>mokocassiopeia</element>
|
||||
<type>template</type>
|
||||
<client>site</client>
|
||||
|
||||
<version>03.08.04</version>
|
||||
<creationDate>2026-02-27</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'>https://github.com/mokoconsulting-tech/MokoCassiopeia</infourl>
|
||||
|
||||
<downloads>
|
||||
<downloadurl type='full' format='zip'>https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/03.08.04/mokocassiopeia-src-03.08.04.zip</downloadurl>
|
||||
<sha256>sha256:a1b2c3d4e5f6...</sha256>
|
||||
</downloads>
|
||||
|
||||
<tags>
|
||||
<tag>stable</tag>
|
||||
</tags>
|
||||
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://www.mokoconsulting.tech</maintainerurl>
|
||||
|
||||
<targetplatform name='joomla' version='5.*'/>
|
||||
</update>
|
||||
</updates>
|
||||
```
|
||||
|
||||
### Hosting Update Server
|
||||
|
||||
The `updates.xml` file is hosted directly on GitHub:
|
||||
|
||||
**URL**: `https://raw.githubusercontent.com/mokoconsulting-tech/MokoCassiopeia/main/updates.xml`
|
||||
|
||||
This URL is configured in `src/templateDetails.xml`:
|
||||
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" name="MokoCassiopeia Updates" priority="1">
|
||||
https://raw.githubusercontent.com/mokoconsulting-tech/MokoCassiopeia/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Releases
|
||||
|
||||
### Pre-Release Testing
|
||||
|
||||
```bash
|
||||
# 1. Build package locally
|
||||
./scripts/build-release.sh
|
||||
|
||||
# 2. Set up Joomla test environment
|
||||
# - Clean Joomla 5.x installation
|
||||
# - Previous MokoCassiopeia version installed
|
||||
|
||||
# 3. Test current version features
|
||||
# - All module overrides
|
||||
# - Alternative layouts
|
||||
# - Dark mode toggle
|
||||
# - Responsive behavior
|
||||
|
||||
# 4. Install new package
|
||||
# Extensions → Manage → Install → Upload Package
|
||||
|
||||
# 5. Verify upgrade process
|
||||
# - No errors during installation
|
||||
# - Settings preserved
|
||||
# - Custom modifications retained
|
||||
|
||||
# 6. Test new features
|
||||
# - New functionality works
|
||||
# - Bug fixes applied
|
||||
# - No regressions
|
||||
```
|
||||
|
||||
### Update Server Testing
|
||||
|
||||
```bash
|
||||
# 1. Install previous version in Joomla
|
||||
# 2. Go to: Extensions → Update
|
||||
# 3. Click "Find Updates"
|
||||
# 4. Verify update shows: "MokoCassiopeia 03.08.04"
|
||||
# 5. Click "Update"
|
||||
# 6. Verify successful update
|
||||
# 7. Test template functionality
|
||||
```
|
||||
|
||||
### Checklist
|
||||
|
||||
- [ ] Package installs without errors
|
||||
- [ ] Template activates correctly
|
||||
- [ ] All module overrides work
|
||||
- [ ] Alternative layouts selectable
|
||||
- [ ] Dark mode functions
|
||||
- [ ] Responsive on mobile/tablet/desktop
|
||||
- [ ] No JavaScript console errors
|
||||
- [ ] No PHP errors in Joomla logs
|
||||
- [ ] Update server detects new version
|
||||
- [ ] Update process completes successfully
|
||||
|
||||
---
|
||||
|
||||
## Rollback Procedures
|
||||
|
||||
### Rollback Release
|
||||
|
||||
If a release has critical issues:
|
||||
|
||||
1. **Delete GitHub Release**:
|
||||
- Go to Releases
|
||||
- Click release to delete
|
||||
- Click "Delete"
|
||||
- Confirm deletion
|
||||
|
||||
2. **Delete Git Tag**:
|
||||
```bash
|
||||
# Delete local tag
|
||||
git tag -d 03.08.04
|
||||
|
||||
# Delete remote tag
|
||||
git push --delete origin 03.08.04
|
||||
```
|
||||
|
||||
3. **Revert updates.xml**:
|
||||
```bash
|
||||
# Revert to previous version
|
||||
git revert <commit-hash-of-auto-update>
|
||||
git push
|
||||
```
|
||||
|
||||
4. **Notify Users**:
|
||||
- Create GitHub issue explaining the problem
|
||||
- Pin the issue
|
||||
- Provide rollback instructions for users
|
||||
|
||||
### User Rollback Instructions
|
||||
|
||||
For users who installed the problematic version:
|
||||
|
||||
1. **Download previous version** from GitHub Releases
|
||||
2. **Uninstall current version**:
|
||||
- Extensions → Manage → Manage
|
||||
- Find MokoCassiopeia
|
||||
- Click "Uninstall"
|
||||
3. **Install previous version**:
|
||||
- Extensions → Manage → Install
|
||||
- Upload previous version ZIP
|
||||
4. **Verify functionality**
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Release Workflow Fails
|
||||
|
||||
**Problem**: Build fails with "rsync: command not found"
|
||||
|
||||
**Solution**: The GitHub Actions runner always has rsync installed. If this occurs, check the workflow file syntax.
|
||||
|
||||
**Problem**: ZIP creation fails
|
||||
|
||||
**Solution**: Check that `src/` and `src/media/` directories exist and contain files.
|
||||
|
||||
**Problem**: Version update fails
|
||||
|
||||
**Solution**: Verify `sed` commands in workflow match actual XML structure.
|
||||
|
||||
### Auto-Update SHA Fails
|
||||
|
||||
**Problem**: Cannot download release package
|
||||
|
||||
**Solution**:
|
||||
- Verify release was published (not draft)
|
||||
- Check package naming: `mokocassiopeia-src-{version}.zip`
|
||||
- Verify release tag format
|
||||
|
||||
**Problem**: SHA-256 hash mismatch
|
||||
|
||||
**Solution**:
|
||||
- Package may have been modified after calculation
|
||||
- Re-run the workflow manually
|
||||
- Verify package integrity
|
||||
|
||||
**Problem**: Commit fails
|
||||
|
||||
**Solution**:
|
||||
- Check workflow has write permissions
|
||||
- Verify no branch protection rules blocking bot commits
|
||||
|
||||
### Manual Build Issues
|
||||
|
||||
**Problem**: `./scripts/build-release.sh: Permission denied`
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
chmod +x scripts/build-release.sh
|
||||
./scripts/build-release.sh
|
||||
```
|
||||
|
||||
**Problem**: Build directory exists
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
rm -rf build/
|
||||
./scripts/build-release.sh
|
||||
```
|
||||
|
||||
### Update Server Issues
|
||||
|
||||
**Problem**: Joomla doesn't detect update
|
||||
|
||||
**Solution**:
|
||||
1. Check `updates.xml` is accessible:
|
||||
```bash
|
||||
curl https://raw.githubusercontent.com/mokoconsulting-tech/MokoCassiopeia/main/updates.xml
|
||||
```
|
||||
2. Verify version number is higher than installed version
|
||||
3. Clear Joomla cache: System → Clear Cache
|
||||
4. Check update URL in templateDetails.xml
|
||||
|
||||
**Problem**: Update fails with "Invalid package"
|
||||
|
||||
**Solution**:
|
||||
- Verify SHA-256 hash matches
|
||||
- Re-download package and check integrity
|
||||
- Verify package structure is correct
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Version Numbering
|
||||
|
||||
- **Always increment** version numbers sequentially
|
||||
- **Never reuse** version numbers
|
||||
- **Use consistent** format: `XX.XX.XX`
|
||||
|
||||
### Changelog
|
||||
|
||||
- **Update before** release
|
||||
- **Include all changes** since last version
|
||||
- **Categorize** changes: Added, Changed, Fixed, Removed
|
||||
- **Write clear descriptions** for users
|
||||
|
||||
### Testing
|
||||
|
||||
- **Test locally** before pushing tag
|
||||
- **Test update process** from previous version
|
||||
- **Test on clean** Joomla installation
|
||||
- **Test different** configurations
|
||||
|
||||
### Communication
|
||||
|
||||
- **Announce releases** on GitHub Discussions
|
||||
- **Document breaking changes** clearly
|
||||
- **Provide migration guides** for major changes
|
||||
- **Respond promptly** to issue reports
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Automated Release Commands
|
||||
|
||||
```bash
|
||||
# 1. Create release branch
|
||||
git checkout -b release/03.08.04
|
||||
|
||||
# 2. Update version and CHANGELOG
|
||||
# (edit files)
|
||||
|
||||
# 3. Commit and push
|
||||
git add .
|
||||
git commit -m "chore: Prepare release 03.08.04"
|
||||
git push origin release/03.08.04
|
||||
|
||||
# 4. Create and merge PR (via GitHub UI)
|
||||
|
||||
# 5. Create and push tag
|
||||
git checkout main
|
||||
git pull
|
||||
git tag 03.08.04
|
||||
git push origin 03.08.04
|
||||
|
||||
# 6. Wait for automation to complete
|
||||
```
|
||||
|
||||
### Manual Release Commands
|
||||
|
||||
```bash
|
||||
# Build locally
|
||||
./scripts/build-release.sh 03.08.04
|
||||
|
||||
# Test installation
|
||||
# (manual Joomla testing)
|
||||
|
||||
# Create release on GitHub
|
||||
# (via GitHub UI)
|
||||
|
||||
# Update updates.xml
|
||||
# (edit file with SHA-256)
|
||||
git add updates.xml
|
||||
git commit -m "chore: Update updates.xml for 03.08.04"
|
||||
git push
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- **Build Scripts**: [scripts/README.md](../scripts/README.md)
|
||||
- **Workflow Guide**: [WORKFLOW_GUIDE.md](WORKFLOW_GUIDE.md)
|
||||
- **Contributing**: [CONTRIBUTING.md](../CONTRIBUTING.md)
|
||||
- **Changelog**: [CHANGELOG.md](../CHANGELOG.md)
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
- **Issues**: [GitHub Issues](https://github.com/mokoconsulting-tech/MokoCassiopeia/issues)
|
||||
- **Discussions**: [GitHub Discussions](https://github.com/mokoconsulting-tech/MokoCassiopeia/discussions)
|
||||
- **Email**: hello@mokoconsulting.tech
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2026 Moko Consulting
|
||||
|
||||
This documentation is licensed under GPL-3.0-or-later.
|
||||
@@ -241,7 +241,7 @@ git fetch origin
|
||||
git checkout dev/X.Y.Z
|
||||
|
||||
# 3. Make your changes
|
||||
vim src/templates/index.php
|
||||
vim src/index.php
|
||||
|
||||
# 4. Validate locally
|
||||
make validate-required
|
||||
@@ -293,7 +293,7 @@ Update CHANGELOG.md manually or via pull request following the existing format.
|
||||
|
||||
```bash
|
||||
# Check specific file
|
||||
php -l src/templates/index.php
|
||||
php -l src/index.php
|
||||
|
||||
# Run validation
|
||||
make validate-required
|
||||
|
||||
276
scripts/README.md
Normal file
276
scripts/README.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# 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
|
||||
132
scripts/build-release.sh
Executable file
132
scripts/build-release.sh
Executable file
@@ -0,0 +1,132 @@
|
||||
#!/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 ""
|
||||
@@ -1,168 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Script: Create Client Fork Setup
|
||||
# This script prepares the repository for a client-specific fork by:
|
||||
# - Copying custom color templates to the appropriate locations
|
||||
# - Replacing the main README with the client fork README
|
||||
# - Cleaning up template documentation files
|
||||
|
||||
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
|
||||
|
||||
# Function to print colored output
|
||||
print_success() { echo -e "${GREEN}✓${NC} $1"; }
|
||||
print_error() { echo -e "${RED}✗${NC} $1"; }
|
||||
print_info() { echo -e "${BLUE}ℹ${NC} $1"; }
|
||||
print_warning() { echo -e "${YELLOW}⚠${NC} $1"; }
|
||||
|
||||
# Check if client name is provided
|
||||
if [ -z "$1" ]; then
|
||||
print_error "Usage: $0 <CLIENT_NAME>"
|
||||
echo "Example: $0 \"Acme Corporation\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CLIENT_NAME="$1"
|
||||
CLIENT_SLUG=$(echo "${CLIENT_NAME}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
|
||||
BRANCH_NAME="client-fork/${CLIENT_SLUG}"
|
||||
|
||||
echo ""
|
||||
echo "╔════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ MokoCassiopeia - Client Fork Setup Script ║"
|
||||
echo "╚════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
print_info "Client Name: ${CLIENT_NAME}"
|
||||
print_info "Branch Name: ${BRANCH_NAME}"
|
||||
echo ""
|
||||
|
||||
# Confirm before proceeding
|
||||
read -p "Do you want to proceed? (yes/no): " -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]es$ ]]; then
|
||||
print_warning "Operation cancelled by user"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "CLIENT_FORK_README.md" ]; then
|
||||
print_error "CLIENT_FORK_README.md not found. Are you in the repository root?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create new branch
|
||||
print_info "Creating branch: ${BRANCH_NAME}"
|
||||
git checkout -b "${BRANCH_NAME}"
|
||||
print_success "Branch created"
|
||||
|
||||
# Copy custom color templates
|
||||
print_info "Copying colors_custom.css to light and dark mode directories..."
|
||||
cp templates/colors_custom.css src/media/css/colors/light/colors_custom.css
|
||||
cp templates/colors_custom.css src/media/css/colors/dark/colors_custom.css
|
||||
|
||||
if [ -f "src/media/css/colors/light/colors_custom.css" ] && [ -f "src/media/css/colors/dark/colors_custom.css" ]; then
|
||||
print_success "Created src/media/css/colors/light/colors_custom.css"
|
||||
print_success "Created src/media/css/colors/dark/colors_custom.css"
|
||||
else
|
||||
print_error "Failed to create colors_custom.css files"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Replace README with client fork README
|
||||
print_info "Replacing README.md with CLIENT_FORK_README.md..."
|
||||
sed "s/\[CLIENT NAME\]/${CLIENT_NAME}/g" CLIENT_FORK_README.md > README.md.new
|
||||
mv README.md.new README.md
|
||||
|
||||
# Update fork information section
|
||||
CURRENT_DATE=$(date +"%Y-%m-%d")
|
||||
sed -i.bak "s/\[DATE\]/${CURRENT_DATE}/g" README.md
|
||||
sed -i.bak "s/\[YOUR-FORK-URL\]/[UPDATE-WITH-YOUR-FORK-URL]/g" README.md
|
||||
rm -f README.md.bak
|
||||
|
||||
print_success "README.md replaced with customized client fork README"
|
||||
|
||||
# Clean up template files
|
||||
print_info "Removing template documentation files..."
|
||||
|
||||
if [ -f "CLIENT_FORK_README.md" ]; then
|
||||
rm CLIENT_FORK_README.md
|
||||
print_success "Removed CLIENT_FORK_README.md"
|
||||
fi
|
||||
|
||||
if [ -f "templates/CLIENT_FORK_README_TEMPLATE.md" ]; then
|
||||
rm templates/CLIENT_FORK_README_TEMPLATE.md
|
||||
print_success "Removed templates/CLIENT_FORK_README_TEMPLATE.md"
|
||||
fi
|
||||
|
||||
# Update templates/README.md
|
||||
if [ -f "templates/README.md" ]; then
|
||||
# Create a backup
|
||||
cp templates/README.md templates/README.md.bak
|
||||
|
||||
# Remove references to CLIENT_FORK_README_TEMPLATE.md
|
||||
sed '/CLIENT_FORK_README_TEMPLATE.md/d' templates/README.md > templates/README.md.tmp
|
||||
mv templates/README.md.tmp templates/README.md
|
||||
rm -f templates/README.md.bak
|
||||
|
||||
print_success "Updated templates/README.md"
|
||||
fi
|
||||
|
||||
print_success "Keeping templates/colors_custom.css as template"
|
||||
|
||||
# Show git status
|
||||
echo ""
|
||||
print_info "Git status:"
|
||||
git status --short
|
||||
|
||||
# Commit changes
|
||||
echo ""
|
||||
read -p "Commit these changes? (yes/no): " -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]es$ ]]; then
|
||||
git add .
|
||||
git commit -m "Setup client fork for ${CLIENT_NAME}
|
||||
|
||||
- Copied colors_custom.css to src/media/css/colors/light/ and dark/
|
||||
- Replaced README.md with customized CLIENT_FORK_README.md
|
||||
- Removed CLIENT_FORK_README.md and templates/CLIENT_FORK_README_TEMPLATE.md
|
||||
- Kept templates/colors_custom.css as template
|
||||
|
||||
This commit prepares the repository for ${CLIENT_NAME}'s custom fork."
|
||||
|
||||
print_success "Changes committed successfully"
|
||||
|
||||
echo ""
|
||||
print_info "To push this branch, run:"
|
||||
echo " git push origin ${BRANCH_NAME}"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "╔════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ Setup Complete! 🎉 ║"
|
||||
echo "╚════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "Changes Applied:"
|
||||
print_success "Copied colors_custom.css to src/media/css/colors/light/"
|
||||
print_success "Copied colors_custom.css to src/media/css/colors/dark/"
|
||||
print_success "Replaced README.md with customized client fork README"
|
||||
print_success "Removed CLIENT_FORK_README.md"
|
||||
print_success "Removed templates/CLIENT_FORK_README_TEMPLATE.md"
|
||||
print_success "Kept templates/colors_custom.css as template"
|
||||
echo ""
|
||||
echo "Next Steps:"
|
||||
echo "1. Review the changes in branch: ${BRANCH_NAME}"
|
||||
echo "2. Customize colors in src/media/css/colors/light/colors_custom.css"
|
||||
echo "3. Customize colors in src/media/css/colors/dark/colors_custom.css"
|
||||
echo "4. Update README.md with client-specific details"
|
||||
echo "5. Create a new repository for ${CLIENT_NAME}"
|
||||
echo "6. Push this branch to the new repository"
|
||||
echo ""
|
||||
96
scripts/download-google-fonts.sh
Executable file
96
scripts/download-google-fonts.sh
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/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,95 +0,0 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <jmiller@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Site
|
||||
INGROUP: Templates.MokoCassiopeia
|
||||
FILE: index.html
|
||||
BRIEF: Security redirect page to block folder access and forward to site root.
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Redirecting…</title>
|
||||
|
||||
<!-- Search engines: do not index this placeholder redirect page -->
|
||||
<meta name="robots" content="noindex, nofollow, noarchive" />
|
||||
|
||||
<!-- Instant redirect fallback even if JavaScript is disabled -->
|
||||
<meta http-equiv="refresh" content="0; url=/" />
|
||||
|
||||
<!-- Canonical root reference -->
|
||||
<link rel="canonical" href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<script>
|
||||
|
||||
(function redirectToRoot() {
|
||||
// Configuration object with safe defaults.
|
||||
var opts = {
|
||||
fallbackPath: "/", // string: fallback destination if origin is unavailable
|
||||
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
|
||||
behavior: "replace" // enum: "replace" | "assign"
|
||||
};
|
||||
|
||||
// Determine absolute origin in all mainstream browsers.
|
||||
var origin = (typeof location.origin === "string" && location.origin)
|
||||
|| (location.protocol + "//" + location.host);
|
||||
|
||||
// Final destination: absolute root of the current site, or fallback path.
|
||||
var destination = origin ? origin + "/" : opts.fallbackPath;
|
||||
|
||||
function go() {
|
||||
if (opts.behavior === "assign") {
|
||||
location.assign(destination);
|
||||
} else {
|
||||
location.replace(destination);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute redirect, optionally after a short delay.
|
||||
if (opts.delayMs > 0) {
|
||||
setTimeout(go, opts.delayMs);
|
||||
} else {
|
||||
go();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Secondary meta-refresh for no-JS environments is already set above.
|
||||
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
|
||||
-->
|
||||
|
||||
<noscript>
|
||||
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
|
||||
<style>
|
||||
html, body { height:100%; }
|
||||
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
|
||||
.msg { opacity: .75; text-align: center; }
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
<body>
|
||||
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,95 +0,0 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <jmiller@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Site
|
||||
INGROUP: Templates.MokoCassiopeia
|
||||
FILE: index.html
|
||||
BRIEF: Security redirect page to block folder access and forward to site root.
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Redirecting…</title>
|
||||
|
||||
<!-- Search engines: do not index this placeholder redirect page -->
|
||||
<meta name="robots" content="noindex, nofollow, noarchive" />
|
||||
|
||||
<!-- Instant redirect fallback even if JavaScript is disabled -->
|
||||
<meta http-equiv="refresh" content="0; url=/" />
|
||||
|
||||
<!-- Canonical root reference -->
|
||||
<link rel="canonical" href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<script>
|
||||
|
||||
(function redirectToRoot() {
|
||||
// Configuration object with safe defaults.
|
||||
var opts = {
|
||||
fallbackPath: "/", // string: fallback destination if origin is unavailable
|
||||
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
|
||||
behavior: "replace" // enum: "replace" | "assign"
|
||||
};
|
||||
|
||||
// Determine absolute origin in all mainstream browsers.
|
||||
var origin = (typeof location.origin === "string" && location.origin)
|
||||
|| (location.protocol + "//" + location.host);
|
||||
|
||||
// Final destination: absolute root of the current site, or fallback path.
|
||||
var destination = origin ? origin + "/" : opts.fallbackPath;
|
||||
|
||||
function go() {
|
||||
if (opts.behavior === "assign") {
|
||||
location.assign(destination);
|
||||
} else {
|
||||
location.replace(destination);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute redirect, optionally after a short delay.
|
||||
if (opts.delayMs > 0) {
|
||||
setTimeout(go, opts.delayMs);
|
||||
} else {
|
||||
go();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Secondary meta-refresh for no-JS environments is already set above.
|
||||
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
|
||||
-->
|
||||
|
||||
<noscript>
|
||||
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
|
||||
<style>
|
||||
html, body { height:100%; }
|
||||
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
|
||||
.msg { opacity: .75; text-align: center; }
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
<body>
|
||||
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,95 +0,0 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <jmiller@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Site
|
||||
INGROUP: Templates.MokoCassiopeia
|
||||
FILE: index.html
|
||||
BRIEF: Security redirect page to block folder access and forward to site root.
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Redirecting…</title>
|
||||
|
||||
<!-- Search engines: do not index this placeholder redirect page -->
|
||||
<meta name="robots" content="noindex, nofollow, noarchive" />
|
||||
|
||||
<!-- Instant redirect fallback even if JavaScript is disabled -->
|
||||
<meta http-equiv="refresh" content="0; url=/" />
|
||||
|
||||
<!-- Canonical root reference -->
|
||||
<link rel="canonical" href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<script>
|
||||
|
||||
(function redirectToRoot() {
|
||||
// Configuration object with safe defaults.
|
||||
var opts = {
|
||||
fallbackPath: "/", // string: fallback destination if origin is unavailable
|
||||
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
|
||||
behavior: "replace" // enum: "replace" | "assign"
|
||||
};
|
||||
|
||||
// Determine absolute origin in all mainstream browsers.
|
||||
var origin = (typeof location.origin === "string" && location.origin)
|
||||
|| (location.protocol + "//" + location.host);
|
||||
|
||||
// Final destination: absolute root of the current site, or fallback path.
|
||||
var destination = origin ? origin + "/" : opts.fallbackPath;
|
||||
|
||||
function go() {
|
||||
if (opts.behavior === "assign") {
|
||||
location.assign(destination);
|
||||
} else {
|
||||
location.replace(destination);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute redirect, optionally after a short delay.
|
||||
if (opts.delayMs > 0) {
|
||||
setTimeout(go, opts.delayMs);
|
||||
} else {
|
||||
go();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Secondary meta-refresh for no-JS environments is already set above.
|
||||
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
|
||||
-->
|
||||
|
||||
<noscript>
|
||||
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
|
||||
<style>
|
||||
html, body { height:100%; }
|
||||
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
|
||||
.msg { opacity: .75; text-align: center; }
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
<body>
|
||||
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
|
||||
</body>
|
||||
</html>
|
||||
184
src/component.php
Normal file
184
src/component.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?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
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||
PATH: ./templates/mokocassiopeia/component.php
|
||||
VERSION: 03.06.02
|
||||
BRIEF: Main template index file for MokoCassiopeia rendering site layout
|
||||
*/
|
||||
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
|
||||
/** @var Joomla\CMS\Document\HtmlDocument $this */
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$input = $app->getInput();
|
||||
$document = $app->getDocument();
|
||||
$wa = $document->getWebAssetManager();
|
||||
|
||||
// Template params - Component uses minimal configuration
|
||||
$params_googletagmanager = $this->params->get('googletagmanager', false);
|
||||
$params_googletagmanagerid = $this->params->get('googletagmanagerid', null);
|
||||
$params_googleanalytics = $this->params->get('googleanalytics', false);
|
||||
$params_googleanalyticsid = $this->params->get('googleanalyticsid', null);
|
||||
|
||||
// Detecting Active Variables
|
||||
$option = $input->getCmd('option', '');
|
||||
$view = $input->getCmd('view', '');
|
||||
$layout = $input->getCmd('layout', '');
|
||||
$task = $input->getCmd('task', '');
|
||||
$itemid = $input->getCmd('Itemid', '');
|
||||
$sitenameR = $app->get('sitename'); // raw for title composition
|
||||
$sitename = htmlspecialchars($sitenameR, ENT_QUOTES, 'UTF-8');
|
||||
$menu = $app->getMenu()->getActive();
|
||||
$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : '';
|
||||
|
||||
// Respect “Site Name in Page Titles” (0:none, 1:before, 2:after)
|
||||
$mode = (int) $app->get('sitename_pagetitles', 0);
|
||||
$pageTitle = trim($this->getTitle());
|
||||
$final = $pageTitle !== ''
|
||||
? ($mode === 1 ? $sitenameR . ' - ' . $pageTitle
|
||||
: ($mode === 2 ? $pageTitle . ' - ' . $sitenameR : $pageTitle))
|
||||
: $sitenameR;
|
||||
$this->setTitle($final);
|
||||
|
||||
// Template/Media path
|
||||
$templatePath = 'media/templates/site/mokocassiopeia';
|
||||
|
||||
// Core template CSS
|
||||
$wa->useStyle('template.base'); // css/template.css
|
||||
|
||||
// Component always uses light theme only (no theme switching)
|
||||
$wa->useStyle('template.light.standard'); // css/theme/light.standard.css
|
||||
|
||||
// Load Osaka font for site title
|
||||
$wa->useStyle('template.font.osaka');
|
||||
|
||||
// Brand: logo from params OR siteTitle
|
||||
// -------------------------------------
|
||||
$brandHtml = '';
|
||||
$logoFile = (string) $this->params->get('logoFile');
|
||||
|
||||
if ($logoFile !== '') {
|
||||
$brandHtml = HTMLHelper::_(
|
||||
'image',
|
||||
Uri::root(false) . htmlspecialchars($logoFile, ENT_QUOTES, 'UTF-8'),
|
||||
$sitename,
|
||||
['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'],
|
||||
false,
|
||||
0
|
||||
);
|
||||
} else {
|
||||
// If no logo file, show the title (defaults to "MokoCassiopeia" if not set)
|
||||
$siteTitle = $this->params->get('siteTitle', 'MokoCassiopeia');
|
||||
$brandHtml = '<span class="site-title" title="' . $sitename . '">'
|
||||
. htmlspecialchars($siteTitle, ENT_COMPAT, 'UTF-8')
|
||||
. '</span>';
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html class="component" lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>" data-bs-theme="light">
|
||||
<head>
|
||||
<jdoc:include type="metas" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<jdoc:include type="styles" />
|
||||
<jdoc:include type="scripts" />
|
||||
</head>
|
||||
<body class="<?php echo $this->direction === 'rtl' ? 'rtl' : ''; ?>">
|
||||
<?php if (!empty($params_googletagmanager) && !empty($params_googletagmanagerid)) :
|
||||
$gtmID = htmlspecialchars($params_googletagmanagerid, ENT_QUOTES, 'UTF-8'); ?>
|
||||
<!-- Google Tag Manager -->
|
||||
<script>
|
||||
(function(w,d,s,l,i){
|
||||
w[l]=w[l]||[];
|
||||
w[l].push({'gtm.start': new Date().getTime(), event:'gtm.js'});
|
||||
var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),
|
||||
dl=l!='dataLayer'?'&l='+l:'';
|
||||
j.async=true;
|
||||
j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
|
||||
f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','<?php echo $gtmID; ?>');
|
||||
</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
|
||||
<!-- Google Tag Manager (noscript) -->
|
||||
<noscript>
|
||||
<iframe src="https://www.googletagmanager.com/ns.html?id=<?php echo $gtmID; ?>"
|
||||
height="0" width="0" style="display:none;visibility:hidden"></iframe>
|
||||
</noscript>
|
||||
<!-- End Google Tag Manager (noscript) -->
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
|
||||
$gaId = htmlspecialchars($params_googleanalyticsid, ENT_QUOTES, 'UTF-8'); ?>
|
||||
<!-- Google Analytics (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=<?php echo $gaId; ?>"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('consent', 'default', {
|
||||
'ad_storage': 'denied',
|
||||
'analytics_storage': 'granted',
|
||||
'ad_user_data': 'denied',
|
||||
'ad_personalization': 'denied'
|
||||
});
|
||||
(function(id){
|
||||
if (/^G-/.test(id)) {
|
||||
gtag('config', id, { 'anonymize_ip': true });
|
||||
} else if (/^UA-/.test(id)) {
|
||||
gtag('config', id, { 'anonymize_ip': true });
|
||||
console.warn('Using a UA- ID. Universal Analytics is sunset; consider migrating to GA4.');
|
||||
} else {
|
||||
console.warn('Unrecognized Google Analytics ID format:', id);
|
||||
}
|
||||
})('<?php echo $gaId; ?>');
|
||||
</script>
|
||||
<!-- End Google Analytics -->
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($this->params->get('brand', 1)) : ?>
|
||||
<div class="navbar-brand">
|
||||
<a class="brand-logo" href="<?php echo $this->baseurl; ?>/">
|
||||
<?php echo $brandHtml; ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<jdoc:include type="message" />
|
||||
<jdoc:include type="component" />
|
||||
|
||||
<footer class="container-footer footer full-width">
|
||||
<?php if ($this->countModules('footer-menu', true)) : ?>
|
||||
<div class="grid-child footer-menu">
|
||||
<jdoc:include type="modules" name="footer-menu" />
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->countModules('footer', true)) : ?>
|
||||
<div class="grid-child">
|
||||
<jdoc:include type="modules" name="footer" style="none" />
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</footer>
|
||||
|
||||
<jdoc:include type="modules" name="debug" style="none" />
|
||||
</body>
|
||||
</html>
|
||||
@@ -29,9 +29,9 @@ $params = $this->params;
|
||||
$wa = $this->getWebAssetManager();
|
||||
|
||||
// Template params
|
||||
$params_LightColorName = (string) $params->get('colorLightName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom
|
||||
$params_LightColorName = (string) $params->get('colorLightName', 'standard'); // standard|custom
|
||||
|
||||
$params_DarkColorName = (string) $params->get('colorDarkName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom
|
||||
$params_DarkColorName = (string) $params->get('colorDarkName', 'standard'); // standard|custom
|
||||
|
||||
$params_googletagmanager = $params->get('googletagmanager', false);
|
||||
$params_googletagmanagerid = $params->get('googletagmanagerid', '');
|
||||
@@ -60,30 +60,18 @@ $templatePath = 'media/templates/site/mokocassiopeia';
|
||||
// Core template CSS
|
||||
$wa->useStyle('template.base'); // css/template.css
|
||||
|
||||
// Color theme (light + optional dark)
|
||||
$colorLightKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_LightColorName));
|
||||
$colorDarkKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_DarkColorName));
|
||||
$lightKey = 'template.light.' . $colorLightKey;
|
||||
$darkKey = 'template.dark.' . $colorDarkKey;
|
||||
try {
|
||||
$wa->useStyle('template.light.colors_standard');
|
||||
} catch (\Throwable $e) {
|
||||
$wa->registerAndUseStyle('template.light.colors_standard', $templatePath . '/css/colors/light/colors_standard.css');
|
||||
// Load theme palette stylesheets based on configuration
|
||||
$wa->useStyle('template.light.standard'); // css/theme/light.standard.css
|
||||
$wa->useStyle('template.dark.standard'); // css/theme/dark.standard.css
|
||||
|
||||
// Load custom palettes only if selected in template configuration AND files exist
|
||||
if ($params_LightColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/light.custom.css'))
|
||||
{
|
||||
$wa->useStyle('template.light.custom');
|
||||
}
|
||||
try {
|
||||
$wa->useStyle('template.dark.colors_standard');
|
||||
} catch (\Throwable $e) {
|
||||
$wa->registerAndUseStyle('template.dark.colors_standard', $templatePath . '/css/colors/dark/colors_standard.css');
|
||||
}
|
||||
try {
|
||||
$wa->useStyle($lightKey);
|
||||
} catch (\Throwable $e) {
|
||||
$wa->registerAndUseStyle('template.light.dynamic', $templatePath . '/css/colors/light/' . $colorLightKey . '.css');
|
||||
}
|
||||
try {
|
||||
$wa->useStyle($darkKey);
|
||||
} catch (\Throwable $e) {
|
||||
$wa->registerAndUseStyle('template.dark.dynamic', $templatePath . '/css/colors/dark/' . $colorDarkKey . '.css');
|
||||
if ($params_DarkColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/dark.custom.css'))
|
||||
{
|
||||
$wa->useStyle('template.dark.custom');
|
||||
}
|
||||
|
||||
// Scripts
|
||||
@@ -137,8 +125,6 @@ if ($this->params->get('faKitCode')) {
|
||||
}
|
||||
}
|
||||
|
||||
$wa->useStyle('template.user'); // css/user.css
|
||||
|
||||
// ------------------ Context (logo, bootstrap needs) ------------------
|
||||
$sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8');
|
||||
|
||||
@@ -170,6 +156,10 @@ $errorObj = isset($this->error) && is_object($this->error) ? $this->error : nul
|
||||
$errorCode = $errorObj ? (int) $errorObj->getCode() : 500;
|
||||
$errorMsg = $errorObj ? $errorObj->getMessage() : Text::_('JERROR_AN_ERROR_HAS_OCCURRED');
|
||||
$debugOn = defined('JDEBUG') && JDEBUG;
|
||||
|
||||
// Load user assets last (after all other styles and scripts)
|
||||
$wa->useStyle('template.user'); // css/user.css
|
||||
$wa->useScript('user.js'); // js/user.js
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
|
||||
1
src/html/com_jem/calendar/index.html
Normal file
1
src/html/com_jem/calendar/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
167
src/html/com_jem/calendar/mobile.php
Normal file
167
src/html/com_jem/calendar/mobile.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
/**
|
||||
* @package JEM
|
||||
* @subpackage com_jem
|
||||
*
|
||||
* @copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Mobile responsive override for JEM calendar view
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
$events = $this->rows ?? [];
|
||||
$date = $this->date ?? null;
|
||||
$year = $this->year ?? date('Y');
|
||||
$month = $this->month ?? date('m');
|
||||
?>
|
||||
|
||||
<div class="jem-calendar-responsive jem-component">
|
||||
<div class="jem-calendar__container">
|
||||
|
||||
<!-- Calendar Header -->
|
||||
<div class="jem-calendar__header">
|
||||
<h1 class="jem-calendar__title">
|
||||
<?php echo Text::_('COM_JEM_CALENDAR'); ?>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<!-- Calendar Navigation -->
|
||||
<div class="jem-calendar__navigation">
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=calendar&year=' . ($month == 1 ? $year - 1 : $year) . '&month=' . ($month == 1 ? 12 : $month - 1)); ?>"
|
||||
class="jem-calendar__nav-button jem-calendar__nav-prev"
|
||||
aria-label="<?php echo Text::_('COM_JEM_PREVIOUS_MONTH'); ?>">
|
||||
<span aria-hidden="true">‹</span>
|
||||
</a>
|
||||
|
||||
<h2 class="jem-calendar__current-month">
|
||||
<?php echo HTMLHelper::_('date', $year . '-' . $month . '-01', 'F Y'); ?>
|
||||
</h2>
|
||||
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=calendar&year=' . ($month == 12 ? $year + 1 : $year) . '&month=' . ($month == 12 ? 1 : $month + 1)); ?>"
|
||||
class="jem-calendar__nav-button jem-calendar__nav-next"
|
||||
aria-label="<?php echo Text::_('COM_JEM_NEXT_MONTH'); ?>">
|
||||
<span aria-hidden="true">›</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Calendar Grid -->
|
||||
<div class="jem-calendar__grid">
|
||||
<!-- Weekday Headers -->
|
||||
<div class="jem-calendar__weekdays">
|
||||
<?php
|
||||
$weekDays = [
|
||||
Text::_('SUN'),
|
||||
Text::_('MON'),
|
||||
Text::_('TUE'),
|
||||
Text::_('WED'),
|
||||
Text::_('THU'),
|
||||
Text::_('FRI'),
|
||||
Text::_('SAT')
|
||||
];
|
||||
foreach ($weekDays as $day) : ?>
|
||||
<div class="jem-calendar__weekday">
|
||||
<?php echo $day; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Calendar Days -->
|
||||
<div class="jem-calendar__days">
|
||||
<?php
|
||||
// Generate calendar days
|
||||
$firstDay = mktime(0, 0, 0, $month, 1, $year);
|
||||
$daysInMonth = date('t', $firstDay);
|
||||
$dayOfWeek = date('w', $firstDay);
|
||||
|
||||
// Empty cells before first day
|
||||
for ($i = 0; $i < $dayOfWeek; $i++) : ?>
|
||||
<div class="jem-calendar__day jem-calendar__day--empty"></div>
|
||||
<?php endfor;
|
||||
|
||||
// Days with events
|
||||
for ($day = 1; $day <= $daysInMonth; $day++) :
|
||||
$currentDate = sprintf('%04d-%02d-%02d', $year, $month, $day);
|
||||
$hasEvents = false;
|
||||
$dayEvents = [];
|
||||
|
||||
// Check for events on this day
|
||||
if (!empty($events)) {
|
||||
foreach ($events as $event) {
|
||||
if (!empty($event->dates) && date('Y-m-d', strtotime($event->dates)) == $currentDate) {
|
||||
$hasEvents = true;
|
||||
$dayEvents[] = $event;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$isToday = ($currentDate == date('Y-m-d'));
|
||||
$classes = 'jem-calendar__day';
|
||||
if ($hasEvents) {
|
||||
$classes .= ' jem-calendar__day--has-events';
|
||||
}
|
||||
if ($isToday) {
|
||||
$classes .= ' jem-calendar__day--today';
|
||||
}
|
||||
?>
|
||||
<div class="<?php echo $classes; ?>" data-date="<?php echo $currentDate; ?>">
|
||||
<div class="jem-calendar__day-number">
|
||||
<?php echo $day; ?>
|
||||
</div>
|
||||
<?php if ($hasEvents) : ?>
|
||||
<div class="jem-calendar__day-events">
|
||||
<span class="jem-calendar__event-indicator"
|
||||
aria-label="<?php echo Text::sprintf('COM_JEM_EVENTS_COUNT', count($dayEvents)); ?>">
|
||||
<?php echo count($dayEvents); ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Events List for Selected/Current Day -->
|
||||
<?php if (!empty($events)) : ?>
|
||||
<div class="jem-calendar__events-list">
|
||||
<h3 class="jem-calendar__events-title">
|
||||
<?php echo Text::_('COM_JEM_UPCOMING_EVENTS'); ?>
|
||||
</h3>
|
||||
<div class="jem-calendar__events">
|
||||
<?php foreach ($events as $event) : ?>
|
||||
<div class="jem-calendar__event-item">
|
||||
<div class="jem-calendar__event-date">
|
||||
<?php if (!empty($event->dates)) : ?>
|
||||
<time datetime="<?php echo $this->escape($event->dates); ?>">
|
||||
<?php echo HTMLHelper::_('date', $event->dates, Text::_('DATE_FORMAT_LC4')); ?>
|
||||
</time>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<h4 class="jem-calendar__event-title">
|
||||
<?php if (!empty($event->slug)) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=event&id=' . $event->slug); ?>"
|
||||
class="jem-calendar__event-link">
|
||||
<?php echo $this->escape($event->title); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape($event->title); ?>
|
||||
<?php endif; ?>
|
||||
</h4>
|
||||
<?php if (!empty($event->venue)) : ?>
|
||||
<div class="jem-calendar__event-venue">
|
||||
📍 <?php echo $this->escape($event->venue); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
1
src/html/com_jem/categories/index.html
Normal file
1
src/html/com_jem/categories/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
111
src/html/com_jem/categories/mobile.php
Normal file
111
src/html/com_jem/categories/mobile.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/**
|
||||
* @package JEM
|
||||
* @subpackage com_jem
|
||||
*
|
||||
* @copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Mobile responsive override for JEM categories view
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
$categories = $this->categories ?? [];
|
||||
?>
|
||||
|
||||
<div class="jem-categories-responsive jem-component">
|
||||
<div class="jem-categories__container">
|
||||
|
||||
<!-- Categories Header -->
|
||||
<div class="jem-categories__header">
|
||||
<h1 class="jem-categories__title">
|
||||
<?php echo Text::_('COM_JEM_CATEGORIES'); ?>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($categories)) : ?>
|
||||
<div class="jem-categories__list">
|
||||
<?php foreach ($categories as $category) : ?>
|
||||
<div class="jem-categories__item">
|
||||
<div class="jem-categories__item-inner">
|
||||
|
||||
<!-- Category Image -->
|
||||
<?php if (!empty($category->image)) : ?>
|
||||
<div class="jem-categories__image-wrapper">
|
||||
<img src="<?php echo $this->escape($category->image); ?>"
|
||||
alt="<?php echo $this->escape($category->catname); ?>"
|
||||
class="jem-categories__image"
|
||||
loading="lazy">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Category Content -->
|
||||
<div class="jem-categories__content">
|
||||
|
||||
<!-- Category Title -->
|
||||
<h2 class="jem-categories__category-title">
|
||||
<?php if (!empty($category->slug)) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=category&id=' . $category->slug); ?>"
|
||||
class="jem-categories__link">
|
||||
<?php echo $this->escape($category->catname); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape($category->catname); ?>
|
||||
<?php endif; ?>
|
||||
</h2>
|
||||
|
||||
<!-- Category Description -->
|
||||
<?php if (!empty($category->catdescription)) : ?>
|
||||
<div class="jem-categories__description">
|
||||
<?php echo $category->catdescription; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Event Count -->
|
||||
<?php if (isset($category->eventcount)) : ?>
|
||||
<div class="jem-categories__meta">
|
||||
<span class="jem-categories__event-count">
|
||||
<?php echo Text::sprintf('COM_JEM_EVENTS_COUNT_FULL', (int) $category->eventcount); ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- View Category Button -->
|
||||
<?php if (!empty($category->slug)) : ?>
|
||||
<div class="jem-categories__actions">
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=category&id=' . $category->slug); ?>"
|
||||
class="jem-categories__button btn btn-primary"
|
||||
aria-label="<?php echo Text::sprintf('COM_JEM_VIEW_CATEGORY', $this->escape($category->catname)); ?>">
|
||||
<?php echo Text::_('COM_JEM_VIEW_CATEGORY'); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<?php if (!empty($this->pagination)) : ?>
|
||||
<div class="jem-categories__pagination">
|
||||
<?php echo $this->pagination->getPagesLinks(); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php else : ?>
|
||||
<div class="jem-categories__empty">
|
||||
<p class="jem-categories__empty-message">
|
||||
<?php echo Text::_('COM_JEM_NO_CATEGORIES'); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
1
src/html/com_jem/event/index.html
Normal file
1
src/html/com_jem/event/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
212
src/html/com_jem/event/mobile.php
Normal file
212
src/html/com_jem/event/mobile.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/**
|
||||
* @package JEM
|
||||
* @subpackage com_jem
|
||||
*
|
||||
* @copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Mobile responsive override for JEM event details view
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
$item = $this->item ?? null;
|
||||
$params = $this->params ?? null;
|
||||
|
||||
if (!$item) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="jem-event-responsive jem-component">
|
||||
<div class="jem-event__container">
|
||||
|
||||
<!-- Event Header -->
|
||||
<div class="jem-event__header">
|
||||
<h1 class="jem-event__title">
|
||||
<?php echo $this->escape($item->title); ?>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<!-- Event Image -->
|
||||
<?php if (!empty($item->datimage)) : ?>
|
||||
<div class="jem-event__image-wrapper">
|
||||
<img src="<?php echo $this->escape($item->datimage); ?>"
|
||||
alt="<?php echo $this->escape($item->title); ?>"
|
||||
class="jem-event__image"
|
||||
loading="lazy">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Event Meta Information -->
|
||||
<div class="jem-event__meta">
|
||||
|
||||
<!-- Date and Time -->
|
||||
<div class="jem-event__meta-item jem-event__date">
|
||||
<span class="jem-event__meta-icon" aria-hidden="true">📅</span>
|
||||
<div class="jem-event__meta-content">
|
||||
<strong class="jem-event__meta-label">
|
||||
<?php echo Text::_('COM_JEM_DATE'); ?>:
|
||||
</strong>
|
||||
<?php if (!empty($item->dates)) : ?>
|
||||
<time datetime="<?php echo $this->escape($item->dates); ?>"
|
||||
class="jem-event__datetime">
|
||||
<?php echo HTMLHelper::_('date', $item->dates, Text::_('DATE_FORMAT_LC3')); ?>
|
||||
</time>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($item->enddates) && $item->enddates != $item->dates) : ?>
|
||||
<span class="jem-event__date-separator"> - </span>
|
||||
<time datetime="<?php echo $this->escape($item->enddates); ?>"
|
||||
class="jem-event__datetime">
|
||||
<?php echo HTMLHelper::_('date', $item->enddates, Text::_('DATE_FORMAT_LC3')); ?>
|
||||
</time>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Time -->
|
||||
<?php if (!empty($item->times)) : ?>
|
||||
<div class="jem-event__meta-item jem-event__time">
|
||||
<span class="jem-event__meta-icon" aria-hidden="true">🕐</span>
|
||||
<div class="jem-event__meta-content">
|
||||
<strong class="jem-event__meta-label">
|
||||
<?php echo Text::_('COM_JEM_TIME'); ?>:
|
||||
</strong>
|
||||
<span class="jem-event__time-value">
|
||||
<?php echo $this->escape($item->times); ?>
|
||||
<?php if (!empty($item->endtimes)) : ?>
|
||||
- <?php echo $this->escape($item->endtimes); ?>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Venue -->
|
||||
<?php if (!empty($item->venue)) : ?>
|
||||
<div class="jem-event__meta-item jem-event__venue">
|
||||
<span class="jem-event__meta-icon" aria-hidden="true">📍</span>
|
||||
<div class="jem-event__meta-content">
|
||||
<strong class="jem-event__meta-label">
|
||||
<?php echo Text::_('COM_JEM_VENUE'); ?>:
|
||||
</strong>
|
||||
<?php if (!empty($item->venueslug)) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=venue&id=' . $item->venueslug); ?>"
|
||||
class="jem-event__venue-link">
|
||||
<?php echo $this->escape($item->venue); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<span class="jem-event__venue-name">
|
||||
<?php echo $this->escape($item->venue); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($item->street) || !empty($item->city)) : ?>
|
||||
<div class="jem-event__address">
|
||||
<?php if (!empty($item->street)) : ?>
|
||||
<span class="jem-event__street">
|
||||
<?php echo $this->escape($item->street); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($item->city)) : ?>
|
||||
<span class="jem-event__city">
|
||||
<?php echo $this->escape($item->city); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Categories -->
|
||||
<?php if (!empty($item->categories)) : ?>
|
||||
<div class="jem-event__meta-item jem-event__categories">
|
||||
<span class="jem-event__meta-icon" aria-hidden="true">🏷️</span>
|
||||
<div class="jem-event__meta-content">
|
||||
<strong class="jem-event__meta-label">
|
||||
<?php echo Text::_('COM_JEM_CATEGORIES'); ?>:
|
||||
</strong>
|
||||
<div class="jem-event__category-list">
|
||||
<?php foreach ($item->categories as $category) : ?>
|
||||
<span class="jem-event__category-badge">
|
||||
<?php echo $this->escape($category->catname); ?>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Event Description -->
|
||||
<?php if (!empty($item->fulltext)) : ?>
|
||||
<div class="jem-event__description">
|
||||
<h2 class="jem-event__description-title">
|
||||
<?php echo Text::_('COM_JEM_DESCRIPTION'); ?>
|
||||
</h2>
|
||||
<div class="jem-event__description-content">
|
||||
<?php echo $item->fulltext; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Event Registration -->
|
||||
<?php if (!empty($item->registra) && $item->registra == 1) : ?>
|
||||
<div class="jem-event__registration">
|
||||
<h2 class="jem-event__registration-title">
|
||||
<?php echo Text::_('COM_JEM_REGISTRATION'); ?>
|
||||
</h2>
|
||||
<?php if (!empty($item->maxplaces)) : ?>
|
||||
<p class="jem-event__capacity">
|
||||
<strong><?php echo Text::_('COM_JEM_MAX_PLACES'); ?>:</strong>
|
||||
<?php echo (int) $item->maxplaces; ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($item->waitinglist)) : ?>
|
||||
<p class="jem-event__waitinglist">
|
||||
<?php echo Text::_('COM_JEM_WAITING_LIST_ENABLED'); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Event Contact -->
|
||||
<?php if (!empty($item->contactname)) : ?>
|
||||
<div class="jem-event__contact">
|
||||
<h2 class="jem-event__contact-title">
|
||||
<?php echo Text::_('COM_JEM_CONTACT'); ?>
|
||||
</h2>
|
||||
<p class="jem-event__contact-info">
|
||||
<strong><?php echo Text::_('COM_JEM_NAME'); ?>:</strong>
|
||||
<?php echo $this->escape($item->contactname); ?>
|
||||
</p>
|
||||
<?php if (!empty($item->contactemail)) : ?>
|
||||
<p class="jem-event__contact-info">
|
||||
<strong><?php echo Text::_('COM_JEM_EMAIL'); ?>:</strong>
|
||||
<a href="mailto:<?php echo $this->escape($item->contactemail); ?>"
|
||||
class="jem-event__contact-link">
|
||||
<?php echo $this->escape($item->contactemail); ?>
|
||||
</a>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Back Button -->
|
||||
<div class="jem-event__actions">
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=eventslist'); ?>"
|
||||
class="jem-event__button btn btn-secondary">
|
||||
<?php echo Text::_('COM_JEM_BACK_TO_EVENTS'); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
1
src/html/com_jem/eventslist/index.html
Normal file
1
src/html/com_jem/eventslist/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
147
src/html/com_jem/eventslist/mobile.php
Normal file
147
src/html/com_jem/eventslist/mobile.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/**
|
||||
* @package JEM
|
||||
* @subpackage com_jem
|
||||
*
|
||||
* @copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Mobile responsive override for JEM events list view
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
// Load JEM helper if available
|
||||
if (file_exists(JPATH_SITE . '/components/com_jem/helpers/helper.php')) {
|
||||
require_once JPATH_SITE . '/components/com_jem/helpers/helper.php';
|
||||
}
|
||||
|
||||
$items = $this->items ?? [];
|
||||
$params = $this->params ?? null;
|
||||
?>
|
||||
|
||||
<div class="jem-eventslist-responsive jem-component">
|
||||
<div class="jem-eventslist__container">
|
||||
|
||||
<?php if (!empty($this->pageheading)) : ?>
|
||||
<div class="jem-eventslist__header">
|
||||
<h1 class="jem-eventslist__title">
|
||||
<?php echo $this->escape($this->pageheading); ?>
|
||||
</h1>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($items)) : ?>
|
||||
<div class="jem-eventslist__list">
|
||||
<?php foreach ($items as $item) : ?>
|
||||
<div class="jem-eventslist__item">
|
||||
<div class="jem-eventslist__item-inner">
|
||||
|
||||
<!-- Event Date -->
|
||||
<div class="jem-eventslist__date">
|
||||
<?php if (!empty($item->dates)) : ?>
|
||||
<time datetime="<?php echo $this->escape($item->dates); ?>"
|
||||
class="jem-eventslist__datetime">
|
||||
<?php echo HTMLHelper::_('date', $item->dates, Text::_('DATE_FORMAT_LC4')); ?>
|
||||
</time>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($item->enddates) && $item->enddates != $item->dates) : ?>
|
||||
<span class="jem-eventslist__date-separator"> - </span>
|
||||
<time datetime="<?php echo $this->escape($item->enddates); ?>"
|
||||
class="jem-eventslist__datetime">
|
||||
<?php echo HTMLHelper::_('date', $item->enddates, Text::_('DATE_FORMAT_LC4')); ?>
|
||||
</time>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Event Title -->
|
||||
<h2 class="jem-eventslist__event-title">
|
||||
<?php if (!empty($item->slug)) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=event&id=' . $item->slug); ?>"
|
||||
class="jem-eventslist__link">
|
||||
<?php echo $this->escape($item->title); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape($item->title); ?>
|
||||
<?php endif; ?>
|
||||
</h2>
|
||||
|
||||
<!-- Event Venue -->
|
||||
<?php if (!empty($item->venue)) : ?>
|
||||
<div class="jem-eventslist__venue">
|
||||
<span class="jem-eventslist__venue-icon" aria-hidden="true">📍</span>
|
||||
<?php if (!empty($item->venueslug)) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=venue&id=' . $item->venueslug); ?>"
|
||||
class="jem-eventslist__venue-link">
|
||||
<?php echo $this->escape($item->venue); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<span class="jem-eventslist__venue-name">
|
||||
<?php echo $this->escape($item->venue); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($item->city)) : ?>
|
||||
<span class="jem-eventslist__city">
|
||||
, <?php echo $this->escape($item->city); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Event Description -->
|
||||
<?php if (!empty($item->introtext)) : ?>
|
||||
<div class="jem-eventslist__description">
|
||||
<?php echo $item->introtext; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Event Categories -->
|
||||
<?php if (!empty($item->categories)) : ?>
|
||||
<div class="jem-eventslist__categories">
|
||||
<?php foreach ($item->categories as $category) : ?>
|
||||
<span class="jem-eventslist__category-badge">
|
||||
<?php echo $this->escape($category->catname); ?>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Read More Button -->
|
||||
<?php if (!empty($item->slug)) : ?>
|
||||
<div class="jem-eventslist__actions">
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=event&id=' . $item->slug); ?>"
|
||||
class="jem-eventslist__button btn btn-primary"
|
||||
aria-label="<?php echo Text::sprintf('COM_JEM_READ_MORE_ABOUT', $this->escape($item->title)); ?>">
|
||||
<?php echo Text::_('COM_JEM_READ_MORE'); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<?php if (!empty($this->pagination)) : ?>
|
||||
<div class="jem-eventslist__pagination">
|
||||
<?php echo $this->pagination->getPagesLinks(); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php else : ?>
|
||||
<div class="jem-eventslist__empty">
|
||||
<p class="jem-eventslist__empty-message">
|
||||
<?php echo Text::_('COM_JEM_NO_EVENTS'); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
1
src/html/com_jem/index.html
Normal file
1
src/html/com_jem/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
1
src/html/com_jem/venue/index.html
Normal file
1
src/html/com_jem/venue/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
188
src/html/com_jem/venue/mobile.php
Normal file
188
src/html/com_jem/venue/mobile.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
/**
|
||||
* @package JEM
|
||||
* @subpackage com_jem
|
||||
*
|
||||
* @copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Mobile responsive override for JEM venue view
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
$venue = $this->venue ?? null;
|
||||
$events = $this->rows ?? [];
|
||||
|
||||
if (!$venue) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="jem-venue-responsive jem-component">
|
||||
<div class="jem-venue__container">
|
||||
|
||||
<!-- Venue Header -->
|
||||
<div class="jem-venue__header">
|
||||
<h1 class="jem-venue__title">
|
||||
<?php echo $this->escape($venue->venue); ?>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<!-- Venue Image -->
|
||||
<?php if (!empty($venue->locimage)) : ?>
|
||||
<div class="jem-venue__image-wrapper">
|
||||
<img src="<?php echo $this->escape($venue->locimage); ?>"
|
||||
alt="<?php echo $this->escape($venue->venue); ?>"
|
||||
class="jem-venue__image"
|
||||
loading="lazy">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Venue Information -->
|
||||
<div class="jem-venue__info">
|
||||
|
||||
<!-- Address -->
|
||||
<?php if (!empty($venue->street) || !empty($venue->city) || !empty($venue->postalCode)) : ?>
|
||||
<div class="jem-venue__info-item jem-venue__address">
|
||||
<span class="jem-venue__info-icon" aria-hidden="true">📍</span>
|
||||
<div class="jem-venue__info-content">
|
||||
<strong class="jem-venue__info-label">
|
||||
<?php echo Text::_('COM_JEM_ADDRESS'); ?>:
|
||||
</strong>
|
||||
<address class="jem-venue__address-content">
|
||||
<?php if (!empty($venue->street)) : ?>
|
||||
<div class="jem-venue__street">
|
||||
<?php echo $this->escape($venue->street); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($venue->postalCode) || !empty($venue->city)) : ?>
|
||||
<div class="jem-venue__city-line">
|
||||
<?php if (!empty($venue->postalCode)) : ?>
|
||||
<span class="jem-venue__postal">
|
||||
<?php echo $this->escape($venue->postalCode); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($venue->city)) : ?>
|
||||
<span class="jem-venue__city">
|
||||
<?php echo $this->escape($venue->city); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($venue->state)) : ?>
|
||||
<div class="jem-venue__state">
|
||||
<?php echo $this->escape($venue->state); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($venue->country)) : ?>
|
||||
<div class="jem-venue__country">
|
||||
<?php echo $this->escape($venue->country); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</address>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Website -->
|
||||
<?php if (!empty($venue->url)) : ?>
|
||||
<div class="jem-venue__info-item jem-venue__website">
|
||||
<span class="jem-venue__info-icon" aria-hidden="true">🌐</span>
|
||||
<div class="jem-venue__info-content">
|
||||
<strong class="jem-venue__info-label">
|
||||
<?php echo Text::_('COM_JEM_WEBSITE'); ?>:
|
||||
</strong>
|
||||
<a href="<?php echo $this->escape($venue->url); ?>"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="jem-venue__link">
|
||||
<?php echo $this->escape($venue->url); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Description -->
|
||||
<?php if (!empty($venue->locdescription)) : ?>
|
||||
<div class="jem-venue__description">
|
||||
<h2 class="jem-venue__description-title">
|
||||
<?php echo Text::_('COM_JEM_DESCRIPTION'); ?>
|
||||
</h2>
|
||||
<div class="jem-venue__description-content">
|
||||
<?php echo $venue->locdescription; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Map -->
|
||||
<?php if (!empty($venue->latitude) && !empty($venue->longitude)) : ?>
|
||||
<div class="jem-venue__map">
|
||||
<h2 class="jem-venue__map-title">
|
||||
<?php echo Text::_('COM_JEM_LOCATION'); ?>
|
||||
</h2>
|
||||
<div class="jem-venue__map-container">
|
||||
<!-- Map would be rendered here by JEM's map functionality -->
|
||||
<div class="jem-venue__map-placeholder">
|
||||
<p><?php echo Text::_('COM_JEM_MAP_VIEW'); ?></p>
|
||||
<p>
|
||||
<a href="https://www.google.com/maps?q=<?php echo $venue->latitude; ?>,<?php echo $venue->longitude; ?>"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="jem-venue__map-link btn btn-primary">
|
||||
<?php echo Text::_('COM_JEM_VIEW_ON_MAP'); ?>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Events at this Venue -->
|
||||
<?php if (!empty($events)) : ?>
|
||||
<div class="jem-venue__events">
|
||||
<h2 class="jem-venue__events-title">
|
||||
<?php echo Text::_('COM_JEM_EVENTS_AT_VENUE'); ?>
|
||||
</h2>
|
||||
<div class="jem-venue__events-list">
|
||||
<?php foreach ($events as $event) : ?>
|
||||
<div class="jem-venue__event-item">
|
||||
<div class="jem-venue__event-date">
|
||||
<?php if (!empty($event->dates)) : ?>
|
||||
<time datetime="<?php echo $this->escape($event->dates); ?>">
|
||||
<?php echo HTMLHelper::_('date', $event->dates, Text::_('DATE_FORMAT_LC4')); ?>
|
||||
</time>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<h3 class="jem-venue__event-title">
|
||||
<?php if (!empty($event->slug)) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=event&id=' . $event->slug); ?>"
|
||||
class="jem-venue__event-link">
|
||||
<?php echo $this->escape($event->title); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape($event->title); ?>
|
||||
<?php endif; ?>
|
||||
</h3>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Back Button -->
|
||||
<div class="jem-venue__actions">
|
||||
<a href="<?php echo Route::_('index.php?option=com_jem&view=eventslist'); ?>"
|
||||
class="jem-venue__button btn btn-secondary">
|
||||
<?php echo Text::_('COM_JEM_BACK_TO_EVENTS'); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -11,8 +11,13 @@
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// Ensure module language file is loaded
|
||||
$lang = Factory::getLanguage();
|
||||
$lang->load('mod_cblogin', JPATH_SITE);
|
||||
|
||||
$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
// Add responsive wrapper class
|
||||
@@ -11,8 +11,13 @@
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// Ensure module language file is loaded
|
||||
$lang = Factory::getLanguage();
|
||||
$lang->load('mod_comprofilerOnline', JPATH_SITE);
|
||||
|
||||
$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
// Add responsive wrapper class
|
||||
9
src/html/mod_menu/index.html
Normal file
9
src/html/mod_menu/index.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
104
src/html/mod_menu/mainmenu.php
Normal file
104
src/html/mod_menu/mainmenu.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage mod_menu
|
||||
*
|
||||
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Main Menu - Mobile responsive collapsible dropdown menu override
|
||||
* Bootstrap 5 responsive navbar with hamburger menu
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Helper\ModuleHelper;
|
||||
|
||||
$id = '';
|
||||
|
||||
if ($tagId = $params->get('tag_id', '')) {
|
||||
$id = ' id="' . $tagId . '"';
|
||||
}
|
||||
|
||||
// Get module class suffix
|
||||
$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
// The menu class is deprecated. Use mod-menu instead
|
||||
?>
|
||||
<nav class="mod-menu mod-menu-main navbar navbar-expand-lg<?php echo $moduleclass_sfx; ?>"<?php echo $id; ?>>
|
||||
<div class="container-fluid">
|
||||
<!-- Hamburger toggle button for mobile -->
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainMenuCollapse" aria-controls="mainMenuCollapse" aria-expanded="false" aria-label="Toggle Main Menu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- Collapsible menu content -->
|
||||
<div class="collapse navbar-collapse" id="mainMenuCollapse">
|
||||
<ul class="navbar-nav mod-menu-main__list">
|
||||
<?php foreach ($list as $i => &$item) :
|
||||
$itemParams = $item->getParams();
|
||||
$class = 'nav-item mod-menu-main__item item-' . $item->id;
|
||||
|
||||
if ($item->id == $default_id) {
|
||||
$class .= ' default';
|
||||
}
|
||||
|
||||
if ($item->id == $active_id || ($item->type === 'alias' && $itemParams->get('aliasoptions') == $active_id)) {
|
||||
$class .= ' current';
|
||||
}
|
||||
|
||||
if (in_array($item->id, $path)) {
|
||||
$class .= ' active';
|
||||
} elseif ($item->type === 'alias') {
|
||||
$aliasToId = $itemParams->get('aliasoptions');
|
||||
|
||||
if (count($path) > 0 && $aliasToId == $path[count($path) - 1]) {
|
||||
$class .= ' active';
|
||||
} elseif (in_array($aliasToId, $path)) {
|
||||
$class .= ' alias-parent-active';
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->type === 'separator') {
|
||||
$class .= ' divider';
|
||||
}
|
||||
|
||||
if ($item->deeper) {
|
||||
$class .= ' deeper dropdown';
|
||||
}
|
||||
|
||||
if ($item->parent) {
|
||||
$class .= ' parent';
|
||||
}
|
||||
|
||||
echo '<li class="' . $class . '">';
|
||||
|
||||
switch ($item->type) :
|
||||
case 'separator':
|
||||
case 'component':
|
||||
case 'heading':
|
||||
case 'url':
|
||||
require ModuleHelper::getLayoutPath('mod_menu', 'mainmenu_' . $item->type);
|
||||
break;
|
||||
|
||||
default:
|
||||
require ModuleHelper::getLayoutPath('mod_menu', 'mainmenu_url');
|
||||
break;
|
||||
endswitch;
|
||||
|
||||
// The next item is deeper.
|
||||
if ($item->deeper) {
|
||||
echo '<ul class="dropdown-menu mod-menu-main__dropdown">';
|
||||
} elseif ($item->shallower) {
|
||||
// The next item is shallower.
|
||||
echo '</li>';
|
||||
echo str_repeat('</ul></li>', $item->level_diff);
|
||||
} else {
|
||||
// The next item is on the same level.
|
||||
echo '</li>';
|
||||
}
|
||||
endforeach;
|
||||
?></ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
64
src/html/mod_menu/mainmenu_component.php
Normal file
64
src/html/mod_menu/mainmenu_component.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage mod_menu
|
||||
*
|
||||
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Main Menu - Component item layout
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Filter\OutputFilter;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
$attributes = [];
|
||||
|
||||
if ($item->anchor_title) {
|
||||
$attributes['title'] = $item->anchor_title;
|
||||
}
|
||||
|
||||
if ($item->anchor_css) {
|
||||
$attributes['class'] = $item->anchor_css;
|
||||
}
|
||||
|
||||
if ($item->anchor_rel) {
|
||||
$attributes['rel'] = $item->anchor_rel;
|
||||
}
|
||||
|
||||
$linktype = $item->title;
|
||||
|
||||
if ($item->menu_icon) {
|
||||
// The link is an icon
|
||||
if ($itemParams->get('menu_text', 1)) {
|
||||
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||
} else {
|
||||
// If the icon itself is the link, it needs a visually hidden text
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->browserNav == 1) {
|
||||
$attributes['target'] = '_blank';
|
||||
$attributes['rel'] = 'noopener noreferrer';
|
||||
} elseif ($item->browserNav == 2) {
|
||||
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
|
||||
|
||||
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
|
||||
}
|
||||
|
||||
// Add dropdown toggle for items with children
|
||||
$linkClass = 'nav-link mod-menu-main__link';
|
||||
if ($item->deeper) {
|
||||
$linkClass .= ' dropdown-toggle';
|
||||
$attributes['data-bs-toggle'] = 'dropdown';
|
||||
$attributes['role'] = 'button';
|
||||
$attributes['aria-expanded'] = 'false';
|
||||
}
|
||||
|
||||
$attributes['class'] = $linkClass;
|
||||
|
||||
echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
|
||||
37
src/html/mod_menu/mainmenu_heading.php
Normal file
37
src/html/mod_menu/mainmenu_heading.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage mod_menu
|
||||
*
|
||||
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Main Menu - Heading item layout
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : '';
|
||||
$anchor_css = $item->anchor_css ?: '';
|
||||
|
||||
$linktype = $item->title;
|
||||
|
||||
if ($item->menu_icon) {
|
||||
// The link is an icon
|
||||
if ($itemParams->get('menu_text', 1)) {
|
||||
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||
} else {
|
||||
// If the icon itself is the link, it needs a visually hidden text
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
// Add dropdown toggle for items with children
|
||||
$headingClass = 'nav-link mod-menu-main__heading';
|
||||
if ($item->deeper) {
|
||||
$headingClass .= ' dropdown-toggle';
|
||||
}
|
||||
|
||||
?>
|
||||
<span class="<?php echo $headingClass . ' ' . $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
|
||||
31
src/html/mod_menu/mainmenu_separator.php
Normal file
31
src/html/mod_menu/mainmenu_separator.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage mod_menu
|
||||
*
|
||||
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Main Menu - Separator item layout
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : '';
|
||||
$anchor_css = $item->anchor_css ?: '';
|
||||
|
||||
$linktype = $item->title;
|
||||
|
||||
if ($item->menu_icon) {
|
||||
// The link is an icon
|
||||
if ($itemParams->get('menu_text', 1)) {
|
||||
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||
} else {
|
||||
// If the icon itself is the link, it needs a visually hidden text
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<span class="dropdown-divider mod-menu-main__separator <?php echo $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
|
||||
69
src/html/mod_menu/mainmenu_url.php
Normal file
69
src/html/mod_menu/mainmenu_url.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage mod_menu
|
||||
*
|
||||
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Main Menu - URL item layout
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Filter\OutputFilter;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
$attributes = [];
|
||||
|
||||
if ($item->anchor_title) {
|
||||
$attributes['title'] = $item->anchor_title;
|
||||
}
|
||||
|
||||
if ($item->anchor_css) {
|
||||
$attributes['class'] = $item->anchor_css;
|
||||
}
|
||||
|
||||
if ($item->anchor_rel) {
|
||||
$attributes['rel'] = $item->anchor_rel;
|
||||
}
|
||||
|
||||
$linktype = $item->title;
|
||||
|
||||
if ($item->menu_icon) {
|
||||
// The link is an icon
|
||||
if ($itemParams->get('menu_text', 1)) {
|
||||
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||
} else {
|
||||
// If the icon itself is the link, it needs a visually hidden text
|
||||
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->browserNav == 1) {
|
||||
$attributes['target'] = '_blank';
|
||||
$attributes['rel'] = 'noopener noreferrer';
|
||||
} elseif ($item->browserNav == 2) {
|
||||
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
|
||||
|
||||
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
|
||||
}
|
||||
|
||||
// Add dropdown toggle for items with children
|
||||
$linkClass = 'nav-link mod-menu-main__link';
|
||||
if ($item->deeper) {
|
||||
$linkClass .= ' dropdown-toggle';
|
||||
$attributes['data-bs-toggle'] = 'dropdown';
|
||||
$attributes['role'] = 'button';
|
||||
$attributes['aria-expanded'] = 'false';
|
||||
}
|
||||
|
||||
// Merge existing class with our class
|
||||
if (isset($attributes['class'])) {
|
||||
$attributes['class'] .= ' ' . $linkClass;
|
||||
} else {
|
||||
$attributes['class'] = $linkClass;
|
||||
}
|
||||
|
||||
echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
|
||||
@@ -45,9 +45,9 @@ $document = $app->getDocument();
|
||||
$wa = $document->getWebAssetManager();
|
||||
|
||||
// Template params
|
||||
$params_LightColorName = (string) $this->params->get('colorLightName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom
|
||||
$params_LightColorName = (string) $this->params->get('colorLightName', 'standard'); // standard|custom
|
||||
|
||||
$params_DarkColorName = (string) $this->params->get('colorDarkName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom
|
||||
$params_DarkColorName = (string) $this->params->get('colorDarkName', 'standard'); // standard|custom
|
||||
|
||||
$params_googletagmanager = $this->params->get('googletagmanager', false);
|
||||
$params_googletagmanagerid = $this->params->get('googletagmanagerid', null);
|
||||
@@ -88,36 +88,6 @@ $templatePath = 'media/templates/site/mokocassiopeia';
|
||||
// Core template CSS
|
||||
$wa->useStyle('template.base'); // css/template.css
|
||||
|
||||
// Color theme (light + optional dark)
|
||||
$colorLightKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_LightColorName));
|
||||
$colorDarkKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_DarkColorName));
|
||||
$lightKey = 'template.light.' . $colorLightKey;
|
||||
$darkKey = 'template.dark.' . $colorDarkKey;
|
||||
|
||||
try {
|
||||
$wa->useStyle('template.light.colors_standard');
|
||||
} catch (\Throwable $e) {
|
||||
$wa->registerAndUseStyle('template.light.colors_standard', $templatePath . '/css/colors/light/colors_standard.css');
|
||||
}
|
||||
|
||||
try {
|
||||
$wa->useStyle('template.dark.colors_standard');
|
||||
} catch (\Throwable $e) {
|
||||
$wa->registerAndUseStyle('template.dark.colors_standard', $templatePath . '/css/colors/dark/colors_standard.css');
|
||||
}
|
||||
|
||||
try {
|
||||
$wa->useStyle($lightKey);
|
||||
} catch (\Throwable $e) {
|
||||
$wa->registerAndUseStyle('template.light.dynamic', $templatePath . '/css/colors/light/' . $colorLightKey . '.css');
|
||||
}
|
||||
|
||||
try {
|
||||
$wa->useStyle($darkKey);
|
||||
} catch (\Throwable $e) {
|
||||
$wa->registerAndUseStyle('template.dark.dynamic', $templatePath . '/css/colors/dark/' . $colorDarkKey . '.css');
|
||||
}
|
||||
|
||||
// Scripts
|
||||
$wa->useScript('template.js');
|
||||
|
||||
@@ -149,8 +119,6 @@ $fontStyles = '';
|
||||
|
||||
if ($params_FontScheme) {
|
||||
if (stripos($params_FontScheme, 'https://') === 0) {
|
||||
$this->getPreloadManager()->preconnect('https://fonts.googleapis.com/', ['crossorigin' => 'anonymous']);
|
||||
$this->getPreloadManager()->preconnect('https://fonts.gstatic.com/', ['crossorigin' => 'anonymous']);
|
||||
$this->getPreloadManager()->preload($params_FontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']);
|
||||
$wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, [], [
|
||||
'media' => 'print',
|
||||
@@ -259,7 +227,23 @@ if ($this->params->get('fA6KitCode')) {
|
||||
$params_leftIcon = htmlspecialchars($this->params->get('drawerLeftIcon', 'fa-solid fa-chevron-left'), ENT_COMPAT, 'UTF-8');
|
||||
$params_rightIcon = htmlspecialchars($this->params->get('drawerRightIcon', 'fa-solid fa-chevron-right'), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
// Load theme palette stylesheets based on configuration
|
||||
$wa->useStyle('template.light.standard'); // css/theme/light.standard.css
|
||||
$wa->useStyle('template.dark.standard'); // css/theme/dark.standard.css
|
||||
|
||||
// Load custom palettes only if selected in template configuration AND files exist
|
||||
if ($params_LightColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/light.custom.css'))
|
||||
{
|
||||
$wa->useStyle('template.light.custom');
|
||||
}
|
||||
if ($params_DarkColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/dark.custom.css'))
|
||||
{
|
||||
$wa->useStyle('template.dark.custom');
|
||||
}
|
||||
|
||||
// Load user assets last (after all other styles and scripts)
|
||||
$wa->useStyle('template.user'); // css/user.css
|
||||
$wa->useScript('user.js'); // js/user.js
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
|
||||
@@ -46,6 +46,18 @@
|
||||
"uri": "media/templates/site/mokocassiopeia/css/user.min.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "user.js",
|
||||
"type": "script",
|
||||
"uri": "media/templates/site/mokocassiopeia/js/user.js",
|
||||
"attributes": {"defer": true}
|
||||
},
|
||||
{
|
||||
"name": "user.js.min",
|
||||
"type": "script",
|
||||
"uri": "media/templates/site/mokocassiopeia/js/user.min.js",
|
||||
"attributes": {"defer": true}
|
||||
},
|
||||
{
|
||||
"name": "template.font.osaka",
|
||||
"type": "style",
|
||||
@@ -65,62 +77,51 @@
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.light.colors_standard",
|
||||
"name": "template.light.standard",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/light/colors_standard.css",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/light.standard.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.light.colors_standard.min",
|
||||
"name": "template.light.standard.min",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/light/colors_standard.min.css",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/light.standard.min.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.light.colors_custom",
|
||||
"name": "template.light.custom",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/light.custom.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.light.colors_custom.min",
|
||||
"name": "template.light.custom.min",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/light/colors_custom.min.css",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/light.custom.min.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.dark.colors_standard",
|
||||
"name": "template.dark.standard",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_standard.css",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/dark.standard.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.dark.colors_standard.min",
|
||||
"name": "template.dark.standard.min",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_standard.min.css",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/dark.standard.min.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.dark.colors_alternative",
|
||||
"name": "template.dark.custom",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_alternative.css",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/dark.custom.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.dark.colors_alternative.min",
|
||||
"name": "template.dark.custom.min",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_alternative.min.css"
|
||||
},
|
||||
{
|
||||
"name": "template.dark.colors_custom",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.dark.colors_custom.min",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.min.css",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/dark.custom.min.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
@@ -11,9 +11,7 @@
|
||||
; VERSION: 03.06.02
|
||||
; BRIEF: English (GB) language strings for the MokoCassiopeia Joomla template
|
||||
;
|
||||
; ===== Template meta =====
|
||||
MOKOCASSIOPEIA="MokoCassiopeia Site template"
|
||||
TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="<h3>MokoCassiopeia Template Description</h3> <p> <strong>MokoCassiopeia 3.0</strong> continues Joomla’s tradition of space-themed default templates— building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5), and <em>Protostar</em> (Joomla 3.0). </p> <p> This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting. </p> <h4>Code Attribution</h4> <p> This template is based on the original <strong>Cassiopeia</strong> template developed by the <a href=\"https://www.joomla.org\" target=\"_blank\" rel=\"noopener\">Joomla! Project</a> and released under the GNU General Public License. </p> <p> Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. </p> <p> It includes integration with <a href=\"https://afeld.github.io/bootstrap-toc/\" target=\"_blank\" rel=\"noopener\">Bootstrap TOC</a>, an open-source table of contents generator by A. Feld, licensed under the MIT License. </p> <p> All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. </p>"
|
||||
; Note: Template metadata strings (name, description) are in tpl_mokocassiopeia.sys.ini
|
||||
|
||||
; ===== System / layout =====
|
||||
TPL_MOKOCASSIOPEIA_DEVELOPMENTMODE_LABEL="Development Mode"
|
||||
@@ -77,9 +75,9 @@ TPL_MOKOCASSIOPEIA_COLOR_NAME_STANDARD="Standard"
|
||||
TPL_MOKOCASSIOPEIA_COLOR_NAME_CUSTOM="Custom"
|
||||
; New labels for Theme tab dropdowns
|
||||
TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_LABEL="Light colour palette"
|
||||
TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_DESC="Select a colour palette for light mode. <strong>Standard</strong> uses the default blue theme with comprehensive styling for all components. <strong>Custom</strong> allows you to create your own colour scheme - copy the template file from <code>templates/colors_custom.css</code> to <code>media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css</code> and customise the CSS variables to match your brand."
|
||||
TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_DESC="Select a colour palette for light mode. <strong>Standard</strong> uses the default blue theme with comprehensive styling for all components. <strong>Custom</strong> allows you to create your own colour scheme - copy the template file from <code>templates/theme_custom_light.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/light.custom.css</code> and customise the CSS variables to match your brand."
|
||||
TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_LABEL="Dark colour palette"
|
||||
TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_DESC="Select a colour palette for dark mode. <strong>Standard</strong> uses the default blue theme optimised for dark backgrounds with proper contrast. <strong>Custom</strong> allows you to create your own colour scheme - copy the template file from <code>templates/colors_custom.css</code> to <code>media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css</code> and customise the CSS variables to match your brand."
|
||||
TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_DESC="Select a colour palette for dark mode. <strong>Standard</strong> uses the default blue theme optimised for dark backgrounds with proper contrast. <strong>Custom</strong> allows you to create your own colour scheme - copy the template file from <code>templates/theme_custom_dark.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/dark.custom.css</code> and customise the CSS variables to match your brand."
|
||||
|
||||
; ===== Theme tab (core feature strings) =====
|
||||
TPL_MOKO_THEME_FIELDSET="Theme"
|
||||
|
||||
@@ -34,4 +34,4 @@ TPL_MOKOCASSIOPEIA_POSITION_TOP_B="Top-b"
|
||||
TPL_MOKOCASSIOPEIA_POSITION_TOPBAR="Top Bar"
|
||||
TPL_MOKOCASSIOPEIA_POSITION_DRAWER_LEFT="Drawer-Left"
|
||||
TPL_MOKOCASSIOPEIA_POSITION_DRAWER_RIGHT="Drawer-Right"
|
||||
TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="<h3>MokoCassiopeia Template Description</h3> <p> <strong>MokoCassiopeia 3.0</strong> continues Joomla’s tradition of space-themed default templates— building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5), and <em>Protostar</em> (Joomla 3.0). </p> <p> This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting. </p> <h4>Custom Colour Themes</h4> <p> To create a custom colour scheme, copy the template file <code>templates/colors_custom.css</code> to either <code>media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css</code> or <code>media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css</code>. Customise the CSS variables to match your brand, then activate it in <em>System → Site Templates → MokoCassiopeia → Theme tab</em> by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see <code>docs/CSS_VARIABLES.md</code>. </p> <h4>Code Attribution</h4> <p> This template is based on the original <strong>Cassiopeia</strong> template developed by the <a href=\"https://www.joomla.org\" target=\"_blank\" rel=\"noopener\">Joomla! Project</a> and released under the GNU General Public License. </p> <p> Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. </p> <p> It includes integration with <a href=\"https://afeld.github.io/bootstrap-toc/\" target=\"_blank\" rel=\"noopener\">Bootstrap TOC</a>, an open-source table of contents generator by A. Feld, licensed under the MIT License. </p> <p> All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. </p>"
|
||||
TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="<h3>MokoCassiopeia Template Description</h3> <p> <strong>MokoCassiopeia 3.0</strong> continues Joomla’s tradition of space-themed default templates— building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5), and <em>Protostar</em> (Joomla 3.0). </p> <p> This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting. </p> <h4>Custom Colour Themes</h4> <p> To create a custom colour scheme, copy the template file <code>templates/theme_custom_light.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/light.custom.css</code> or <code>media/templates/site/mokocassiopeia/css/theme/dark.custom.css</code>. Customise the CSS variables to match your brand, then activate it in <em>System → Site Templates → MokoCassiopeia → Theme tab</em> by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see <code>docs/CSS_VARIABLES.md</code>. </p> <h4>Code Attribution</h4> <p> This template is based on the original <strong>Cassiopeia</strong> template developed by the <a href=\"https://www.joomla.org\" target=\"_blank\" rel=\"noopener\">Joomla! Project</a> and released under the GNU General Public License. </p> <p> Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. </p> <p> It includes integration with <a href=\"https://afeld.github.io/bootstrap-toc/\" target=\"_blank\" rel=\"noopener\">Bootstrap TOC</a>, an open-source table of contents generator by A. Feld, licensed under the MIT License. </p> <p> All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. </p>"
|
||||
@@ -11,9 +11,7 @@
|
||||
; VERSION: 03.06.02
|
||||
; BRIEF: English (US) language strings for the MokoCassiopeia Joomla template
|
||||
;
|
||||
; ===== Template meta =====
|
||||
MOKOCASSIOPEIA="MokoCassiopeia Site template"
|
||||
TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="<h3>MokoCassiopeia Template Description</h3> <p> <strong>MokoCassiopeia 3.0</strong> continues Joomla’s tradition of space-themed default templates— building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5), and <em>Protostar</em> (Joomla 3.0). </p> <p> This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting. </p> <h4>Code Attribution</h4> <p> This template is based on the original <strong>Cassiopeia</strong> template developed by the <a href=\"https://www.joomla.org\" target=\"_blank\" rel=\"noopener\">Joomla! Project</a> and released under the GNU General Public License. </p> <p> Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. </p> <p> It includes integration with <a href=\"https://afeld.github.io/bootstrap-toc/\" target=\"_blank\" rel=\"noopener\">Bootstrap TOC</a>, an open-source table of contents generator by A. Feld, licensed under the MIT License. </p> <p> All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. </p>"
|
||||
; Note: Template metadata strings (name, description) are in tpl_mokocassiopeia.sys.ini
|
||||
|
||||
; ===== System / layout =====
|
||||
TPL_MOKOCASSIOPEIA_DEVELOPMENTMODE_LABEL="Development Mode"
|
||||
@@ -77,9 +75,9 @@ TPL_MOKOCASSIOPEIA_COLOR_NAME_STANDARD="Standard"
|
||||
TPL_MOKOCASSIOPEIA_COLOR_NAME_CUSTOM="Custom"
|
||||
; New labels for Theme tab dropdowns
|
||||
TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_LABEL="Light color palette"
|
||||
TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_DESC="Select a color palette for light mode. <strong>Standard</strong> uses the default blue theme with comprehensive styling for all components. <strong>Custom</strong> allows you to create your own color scheme - copy the template file from <code>templates/colors_custom.css</code> to <code>media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css</code> and customize the CSS variables to match your brand."
|
||||
TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_DESC="Select a color palette for light mode. <strong>Standard</strong> uses the default blue theme with comprehensive styling for all components. <strong>Custom</strong> allows you to create your own color scheme - copy the template file from <code>templates/theme_custom_light.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/light.custom.css</code> and customize the CSS variables to match your brand."
|
||||
TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_LABEL="Dark color palette"
|
||||
TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_DESC="Select a color palette for dark mode. <strong>Standard</strong> uses the default blue theme optimized for dark backgrounds with proper contrast. <strong>Custom</strong> allows you to create your own color scheme - copy the template file from <code>templates/colors_custom.css</code> to <code>media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css</code> and customize the CSS variables to match your brand."
|
||||
TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_DESC="Select a color palette for dark mode. <strong>Standard</strong> uses the default blue theme optimized for dark backgrounds with proper contrast. <strong>Custom</strong> allows you to create your own color scheme - copy the template file from <code>templates/theme_custom_dark.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/dark.custom.css</code> and customize the CSS variables to match your brand."
|
||||
|
||||
; ===== Theme tab (core feature strings) =====
|
||||
TPL_MOKO_THEME_FIELDSET="Theme"
|
||||
|
||||
@@ -34,4 +34,4 @@ TPL_MOKOCASSIOPEIA_POSITION_TOP_B="Top-b"
|
||||
TPL_MOKOCASSIOPEIA_POSITION_TOPBAR="Top Bar"
|
||||
TPL_MOKOCASSIOPEIA_POSITION_DRAWER_LEFT="Drawer-Left"
|
||||
TPL_MOKOCASSIOPEIA_POSITION_DRAWER_RIGHT="Drawer-Right"
|
||||
TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="<h3>MokoCassiopeia Template Description</h3> <p> <strong>MokoCassiopeia 3.0</strong> continues Joomla’s tradition of space-themed default templates— building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5), and <em>Protostar</em> (Joomla 3.0). </p> <p> This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting. </p> <h4>Custom Color Themes</h4> <p> To create a custom color scheme, copy the template file <code>templates/colors_custom.css</code> to either <code>media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css</code> or <code>media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css</code>. Customize the CSS variables to match your brand, then activate it in <em>System → Site Templates → MokoCassiopeia → Theme tab</em> by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see <code>docs/CSS_VARIABLES.md</code>. </p> <h4>Code Attribution</h4> <p> This template is based on the original <strong>Cassiopeia</strong> template developed by the <a href=\"https://www.joomla.org\" target=\"_blank\" rel=\"noopener\">Joomla! Project</a> and released under the GNU General Public License. </p> <p> Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. </p> <p> It includes integration with <a href=\"https://afeld.github.io/bootstrap-toc/\" target=\"_blank\" rel=\"noopener\">Bootstrap TOC</a>, an open-source table of contents generator by A. Feld, licensed under the MIT License. </p> <p> All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. </p>"
|
||||
TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="<h3>MokoCassiopeia Template Description</h3> <p> <strong>MokoCassiopeia 3.0</strong> continues Joomla’s tradition of space-themed default templates— building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5), and <em>Protostar</em> (Joomla 3.0). </p> <p> This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting. </p> <h4>Custom Color Themes</h4> <p> To create a custom color scheme, copy the template file <code>templates/theme_custom_light.css</code> to <code>media/templates/site/mokocassiopeia/css/theme/light.custom.css</code> or <code>media/templates/site/mokocassiopeia/css/theme/dark.custom.css</code>. Customize the CSS variables to match your brand, then activate it in <em>System → Site Templates → MokoCassiopeia → Theme tab</em> by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see <code>docs/CSS_VARIABLES.md</code>. </p> <h4>Code Attribution</h4> <p> This template is based on the original <strong>Cassiopeia</strong> template developed by the <a href=\"https://www.joomla.org\" target=\"_blank\" rel=\"noopener\">Joomla! Project</a> and released under the GNU General Public License. </p> <p> Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. </p> <p> It includes integration with <a href=\"https://afeld.github.io/bootstrap-toc/\" target=\"_blank\" rel=\"noopener\">Bootstrap TOC</a>, an open-source table of contents generator by A. Feld, licensed under the MIT License. </p> <p> All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. </p>"
|
||||
@@ -1,95 +0,0 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <jmiller@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Site
|
||||
INGROUP: Templates.MokoCassiopeia
|
||||
FILE: index.html
|
||||
BRIEF: Security redirect page to block folder access and forward to site root.
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Redirecting…</title>
|
||||
|
||||
<!-- Search engines: do not index this placeholder redirect page -->
|
||||
<meta name="robots" content="noindex, nofollow, noarchive" />
|
||||
|
||||
<!-- Instant redirect fallback even if JavaScript is disabled -->
|
||||
<meta http-equiv="refresh" content="0; url=/" />
|
||||
|
||||
<!-- Canonical root reference -->
|
||||
<link rel="canonical" href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<script>
|
||||
|
||||
(function redirectToRoot() {
|
||||
// Configuration object with safe defaults.
|
||||
var opts = {
|
||||
fallbackPath: "/", // string: fallback destination if origin is unavailable
|
||||
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
|
||||
behavior: "replace" // enum: "replace" | "assign"
|
||||
};
|
||||
|
||||
// Determine absolute origin in all mainstream browsers.
|
||||
var origin = (typeof location.origin === "string" && location.origin)
|
||||
|| (location.protocol + "//" + location.host);
|
||||
|
||||
// Final destination: absolute root of the current site, or fallback path.
|
||||
var destination = origin ? origin + "/" : opts.fallbackPath;
|
||||
|
||||
function go() {
|
||||
if (opts.behavior === "assign") {
|
||||
location.assign(destination);
|
||||
} else {
|
||||
location.replace(destination);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute redirect, optionally after a short delay.
|
||||
if (opts.delayMs > 0) {
|
||||
setTimeout(go, opts.delayMs);
|
||||
} else {
|
||||
go();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Secondary meta-refresh for no-JS environments is already set above.
|
||||
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
|
||||
-->
|
||||
|
||||
<noscript>
|
||||
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
|
||||
<style>
|
||||
html, body { height:100%; }
|
||||
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
|
||||
.msg { opacity: .75; text-align: center; }
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
<body>
|
||||
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
|
||||
</body>
|
||||
</html>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user