Make WordPress Core

Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#17067 closed defect (bug) (fixed)

Appearance > Menus removing custom class underscore ("_")

Reported by: swartsr Owned by:
Milestone: 3.2 Priority: normal
Severity: normal Version: 3.1
Component: Menus Keywords:
Focuses: Cc:


I've created a custom menu for my site with a handful of top-level pages. I activated the 'CSS Classes' property from the 'Screen Options' and when I try to us a class for one of my link items that has an underscore in it, the system simply ignores/removes it.

I want to add a class to my list from the 960.gs which looks like this: .grid_4

Change History (8)

#1 @nacin
5 years ago

sanitize_html_class() strips the string down to A-Z,a-z,0-9 and hyphens. Really not sure why underscores aren't allowed there. Per the spec they are: http://www.w3.org/TR/CSS21/syndata.html.

#2 @nacin
5 years ago

  • Milestone changed from Awaiting Review to 3.2

Looks like it was simply left out of the original commit in [11433].

#3 @nacin
5 years ago

  • Resolution set to fixed
  • Status changed from new to closed

(In [17614]) Make underscores valid in sanitize_html_class. fixes #17067.

#4 @nacin
5 years ago

This will appear in the next major release. As a stopgap you can leverage the filter there to re-sanitize it, allowing for an underscore.

#5 @swartsr
5 years ago

Thank you so much for the quick response and the help! I can probably wait, but I'll see if I can figure out how to accomplish this with a filter. Maybe someone has already done it...

#6 @swartsr
5 years ago

This filter should fix it! The issue seems to be in the formatting.php file. Just a simple matter of leaving the "_" out of the accepted characters. Thanks!

function my_sanitize_html_class( $class, $fallback = '' ) {
	//Strip out any % encoded octets
	$sanitized = preg_replace('|%[a-fA-F0-9][a-fA-F0-9]|', '', $class);

	//Limit to A-Z,a-z,0-9,'-' '_'
	$sanitized = preg_replace('/[^A-Za-z0-9-_]/', '', $sanitized);

	if ( '' == $sanitized )
		$sanitized = $fallback;

	return apply_filters( 'sanitize_html_class', $sanitized, $class, $fallback );

#7 @nacin
5 years ago

You'll want to remove return apply_filters( 'sanitize_html_class', $sanitized, $class, $fallback );, otherwise you'll create an indefinite loop.

So change that to return $sanitized;

Also, you need to check out the order in which things are passed. The filter passes $sanitized, then $class, then $fallback. So:

function my_sanitize_html_class( $class, $fallback = '' ) {

Needs to be:

function my_sanitize_html_class( $sanitize, $class, $fallback ) {

Additionally, you need all three arguments, so:

add_filter( 'sanitize_html_class', 'my_sanitize_html_class', 10, 3 );

Note that 10 is priority. 10 is default.

Last edited 5 years ago by nacin (previous) (diff)

#8 @swartsr
5 years ago

Thank you! I appreciate it!

Note: See TracTickets for help on using tickets.