This module provides Emulsify Twig extensions, theme-defined Twig namespaces, child theme generation Drush commands, and deployment commands for Emulsify Drupal favicon packages.
This module targets Drupal 11.3+, includes Drupal 12 forward compatibility, and requires PHP 8.4+. Drupal core development branch coverage is experimental until Drupal 12 beta or stable releases are available.
The bundled Drush commands follow the Drush 13+ autowiring pattern, and the codebase now uses PHP 8.4-only syntax where it improves readability.
emulsify_tools^2.0is intended to pair with Emulsify Drupal^7.0.- The Twig helpers and child theme generator remain broadly useful on their own, but the favicon migration and admin-theme favicon features expect the Emulsify 7.x companion theme APIs to be present.
- In short: child theme generation remains available for Emulsify Drupal 6.x projects, while generated favicon deployment and repair are the Emulsify Drupal 7.x companion workflows in this 2.x line.
Emulsify Tools 2.x still includes the supported Drush workflow for generating Emulsify Drupal 6.x child themes. Use either command form:
drush emulsify_tools:bake [theme_name]
drush emulsify [theme_name]
The commands are equivalent. The generated child theme uses emulsify as its
runtime parent theme and should be created under the Drupal custom theme path
expected by the command, such as web/themes/custom/my_theme in a
Composer-based Drupal project.
Drupal core Starterkit-based generation is being prepared for the Emulsify Drupal 7.x release line. For Emulsify Drupal 6.x child theme projects, use Emulsify Tools for child theme generation.
Generated favicon deployment for Emulsify Drupal 7.x companion themes:
drush emulsify_tools:favicon-generate [theme_name]
drush emulsify_tools:favicon-status [theme_name]
drush emulsify_tools:favicon-reset [theme_name]
Child theme source repair:
drush emulsify_tools:repair-favicon-config
drush emulsify_tools:repair-favicon-config [theme_machine_name]
Emulsify Drupal 7.x owns favicon theme settings, config defaults and schema,
admin preview UI, frontend head tag attachment, portable SVG source storage, and
the generated asset references stored in <theme>.settings.
Emulsify Tools 2.x owns Drush-facing deployment operations for that workflow. Configure the favicon in the Emulsify Drupal theme settings form, export config, and run the generate command after config import or deploy so environment-local package files exist before traffic reaches the site.
Emulsify Drupal page requests do not generate missing favicon package files.
After config import, emulsify_tools:favicon-generate is the supported
deployment path for recreating packages from saved portable SVG config.
The favicon commands delegate generation, status, and reset behavior to the Emulsify Drupal favicon manager instead of duplicating package logic in this module.
The optional admin-theme favicon toggle in this module only reuses an already generated Emulsify package on admin routes. It does not replace the Emulsify Drupal theme settings UI or frontend head-tag attachment.
- Configure and save favicon settings in the Emulsify Drupal theme settings
form for
emulsifyor an Emulsify child theme. - Export and deploy/import configuration as usual.
- Run
drush emulsify_tools:favicon-generate my_themeafter config import so the environment-local generated package exists before page requests need it. - Run
drush emulsify_tools:favicon-status my_themein deployment diagnostics to confirm dependencies, package state, and portable SVG source state.
drush emulsify_tools:favicon-generate my_theme
drush emulsify_tools:favicon-status my_theme
drush emulsify_tools:favicon-reset my_themeOmit my_theme to target the configured default frontend theme. The target must
be emulsify or an Emulsify child theme.
emulsify_tools:favicon-generate generates or refreshes the package from the
saved Emulsify Drupal theme settings. Use it in deployment hooks and
post-config-import automation.
emulsify_tools:favicon-status reports whether generation is enabled, whether
the package exists, whether GD and Imagick are available, and whether the
portable SVG source is available for regeneration.
emulsify_tools:favicon-reset removes generated package metadata and assets and
restores the default theme favicon behavior. Configure and save the Emulsify
Drupal theme settings form again, or rerun emulsify_tools:favicon-generate
after config import, to recreate the package.
Emulsify themes can register Symfony-style Twig namespaces in their .info.yml
file using the same components.namespaces structure supported by the
Components module:
components:
namespaces:
atoms: components/01-atoms
molecules:
- components/02-molecules
- src/components/molecules
vendor_components: /../vendor/acme/componentsRelative paths are resolved from the theme directory. Paths starting with /
are resolved from the Drupal app root. Namespaces are searched in this order:
- Active theme
- Active theme base themes
- Default frontend theme, if the active theme is different
Templates can then be referenced with standard Twig namespace syntax such as
@atoms/button/button.twig. Nested component templates are also registered
by basename, so @atoms/button.twig will resolve when the file is uniquely
named within the namespace.
The bem() Twig function builds BEM class names and returns them in a form that can be printed into Drupal template attributes.
<h1 {{ bem('title') }}>
This creates:
<h1 class="title">
<h1 {{ bem('title', ['small', 'red']) }}>
This creates:
<h1 class="title title--small title--red">
<h1 {{ bem('title', ['small', 'red'], 'card') }}>
This creates:
<h1 class="card__title card__title--small card__title--red">
<h1 {{ bem('title', '', 'card') }}>
This creates:
<h1 class="card__title">
<h1 {{ bem('title', ['small', 'red'], 'card', ['js-click', 'something-else']) }}>
This creates:
<h1 class="card__title card__title--small card__title--red js-click something-else">
<h1 {{ bem('title', '', '', ['js-click']) }}>
This creates:
<h1 class="title js-click">
The add_attributes() Twig function merges additional attributes with Drupal's template-level attributes and prevents those attributes from trickling into child includes.
{% set additional_attributes = {
"class": ["foo", "bar"],
"baz": ["foobar", "goobar"],
"foobaz": "goobaz",
} %}
<div {{ add_attributes(additional_attributes) }}></div>
Can also be used with the BEM Function:
{% set additional_attributes = {
"class": bem("foo", ["bar", "baz"], "foobar"),
} %}
<div {{ add_attributes(additional_attributes) }}></div>
This adds the ability to do a switch/case function from within Twig templates. To use:
{% switch content.field_name.0 %}
{% case "text" %}
<p>This appears if the field name value is set to "text"</p>
{% case "image" %}
<p>This appears if the field name value is set to "image"</p>
{% default %}
<p>The field text did not match any case.</p>
{% endswitch %}Note that the switch, endswitch, and case tags are required and the default is optional.
Upgrading from Emulsify 6.x to 7.x introduces a new generated favicon workflow. Instead of relying only on legacy theme-level favicon settings, Emulsify 7.x stores a portable SVG source and generated package metadata in theme settings so favicon packages can be regenerated consistently across environments.
- Active theme settings gain new favicon keys such as
favicon_source_svg,favicon_source_filename, platform-specific color and padding settings, and generated package metadata fields likefavicon_package_hash,favicon_package_path, andfavicon_package_generated_at. - Installed Emulsify-based themes can be migrated in place by running Drupal
database updates. This module provides a post update that backfills missing
favicon keys in active
<theme>.settingsconfig and, when possible, stores a sanitized portable SVG source from the existing managed favicon file. - Older generated child themes may still be missing the source files that define those settings for fresh installs and future config exports.
Run drush updatedb after upgrading the module so the installed theme settings
receive the new defaults before exporting configuration.
After exporting or importing those settings, use
drush emulsify_tools:favicon-generate [theme_name] to recreate generated
package files in each environment. Use
drush emulsify_tools:favicon-status [theme_name] for deployment diagnostics
and drush emulsify_tools:favicon-reset [theme_name] when you intentionally
want to remove generated package state.
Run the repair command in the Drupal site root to update older Emulsify-based child theme codebases:
drush emulsify_tools:repair-favicon-config
To target a single child theme:
drush emulsify_tools:repair-favicon-config my_child_theme
The command scans Emulsify-based child themes in the current codebase and backfills missing favicon entries in:
config/install/<theme>.settings.ymlconfig/schema/<theme>.schema.yml
Existing values are preserved. Only missing or NULL favicon keys and schema
definitions are filled in. Review and commit those child theme source-file
changes after running the command.
- Run
composer installto install the PHPUnit and Drupal development stack. - Run
npm installto install the lightweight release and commit tooling.
npm run lintcomposer test:unitbash .github/scripts/favicon-command-smoke.sh /path/to/drupal-site [theme_name]for a prepared integration fixture with Emulsify Drupal 7.x, Emulsify Tools 2.x, and favicon source config.
To validate the Emulsify Drupal 6.x child theme generation workflow against this checkout, run:
.github/scripts/generation-smoke.sh
The script creates a disposable Drupal fixture site, installs Emulsify Drupal
^6, installs this 2.x checkout through the script's local TOOLS_VERSION
fixture alias, verifies both Drush command help targets, runs
drush emulsify watson, validates the generated theme files, and enables the
generated child theme. It intentionally does not test Drupal core Starterkit
generation or the Emulsify Drupal 7.x favicon deployment workflow.
Requirements: Composer and PHP. The default SQLite fixture database also requires pdo_sqlite.
Optional environment variables:
FIXTURE_DIR=/tmp/emulsify-tools-generation-smoke
DRUPAL_VERSION=11.3.*
EMULSIFY_VERSION=^6
TOOLS_VERSION=1.0.99
DRUSH_VERSION=^13
THEME_NAME=watson
DB_URL=sqlite://sites/default/files/.ht.sqlite
KEEP_FIXTURE=1
This repository uses Conventional Commits so semantic-release can determine the next version automatically.
- Stage your changes, ensuring they encompass exactly what you wish to change, no more.
- Commit using a conventional message such as
fix: repair favicon config sync. - Run the validation commands above before opening a pull request.
There's a two-step process to publish a new release to the project page on Drupal.org.
- Cut a release on GitHub
- Select the generated tag for the release on Drupal.org, and set it as the "recommended" release.
- Merge the release-ready changes into
main. - The semantic-release workflow
will calculate the next version from the merged commit messages, update
CHANGELOG.md, create a[skip ci]release commit, create the GitHub release, and push the release commit and new tag to Drupal.org. - When the workflow completes, confirm the new version appears on the GitHub Releases page.
- Go to the Releases tab for the Emulsify Tools project on drupal.org. (You'll need to be a maintainer to access this page.)
- Click "Add new release"
- Select the tag for the latest release and click Next
- Copy the release notes from the GitHub releases page, and reformat them according to the wysiwyg options
- Select the appropriate release type(s) (Bug fixes/New features).
- Click Save
- Back on the Releases tab, select the new release as the "Supported" and "Recommended" release. Deselect any others.
- Save, and go to the projects main page to verify that the new release is displayed in the green box so that future builds will pull it by default.