feat: Add keyboard shortcuts configuration and functionality - #239
Conversation
dermatz
commented
Aug 10, 2026
- Introduced a new configuration group for keyboard shortcuts in system.xml.
- Added fields to enable keyboard shortcuts and configure toolbar and inspector shortcuts.
- Updated config.xml with default values for keyboard shortcuts.
- Enhanced German and English translation files to include new keyboard shortcut labels and descriptions.
- Modified inspector.phtml and toolbar.js to support keyboard shortcuts.
- Implemented shortcut parsing logic in a new shortcut-parser.js file.
- Updated inspector and toolbar JavaScript to utilize the new shortcut functionality.
- Added unit tests for keyboard shortcut configuration and functionality.
- Enhanced template copier tests to handle new header options for PHTML files.
- Introduced a new configuration group for keyboard shortcuts in system.xml. - Added fields to enable keyboard shortcuts and configure toolbar and inspector shortcuts. - Updated config.xml with default values for keyboard shortcuts. - Enhanced German and English translation files to include new keyboard shortcut labels and descriptions. - Modified inspector.phtml and toolbar.js to support keyboard shortcuts. - Implemented shortcut parsing logic in a new shortcut-parser.js file. - Updated inspector and toolbar JavaScript to utilize the new shortcut functionality. - Added unit tests for keyboard shortcut configuration and functionality. - Enhanced template copier tests to handle new header options for PHTML files.
There was a problem hiding this comment.
Pull request overview
Adds configurable keyboard shortcuts for the MageForge Toolbar/Inspector and expands Template Override “source header” configurability, including updated admin configuration, defaults, frontend template wiring, and unit tests.
Changes:
- Introduces keyboard-shortcut admin settings (enable switch + per-feature shortcut strings) and wires them into frontend JS via
data-*attributes. - Adds
shortcut-parser.jsand updates Toolbar/Inspector JS to use configurable shortcut matching. - Extends Template Override header generation with granular include/enable toggles and updates unit tests accordingly.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/Service/TemplateOverride/TemplateCopierTest.php | Adds/adjusts unit tests for new header toggles and per-format enable switches. |
| tests/Unit/Model/Config/InspectorTest.php | Verifies new Inspector config paths and default shortcut constants. |
| tests/Unit/Block/InspectorTest.php | Tests block getters for keyboard shortcuts enablement and shortcut defaults. |
| src/view/frontend/web/js/toolbar.js | Reads shortcut config from DOM and uses shortcut matching to toggle audits. |
| src/view/frontend/web/js/shortcut-parser.js | Implements parsing and matching of human-readable shortcuts. |
| src/view/frontend/web/js/inspector/picker.js | Uses configurable shortcut matching to toggle the inspector. |
| src/view/frontend/web/js/inspector.js | Adjusts inspector button title now that shortcuts are configurable. |
| src/view/frontend/templates/inspector.phtml | Passes shortcut config to JS via data-keyboard-shortcuts-enabled and data-shortcut. |
| src/Service/TemplateOverride/TemplateCopier.php | Adds granular header include/enable toggles and applies them during copy. |
| src/Model/Config/TemplateOverride.php | Adds config path constants for new Template Override header toggles. |
| src/Model/Config/Inspector.php | Adds config path constants + default shortcut constants. |
| src/i18n/en_US.csv | Adds new strings for keyboard shortcut and source header toggle settings. |
| src/i18n/de_DE.csv | Adds German translations for new keyboard shortcut and source header toggle settings. |
| src/etc/config.xml | Adds default values for keyboard shortcuts and source header toggles. |
| src/etc/adminhtml/system.xml | Adds admin configuration fields/groups for shortcuts and header toggles. |
| src/Block/Inspector.php | Adds getters for shortcut enablement and configured shortcut strings. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| /** | ||
| * Extract the lower-cased file extension from a path | ||
| * | ||
| * @param string $filePath | ||
| * @return string | ||
| */ |
- Memoise parsed keyboard shortcuts by normalised string (review) - Lower-case extension inside extension() to match its docblock (review) - Generalise source-header help text and i18n strings (review) - Remove redundant (string) cast flagged by Mago analyze - Prettier-format picker.js, shortcut-parser.js, toolbar.js (Trunk) - Kill escaped mutants: cover all match-arm aliases, header include toggles, Windows paths and PHP-tag injection edge cases - Make Inspector::shouldRender() branch tests observable
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/view/frontend/web/js/inspector/picker.js:19
- Inspector shortcut behaviour is now configurable (and defaults to Ctrl/Cmd+Shift+I), but repository docs and CLI output still state the macOS toggle as Cmd+Option+I. Unless the admin config is changed to
Cmd+Option+I, that key combo will no longer match the default behaviour, so the README/commands docs andmageforge:theme:inspector enablehelp text become misleading.
this.keyboardShortcutsEnabled =
this.$el?.getAttribute("data-keyboard-shortcuts-enabled") !== "0";
this.shortcut = this.$el?.getAttribute("data-shortcut") || "Ctrl+Shift+I";
this.keydownHandler = (e) => {
// Configured inspector shortcut (default: Ctrl/Cmd+Shift+I)
if (this.keyboardShortcutsEnabled && matchesShortcut(e, this.shortcut)) {
src/Service/TemplateOverride/TemplateCopier.php:237
- The plain (non-PHPDoc) source header ignores the new
XML_PATH_SOURCE_HEADER_INCLUDE_OVERRIDE_FORflag:Override For:is still emitted whenever a logical module name is provided (andinclude_source_moduleis enabled), and it is never emitted when the physical source module differs from the logical override target. This makes the new admin setting ineffective for JS/CSS/etc and loses information for mismatched-module overrides.
$actualSourceModule = $this->resolveSourceModule($sourceFile);
$includeSourceModule = $this->shouldIncludeSourceModuleInHeader();
if ($actualSourceModule !== null && $includeSourceModule) {
$lines[] = 'Source Module: ' . $actualSourceModule;
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (2)
tests/Unit/Service/TemplateOverride/TemplateCopierTest.php:116
testAddsHeaderWhenEnabled()now stubsisSetFlag()to always return true, which stops the test from asserting that the copier reads the correct config paths (and store scope) for header enablement. Using a callback that only enables the expected flags keeps the test meaningful and protects against regressions as more flags are added.
$this->scopeConfig->method('isSetFlag')->willReturn(true);
src/Service/TemplateOverride/TemplateCopier.php:237
buildHeaderLines()never consultsTemplateOverrideConfig::XML_PATH_SOURCE_HEADER_INCLUDE_OVERRIDE_FOR, so the “Include Override Target in Header” setting only works for PHP/PHTML (@override-for) and is ignored for plain headers (JS/CSS/XML/etc). Add the same gating used inbuildPhpDocHeaderLines()and append an "Override For" line when the source module differs from the logical override target.
$actualSourceModule = $this->resolveSourceModule($sourceFile);
$includeSourceModule = $this->shouldIncludeSourceModuleInHeader();
if ($actualSourceModule !== null && $includeSourceModule) {
$lines[] = 'Source Module: ' . $actualSourceModule;
…cosystem Dependabot does not support cooldown.semver-major-days for the github-actions package ecosystem; keep the default 7-day cooldown.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (3)
src/Service/TemplateOverride/TemplateCopier.php:254
- The new "Include Override Target" config is applied for PHP/PHTML headers (@override-for) but the plain-text headers for non-PHP files never include the logical override target when the resolved source module differs. This makes the setting ineffective for formats like JS/CSS/XML and contradicts the system.xml/i18n description.
if ($version !== '') {
$lines[] = 'Module-Version: ' . $version;
}
}
return $lines;
tests/Unit/Service/TemplateOverride/TemplateCopierTest.php:736
- This uses date('Y-m-d') in an assertion after copy(). Capturing the date once before copy() reduces the chance of a midnight boundary causing a flaky failure.
$this->copier->copy('/module/web/js/source.js', '/theme/dir/source.js', 'Vendor_Module');
$this->assertStringContainsString('MageForge Template Override', $captured ?? '');
$this->assertStringContainsString('Date: ' . date('Y-m-d'), $captured ?? '');
$this->assertStringContainsString('Source: /module/web/js/source.js', $captured ?? '');
tests/Unit/Service/TemplateOverride/TemplateCopierTest.php:455
- This assertion computes date('Y-m-d') after the copy() call; if the test runs across midnight, the header date and assertion date can differ and cause a flaky failure. Capture the date once before calling copy() and assert against that value.
This issue also appears on line 732 of the same file.
);
$this->assertStringContainsString('@date ' . date('Y-m-d'), $captured ?? '');
$this->assertStringContainsString('@module Vendor_Module', $captured ?? '');
$this->assertStringNotContainsString('@module-version', $captured ?? '');