Auto-enable dev mode when Joomla debug is on; fix TOC heading detection

- Development mode now activates automatically when Joomla global
  debug is enabled, so admins don't need to toggle both settings.
- Bootstrap TOC now detects the highest heading level present (even
  if only one exists) and includes up to two levels below it
  (e.g. h2 → h2, h3, h4). Fixes incorrect top-level detection and
  adds proper three-level nesting support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 11:26:37 -05:00
parent 8d4ddbc1e4
commit 93e9d3a88c
2 changed files with 36 additions and 22 deletions

View File

@@ -34,7 +34,7 @@ $params_googleanalyticsid = $this->params->get('googleanalyticsid', null);
$params_googlesitekey = $this->params->get('googlesitekey', null); $params_googlesitekey = $this->params->get('googlesitekey', null);
$params_custom_head_start = $this->params->get('custom_head_start', null); $params_custom_head_start = $this->params->get('custom_head_start', null);
$params_custom_head_end = $this->params->get('custom_head_end', null); $params_custom_head_end = $this->params->get('custom_head_end', null);
$params_developmentmode = $this->params->get('developmentmode', false); $params_developmentmode = $this->params->get('developmentmode', false) || $app->get('debug', false);
$params_favicon_source = (string) $this->params->get('favicon_source', ''); $params_favicon_source = (string) $this->params->get('favicon_source', '');
// Theme params // Theme params

View File

@@ -83,11 +83,12 @@
return this.generateNavEl(anchor, text); return this.generateNavEl(anchor, text);
}, },
// Find the first heading level (`<h1>`, then `<h2>`, etc.) that has more than one element. Defaults to 1 (for `<h1>`). // Find the highest (lowest-numbered) heading level present in the scope.
// Returns the tag number of the first heading found (e.g. 2 for <h2>).
getTopLevel: function($scope) { getTopLevel: function($scope) {
for (var i = 1; i <= 6; i++) { for (var i = 1; i <= 6; i++) {
var $headings = this.findOrFilter($scope, 'h' + i); var $headings = this.findOrFilter($scope, 'h' + i);
if ($headings.length > 1) { if ($headings.length >= 1) {
return i; return i;
} }
} }
@@ -95,14 +96,15 @@
return 1; return 1;
}, },
// returns the elements for the top level, and the next below it // Returns elements for the top level and up to two levels below it.
// e.g. if topLevel is 2 → h2, h3, h4
getHeadings: function($scope, topLevel) { getHeadings: function($scope, topLevel) {
var topSelector = 'h' + topLevel; var selectors = [];
for (var i = topLevel; i <= Math.min(topLevel + 2, 6); i++) {
selectors.push('h' + i);
}
var secondaryLevel = topLevel + 1; return this.findOrFilter($scope, selectors.join(','));
var secondarySelector = 'h' + secondaryLevel;
return this.findOrFilter($scope, topSelector + ',' + secondarySelector);
}, },
getNavLevel: function(el) { getNavLevel: function(el) {
@@ -110,26 +112,38 @@
}, },
populateNav: function($topContext, topLevel, $headings) { populateNav: function($topContext, topLevel, $headings) {
var $context = $topContext; var $contexts = {};
var $prevNav; $contexts[topLevel] = $topContext;
var $prevNavByLevel = {};
var helpers = this; var helpers = this;
$headings.each(function(i, el) { $headings.each(function(i, el) {
var $newNav = helpers.generateNavItem(el); var $newNav = helpers.generateNavItem(el);
var navLevel = helpers.getNavLevel(el); var navLevel = helpers.getNavLevel(el);
// determine the proper $context
if (navLevel === topLevel) { if (navLevel === topLevel) {
// use top level // Top level — append directly
$context = $topContext; $topContext.append($newNav);
} else if ($prevNav && $context === $topContext) { $prevNavByLevel = {};
// create a new level of the tree and switch to it $prevNavByLevel[topLevel] = $newNav;
$context = helpers.createChildNavList($prevNav); // Reset deeper contexts so next child creates a fresh sublist
} // else use the current $context $contexts = {};
$contexts[topLevel] = $topContext;
$context.append($newNav); } else {
// Child level — ensure parent context exists
$prevNav = $newNav; var parentLevel = navLevel - 1;
if (!$contexts[navLevel] && $prevNavByLevel[parentLevel]) {
$contexts[navLevel] = helpers.createChildNavList($prevNavByLevel[parentLevel]);
}
var $ctx = $contexts[navLevel] || $topContext;
$ctx.append($newNav);
$prevNavByLevel[navLevel] = $newNav;
// Reset deeper contexts
for (var l = navLevel + 1; l <= 6; l++) {
delete $contexts[l];
delete $prevNavByLevel[l];
}
}
}); });
}, },