Разрешенные символы для идентификаторов CSS
Каковы символы (полный) допустимый/допустимый charset для идентификаторов CSS id
и class
?
Есть ли регулярное выражение, которое я могу использовать для проверки? Является ли он агностиком браузера?
Ответы
Ответ 1
Кодировка не имеет значения. Разрешенные символы имеют большее значение. Проверьте спецификацию CSS. Здесь приведенная ссылка:
В CSS идентификаторы (включая имена элементов, классы и идентификаторы в селекторы) могут содержать только символы [a-zA-Z0-9]
и символы ISO 10646 U+00A1
и выше, плюс дефис (-
) и подчеркивание (_
); они не могут начинаться с цифры или дефиса, за которым следует цифра. Идентификаторы также могут содержать экранированные символы и любой символ ISO 10646 в виде числового кода (см. Следующий элемент). Например, идентификатор "B&W?"
может быть записан как "B\&W\?"
или "B\26 W\3F"
.
Обновить. Что касается вопроса о регулярном выражении, вы можете найти грамматику здесь:
ident -?{nmstart}{nmchar}*
Что содержит части:
nmstart [_a-z]|{nonascii}|{escape}
nmchar [_a-z0-9-]|{nonascii}|{escape}
nonascii [\240-\377]
escape {unicode}|\\[^\r\n\f0-9a-f]
unicode \\{h}{1,6}(\r\n|[ \t\r\n\f])?
h [0-9a-f]
Это можно перевести в регулярное выражение Java следующим образом (я только добавил круглые скобки к частям, содержащим OR и избегающим обратную косую черту):
String h = "[0-9a-f]";
String unicode = "\\\\{h}{1,6}(\\r\\n|[ \\t\\r\\n\\f])?".replace("{h}", h);
String escape = "({unicode}|\\\\[^\\r\\n\\f0-9a-f])".replace("{unicode}", unicode);
String nonascii = "[\\240-\\377]";
String nmchar = "([_a-z0-9-]|{nonascii}|{escape})".replace("{nonascii}", nonascii).replace("{escape}", escape);
String nmstart = "([_a-z]|{nonascii}|{escape})".replace("{nonascii}", nonascii).replace("{escape}", escape);
String ident = "-?{nmstart}{nmchar}*".replace("{nmstart}", nmstart).replace("{nmchar}", nmchar);
System.out.println(ident); // The full regex.
Обновление 2: о, вы больше PHP'er, ну, я думаю, вы можете понять, как и где делать str_replace
?
Ответ 2
Для тех, кто ищет что-то еще немного под ключ. Полное выражение, замененное и все, из ответа @BalusC:
/-?([_a-z]|[\240-\377]|([0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|[^\r\n\f0-9a-f]))([_a-z0-9-]|[\240-\377]|([0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|[^\r\n\f0-9a-f]))*/
И используя DEFINE
, который я нахожу немного более читаемым:
/(?(DEFINE)
(?P<h> [0-9a-f] )
(?P<unicode> (?&h){1,6}(\r\n|[ \t\r\n\f])? )
(?P<escape> ((?&unicode)|[^\r\n\f0-9a-f])* )
(?P<nonascii> [\240-\377] )
(?P<nmchar> ([_a-z0-9-]|(?&nonascii)|(?&escape)) )
(?P<nmstart> ([_a-z]|(?&nonascii)|(?&escape)) )
(?P<ident> -?(?&nmstart)(?&nmchar)* )
) (?:
(?&ident)
)/x
Кстати, в исходном регулярном выражении (и в вкладе @human) было несколько escape-символов изгоев, которые позволяют [
в имени.
Кроме того, следует отметить, что необработанное регулярное выражение без DEFINE
работает примерно в 2 раза быстрее, чем выражение DEFINE
, используя только ~ 23 шага для идентификации одного символа юникода, а позже - ~ 40.
Ответ 3
Это всего лишь вклад в ответ @BalusC. Это PHP-версия Java-кода, которую он предоставил, я ее преобразовал, и я подумал, что кто-то может найти это полезным.
$h = "[0-9a-f]";
$unicode = str_replace( "{h}", $h, "\{h}{1,6}(\r\n|[ \t\r\n\f])?" );
$escape = str_replace( "{unicode}", $unicode, "({unicode}|\[^\r\n\f0-9a-f])");
$nonascii = "[\240-\377]";
$nmchar = str_replace( array( "{nonascii}", "{escape}" ), array( $nonascii, $escape ), "([_a-z0-9-]|{nonascii}|{escape})");
$nmstart = str_replace( array( "{nonascii}", "{escape}" ), array( $nonascii, $escape ), "([_a-z]|{nonascii}|{escape})" );
$ident = str_replace( array( "{nmstart}", "{nmchar}" ), array( $nmstart, $nmchar ), "-?{nmstart}{nmchar}*");
echo $ident; // The full regex.