Public Access
7e4d88eea5
Universal: Build & Release / Promote to RC (pull_request) Failing after 3s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 31s
Platform: mokocli CI / Gate 1: Code Quality (pull_request) Failing after 56s
pr-check.yml / Branch Policy (pull_request) Has been cancelled
Universal: PR Check / Secret Scan (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Generic: Repo Health / Access control (pull_request) Has been cancelled
Generic: Repo Health / Site Health (pull_request) Has been cancelled
Generic: Project CI / Tests (pull_request) Has been cancelled
Platform: mokocli CI / Gate 2: Unit Tests (8.1) (pull_request) Has been cancelled
Platform: mokocli CI / Gate 2: Unit Tests (8.2) (pull_request) Has been cancelled
Platform: mokocli CI / Gate 2: Unit Tests (8.3) (pull_request) Has been cancelled
Platform: mokocli CI / Gate 3: Self-Health Check (pull_request) Has been cancelled
Platform: mokocli CI / Gate 4: Governance (pull_request) Has been cancelled
Platform: mokocli CI / Gate 5: Template Integrity (pull_request) Has been cancelled
Platform: mokocli CI / CI Summary (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Validates a client theme package: required CSS variables defined in both light.custom.css and dark.custom.css, required files present, and templateDetails.xml sanity (version, dynamic update server not raw/branch, dlid). Standalone (no CliFramework dependency). Authored-by: Moko Consulting
142 lines
5.1 KiB
PHP
142 lines
5.1 KiB
PHP
#!/usr/bin/env php
|
|
<?php
|
|
|
|
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
*
|
|
* 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('<version> is missing or empty');
|
|
|
|
$server = isset($xml->updateservers->server) ? trim((string) $xml->updateservers->server) : '';
|
|
if ($server === '') {
|
|
$fail('<updateservers><server> is missing');
|
|
} elseif (strpos($server, '/raw/branch/') !== false) {
|
|
$fail('update server uses a legacy raw/branch URL; use the dynamic MokoGitea feed (…/<org>/<repo>/updates.xml)');
|
|
} else {
|
|
$ok("update server: $server");
|
|
}
|
|
|
|
isset($xml->dlid) ? $ok('<dlid> license-key field present')
|
|
: $fail('<dlid prefix="dlid=" suffix=""/> 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);
|