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

@@ -83,11 +83,12 @@
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) {
for (var i = 1; i <= 6; i++) {
var $headings = this.findOrFilter($scope, 'h' + i);
if ($headings.length > 1) {
if ($headings.length >= 1) {
return i;
}
}
@@ -95,14 +96,15 @@
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) {
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;
var secondarySelector = 'h' + secondaryLevel;
return this.findOrFilter($scope, topSelector + ',' + secondarySelector);
return this.findOrFilter($scope, selectors.join(','));
},
getNavLevel: function(el) {
@@ -110,26 +112,38 @@
},
populateNav: function($topContext, topLevel, $headings) {
var $context = $topContext;
var $prevNav;
var $contexts = {};
$contexts[topLevel] = $topContext;
var $prevNavByLevel = {};
var helpers = this;
$headings.each(function(i, el) {
var $newNav = helpers.generateNavItem(el);
var navLevel = helpers.getNavLevel(el);
// determine the proper $context
if (navLevel === topLevel) {
// use top level
$context = $topContext;
} else if ($prevNav && $context === $topContext) {
// create a new level of the tree and switch to it
$context = helpers.createChildNavList($prevNav);
} // else use the current $context
$context.append($newNav);
$prevNav = $newNav;
// Top level — append directly
$topContext.append($newNav);
$prevNavByLevel = {};
$prevNavByLevel[topLevel] = $newNav;
// Reset deeper contexts so next child creates a fresh sublist
$contexts = {};
$contexts[topLevel] = $topContext;
} else {
// Child level — ensure parent context exists
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];
}
}
});
},