From 42129e17fe1dd7466c640a4a9805c33076d2e2df Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Tue, 10 Nov 2026 13:44:28 +0000 Subject: [PATCH 1/3] Use Statamic's own fast YAML parser where it has one Statamic is getting the same parser in core. On versions that have it, Flatpack parses with Statamic's and leaves its own copy unused; older versions keep using Flatpack's. --- CHANGELOG.md | 2 ++ src/Flatpack.php | 15 +++++++++++++++ src/ServiceProvider.php | 5 ++++- src/Yaml/FastParser.php | 3 +++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0458b91..046c591 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - **A faster YAML parser that gives up on far fewer files.** An unusual key or value (a double-quoted string with escapes, a key that starts with a digit or has a dash or quotes, a date) is now read by Symfony's inline parser on its own, where before the whole file went back to Symfony's full parser. Tabs inside literal blocks no longer send the file back either. On a large site, files that needed the full parser went from 38% to 2%, and parsing all of its content from 13.9 s to 1.6 s. +- **Statamic's own fast YAML parser is used where it has one.** Flatpack's copy is only used on Statamic versions without it. + ### Fixed - A sequence written inside a sequence item (`- - one`) was read as the text `- one`. diff --git a/src/Flatpack.php b/src/Flatpack.php index a3fad10..92abd2d 100644 --- a/src/Flatpack.php +++ b/src/Flatpack.php @@ -21,6 +21,8 @@ public static function configure(string $path, int $lazyLimit = 2048): void self::$bodies = null; } + private static ?bool $statamicHasFastParser = null; + public static function bodies(): BodyStore { return self::$bodies ??= new BodyStore(self::$path.'/bodies'); @@ -32,9 +34,22 @@ public static function parseFrontMatter(string $contents): array $fm = str_starts_with($contents, '---') ? preg_split("/\n---/", $contents, 2, PREG_SPLIT_NO_EMPTY)[0] : $contents; $fm = preg_replace('/^---\n?/', '', $fm); + if (self::statamicHasFastParser()) { + return (new \Statamic\Yaml\FastParser)->parse($fm) ?? []; + } + return Yaml\FastParser::parse($fm) ?? SymfonyYaml::parse($fm) ?? []; } + /** + * Whether this Statamic version has its own fast YAML parser, which Flatpack then uses + * instead of the copy it ships for older versions. + */ + public static function statamicHasFastParser(): bool + { + return self::$statamicHasFastParser ??= method_exists(\Statamic\Yaml\FastParser::class, 'parse'); + } + /** True when $v holds only scalars, nulls and arrays of them (safe for var_export + OPcache). */ public static function isPlain($v): bool { diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index c178d6c..9ffb5c3 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -71,7 +71,10 @@ public function register(): void $this->app->booting(function ($app) { $app->bind(\Statamic\Contracts\Entries\Entry::class, FlatpackEntry::class); $app->bind(\Statamic\Stache\Traverser::class, Stache\FastTraverser::class); - $app->singleton(\Statamic\Yaml\Yaml::class, fn () => new LeanYaml(new Yaml\SymfonyFast)); + // Statamic parses with its own fast parser where it has one; older versions get Flatpack's. + $app->singleton(\Statamic\Yaml\Yaml::class, fn () => new LeanYaml( + Flatpack::statamicHasFastParser() ? new \Symfony\Component\Yaml\Yaml : new Yaml\SymfonyFast + )); Facade::clearResolvedInstance(\Statamic\Yaml\Yaml::class); }); } diff --git a/src/Yaml/FastParser.php b/src/Yaml/FastParser.php index 93b9af7..0d011f2 100644 --- a/src/Yaml/FastParser.php +++ b/src/Yaml/FastParser.php @@ -17,6 +17,9 @@ * collections or plain scalars, invalid YAML) makes it return null, and the caller parses the * whole document with Symfony. Errors are therefore always Symfony's. * + * Statamic has had the same parser of its own since [version to fill in at release]. Flatpack uses + * Statamic's where it exists and this one on older versions (see Flatpack::statamicHasFastParser()). + * * tests/yaml/fuzz.php checks it against Symfony's parser. */ final class FastParser From 77cfcff8854524874e8f909c4013166442dc4b07 Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Tue, 10 Nov 2026 14:26:29 +0000 Subject: [PATCH 2/3] Move the changelog entry under Unreleased now that 1.1.0 is out --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5080dc..dacd6ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,17 @@ # Changelog +## Unreleased + +### Changed + +- **Statamic's own fast YAML parser is used where it has one.** Flatpack's copy is only used on Statamic versions without it. + ## 1.1.0 (2026-11-10) ### Changed - **A faster YAML parser that gives up on far fewer files.** An unusual key or value (a double-quoted string with escapes, a key that starts with a digit or has a dash or quotes, a date) is now read by Symfony's inline parser on its own, where before the whole file went back to Symfony's full parser. Tabs inside literal blocks no longer send the file back either. On a large site, files that needed the full parser went from 38% to 2%, and parsing all of its content from 13.9 s to 1.6 s. -- **Statamic's own fast YAML parser is used where it has one.** Flatpack's copy is only used on Statamic versions without it. - ### Fixed - A sequence written inside a sequence item (`- - one`) was read as the text `- one`. From c954c8915acb1a04e8a3cad16b4068fccbbe4d80 Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Tue, 10 Nov 2026 17:12:33 +0000 Subject: [PATCH 3/3] Say where Statamic's own parser comes from --- src/Yaml/FastParser.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Yaml/FastParser.php b/src/Yaml/FastParser.php index 33fa6b3..bed92ab 100644 --- a/src/Yaml/FastParser.php +++ b/src/Yaml/FastParser.php @@ -17,8 +17,9 @@ * collections or plain scalars, invalid YAML) makes it return null, and the caller parses the * whole document with Symfony. Errors are therefore always Symfony's. * - * Statamic has had the same parser of its own since [version to fill in at release]. Flatpack uses - * Statamic's where it exists and this one on older versions (see Flatpack::statamicHasFastParser()). + * Statamic has the same parser of its own from the release after 6.40 (statamic/cms#15838). + * Flatpack uses Statamic's where it exists and this one on older versions, Statamic 5 included + * (see Flatpack::statamicHasFastParser()). * * tests/yaml/fuzz.php checks it against Symfony's parser. */