baxtian / merak
Class to be inherite to add merak requirements.
Requires
- php: >=8.1
- baxtian/php-singleton: *
Requires (Dev)
- baxtian/timber-stubs: ^1.22
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- 0.5.45
- 0.5.44
- 0.5.43
- 0.5.42
- 0.5.41
- 0.5.40
- 0.5.39
- 0.5.38
- 0.5.37
- 0.5.36
- 0.5.35
- 0.5.34
- 0.5.33
- 0.5.32
- 0.5.31
- 0.5.30
- 0.5.29
- 0.5.28
- 0.5.27
- 0.5.26
- 0.5.25
- 0.5.24
- 0.5.23
- 0.5.22
- 0.5.21
- 0.5.20
- 0.5.19
- 0.5.18
- 0.5.17
- 0.5.16
- 0.5.15
- 0.5.14
- 0.5.13
- 0.5.12
- 0.5.11
- 0.5.10
- 0.5.9
- 0.5.8
- 0.5.7
- 0.5.6
- 0.5.5
- 0.5.4
- 0.5.3
- 0.5.2
- 0.5.1
- 0.4.19
- 0.4.18
- 0.4.17
- 0.4.16
- 0.4.15
- 0.4.14
- 0.4.13
- 0.4.12
- 0.4.11
- 0.4.10
- 0.4.9
- 0.4.8
- 0.4.7
- 0.4.6
- 0.4.5
- 0.4.4
- 0.4.3
- 0.4.2
- 0.4.1
- 0.4
- 0.3
- 0.2.10
- 0.2.9
- 0.2.8
- 0.2.7
- 0.2.6
- 0.2.5
- 0.2.4
- 0.2.3
- 0.2.2
- 0.2.1
- 0.2.0
- 0.1.0
This package is auto-updated.
Last update: 2026-11-11 02:07:06 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/scriptsand the loaders/plugins required byconfig/webpack.config.js, installed in the consuming project'snode_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::.
| Constant | Purpose |
|---|---|
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. |
DOMAIN | Text domain of the project. |
PREFIX | Project prefix. Used for asset handles and for the image resize cache directory. |
VERSION | Project version. Used as asset version in production. |
CONTEXT | Values 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
| Method | Returns |
|---|---|
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}.cssfirst, thenbuild/{$name}.js, and registers whichever exists. $typeisfrontend,adminorlogin(anything else falls back tofrontend). When$enqueueis true, the asset is enqueued automatically on that screen.- If
build/{$name}.asset.phpexists, itsversionanddependenciesare 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 classVERSIONis 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().
| Name | Kind | Purpose |
|---|---|---|
html_classes(...) | function | Builds a class string from strings and {class: condition} maps. |
pagenavi(args) | function | Pagination through WP-PageNavi, if installed. |
breadcrumb(args) | function | Array of {title, link} for the current page. Filterable with merak/breadcrumbs. |
reusable_block(id) | function | Renders a reusable block by ID, slug or title. |
date_i18n(format) | filter | Localized date with the site's GMT offset. |
format_content | filter | Applies the_content and nl2br. |
adjust(width, height) | filter | Resized image URL (Fly Dynamic Image Resizer if available, Timber otherwise). |
srcset_style(id, srcset, lazyload) | filter | Background-image srcset styles for an image. |
related_posts(args) | filter | Related posts (Custom Related Posts Premium if available, same categories otherwise). |
skip_tabs | filter | Removes tabs and collapses whitespace. |
Theme-only features
get_og($default_image = null): Open Graph data and the<meta>tags for the current page, filterable withget_og.timber_blockfilter: lets a block render through a theme template,apply_filters('timber_block', $html, $tpl, $attributes).- Adds
postIdto the context ofcore/post-*blocks on singular pages. - Allows editing
.twigfiles 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/:
| Source | Output 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}/*.scss | libs/{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.
Libs built in another repo
An app compiled elsewhere (Vue, React…) keeps its lib.json in the project, like any lib, but its entries point to the app's build with source instead of to files in assets/libs/. The lib.json is committed; the bundle is not:
{
"my-app/index.js": {
"type": "script",
"handle": "my-app",
"dependencies": [],
"source": "env:MY_APP_DIST/assets/index.js",
"app_version": "1.2.0"
},
"my-app/index.css": {
"type": "style",
"handle": "my-app-style",
"dependencies": [],
"source": "env:MY_APP_DIST/assets/index.css",
"app_version": "1.2.0"
}
}
This file lives in assets/libs/my-app/lib.json.
| Field | Meaning |
|---|---|
source | Path of the build file, or a list of candidate paths (the first that exists wins). env:NAME/path takes the environment variable NAME or, if missing, NAME from .env.libs in the project root (per machine, not committed). Relative paths start at the project root. The file name must match the one in the key. |
* in the name | An app whose entry has a hash in its name (index-HASH.js) uses a * in the file name, the same in source and in the key ("my-app/index-*.js"). The build resolves it to the one file that matches (an error if several or none do) and registers the entry under its real name. Any entry already in build/libs/lib.json with the same handle is replaced. |
app_version | Expected app version (optional). It is compared with the version of the build (version.json, see below) or, when the build does not declare one, with the nearest package.json above the file. A production build fails on a mismatch; development only warns. |
If the copied folder has a version.json ({"version":"x.y.z"}), written by the app's own build from its package.json, that is the version of the build: a production build also fails when it differs from the version in package.json (the app was built with another version), and the date of package.json is no longer compared. All the entries of a lib must come from the same folder. The build copies that whole folder to build/libs/{lib}/, untouched, and adds each entry to build/libs/lib.json with a version (content hash, calculated at build time: do not commit it). If a lib cannot be resolved, a production build fails before compiling and a development build warns and continues. Entries without source are not affected.
Files in config/
| File | Convention |
|---|---|
webpack.config.js | Main configuration. |
webpack.{name}.config.js | Build scripts loaded by the main configuration (e.g. webpack.theme-json.config.js). |
webpack.{package}.fix.js | Vendored fork of an npm package with an upstream bug (e.g. webpack.node-sass-variables.fix.js). |
webpack.assets.js | Writes 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.