diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cb4761d..4af0a5a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -104,15 +104,7 @@ jobs: INPUT_SUFFIX: ${{ steps.meta.outputs.suffix }} run: | BRANCH="${{ github.ref_name }}" - - # Skip auto-bump on main — version is already set before merge - if [ "$BRANCH" = "main" ]; then - CURRENT=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1) - echo "On main — using current version ${CURRENT} (no bump)" - echo "version=${CURRENT}" >> "$GITHUB_OUTPUT" - echo "zip_name=${EXT_ELEMENT}-${CURRENT}${INPUT_SUFFIX}.zip" >> "$GITHUB_OUTPUT" - exit 0 - fi + GITEA_API="${GITEA_URL}/api/v1/repos/${{ github.repository }}" # Read current version from README.md CURRENT=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1) @@ -163,7 +155,7 @@ jobs: PYEOF fi - # Commit bump + # Commit bump to current branch git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" git config --local user.name "gitea-actions[bot]" git remote set-url origin "https://jmiller:${GA_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git" @@ -174,6 +166,21 @@ jobs: git push } + # For stable releases from dev: merge dev → main via Gitea API + if [ "$INPUT_STABILITY" = "stable" ] && [ "$BRANCH" != "main" ]; then + echo "Merging ${BRANCH} → main via Gitea API..." + MERGE_RESULT=$(curl -sf -X POST -H "Authorization: token ${GA_TOKEN}" \ + -H "Content-Type: application/json" \ + "${GITEA_API}/merges" \ + -d "$(jq -n \ + --arg base "main" \ + --arg head "${BRANCH}" \ + --arg msg "chore(release): merge ${BRANCH} for stable ${NEW_VERSION} [skip ci]" \ + '{base: $base, head: $head, merge_message_field: $msg}' + )" 2>&1) || true + echo "Merge result: ${MERGE_RESULT}" + fi + echo "version=${NEW_VERSION}" >> "$GITHUB_OUTPUT" echo "zip_name=${EXT_ELEMENT}-${NEW_VERSION}${INPUT_SUFFIX}.zip" >> "$GITHUB_OUTPUT" @@ -368,6 +375,7 @@ jobs: exit 0 fi + # Cascading channels: each stability updates itself and all lower levels export PY_STABILITY="$STABILITY" PY_VERSION="$VERSION" PY_SHA256="$SHA256" \ PY_ZIP_NAME="$ZIP_NAME" PY_TAG="$TAG" PY_DATE="$DATE" \ PY_GITEA_ORG="$GITEA_ORG" PY_GITEA_REPO="$GITEA_REPO" @@ -383,73 +391,53 @@ jobs: gitea_org = os.environ["PY_GITEA_ORG"] gitea_repo = os.environ["PY_GITEA_REPO"] - # Map stability to the value in updates.xml - tag_map = { - "development": "development", - "alpha": "alpha", - "beta": "beta", - "rc": "rc", - "stable": "stable", + # Cascade map: each level updates itself + all lower levels + cascade = { + "stable": ["development", "alpha", "beta", "rc", "stable"], + "rc": ["development", "alpha", "beta", "rc"], + "beta": ["development", "alpha", "beta"], + "alpha": ["development", "alpha"], + "development": ["development"], } - xml_tag = tag_map.get(stability, "development") + targets = cascade.get(stability, [stability]) with open("updates.xml", "r") as f: content = f.read() - # Build regex to find the specific block for this stability tag - # Use negative lookahead to avoid matching across multiple blocks - block_pattern = r"((?:(?!).)*?" + re.escape(xml_tag) + r".*?)" - match = re.search(block_pattern, content, re.DOTALL) - - if not match: - print(f"No block found for {xml_tag}") - exit(0) - - block = match.group(1) - original_block = block - - # Update version - block = re.sub(r"[^<]*", f"{version}", block) - - # Update creation date - block = re.sub(r"[^<]*", f"{date}", block) - - # Update or add SHA-256 - if "" in block: - block = re.sub(r"[^<]*", f"{sha256}", block) - else: - block = block.replace("", f"\n {sha256}") - - # Update Gitea download URL gitea_url = f"https://git.mokoconsulting.tech/{gitea_org}/{gitea_repo}/releases/download/{tag}/{zip_name}" - block = re.sub( - r"(]*>)https://git\.mokoconsulting\.tech/[^<]*()", - rf"\g<1>{gitea_url}\g<2>", - block - ) - # Update GitHub download URL only for RC and stable (others are Gitea-only) - if stability in ("rc", "stable"): - gh_url = f"https://github.com/mokoconsulting-tech/{gitea_repo}/releases/download/{tag}/{zip_name}" + for xml_tag in targets: + block_pattern = r"((?:(?!).)*?" + re.escape(xml_tag) + r".*?)" + match = re.search(block_pattern, content, re.DOTALL) + + if not match: + print(f"No block for {xml_tag} — skipping") + continue + + block = match.group(1) + original = block + + block = re.sub(r"[^<]*", f"{version}", block) + block = re.sub(r"[^<]*", f"{date}", block) + + if "" in block: + block = re.sub(r"[^<]*", f"{sha256}", block) + else: + block = block.replace("", f"\n {sha256}") + block = re.sub( - r"(]*>)https://github\.com/[^<]*()", - rf"\g<1>{gh_url}\g<2>", - block - ) - else: - # Remove any GitHub download URL for dev/alpha/beta - block = re.sub( - r"\n\s*]*>https://github\.com/[^<]*", - "", + r"(]*>)https://git\.mokoconsulting\.tech/[^<]*()", + rf"\g<1>{gitea_url}\g<2>", block ) - content = content.replace(original_block, block) + content = content.replace(original, block) + print(f"Updated {xml_tag} channel") with open("updates.xml", "w") as f: f.write(content) - print(f"Updated {xml_tag} channel: version={version}, sha={sha256[:16]}..., date={date}") + print(f"Cascaded {stability} → {', '.join(targets)}: v={version}, sha={sha256[:16]}...") PYEOF - name: "Commit updates.xml to current branch and main" @@ -476,39 +464,27 @@ jobs: # Push to current branch git push || true - # Also update updates.xml on main via Gitea API (git push blocked by branch protection) - if [ "$CURRENT_BRANCH" != "main" ]; then - GA_TOKEN="${{ secrets.GA_TOKEN }}" - API="${GITEA_URL}/api/v1/repos/${{ github.repository }}" + # Sync updates.xml to main via direct API + GA_TOKEN="${{ secrets.GA_TOKEN }}" + API="${GITEA_URL}/api/v1/repos/${{ github.repository }}" - # Get current file SHA on main (required for update) - FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \ - "${API}/contents/updates.xml?ref=main" | jq -r '.sha // empty') + FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \ + "${API}/contents/updates.xml?ref=main" | jq -r '.sha // empty') - if [ -n "$FILE_SHA" ]; then - # Base64-encode the updates.xml content from working tree (has updated SHA) - CONTENT=$(base64 -w0 updates.xml) - - RESPONSE=$(curl -s -w "\n%{http_code}" -X PUT -H "Authorization: token ${GA_TOKEN}" \ - -H "Content-Type: application/json" \ - "${API}/contents/updates.xml" \ - -d "$(jq -n \ - --arg content "$CONTENT" \ - --arg sha "$FILE_SHA" \ - --arg msg "chore: update ${STABILITY} channel to ${VERSION} on main [skip ci]" \ - --arg branch "main" \ - '{content: $content, sha: $sha, message: $msg, branch: $branch}' - )") - HTTP_CODE=$(echo "$RESPONSE" | tail -1) - if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "201" ]; then - echo "updates.xml synced to main via API (HTTP ${HTTP_CODE})" - else - echo "WARNING: failed to sync updates.xml to main (HTTP ${HTTP_CODE})" - echo "$RESPONSE" | head -5 - fi - else - echo "WARNING: could not get file SHA for updates.xml on main" - fi + if [ -n "$FILE_SHA" ]; then + CONTENT=$(base64 -w0 updates.xml) + curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \ + -H "Content-Type: application/json" \ + "${API}/contents/updates.xml" \ + -d "$(jq -n \ + --arg content "$CONTENT" \ + --arg sha "$FILE_SHA" \ + --arg msg "chore: sync updates.xml ${STABILITY} ${VERSION} [skip ci]" \ + --arg branch "main" \ + '{content: $content, sha: $sha, message: $msg, branch: $branch}' + )" > /dev/null 2>&1 \ + && echo "updates.xml synced to main" \ + || echo "WARNING: failed to sync updates.xml to main" fi - name: Summary diff --git a/README.md b/README.md index b850b5d..c7eaf8d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ INGROUP: MokoCassiopeia.Documentation REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia FILE: ./README.md - VERSION: 03.10.22 + VERSION: 03.10.24 BRIEF: Documentation for MokoCassiopeia template --> @@ -19,7 +19,7 @@ **Retired — See [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx)** -[![Version](https://img.shields.io/badge/version-03.09.07-blue.svg?logo=v&logoColor=white)](https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia/releases/tag/v03) +[![Version](https://img.shields.io/badge/version-03.10.24-blue.svg?logo=v&logoColor=white)](https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia/releases/tag/v03) [![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green.svg?logo=gnu&logoColor=white)](LICENSE) [![Joomla](https://img.shields.io/badge/Joomla-5.x%20%7C%206.x-red.svg?logo=joomla&logoColor=white)](https://www.joomla.org) [![PHP](https://img.shields.io/badge/PHP-8.1%2B-777BB4.svg?logo=php&logoColor=white)](https://www.php.net) @@ -28,13 +28,13 @@ MokoCassiopeia is a modern, lightweight enhancement layer built on top of Joomla --- -## 📑 Table of Contents +## Table of Contents - [Features](#-features) - [Requirements](#-requirements) - [Installation](#-installation) - [Quick Start](#-quick-start) -- [Configuration](#️-configuration) +- [Configuration](#-configuration) - [Theme System](#-theme-system) - [Development](#-development) - [Documentation](#-documentation) @@ -46,475 +46,19 @@ MokoCassiopeia is a modern, lightweight enhancement layer built on top of Joomla --- -## ✨ Features - -### Core Enhancements +## Features - **Built on Cassiopeia**: Extends Joomla's default template with minimal overrides - **Font Awesome 7**: Fully integrated into Joomla's asset manager with 2,000+ icons - **Bootstrap 5**: Extended utility classes and responsive grid system -- **No Template Overrides**: Clean installation that inherits all Cassiopeia defaults -- **Upgrade-Friendly**: Minimal modifications ensure smooth Joomla updates - -### Advanced Theming - - **Dark Mode Support**: Built-in light/dark mode toggle with system preference detection -- **Color Palettes**: Standard, Alternative, and Custom color schemes -- **Theme Persistence**: User preferences saved via localStorage -- **Theme Control Options**: Switch, radio buttons, or hidden controls -- **Auto Dark Mode**: Optional automatic dark mode based on time/system settings -- **Meta Tags**: Automatic color-scheme and theme-color meta tags - -### Developer Features - -- **Custom Code Injection**: Add custom HTML to `` start/end -- **Drawer Sidebars**: Configurable left/right drawer positions with custom icons -- **Font Options**: Local and web fonts (Roboto, Fira Sans, Noto Sans) -- **Sticky Header**: Optional sticky navigation -- **Back to Top**: Floating back-to-top button - -### Analytics & Tracking - -- **Google Tag Manager**: Optional GTM integration with container ID configuration -- **Google Analytics**: Optional GA4 integration with measurement ID -- **Privacy-Friendly**: All tracking features are optional and easily disabled - -### Content Features - +- **Google Tag Manager / GA4**: Optional analytics integrations - **Table of Contents**: Automatic TOC generation for long articles - - Placement options: `toc-left` or `toc-right` layouts - - Automatic heading extraction and navigation - - Responsive sidebar positioning ---- - -## 📋 Requirements - -- **Joomla**: 4.4.x or 5.x -- **PHP**: 8.0 or higher -- **Database**: MySQL 5.7+ / MariaDB 10.2+ / PostgreSQL 11+ -- **Browser Support**: Modern browsers (Chrome, Firefox, Safari, Edge) - ---- - -## 📦 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://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia/releases) -2. In Joomla admin, navigate to **System → Install → Extensions** -3. Upload the ZIP file and click **Upload & Install** -4. Navigate to **System → Site Templates** -5. Set **MokoCassiopeia** as your default template - -### Via Git (Development) - -```bash -git clone https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia.git -cd MokoCassiopeia -``` - -See [Development Guide](./docs/JOOMLA_DEVELOPMENT.md) for development setup. - ---- - -## 🚀 Quick Start - -### 1. Install the Template - -Install `mokocassiopeia.zip` via Joomla's Extension Manager. - -### 2. Set as Default - -Navigate to **System → Site Templates** and set **MokoCassiopeia** as default. - -### 3. Configure Template Options - -Go to **System → Site Templates → MokoCassiopeia** to configure: - -- **Branding**: Upload logo, set site title/description -- **Theme**: Configure color schemes and dark mode -- **Layout**: Set container type (static/fluid), sticky header -- **Analytics**: Add GTM/GA4 tracking codes (optional) -- **Custom Code**: Inject custom HTML/CSS/JS - -### 4. Test Dark Mode - -The template includes a dark mode toggle. Test it by: -- Using the floating theme toggle button (bottom-right by default) -- Checking theme persistence across page loads -- Verifying system preference detection - ---- - -## Usage - -Once installed and set as the default site template, MokoCassiopeia works out of the box with Joomla's standard content and module system. Key usage points: - -- **Template Options** — Configure via **System → Site Templates → MokoCassiopeia** (theme colours, layout, analytics, favicon, drawers) -- **Custom Colour Schemes** — Copy `templates/mokocassiopeia/templates/light.custom.css` or `dark.custom.css` to `media/templates/site/mokocassiopeia/css/theme/` and select "Custom" in the Theme tab -- **Custom CSS/JS** — Create `media/templates/site/mokocassiopeia/css/user.css` or `js/user.js` for site-specific overrides that survive template updates -- **Module Overrides** — The template includes overrides for common Joomla modules with consistent title rendering, Bootstrap 5 styling, and Font Awesome 7 icons -- **Dark Mode** — Enabled by default with a floating toggle button; respects system preference and persists via localStorage - -See [Configuration](#️-configuration) below for detailed parameter reference. - ---- - -## ⚙️ Configuration - -### Global Parameters - -Access template configuration via **System → Site Templates → MokoCassiopeia**. - -#### Theme Tab - -**General Settings:** -- **Theme Enabled**: Enable/disable theme system -- **Theme Control Type**: Switch (Light↔Dark), Radios (Light/Dark/System), or None -- **Default Choice**: System, Light, or Dark -- **Auto Dark Mode**: Automatic dark mode based on time -- **Meta Tags**: Enable color-scheme and theme-color meta tags -- **Bridge Bootstrap ARIA**: Sync theme with Bootstrap's data-bs-theme - -**Variables & Palettes:** -- **Light Mode Palette**: Standard, Alternative, or Custom -- **Dark Mode Palette**: Standard, Alternative, or Custom - -**Typography:** -- **Font Scheme**: Local (Roboto) or Web fonts (Fira Sans, Roboto+Noto Sans) - -**Branding & Icons:** -- **Brand**: Enable/disable site branding -- **Logo File**: Upload custom logo (no default logo included) -- **Site Title**: Custom site title -- **Site Description**: Tagline/description -- **Font Awesome Kit**: Optional FA Pro kit code - -**Header & Navigation:** -- **Sticky Header**: Enable fixed header on scroll -- **Back to Top**: Enable floating back-to-top button - -**Theme Toggle UI:** -- **FAB Enabled**: Enable floating action button toggle -- **FAB Position**: Bottom-right, Bottom-left, Top-right, or Top-left - -#### Advanced Tab - -- **Layout**: Static or Fluid container - -#### Google Tab - -- **Google Tag Manager**: Enable and configure GTM container ID -- **Google Analytics**: Enable and configure GA4 measurement ID - -#### Custom Code Tab - -- **Custom Head Start**: HTML injected at start of `` -- **Custom Head End**: HTML injected at end of `` - -#### Drawers Tab - -- **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 Theme Palettes - -MokoCassiopeia supports custom theme schemes: - -1. **Copy template files** from `/templates/` directory: - - `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 - -**Note:** Custom color files are excluded from version control (`.gitignore`) to prevent fork-specific customizations from being committed. - -**Quick Example:** - -```css -:root[data-bs-theme="light"] { - --color-primary: #1e40af; - --color-link: #2563eb; - --color-hover: #1d4ed8; - --body-color: #1f2937; - --body-bg: #ffffff; -} -``` - -**Complete Reference:** See [CSS Variables Documentation](./docs/CSS_VARIABLES.md) for all available variables and detailed usage examples. - -### Table of Contents - -Enable automatic TOC for articles: - -1. Edit an article in Joomla admin -2. Navigate to **Options → Layout** -3. Select **toc-left** or **toc-right** -4. Save the article - -The TOC will automatically generate from article headings (H2, H3, etc.) and appear as a sidebar. - ---- - -## 🎨 Theme System - -### Dark Mode Features - -- **Automatic Detection**: Respects user's system preferences -- **Manual Toggle**: Floating button or radio controls -- **Persistence**: Saves preference in localStorage -- **Smooth Transitions**: Animated theme switching -- **Comprehensive Support**: All components themed for dark mode - -### Theme Control Types - -1. **Switch**: Simple light/dark toggle button -2. **Radios**: Three options - Light, Dark, System -3. **None**: No visible control (respects system only) - -### Meta Tags - -When enabled, the template adds: - -```html - - - -``` - ---- - -## 🛠 Development - -### For Contributors - -**New to the project?** See [Quick Start Guide](./docs/QUICK_START.md) for a 5-minute setup. - -### Development Resources - -- **[Quick Start Guide](./docs/QUICK_START.md)** - Setup and first steps -- **[Joomla Development Guide](./docs/JOOMLA_DEVELOPMENT.md)** - Testing, quality checks, deployment -- **[Workflow Guide](./docs/WORKFLOW_GUIDE.md)** - Git workflow and branching -- **[Contributing Guide](./CONTRIBUTING.md)** - Contribution guidelines -- **[Roadmap](./docs/ROADMAP.md)** - Feature roadmap and planning - -### Development Tools - -- **Pre-commit Hooks**: Automatic validation before commits -- **PHP CodeSniffer**: Code style validation (Joomla standards) -- **PHPStan**: Static analysis for PHP code -- **Codeception**: Testing framework - -### Quick Development Setup - -```bash -# Clone repository -git clone https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia.git -cd MokoCassiopeia - -# Install development dependencies (if using Composer) -composer install --dev - -# Run code quality checks -make validate # or manual commands -``` - -### Building Template Package - -See [Joomla Development Guide](./docs/JOOMLA_DEVELOPMENT.md) for packaging instructions. - ---- - -## 📚 Documentation - -### User Documentation - -- **[README](./README.md)** - This file (overview and features) -- **[CHANGELOG](./CHANGELOG.md)** - Version history and changes -- **[Roadmap](./docs/ROADMAP.md)** - Planned features and timeline - -### Developer Documentation - -- **[Quick Start](./docs/QUICK_START.md)** - 5-minute developer setup -- **[Development Guide](./docs/JOOMLA_DEVELOPMENT.md)** - Comprehensive development guide -- **[Workflow Guide](./docs/WORKFLOW_GUIDE.md)** - Git workflow and processes -- **[CSS Variables Reference](./docs/CSS_VARIABLES.md)** - Complete CSS customization guide -- **[Documentation Index](./docs/README.md)** - All documentation links - -### Governance - -- **[Contributing](./CONTRIBUTING.md)** - How to contribute -- **[Code of Conduct](./CODE_OF_CONDUCT.md)** - Community standards -- **[Governance](./GOVERNANCE.md)** - Project governance model -- **[Security Policy](./SECURITY.md)** - Security reporting and procedures - ---- - -## 📖 Changelog - -See the [CHANGELOG.md](./CHANGELOG.md) for detailed version history. - -### Recent Releases - -- **[03.06.03]** (2026-01-30) - README updates and TOC color variable improvements -- **[03.06.02]** (2026-01-30) - Complete rebrand to MokoCassiopeia, removed all overrides -- **[03.06.00]** (2026-01-28) - Version standardization -- **[03.05.01]** (2026-01-09) - Security and compliance improvements -- **[02.00.00]** (2025-08-30) - Dark mode toggle and improved theming - ---- - -## 💬 Support - -### Getting Help - -- **Documentation**: Check this README and [docs folder](./docs/) -- **Issues**: Report bugs via [GitHub Issues](https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia/issues) -- **Discussions**: Ask questions in [GitHub Discussions](https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia/discussions) -- **Roadmap**: View planned features in [Roadmap](https://mokoconsulting.tech/support/joomla-cms/mokocassiopeia-roadmap) - -### Reporting Bugs - -Please include: -- Joomla version -- PHP version -- Template version -- Steps to reproduce -- Expected vs actual behavior -- Screenshots (if applicable) - -### Security Issues - -**Do not** report security vulnerabilities via public issues. See [SECURITY.md](./SECURITY.md) for reporting procedures. - ---- - -## 🤝 Contributing - -We welcome contributions! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines. - -### How to Contribute - -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/amazing-feature`) -3. Make your changes -4. Run quality checks -5. Commit your changes (`git commit -m 'Add amazing feature'`) -6. Push to the branch (`git push origin feature/amazing-feature`) -7. Open a Pull Request - -### Development Workflow - -See [Workflow Guide](./docs/WORKFLOW_GUIDE.md) for detailed Git workflow. - -### Customizations - -For template customizations, use Joomla's built-in template settings (System → Site Templates → MokoCassiopeia → Custom Code tab) for HTML/CSS/JS customizations. - ---- - -## 📦 Included Libraries - -MokoCassiopeia includes the following third-party libraries to provide enhanced functionality: - -### Bootstrap TOC - -- **Version**: 1.0.1 -- **Author**: Aidan Feldman -- **License**: MIT License -- **Source**: [GitHub Repository](https://github.com/afeld/bootstrap-toc) -- **Release**: [v1.0.1 Release](https://github.com/afeld/bootstrap-toc/releases/tag/v1.0.1) -- **Purpose**: Automatically generates a table of contents from article headings with scrollspy support -- **Location**: `src/media/vendor/bootstrap-toc/` -- **Integration**: Registered in `joomla.asset.json` as `vendor.bootstrap-toc` (CSS) and `vendor.bootstrap-toc.js` (JavaScript) -- **Usage**: Activated when using `toc-left` or `toc-right` article layouts -- **Features**: - - Automatic TOC generation from H1-H6 headings - - Hierarchical nested navigation - - Active state highlighting with scrollspy - - Responsive design (collapses on mobile) - - Smooth scrolling to sections - - Automatic unique ID generation for headings -- **Customizations**: CSS adapted to use Cassiopeia CSS variables for theme compatibility - -### Font Awesome 7 Free - -- **Version**: 7.0 (Free) -- **License**: Font Awesome Free License -- **Source**: [Font Awesome](https://fontawesome.com) -- **Purpose**: Provides 2,000+ vector icons for interface elements -- **Location**: `src/media/vendor/fa7free/` -- **Integration**: Fully integrated into Joomla's asset manager -- **Styles Available**: Solid, Regular, Brands - -### Bootstrap 5 - -- **Version**: 5.x (via Joomla) -- **License**: MIT License -- **Source**: [Bootstrap](https://getbootstrap.com) -- **Purpose**: Provides responsive grid system and utility classes -- **Integration**: Inherited from Joomla's Cassiopeia template, extended with additional helpers -- **Components Used**: Grid, utilities, modal, dropdown, collapse, offcanvas, tooltip, popover, scrollspy - -### Integration Method - -All third-party libraries are: -- ✅ Properly licensed and attributed -- ✅ Registered in Joomla's Web Asset Manager (`joomla.asset.json`) -- ✅ Loaded on-demand to optimize performance -- ✅ Versioned and documented for maintenance -- ✅ Compatible with Joomla 4.4.x and 5.x - ---- - -## 📄 License +## License This project is licensed under the **GNU General Public License v3.0** - see the [LICENSE](./LICENSE) file for details. -### Third-Party Licenses - -- **Joomla! CMS**: GPL-2.0-or-later -- **Cassiopeia Template**: GPL-2.0-or-later (Joomla Project) -- **Font Awesome 7 Free**: Font Awesome Free License -- **Bootstrap 5**: MIT License -- **Bootstrap TOC**: MIT License (A. Feld) - -All third-party libraries and assets remain the property of their respective authors and are credited in source files. - --- -## 🔗 Links - -- **Repository**: [GitHub](https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia) -- **Issue Tracker**: [GitHub Issues](https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia/issues) -- **Discussions**: [GitHub Discussions](https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia/discussions) -- **Roadmap**: [Full Roadmap](https://mokoconsulting.tech/support/joomla-cms/mokocassiopeia-roadmap) -- **Moko Consulting**: [Website](https://mokoconsulting.tech) - ---- - -## 📊 Metadata - -- **Maintainer**: Moko Consulting Engineering -- **Author**: Jonathan Miller (@jmiller-moko) -- **Repository**: https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia -- **License**: GPL-3.0-or-later -- **Classification**: Public Open Source Standards - -## 📝 Revision History - -| Date | Version | Change Summary | Author | -| ---------- | -------- | ------------------------------------------------------------------------- | ------------------------------- | -| 2026-01-30 | 03.06.03 | Updated README title, fixed custom color variables instructions, improved TOC color scheme integration | Copilot Agent | -| 2026-01-30 | 03.06.02 | Regenerated README with comprehensive documentation and updated structure | Copilot Agent | -| 2026-01-30 | 03.06.02 | Complete rebrand to MokoCassiopeia, removed overrides | Copilot Agent | -| 2026-01-05 | 03.00.00 | Initial publication of template documentation and feature overview | Moko Consulting | -| 2026-01-05 | 03.00.00 | Fixed malformed markdown table formatting in revision history | Jonathan Miller (@jmiller-moko) | - ---- - -**Made with ❤️ by [Moko Consulting](https://mokoconsulting.tech)** +**Made with love by [Moko Consulting](https://mokoconsulting.tech)** diff --git a/src/script.php b/src/script.php index c6d0023..5fa417a 100644 --- a/src/script.php +++ b/src/script.php @@ -122,11 +122,14 @@ class Tpl_MokocassiopeiaInstallerScript implements InstallerScriptInterface // 5. Redirect update server to MokoOnyx $this->updateUpdateServer(); - // 6. Notify + // 6. Unlock MokoCassiopeia (allow uninstall) + lock MokoOnyx (prevent accidental uninstall) + $this->updateExtensionLocks(); + + // 7. Notify $app->enqueueMessage( 'MokoOnyx has been installed as a replacement for MokoCassiopeia.
' . 'Your template settings have been migrated. MokoOnyx is now your active site template.
' - . 'You can safely uninstall MokoCassiopeia from Extensions → Manage.', + . 'MokoCassiopeia has been unlocked — you can uninstall it from Extensions → Manage.', 'success' ); @@ -362,6 +365,42 @@ class Tpl_MokocassiopeiaInstallerScript implements InstallerScriptInterface } } + private function updateExtensionLocks(): void + { + $db = Factory::getDbo(); + + // Unlock MokoCassiopeia — allow uninstall + try { + $query = $db->getQuery(true) + ->update('#__extensions') + ->set($db->quoteName('locked') . ' = 0') + ->set($db->quoteName('protected') . ' = 0') + ->where($db->quoteName('element') . ' = ' . $db->quote(self::OLD_NAME)) + ->where($db->quoteName('type') . ' = ' . $db->quote('template')); + $db->setQuery($query)->execute(); + if ($db->getAffectedRows() > 0) { + $this->log('Bridge: unlocked MokoCassiopeia (can be uninstalled).'); + } + } catch (\Throwable $e) { + $this->log('Bridge: failed to unlock MokoCassiopeia: ' . $e->getMessage(), 'warning'); + } + + // Lock MokoOnyx — prevent accidental uninstall + try { + $query = $db->getQuery(true) + ->update('#__extensions') + ->set($db->quoteName('locked') . ' = 1') + ->where($db->quoteName('element') . ' = ' . $db->quote(self::NEW_NAME)) + ->where($db->quoteName('type') . ' = ' . $db->quote('template')); + $db->setQuery($query)->execute(); + if ($db->getAffectedRows() > 0) { + $this->log('Bridge: locked MokoOnyx (protected from uninstall).'); + } + } catch (\Throwable $e) { + $this->log('Bridge: failed to lock MokoOnyx: ' . $e->getMessage(), 'warning'); + } + } + // ── Logging ──────────────────────────────────────────────────────── private function log(string $message, string $priority = 'info'): void diff --git a/src/templateDetails.xml b/src/templateDetails.xml index 117e5df..2579be4 100644 --- a/src/templateDetails.xml +++ b/src/templateDetails.xml @@ -39,7 +39,7 @@ MokoCassiopeia - 03.10.22 + 03.10.23 script.php 2026-04-19 Jonathan Miller || Moko Consulting