Berechnen Sie die Spezifität eines CSS-Selektors

8

Heute besteht Ihre Aufgabe darin, ein Programm (oder eine Funktion) zu schreiben, das eine Zeichenfolge akzeptiert und vier Ganzzahlen ausgibt (oder zurückgibt).


Eingang

Die Eingabezeichenfolge ist ein CSS3-Selektor und kann grundsätzlich jedes Unicode-Zeichen enthalten.


Ausgabe

Die Ausgabe repräsentiert die CSS-Spezifität dieses Selektors.

  • Die erste Zahl ist immer 0 (da sie für Inline-Stile verwendet wird und diese Übung nicht für Inline-Stile gilt).

  • Die zweite Zahl ist die Anzahl der #fooim Selektor vorhandenen ids ( ).

  • Die dritte Zahl ist , die Anzahl der Klassen ( .foo), Attribute ( [bar]) und pseudo-Klassen , die in der Auswahleinrichtung .

  • Die vierte Zahl ist die Anzahl der Elemente ( biz) und pseudo-Elemente , die in der Auswahleinrichtung .


Anmerkungen:

  • Der Universalwähler (*) wird nirgendwo gezählt

  • Die Pseudoelemente ::beforeund ::afterkönnen auch mit einem einzigen ":" (Legacy-Notation) geschrieben werden.

  • Die Eingabe kann die :not(selector)Pseudoklasse verwenden. Der darin enthaltene Selektor zählt nicht, selbst wenn er IDs, Klassen, Elemente usw. enthält.

  • Die "Bausteine" des Wählers durch combinators getrennt (Leerzeichen / Tabs +, >, ~, ex: body > div+a ~*), aber sie können auch kumuliert werden (zB: div#foo.bar[baz]:hover::before)

  • Sie müssen auch CSS-Escape-Sequenzen ( \gefolgt von 1 bis 6 Hexadezimalzahlen, gefolgt von einem Leerzeichen) und Escape- Sonderzeichen ( \gefolgt von diesen !"#$%&'()*+,-./:;<=>?@[\]^`{|}~:) ordnungsgemäß verarbeiten. Diese Escapezeichen können Teil eines beliebigen Bausteins des Selektors sein (ID, Klasse usw.).

  • Sie müssen nichts Besonderes tun, wenn Sie einen ungültigen Selektor oder einen CSS4-Selektor erhalten. Machen Sie sich nicht die Mühe, einen CSS3-Selektor-Validator zu implementieren.

  • Hier sind einige Links, um mehr über die CSS-Spezifität zu erfahren:


Beispiele

// Universal

* => 0,0,0,0

// ICH WÜRDE

#id => 0,1,0,0

// Klasse

.class => 0,0,1,0

// Attribute

[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: Klammern [] können alles außer einem nicht entflohenen "]" enthalten.)

// Pseudoklassen

: root => 0,0,1,0
: n-tes Kind (n) => 0,0,1,0
: n-letztes Kind (n) => 0,0,1,0
: n-tes Typ (n) => 0,0,1,0
: n-letztes vom Typ (n) => 0,0,1,0
: erstes Kind => 0,0,1,0
: letztes Kind => 0,0,1,0
: first-of-type => 0,0,1,0
: last-of-type => 0,0,1,0
: only-child => 0,0,1,0
: nur vom Typ => 0,0,1,0
: leer => 0,0,1,0
: link => 0,0,1,0
: besucht => 0,0,1,0
: active => 0,0,1,0
: hover => 0,0,1,0
: focus => 0,0,1,0
: Ziel => 0,0,1,0
: lang (fr) => 0,0,1,0
: enabled => 0,0,1,0
: disabled => 0,0,1,0
: geprüft => 0,0,1,0
: not (Selektor) => 0,0,1,0

(NB: Das Schlüsselwort nach ":" kann alles andere als ein Pseudoelement sein.)


// Elemente

Körper => 0,0,0,1

// Pseudoelemente

: vor => 0,0,0,1
: after => 0,0,0,1
:: vor => 0,0,0,1
:: after => 0,0,0,1
:: erste Zeile => 0,0,0,1
:: erster Buchstabe => 0,0,0,1

(NB: Klammern () können alles enthalten, außer ein ")")

(Fortsetzung folgt)


Wenn Sie Fragen haben oder Beispiele oder Testdaten benötigen, fragen Sie bitte in den Kommentaren.

Der kürzeste Code (in Bytes) gewinnt.

Viel Glück!

xem
quelle
3
Bitte fügen Sie Beispiele hinzu (idealerweise für alle Macken in den Notizen).
Martin Ender
2
Die Liste der Tests sieht wirklich gut aus, aber einige Beispiele, die über eine einzelne hinausgehen, 1wären großartig. (Übrigens denke ich, dass dies tatsächlich eine ziemlich gute Herausforderung ist, aber eine vollständige Liste von Testfällen scheint wichtig zu sein, damit es gut funktioniert.)
Martin Ender

Antworten:

1

Javascript ES6 453 430 Bytes

Hier geht mein Schuss!

a=>(s){var n=z=[],c=[0,0,0,0],e=s.split(/[\s\+\>\~]+/);return e.forEach((s)=>{n=n.concat(s.replace(/\((.*)\)/,"").split(/(?=\[|::|\.)/))}),n.forEach((s)=>{if(0==s.indexOf("::"))return z.push(s);var n=s.split(/(?=:)/);z=z.concat(n[0].split(/(?=[\#])/)),/before|after/.test(n[1])?z.push(":"+n[1]):n[1]&&z.push(n[1])}),z.forEach((s)=>{/^[a-z]+$/gi.test(s)||"::"==s[0]+s[1]?c[3]++:-1!=":.[".indexOf(s[0])?c[2]++:"#"==s[0]&&c[1]++}),c}

@UPDATE verbesserter Code, jetzt behandelt es: nicht und: vor /: nach Selektoren besser, hat jedoch keine CSS-Escape-Sequenzen getestet.

josegomezr
quelle