Hoje, sua tarefa é escrever um programa (ou uma função) que aceite uma string e produza (ou retorne) quatro números inteiros.
Entrada
A sequência de entrada é um seletor CSS3 e pode conter basicamente qualquer caractere Unicode.
Resultado
A saída representa a especificidade do CSS desse seletor.
O primeiro número é sempre 0 (porque é usado para estilos embutidos e este exercício não se aplica a estilos embutidos)
O segundo número é o número de ids (
#foo
) presentes no seletor.O terceiro número é o número de classes (
.foo
), atributos ([bar]
) e pseudo-classes presentes no seletor.O quarto número é o número de elementos (
biz
) e pseudoelementos presentes no seletor.
Notas:
O seletor universal (*) não é contado em nenhum lugar
Os pseudo-elementos
::before
e::after
também podem ser escritos com um único ":" (notação herdada)A entrada pode usar a
:not(selector)
pseudo-classe. O seletor interno não conta, mesmo que contenha IDs, classes, elementos, ...)Os "tijolos" do selector são separados por combinadores (espaços / abas,
+
,>
,~
, ex:body > div+a ~*
), mas eles também podem ser acumulados (ex:div#foo.bar[baz]:hover::before
)Você também precisa lidar com seqüências de escape de CSS (
\
seguidas de 1 a 6 números hexadecimais, seguidos de um espaço) e caracteres especiais de escape (\
seguidos por qualquer um destes!"#$%&'()*+,-./:;<=>?@[\]^`{|}~
:) corretamente. Essas fugas podem fazer parte de qualquer bloco do seletor (ID, classe, etc.).Você não precisa fazer nada em particular se receber um seletor inválido ou um CSS4. Não se preocupe em implementar um validador de seletor CSS3.
Aqui estão alguns links para aprender mais sobre CSS:
- Artigo de truques CSS: http://css-tricks.com/specifics-on-css-specificity/
- Uma ferramenta (incompleta) que conta: http://specificity.keegan.st/
Exemplos
// Universal * => 0,0,0,0 // EU IRIA #id => 0,1,0,0 // Classe .class => 0,0,1,0 // Atributos [foo] => 0,0,1,0 [foo = "bar"] => 0,0,1,0 [foo ~ = "bar"] => 0,0,1,0 [foo ^ = "bar"] => 0,0,1,0 [foo $ = "bar"] => 0,0,1,0 [foo * = "bar"] => 0,0,1,0 [foo | = "bar"] => 0,0,1,0 [foo = bar] => 0,0,1,0 [foo = 'bar'] => 0,0,1,0 (NB: colchetes [] podem conter qualquer coisa, exceto um "]" sem escape) // Pseudo-classes : raiz => 0,0,1,0 : enésimo filho (n) => 0,0,1,0 : enésimo último filho (n) => 0,0,1,0 : enésimo tipo (n) => 0,0,1,0 : enésimo último do tipo (n) => 0,0,1,0 : primeiro filho => 0,0,1,0 : último filho => 0,0,1,0 : primeiro-tipo => 0,0,1,0 : último tipo => 0,0,1,0 : filho único => 0,0,1,0 : apenas do tipo => 0,0,1,0 : vazio => 0,0,1,0 : link => 0,0,1,0 : visitado => 0,0,1,0 : ativo => 0,0,1,0 : pairar => 0,0,1,0 : foco => 0,0,1,0 : target => 0,0,1,0 : lang (fr) => 0,0,1,0 : ativado => 0,0,1,0 : desativado => 0,0,1,0 : verificado => 0,0,1,0 : not (seletor) => 0,0,1,0 (NB: a palavra-chave após ":" pode ser qualquer coisa, exceto um pseudo-elemento) // Elementos body => 0,0,0,1 // Pseudoelementos : antes => 0,0,0,1 : depois => 0,0,0,1 :: antes => 0,0,0,1 :: depois => 0,0,0,1 :: primeira linha => 0,0,0,1 :: primeira letra => 0,0,0,1 (NB: parênteses () pode conter qualquer coisa, exceto um ") sem escape")
(continua)
Se você tiver dúvidas ou precisar de exemplos ou dados de teste, pergunte nos comentários.
O código mais curto (em bytes) vence.
Boa sorte!
1
seriam ótimos. (Btw, eu acho que este é realmente um bom desafio, mas uma lista exaustiva de casos de teste parece vital para que ele funcione bem.)