Skip to content

Commit c191b0b

Browse files
committed
impoved yaml linter to be more use built-in grav for more detail
Signed-off-by: Andy Miller <rhuk@mac.com>
1 parent dfdd378 commit c191b0b

File tree

2 files changed

+78
-18
lines changed

2 files changed

+78
-18
lines changed

system/src/Grav/Common/Helpers/YamlLinter.php

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use RecursiveDirectoryIterator;
1616
use RecursiveIteratorIterator;
1717
use RegexIterator;
18+
use RocketTheme\Toolbox\Compat\Yaml\Yaml as CompatYaml;
1819
use RocketTheme\Toolbox\File\MarkdownFile;
1920
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
2021
use Symfony\Component\Yaml\Yaml;
@@ -30,44 +31,78 @@ class YamlLinter
3031
* @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
3132
* @return array
3233
*/
33-
public static function lint(?string $folder = null, ?callable $callback = null)
34+
public static function lint(?string $folder = null, ?callable $callback = null, bool $strict = false)
3435
{
3536
if (null !== $folder) {
3637
$folder = $folder ?: GRAV_ROOT;
3738

38-
return static::recurseFolder($folder, '(md|yaml)', $callback);
39+
return static::recurseFolder($folder, '(md|yaml)', $callback, $strict);
3940
}
4041

4142
return array_merge(
42-
static::lintConfig($callback),
43-
static::lintPages($callback),
44-
static::lintBlueprints($callback)
43+
static::lintConfig($callback, $strict),
44+
static::lintPages($callback, $strict),
45+
static::lintBlueprints($callback, $strict),
46+
static::lintEnvironments($callback, $strict)
4547
);
4648
}
4749

4850
/**
4951
* @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
5052
* @return array
5153
*/
52-
public static function lintPages(?callable $callback = null)
54+
public static function lintPages(?callable $callback = null, bool $strict = false)
5355
{
54-
return static::recurseFolder('page://', '(md|yaml)', $callback);
56+
return static::recurseFolder('page://', '(md|yaml)', $callback, $strict);
5557
}
5658

5759
/**
5860
* @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
61+
* @param bool $strict Use the stricter Compat YAML parser (matches runtime behavior)
5962
* @return array
6063
*/
61-
public static function lintConfig(?callable $callback = null)
64+
public static function lintConfig(?callable $callback = null, bool $strict = false)
6265
{
63-
return static::recurseFolder('config://', '(md|yaml)', $callback);
66+
return static::recurseFolder('config://', '(md|yaml)', $callback, $strict);
6467
}
6568

6669
/**
6770
* @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
71+
* @param bool $strict Use the stricter Compat YAML parser (matches runtime behavior)
6872
* @return array
6973
*/
70-
public static function lintBlueprints(?callable $callback = null)
74+
public static function lintEnvironments(?callable $callback = null, bool $strict = false)
75+
{
76+
$lint_errors = [];
77+
$user_path = GRAV_ROOT . '/' . GRAV_USER_PATH;
78+
79+
// Scan Grav 1.6 style: user/<hostname>/config/
80+
foreach (glob($user_path . '/*/config', GLOB_ONLYDIR) as $envConfigDir) {
81+
$envName = basename(dirname($envConfigDir));
82+
// Skip known non-environment directories
83+
if (in_array($envName, ['config', 'plugins', 'themes', 'pages', 'accounts', 'data', 'assets'])) {
84+
continue;
85+
}
86+
$lint_errors = array_merge($lint_errors, static::recurseFolder($envConfigDir, '(md|yaml)', $callback, $strict));
87+
}
88+
89+
// Scan Grav 1.7+ style: user/env/<hostname>/config/
90+
$envPath = $user_path . '/env';
91+
if (is_dir($envPath)) {
92+
foreach (glob($envPath . '/*/config', GLOB_ONLYDIR) as $envConfigDir) {
93+
$lint_errors = array_merge($lint_errors, static::recurseFolder($envConfigDir, '(md|yaml)', $callback, $strict));
94+
}
95+
}
96+
97+
return $lint_errors;
98+
}
99+
100+
/**
101+
* @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
102+
* @param bool $strict Use the stricter Compat YAML parser (matches runtime behavior)
103+
* @return array
104+
*/
105+
public static function lintBlueprints(?callable $callback = null, bool $strict = false)
71106
{
72107
/** @var UniformResourceLocator $locator */
73108
$locator = Grav::instance()['locator'];
@@ -76,7 +111,7 @@ public static function lintBlueprints(?callable $callback = null)
76111
$theme_path = 'themes://' . $current_theme . '/blueprints';
77112

78113
$locator->addPath('blueprints', '', [$theme_path]);
79-
return static::recurseFolder('blueprints://', '(md|yaml)', $callback);
114+
return static::recurseFolder('blueprints://', '(md|yaml)', $callback, $strict);
80115
}
81116

82117
/**
@@ -85,7 +120,7 @@ public static function lintBlueprints(?callable $callback = null)
85120
* @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
86121
* @return array
87122
*/
88-
public static function recurseFolder($path, $extensions = '(md|yaml)', ?callable $callback = null)
123+
public static function recurseFolder($path, $extensions = '(md|yaml)', ?callable $callback = null, bool $strict = false)
89124
{
90125
$lint_errors = [];
91126

@@ -104,7 +139,12 @@ public static function recurseFolder($path, $extensions = '(md|yaml)', ?callable
104139
foreach ($iterator as $filepath => $file) {
105140
$relativePath = str_replace(GRAV_ROOT, '', $filepath);
106141
try {
107-
Yaml::parse(static::extractYaml($filepath));
142+
$yaml = static::extractYaml($filepath);
143+
if ($strict) {
144+
CompatYaml::parse($yaml);
145+
} else {
146+
Yaml::parse($yaml);
147+
}
108148
if ($callback) {
109149
$callback($relativePath, true, null);
110150
}

system/src/Grav/Console/Cli/YamlLinterCommand.php

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ protected function configure(): void
3939
InputOption::VALUE_OPTIONAL,
4040
'Go through specific folder'
4141
)
42+
->addOption(
43+
'strict',
44+
's',
45+
InputOption::VALUE_NONE,
46+
'Use the stricter Compat YAML parser that matches runtime behavior'
47+
)
4248
->setDescription('Checks various files for YAML errors')
4349
->setHelp('Checks various files for YAML errors');
4450
}
@@ -54,6 +60,7 @@ protected function serve(): int
5460
$io->title('Yaml Linter');
5561

5662
$verbose = $io->isVerbose();
63+
$strict = (bool) $input->getOption('strict');
5764
$checked = 0;
5865
$callback = $verbose ? function (string $file, bool $success, ?string $error) use ($io, &$checked) {
5966
$checked++;
@@ -64,18 +71,22 @@ protected function serve(): int
6471
}
6572
} : null;
6673

74+
if ($strict) {
75+
$io->note('Using strict Compat YAML parser (matches runtime behavior)');
76+
}
77+
6778
$error = 0;
6879
if ($input->getOption('all')) {
6980
$io->section('All');
70-
$errors = YamlLinter::lint('', $callback);
81+
$errors = YamlLinter::lint('', $callback, $strict);
7182

7283
$this->displayResult($errors, $io, 'No YAML Linting issues found', $verbose, $checked);
7384
if (!empty($errors)) {
7485
$error = 1;
7586
}
7687
} elseif ($folder = $input->getOption('folder')) {
7788
$io->section($folder);
78-
$errors = YamlLinter::lint($folder, $callback);
89+
$errors = YamlLinter::lint($folder, $callback, $strict);
7990

8091
$this->displayResult($errors, $io, 'No YAML Linting issues found', $verbose, $checked);
8192
if (!empty($errors)) {
@@ -84,7 +95,7 @@ protected function serve(): int
8495
} else {
8596
$io->section('User Configuration');
8697
$checked = 0;
87-
$errors = YamlLinter::lintConfig($callback);
98+
$errors = YamlLinter::lintConfig($callback, $strict);
8899

89100
$this->displayResult($errors, $io, 'No YAML Linting issues with configuration', $verbose, $checked);
90101
if (!empty($errors)) {
@@ -93,7 +104,7 @@ protected function serve(): int
93104

94105
$io->section('Pages Frontmatter');
95106
$checked = 0;
96-
$errors = YamlLinter::lintPages($callback);
107+
$errors = YamlLinter::lintPages($callback, $strict);
97108

98109
$this->displayResult($errors, $io, 'No YAML Linting issues with pages', $verbose, $checked);
99110
if (!empty($errors)) {
@@ -102,12 +113,21 @@ protected function serve(): int
102113

103114
$io->section('Page Blueprints');
104115
$checked = 0;
105-
$errors = YamlLinter::lintBlueprints($callback);
116+
$errors = YamlLinter::lintBlueprints($callback, $strict);
106117

107118
$this->displayResult($errors, $io, 'No YAML Linting issues with blueprints', $verbose, $checked);
108119
if (!empty($errors)) {
109120
$error = 1;
110121
}
122+
123+
$io->section('Environment Configuration');
124+
$checked = 0;
125+
$errors = YamlLinter::lintEnvironments($callback, $strict);
126+
127+
$this->displayResult($errors, $io, 'No YAML Linting issues with environment configs', $verbose, $checked);
128+
if (!empty($errors)) {
129+
$error = 1;
130+
}
111131
}
112132

113133
return $error;

0 commit comments

Comments
 (0)