Search by

baxtian / merak

baxtian

Class to be inherite to add merak requirements.

Package info

bitbucket.org/baxtian/merak

pkg:composer/baxtian/merak

Statistics

Installs: 1 204

Dependents: 3

Suggesters: 0

0.5.40 2026-10-02 21:57 UTC

README

Base classes and shared build configuration for Merak-based WordPress plugins and themes.

A plugin or theme extends MerakPlugin or MerakTheme from its Init class and inherits the behavior every Merak project shares: path and URL resolution, translations, asset registration and enqueueing, Timber/Twig rendering with a set of common Twig functions and filters, and the webpack configuration used to compile assets/ into build/.

Mantainers

Juan Sebastián Echeverry baxtian.echeverry@gmail.com

Requirements

  • PHP >= 8.1
  • Timber (provided by the consuming project, not required by this package)
  • baxtian/php-singleton
  • For the build: @wordpress/scripts and the loaders/plugins required by config/webpack.config.js, installed in the consuming project's node_modules

Usage

Plugin

<?php
namespace MyPlugin;

use Baxtian\MerakPlugin;

class Init extends MerakPlugin
{
	use \Baxtian\SingletonTrait;

	public const FILE    = __FILE__;
	public const DIR     = __DIR__;
	public const DOMAIN  = MYP_D;
	public const PREFIX  = MYP_P;
	public const VERSION = MYP_V;
	public const CONTEXT = [
		'MYP_V' => MYP_V,
		'MYP_D' => MYP_D,
		'MYP_P' => MYP_P,
	];

	protected function __construct()
	{
		// Own hooks go here

		parent::__construct();
	}

	public function register_assets()
	{
		// Register libraries declared in build/libs/lib.json
		parent::register_assets();

		$this->register_asset(static::PREFIX . '_admin', 'admin_style', 'admin');
	}
}

Theme

Same pattern, extending MerakTheme (which extends Timber\Site). The theme is responsible for initializing Timber: MerakTheme calls Timber::init() unless TIMBER_LOADED is already defined.

<?php
namespace MyTheme;

use Baxtian\MerakTheme;

class Init extends MerakTheme
{
	use \Baxtian\SingletonTrait;

	public const FILE    = __FILE__;
	public const DIR     = __DIR__;
	// DOMAIN, PREFIX, VERSION and CONTEXT as in the plugin example

	public function __construct()
	{
		parent::__construct();
	}

	// Required: MerakTheme hooks it to after_setup_theme but does not define it
	public function setup()
	{
		add_theme_support('post-thumbnails');
	}
}

Class constants

Every subclass must redeclare these constants; the library reads them through static::.

ConstantPurpose
FILE__FILE__ of the Init class. Used to resolve the plugin URL and languages directory.
DIR__DIR__ of the Init class (usually src/). The project root is its parent.
DOMAINText domain of the project.
PREFIXProject prefix. Used for asset handles and for the image resize cache directory.
VERSIONProject version. Used as asset version in production.
CONTEXTValues added to the Timber context. Convention: three entries in the order version, domain, prefix. The value of the third entry (the prefix) becomes a context key holding ['link' => url_path()].

They are also available as properties: $this->file, $this->dir, $this->domain, $this->prefix, $this->version, $this->context, $this->type (plugin or theme).

Overriding register_assets()

register_assets() is hooked to wp_loaded but declared protected in the library. The Init class must override it as public and call parent::register_assets(), as in the examples above.

API

Paths

MethodReturns
url_path()URL of the plugin/theme root.
dir_path()Filesystem path of the plugin/theme root, with trailing separator.
languages_dir()Path of the languages/ directory.

Assets

$this->register_asset($handle, $name, $type, $dependencies = [], $enqueue = true);
  • Looks for build/{$name}.css first, then build/{$name}.js, and registers whichever exists.
  • $type is frontend, admin or login (anything else falls back to frontend). When $enqueue is true, the asset is enqueued automatically on that screen.
  • If build/{$name}.asset.php exists, its version and dependencies are used (dependencies are merged with $dependencies).
  • In development, build/assets.version.php (written by the webpack build) provides the version, so every build busts the browser cache. In production the class VERSION is used.

register_assets() registers, without enqueueing, every library declared in build/libs/lib.json:

{
	"owl/owl.carousel.js": { "type": "script", "handle": "owl", "dependencies": ["jquery"] },
	"owl/owl.carousel.css": { "type": "style", "handle": "owl", "dependencies": [] },
	"https://example.com/lib.js": { "type": "script", "handle": "remote-lib", "dependencies": [] }
}

Keys are paths relative to build/libs/ or external URLs. A .scss key is registered as its compiled .css.

Rendering

$this->render($tpl, $args, $echo = true);
$this->render_string($tpl, $args, $echo = true);

render() renders a Twig file from the project's templates/ or views/ directory; render_string() renders a Twig string. Both merge Timber::context(), the class CONTEXT and $args. With $echo = false they return the rendered string.

Timber context

add_to_context() (hooked to timber/context) adds the CONTEXT values and {prefix}.link. In themes it also sets site to the Init instance. Override it and call parent::add_to_context($context) to add project values.

Twig functions and filters

Registered once for all projects by MerakTimber through add_to_twig().

NameKindPurpose
html_classes(...)functionBuilds a class string from strings and {class: condition} maps.
pagenavi(args)functionPagination through WP-PageNavi, if installed.
breadcrumb(args)functionArray of {title, link} for the current page. Filterable with merak/breadcrumbs.
reusable_block(id)functionRenders a reusable block by ID, slug or title.
date_i18n(format)filterLocalized date with the site's GMT offset.
format_contentfilterApplies the_content and nl2br.
adjust(width, height)filterResized image URL (Fly Dynamic Image Resizer if available, Timber otherwise).
srcset_style(id, srcset, lazyload)filterBackground-image srcset styles for an image.
related_posts(args)filterRelated posts (Custom Related Posts Premium if available, same categories otherwise).
skip_tabsfilterRemoves tabs and collapses whitespace.

Theme-only features

  • get_og($default_image = null): Open Graph data and the <meta> tags for the current page, filterable with get_og.
  • timber_block filter: lets a block render through a theme template, apply_filters('timber_block', $html, $tpl, $attributes).
  • Adds postId to the context of core/post-* blocks on singular pages.
  • Allows editing .twig files from the theme editor (plugins get the same in the plugin editor).
  • Integrates Fly Dynamic Image Resizer when fly_add_image_size() exists.

Build

The consuming project's webpack.config.js extends the shared configuration:

const defaultConfig = require('./vendor/baxtian/merak/config/webpack.config.js');

module.exports = {
	...defaultConfig
};

The config resolves @wordpress/scripts from the project's node_modules, four levels above vendor/baxtian/merak/config/.

Entries

Unless WP_ENTRY is already defined, entries are discovered from assets/:

SourceOutput in build/
assets/css/{name}.scss{name}_style.css (style.scss → style.css)
assets/scripts/{name}.js{name}_script.js (script.js → script.js)
assets/blocks/{name}.(js\|scss)gtmbrg/{name}.*
assets/libs/{lib}/*.scsslibs/{lib}/*.css
assets/libs/** (non-scss)copied to libs/
assets/img/**copied to media/images/

Images and fonts referenced from styles go to build/media/images/ and build/media/fonts/.

Theme colors in SVGs

In SVG files copied to build/, every @name is replaced by the color of the Sass variable $name. Variables are read from assets/css/theme/_theme-json.scss and assets/css/theme/_colors.scss (the latter takes precedence). Unknown names become #000000; @keyframes is preserved.

theme.json

When the project has a theme.json with a color palette or font families, the build writes assets/css/theme/_theme-json.scss with $color-{slug} and $font-{slug} variables, so Sass and SVG colors follow the same values as the block editor. Colors keep their literal value (needed by Sass functions and SVG replacement); fonts point to the WordPress custom property var(--wp--preset--font-family--{slug}), so a font change in theme.json applies without recompiling. In watch mode the file is regenerated when theme.json changes. Plugins without theme.json are unaffected.

Files in config/

FileConvention
webpack.config.jsMain configuration.
webpack.{name}.config.jsBuild scripts loaded by the main configuration (e.g. webpack.theme-json.config.js).
webpack.{package}.fix.jsVendored fork of an npm package with an upstream bug (e.g. webpack.node-sass-variables.fix.js).
webpack.assets.jsWrites build/assets.version.php on every development build.

Consuming projects must exclude these files from their distribution zip (archive.exclude in their composer.json).

Changelog

See CHANGELOG.md.