table-of-contents-plus icon indicating copy to clipboard operation
table-of-contents-plus copied to clipboard

Allow toc labels to be different from actual headings

Open erikhofer opened this issue 7 years ago • 3 comments

It would be great to be able to override headings in the toc instead of just being able to exclude them.

My use-case is that I have headings that are too long to fit in a single line in my sidebar. I'd like to use shorter labels in the toc.

One approach would be a shorttag to define an override: <h2>The actual heading[toc-label]The toc label[/toc-label]</h2>

It would also be sufficient to provide a filter hook in extract_headings() so that the override can be implemented individually.

erikhofer avatar Mar 28 '17 15:03 erikhofer

If anyone has the same issue, you can edit toc.php to achieve this. In extract_headings() after

// remove undesired headings (if any) as defined by heading_levels
if ( count($this->options['heading_levels']) != 6 ) {
	$new_matches = array();
	for ($i = 0; $i < count($matches); $i++) {
		if ( in_array($matches[$i][2], $this->options['heading_levels']) )
			$new_matches[] = $matches[$i];
	}
	$matches = $new_matches;
}

add this

for ($i = 0; $i < count($matches); $i++) {
  $matches[$i][3] = $matches[$i][0]; //save original match for anchor injection
  $matches[$i][4] = preg_replace('/\[toc-label\].*\[\/toc-label\]/', '', $matches[$i][0]); //save title without shorttag
  $label = preg_replace(array('/.*\[toc-label\]/', '/\[\/toc-label\].*/'), '', $matches[$i][0]);
  $matches[$i][0] = '</h' . $matches[$i][2] . '>' . $matches[$i][1] . $label . '</h' . $matches[$i][2] . '>';
}

and replace

for ($i = 0; $i < count($matches); $i++) {
	// get anchor and add to find and replace arrays
	$anchor = $this->url_anchor_target( $matches[$i][0] );
	$find[] = $matches[$i][0];
	$replace[] = str_replace(
		array(
			$matches[$i][1],	// start of heading
			'</h' . $matches[$i][2] . '>'	// end of heading
		),
		array(
			$matches[$i][1] . '<span id="' . $anchor . '">',
			'</span></h' . $matches[$i][2] . '>'
		),
		$matches[$i][0]
	);

	// assemble flat list
	if ( !$this->options['show_heirarchy'] ) {
		$items .= '<li><a href="#' . $anchor . '">';
		if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
		$items .= strip_tags($matches[$i][0]) . '</a></li>';
	}
}

with

for ($i = 0; $i < count($matches); $i++) {
	// get anchor and add to find and replace arrays
	$anchor = $this->url_anchor_target( $matches[$i][0] );
	$find[] = $matches[$i][3]; // <= use original match
	$replace[] = str_replace(
		array(
			$matches[$i][1],	// start of heading
			'</h' . $matches[$i][2] . '>'	// end of heading
		),
		array(
			$matches[$i][1] . '<span id="' . $anchor . '">',
			'</span></h' . $matches[$i][2] . '>'
		),
		$matches[$i][4] // <= use title without shorttag
	);

	// assemble flat list
	if ( !$this->options['show_heirarchy'] ) {
		$items .= '<li><a href="#' . $anchor . '">';
		if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
		$items .= strip_tags($matches[$i][0]) . '</a></li>';
	}
}

erikhofer avatar Apr 02 '17 14:04 erikhofer

but editing the plugin means future updates will override it.

sweethoneycode avatar Sep 06 '17 05:09 sweethoneycode

This is true, unless the next update (if any) includes this functionality itself. But it is the only sane workaround I have found.

erikhofer avatar Sep 06 '17 10:09 erikhofer