#!/usr/bin/env php * * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION * DEFGROUP: mokocli.CLI * INGROUP: mokocli * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli * PATH: /cli/theme_vars_check.php * BRIEF: Verify a client MokoOnyx theme defines all required CSS variables * (light + dark) and passes basic theme-package sanity checks. * * Standalone (no CliFramework dependency) so it runs even when the shared * framework autoloader is unavailable. * * Usage: php theme_vars_check.php --path . [--github-output] [--strict] */ declare(strict_types=1); $opts = getopt('', ['path:', 'github-output', 'strict']); $path = $opts['path'] ?? '.'; if (!is_string($path) || $path === '') { $path = '.'; } $gh = array_key_exists('github-output', $opts); $root = realpath($path); if ($root === false) { $root = $path; } // Locate the package source directory (src/ preferred, source/ legacy). $src = is_dir("$root/src") ? "$root/src" : (is_dir("$root/source") ? "$root/source" : null); if ($src === null) { fwrite(STDERR, "ERROR: no src/ or source/ directory under $root\n"); exit(1); } $errors = 0; $summary = []; $fail = function (string $msg) use (&$errors, &$summary): void { echo " [FAIL] $msg\n"; $summary[] = "FAIL: $msg"; $errors++; }; $ok = function (string $msg): void { echo " [ok] $msg\n"; }; $cssDir = "$src/media/templates/site/mokoonyx/css"; $themeDir = "$cssDir/theme"; $light = "$themeDir/light.custom.css"; $dark = "$themeDir/dark.custom.css"; $manifest = "$src/templateDetails.xml"; echo "MokoOnyx theme validation: $src\n\n"; // 1) Required files ------------------------------------------------------- echo "=== Required files ===\n"; $requiredFiles = [ 'templateDetails.xml' => $manifest, 'theme/light.custom.css' => $light, 'theme/dark.custom.css' => $dark, 'user.css' => "$cssDir/user.css", ]; foreach ($requiredFiles as $label => $file) { is_file($file) ? $ok("$label present") : $fail("missing required file: $label"); } // 2) Required CSS variables (must be defined in BOTH light and dark) ------ $required = [ // accent + Bootstrap contextual colors '--color-primary', '--primary', '--secondary', '--success', '--info', '--warning', '--danger', '--light', '--dark', // rgb triplets (utilities rely on these) '--primary-rgb', '--secondary-rgb', '--success-rgb', '--info-rgb', '--warning-rgb', '--danger-rgb', '--light-rgb', '--dark-rgb', // 5.3 emphasis + subtle tokens (theme-aware utilities) '--primary-text-emphasis', '--success-text-emphasis', '--info-text-emphasis', '--warning-text-emphasis', '--danger-text-emphasis', '--primary-bg-subtle', '--success-bg-subtle', '--info-bg-subtle', '--warning-bg-subtle', '--danger-bg-subtle', // body + links '--body-bg', '--body-color', '--body-bg-rgb', '--body-color-rgb', '--color-link', '--color-hover', ]; echo "\n=== MokoOnyx CSS variables (light + dark) ===\n"; foreach (['light' => $light, 'dark' => $dark] as $mode => $file) { if (!is_file($file)) { continue; } // already reported as missing file $css = (string) file_get_contents($file); $missing = []; foreach ($required as $var) { if (!preg_match('/' . preg_quote($var, '/') . '\s*:/', $css)) { $missing[] = $var; } } if ($missing) { $fail("$mode mode is missing " . count($missing) . ' variable(s): ' . implode(', ', $missing)); } else { $ok("$mode mode defines all " . count($required) . ' required variables'); } } // 3) Manifest sanity ------------------------------------------------------ echo "\n=== Manifest (templateDetails.xml) ===\n"; if (is_file($manifest)) { $xml = @simplexml_load_file($manifest); if ($xml === false) { $fail('templateDetails.xml is not well-formed XML'); } else { $version = isset($xml->version) ? trim((string) $xml->version) : ''; $version !== '' ? $ok("version $version") : $fail(' is missing or empty'); $server = isset($xml->updateservers->server) ? trim((string) $xml->updateservers->server) : ''; if ($server === '') { $fail(' is missing'); } elseif (strpos($server, '/raw/branch/') !== false) { $fail('update server uses a legacy raw/branch URL; use the dynamic MokoGitea feed (…///updates.xml)'); } else { $ok("update server: $server"); } isset($xml->dlid) ? $ok(' license-key field present') : $fail(' is missing'); } } // Output / exit ----------------------------------------------------------- echo "\n"; if ($gh && ($f = getenv('GITHUB_STEP_SUMMARY'))) { $md = "## MokoOnyx Theme Validation\n\n"; $md .= $errors === 0 ? "All checks passed.\n" : implode("\n", array_map(static fn ($l) => "- $l", $summary)) . "\n"; @file_put_contents($f, $md, FILE_APPEND); } if ($errors > 0) { echo "FAILED: $errors issue(s) found.\n"; exit(1); } echo "All MokoOnyx theme validation checks passed.\n"; exit(0);