CSS çözümleyici: kademe ve özgüllük
Bir bakışta
“Bir bakışta” başlıklı bölümÇö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.
Kurulum
“Kurulum” başlıklı bölümcomposer require nextpdf/core:^3Kavramsal genel bakış
“Kavramsal genel bakış” başlıklı bölümCssResolver, 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.
API yüzeyi
“API yüzeyi” başlıklı bölüm| Sembol | Konum | Rol |
|---|---|---|
CssResolver::parseStyleBlock(string $css, bool $nestingEnabled = false): void | src/Html/CssResolver.php | Bir <style> bloğunu kurallara ayrıştırır. |
CssResolver::resolveMatchingProperties(...) | src/Html/CssResolver.php | Seçicileri eşleştirir ve iki geçişli kademeyi çözümler. |
CssResolver::resolveHasSelectors(array $tokens): array | src/Html/CssResolver.php | Sınırlı :has() ön taramasını yapar (geçit kontrollü). |
CssResolver::resolveFirstLetterProperties(...) | src/Html/CssResolver.php | Sözde öğe ::first-letter özelliklerini çözümler. |
CssResolver::resolvePseudoElementProperties(...) | src/Html/CssResolver.php | Sözde öğe ::before / ::after özelliklerini çözümler. |
CssResolver::getLayerRegistry(): LayerRegistry | src/Html/CssResolver.php | Bildirilen kademe katmanlarını sağlar. |
Kod örneği — hızlı başlangıç
“Kod örneği — hızlı başlangıç” başlıklı bölümÇö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');Kod örneği — üretim
“Kod örneği — üretim” başlıklı bölümBu ö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');Uç durumlar ve dikkat edilecek noktalar
“Uç durumlar ve dikkat edilecek noktalar” başlıklı bölüm!importantözgüllüğü yok sayar. 2. geçiş,!importantbildirimlerini ö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
@layerolmadığı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ızcacss.hasdeneysel ö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.
Performans
“Performans” başlıklı bölümEn 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).
Güvenlik notları
“Güvenlik notları” başlıklı bölümÇö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.
Uygunluk
“Uygunluk” başlıklı bölüm| Davranış | Belirtim | Madde | reference_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ük | W3C Selectors Level 4 | §16 (selectors_4#x1.x16.p2) | |
| Belirlenimci ayrıştırma ve ayrıştırma hatası kurtarma | W3C 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.
Ticari bağlam
“Ticari bağlam” başlıklı bölümKurumsal yetenek. Premium, eşleşen ve uygulanan özellik kümesini genişletir. Kademe algoritması ve iki geçişli
!importantmodeli, sürümler genelinde aynıdır. CSS destek matrisi bölümüne bakın.