İçeriğe geç

CSS çözümleyici: kademe ve özgüllük

Çözümleyici CssResolver, seçicileri token akışı üzerinden eşleştirir, eşleşen kuralları kademe katmanı ağırlığına, özgüllüğe ve belge sırasına göre sıralar, ardından ikinci bir geçişte !important bildirimlerini uygular.

Terminal window
composer require nextpdf/core:^3

CssResolver, ADR-010 uyarınca bir Katman 1 bileşenidir. Ayrıştırılmış CSS kurallarını tutar ve her öğeye hangi bildirimlerin uygulanacağına karar verir. Yapıyı net tutmak için HtmlParser sınıfından ayrıdır; genel bir uygulama programlama arabirimi (API) değil, dahili bir sınıftır.

Çözümleyicinin bir belge ağacına ihtiyacı yoktur. Seçici eşleştirme, düz token akışını okur ve HtmlChildScanner bileşeninin işlem hattı aşama 3’te oluşturduğu dizin haritalarını kullanır: alt öğe sayıları, aynı etiket sayıları ve boşluk durumu. Bu haritalar, yapısal sözde sınıfların değerlendirilmesini sağlar. İlişkisel :has() seçicisi, akış kısıtlamaları bölümünde açıklanan sınırlı ön taramadan yararlanır.

Kademe çözümlemesi, CssResolver::resolveMatchingProperties() içinde iki geçişte gerçekleşir. 1. geçiş, normal bildirimleri kademe sırasına göre uygular: önce kademe katmanı ağırlığı, sonra özgüllük, ardından belge sırası. 2. geçiş, !important bildirimlerini özgüllük sırasına göre uygular. Bir !important bildirimi, özgüllüğünden bağımsız olarak herhangi bir normal bildirimi geçersiz kılar. Bu iki geçişli ayrım bir uygulama stratejisidir ve yerleşim katmanının tükettiği çözümlenmiş özellik kümesini üretir.

Çözümleyicinin uyguladığı kademe sırası, World Wide Web Consortium (W3C) CSS Cascading and Inheritance belirtimiyle uyumludur. Bildirimler önce köken ve önem derecesine, ardından seçici özgüllüğüne göre sıralanır. Özgüllük eşitse, belge sırasındaki son bildirim kazanır (CSS Cascade 5 §6.4; bkz. Uygunluk). CssResolver içindeki kaynak içi yorum da aynı maddeye atıfta bulunur; bu nedenle davranışı doğrularken belirtim ve sözlüğe ek olarak üçüncü bir yolunuz olur.

Özgüllük, ID, sınıf ve tür bileşeni sayılarından bir (A, B, C) üçlüsü olarak hesaplanır ve üçlüler bileşen bileşen karşılaştırılır (Selectors Level 4 §16). NextPDF, kademeyi sıralamadan önce eşleşen her kural için özgüllüğü hesaplar.

Önemli bir kısıtlama vardır. §6.4.3 katman tersine çevirme kuralı, kademe katmanları arasındaki !important bildirimlerine uygulanır ve kaynak kod, bunu kademe katmanı çalışma kümesi için bekleyen iş olarak kaydeder. Kademe katmanları bildirildiğinde ve !important katmanlar arasında kullanıldığında, çözümlenen sıra belirtimin tam davranışından farklı olabilir. Özellik bazlı destek durumu için yetkili kaynak CSS destek matrisidir ve bu sayfa, özellik bazlı desteği yeniden açıklamaz.

SembolKonumRol
CssResolver::parseStyleBlock(string $css, bool $nestingEnabled = false): voidsrc/Html/CssResolver.phpBir <style> bloğunu kurallara ayrıştırır.
CssResolver::resolveMatchingProperties(...)src/Html/CssResolver.phpSeçicileri eşleştirir ve iki geçişli kademeyi çözümler.
CssResolver::resolveHasSelectors(array $tokens): arraysrc/Html/CssResolver.phpSınırlı :has() ön taramasını yapar (geçit kontrollü).
CssResolver::resolveFirstLetterProperties(...)src/Html/CssResolver.phpSözde öğe ::first-letter özelliklerini çözümler.
CssResolver::resolvePseudoElementProperties(...)src/Html/CssResolver.phpSözde öğe ::before / ::after özelliklerini çözümler.
CssResolver::getLayerRegistry(): LayerRegistrysrc/Html/CssResolver.phpBildirilen kademe katmanlarını sağlar.

Çözümleyiciyi doğrudan çağırmazsınız. CSS yazarsınız ve çözümleyici writeHtml() içinde çalışır. Aşağıdaki kademe örneğinde, sınıf kuralının özgüllüğü tür kuralından daha yüksek olduğu için p kırmızı olarak çözümlenir.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->writeHtml(
'<style>p { color: blue; } .lead { color: red; }</style>'
. '<p class="lead">Higher-specificity class wins.</p>'
);
$doc->save(__DIR__ . '/output/cascade.pdf');

Bu örnek, !important için ikinci geçişi gösterir. Sınıf seçicisinin özgüllüğü daha yüksek olsa bile, !important tür bildirimi, satır içi eşdeğer sınıf bildirimini geçersiz kılar.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->writeHtml(
'<style>p { color: green !important; } .lead { color: red; }</style>'
. '<p class="lead">!important overrides higher specificity.</p>'
);
$doc->save(__DIR__ . '/output/important.pdf');
  • !important özgüllüğü yok sayar. 2. geçiş, !important bildirimlerini özgüllük sırasına göre uygular ve bu bildirimler her zaman normal bildirimleri geçersiz kılar.
  • Kademe katmanları + katmanlar arasında !important. Kaynak kod, important bildirimleri için §6.4.3 katman tersine çevirme kuralını bekleyen iş olarak kaydeder. Buna güvenmeden önce davranışı CSS destek matrisi ile doğrulayın.
  • Katman bildirilmediğinde hızlı yol kullanılır. Hiçbir @layer olmadığında, sıralama yalnızca özgüllüğe dayalı davranışa döner ve katman öncesi davranışla bit düzeyinde aynıdır.
  • :has() geçit kontrollü çalışır. İlişkisel ön tarama yalnızca css.has deneysel özelliği etkinleştirildiğinde çalışır.
  • Seçici eşleştirme akış tabanlıdır. Yapısal seçiciler, ağaç dolaşımı yerine dizin haritalarını kullanır. Dizin haritalarının ötesinde keyfi ağaç gezinimi gerektiren bir seçici, bu modelde çözümlenemez.

En kötü durumda, seçici eşleştirme O(kural × öğe) karmaşıklığındadır ve akış kısıtlamaları ile sınırlandırılmıştır. İki kademe sıralaması, öğe başına O(eşleşen kural · log eşleşen kural) karmaşıklığındadır. Katmansız yol, katman çözümlemesini tamamen atlar. Sayfa başına performance_budget (wall_ms: 1500, peak_mb: 64), işlevsel üst sınırı belirler. HTML işleme hattı kıyaslaması, gerilemelere karşı koruma sağlar (birleştirilmiş çalışma, PR #564).

Çözümleyici yalnızca DefaultHtmlSecurityPolicy::isCssPropertyAllowed() tarafından kabul edilen CSS’yi görür. İzin listesi güvenlik üst sınırını belirler, çalışma zamanı destek tablosu ise ayrı bir yetenek üst sınırı belirler. İlke tarafından engellenen bir özellik kademeye asla ulaşmaz. HTML modülü güvenlik modeli bölümüne bakın.

DavranışBelirtimMaddereference_id
Kademe sıralaması: origin/importance → özgüllük → görünme sırasıW3C CSS Cascading and Inheritance Level 5§6.4 (css_cascade_5#x1.x7.x1.p21)
ID/sınıf/tür sayılarından bir (A,B,C) üçlüsü olarak özgüllükW3C Selectors Level 4§16 (selectors_4#x1.x16.p2)
Belirlenimci ayrıştırma ve ayrıştırma hatası kurtarmaW3C CSS Syntax Level 3§4 (css_syntax_3#x1.x4.p2)

W3C materyali CC-BY 4.0 lisanslıdır. Yukarıdaki ifadeler başka sözcüklerle aktarılmıştır. Doğrulama için madde ve parça tanımlayıcıları sağlanmıştır. NextPDF, bu modüller için tam uygunluk iddiasında bulunmaz; doğrulanmış modül bazlı durum için CSS destek matrisi bölümüne bakın.

Kurumsal yetenek. Premium, eşleşen ve uygulanan özellik kümesini genişletir. Kademe algoritması ve iki geçişli !important modeli, sürümler genelinde aynıdır. CSS destek matrisi bölümüne bakın.