Декомпозиция theme.json

Файл theme.json может быть очень большим из-за чего его становится сложно поддерживать, поэтому иногда удобно разбить его на отдельные файлы поменьше.

Для того чтобы этот подход работал важно наличие файла theme.json в теме.

Файл theme.json — это флаг. Ядро вызывает wp_theme_has_theme_json() и, если файла нет, помечает тему как «classic»:

  • не включает систему Global Styles;
  • не выводит wp‑global‑styles;
  • отключает layout/spacing и другие возможности;
    Поэтому фильтры из описания ниже просто не будет применёны.

Чтобы обойти это вам нужно либо создать файл theme.json в теме либо на хуке изменить путь этого файла, указав путь до theme.json из ядра:

add_filter( 'theme_file_path', function( $path, $file ){
	if( 'theme.json' === $file ){
		$path = ABSPATH . WPINC . '/theme.json';
	}

	return $path;
} );

Однако ни JSON-спецификация, ни WordPress theme.json (или любой «SamJSON») не умеют «импортировать» другие JSON-файлы.

Разделить можно только через сборку или PHP-фильтры, которые склеят куски в один объект до того, как его увидит WordPress.

WordPress ≥ 6.1 даёт четыре фильтра, самый удобный — wp_theme_json_data_theme.

Пример структуры файлов:

src/
  ├─ tokens/
  │   ├─ colors.json
  │   ├─ typography.json
  │   └─ spacing.json
  └─ settings.json

Пример склейки через PHP фильтр:

add_filter( 'wp_theme_json_data_theme', function( $theme_json ) {

	$parts = [
		json_decode( file_get_contents( get_theme_file_path( 'tokens/colors.json' ) ), true ),
		json_decode( file_get_contents( get_theme_file_path( 'tokens/spacing.json' ) ), true ),
	];

	foreach ( $parts as $fragment ) {
		$theme_json->update_with( $fragment );
	}

	return $theme_json;
} );

--